File indexing completed on 2024-05-12 05:06:45

0001 /*
0002     SPDX-FileCopyrightText: 2000-2002 Michael Edwardes <mte@users.sourceforge.net>
0003     SPDX-FileCopyrightText: 2001-2019 Thomas Baumgart <tbaumgart@kde.org>
0004     SPDX-FileCopyrightText: 2001 Felix Rodriguez <frodriguez@users.sourceforge.net>
0005     SPDX-FileCopyrightText: 2003 Kevin Tambascio <ktambascio@users.sourceforge.net>
0006     SPDX-FileCopyrightText: 2004-2005 Ace Jones <acejones@users.sourceforge.net>
0007     SPDX-FileCopyrightText: 2006 Darren Gould <darren_gould@gmx.de>
0008     SPDX-License-Identifier: GPL-2.0-or-later
0009 */
0010 
0011 #ifndef MYMONEYTRANSACTION_H
0012 #define MYMONEYTRANSACTION_H
0013 
0014 // ----------------------------------------------------------------------------
0015 // QT Includes
0016 
0017 #include <QMetaType>
0018 #include <QStringList>
0019 
0020 // ----------------------------------------------------------------------------
0021 // Project Includes
0022 
0023 #include "mymoneykeyvaluecontainer.h"
0024 #include "mymoneyobject.h"
0025 #include "kmm_mymoney_export.h"
0026 #include "mymoneyunittestable.h"
0027 
0028 class QString;
0029 class QDate;
0030 
0031 class MyMoneyMoney;
0032 class MyMoneySplit;
0033 
0034 template <typename T> class QList;
0035 
0036 /**
0037   * This class represents a transaction within the MyMoneyEngine. A transaction
0038   * contains none, one or more splits of type MyMoneySplit. They are stored in
0039   * a QList<MyMoneySplit> within this object. A transaction containing only
0040   * a single split with an amount not equal to 0 is an unbalanced transaction. It
0041   * is tolerated by the engine, but in general not a good idea as it is financially
0042   * wrong.
0043   */
0044 class MyMoneyTransactionPrivate;
0045 class KMM_MYMONEY_EXPORT MyMoneyTransaction : public MyMoneyObject, public MyMoneyKeyValueContainer
0046 {
0047     Q_DECLARE_PRIVATE_D(MyMoneyObject::d_ptr, MyMoneyTransaction)
0048 
0049     KMM_MYMONEY_UNIT_TESTABLE
0050 
0051 public:
0052 
0053     MyMoneyTransaction();
0054     explicit MyMoneyTransaction(const QString &id);
0055 
0056     MyMoneyTransaction(const QString& id,
0057                        const MyMoneyTransaction& other);
0058 
0059     MyMoneyTransaction(const MyMoneyTransaction & other);
0060     MyMoneyTransaction(MyMoneyTransaction && other);
0061     MyMoneyTransaction & operator=(MyMoneyTransaction other);
0062     friend void swap(MyMoneyTransaction& first, MyMoneyTransaction& second);
0063 
0064     ~MyMoneyTransaction();
0065 
0066     friend QDataStream &operator<<(QDataStream &, MyMoneyTransaction &);
0067     friend QDataStream &operator>>(QDataStream &, MyMoneyTransaction &);
0068 
0069     QDate entryDate() const;
0070     void setEntryDate(const QDate& date);
0071 
0072     QDate postDate() const;
0073     void setPostDate(const QDate& date);
0074 
0075     QString memo() const;
0076     void setMemo(const QString& memo);
0077 
0078     QList<MyMoneySplit> splits() const;
0079     QList<MyMoneySplit>& splits();
0080     MyMoneySplit firstSplit() const;
0081     uint splitCount() const;
0082     uint splitCountWithValue() const;
0083 
0084     QString commodity() const;
0085     void setCommodity(const QString& commodityId);
0086 
0087     QString bankID() const;
0088     void setBankID(const QString& bankID);
0089 
0090     bool operator ==  (const MyMoneyTransaction& right) const;
0091     bool operator !=  (const MyMoneyTransaction& r) const;
0092     bool operator <   (const MyMoneyTransaction& r) const;
0093     bool operator <=  (const MyMoneyTransaction& r) const;
0094     bool operator >   (const MyMoneyTransaction& r) const;
0095 
0096     /**
0097       * This method is used to extract a split for a given accountId
0098       * from a transaction. A parameter controls, whether the accountId
0099       * should match or not. In case of 'not match', the first not-matching
0100       * split is returned.
0101       *
0102       * @param accountId the account to look for
0103       * @param match if true, the account Id must match
0104       *              if false, the account Id must not match
0105       *
0106       * @return reference to split within the transaction is returned
0107       */
0108     MyMoneySplit splitByAccount(const QString& accountId, const bool match = true) const;
0109 
0110     /**
0111       * This method is essentially the same as the previous method, except that
0112       * takes a list of accounts instead of just one.
0113       *
0114       * @param accountIds the list of accounts to look for
0115       * @param match if true, the account Id must match
0116       *              if false, the account Id must not match
0117       *
0118       * @return reference to split within the transaction is returned
0119       */
0120     MyMoneySplit splitByAccount(const QStringList& accountIds, const bool match = true) const;
0121 
0122     /**
0123       * This method is used to extract a split from a transaction.
0124       *
0125       * @param splitId the split to look for
0126       *
0127       * @return reference to split within the transaction is returned
0128       */
0129     MyMoneySplit splitById(const QString& splitId) const;
0130 
0131     /**
0132       * This method is used to extract a split for a given payeeId
0133       * from a transaction.
0134       *
0135       * @param payeeId the payee to look for
0136       *
0137       * @return reference to split within the transaction is returned
0138       */
0139     MyMoneySplit splitByPayee(const QString& payeeId) const;
0140 
0141     /**
0142       * This method is used to check if the given account is used
0143       * in any of the splits of this transaction
0144       *
0145       * @param id account id that should be checked for usage
0146       */
0147     bool accountReferenced(const QString& id) const;
0148 
0149     /**
0150       * This method is used to add a split to the transaction. The split
0151       * will be assigned an id. The id member must be empty and the
0152       * accountId member must be filled.
0153       *
0154       * @param split reference to the split that should be added
0155       *
0156       */
0157     void addSplit(MyMoneySplit &split);
0158 
0159     /**
0160       * This method is used to modify a split in a transaction
0161       */
0162     void modifySplit(const MyMoneySplit& split);
0163 
0164     /**
0165       * This method is used to remove a split from a transaction
0166       */
0167     void removeSplit(const MyMoneySplit& split);
0168 
0169     /**
0170       * This method is used to remove all splits from a transaction
0171       */
0172     void removeSplits();
0173 
0174     /**
0175       * This method is used to return the sum of all splits of this transaction
0176       *
0177       * @return MyMoneyMoney value of sum of all splits
0178       */
0179     MyMoneyMoney splitSum() const;
0180 
0181     /**
0182       * This method is used to reverse a transaction by reversing the values of each split
0183       */
0184     void reverse();
0185 
0186     /**
0187       * This method returns information if the transaction
0188       * contains information of a loan payment or not.
0189       * Loan payment transactions have at least one
0190       * split that is identified with a MyMoneySplit::action() of type
0191       * MyMoneySplit::actionName(eMyMoney::Split::Action::Amortization).
0192       *
0193       * @retval false transaction is no loan payment transaction
0194       * @retval true  transaction is a loan payment transaction
0195       *
0196       * @note Upon internal failures, the return value @p false will be used.
0197       */
0198     bool isLoanPayment() const;
0199 
0200     /**
0201       * This method returns a const reference to the amortization split.
0202       * In case none is found, a reference to an empty split will be returned.
0203       */
0204     MyMoneySplit amortizationSplit() const;
0205 
0206     /**
0207      * This method returns a const reference to the interest split.
0208      * In case none is found, a reference to an empty split will be returned.
0209      */
0210     MyMoneySplit interestSplit() const;
0211 
0212     /**
0213       * returns @a true if this is a stock split transaction
0214       */
0215     bool isStockSplit() const;
0216 
0217     /**
0218       * returns @a true if this is an imported transaction
0219       */
0220     bool isImported() const;
0221 
0222     /**
0223      * Sets the imported state of this transaction to be the value of @a state .
0224      * @p state defaults to @p true.
0225      */
0226     void setImported(bool state = true);
0227 
0228     /**
0229       * This static method returns the id which will be assigned to the
0230       * first split added to a transaction. This ID can be used to figure
0231       * out the split that references the account through which a transaction
0232       * was entered.
0233       *
0234       * @return QString with ID of the first split of transactions
0235       */
0236     static QString firstSplitID();
0237 
0238     /**
0239       * Checks whether any split contains an autocalc split.
0240       *
0241       * @retval true at least one split has an autocalc value
0242       * @retval false all splits have fixed values
0243       */
0244     bool hasAutoCalcSplit() const;
0245 
0246     /**
0247       * Returns a signature consisting of the account ids and the
0248       * number of times they occur in the transaction if @a includeSplitCount
0249       * is @a true. The signature is independent from the order of splits.
0250       *
0251       * Example: Having splits referencing the account B, A and B, the returned
0252       * value will be "A-B" if @p includeSplitCount is @p false or A*1-B*2 if it
0253       * is @p true.
0254       *
0255       * The same result will be returned if the list of splits is A, B, B.
0256       *
0257       * @param includeSplitCount if @p true, the string @p *n with @p n being
0258       *        the number of splits referencing this account. The default for
0259       *        this parameter is @p false.
0260       */
0261     QString accountSignature(bool includeSplitCount = false) const;
0262 
0263     QString uniqueSortKey() const;
0264     static QString uniqueSortKey(const QDate& date, const QString& id);
0265 
0266     /**
0267      * This module implements an algorithm used by P.J. Weinberger
0268      * for fast hashing. Source: COMPILERS by Alfred V. Aho,
0269      * pages 435-437.
0270      *
0271      * It converts the string passed in @p txt into a non-unique
0272      * unsigned long integer value.
0273      *
0274      * @param txt the text to be hashed
0275      * @param h initial hash value (default 0)
0276      * @return non-unique hash value of the text @p txt
0277      */
0278     static unsigned long hash(const QString& txt, unsigned long h = 0);
0279 
0280     /**
0281      * This method replaces all occurrences of id @a oldId with
0282      * @a newId.  All other ids are not changed.
0283      *
0284      * @return true if any change has been performed
0285      * @return false if nothing has been modified
0286      */
0287     bool replaceId(const QString& newId, const QString& oldId);
0288 };
0289 
0290 inline void swap(MyMoneyTransaction& first, MyMoneyTransaction& second) // krazy:exclude=inline
0291 {
0292     using std::swap;
0293     swap(first.MyMoneyObject::d_ptr, second.MyMoneyObject::d_ptr);
0294     swap(first.MyMoneyKeyValueContainer::d_ptr, second.MyMoneyKeyValueContainer::d_ptr);
0295 }
0296 
0297 inline MyMoneyTransaction::MyMoneyTransaction(MyMoneyTransaction && other) : MyMoneyTransaction() // krazy:exclude=inline
0298 {
0299     swap(*this, other);
0300 }
0301 
0302 inline MyMoneyTransaction & MyMoneyTransaction::operator=(MyMoneyTransaction other) // krazy:exclude=inline
0303 {
0304     swap(*this, other);
0305     return *this;
0306 }
0307 
0308 /**
0309   * Make it possible to hold @ref MyMoneyTransaction objects inside @ref QVariant objects.
0310   */
0311 Q_DECLARE_METATYPE(MyMoneyTransaction)
0312 
0313 #endif