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