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.oceanus.decimal.OceanusMoney;
20  import io.github.tonywasher.joceanus.oceanus.decimal.OceanusRate;
21  import io.github.tonywasher.joceanus.metis.field.MetisFieldSet;
22  import io.github.tonywasher.joceanus.moneywise.data.statics.MoneyWiseTaxClass;
23  import io.github.tonywasher.joceanus.moneywise.tax.MoneyWiseTaxBandSet.MoneyWiseTaxBand;
24  import io.github.tonywasher.joceanus.moneywise.tax.MoneyWiseTaxResource;
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          * Constructor.
168          */
169         public MoneyWiseUKInterestAsIncomeScheme() {
170         }
171 
172         @Override
173         protected OceanusRate getTaxCreditRate(final MoneyWiseUKTaxYear pTaxYear) {
174             return pTaxYear.getTaxBands().getBasicTaxRate();
175         }
176 
177         @Override
178         public MetisFieldSet<MoneyWiseUKInterestAsIncomeScheme> getDataFieldSet() {
179             return FIELD_DEFS;
180         }
181     }
182 
183     /**
184      * Base Rate Scheme.
185      */
186     public static class MoneyWiseUKInterestBaseRateScheme
187             extends MoneyWiseUKInterestScheme {
188         /**
189          * Local Report fields.
190          */
191         private static final MetisFieldSet<MoneyWiseUKInterestBaseRateScheme> FIELD_DEFS = MetisFieldSet.newFieldSet(MoneyWiseUKInterestBaseRateScheme.class);
192 
193         /*
194          * Declare Fields.
195          */
196         static {
197             FIELD_DEFS.declareLocalField(MoneyWiseTaxResource.SCHEME_BASE_RATE, MoneyWiseUKInterestBaseRateScheme::getBaseRate);
198         }
199 
200         /**
201          * The Base Rate.
202          */
203         private final OceanusRate theBaseRate;
204 
205         /**
206          * Constructor.
207          *
208          * @param pRate the base rate
209          */
210         protected MoneyWiseUKInterestBaseRateScheme(final OceanusRate pRate) {
211             theBaseRate = pRate;
212         }
213 
214         @Override
215         protected OceanusRate getBaseRate() {
216             return theBaseRate;
217         }
218 
219         @Override
220         protected OceanusRate getTaxCreditRate(final MoneyWiseUKTaxYear pTaxYear) {
221             return theBaseRate;
222         }
223 
224         @Override
225         public MetisFieldSet<? extends MoneyWiseUKInterestBaseRateScheme> getDataFieldSet() {
226             return FIELD_DEFS;
227         }
228     }
229 
230     /**
231      * LoBase Rate Scheme.
232      */
233     public static class MoneyWiseUKInterestLoBaseRateScheme
234             extends MoneyWiseUKInterestBaseRateScheme {
235         /**
236          * Local Report fields.
237          */
238         private static final MetisFieldSet<MoneyWiseUKInterestLoBaseRateScheme> FIELD_DEFS = MetisFieldSet.newFieldSet(MoneyWiseUKInterestLoBaseRateScheme.class);
239 
240         /**
241          * Constructor.
242          *
243          * @param pRate the base rate
244          */
245         protected MoneyWiseUKInterestLoBaseRateScheme(final OceanusRate pRate) {
246             super(pRate);
247         }
248 
249         @Override
250         public MetisFieldSet<MoneyWiseUKInterestLoBaseRateScheme> getDataFieldSet() {
251             return FIELD_DEFS;
252         }
253     }
254 }