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