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.OceanusRatio;
21 import io.github.tonywasher.joceanus.oceanus.format.OceanusDataFormatter;
22 import io.github.tonywasher.joceanus.metis.field.MetisFieldSet;
23 import io.github.tonywasher.joceanus.moneywise.tax.MoneyWiseChargeableGainSlice;
24 import io.github.tonywasher.joceanus.moneywise.tax.MoneyWiseTaxBandSet;
25 import io.github.tonywasher.joceanus.moneywise.tax.MoneyWiseTaxBandSet.MoneyWiseTaxBand;
26 import io.github.tonywasher.joceanus.moneywise.tax.MoneyWiseTaxDueBucket;
27 import io.github.tonywasher.joceanus.moneywise.tax.MoneyWiseTaxResource;
28 import io.github.tonywasher.joceanus.moneywise.tax.MoneyWiseTaxSource;
29
30 import java.util.Iterator;
31
32
33
34
35 public class MoneyWiseUKChargeableGainsScheme
36 extends MoneyWiseUKIncomeScheme {
37
38
39
40 protected MoneyWiseUKChargeableGainsScheme() {
41 super(Boolean.FALSE);
42 }
43
44
45
46
47 public static class MoneyWiseUKSlicedTaxDueBucket
48 extends MoneyWiseTaxDueBucket {
49
50
51
52 private static final MetisFieldSet<MoneyWiseUKSlicedTaxDueBucket> FIELD_DEFS = MetisFieldSet.newFieldSet(MoneyWiseUKSlicedTaxDueBucket.class);
53
54
55
56
57 static {
58 FIELD_DEFS.declareLocalField(MoneyWiseTaxResource.CHARGEABLEGAIN_TOTALGAINS, MoneyWiseUKSlicedTaxDueBucket::getTotalGains);
59 FIELD_DEFS.declareLocalField(MoneyWiseTaxResource.CHARGEABLEGAIN_TOTALSLICES, MoneyWiseUKSlicedTaxDueBucket::getTotalSlices);
60 FIELD_DEFS.declareLocalField(MoneyWiseTaxResource.CHARGEABLEGAIN_RATIO, MoneyWiseUKSlicedTaxDueBucket::getRatio);
61 FIELD_DEFS.declareLocalField(MoneyWiseTaxResource.CHARGEABLEGAIN_TAXEDSLICES, MoneyWiseUKSlicedTaxDueBucket::getTaxedSlices);
62 FIELD_DEFS.declareLocalField(MoneyWiseTaxResource.CHARGEABLEGAIN_NETTTAXDUE, MoneyWiseUKSlicedTaxDueBucket::getNettTaxDue);
63 FIELD_DEFS.declareLocalField(MoneyWiseTaxResource.CHARGEABLEGAIN_TAXRELIEF, MoneyWiseUKSlicedTaxDueBucket::getTaxRelief);
64 }
65
66
67
68
69 private final OceanusMoney theTotalGains;
70
71
72
73
74 private final OceanusMoney theTotalSlices;
75
76
77
78
79 private final OceanusRatio theRatio;
80
81
82
83
84 private final MoneyWiseTaxDueBucket theSliceBucket;
85
86
87
88
89 private final OceanusMoney theTaxRelief;
90
91
92
93
94 private final OceanusMoney theNettTaxDue;
95
96
97
98
99
100
101
102 protected MoneyWiseUKSlicedTaxDueBucket(final MoneyWiseTaxDueBucket pBase,
103 final MoneyWiseTaxSource pSource) {
104
105 super(pBase);
106
107
108 final OceanusMoney myZero = new OceanusMoney(pBase.getTaxDue());
109 theTotalGains = new OceanusMoney(myZero);
110 theTotalSlices = new OceanusMoney(myZero);
111 theTaxRelief = new OceanusMoney(myZero);
112 theNettTaxDue = new OceanusMoney(myZero);
113
114
115 for (MoneyWiseChargeableGainSlice mySlice : pSource.getGainSlices().getUnderlyingList()) {
116 processSlice(mySlice);
117 }
118
119
120 theRatio = new OceanusRatio(theTotalGains, theTotalSlices);
121
122
123 theSliceBucket = buildSliceBucket();
124 calculateTax();
125 }
126
127
128
129
130
131
132 public OceanusMoney getTotalGains() {
133 return theTotalGains;
134 }
135
136
137
138
139
140
141 public OceanusMoney getTotalSlices() {
142 return theTotalSlices;
143 }
144
145
146
147
148
149
150 public OceanusRatio getRatio() {
151 return theRatio;
152 }
153
154
155
156
157
158
159 public MoneyWiseTaxDueBucket getTaxedSlices() {
160 return theSliceBucket;
161 }
162
163
164
165
166
167
168 public OceanusMoney getNettTaxDue() {
169 return theNettTaxDue;
170 }
171
172
173
174
175
176
177 public OceanusMoney getTaxRelief() {
178 return theTaxRelief;
179 }
180
181
182
183
184
185
186 private void processSlice(final MoneyWiseChargeableGainSlice pSlice) {
187
188 theTotalGains.addAmount(pSlice.getGain());
189 theTotalSlices.addAmount(pSlice.getSlice());
190 }
191
192
193
194
195
196
197 private MoneyWiseTaxDueBucket buildSliceBucket() {
198
199 final MoneyWiseTaxBandSet myTaxBands = new MoneyWiseTaxBandSet();
200 final OceanusMoney myRemaining = new OceanusMoney(theTotalSlices);
201
202
203 final Iterator<MoneyWiseTaxBandBucket> myIterator = taxBandIterator();
204 while (myRemaining.isNonZero()
205 && myIterator.hasNext()) {
206 final MoneyWiseTaxBandBucket myBucket = myIterator.next();
207
208
209 OceanusMoney myAmount = getAmountInBand(myBucket.getAmount(), myRemaining);
210 myAmount = new OceanusMoney(myAmount);
211
212
213 myTaxBands.addTaxBand(new MoneyWiseTaxBand(myAmount, myBucket.getRate()));
214 myRemaining.subtractAmount(myAmount);
215 }
216
217
218 return new MoneyWiseTaxDueBucket(getTaxBasis(), myTaxBands, getTaxConfig());
219 }
220
221
222
223
224 private void calculateTax() {
225
226 theNettTaxDue.add(theSliceBucket.getTaxDue().valueAtRatio(theRatio));
227
228
229 theTaxRelief.addAmount(getTaxDue());
230 theTaxRelief.subtractAmount(theNettTaxDue);
231 }
232
233 @Override
234 public String formatObject(final OceanusDataFormatter pFormatter) {
235 return FIELD_DEFS.getName();
236 }
237
238 @Override
239 public MetisFieldSet<MoneyWiseUKSlicedTaxDueBucket> getDataFieldSet() {
240 return FIELD_DEFS;
241 }
242 }
243 }