Statistics
| Branch: | Tag: | Revision:

root / snf-astakos-app / astakos / quotaholder / commission.py @ e311d555

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.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
                                  limit=limit,
95
                                  usage=imported_max)
96

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

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

    
105

    
106
class Release(Operation):
107

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

    
113
        if check and new_imported_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
                                  available=imported_min)
122

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

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

    
131

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

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

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

    
145

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

    
149

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