1 /*
2  * Copyright 2004-2006  Ace Jones <acejones@users.sourceforge.net>
3  * Copyright 2006       Darren Gould <darren_gould@gmx.de>
4  * Copyright 2007-2010  Alvaro Soliverez <asoliverez@gmail.com>
5  * Copyright 2017-2018  Łukasz Wojniłowicz <lukasz.wojnilowicz@gmail.com>
6  * Copyright 2018       Michael Kiefer <Michael-Kiefer@web.de>
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License as
10  * published by the Free Software Foundation; either version 2 of
11  * the License, or (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
20  */
21 
22 #ifndef MYMONEYREPORT_H
23 #define MYMONEYREPORT_H
24 
25 // ----------------------------------------------------------------------------
26 // QT Includes
27 
28 // ----------------------------------------------------------------------------
29 // Project Includes
30 #include "mymoneyobject.h"
31 #include "mymoneytransactionfilter.h"
32 #include "kmm_mymoney_export.h"
33 #include "mymoneyunittestable.h"
34 
35 class QString;
36 class MyMoneyAccount;
37 
38 template <typename T> class QList;
39 
40 namespace eMyMoney { namespace Account { enum class Type; }
41                      namespace TransactionFilter { enum class Date; } }
42 
43 namespace eMyMoney { namespace Report { enum class RowType; } }
44 namespace eMyMoney { namespace Report { enum class ReportType; } }
45 namespace eMyMoney { namespace Report { enum class ColumnType; } }
46 namespace eMyMoney { namespace Report { enum QueryColumn : int; } }
47 namespace eMyMoney { namespace Report { enum class DetailLevel; } }
48 namespace eMyMoney { namespace Report { enum class InvestmentSum; } }
49 namespace eMyMoney { namespace Report { enum class ChartType; } }
50 namespace eMyMoney { namespace Report { enum class DataLock; } }
51 namespace eMyMoney { namespace Report { enum class ChartPalette; } }
52 
53 /**
54   * This class defines a report within the MyMoneyEngine.  The report class
55   * contains all the configuration parameters needed to run a report, plus
56   * XML serialization.
57   *
58   * A report is a transactionfilter, so any report can specify which
59   * transactions it's interested down to the most minute level of detail.
60   * It extends the transactionfilter by providing identification (name,
61   * comments, group type, etc) as well as layout information (what kind
62   * of layout should be used, how the rows & columns should be presented,
63   * currency converted, etc.)
64   *
65   * As noted above, this class only provides a report DEFINITION.  The
66   * generation and presentation of the report itself are left to higher
67   * level classes.
68   *
69   * @author Ace Jones <acejones@users.sourceforge.net>
70   */
71 
72 class MyMoneyReportPrivate;
73 class KMM_MYMONEY_EXPORT MyMoneyReport: public MyMoneyObject, public MyMoneyTransactionFilter
74 {
75   Q_DECLARE_PRIVATE_D(MyMoneyObject::d_ptr, MyMoneyReport)
76 
77   KMM_MYMONEY_UNIT_TESTABLE
78 
79 public:
80   MyMoneyReport();
81   explicit MyMoneyReport(const QString &id);
82 
83   explicit MyMoneyReport(eMyMoney::Report::RowType rt,
84                          unsigned ct,
85                          eMyMoney::TransactionFilter::Date dl,
86                          eMyMoney::Report::DetailLevel ss,
87                          const QString& name,
88                          const QString& comment);
89 
90   MyMoneyReport(const QString& id,
91                 const MyMoneyReport& other);
92 
93   MyMoneyReport(const MyMoneyReport & other);
94   MyMoneyReport(MyMoneyReport && other);
95   MyMoneyReport & operator=(MyMoneyReport other);
96   friend void swap(MyMoneyReport& first, MyMoneyReport& second);
97 
98   ~MyMoneyReport();
99 
100   eMyMoney::Report::ReportType reportType() const;
101   void setReportType(eMyMoney::Report::ReportType rt);
102 
103   QString name() const;
104   void setName(const QString& s);
105 
106   bool isShowingRowTotals() const;
107   void setShowingRowTotals(bool f);
108 
109   bool isShowingColumnTotals() const;
110   void setShowingColumnTotals(bool f);
111 
112   eMyMoney::Report::RowType rowType() const;
113   void setRowType(eMyMoney::Report::RowType rt);
114   bool isRunningSum() const;
115 
116   eMyMoney::Report::ColumnType columnType() const;
117   void setColumnType(eMyMoney::Report::ColumnType ct);
118 
119   bool isConvertCurrency() const;
120   void setConvertCurrency(bool f);
121   uint columnPitch() const;
122 
123   QString comment() const;
124   void setComment(const QString& comment);
125 
126   eMyMoney::Report::QueryColumn queryColumns() const;
127   void setQueryColumns(eMyMoney::Report::QueryColumn qc);
128 
129   QString group() const;
130   void setGroup(const QString& group);
131 
132   bool isFavorite() const;
133   void setFavorite(bool f);
134 
135   bool isTax() const;
136   void setTax(bool f);
137 
138   bool isInvestmentsOnly() const;
139   void setInvestmentsOnly(bool f);
140 
141   bool isLoansOnly() const;
142   void setLoansOnly(bool f);
143 
144   eMyMoney::Report::DetailLevel detailLevel() const;
145   void setDetailLevel(eMyMoney::Report::DetailLevel detail);
146 
147   eMyMoney::Report::InvestmentSum investmentSum() const;
148   void setInvestmentSum(eMyMoney::Report::InvestmentSum sum);
149 
150   bool isHideTransactions() const;
151   void setHideTransactions(bool f);
152 
153   eMyMoney::Report::ChartType chartType() const;
154   void setChartType(eMyMoney::Report::ChartType type);
155 
156   eMyMoney::Report::ChartPalette chartPalette() const;
157   void setChartPalette(eMyMoney::Report::ChartPalette type);
158 
159   bool isChartDataLabels() const;
160   void setChartDataLabels(bool f);
161 
162   bool isChartCHGridLines() const;
163   void setChartCHGridLines(bool f);
164 
165   bool isChartSVGridLines() const;
166   void setChartSVGridLines(bool f);
167 
168   bool isChartByDefault() const;
169   void setChartByDefault(bool f);
170 
171   uint chartLineWidth() const;
172   void setChartLineWidth(uint f);
173 
174   bool isLogYAxis() const;
175   void setLogYAxis(bool f);
176 
177   bool isNegExpenses() const;
178   void setNegExpenses(bool f);
179 
180   QString dataRangeStart() const;
181   void setDataRangeStart(const QString& f);
182 
183   QString dataRangeEnd() const;
184   void setDataRangeEnd(const QString& f);
185 
186   QString dataMajorTick() const;
187   void setDataMajorTick(const QString& f);
188 
189   QString dataMinorTick() const;
190   void setDataMinorTick(const QString& f);
191 
192   uint yLabelsPrecision() const;
193   void setYLabelsPrecision(int f);
194 
195   bool isIncludingSchedules() const;
196   void setIncludingSchedules(bool f);
197 
198   bool isColumnsAreDays() const;
199   void setColumnsAreDays(bool f);
200 
201   bool isIncludingTransfers() const;
202   void setIncludingTransfers(bool f);
203 
204   bool isIncludingUnusedAccounts() const;
205   void setIncludingUnusedAccounts(bool f);
206 
207   bool hasBudget() const;
208   QString budget() const;
209 
210   /**
211     * Sets the budget used for this report
212     *
213     * @param budget The ID of the budget to use, or an empty string
214     * to indicate a budget is NOT included
215     * @param fa Whether to display actual data alongside the budget.
216     * Setting to false means the report displays ONLY the budget itself.
217     * @warning For now, the budget ID is ignored.  The budget id is
218     * simply checked for any non-empty string, and if so, hasBudget()
219     * will return true.
220     */
221   void setBudget(const QString& budget, bool fa = true);
222 
223   bool isIncludingBudgetActuals() const;
224   void setIncludingBudgetActuals(bool f);
225 
226   bool isIncludingForecast() const;
227   void setIncludingForecast(bool f);
228 
229   bool isIncludingMovingAverage() const;
230   void setIncludingMovingAverage(bool f);
231 
232   int movingAverageDays() const;
233   void setMovingAverageDays(int days);
234 
235   bool isIncludingPrice() const;
236   void setIncludingPrice(bool f);
237 
238   bool isIncludingAveragePrice() const;
239   void setIncludingAveragePrice(bool f);
240 
241   eMyMoney::Report::DataLock dataFilter() const;
242   bool isDataUserDefined() const;
243   void setDataFilter(eMyMoney::Report::DataLock u);
244 
245   eMyMoney::TransactionFilter::Date dateRange() const;
246   bool isDateUserDefined() const;
247 
248   /**
249     * Set the underlying date filter and LOCK that filter to the specified
250     * range.  For example, if @p _u is "CurrentMonth", this report should always
251     * be updated to the current month no matter when the report is run.
252     *
253     * This updating is not entirely automatic, you should update it yourself by
254     * calling updateDateFilter.
255     *
256     * @param _u The date range constant (MyMoneyTransactionFilter::dateRangeE)
257     *          which this report should be locked to.
258     */
259 
260   void setDateFilter(eMyMoney::TransactionFilter::Date u);
261 
262   /**
263     * Set the underlying date filter using the start and end dates provided.
264     * Note that this does not LOCK to any range like setDateFilter(unsigned)
265     * above.  It is just a reimplementation of the MyMoneyTransactionFilter
266     * version.
267     *
268     * @param _db The inclusive begin date of the date range
269     * @param _de The inclusive end date of the date range
270     */
271 
272   void setDateFilter(const QDate& db, const QDate& de);
273 
274   /**
275     * Set the underlying date filter using the 'date lock' property.
276     *
277     * Always call this function before executing the report to be sure that
278     * the date filters properly match the plain-language 'date lock'.
279     *
280     * For example, if the report is date-locked to "Current Month", and the
281     * last time you loaded or ran the report was in August, but it's now
282     * September, this function will update the date range to be September,
283     * as is proper.
284     */
285   void updateDateFilter();
286 
287   bool isMixedTime() const;
288   void setMixedTime(bool f);
289 
290   int currentDateColumn() const;
291   void setCurrentDateColumn(int f);
292 
293   uint settlementPeriod() const;
294   void setSettlementPeriod(uint days);
295 
296   bool isShowingSTLTCapitalGains() const;
297   void setShowSTLTCapitalGains(bool f);
298 
299   QDate termSeparator() const;
300   void setTermSeparator(const QDate& date);
301 
302   bool isSkippingZero() const;
303   void setSkipZero(int f);
304 
305   /**
306     * This method allows you to clear the underlying transaction filter
307     */
308   void clearTransactionFilter();
309 
310   /**
311     * This method allows you to set the underlying transaction filter
312     *
313     * @param _filter The filter which should replace the existing transaction
314     * filter.
315     */
316   void assignFilter(const MyMoneyTransactionFilter& filter);
317 
318   /**
319     * Retrieves a VALID beginning & ending date for this report.
320     *
321     * The underlying date filter can return en empty QDate() for either the
322     * begin or end date or both.  This is typically unacceptable for reports,
323     * which need the REAL begin and end date.
324     *
325     * This function gets the underlying date filter range, and if either is
326     * an empty QDate(), it determines the missing date from looking at all
327     * the transactions which match the underlying filter, and returning the
328     * date of the first or last transaction (as appropriate).
329     *
330     * @param _db The inclusive begin date of the date range
331     * @param _de The inclusive end date of the date range
332     */
333   void validDateRange(QDate &db, QDate &de);
334 
335   /**
336     * This method turns on the account group filter and adds the
337     * @p type to the list of allowed groups.
338     *
339     * Note that account group filtering is handled differently
340     * than all the filters of the underlying class.  This filter
341     * is meant to be applied to individual splits of matched
342     * transactions AFTER the underlying filter is used to find
343     * the matching transactions.
344     *
345     * @param type the account group to add to the allowed groups list
346     */
347   void addAccountGroup(eMyMoney::Account::Type type);
348 
349   /**
350     * This method returns whether an account group filter has been set,
351     * and if so, it returns all the account groups set in the filter.
352     *
353     * @param list list to append account groups into
354     * @return return true if an account group filter has been set
355     */
356   bool accountGroups(QList<eMyMoney::Account::Type>& list) const;
357 
358   /**
359     * This method returns whether the specified account group
360     * is allowed by the account groups filter.
361     *
362     * @param type group to append account groups into
363     * @return return true if an account group filter has been set
364     */
365   bool includesAccountGroup(eMyMoney::Account::Type type) const;
366 
367   /**
368     * This method is used to test whether a specific account
369     * passes the accountGroup test and either the Account or
370     * Category test, depending on which sort of Account it is.
371     *
372     * The m_tax and m_investments properties are also considered.
373     *
374     * @param acc the account in question
375     * @return true if account is in filter set, false otherwise
376     */
377   bool includes(const MyMoneyAccount& acc) const;
378 
379   /**
380     * This method checks if a reference to the given object exists. It returns,
381     * a @p true if the object is referencing the one requested by the
382     * parameter @p id. If it does not, this method returns @p false.
383     *
384     * @param id id of the object to be checked for references
385     * @retval true This object references object with id @p id.
386     * @retval false This object does not reference the object with id @p id.
387     */
388   bool hasReferenceTo(const QString& id) const override;
389 
390   /**
391    * Return row type as string.
392    *
393    * @param type type to get string for
394    * @return row type converted to string
395    */
396   static QString toString(eMyMoney::Report::RowType type);
397 
398   /**
399    * Return report type as string.
400    *
401    * @param type report type to get string for
402    * @return report type converted to string
403    */
404   static QString toString(eMyMoney::Report::ReportType type);
405 
406   /**
407     * This method allows to modify and retrieve the default lineWidth for graphs.
408     * The default is 2.
409     */
410   static void setLineWidth(int width);
411   static int lineWidth();
412 
413   // set the expert mode which shows equity accounts for some reports
414   static void setExpertMode(bool expertMode);
415 
416 private:
417   void addAccountGroupsByRowType(eMyMoney::Report::RowType rt);
418 
419 private:
420   /**
421     * This member keeps the current setting for line graphs lineWidth.
422     * @sa setLineWidth()
423     */
424   static int m_lineWidth;
425 
426   static bool m_expertMode;
427 };
428 
swap(MyMoneyReport & first,MyMoneyReport & second)429 inline void swap(MyMoneyReport& first, MyMoneyReport& second) // krazy:exclude=inline
430 {
431   using std::swap;
432   swap(first.MyMoneyObject::d_ptr, second.MyMoneyObject::d_ptr);
433   swap(first.MyMoneyTransactionFilter::d_ptr, second.MyMoneyTransactionFilter::d_ptr);
434 }
435 
MyMoneyReport(MyMoneyReport && other)436 inline MyMoneyReport::MyMoneyReport(MyMoneyReport && other) : MyMoneyReport() // krazy:exclude=inline
437 {
438   swap(*this, other);
439 }
440 
441 inline MyMoneyReport & MyMoneyReport::operator=(MyMoneyReport other) // krazy:exclude=inline
442 {
443   swap(*this, other);
444   return *this;
445 }
446 
447 /**
448   * Make it possible to hold @ref MyMoneyReport objects inside @ref QVariant objects.
449   */
450 Q_DECLARE_METATYPE(MyMoneyReport)
451 
452 #endif // MYMONEYREPORT_H
453