Statistics
| Branch: | Tag: | Revision:

root / snf-astakos-app / astakos / quotaholder / commission.py @ 79e3da8a

History | View | Annotate | Download (5.1 kB)

1
# Copyright 2013 GRNET S.A. All rights reserved.
2
#
3
# Redistribution and use in source and binary forms, with or
4
# without modification, are permitted provided that the following
5
# conditions are met:
6
#
7
#   1. Redistributions of source code must retain the above
8
#      copyright notice, this list of conditions and the following
9
#      disclaimer.
10
#
11
#   2. Redistributions in binary form must reproduce the above
12
#      copyright notice, this list of conditions and the following
13
#      disclaimer in the documentation and/or other materials
14
#      provided with the distribution.
15
#
16
# THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
17
# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
20
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
23
# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
24
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
26
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27
# POSSIBILITY OF SUCH DAMAGE.
28
#
29
# The views and conclusions contained in the software and
30
# documentation are those of the authors and should not be
31
# interpreted as representing official policies, either expressed
32
# or implied, of GRNET S.A.
33

    
34
from astakos.quotaholder.exception import NoCapacityError, NoQuantityError
35

    
36

    
37
class Operation(object):
38

    
39
    @staticmethod
40
    def assertions(holding):
41
        assert(holding.imported_min <= holding.imported_max)
42

    
43
    @classmethod
44
    def _prepare(cls, holding, quantity, check=True):
45
        raise NotImplementedError
46

    
47
    @classmethod
48
    def prepare(cls, holding, quantity, check=True):
49
        cls.assertions(holding)
50
        cls._prepare(holding, quantity, check)
51

    
52
    @classmethod
53
    def _finalize(cls, holding, quantity):
54
        raise NotImplementedError
55

    
56
    @classmethod
57
    def finalize(cls, holding, quantity):
58
        cls.assertions(holding)
59
        cls._finalize(holding, quantity)
60

    
61
    @classmethod
62
    def undo(cls, holding, quantity):
63
        cls.prepare(holding, -quantity, check=False)
64

    
65
    @classmethod
66
    def revert(cls, holding, quantity):
67
        # Assertions do not hold when reverting
68
        cls._prepare(holding, -quantity, check=False)
69

    
70
    @classmethod
71
    def provision(cls, holding, quantity, importing=True):
72
        return {'holder': holding.holder,
73
                'source': holding.source,
74
                'resource': holding.resource,
75
                'quantity': quantity if importing else -quantity,
76
                }
77

    
78

    
79
class Import(Operation):
80

    
81
    @classmethod
82
    def _prepare(cls, holding, quantity, check=True):
83
        imported_max = holding.imported_max
84
        new_imported_max = imported_max + quantity
85

    
86
        limit = holding.limit
87
        if check and new_imported_max > limit:
88
            holder = holding.holder
89
            resource = holding.resource
90
            m = ("%s has not enough capacity of %s." % (holder, resource))
91
            provision = cls.provision(holding, quantity, importing=True)
92
            raise NoCapacityError(m,
93
                                  provision=provision,
94
                                  available=limit-imported_max)
95

    
96
        holding.imported_max = new_imported_max
97
        holding.save()
98

    
99
    @classmethod
100
    def _finalize(cls, holding, quantity):
101
        holding.imported_min += quantity
102
        holding.save()
103

    
104

    
105
class Release(Operation):
106

    
107
    @classmethod
108
    def _prepare(cls, holding, quantity, check=True):
109
        imported_min = holding.imported_min
110
        new_imported_min = imported_min - quantity
111

    
112
        if check and new_imported_min < 0:
113
            holder = holding.holder
114
            resource = holding.resource
115
            m = ("%s attempts to release more %s than it contains." %
116
                 (holder, resource))
117
            provision = cls.provision(holding, quantity, importing=False)
118
            raise NoQuantityError(m,
119
                                  provision=provision,
120
                                  available=imported_min)
121

    
122
        holding.imported_min = new_imported_min
123
        holding.save()
124

    
125
    @classmethod
126
    def _finalize(cls, holding, quantity):
127
        holding.imported_max -= quantity
128
        holding.save()
129

    
130

    
131
class Operations(object):
132
    def __init__(self):
133
        self.operations = []
134

    
135
    def prepare(self, operation, holding, quantity, force):
136
        check = not force
137
        operation.prepare(holding, quantity, check)
138
        self.operations.append((operation, holding, quantity))
139

    
140
    def finalize(self, operation, holding, quantity):
141
        operation.finalize(holding, quantity)
142
        self.operations.append((operation, holding, quantity))
143

    
144
    def undo(self, operation, holding, quantity):
145
        operation.undo(holding, quantity)
146
        self.operations.append((operation, holding, quantity))
147

    
148
    def revert(self):
149
        for (operation, holding, quantity) in self.operations:
150
            operation.revert(holding, quantity)