Statistics
| Branch: | Tag: | Revision:

root / snf-astakos-app / astakos / quotaholder_app / commission.py @ 3715f954

History | View | Annotate | Download (5 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_app.exception import NoCapacityError, NoQuantityError
35

    
36

    
37
class Operation(object):
38

    
39
    @staticmethod
40
    def assertions(holding):
41
        assert(holding.usage_min <= holding.usage_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
        usage_max = holding.usage_max
84
        new_usage_max = usage_max + quantity
85

    
86
        limit = holding.limit
87
        if check and new_usage_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
                                  limit=limit,
95
                                  usage=usage_max)
96

    
97
        holding.usage_max = new_usage_max
98
        holding.save()
99

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

    
105

    
106
class Release(Operation):
107

    
108
    @classmethod
109
    def _prepare(cls, holding, quantity, check=True):
110
        usage_min = holding.usage_min
111
        new_usage_min = usage_min - quantity
112

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

    
124
        holding.usage_min = new_usage_min
125
        holding.save()
126

    
127
    @classmethod
128
    def _finalize(cls, holding, quantity):
129
        holding.usage_max -= quantity
130
        holding.save()
131

    
132

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

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

    
142
    def revert(self):
143
        for (operation, holding, quantity) in self.operations:
144
            operation.revert(holding, quantity)
145

    
146

    
147
def finalize(operation, holding, quantity):
148
    operation.finalize(holding, quantity)
149

    
150

    
151
def undo(operation, holding, quantity):
152
    operation.undo(holding, quantity)