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