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.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.oceanus.decimal.OceanusMoney;
24  import io.github.tonywasher.joceanus.oceanus.decimal.OceanusRate;
25  
26  import java.util.ArrayList;
27  import java.util.Iterator;
28  import java.util.List;
29  
30  /**
31   * Interest Tax Scheme.
32   */
33  public abstract class MoneyWiseUKInterestScheme
34          extends MoneyWiseUKIncomeScheme {
35      /*
36       * Local Report fields.
37       */
38      static {
39          MetisFieldSet.newFieldSet(MoneyWiseUKInterestScheme.class);
40      }
41  
42      /**
43       * Constructor.
44       */
45      protected MoneyWiseUKInterestScheme() {
46      }
47  
48      /**
49       * Obtain theTaxCredit rate for interest.
50       *
51       * @param pTaxYear the taxYear
52       * @return the taxCredit rate
53       */
54      protected abstract OceanusRate getTaxCreditRate(MoneyWiseUKTaxYear pTaxYear);
55  
56      @Override
57      protected OceanusMoney adjustAllowances(final MoneyWiseUKTaxConfig pConfig,
58                                              final OceanusMoney pAmount) {
59          /* Adjust against the basic allowance */
60          final OceanusMoney myRemaining = super.adjustAllowances(pConfig, pAmount);
61  
62          /* If we have any interest left */
63          if (myRemaining.isNonZero()) {
64              /* Adjust the savings allowance noting that it still counts against the taxBand */
65              final OceanusMoney myInterest = adjustForAllowance(pConfig.getSavingsAllowance(), myRemaining);
66  
67              /* Adjust any loSavings band noting that it still counts against the taxBand */
68              adjustForAllowance(pConfig.getLoSavingsBand().getAmount(), myInterest);
69          }
70  
71          /* Return unallocated income */
72          return myRemaining;
73      }
74  
75      @Override
76      protected OceanusMoney getAmountInAllowance(final MoneyWiseUKTaxConfig pConfig,
77                                                  final OceanusMoney pAmount) {
78          /* Obtain the amount covered by the basic allowance */
79          OceanusMoney myAmount = super.getAmountInAllowance(pConfig, pAmount);
80  
81          /* If we have income left over */
82          if (myAmount.compareTo(pAmount) < 0) {
83              /* Calculate remaining amount */
84              final OceanusMoney myRemaining = new OceanusMoney(pAmount);
85              myRemaining.subtractAmount(myAmount);
86  
87              /* Calculate the amount covered by savings allowance */
88              final OceanusMoney myXtra = getAmountInBand(pConfig.getSavingsAllowance(), myRemaining);
89  
90              /* Determine the total amount covered by the allowance */
91              myAmount = new OceanusMoney(myAmount);
92              myAmount.addAmount(myXtra);
93          }
94  
95          /* return the amount */
96          return myAmount;
97      }
98  
99      /**
100      * Obtain the base rate.
101      *
102      * @return the base rate
103      */
104     protected OceanusRate getBaseRate() {
105         return null;
106     }
107 
108     @Override
109     protected Iterator<MoneyWiseTaxBand> taxBandIterator(final MoneyWiseUKTaxConfig pConfig,
110                                                          final MoneyWiseTaxClass pBasis) {
111         /* Obtain the loSavingsBand and the basicRate */
112         final MoneyWiseTaxBand myLoBand = pConfig.getLoSavingsBand();
113         final OceanusMoney myLoAmount = myLoBand.getAmount();
114         OceanusRate myRate = getBaseRate();
115 
116         /* Create a new List */
117         final List<MoneyWiseTaxBand> myList = new ArrayList<>();
118 
119         /* Access underlying iterator and obtain first band */
120         final Iterator<MoneyWiseTaxBand> myIterator = super.taxBandIterator(pConfig, pBasis);
121         MoneyWiseTaxBand myBasicBand = myIterator.next();
122         OceanusMoney myAmount = myBasicBand.getAmount();
123 
124         /* If we are a LoBase instance */
125         if (this instanceof MoneyWiseUKInterestLoBaseRateScheme) {
126             /* Add the first band as is */
127             myList.add(myBasicBand);
128 
129             /* Access the true basic band */
130             myBasicBand = myIterator.next();
131             myAmount = myBasicBand.getAmount();
132 
133             /* Add low band if required */
134         } else if (myLoAmount.isNonZero()) {
135             myList.add(myLoBand);
136             myAmount = new OceanusMoney(myAmount);
137             myAmount.subtract(myLoAmount);
138         }
139 
140         /* Add the basic band */
141         if (myRate == null) {
142             myRate = myBasicBand.getRate();
143         }
144         myList.add(new MoneyWiseTaxBand(myAmount, myRate));
145 
146         /* Loop through remaining tax bands */
147         while (myIterator.hasNext()) {
148             final MoneyWiseTaxBand myBand = myIterator.next();
149             myList.add(myBand);
150         }
151 
152         /* Return the iterator */
153         return myList.iterator();
154     }
155 
156     /**
157      * As Income Scheme.
158      */
159     public static class MoneyWiseUKInterestAsIncomeScheme
160             extends MoneyWiseUKInterestScheme {
161         /**
162          * Local Report fields.
163          */
164         private static final MetisFieldSet<MoneyWiseUKInterestAsIncomeScheme> FIELD_DEFS = MetisFieldSet.newFieldSet(MoneyWiseUKInterestAsIncomeScheme.class);
165 
166         /**
167          * Default constructor.
168          */
169         MoneyWiseUKInterestAsIncomeScheme() {
170             /* NoOp */
171         }
172 
173         @Override
174         protected OceanusRate getTaxCreditRate(final MoneyWiseUKTaxYear pTaxYear) {
175             return pTaxYear.getTaxBands().getBasicTaxRate();
176         }
177 
178         @Override
179         public MetisFieldSet<MoneyWiseUKInterestAsIncomeScheme> getDataFieldSet() {
180             return FIELD_DEFS;
181         }
182     }
183 
184     /**
185      * Base Rate Scheme.
186      */
187     public static class MoneyWiseUKInterestBaseRateScheme
188             extends MoneyWiseUKInterestScheme {
189         /**
190          * Local Report fields.
191          */
192         private static final MetisFieldSet<MoneyWiseUKInterestBaseRateScheme> FIELD_DEFS = MetisFieldSet.newFieldSet(MoneyWiseUKInterestBaseRateScheme.class);
193 
194         /*
195          * Declare Fields.
196          */
197         static {
198             FIELD_DEFS.declareLocalField(MoneyWiseTaxResource.SCHEME_BASE_RATE, MoneyWiseUKInterestBaseRateScheme::getBaseRate);
199         }
200 
201         /**
202          * The Base Rate.
203          */
204         private final OceanusRate theBaseRate;
205 
206         /**
207          * Constructor.
208          *
209          * @param pRate the base rate
210          */
211         protected MoneyWiseUKInterestBaseRateScheme(final OceanusRate pRate) {
212             theBaseRate = pRate;
213         }
214 
215         @Override
216         protected OceanusRate getBaseRate() {
217             return theBaseRate;
218         }
219 
220         @Override
221         protected OceanusRate getTaxCreditRate(final MoneyWiseUKTaxYear pTaxYear) {
222             return theBaseRate;
223         }
224 
225         @Override
226         public MetisFieldSet<? extends MoneyWiseUKInterestBaseRateScheme> getDataFieldSet() {
227             return FIELD_DEFS;
228         }
229     }
230 
231     /**
232      * LoBase Rate Scheme.
233      */
234     public static class MoneyWiseUKInterestLoBaseRateScheme
235             extends MoneyWiseUKInterestBaseRateScheme {
236         /**
237          * Local Report fields.
238          */
239         private static final MetisFieldSet<MoneyWiseUKInterestLoBaseRateScheme> FIELD_DEFS = MetisFieldSet.newFieldSet(MoneyWiseUKInterestLoBaseRateScheme.class);
240 
241         /**
242          * Constructor.
243          *
244          * @param pRate the base rate
245          */
246         protected MoneyWiseUKInterestLoBaseRateScheme(final OceanusRate pRate) {
247             super(pRate);
248         }
249 
250         @Override
251         public MetisFieldSet<MoneyWiseUKInterestLoBaseRateScheme> getDataFieldSet() {
252             return FIELD_DEFS;
253         }
254     }
255 }