summaryrefslogtreecommitdiffstats
path: root/bank-eiffel/account.e
blob: fe9cc3b8645513dd43de46f62067dcf9ea2799d5 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
class
	ACCOUNT

create
	make

feature -- Access

	balance: REAL_64
			-- Kontostand

	creditline: REAL_64 assign set_creditline
			-- Kreditrahmen

	interest_deposit: REAL_64 assign set_interest_deposit
			-- Habenverzinsung

	interest_debit: REAL_64 assign set_interest_debit
			-- Sollverzinsung

	transfer_minamount: REAL_64 assign set_transfer_minamount
			-- Mindestbetrag fuer jede Einzahlung, Auszahlung und Ueberweisung

feature {NONE} -- Implementation

	range: detachable TUPLE [min: REAL_64; max: REAL_64]

	creditline_range: attached like range
			-- min/max for creditline

	interest_deposit_range: attached like range
			-- min/max for interest_deposit

	interest_debit_range: attached like range
			-- min/max for interest_debit

	authorized_signers: ARRAYED_SET [PERSON]
			-- Zeichnungsberechtigte

feature {NONE} -- Initialization

	make (an_authorized_signer: PERSON;
		  an_interest_deposit: like interest_deposit;
		  an_interest_debit: like interest_debit;
		  a_credit_line: like creditline;
		  an_interest_deposit_range: like interest_deposit_range;
		  an_interest_debit_range: like interest_debit_range;
		  a_credit_line_range: like creditline_range)
		require
			a_credit_line_range.min < a_credit_line_range.max
			an_interest_debit_range.min < an_interest_debit_range.max
			an_interest_deposit_range.min < an_interest_deposit_range.max
		do
			create authorized_signers.make(1)
			add_authorized_signer (an_authorized_signer)
			creditline := a_credit_line
			interest_debit := an_interest_debit
			interest_deposit := an_interest_deposit
			interest_deposit_range := an_interest_deposit_range
			interest_debit_range := an_interest_debit_range
			creditline_range := a_credit_line_range

			set_default_transfer_minamount
			balance := 0.0
		end

feature -- Basic operations

	deposit (an_amount: like transfer_minamount; an_authorized_signer: PERSON)
		require
			an_authorized_signer_authorized: get_authorized_signers.has (an_authorized_signer)
			transfer_minamount_ok: an_amount >= transfer_minamount
		do
			balance := balance + an_amount
		ensure
			balance_increased: balance > old balance
			deposited: balance = old balance + an_amount
		end

	withdraw (an_amount: like transfer_minamount; an_authorized_signer: PERSON)
		require
			an_authorized_signer_authorized: get_authorized_signers.has (an_authorized_signer)
			transfer_minamount_ok: an_amount >= transfer_minamount
		do
			balance := balance - an_amount
		ensure
			balance_decreased: balance < old balance
			withdrawed: balance = old balance - an_amount
			balance_beneath_creditline: balance >= creditline
		end

	transfer(an_amount: like transfer_minamount; an_authorized_signer: PERSON;
			 an_account: like Current; another_authorized_signer: PERSON)
		do
			withdraw (an_amount, an_authorized_signer)
			an_account.deposit (an_amount, another_authorized_signer)
		end

	add_authorized_signer (an_authorized_signer: PERSON)
		do
			if not authorized_signers.has (an_authorized_signer) then
				authorized_signers.put (an_authorized_signer)
			end
		ensure
			authorized_signers_assigned: authorized_signers.has (an_authorized_signer)
		end

	remove_authorized_signer (an_authorized_signer: PERSON)
		require
			authorized_signers_never_empty: (get_authorized_signers.has (an_authorized_signer)
				and get_authorized_signers.count >= 2) or True
		do
			if authorized_signers.has (an_authorized_signer) then
				authorized_signers.prune (an_authorized_signer)
			end
		ensure
			authorized_signers_assigned: not authorized_signers.has (an_authorized_signer)
		end

	get_authorized_signers: FINITE [PERSON]
		do
			Result := authorized_signers
		end

	advance
		do
			if balance < 0.0 then
				-- debit
				balance := balance + (balance * interest_debit)
			else
				-- deposit
				balance := balance + (balance * interest_deposit)
			end
		end

feature {NONE} -- Implementation

	set_transfer_minamount (a_transfer_minamount: like transfer_minamount)
		require
			a_transfer_minamount_positive: a_transfer_minamount > 0.0
		do
			transfer_minamount := a_transfer_minamount
		ensure
			transfer_minamount_assigned: transfer_minamount = a_transfer_minamount
		end

	set_default_transfer_minamount
		do
			set_transfer_minamount (2.0)
		end

	set_creditline (a_creditline: like creditline)
		require
			a_creditline_within_bounds: a_creditline >= creditline_range.min
				and a_creditline <= creditline_range.max
		do
			creditline := a_creditline
		ensure
			creditline_assigned: creditline = a_creditline
		end

	set_interest_deposit (an_interest_deposit: like interest_deposit)
		require
			an_interest_deposit_within_bounds: interest_deposit >= interest_deposit_range.min
				and interest_deposit <= interest_deposit_range.max
		do
			interest_deposit := an_interest_deposit
		ensure
			interest_deposit_assigned: interest_deposit = an_interest_deposit
		end

	set_interest_debit (an_interest_debit: like interest_debit)
		require
			an_interest_deposit_within_bounds: interest_debit >= interest_debit_range.min
				and interest_debit <= interest_debit_range.max
		do
			interest_debit := an_interest_debit
		ensure
			interest_debit_assigned: interest_debit = an_interest_debit
		end

invariant
	authorized_signers_not_empty: authorized_signers.count > 0
	transfer_minamount_positive: transfer_minamount > 0.0
	creditline_within_bounds: creditline >= creditline_range.min
		and creditline <= creditline_range.max
	interest_debit_within_bounds: interest_debit >= interest_debit_range.min
		and interest_debit <= interest_debit_range.max
	interest_deposit_within_bounds: interest_deposit >= interest_deposit_range.min
		and interest_deposit <= interest_deposit_range.max
end