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.atlas.reports;
18  
19  import io.github.tonywasher.joceanus.oceanus.date.OceanusDateRange;
20  import io.github.tonywasher.joceanus.oceanus.format.OceanusDataFormatter;
21  import io.github.tonywasher.joceanus.metis.data.MetisDataDifference;
22  import io.github.tonywasher.joceanus.metis.report.MetisReportBase;
23  import io.github.tonywasher.joceanus.metis.report.MetisReportHTMLBuilder;
24  import io.github.tonywasher.joceanus.metis.report.MetisReportHTMLBuilder.MetisHTMLTable;
25  import io.github.tonywasher.joceanus.metis.report.MetisReportManager;
26  import io.github.tonywasher.joceanus.metis.report.MetisReportReferenceManager.DelayedTable;
27  import io.github.tonywasher.joceanus.moneywise.atlas.data.analysis.buckets.MoneyWiseXAnalysis;
28  import io.github.tonywasher.joceanus.moneywise.atlas.data.analysis.buckets.MoneyWiseXAnalysisTransCategoryBucket;
29  import io.github.tonywasher.joceanus.moneywise.atlas.data.analysis.buckets.MoneyWiseXAnalysisTransCategoryBucket.MoneyWiseXAnalysisTransCategoryBucketList;
30  import io.github.tonywasher.joceanus.moneywise.atlas.data.analysis.values.MoneyWiseXAnalysisTransAttr;
31  import io.github.tonywasher.joceanus.moneywise.atlas.data.analysis.values.MoneyWiseXAnalysisTransValues;
32  import io.github.tonywasher.joceanus.moneywise.atlas.views.MoneyWiseXAnalysisFilter;
33  import io.github.tonywasher.joceanus.moneywise.atlas.views.MoneyWiseXAnalysisFilter.MoneyWiseXAnalysisTransCategoryFilter;
34  import io.github.tonywasher.joceanus.moneywise.data.basic.MoneyWiseTransCategory;
35  import io.github.tonywasher.joceanus.moneywise.data.statics.MoneyWiseTransCategoryClass;
36  import org.w3c.dom.Document;
37  import org.w3c.dom.Element;
38  
39  import java.util.Iterator;
40  
41  /**
42   * Income/Expense report builder.
43   */
44  public class MoneyWiseXReportIncomeExpense
45          extends MetisReportBase<MoneyWiseXAnalysis, MoneyWiseXAnalysisFilter<?, ?>> {
46      /**
47       * The Title text.
48       */
49      private static final String TEXT_TITLE = MoneyWiseXReportResource.INCEXP_TITLE.getValue();
50  
51      /**
52       * HTML builder.
53       */
54      private final MetisReportHTMLBuilder theBuilder;
55  
56      /**
57       * The Formatter.
58       */
59      private final OceanusDataFormatter theFormatter;
60  
61      /**
62       * Data Analysis.
63       */
64      private MoneyWiseXAnalysis theAnalysis;
65  
66      /**
67       * Constructor.
68       *
69       * @param pManager the Report Manager
70       */
71      MoneyWiseXReportIncomeExpense(final MetisReportManager<MoneyWiseXAnalysisFilter<?, ?>> pManager) {
72          /* Access underlying utilities */
73          theBuilder = pManager.getBuilder();
74          theFormatter = theBuilder.getDataFormatter();
75      }
76  
77      @Override
78      public Document createReport(final MoneyWiseXAnalysis pAnalysis) {
79          /* Access the bucket list */
80          theAnalysis = pAnalysis;
81          final MoneyWiseXAnalysisTransCategoryBucketList myCategories = theAnalysis.getTransCategories();
82          final OceanusDateRange myRange = theAnalysis.getDateRange();
83  
84          /* Obtain the totals bucket */
85          final MoneyWiseXAnalysisTransCategoryBucket myTotals = myCategories.getTotals();
86  
87          /* Start the report */
88          final Element myBody = theBuilder.startReport();
89          theBuilder.makeTitle(myBody, TEXT_TITLE, theFormatter.formatObject(myRange));
90  
91          /* Initialise the table */
92          final MetisHTMLTable myTable = theBuilder.startTable(myBody);
93          theBuilder.startHdrRow(myTable);
94          theBuilder.makeTitleCell(myTable);
95          theBuilder.makeTitleCell(myTable, MoneyWiseXReportBuilder.TEXT_INCOME);
96          theBuilder.makeTitleCell(myTable, MoneyWiseXReportBuilder.TEXT_EXPENSE);
97          theBuilder.makeTitleCell(myTable, MoneyWiseXReportBuilder.TEXT_PROFIT);
98  
99          /* Loop through the SubTotal Buckets */
100         final Iterator<MoneyWiseXAnalysisTransCategoryBucket> myIterator = myCategories.iterator();
101         while (myIterator.hasNext()) {
102             final MoneyWiseXAnalysisTransCategoryBucket myBucket = myIterator.next();
103 
104             /* Only process subTotal items */
105             final MoneyWiseTransCategoryClass myClass = myBucket.getTransactionCategoryType().getCategoryClass();
106             if (!myClass.isSubTotal()) {
107                 continue;
108             }
109 
110             /* Access bucket name */
111             final String myName = myBucket.getName();
112 
113             /* Access values */
114             final MoneyWiseXAnalysisTransValues myValues = myBucket.getValues();
115 
116             /* Format the Category Total */
117             theBuilder.startRow(myTable);
118             theBuilder.makeDelayLinkCell(myTable, myName);
119             theBuilder.makeTotalCell(myTable, myValues.getMoneyValue(MoneyWiseXAnalysisTransAttr.INCOME));
120             theBuilder.makeTotalCell(myTable, myValues.getMoneyValue(MoneyWiseXAnalysisTransAttr.EXPENSE));
121             theBuilder.makeTotalCell(myTable, myValues.getMoneyValue(MoneyWiseXAnalysisTransAttr.PROFIT));
122 
123             /* Note the delayed subTable */
124             setDelayedTable(myName, myTable, myBucket);
125         }
126 
127         /* Access values */
128         final MoneyWiseXAnalysisTransValues myValues = myTotals.getValues();
129 
130         /* Format the total */
131         theBuilder.startTotalRow(myTable);
132         theBuilder.makeTitleCell(myTable, MoneyWiseXReportBuilder.TEXT_TOTAL);
133         theBuilder.makeTotalCell(myTable, myValues.getMoneyValue(MoneyWiseXAnalysisTransAttr.INCOME));
134         theBuilder.makeTotalCell(myTable, myValues.getMoneyValue(MoneyWiseXAnalysisTransAttr.EXPENSE));
135         theBuilder.makeTotalCell(myTable, myValues.getMoneyValue(MoneyWiseXAnalysisTransAttr.PROFIT));
136 
137         /* Return the document */
138         return theBuilder.getDocument();
139     }
140 
141     @Override
142     public MetisHTMLTable createDelayedTable(final DelayedTable pTable) {
143         /* Access the source */
144         final Object mySource = pTable.getSource();
145         if (mySource instanceof MoneyWiseXAnalysisTransCategoryBucket mySourceBucket) {
146             return createDelayedCategory(pTable.getParent(), mySourceBucket);
147         }
148 
149         /* Return the null table */
150         return null;
151     }
152 
153     /**
154      * Create a delayed category table.
155      *
156      * @param pParent the parent table
157      * @param pSource the source bucket
158      * @return the new document fragment
159      */
160     protected MetisHTMLTable createDelayedCategory(final MetisHTMLTable pParent,
161                                                    final MoneyWiseXAnalysisTransCategoryBucket pSource) {
162         /* Access the category */
163         final MoneyWiseXAnalysisTransCategoryBucketList myCategories = theAnalysis.getTransCategories();
164         final MoneyWiseTransCategory myCategory = pSource.getTransactionCategory();
165 
166         /* Create an embedded table */
167         final MetisHTMLTable myTable = theBuilder.createEmbeddedTable(pParent);
168 
169         /* Loop through the Category Buckets */
170         final Iterator<MoneyWiseXAnalysisTransCategoryBucket> myIterator = myCategories.iterator();
171         while (myIterator.hasNext()) {
172             final MoneyWiseXAnalysisTransCategoryBucket myBucket = myIterator.next();
173 
174             /* Skip record if incorrect category */
175             final MoneyWiseTransCategory myCurr = myBucket.getTransactionCategory();
176             if (!MetisDataDifference.isEqual(myCurr.getParentCategory(), myCategory)) {
177                 continue;
178             }
179 
180             /* Access bucket name */
181             final String myName = myBucket.getName();
182 
183             /* Access values */
184             final MoneyWiseXAnalysisTransValues myValues = myBucket.getValues();
185 
186             /* Create the SubCategory row */
187             theBuilder.startRow(myTable);
188             theBuilder.makeFilterLinkCell(myTable, myName, myCurr.getSubCategory());
189             theBuilder.makeTotalCell(myTable, myValues.getMoneyValue(MoneyWiseXAnalysisTransAttr.INCOME));
190             theBuilder.makeTotalCell(myTable, myValues.getMoneyValue(MoneyWiseXAnalysisTransAttr.EXPENSE));
191             theBuilder.makeTotalCell(myTable, myValues.getMoneyValue(MoneyWiseXAnalysisTransAttr.PROFIT));
192 
193             /* Record the selection */
194             setFilterForId(myName, myBucket);
195         }
196 
197         /* Return the table */
198         return myTable;
199     }
200 
201     @Override
202     public MoneyWiseXAnalysisTransCategoryFilter processFilter(final Object pSource) {
203         /* If this is an EventCategoryBucket */
204         if (pSource instanceof MoneyWiseXAnalysisTransCategoryBucket mySource) {
205             /* Create the new filter */
206             return new MoneyWiseXAnalysisTransCategoryFilter(mySource);
207         }
208         return null;
209     }
210 }