View Javadoc
1   /*
2    * MoneyWise: Finance Application
3    * Copyright 2012-2026. Tony Washer
4    *
5    * Licensed under the Apache License, Version 2.0 (the "License"); you may not
6    * use this file except in compliance with the License.  You may obtain a copy
7    * of the License at
8    *
9    *   http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13   * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
14   * License for the specific language governing permissions and limitations under
15   * the License.
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.moneywise.data.statics.MoneyWiseStaticDataType;
22  import io.github.tonywasher.joceanus.moneywise.data.statics.MoneyWiseTaxClass;
23  import io.github.tonywasher.joceanus.moneywise.tax.MoneyWiseTaxBandSet;
24  import io.github.tonywasher.joceanus.moneywise.tax.MoneyWiseTaxBandSet.MoneyWiseTaxBand;
25  import io.github.tonywasher.joceanus.moneywise.tax.MoneyWiseTaxResource;
26  import io.github.tonywasher.joceanus.moneywise.tax.MoneyWiseTaxSource;
27  import io.github.tonywasher.joceanus.moneywise.tax.uk.MoneyWiseUKTax.MoneyWiseUKBasicAllowanceCtl;
28  import io.github.tonywasher.joceanus.moneywise.tax.uk.MoneyWiseUKTax.MoneyWiseUKTaxConfigCtl;
29  import io.github.tonywasher.joceanus.moneywise.tax.uk.MoneyWiseUKTax.MoneyWiseUKTaxYearCtl;
30  import io.github.tonywasher.joceanus.oceanus.date.OceanusDate;
31  import io.github.tonywasher.joceanus.oceanus.date.OceanusDateUtils;
32  import io.github.tonywasher.joceanus.oceanus.decimal.OceanusMoney;
33  import io.github.tonywasher.joceanus.oceanus.format.OceanusDataFormatter;
34  
35  /**
36   * Tax configuration.
37   */
38  public class MoneyWiseUKTaxConfig
39          implements MetisFieldItem, MoneyWiseUKTaxConfigCtl {
40      /**
41       * Local Report fields.
42       */
43      private static final MetisFieldSet<MoneyWiseUKTaxConfig> FIELD_DEFS = MetisFieldSet.newFieldSet(MoneyWiseUKTaxConfig.class);
44  
45      /*
46       * Declare Fields.
47       */
48      static {
49          FIELD_DEFS.declareLocalField(MoneyWiseTaxResource.TAXYEAR_NAME, MoneyWiseUKTaxConfig::getTaxYear);
50          FIELD_DEFS.declareLocalField(MoneyWiseStaticDataType.TAXBASIS, MoneyWiseUKTaxConfig::getTaxSource);
51          FIELD_DEFS.declareLocalField(MoneyWiseTaxResource.TAXCONFIG_GROSS, MoneyWiseUKTaxConfig::getGrossTaxable);
52          FIELD_DEFS.declareLocalField(MoneyWiseTaxResource.TAXCONFIG_PRESAVINGS, MoneyWiseUKTaxConfig::getGrossPreSavings);
53          FIELD_DEFS.declareLocalField(MoneyWiseTaxResource.TAXCONFIG_BIRTHDAY, MoneyWiseUKTaxConfig::getBirthday);
54          FIELD_DEFS.declareLocalField(MoneyWiseTaxResource.TAXCONFIG_AGE, MoneyWiseUKTaxConfig::getClientAge);
55          FIELD_DEFS.declareLocalField(MoneyWiseTaxResource.TAXCONFIG_AGEALLOWANCE, MoneyWiseUKTaxConfig::hasAgeRelatedAllowance);
56          FIELD_DEFS.declareLocalField(MoneyWiseTaxResource.ALLOWANCE_BASIC, MoneyWiseUKTaxConfig::getAllowance);
57          FIELD_DEFS.declareLocalField(MoneyWiseTaxResource.ALLOWANCE_RENTAL, MoneyWiseUKTaxConfig::getRentalAllowance);
58          FIELD_DEFS.declareLocalField(MoneyWiseTaxResource.ALLOWANCE_SAVINGS, MoneyWiseUKTaxConfig::getSavingsAllowance);
59          FIELD_DEFS.declareLocalField(MoneyWiseTaxResource.ALLOWANCE_DIVIDEND, MoneyWiseUKTaxConfig::getDividendAllowance);
60          FIELD_DEFS.declareLocalField(MoneyWiseTaxResource.ALLOWANCE_CAPITAL, MoneyWiseUKTaxConfig::getCapitalAllowance);
61          FIELD_DEFS.declareLocalField(MoneyWiseTaxResource.TAXYEAR_BANDS, MoneyWiseUKTaxConfig::getTaxBands);
62          FIELD_DEFS.declareLocalField(MoneyWiseTaxResource.TAXBANDS_LOSAVINGS, MoneyWiseUKTaxConfig::getLoSavingsBand);
63      }
64  
65      /**
66       * TaxYear.
67       */
68      private final MoneyWiseUKTaxYearCtl theTaxYear;
69  
70      /**
71       * The taxSource.
72       */
73      private final MoneyWiseTaxSource theTaxSource;
74  
75      /**
76       * Gross Taxable Income.
77       */
78      private final OceanusMoney theGrossTaxable;
79  
80      /**
81       * Gross PreSavings.
82       */
83      private final OceanusMoney theGrossPreSavings;
84  
85      /**
86       * The client birthday.
87       */
88      private final OceanusDate theBirthday;
89  
90      /**
91       * The client age in the tax year.
92       */
93      private final Integer theClientAge;
94  
95      /**
96       * Do we have an age related allowance.
97       */
98      private boolean hasAgeRelatedAllowance;
99  
100     /**
101      * Basic Allowance.
102      */
103     private final OceanusMoney theAllowance;
104 
105     /**
106      * Rental Allowance.
107      */
108     private final OceanusMoney theRentalAllowance;
109 
110     /**
111      * Savings Allowance.
112      */
113     private final OceanusMoney theSavingsAllowance;
114 
115     /**
116      * Dividend Allowance.
117      */
118     private final OceanusMoney theDividendAllowance;
119 
120     /**
121      * Capital Allowance.
122      */
123     private final OceanusMoney theCapitalAllowance;
124 
125     /**
126      * Tax Bands.
127      */
128     private final MoneyWiseTaxBandSet theTaxBands;
129 
130     /**
131      * LoSavings Band.
132      */
133     private final MoneyWiseTaxBand theLoSavings;
134 
135     /**
136      * Constructor.
137      *
138      * @param pTaxYear   the taxYear
139      * @param pTaxSource the tax source
140      * @param pBirthday  the client birthday
141      */
142     protected MoneyWiseUKTaxConfig(final MoneyWiseUKTaxYearCtl pTaxYear,
143                                    final MoneyWiseTaxSource pTaxSource,
144                                    final OceanusDate pBirthday) {
145         /* Store details */
146         theTaxYear = pTaxYear;
147         theTaxSource = pTaxSource;
148         theBirthday = pBirthday;
149         theClientAge = OceanusDateUtils.ageOn(theBirthday, pTaxYear.getYearEnd());
150 
151         /* calculate the gross taxable income and preSavings */
152         theGrossPreSavings = determineGrossPreSavings();
153         theGrossTaxable = determineGrossTaxableIncome();
154 
155         /* Access the basic allowances */
156         final MoneyWiseUKBasicAllowanceCtl myAllowances = theTaxYear.getAllowances();
157 
158         /* Calculate the allowances */
159         theAllowance = new OceanusMoney(myAllowances.calculateBasicAllowance(this));
160         theRentalAllowance = new OceanusMoney(myAllowances.getRentalAllowance());
161         theSavingsAllowance = new OceanusMoney(myAllowances.calculateSavingsAllowance(this));
162         theDividendAllowance = new OceanusMoney(myAllowances.calculateDividendAllowance());
163         theCapitalAllowance = new OceanusMoney(myAllowances.getCapitalAllowance());
164 
165         /* Access the taxBands */
166         final MoneyWiseUKTaxBands myBands = (MoneyWiseUKTaxBands) theTaxYear.getTaxBands();
167         theTaxBands = new MoneyWiseTaxBandSet(myBands.getStandardSet());
168 
169         /* Calculate the loSavings band */
170         theLoSavings = myAllowances.calculateLoSavingsBand(this, myBands.getLoSavings());
171     }
172 
173     /**
174      * Constructor.
175      *
176      * @param pSource the source configuration
177      */
178     private MoneyWiseUKTaxConfig(final MoneyWiseUKTaxConfig pSource) {
179         /* Copy basic details */
180         theTaxYear = pSource.getTaxYear();
181         theTaxSource = pSource.getTaxSource();
182         theGrossTaxable = pSource.getGrossTaxable();
183         theGrossPreSavings = pSource.getGrossPreSavings();
184         theBirthday = pSource.getBirthday();
185         theClientAge = pSource.getClientAge();
186         hasAgeRelatedAllowance = pSource.hasAgeRelatedAllowance();
187 
188         /* Copy the allowances */
189         theAllowance = new OceanusMoney(pSource.getAllowance());
190         theRentalAllowance = new OceanusMoney(pSource.getRentalAllowance());
191         theSavingsAllowance = new OceanusMoney(pSource.getSavingsAllowance());
192         theDividendAllowance = new OceanusMoney(pSource.getDividendAllowance());
193         theCapitalAllowance = new OceanusMoney(pSource.getCapitalAllowance());
194 
195         /* Copy the taxBands */
196         theTaxBands = new MoneyWiseTaxBandSet(pSource.getTaxBands());
197         theLoSavings = new MoneyWiseTaxBand(pSource.getLoSavingsBand());
198     }
199 
200     @Override
201     public MoneyWiseUKTaxYearCtl getTaxYear() {
202         return theTaxYear;
203     }
204 
205     /**
206      * Obtain the tax bases.
207      *
208      * @return the bases
209      */
210     public MoneyWiseTaxSource getTaxSource() {
211         return theTaxSource;
212     }
213 
214     @Override
215     public OceanusMoney getGrossPreSavings() {
216         return theGrossPreSavings;
217     }
218 
219     @Override
220     public OceanusMoney getGrossTaxable() {
221         return theGrossTaxable;
222     }
223 
224     @Override
225     public OceanusDate getBirthday() {
226         return theBirthday;
227     }
228 
229     @Override
230     public Integer getClientAge() {
231         return theClientAge;
232     }
233 
234     /**
235      * Do we have an age related allowance?
236      *
237      * @return true/false
238      */
239     public boolean hasAgeRelatedAllowance() {
240         return hasAgeRelatedAllowance;
241     }
242 
243     @Override
244     public void setHasAgeRelatedAllowance(final boolean pFlag) {
245         hasAgeRelatedAllowance = pFlag;
246     }
247 
248     @Override
249     public OceanusMoney getAllowance() {
250         return theAllowance;
251     }
252 
253     /**
254      * Obtain the rental allowance.
255      *
256      * @return the rental allowance
257      */
258     public OceanusMoney getRentalAllowance() {
259         return theRentalAllowance;
260     }
261 
262     /**
263      * Obtain the savings allowance.
264      *
265      * @return the allowance
266      */
267     public OceanusMoney getSavingsAllowance() {
268         return theSavingsAllowance;
269     }
270 
271     /**
272      * Obtain the dividend allowance.
273      *
274      * @return the allowance
275      */
276     public OceanusMoney getDividendAllowance() {
277         return theDividendAllowance;
278     }
279 
280     /**
281      * Obtain the capital allowance.
282      *
283      * @return the allowance
284      */
285     public OceanusMoney getCapitalAllowance() {
286         return theCapitalAllowance;
287     }
288 
289     /**
290      * Obtain the tax bands.
291      *
292      * @return the tax bands
293      */
294     public MoneyWiseTaxBandSet getTaxBands() {
295         return theTaxBands;
296     }
297 
298     /**
299      * Obtain the low savings band.
300      *
301      * @return the low savings band
302      */
303     public MoneyWiseTaxBand getLoSavingsBand() {
304         return theLoSavings;
305     }
306 
307     @Override
308     public MetisFieldSet<MoneyWiseUKTaxConfig> getDataFieldSet() {
309         return FIELD_DEFS;
310     }
311 
312     @Override
313     public String formatObject(final OceanusDataFormatter pFormatter) {
314         return FIELD_DEFS.getName();
315     }
316 
317     @Override
318     public MoneyWiseUKTaxConfig cloneIt() {
319         return new MoneyWiseUKTaxConfig(this);
320     }
321 
322     /**
323      * Determine the gross taxable income.
324      *
325      * @return the gross taxable income
326      */
327     private OceanusMoney determineGrossTaxableIncome() {
328         /* Initialise income to preSavings */
329         final OceanusMoney myIncome = new OceanusMoney(theGrossPreSavings);
330 
331         /* Add taxed interest to income */
332         myIncome.addAmount(theTaxSource.getAmountForTaxBasis(MoneyWiseTaxClass.TAXEDINTEREST));
333 
334         /* Add unTaxed interest to income */
335         myIncome.addAmount(theTaxSource.getAmountForTaxBasis(MoneyWiseTaxClass.UNTAXEDINTEREST));
336 
337         /* Add share dividends to income */
338         myIncome.addAmount(theTaxSource.getAmountForTaxBasis(MoneyWiseTaxClass.DIVIDEND));
339 
340         /* Add unit trust dividends to income */
341         myIncome.addAmount(theTaxSource.getAmountForTaxBasis(MoneyWiseTaxClass.UNITTRUSTDIVIDEND));
342 
343         /* Add foreign dividends to income */
344         myIncome.addAmount(theTaxSource.getAmountForTaxBasis(MoneyWiseTaxClass.FOREIGNDIVIDEND));
345 
346         /* Add chargeable gains to income */
347         myIncome.addAmount(theTaxSource.getAmountForTaxBasis(MoneyWiseTaxClass.CHARGEABLEGAINS));
348 
349         /* Capital Gains does not class as taxable income */
350 
351         /* Return the gross taxable amount */
352         return myIncome;
353     }
354 
355     /**
356      * Determine the gross preSavings income.
357      *
358      * @return the gross preSavings income
359      */
360     private OceanusMoney determineGrossPreSavings() {
361         /* Access the basic allowances */
362         final MoneyWiseUKBasicAllowanceCtl myAllowances = theTaxYear.getAllowances();
363 
364         /* Initialise income to correct currency */
365         final OceanusMoney myIncome = new OceanusMoney(myAllowances.getAllowance());
366         myIncome.setZero();
367 
368         /* Add the salary to income */
369         myIncome.addAmount(theTaxSource.getAmountForTaxBasis(MoneyWiseTaxClass.SALARY));
370 
371         /* Add the other income to income */
372         myIncome.addAmount(theTaxSource.getAmountForTaxBasis(MoneyWiseTaxClass.OTHERINCOME));
373 
374         /* Add the rental to income */
375         myIncome.addAmount(theTaxSource.getAmountForTaxBasis(MoneyWiseTaxClass.RENTALINCOME));
376 
377         /* Access the room rental income */
378         final OceanusMoney myChargeable = theTaxSource.getAmountForTaxBasis(MoneyWiseTaxClass.ROOMRENTAL);
379 
380         /* If we have a chargeable element */
381         final OceanusMoney myAllowance = myAllowances.getRentalAllowance();
382         if (myChargeable.compareTo(myAllowance) > 0) {
383             /* Add the chargeable element to income */
384             myChargeable.subtractAmount(myAllowance);
385             myIncome.addAmount(myChargeable);
386         }
387 
388         /* Return the gross preSavings amount */
389         return myIncome;
390     }
391 }