File indexing completed on 2024-06-23 05:02:17

0001 /*
0002     SPDX-FileCopyrightText: 2005-2006 Ace Jones <acejones@users.sourceforge.net>
0003     SPDX-FileCopyrightText: 2005-2018 Thomas Baumgart <tbaumgart@kde.org>
0004     SPDX-License-Identifier: GPL-2.0-or-later
0005 */
0006 
0007 #ifndef PIVOTGRID_H
0008 #define PIVOTGRID_H
0009 
0010 // ----------------------------------------------------------------------------
0011 // QT Includes
0012 
0013 #include <QMap>
0014 #include <QList>
0015 
0016 // ----------------------------------------------------------------------------
0017 // KDE Includes
0018 
0019 // ----------------------------------------------------------------------------
0020 // Project Includes
0021 
0022 #include "reportaccount.h"
0023 #include "mymoneymoney.h"
0024 
0025 namespace reports
0026 {
0027 
0028 enum ERowType {eActual, eBudget, eBudgetDiff, eForecast, eAverage, ePrice };
0029 
0030 /**
0031   * The fundamental data construct of this class is a 'grid'.  It is organized as follows:
0032   *
0033   * A 'Row' is a row of money values, each column is a month.  The first month corresponds to
0034   * m_beginDate.
0035   *
0036   * A 'Row Pair' is two rows of money values.  Each column is the SAME month.  One row is the
0037   * 'actual' values for the period, the other row is the 'budgetted' values for the same
0038   * period.  For ease of implementation, a Row Pair is implemented as a Row which contains
0039   * another Row.  The inherited Row is the 'actual', the contained row is the 'Budget'.
0040   *
0041   * An 'Inner Group' contains a rows for each subordinate account within a single top-level
0042   * account.  It also contains a mapping from the account descriptor for the subordinate account
0043   * to its row data.  So if we have an Expense account called "Computers", with sub-accounts called
0044   * "Hardware", "Software", and "Peripherals", there will be one Inner Group for "Computers"
0045   * which contains three Rows.
0046   *
0047   * An 'Outer Group' contains Inner Row Groups for all the top-level accounts in a given
0048   * account class.  Account classes are Expense, Income, Asset, Liability.  In the case above,
0049   * the "Computers" Inner Group is contained within the "Expense" Outer Group.
0050   *
0051   * A 'Grid' is the set of all Outer Groups contained in this report.
0052   *
0053   */
0054 class PivotCell: public MyMoneyMoney
0055 {
0056     KMM_MYMONEY_UNIT_TESTABLE
0057 
0058 public:
0059     PivotCell() : m_stockSplit(MyMoneyMoney::ONE), m_cellUsed(false) {}
0060     explicit PivotCell(const MyMoneyMoney& value);
0061     virtual ~PivotCell();
0062     static PivotCell stockSplit(const MyMoneyMoney& factor);
0063     PivotCell operator += (const PivotCell& right);
0064     PivotCell operator += (const MyMoneyMoney& value);
0065     const QString formatMoney(int fraction, bool showThousandSeparator = true) const;
0066     const QString formatMoney(const QString& currency, const int prec, bool showThousandSeparator = true) const;
0067     MyMoneyMoney calculateRunningSum(const MyMoneyMoney& runningSum);
0068     MyMoneyMoney cellBalance(const MyMoneyMoney& _balance);
0069     bool isUsed() const {
0070         return m_cellUsed;
0071     }
0072 private:
0073     MyMoneyMoney m_stockSplit;
0074     MyMoneyMoney m_postSplit;
0075     bool m_cellUsed;
0076 };
0077 class PivotGridRow: public QList<PivotCell>
0078 {
0079 public:
0080 
0081     explicit PivotGridRow(unsigned _numcolumns = 0) {
0082         for (uint i = 0; i < _numcolumns; i++)
0083             append(PivotCell());
0084     }
0085     MyMoneyMoney m_total;
0086 };
0087 
0088 class PivotGridRowSet: public QMap<ERowType, PivotGridRow>
0089 {
0090 public:
0091     explicit PivotGridRowSet(unsigned _numcolumns = 0);
0092 };
0093 
0094 class PivotInnerGroup: public QMap<ReportAccount, PivotGridRowSet>
0095 {
0096 public:
0097     explicit PivotInnerGroup(unsigned _numcolumns = 0): m_total(_numcolumns) {}
0098 
0099     PivotGridRowSet m_total;
0100 };
0101 
0102 class PivotOuterGroup: public QMap<QString, PivotInnerGroup>
0103 {
0104 public:
0105     explicit PivotOuterGroup(unsigned _numcolumns = 0, unsigned _sort = m_kDefaultSortOrder, bool _inverted = false): m_total(_numcolumns), m_inverted(_inverted), m_sortOrder(_sort) {}
0106     bool operator<(const PivotOuterGroup& _right) const {
0107         if (m_sortOrder != _right.m_sortOrder)
0108             return m_sortOrder < _right.m_sortOrder;
0109         else
0110             return m_displayName < _right.m_displayName;
0111     }
0112     PivotGridRowSet m_total;
0113 
0114     // An inverted outergroup means that all values placed in subordinate rows
0115     // should have their sign inverted from typical cash-flow notation.  Also it
0116     // means that when the report is summed, the values should be inverted again
0117     // so that the grand total is really "non-inverted outergroup MINUS inverted outergroup".
0118     bool m_inverted;
0119 
0120     // The localized name of the group for display in the report. Outergoups need this
0121     // independently, because they will lose their association with the TGrid when the
0122     // report is rendered.
0123     QString m_displayName;
0124 
0125     // lower numbers sort toward the top of the report. defaults to 100, which is a nice
0126     // middle-of-the-road value
0127     unsigned m_sortOrder;
0128 
0129     // default sort order
0130     static const unsigned m_kDefaultSortOrder;
0131 };
0132 class PivotGrid: public QMap<QString, PivotOuterGroup>
0133 {
0134 public:
0135     PivotGridRowSet rowSet(QString id);
0136 
0137     PivotGridRowSet m_total;
0138 };
0139 
0140 }
0141 
0142 #endif
0143 // PIVOTGRID_H