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.oceanus.logger.OceanusLogManager;
22  import io.github.tonywasher.joceanus.oceanus.logger.OceanusLogger;
23  import io.github.tonywasher.joceanus.metis.report.MetisReportBase;
24  import io.github.tonywasher.joceanus.metis.report.MetisReportHTMLBuilder;
25  import io.github.tonywasher.joceanus.metis.report.MetisReportHTMLBuilder.MetisHTMLTable;
26  import io.github.tonywasher.joceanus.metis.report.MetisReportManager;
27  import io.github.tonywasher.joceanus.metis.report.MetisReportReferenceManager.DelayedTable;
28  import io.github.tonywasher.joceanus.moneywise.atlas.data.analysis.buckets.MoneyWiseXAnalysis;
29  import io.github.tonywasher.joceanus.moneywise.atlas.data.analysis.buckets.MoneyWiseXAnalysisPortfolioBucket;
30  import io.github.tonywasher.joceanus.moneywise.atlas.data.analysis.buckets.MoneyWiseXAnalysisPortfolioBucket.MoneyWiseXAnalysisPortfolioBucketList;
31  import io.github.tonywasher.joceanus.moneywise.atlas.data.analysis.buckets.MoneyWiseXAnalysisSecurityBucket;
32  import io.github.tonywasher.joceanus.moneywise.atlas.data.analysis.buckets.MoneyWiseXAnalysisSecurityBucket.MoneyWiseXAnalysisSecurityBucketList;
33  import io.github.tonywasher.joceanus.moneywise.atlas.data.analysis.values.MoneyWiseXAnalysisSecurityAttr;
34  import io.github.tonywasher.joceanus.moneywise.atlas.data.analysis.values.MoneyWiseXAnalysisSecurityValues;
35  import io.github.tonywasher.joceanus.moneywise.atlas.data.analysis.values.MoneyWiseXAnalysisValuesResource;
36  import io.github.tonywasher.joceanus.moneywise.atlas.views.MoneyWiseXAnalysisFilter;
37  import io.github.tonywasher.joceanus.moneywise.atlas.views.MoneyWiseXAnalysisFilter.MoneyWiseXAnalysisSecurityFilter;
38  import org.w3c.dom.Document;
39  import org.w3c.dom.Element;
40  
41  import java.util.Iterator;
42  
43  /**
44   * MarketGrowth report builder.
45   */
46  public class MoneyWiseXReportMarketGrowth
47          extends MetisReportBase<MoneyWiseXAnalysis, MoneyWiseXAnalysisFilter<?, ?>> {
48      /**
49       * Logger.
50       */
51      private static final OceanusLogger LOGGER = OceanusLogManager.getLogger(MoneyWiseXReportMarketGrowth.class);
52  
53      /**
54       * The Title text.
55       */
56      private static final String TEXT_TITLE = MoneyWiseXReportResource.MARKETGROWTH_TITLE.getValue();
57  
58      /**
59       * The Value text.
60       */
61      private static final String TEXT_VALUE = MoneyWiseXAnalysisValuesResource.ACCOUNTATTR_VALUATION.getValue();
62  
63      /**
64       * The Adjustment text.
65       */
66      private static final String TEXT_GAINS = MoneyWiseXAnalysisValuesResource.SECURITYATTR_REALISEDGAINS.getValue();
67  
68      /**
69       * The Base text.
70       */
71      private static final String TEXT_BASE = MoneyWiseXReportResource.MARKETGROWTH_BASE.getValue();
72  
73      /**
74       * The Profit text.
75       */
76      private static final String TEXT_PROFIT = MoneyWiseXAnalysisValuesResource.SECURITYATTR_PROFIT.getValue();
77  
78      /**
79       * HTML builder.
80       */
81      private final MetisReportHTMLBuilder theBuilder;
82  
83      /**
84       * The Formatter.
85       */
86      private final OceanusDataFormatter theFormatter;
87  
88      /**
89       * Do we have foreign assets?
90       */
91      private boolean hasForeign;
92  
93      /**
94       * Constructor.
95       *
96       * @param pManager the Report Manager
97       */
98      MoneyWiseXReportMarketGrowth(final MetisReportManager<MoneyWiseXAnalysisFilter<?, ?>> pManager) {
99          /* Access underlying utilities */
100         theBuilder = pManager.getBuilder();
101         theFormatter = theBuilder.getDataFormatter();
102     }
103 
104     @Override
105     public Document createReport(final MoneyWiseXAnalysis pAnalysis) {
106         /* Access the bucket lists */
107         final MoneyWiseXAnalysisPortfolioBucketList myPortfolios = pAnalysis.getPortfolios();
108         hasForeign = myPortfolios.haveForeignCurrency();
109 
110         /* Access the totals */
111         final MoneyWiseXAnalysisPortfolioBucket myTotals = myPortfolios.getTotals();
112         final OceanusDateRange myRange = pAnalysis.getDateRange();
113 
114         /* Start the report */
115         final Element myBody = theBuilder.startReport();
116         theBuilder.makeTitle(myBody, TEXT_TITLE, theFormatter.formatObject(myRange));
117 
118         /* Initialise the table */
119         final MetisHTMLTable myTable = theBuilder.startTable(myBody);
120         theBuilder.startHdrRow(myTable);
121         theBuilder.makeTitleCell(myTable);
122         theBuilder.makeTitleCell(myTable, TEXT_VALUE);
123         theBuilder.makeTitleCell(myTable, TEXT_BASE);
124         //theBuilder.makeTitleCell(myTable, TEXT_INVEST);
125         //theBuilder.makeTitleCell(myTable, TEXT_ADJUST);
126         theBuilder.makeTitleCell(myTable, TEXT_GAINS);
127         //theBuilder.makeTitleCell(myTable, TEXT_GROWTH);
128         //if (hasForeign) {
129         //    theBuilder.makeTitleCell(myTable, TEXT_CURRENCY);
130         //}
131         theBuilder.makeTitleCell(myTable, TEXT_PROFIT);
132 
133         /* Loop through the Portfolio Buckets */
134         final Iterator<MoneyWiseXAnalysisPortfolioBucket> myIterator = myPortfolios.iterator();
135         while (myIterator.hasNext()) {
136             final MoneyWiseXAnalysisPortfolioBucket myBucket = myIterator.next();
137 
138             /* Access bucket name */
139             final String myName = myBucket.getName();
140 
141             /* Access values */
142             final MoneyWiseXAnalysisSecurityValues myValues = myBucket.getValues();
143 
144             /* Only declare the entry if we have securities */
145             if (myBucket.securityIterator().hasNext()) {
146                 /* Format the Asset */
147                 theBuilder.startRow(myTable);
148                 theBuilder.makeDelayLinkCell(myTable, myName);
149                 theBuilder.makeTotalCell(myTable, myBucket.getNonCashValue(false));
150                 theBuilder.makeTotalCell(myTable, myBucket.getNonCashValue(true));
151                 //theBuilder.makeTotalCell(myTable, myValues.getMoneyValue(MoneyWiseXAnalysisSecurityAttr.INVESTED));
152                 theBuilder.makeTotalCell(myTable, myValues.getMoneyValue(MoneyWiseXAnalysisSecurityAttr.GAINSADJUST));
153                 theBuilder.makeTotalCell(myTable, myValues.getMoneyValue(MoneyWiseXAnalysisSecurityAttr.REALISEDGAINS));
154                 //theBuilder.makeTotalCell(myTable, myValues.getMoneyValue(MoneyWiseXAnalysisSecurityAttr.MARKETGROWTH));
155                 //if (hasForeign) {
156                 //    theBuilder.makeTotalCell(myTable, myValues.getMoneyValue(MoneyWiseXAnalysisSecurityAttr.CURRENCYFLUCT));
157                 //}
158                 theBuilder.makeTotalCell(myTable, myValues.getMoneyValue(MoneyWiseXAnalysisSecurityAttr.MARKETPROFIT));
159                 //checkPortfolioGrowth(myBucket);
160 
161                 /* Note the delayed subTable */
162                 setDelayedTable(myName, myTable, myBucket);
163             }
164         }
165 
166         /* Access values */
167         final MoneyWiseXAnalysisSecurityValues myValues = myTotals.getValues();
168 
169         /* Create the total row */
170         theBuilder.startTotalRow(myTable);
171         theBuilder.makeTitleCell(myTable, MoneyWiseXReportBuilder.TEXT_TOTAL);
172         theBuilder.makeTotalCell(myTable, myTotals.getNonCashValue(false));
173         theBuilder.makeTotalCell(myTable, myTotals.getNonCashValue(true));
174         //theBuilder.makeTotalCell(myTable, myValues.getMoneyValue(MoneyWiseXAnalysisSecurityAttr.INVESTED));
175         theBuilder.makeTotalCell(myTable, myValues.getMoneyValue(MoneyWiseXAnalysisSecurityAttr.GAINSADJUST));
176         theBuilder.makeTotalCell(myTable, myValues.getMoneyValue(MoneyWiseXAnalysisSecurityAttr.REALISEDGAINS));
177         //theBuilder.makeTotalCell(myTable, myValues.getMoneyValue(MoneyWiseXAnalysisSecurityAttr.MARKETGROWTH));
178         //if (hasForeign) {
179         //    theBuilder.makeTotalCell(myTable, myValues.getMoneyValue(MoneyWiseXAnalysisSecurityAttr.CURRENCYFLUCT));
180         //}
181         theBuilder.makeTotalCell(myTable, myValues.getMoneyValue(MoneyWiseXAnalysisSecurityAttr.MARKETPROFIT));
182         //checkPortfolioGrowth(myTotals);
183 
184         /* Return the document */
185         return theBuilder.getDocument();
186     }
187 
188     @Override
189     public MetisHTMLTable createDelayedTable(final DelayedTable pTable) {
190         /* Access the source */
191         final Object mySource = pTable.getSource();
192         if (mySource instanceof MoneyWiseXAnalysisPortfolioBucket mySourceBucket) {
193             return createDelayedPortfolio(pTable.getParent(), mySourceBucket);
194         }
195 
196         /* Return the null table */
197         return null;
198     }
199 
200     /**
201      * Create a delayed portfolio table.
202      *
203      * @param pParent the parent table
204      * @param pSource the source bucket
205      * @return the new document fragment
206      */
207     private MetisHTMLTable createDelayedPortfolio(final MetisHTMLTable pParent,
208                                                   final MoneyWiseXAnalysisPortfolioBucket pSource) {
209         /* Access the securities */
210         final MoneyWiseXAnalysisSecurityBucketList mySecurities = pSource.getSecurities();
211 
212         /* Create a new table */
213         final MetisHTMLTable myTable = theBuilder.createEmbeddedTable(pParent);
214 
215         /* Loop through the Security Buckets */
216         final Iterator<MoneyWiseXAnalysisSecurityBucket> myIterator = mySecurities.iterator();
217         while (myIterator.hasNext()) {
218             final MoneyWiseXAnalysisSecurityBucket myBucket = myIterator.next();
219 
220             /* Access bucket name */
221             final String myName = myBucket.getSecurityName();
222             String myFullName = myBucket.getDecoratedName();
223             myFullName = myFullName.replace(':', '-');
224 
225             /* Access values */
226             final MoneyWiseXAnalysisSecurityValues myValues = myBucket.getValues();
227             final MoneyWiseXAnalysisSecurityValues myBaseValues = myBucket.getBaseValues();
228 
229             /* Create the detail row */
230             theBuilder.startRow(myTable);
231             theBuilder.makeFilterLinkCell(myTable, myFullName, myName);
232             theBuilder.makeValueCell(myTable, myValues.getMoneyValue(MoneyWiseXAnalysisSecurityAttr.VALUATION));
233             theBuilder.makeValueCell(myTable, myBaseValues.getMoneyValue(MoneyWiseXAnalysisSecurityAttr.VALUATION));
234             //theBuilder.makeValueCell(myTable, myValues.getMoneyValue(MoneyWiseXAnalysisSecurityAttr.INVESTED));
235             theBuilder.makeValueCell(myTable, myValues.getMoneyValue(MoneyWiseXAnalysisSecurityAttr.GAINSADJUST));
236             theBuilder.makeValueCell(myTable, myValues.getMoneyValue(MoneyWiseXAnalysisSecurityAttr.REALISEDGAINS));
237             //theBuilder.makeValueCell(myTable, myValues.getMoneyValue(MoneyWiseXAnalysisSecurityAttr.MARKETGROWTH));
238             //if (hasForeign) {
239             //    theBuilder.makeValueCell(myTable, myValues.getMoneyValue(MoneyWiseXAnalysisSecurityAttr.CURRENCYFLUCT));
240             //}
241             theBuilder.makeValueCell(myTable, myValues.getMoneyValue(MoneyWiseXAnalysisSecurityAttr.MARKETPROFIT));
242             //checkSecurityGrowth(myBucket);
243 
244             /* Record the filter */
245             setFilterForId(myFullName, myBucket);
246         }
247 
248         /* Return the table */
249         return myTable;
250     }
251 
252     ///**
253     // * Check portfolio growth calculation.
254     // * @param pBucket the portfolio bucket
255     // */
256     //private static void checkPortfolioGrowth(final MoneyWiseXAnalysisPortfolioBucket pBucket) {
257     /* Check market profit */
258     //final MoneyWiseXAnalysisSecurityValues myValues = pBucket.getValues();
259     //final TethysMoney myAdjust = myValues.getMoneyValue(MoneyWiseXAnalysisSecurityAttr.GAINSADJUST);
260     //final TethysMoney myCalcGrowth = pBucket.getNonCashValue(false);
261     //myCalcGrowth.subtractAmount(pBucket.getNonCashValue(true));
262     //myCalcGrowth.subtractAmount(myValues.getMoneyValue(MoneyWiseXAnalysisSecurityAttr.INVESTED));
263     //myCalcGrowth.addAmount(myAdjust);
264     //final TethysMoney myProfit = myValues.getMoneyValue(MoneyWiseXAnalysisSecurityAttr.MARKETPROFIT);
265     //if (!myProfit.equals(myCalcGrowth)) {
266     //    LOGGER.error("Incorrect profit calculation for security <%s> of <%s>", pBucket.getName(), myCalcGrowth);
267     //}
268 
269     /* Check market growth */
270     //myCalcGrowth.subtractAmount(myValues.getMoneyValue(MoneyWiseXAnalysisSecurityAttr.REALISEDGAINS));
271     //myCalcGrowth.subtractAmount(myAdjust);
272     //myCalcGrowth.subtractAmount(myValues.getMoneyValue(MoneyWiseXAnalysisSecurityAttr.CURRENCYFLUCT));
273     //final TethysMoney myGrowth = myValues.getMoneyValue(MoneyWiseXAnalysisSecurityAttr.MARKETGROWTH);
274     //if (!myGrowth.equals(myCalcGrowth)) {
275     //    LOGGER.error("Incorrect growth calculation for portfolio <%s> of <%s>", pBucket.getName(), myCalcGrowth);
276     //}
277     //}
278 
279     /// **
280     // * Check security portfolio profit calculation.
281     // * @param pBucket the security bucket
282     //*/
283     //private static void checkSecurityGrowth(final MoneyWiseXAnalysisSecurityBucket pBucket) {
284     /* Check market profit */
285     //final MoneyWiseXAnalysisSecurityValues myValues = pBucket.getValues();
286     //final MoneyWiseXAnalysisSecurityValues myBaseValues = pBucket.getBaseValues();
287     //final TethysMoney myAdjust = myValues.getMoneyValue(MoneyWiseXAnalysisSecurityAttr.GAINSADJUST);
288     //final TethysMoney myCalcGrowth = new TethysMoney(myValues.getMoneyValue(MoneyWiseXAnalysisSecurityAttr.VALUATION));
289     //myCalcGrowth.subtractAmount(myBaseValues.getMoneyValue(MoneyWiseXAnalysisSecurityAttr.VALUATION));
290     //myCalcGrowth.subtractAmount(myValues.getMoneyValue(MoneyWiseXAnalysisSecurityAttr.INVESTED));
291     //myCalcGrowth.addAmount(myAdjust);
292     //final TethysMoney myProfit = myValues.getMoneyValue(MoneyWiseXAnalysisSecurityAttr.MARKETPROFIT);
293     //if (!myProfit.equals(myCalcGrowth)) {
294     //    LOGGER.error("Incorrect profit calculation for security <%s> of <%s>", pBucket.getDecoratedName(), myCalcGrowth);
295     //}
296 
297     /* Check market growth */
298     //myCalcGrowth.subtractAmount(myValues.getMoneyValue(MoneyWiseXAnalysisSecurityAttr.REALISEDGAINS));
299     //myCalcGrowth.subtractAmount(myAdjust);
300     //final TethysMoney myFluct = myValues.getMoneyValue(MoneyWiseXAnalysisSecurityAttr.CURRENCYFLUCT);
301     //if (myFluct != null) {
302     //    myCalcGrowth.subtractAmount(myFluct);
303     //}
304     //final TethysMoney myGrowth = myValues.getMoneyValue(MoneyWiseXAnalysisSecurityAttr.MARKETGROWTH);
305     //if (!myGrowth.equals(myCalcGrowth)) {
306     //    LOGGER.error("Incorrect growth calculation for security <%s> of <%s>", pBucket.getDecoratedName(), myCalcGrowth);
307     //}
308     //}
309     @Override
310     public MoneyWiseXAnalysisSecurityFilter processFilter(final Object pSource) {
311         /* If this is a SecurityBucket */
312         if (pSource instanceof MoneyWiseXAnalysisSecurityBucket mySource) {
313             /* Create the new filter */
314             return new MoneyWiseXAnalysisSecurityFilter(mySource);
315         }
316         return null;
317     }
318 }