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.tax.MoneyWiseMarginalReduction;
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.moneywise.tax.uk.MoneyWiseUKTax.MoneyWiseUKTaxConfigCtl;
24  import io.github.tonywasher.joceanus.oceanus.decimal.OceanusMoney;
25  import io.github.tonywasher.joceanus.oceanus.format.OceanusDataFormatter;
26  
27  import java.util.Iterator;
28  
29  /**
30   * Savings UK Tax Allowance.
31   */
32  public class MoneyWiseUKSavingsAllowance
33          extends MoneyWiseUKBasicAllowance {
34      /**
35       * Local Report fields.
36       */
37      private static final MetisFieldSet<MoneyWiseUKSavingsAllowance> FIELD_DEFS = MetisFieldSet.newFieldSet(MoneyWiseUKSavingsAllowance.class);
38  
39      /*
40       * Declare Fields.
41       */
42      static {
43          FIELD_DEFS.declareLocalField(MoneyWiseTaxResource.ALLOWANCE_SAVINGS, MoneyWiseUKSavingsAllowance::getSavingsAllowance);
44          FIELD_DEFS.declareLocalField(MoneyWiseTaxResource.ALLOWANCE_DIVIDEND, MoneyWiseUKSavingsAllowance::getDividendAllowance);
45          FIELD_DEFS.declareLocalField(MoneyWiseTaxResource.LIMIT_ADDALLOWANCE, MoneyWiseUKSavingsAllowance::getAdditionalAllowanceLimit);
46      }
47  
48      /**
49       * SavingsAllowance.
50       */
51      private final OceanusMoney theSavingsAllowance;
52  
53      /**
54       * DividendAllowance.
55       */
56      private final OceanusMoney theDividendAllowance;
57  
58      /**
59       * AdditionalAllowanceLimit.
60       */
61      private final OceanusMoney theAddAllowLimit;
62  
63      /**
64       * Constructor.
65       *
66       * @param pAllowance         the allowance
67       * @param pRentalAllowance   the rental allowance
68       * @param pCapitalAllowance  the capital allowance
69       * @param pSavingsAllowance  the savings allowance
70       * @param pDividendAllowance the dividend allowance
71       * @param pAddAllowLimit     the additional allowance limit
72       */
73      protected MoneyWiseUKSavingsAllowance(final OceanusMoney pAllowance,
74                                            final OceanusMoney pRentalAllowance,
75                                            final OceanusMoney pCapitalAllowance,
76                                            final OceanusMoney pSavingsAllowance,
77                                            final OceanusMoney pDividendAllowance,
78                                            final OceanusMoney pAddAllowLimit) {
79          super(pAllowance, pRentalAllowance, pCapitalAllowance, MoneyWiseMarginalReduction.ONEINTWO);
80          theSavingsAllowance = pSavingsAllowance;
81          theDividendAllowance = pDividendAllowance;
82          theAddAllowLimit = pAddAllowLimit;
83      }
84  
85      /**
86       * Obtain the savings allowance.
87       *
88       * @return the Allowance
89       */
90      protected OceanusMoney getSavingsAllowance() {
91          return theSavingsAllowance;
92      }
93  
94      /**
95       * Obtain the dividend allowance.
96       *
97       * @return the Allowance
98       */
99      protected OceanusMoney getDividendAllowance() {
100         return theDividendAllowance;
101     }
102 
103     /**
104      * Obtain the additional Allowance limit.
105      *
106      * @return the Limit
107      */
108     protected OceanusMoney getAdditionalAllowanceLimit() {
109         return theAddAllowLimit;
110     }
111 
112     @Override
113     public OceanusMoney calculateBasicAllowance(final MoneyWiseUKTaxConfigCtl pConfig) {
114         /* Determine Basic allowance */
115         OceanusMoney myAllowance = getAllowance();
116 
117         /* If we have additional tax possible and we are above the allowance limit */
118         final OceanusMoney myGross = pConfig.getGrossTaxable();
119         if (myGross.compareTo(theAddAllowLimit) > 0) {
120             /* Calculate and apply the reduction */
121             final OceanusMoney myReduction = getMarginalReduction().calculateReduction(myGross, theAddAllowLimit);
122             myAllowance = new OceanusMoney(myAllowance);
123             myAllowance.subtractAmount(myReduction);
124 
125             /* If we have reduced below zero */
126             if (!myAllowance.isPositive()) {
127                 /* Set the allowance to zero */
128                 myAllowance.setZero();
129             }
130         }
131 
132         /* Return the allowance */
133         return myAllowance;
134     }
135 
136     @Override
137     public OceanusMoney calculateSavingsAllowance(final MoneyWiseUKTaxConfigCtl pConfig) {
138         /* Obtain the gross taxable and allowance */
139         final OceanusMoney myGross = pConfig.getGrossTaxable();
140         final OceanusMoney myBoundary = new OceanusMoney(pConfig.getAllowance());
141 
142         /* Obtain the tax bands */
143         final MoneyWiseUKTaxBands myBands = (MoneyWiseUKTaxBands) pConfig.getTaxYear().getTaxBands();
144         final Iterator<MoneyWiseTaxBand> myIterator = myBands.getStandardSet().iterator();
145 
146         /* If we have a basic band */
147         if (myIterator.hasNext()) {
148             /* If we are only a basic taxPayer return the full allowance */
149             myBoundary.addAmount(myIterator.next().getAmount());
150             if (myBoundary.compareTo(myGross) >= 0) {
151                 return theSavingsAllowance;
152             }
153         }
154 
155         /* If we have a high band */
156         final OceanusMoney myAllowance = new OceanusMoney(theSavingsAllowance);
157         if (myIterator.hasNext()) {
158             /* If we are only a high taxPayer return the half allowance */
159             myBoundary.addAmount(myIterator.next().getAmount());
160             if (myBoundary.compareTo(myGross) >= 0) {
161                 myAllowance.divide(2);
162                 return myAllowance;
163             }
164         }
165 
166         /* No Allowance */
167         myAllowance.setZero();
168         return theSavingsAllowance;
169     }
170 
171     @Override
172     public OceanusMoney calculateDividendAllowance() {
173         return theDividendAllowance;
174     }
175 
176     @Override
177     public MetisFieldSet<MoneyWiseUKSavingsAllowance> getDataFieldSet() {
178         return FIELD_DEFS;
179     }
180 
181     @Override
182     public String formatObject(final OceanusDataFormatter pFormatter) {
183         return FIELD_DEFS.getName();
184     }
185 }