Statistics
| Branch: | Tag: | Revision:

root / snf-astakos-app / astakos / quotaholder / callpoint.py @ 6cc50d6a

History | View | Annotate | Download (11 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 79e3da8a Giorgos Korfiatis
from functools import partial
35 79e3da8a Giorgos Korfiatis
36 b0727daf Giorgos Korfiatis
from astakos.quotaholder.exception import (
37 b0727daf Giorgos Korfiatis
    QuotaholderError,
38 79e3da8a Giorgos Korfiatis
    NoCommissionError,
39 b0727daf Giorgos Korfiatis
    CorruptedError, InvalidDataError,
40 79e3da8a Giorgos Korfiatis
    NoHoldingError,
41 1d734153 Giorgos Korfiatis
    DuplicateError)
42 fac1de87 Georgios D. Tsoukalas
43 d03796c2 Giorgos Korfiatis
from astakos.quotaholder.commission import (
44 2864e701 Giorgos Korfiatis
    Import, Release, Operations)
45 d03796c2 Giorgos Korfiatis
46 b0727daf Giorgos Korfiatis
from astakos.quotaholder.utils.newname import newname
47 b0727daf Giorgos Korfiatis
from astakos.quotaholder.api import QH_PRACTICALLY_INFINITE
48 f54beeea Giorgos Korfiatis
49 2b888e60 Giorgos Korfiatis
from .models import (Holding,
50 8cff5e41 Giorgos Korfiatis
                     Commission, Provision, ProvisionLog,
51 789d202d Giorgos Korfiatis
                     now,
52 2b888e60 Giorgos Korfiatis
                     db_get_holding,
53 8cff5e41 Giorgos Korfiatis
                     db_get_commission, db_filter_provision)
54 fac1de87 Georgios D. Tsoukalas
55 e5a2e942 Georgios D. Tsoukalas
56 b0727daf Giorgos Korfiatis
class QuotaholderDjangoDBCallpoint(object):
57 fac1de87 Georgios D. Tsoukalas
58 dc9da5b9 Giorgos Korfiatis
    def get_holder_quota(self, holders=None, sources=None, resources=None):
59 dc9da5b9 Giorgos Korfiatis
        holdings = Holding.objects.filter(holder__in=holders)
60 dc9da5b9 Giorgos Korfiatis
61 dc9da5b9 Giorgos Korfiatis
        if sources is not None:
62 dc9da5b9 Giorgos Korfiatis
            holdings = holdings.filter(source__in=sources)
63 dc9da5b9 Giorgos Korfiatis
64 dc9da5b9 Giorgos Korfiatis
        if resources is not None:
65 dc9da5b9 Giorgos Korfiatis
            holdings = holdings.filter(resource__in=resources)
66 dc9da5b9 Giorgos Korfiatis
67 dc9da5b9 Giorgos Korfiatis
        quotas = {}
68 dc9da5b9 Giorgos Korfiatis
        for holding in holdings:
69 dc9da5b9 Giorgos Korfiatis
            key = (holding.holder, holding.source, holding.resource)
70 dc9da5b9 Giorgos Korfiatis
            value = (holding.limit, holding.imported_min, holding.imported_max)
71 dc9da5b9 Giorgos Korfiatis
            quotas[key] = value
72 dc9da5b9 Giorgos Korfiatis
73 dc9da5b9 Giorgos Korfiatis
        return quotas
74 dc9da5b9 Giorgos Korfiatis
75 dc9da5b9 Giorgos Korfiatis
    def set_holder_quota(self, quotas):
76 dc9da5b9 Giorgos Korfiatis
        holders = quotas.keys()
77 dc9da5b9 Giorgos Korfiatis
        hs = Holding.objects.filter(holder__in=holders).select_for_update()
78 dc9da5b9 Giorgos Korfiatis
        holdings = {}
79 dc9da5b9 Giorgos Korfiatis
        for h in hs:
80 dc9da5b9 Giorgos Korfiatis
            holdings[(h.holder, h.source, h.resource)] = h
81 dc9da5b9 Giorgos Korfiatis
82 dc9da5b9 Giorgos Korfiatis
        for holder, holder_quota in quotas.iteritems():
83 dc9da5b9 Giorgos Korfiatis
            for source, source_quota in holder_quota.iteritems():
84 dc9da5b9 Giorgos Korfiatis
                for resource, limit in source_quota.iteritems():
85 dc9da5b9 Giorgos Korfiatis
                    try:
86 dc9da5b9 Giorgos Korfiatis
                        h = holdings[(holder, source, resource)]
87 dc9da5b9 Giorgos Korfiatis
                    except KeyError:
88 dc9da5b9 Giorgos Korfiatis
                        h = Holding(holder=holder,
89 dc9da5b9 Giorgos Korfiatis
                                    source=source,
90 dc9da5b9 Giorgos Korfiatis
                                    resource=resource)
91 dc9da5b9 Giorgos Korfiatis
92 dc9da5b9 Giorgos Korfiatis
                    h.limit = limit
93 dc9da5b9 Giorgos Korfiatis
                    h.save()
94 dc9da5b9 Giorgos Korfiatis
95 1d734153 Giorgos Korfiatis
    def issue_commission(self,
96 e3685916 Giorgos Korfiatis
                         context=None,
97 1d734153 Giorgos Korfiatis
                         clientkey=None,
98 1d734153 Giorgos Korfiatis
                         name=None,
99 79e3da8a Giorgos Korfiatis
                         force=False,
100 d03796c2 Giorgos Korfiatis
                         provisions=()):
101 fac1de87 Georgios D. Tsoukalas
102 2864e701 Giorgos Korfiatis
        if name is None:
103 2864e701 Giorgos Korfiatis
            name = ""
104 c3a709ad root
        create = Commission.objects.create
105 2864e701 Giorgos Korfiatis
        commission = create(clientkey=clientkey, name=name)
106 fac1de87 Georgios D. Tsoukalas
        serial = commission.serial
107 fac1de87 Georgios D. Tsoukalas
108 d03796c2 Giorgos Korfiatis
        operations = Operations()
109 6afede3f Giorgos Korfiatis
110 d03796c2 Giorgos Korfiatis
        try:
111 d03796c2 Giorgos Korfiatis
            checked = []
112 79e3da8a Giorgos Korfiatis
            for provision in provisions:
113 79e3da8a Giorgos Korfiatis
                try:
114 79e3da8a Giorgos Korfiatis
                    holder = provision['holder']
115 79e3da8a Giorgos Korfiatis
                    source = provision['source']
116 79e3da8a Giorgos Korfiatis
                    resource = provision['resource']
117 79e3da8a Giorgos Korfiatis
                    quantity = provision['quantity']
118 79e3da8a Giorgos Korfiatis
                except KeyError:
119 79e3da8a Giorgos Korfiatis
                    raise InvalidDataError("Malformed provision")
120 6afede3f Giorgos Korfiatis
121 79e3da8a Giorgos Korfiatis
                if not isinstance(quantity, (int, long)):
122 79e3da8a Giorgos Korfiatis
                    raise InvalidDataError("Malformed provision")
123 c3a709ad root
124 d03796c2 Giorgos Korfiatis
                ent_res = holder, resource
125 d03796c2 Giorgos Korfiatis
                if ent_res in checked:
126 d03796c2 Giorgos Korfiatis
                    m = "Duplicate provision for %s.%s" % ent_res
127 79e3da8a Giorgos Korfiatis
                    details = {'message': m,
128 79e3da8a Giorgos Korfiatis
                               }
129 79e3da8a Giorgos Korfiatis
                    raise DuplicateError(m,
130 79e3da8a Giorgos Korfiatis
                                         provision=provision,
131 79e3da8a Giorgos Korfiatis
                                         details=details)
132 d03796c2 Giorgos Korfiatis
                checked.append(ent_res)
133 fac1de87 Georgios D. Tsoukalas
134 d03796c2 Giorgos Korfiatis
                # Target
135 d03796c2 Giorgos Korfiatis
                try:
136 2864e701 Giorgos Korfiatis
                    th = db_get_holding(holder=holder,
137 2864e701 Giorgos Korfiatis
                                        resource=resource,
138 2864e701 Giorgos Korfiatis
                                        source=source,
139 d03796c2 Giorgos Korfiatis
                                        for_update=True)
140 d03796c2 Giorgos Korfiatis
                except Holding.DoesNotExist:
141 79e3da8a Giorgos Korfiatis
                    m = ("There is no such holding %s.%s"
142 79e3da8a Giorgos Korfiatis
                         % (holder, resource))
143 79e3da8a Giorgos Korfiatis
                    raise NoHoldingError(m,
144 79e3da8a Giorgos Korfiatis
                                         provision=provision)
145 d551c841 Georgios D. Tsoukalas
146 d03796c2 Giorgos Korfiatis
                if quantity >= 0:
147 79e3da8a Giorgos Korfiatis
                    operations.prepare(Import, th, quantity, force)
148 fac1de87 Georgios D. Tsoukalas
149 d03796c2 Giorgos Korfiatis
                else: # release
150 d03796c2 Giorgos Korfiatis
                    abs_quantity = -quantity
151 79e3da8a Giorgos Korfiatis
                    operations.prepare(Release, th, abs_quantity, force)
152 d03796c2 Giorgos Korfiatis
153 d03796c2 Giorgos Korfiatis
                Provision.objects.create(serial=commission,
154 2864e701 Giorgos Korfiatis
                                         holding=th,
155 d03796c2 Giorgos Korfiatis
                                         quantity=quantity)
156 d03796c2 Giorgos Korfiatis
157 d03796c2 Giorgos Korfiatis
        except QuotaholderError:
158 d03796c2 Giorgos Korfiatis
            operations.revert()
159 d03796c2 Giorgos Korfiatis
            raise
160 fac1de87 Georgios D. Tsoukalas
161 fac1de87 Georgios D. Tsoukalas
        return serial
162 fac1de87 Georgios D. Tsoukalas
163 1d734153 Giorgos Korfiatis
    def _log_provision(self,
164 2864e701 Giorgos Korfiatis
                       commission, provision, log_time, reason):
165 2864e701 Giorgos Korfiatis
166 2864e701 Giorgos Korfiatis
        holding = provision.holding
167 1dedc367 Georgios D. Tsoukalas
168 1d734153 Giorgos Korfiatis
        kwargs = {
169 1d734153 Giorgos Korfiatis
            'serial':              commission.serial,
170 1d734153 Giorgos Korfiatis
            'name':                commission.name,
171 2864e701 Giorgos Korfiatis
            'holder':              holding.holder,
172 2864e701 Giorgos Korfiatis
            'source':              holding.source,
173 2864e701 Giorgos Korfiatis
            'resource':            holding.resource,
174 b78f2b29 Giorgos Korfiatis
            'limit':               holding.limit,
175 2864e701 Giorgos Korfiatis
            'imported_min':        holding.imported_min,
176 2864e701 Giorgos Korfiatis
            'imported_max':        holding.imported_max,
177 1d734153 Giorgos Korfiatis
            'delta_quantity':      provision.quantity,
178 1d734153 Giorgos Korfiatis
            'issue_time':          commission.issue_time,
179 1d734153 Giorgos Korfiatis
            'log_time':            log_time,
180 1d734153 Giorgos Korfiatis
            'reason':              reason,
181 1d734153 Giorgos Korfiatis
        }
182 1d734153 Giorgos Korfiatis
183 1d734153 Giorgos Korfiatis
        ProvisionLog.objects.create(**kwargs)
184 1d734153 Giorgos Korfiatis
185 1d734153 Giorgos Korfiatis
    def accept_commission(self,
186 e3685916 Giorgos Korfiatis
                          context=None, clientkey=None,
187 79e3da8a Giorgos Korfiatis
                          serial=None, reason=''):
188 b435047b root
        log_time = now()
189 b435047b root
190 79e3da8a Giorgos Korfiatis
        try:
191 79e3da8a Giorgos Korfiatis
            c = db_get_commission(clientkey=clientkey, serial=serial,
192 79e3da8a Giorgos Korfiatis
                                  for_update=True)
193 79e3da8a Giorgos Korfiatis
        except Commission.DoesNotExist:
194 79e3da8a Giorgos Korfiatis
            return False
195 d03796c2 Giorgos Korfiatis
196 79e3da8a Giorgos Korfiatis
        operations = Operations()
197 fac1de87 Georgios D. Tsoukalas
198 79e3da8a Giorgos Korfiatis
        provisions = db_filter_provision(serial=serial, for_update=True)
199 79e3da8a Giorgos Korfiatis
        for pv in provisions:
200 79e3da8a Giorgos Korfiatis
            try:
201 79e3da8a Giorgos Korfiatis
                th = db_get_holding(id=pv.holding_id,
202 79e3da8a Giorgos Korfiatis
                                    for_update=True)
203 79e3da8a Giorgos Korfiatis
            except Holding.DoesNotExist:
204 79e3da8a Giorgos Korfiatis
                m = "Corrupted provision"
205 79e3da8a Giorgos Korfiatis
                raise CorruptedError(m)
206 f590f930 Georgios D. Tsoukalas
207 79e3da8a Giorgos Korfiatis
            quantity = pv.quantity
208 f590f930 Georgios D. Tsoukalas
209 79e3da8a Giorgos Korfiatis
            if quantity >= 0:
210 79e3da8a Giorgos Korfiatis
                operations.finalize(Import, th, quantity)
211 79e3da8a Giorgos Korfiatis
            else: # release
212 79e3da8a Giorgos Korfiatis
                abs_quantity = -quantity
213 79e3da8a Giorgos Korfiatis
                operations.finalize(Release, th, abs_quantity)
214 fac1de87 Georgios D. Tsoukalas
215 79e3da8a Giorgos Korfiatis
            reason = 'ACCEPT:' + reason[-121:]
216 79e3da8a Giorgos Korfiatis
            self._log_provision(c, pv, log_time, reason)
217 79e3da8a Giorgos Korfiatis
            pv.delete()
218 79e3da8a Giorgos Korfiatis
        c.delete()
219 79e3da8a Giorgos Korfiatis
        return True
220 fac1de87 Georgios D. Tsoukalas
221 1d734153 Giorgos Korfiatis
    def reject_commission(self,
222 e3685916 Giorgos Korfiatis
                          context=None, clientkey=None,
223 79e3da8a Giorgos Korfiatis
                          serial=None, reason=''):
224 b435047b root
        log_time = now()
225 b435047b root
226 79e3da8a Giorgos Korfiatis
        try:
227 79e3da8a Giorgos Korfiatis
            c = db_get_commission(clientkey=clientkey, serial=serial,
228 79e3da8a Giorgos Korfiatis
                                  for_update=True)
229 79e3da8a Giorgos Korfiatis
        except Commission.DoesNotExist:
230 79e3da8a Giorgos Korfiatis
            return False
231 d03796c2 Giorgos Korfiatis
232 79e3da8a Giorgos Korfiatis
        operations = Operations()
233 fac1de87 Georgios D. Tsoukalas
234 79e3da8a Giorgos Korfiatis
        provisions = db_filter_provision(serial=serial, for_update=True)
235 79e3da8a Giorgos Korfiatis
        for pv in provisions:
236 79e3da8a Giorgos Korfiatis
            try:
237 79e3da8a Giorgos Korfiatis
                th = db_get_holding(id=pv.holding_id,
238 79e3da8a Giorgos Korfiatis
                                    for_update=True)
239 79e3da8a Giorgos Korfiatis
            except Holding.DoesNotExist:
240 79e3da8a Giorgos Korfiatis
                m = "Corrupted provision"
241 79e3da8a Giorgos Korfiatis
                raise CorruptedError(m)
242 f590f930 Georgios D. Tsoukalas
243 79e3da8a Giorgos Korfiatis
            quantity = pv.quantity
244 fe6c61fb root
245 79e3da8a Giorgos Korfiatis
            if quantity >= 0:
246 79e3da8a Giorgos Korfiatis
                operations.undo(Import, th, quantity)
247 79e3da8a Giorgos Korfiatis
            else: # release
248 79e3da8a Giorgos Korfiatis
                abs_quantity = -quantity
249 79e3da8a Giorgos Korfiatis
                operations.undo(Release, th, abs_quantity)
250 fac1de87 Georgios D. Tsoukalas
251 79e3da8a Giorgos Korfiatis
            reason = 'REJECT:' + reason[-121:]
252 79e3da8a Giorgos Korfiatis
            self._log_provision(c, pv, log_time, reason)
253 79e3da8a Giorgos Korfiatis
            pv.delete()
254 79e3da8a Giorgos Korfiatis
        c.delete()
255 79e3da8a Giorgos Korfiatis
        return True
256 fac1de87 Georgios D. Tsoukalas
257 e3685916 Giorgos Korfiatis
    def get_pending_commissions(self, context=None, clientkey=None):
258 e5a2e942 Georgios D. Tsoukalas
        pending = Commission.objects.filter(clientkey=clientkey)
259 e5a2e942 Georgios D. Tsoukalas
        pending_list = pending.values_list('serial', flat=True)
260 79e3da8a Giorgos Korfiatis
        return list(pending_list)
261 79e3da8a Giorgos Korfiatis
262 79e3da8a Giorgos Korfiatis
    def get_commission(self, clientkey=None, serial=None):
263 79e3da8a Giorgos Korfiatis
        try:
264 79e3da8a Giorgos Korfiatis
            commission = Commission.objects.get(clientkey=clientkey,
265 79e3da8a Giorgos Korfiatis
                                                serial=serial)
266 79e3da8a Giorgos Korfiatis
        except Commission.DoesNotExist:
267 79e3da8a Giorgos Korfiatis
            raise NoCommissionError(serial)
268 79e3da8a Giorgos Korfiatis
269 79e3da8a Giorgos Korfiatis
        objs = Provision.objects.select_related('holding')
270 79e3da8a Giorgos Korfiatis
        provisions = objs.filter(serial=commission)
271 79e3da8a Giorgos Korfiatis
272 79e3da8a Giorgos Korfiatis
        ps = [p.todict() for p in provisions]
273 79e3da8a Giorgos Korfiatis
274 79e3da8a Giorgos Korfiatis
        response = {'serial':     serial,
275 79e3da8a Giorgos Korfiatis
                    'provisions': ps,
276 79e3da8a Giorgos Korfiatis
                    'issue_time': commission.issue_time,
277 79e3da8a Giorgos Korfiatis
                    }
278 79e3da8a Giorgos Korfiatis
        return response
279 79e3da8a Giorgos Korfiatis
280 79e3da8a Giorgos Korfiatis
    def _resolve(self, include, exclude, operation):
281 79e3da8a Giorgos Korfiatis
        done = []
282 79e3da8a Giorgos Korfiatis
        failed = []
283 79e3da8a Giorgos Korfiatis
        for serial in include:
284 79e3da8a Giorgos Korfiatis
            if serial in exclude:
285 79e3da8a Giorgos Korfiatis
                failed.append((serial, 'CONFLICT'))
286 79e3da8a Giorgos Korfiatis
            else:
287 79e3da8a Giorgos Korfiatis
                response = operation(serial=serial)
288 79e3da8a Giorgos Korfiatis
                if response:
289 79e3da8a Giorgos Korfiatis
                    done.append(serial)
290 79e3da8a Giorgos Korfiatis
                else:
291 79e3da8a Giorgos Korfiatis
                    failed.append((serial, 'NOTFOUND'))
292 79e3da8a Giorgos Korfiatis
        return done, failed
293 fac1de87 Georgios D. Tsoukalas
294 1d734153 Giorgos Korfiatis
    def resolve_pending_commissions(self,
295 e3685916 Giorgos Korfiatis
                                    context=None, clientkey=None,
296 79e3da8a Giorgos Korfiatis
                                    accept_set=[], reject_set=[]):
297 fac1de87 Georgios D. Tsoukalas
        accept_set = set(accept_set)
298 79e3da8a Giorgos Korfiatis
        reject_set = set(reject_set)
299 fac1de87 Georgios D. Tsoukalas
300 79e3da8a Giorgos Korfiatis
        accept = partial(self.accept_commission, clientkey=clientkey)
301 79e3da8a Giorgos Korfiatis
        reject = partial(self.reject_commission, clientkey=clientkey)
302 fac1de87 Georgios D. Tsoukalas
303 79e3da8a Giorgos Korfiatis
        accepted, failed_ac = self._resolve(accept_set, reject_set, accept)
304 79e3da8a Giorgos Korfiatis
        rejected, failed_re = self._resolve(reject_set, accept_set, reject)
305 fac1de87 Georgios D. Tsoukalas
306 79e3da8a Giorgos Korfiatis
        failed = list(set(failed_ac + failed_re))
307 79e3da8a Giorgos Korfiatis
        return accepted, rejected, failed
308 fac1de87 Georgios D. Tsoukalas
309 e5a2e942 Georgios D. Tsoukalas
310 fac1de87 Georgios D. Tsoukalas
API_Callpoint = QuotaholderDjangoDBCallpoint