1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package io.github.tonywasher.joceanus.moneywise.tax.uk;
18
19 import io.github.tonywasher.joceanus.oceanus.decimal.OceanusMoney;
20 import io.github.tonywasher.joceanus.oceanus.decimal.OceanusRate;
21 import io.github.tonywasher.joceanus.metis.field.MetisFieldSet;
22 import io.github.tonywasher.joceanus.moneywise.data.statics.MoneyWiseTaxClass;
23 import io.github.tonywasher.joceanus.moneywise.tax.MoneyWiseTaxBandSet.MoneyWiseTaxBand;
24 import io.github.tonywasher.joceanus.moneywise.tax.MoneyWiseTaxResource;
25
26 import java.util.ArrayList;
27 import java.util.Iterator;
28 import java.util.List;
29
30
31
32
33 public abstract class MoneyWiseUKDividendScheme
34 extends MoneyWiseUKIncomeScheme {
35
36
37
38 static {
39 MetisFieldSet.newFieldSet(MoneyWiseUKDividendScheme.class);
40 }
41
42
43
44
45 protected MoneyWiseUKDividendScheme() {
46 this(Boolean.TRUE);
47 }
48
49
50
51
52
53
54 protected MoneyWiseUKDividendScheme(final Boolean pReliefAvailable) {
55 super(pReliefAvailable);
56 }
57
58
59
60
61
62
63
64 protected abstract OceanusRate getTaxCreditRate(MoneyWiseUKTaxYear pTaxYear);
65
66 @Override
67 protected OceanusMoney adjustAllowances(final MoneyWiseUKTaxConfig pConfig,
68 final OceanusMoney pAmount) {
69
70 final OceanusMoney myRemaining = super.adjustAllowances(pConfig, pAmount);
71
72
73 if (myRemaining.isNonZero()) {
74
75 adjustForAllowance(pConfig.getDividendAllowance(), myRemaining);
76 }
77
78
79 return myRemaining;
80 }
81
82 @Override
83 protected OceanusMoney getAmountInAllowance(final MoneyWiseUKTaxConfig pConfig,
84 final OceanusMoney pAmount) {
85
86 OceanusMoney myAmount = super.getAmountInAllowance(pConfig, pAmount);
87
88
89 if (myAmount.compareTo(pAmount) < 0) {
90
91 final OceanusMoney myRemaining = new OceanusMoney(pAmount);
92 myRemaining.subtractAmount(myAmount);
93
94
95 final OceanusMoney myXtra = getAmountInBand(pConfig.getDividendAllowance(), myRemaining);
96
97
98 myAmount = new OceanusMoney(myAmount);
99 myAmount.addAmount(myXtra);
100 }
101
102
103 return myAmount;
104 }
105
106
107
108
109
110
111 protected OceanusRate getBaseRate() {
112 return null;
113 }
114
115
116
117
118
119
120 protected OceanusRate getHigherRate() {
121 return null;
122 }
123
124
125
126
127
128
129 protected OceanusRate getAdditionalRate() {
130 return null;
131 }
132
133 @Override
134 protected Iterator<MoneyWiseTaxBand> taxBandIterator(final MoneyWiseUKTaxConfig pConfig,
135 final MoneyWiseTaxClass pBasis) {
136
137
138 final List<MoneyWiseTaxBand> myList = new ArrayList<>();
139
140
141 final Iterator<MoneyWiseTaxBand> myIterator = super.taxBandIterator(pConfig, pBasis);
142 MoneyWiseTaxBand myBand = myIterator.next();
143 OceanusMoney myAmount = myBand.getAmount();
144 OceanusRate myRate = getBaseRate();
145
146
147 if (this instanceof MoneyWiseUKDividendLoHigherRateScheme) {
148
149 myBand = myIterator.next();
150 myAmount = new OceanusMoney(myAmount);
151 myAmount.addAmount(myBand.getAmount());
152 }
153
154
155 if (myRate == null) {
156 myRate = myBand.getRate();
157 }
158 myList.add(new MoneyWiseTaxBand(myAmount, myRate));
159
160
161 if (myIterator.hasNext()) {
162
163 myBand = myIterator.next();
164 myRate = getHigherRate();
165 if (myRate == null) {
166 myRate = myBand.getRate();
167 }
168 myList.add(new MoneyWiseTaxBand(myBand.getAmount(), myRate));
169 }
170
171
172 if (myIterator.hasNext()) {
173
174 myBand = myIterator.next();
175 myRate = getAdditionalRate();
176 if (myRate == null) {
177 myRate = myBand.getRate();
178 }
179 myList.add(new MoneyWiseTaxBand(myBand.getAmount(), myRate));
180 }
181
182
183 while (myIterator.hasNext()) {
184 myBand = myIterator.next();
185 myList.add(myBand);
186 }
187
188
189 return myList.iterator();
190 }
191
192
193
194
195 public static class MoneyWiseUKDividendAsIncomeScheme
196 extends MoneyWiseUKDividendScheme {
197
198
199
200 private static final MetisFieldSet<MoneyWiseUKDividendAsIncomeScheme> FIELD_DEFS = MetisFieldSet.newFieldSet(MoneyWiseUKDividendAsIncomeScheme.class);
201
202
203
204
205 protected MoneyWiseUKDividendAsIncomeScheme() {
206 }
207
208 @Override
209 protected OceanusRate getTaxCreditRate(final MoneyWiseUKTaxYear pTaxYear) {
210 return pTaxYear.getTaxBands().getBasicTaxRate();
211 }
212
213 @Override
214 public MetisFieldSet<MoneyWiseUKDividendAsIncomeScheme> getDataFieldSet() {
215 return FIELD_DEFS;
216 }
217 }
218
219
220
221
222 public static class MoneyWiseUKDividendBaseRateScheme
223 extends MoneyWiseUKDividendScheme {
224
225
226
227 private static final MetisFieldSet<MoneyWiseUKDividendBaseRateScheme> FIELD_DEFS = MetisFieldSet.newFieldSet(MoneyWiseUKDividendBaseRateScheme.class);
228
229
230
231
232 static {
233 FIELD_DEFS.declareLocalField(MoneyWiseTaxResource.SCHEME_BASE_RATE, MoneyWiseUKDividendBaseRateScheme::getBaseRate);
234 }
235
236
237
238
239 private final OceanusRate theBaseRate;
240
241
242
243
244
245
246
247 protected MoneyWiseUKDividendBaseRateScheme(final OceanusRate pRate,
248 final Boolean pReliefAvailable) {
249 super(pReliefAvailable);
250 theBaseRate = pRate;
251 }
252
253
254
255
256
257
258 protected MoneyWiseUKDividendBaseRateScheme(final OceanusRate pRate) {
259 this(pRate, Boolean.TRUE);
260 }
261
262 @Override
263 protected OceanusRate getBaseRate() {
264 return theBaseRate;
265 }
266
267 @Override
268 protected OceanusRate getTaxCreditRate(final MoneyWiseUKTaxYear pTaxYear) {
269 return theBaseRate;
270 }
271
272 @Override
273 public MetisFieldSet<? extends MoneyWiseUKDividendBaseRateScheme> getDataFieldSet() {
274 return FIELD_DEFS;
275 }
276 }
277
278
279
280
281 public static class MoneyWiseUKDividendHigherRateScheme
282 extends MoneyWiseUKDividendBaseRateScheme {
283
284
285
286 private static final MetisFieldSet<MoneyWiseUKDividendHigherRateScheme> FIELD_DEFS = MetisFieldSet.newFieldSet(MoneyWiseUKDividendHigherRateScheme.class);
287
288
289
290
291 static {
292 FIELD_DEFS.declareLocalField(MoneyWiseTaxResource.SCHEME_HIGH_RATE, MoneyWiseUKDividendHigherRateScheme::getHigherRate);
293 }
294
295
296
297
298 private final OceanusRate theHighRate;
299
300
301
302
303
304
305
306 protected MoneyWiseUKDividendHigherRateScheme(final OceanusRate pRate,
307 final OceanusRate pHighRate) {
308 this(pRate, pHighRate, Boolean.FALSE);
309 }
310
311
312
313
314
315
316
317
318 protected MoneyWiseUKDividendHigherRateScheme(final OceanusRate pRate,
319 final OceanusRate pHighRate,
320 final Boolean pReliefAvailable) {
321 super(pRate, pReliefAvailable);
322 theHighRate = pHighRate;
323 }
324
325 @Override
326 protected OceanusRate getHigherRate() {
327 return theHighRate;
328 }
329
330 @Override
331 public MetisFieldSet<? extends MoneyWiseUKDividendHigherRateScheme> getDataFieldSet() {
332 return FIELD_DEFS;
333 }
334 }
335
336
337
338
339 public static class MoneyWiseUKDividendLoHigherRateScheme
340 extends MoneyWiseUKDividendHigherRateScheme {
341
342
343
344 private static final MetisFieldSet<MoneyWiseUKDividendLoHigherRateScheme> FIELD_DEFS = MetisFieldSet.newFieldSet(MoneyWiseUKDividendLoHigherRateScheme.class);
345
346
347
348
349
350
351
352 protected MoneyWiseUKDividendLoHigherRateScheme(final OceanusRate pRate,
353 final OceanusRate pHigherRate) {
354 super(pRate, pHigherRate);
355 }
356
357 @Override
358 public MetisFieldSet<MoneyWiseUKDividendLoHigherRateScheme> getDataFieldSet() {
359 return FIELD_DEFS;
360 }
361 }
362
363
364
365
366 public static class MoneyWiseUKDividendAdditionalRateScheme
367 extends MoneyWiseUKDividendHigherRateScheme {
368
369
370
371 private static final MetisFieldSet<MoneyWiseUKDividendAdditionalRateScheme> FIELD_DEFS = MetisFieldSet.newFieldSet(MoneyWiseUKDividendAdditionalRateScheme.class);
372
373
374
375
376 static {
377 FIELD_DEFS.declareLocalField(MoneyWiseTaxResource.SCHEME_ADDITIONAL_RATE, MoneyWiseUKDividendHigherRateScheme::getAdditionalRate);
378 }
379
380
381
382
383 private final OceanusRate theAdditionalRate;
384
385
386
387
388
389
390
391
392 protected MoneyWiseUKDividendAdditionalRateScheme(final OceanusRate pRate,
393 final OceanusRate pHighRate,
394 final OceanusRate pAddRate) {
395 this(pRate, pHighRate, pAddRate, Boolean.FALSE);
396 }
397
398
399
400
401
402
403
404
405
406 protected MoneyWiseUKDividendAdditionalRateScheme(final OceanusRate pRate,
407 final OceanusRate pHighRate,
408 final OceanusRate pAddRate,
409 final Boolean pReliefAvailable) {
410 super(pRate, pHighRate, pReliefAvailable);
411 theAdditionalRate = pAddRate;
412 }
413
414 @Override
415 protected OceanusRate getAdditionalRate() {
416 return theAdditionalRate;
417 }
418
419 @Override
420 public MetisFieldSet<MoneyWiseUKDividendAdditionalRateScheme> getDataFieldSet() {
421 return FIELD_DEFS;
422 }
423 }
424 }