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;
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.oceanus.format.OceanusDataFormatter;
22  import io.github.tonywasher.joceanus.metis.field.MetisFieldItem;
23  import io.github.tonywasher.joceanus.metis.field.MetisFieldSet;
24  import io.github.tonywasher.joceanus.moneywise.data.statics.MoneyWiseStaticDataType;
25  import io.github.tonywasher.joceanus.moneywise.data.statics.MoneyWiseTaxClass;
26  import io.github.tonywasher.joceanus.moneywise.tax.MoneyWiseTaxBandSet.MoneyWiseTaxBand;
27  
28  import java.util.ArrayList;
29  import java.util.Iterator;
30  import java.util.List;
31  
32  /**
33   * Tax Due Bucket.
34   */
35  public class MoneyWiseTaxDueBucket
36          implements MetisFieldItem {
37      /**
38       * Local Report fields.
39       */
40      private static final MetisFieldSet<MoneyWiseTaxDueBucket> FIELD_DEFS = MetisFieldSet.newFieldSet(MoneyWiseTaxDueBucket.class);
41  
42      /*
43       * Declare Fields.
44       */
45      static {
46          FIELD_DEFS.declareLocalField(MoneyWiseStaticDataType.TAXBASIS, MoneyWiseTaxDueBucket::getTaxBasis);
47          FIELD_DEFS.declareLocalField(MoneyWiseTaxResource.TAXCONFIG_NAME, MoneyWiseTaxDueBucket::getTaxConfig);
48          FIELD_DEFS.declareLocalField(MoneyWiseTaxResource.TAXYEAR_BANDS, MoneyWiseTaxDueBucket::getTaxBands);
49          FIELD_DEFS.declareLocalField(MoneyWiseTaxResource.TAXBANDS_INCOME, MoneyWiseTaxDueBucket::getTaxableIncome);
50          FIELD_DEFS.declareLocalField(MoneyWiseTaxResource.TAXBANDS_TAXDUE, MoneyWiseTaxDueBucket::getTaxDue);
51      }
52  
53      /**
54       * Tax Basis.
55       */
56      private final MoneyWiseTaxClass theTaxBasis;
57  
58      /**
59       * Tax Configuration.
60       */
61      private final MoneyWiseTaxConfig theTaxConfig;
62  
63      /**
64       * Tax Bands.
65       */
66      private final List<MoneyWiseTaxBandBucket> theTaxBands;
67  
68      /**
69       * Taxable income.
70       */
71      private final OceanusMoney theTaxableIncome;
72  
73      /**
74       * Tax Due.
75       */
76      private final OceanusMoney theTaxDue;
77  
78      /**
79       * Constructor.
80       *
81       * @param pBasis  the tax basis
82       * @param pBands  the tax bands
83       * @param pConfig the tax configuration
84       */
85      public MoneyWiseTaxDueBucket(final MoneyWiseTaxClass pBasis,
86                                   final MoneyWiseTaxBandSet pBands,
87                                   final MoneyWiseTaxConfig pConfig) {
88          /* Store parameters */
89          theTaxBasis = pBasis;
90          theTaxConfig = pConfig;
91  
92          /* Allocate the tax band list */
93          theTaxBands = new ArrayList<>();
94  
95          /* Loop through the taxBands */
96          for (MoneyWiseTaxBand myBand : pBands) {
97              /* Ignore the band if there is zero amount */
98              if (myBand.getAmount().isNonZero()) {
99                  /* Create the tax band bucket */
100                 final MoneyWiseTaxBandBucket myBucket = new MoneyWiseTaxBandBucket(myBand);
101                 theTaxBands.add(myBucket);
102             }
103         }
104 
105         /* Copy the values */
106         theTaxableIncome = pBands.getZeroAmount();
107         theTaxDue = pBands.getZeroAmount();
108         calculateTaxDue();
109     }
110 
111     /**
112      * Constructor.
113      *
114      * @param pBase the underlying bucket
115      */
116     protected MoneyWiseTaxDueBucket(final MoneyWiseTaxDueBucket pBase) {
117         /* Store parameters */
118         theTaxBasis = pBase.getTaxBasis();
119         theTaxConfig = pBase.getTaxConfig();
120 
121         /* Allocate the tax band list */
122         theTaxBands = pBase.theTaxBands;
123 
124         /* Create the values */
125         theTaxableIncome = pBase.getTaxableIncome();
126         theTaxDue = pBase.getTaxDue();
127     }
128 
129     /**
130      * Obtain the taxBasis.
131      *
132      * @return the basis
133      */
134     public MoneyWiseTaxClass getTaxBasis() {
135         return theTaxBasis;
136     }
137 
138     /**
139      * Obtain the taxConfig.
140      *
141      * @return the configuration
142      */
143     public MoneyWiseTaxConfig getTaxConfig() {
144         return theTaxConfig;
145     }
146 
147     /**
148      * Obtain the taxBands.
149      *
150      * @return the taxBands
151      */
152     private List<MoneyWiseTaxBandBucket> getTaxBands() {
153         return theTaxBands;
154     }
155 
156     /**
157      * Obtain the taxBands iterator.
158      *
159      * @return the iterator
160      */
161     public Iterator<MoneyWiseTaxBandBucket> taxBandIterator() {
162         return theTaxBands.iterator();
163     }
164 
165     /**
166      * Obtain the taxableIncome.
167      *
168      * @return the taxableIncome
169      */
170     public OceanusMoney getTaxableIncome() {
171         return theTaxableIncome;
172     }
173 
174     /**
175      * Obtain the taxDue.
176      *
177      * @return the taxDue
178      */
179     public OceanusMoney getTaxDue() {
180         return theTaxDue;
181     }
182 
183     /**
184      * Calculate the taxDue.
185      */
186     private void calculateTaxDue() {
187         /* Loop through the tax bands */
188         final Iterator<MoneyWiseTaxBandBucket> myIterator = taxBandIterator();
189         while (myIterator.hasNext()) {
190             final MoneyWiseTaxBandBucket myBand = myIterator.next();
191 
192             /* Add the values */
193             theTaxableIncome.addAmount(myBand.getAmount());
194             theTaxDue.addAmount(myBand.getTaxDue());
195         }
196     }
197 
198     @Override
199     public MetisFieldSet<? extends MoneyWiseTaxDueBucket> getDataFieldSet() {
200         return FIELD_DEFS;
201     }
202 
203     @Override
204     public String formatObject(final OceanusDataFormatter pFormatter) {
205         return toString();
206     }
207 
208     @Override
209     public String toString() {
210         final StringBuilder myBuilder = new StringBuilder();
211         myBuilder.append(theTaxBasis);
212         myBuilder.append("==>");
213         myBuilder.append(theTaxDue);
214         return myBuilder.toString();
215     }
216 
217     /**
218      * Tax Band Bucket.
219      */
220     public static class MoneyWiseTaxBandBucket
221             implements MetisFieldItem {
222         /**
223          * Local Report fields.
224          */
225         private static final MetisFieldSet<MoneyWiseTaxBandBucket> FIELD_DEFS = MetisFieldSet.newFieldSet(MoneyWiseTaxBandBucket.class);
226 
227         /*
228          * Declare Fields.
229          */
230         static {
231             FIELD_DEFS.declareLocalField(MoneyWiseTaxResource.TAXBANDS_AMOUNT, MoneyWiseTaxBandBucket::getAmount);
232             FIELD_DEFS.declareLocalField(MoneyWiseTaxResource.TAXBANDS_RATE, MoneyWiseTaxBandBucket::getRate);
233             FIELD_DEFS.declareLocalField(MoneyWiseTaxResource.TAXBANDS_TAXDUE, MoneyWiseTaxBandBucket::getTaxDue);
234         }
235 
236         /**
237          * Amount in Band.
238          */
239         private final OceanusMoney theAmount;
240 
241         /**
242          * Rate for Band.
243          */
244         private final OceanusRate theRate;
245 
246         /**
247          * TaxDue for Band.
248          */
249         private final OceanusMoney theTaxDue;
250 
251         /**
252          * Constructor.
253          *
254          * @param pBand the tax band
255          */
256         protected MoneyWiseTaxBandBucket(final MoneyWiseTaxBand pBand) {
257             /* Store parameters */
258             theAmount = pBand.getAmount();
259             theRate = pBand.getRate();
260 
261             /* Calculate the tax due */
262             theTaxDue = theAmount.valueAtRate(theRate);
263         }
264 
265         /**
266          * Obtain the amount.
267          *
268          * @return the amount
269          */
270         public OceanusMoney getAmount() {
271             return theAmount;
272         }
273 
274         /**
275          * Obtain the rate.
276          *
277          * @return the rate
278          */
279         public OceanusRate getRate() {
280             return theRate;
281         }
282 
283         /**
284          * Obtain the taxDue.
285          *
286          * @return the taxDue
287          */
288         public OceanusMoney getTaxDue() {
289             return theTaxDue;
290         }
291 
292         @Override
293         public MetisFieldSet<MoneyWiseTaxBandBucket> getDataFieldSet() {
294             return FIELD_DEFS;
295         }
296 
297         @Override
298         public String formatObject(final OceanusDataFormatter pFormatter) {
299             return toString();
300         }
301 
302         @Override
303         public String toString() {
304             final StringBuilder myBuilder = new StringBuilder();
305             myBuilder.append(theAmount);
306             myBuilder.append('@');
307             myBuilder.append(theRate);
308             myBuilder.append("==>");
309             myBuilder.append(theTaxDue);
310             return myBuilder.toString();
311         }
312     }
313 }