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 }