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.base.OceanusException;
20 import io.github.tonywasher.joceanus.oceanus.date.OceanusDate;
21 import io.github.tonywasher.joceanus.oceanus.decimal.OceanusMoney;
22 import io.github.tonywasher.joceanus.oceanus.format.OceanusDataFormatter;
23 import io.github.tonywasher.joceanus.metis.field.MetisFieldItem;
24 import io.github.tonywasher.joceanus.metis.field.MetisFieldSet;
25 import io.github.tonywasher.joceanus.metis.preference.MetisPreferenceKey;
26 import io.github.tonywasher.joceanus.metis.preference.MetisPreferenceManager;
27 import io.github.tonywasher.joceanus.metis.preference.MetisPreferenceSet;
28 import io.github.tonywasher.joceanus.moneywise.data.statics.MoneyWiseStaticResource;
29 import io.github.tonywasher.joceanus.moneywise.data.statics.MoneyWiseTaxClass;
30 import io.github.tonywasher.joceanus.moneywise.tax.MoneyWiseTaxAnalysis;
31 import io.github.tonywasher.joceanus.moneywise.tax.MoneyWiseTaxBandSet;
32 import io.github.tonywasher.joceanus.moneywise.tax.MoneyWiseTaxDueBucket;
33 import io.github.tonywasher.joceanus.moneywise.tax.MoneyWiseTaxResource;
34 import io.github.tonywasher.joceanus.moneywise.tax.MoneyWiseTaxSource;
35 import io.github.tonywasher.joceanus.moneywise.tax.uk.MoneyWiseUKChargeableGainsScheme.MoneyWiseUKSlicedTaxDueBucket;
36
37 import java.time.Month;
38 import java.util.ArrayList;
39 import java.util.Iterator;
40 import java.util.List;
41
42
43
44
45 public class MoneyWiseUKTaxAnalysis
46 implements MetisFieldItem, MoneyWiseTaxAnalysis {
47
48
49
50 private static final MetisFieldSet<MoneyWiseUKTaxAnalysis> FIELD_DEFS = MetisFieldSet.newFieldSet(MoneyWiseUKTaxAnalysis.class);
51
52
53
54
55 static {
56 FIELD_DEFS.declareLocalField(MoneyWiseTaxResource.TAXYEAR_NAME, MoneyWiseUKTaxAnalysis::getTaxYear);
57 FIELD_DEFS.declareLocalField(MoneyWiseTaxResource.TAXCONFIG_NAME, MoneyWiseUKTaxAnalysis::getTaxConfig);
58 FIELD_DEFS.declareLocalField(MoneyWiseTaxResource.TAXANALYSIS_TAXBUCKETS, MoneyWiseUKTaxAnalysis::getTaxBuckets);
59 FIELD_DEFS.declareLocalField(MoneyWiseTaxResource.TAXBANDS_INCOME, MoneyWiseUKTaxAnalysis::getTaxableIncome);
60 FIELD_DEFS.declareLocalField(MoneyWiseTaxResource.TAXBANDS_TAXDUE, MoneyWiseUKTaxAnalysis::getTaxDue);
61 FIELD_DEFS.declareLocalField(MoneyWiseStaticResource.TAXBASIS_TAXPAID, MoneyWiseUKTaxAnalysis::getTaxPaid);
62 FIELD_DEFS.declareLocalField(MoneyWiseTaxResource.TAXANALYSIS_TAXPROFIT, MoneyWiseUKTaxAnalysis::getTaxProfit);
63 }
64
65
66
67
68 private final MoneyWiseUKTaxYear theTaxYear;
69
70
71
72
73 private final MoneyWiseTaxSource theTaxSource;
74
75
76
77
78 private final MoneyWiseUKTaxConfig theTaxConfig;
79
80
81
82
83 private final List<MoneyWiseTaxDueBucket> theTaxBuckets;
84
85
86
87
88 private final OceanusMoney theTaxableIncome;
89
90
91
92
93 private final OceanusMoney theTaxDue;
94
95
96
97
98 private final OceanusMoney theTaxPaid;
99
100
101
102
103 private final OceanusMoney theTaxProfit;
104
105
106
107
108 public enum MoneyWiseUKTaxPreferenceKey implements MetisPreferenceKey {
109
110
111
112 BIRTHDATE("BirthDate", MoneyWiseTaxResource.TAXPREF_BIRTH);
113
114
115
116
117 private final String theName;
118
119
120
121
122 private final String theDisplay;
123
124
125
126
127
128
129
130 MoneyWiseUKTaxPreferenceKey(final String pName,
131 final MoneyWiseTaxResource pDisplay) {
132 theName = pName;
133 theDisplay = pDisplay.getValue();
134 }
135
136 @Override
137 public String getName() {
138 return theName;
139 }
140
141 @Override
142 public String getDisplay() {
143 return theDisplay;
144 }
145 }
146
147
148
149
150 public static class MoneyWiseUKTaxPreferences
151 extends MetisPreferenceSet {
152
153
154
155 private static final int YEAR = 1970;
156
157
158
159
160
161
162
163 public MoneyWiseUKTaxPreferences(final MetisPreferenceManager pManager) throws OceanusException {
164 super(pManager, MoneyWiseTaxResource.TAXPREF_NAME);
165 }
166
167 @Override
168 protected void definePreferences() {
169 defineDatePreference(MoneyWiseUKTaxPreferenceKey.BIRTHDATE);
170 }
171
172 @Override
173 public void autoCorrectPreferences() {
174
175 final MetisDatePreference myPref = getDatePreference(MoneyWiseUKTaxPreferenceKey.BIRTHDATE);
176 if (!myPref.isAvailable()) {
177 myPref.setValue(new OceanusDate(YEAR, Month.JANUARY, 1));
178 }
179 }
180 }
181
182
183
184
185
186
187
188
189 protected MoneyWiseUKTaxAnalysis(final MoneyWiseTaxSource pTaxSource,
190 final MetisPreferenceManager pPrefMgr,
191 final MoneyWiseUKTaxYear pTaxYear) {
192
193 theTaxYear = pTaxYear;
194 theTaxSource = pTaxSource;
195
196
197 theTaxBuckets = new ArrayList<>();
198
199
200 final MoneyWiseUKTaxPreferences myPreferences = pPrefMgr.getPreferenceSet(MoneyWiseUKTaxPreferences.class);
201 final OceanusDate myBirthday = myPreferences.getDateValue(MoneyWiseUKTaxPreferenceKey.BIRTHDATE);
202 theTaxConfig = new MoneyWiseUKTaxConfig(theTaxYear, theTaxSource, myBirthday);
203
204
205 theTaxPaid = pTaxSource.getAmountForTaxBasis(MoneyWiseTaxClass.TAXPAID);
206 theTaxableIncome = new OceanusMoney(theTaxPaid);
207 theTaxableIncome.setZero();
208 theTaxDue = new OceanusMoney(theTaxPaid);
209 theTaxDue.setZero();
210 theTaxProfit = new OceanusMoney(theTaxPaid);
211 theTaxProfit.setZero();
212 }
213
214 @Override
215 public MoneyWiseUKTaxYear getTaxYear() {
216 return theTaxYear;
217 }
218
219
220
221
222
223
224 public MoneyWiseUKTaxConfig getTaxConfig() {
225 return theTaxConfig;
226 }
227
228 @Override
229 public Iterator<MoneyWiseTaxDueBucket> taxDueIterator() {
230 return theTaxBuckets.iterator();
231 }
232
233
234
235
236
237
238 private List<MoneyWiseTaxDueBucket> getTaxBuckets() {
239 return theTaxBuckets;
240 }
241
242 @Override
243 public OceanusMoney getTaxableIncome() {
244 return theTaxableIncome;
245 }
246
247 @Override
248 public OceanusMoney getTaxDue() {
249 return theTaxDue;
250 }
251
252 @Override
253 public OceanusMoney getTaxPaid() {
254 return theTaxPaid;
255 }
256
257 @Override
258 public OceanusMoney getTaxProfit() {
259 return theTaxProfit;
260 }
261
262
263
264
265 protected void calculateTaxDue() {
266
267 theTaxableIncome.setZero();
268 theTaxDue.setZero();
269
270
271 final Iterator<MoneyWiseTaxDueBucket> myIterator = theTaxBuckets.iterator();
272 while (myIterator.hasNext()) {
273 final MoneyWiseTaxDueBucket myBucket = myIterator.next();
274
275
276 theTaxableIncome.addAmount(myBucket.getTaxableIncome());
277 theTaxDue.addAmount(myBucket.getTaxDue());
278
279
280 if (myBucket instanceof MoneyWiseUKSlicedTaxDueBucket mySliced) {
281
282 theTaxDue.subtractAmount(mySliced.getTaxRelief());
283 }
284 }
285 }
286
287
288
289
290 protected void calculateTaxProfit() {
291
292 theTaxProfit.setZero();
293 theTaxProfit.addAmount(theTaxDue);
294 theTaxProfit.addAmount(theTaxPaid);
295 }
296
297
298
299
300
301
302
303 protected void processItem(final MoneyWiseTaxClass pBasis,
304 final MoneyWiseUKIncomeScheme pScheme) {
305
306 final OceanusMoney myAmount = theTaxSource.getAmountForTaxBasis(pBasis);
307
308
309 if (myAmount.isZero()
310 || !myAmount.isPositive()) {
311 return;
312 }
313
314
315 final MoneyWiseUKTaxConfig myConfig = theTaxConfig.cloneIt();
316
317
318 final MoneyWiseTaxBandSet myBands = pScheme.allocateToTaxBands(theTaxConfig, pBasis, myAmount);
319
320
321 MoneyWiseTaxDueBucket myBucket = new MoneyWiseTaxDueBucket(pBasis, myBands, myConfig);
322
323
324 if (MoneyWiseTaxClass.CHARGEABLEGAINS.equals(pBasis)
325 && myBands.multipleBands()) {
326
327 myBucket = new MoneyWiseUKSlicedTaxDueBucket(myBucket, theTaxSource);
328 }
329
330
331 theTaxBuckets.add(myBucket);
332 }
333
334 @Override
335 public MetisFieldSet<MoneyWiseUKTaxAnalysis> getDataFieldSet() {
336 return FIELD_DEFS;
337 }
338
339 @Override
340 public String formatObject(final OceanusDataFormatter pFormatter) {
341 return FIELD_DEFS.getName();
342 }
343 }