1 /* 2 * Copyright 2005-2006 Ace Jones <acejones@users.sourceforge.net> 3 * Copyright 2005-2018 Thomas Baumgart <tbaumgart@kde.org> 4 * 5 * This program is free software; you can redistribute it and/or 6 * modify it under the terms of the GNU General Public License as 7 * published by the Free Software Foundation; either version 2 of 8 * the License, or (at your option) any later version. 9 * 10 * This program is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU General Public License for more details. 14 * 15 * You should have received a copy of the GNU General Public License 16 * along with this program. If not, see <http://www.gnu.org/licenses/>. 17 */ 18 19 #ifndef PIVOTGRID_H 20 #define PIVOTGRID_H 21 22 // ---------------------------------------------------------------------------- 23 // QT Includes 24 25 #include <QMap> 26 #include <QList> 27 28 // ---------------------------------------------------------------------------- 29 // KDE Includes 30 31 // ---------------------------------------------------------------------------- 32 // Project Includes 33 34 #include "reportaccount.h" 35 #include "mymoneymoney.h" 36 37 namespace reports 38 { 39 40 enum ERowType {eActual, eBudget, eBudgetDiff, eForecast, eAverage, ePrice }; 41 42 /** 43 * The fundamental data construct of this class is a 'grid'. It is organized as follows: 44 * 45 * A 'Row' is a row of money values, each column is a month. The first month corresponds to 46 * m_beginDate. 47 * 48 * A 'Row Pair' is two rows of money values. Each column is the SAME month. One row is the 49 * 'actual' values for the period, the other row is the 'budgetted' values for the same 50 * period. For ease of implementation, a Row Pair is implemented as a Row which contains 51 * another Row. The inherited Row is the 'actual', the contained row is the 'Budget'. 52 * 53 * An 'Inner Group' contains a rows for each subordinate account within a single top-level 54 * account. It also contains a mapping from the account descriptor for the subordinate account 55 * to its row data. So if we have an Expense account called "Computers", with sub-accounts called 56 * "Hardware", "Software", and "Peripherals", there will be one Inner Group for "Computers" 57 * which contains three Rows. 58 * 59 * An 'Outer Group' contains Inner Row Groups for all the top-level accounts in a given 60 * account class. Account classes are Expense, Income, Asset, Liability. In the case above, 61 * the "Computers" Inner Group is contained within the "Expense" Outer Group. 62 * 63 * A 'Grid' is the set of all Outer Groups contained in this report. 64 * 65 */ 66 class PivotCell: public MyMoneyMoney 67 { 68 KMM_MYMONEY_UNIT_TESTABLE 69 70 public: PivotCell()71 PivotCell() : m_stockSplit(MyMoneyMoney::ONE), m_cellUsed(false) {} 72 explicit PivotCell(const MyMoneyMoney& value); 73 virtual ~PivotCell(); 74 static PivotCell stockSplit(const MyMoneyMoney& factor); 75 PivotCell operator += (const PivotCell& right); 76 PivotCell operator += (const MyMoneyMoney& value); 77 const QString formatMoney(int fraction, bool showThousandSeparator = true) const; 78 const QString formatMoney(const QString& currency, const int prec, bool showThousandSeparator = true) const; 79 MyMoneyMoney calculateRunningSum(const MyMoneyMoney& runningSum); 80 MyMoneyMoney cellBalance(const MyMoneyMoney& _balance); isUsed()81 bool isUsed() const { 82 return m_cellUsed; 83 } 84 private: 85 MyMoneyMoney m_stockSplit; 86 MyMoneyMoney m_postSplit; 87 bool m_cellUsed; 88 }; 89 class PivotGridRow: public QList<PivotCell> 90 { 91 public: 92 93 explicit PivotGridRow(unsigned _numcolumns = 0) { 94 for (uint i = 0; i < _numcolumns; i++) 95 append(PivotCell()); 96 } 97 MyMoneyMoney m_total; 98 }; 99 100 class PivotGridRowSet: public QMap<ERowType, PivotGridRow> 101 { 102 public: 103 explicit PivotGridRowSet(unsigned _numcolumns = 0); 104 }; 105 106 class PivotInnerGroup: public QMap<ReportAccount, PivotGridRowSet> 107 { 108 public: m_total(_numcolumns)109 explicit PivotInnerGroup(unsigned _numcolumns = 0): m_total(_numcolumns) {} 110 111 PivotGridRowSet m_total; 112 }; 113 114 class PivotOuterGroup: public QMap<QString, PivotInnerGroup> 115 { 116 public: m_total(_numcolumns)117 explicit PivotOuterGroup(unsigned _numcolumns = 0, unsigned _sort = m_kDefaultSortOrder, bool _inverted = false): m_total(_numcolumns), m_inverted(_inverted), m_sortOrder(_sort) {} 118 bool operator<(const PivotOuterGroup& _right) const { 119 if (m_sortOrder != _right.m_sortOrder) 120 return m_sortOrder < _right.m_sortOrder; 121 else 122 return m_displayName < _right.m_displayName; 123 } 124 PivotGridRowSet m_total; 125 126 // An inverted outergroup means that all values placed in subordinate rows 127 // should have their sign inverted from typical cash-flow notation. Also it 128 // means that when the report is summed, the values should be inverted again 129 // so that the grand total is really "non-inverted outergroup MINUS inverted outergroup". 130 bool m_inverted; 131 132 // The localized name of the group for display in the report. Outergoups need this 133 // independently, because they will lose their association with the TGrid when the 134 // report is rendered. 135 QString m_displayName; 136 137 // lower numbers sort toward the top of the report. defaults to 100, which is a nice 138 // middle-of-the-road value 139 unsigned m_sortOrder; 140 141 // default sort order 142 static const unsigned m_kDefaultSortOrder; 143 }; 144 class PivotGrid: public QMap<QString, PivotOuterGroup> 145 { 146 public: 147 PivotGridRowSet rowSet(QString id); 148 149 PivotGridRowSet m_total; 150 }; 151 152 } 153 154 #endif 155 // PIVOTGRID_H 156