File indexing completed on 2024-05-12 16:42:42

0001 /*
0002     SPDX-FileCopyrightText: 2000-2002 Michael Edwardes <mte@users.sourceforge.net>
0003     SPDX-FileCopyrightText: 2001-2017 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 
0019 // ----------------------------------------------------------------------------
0020 // Project Includes
0021 
0022 #include "mymoneykeyvaluecontainer.h"
0023 #include "mymoneyobject.h"
0024 #include "kmm_mymoney_export.h"
0025 #include "mymoneyunittestable.h"
0026 
0027 class QString;
0028 class QDate;
0029 
0030 class MyMoneyMoney;
0031 class MyMoneySplit;
0032 class QStringList;
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 
0083     QString commodity() const;
0084     void setCommodity(const QString& commodityId);
0085 
0086     QString bankID() const;
0087     void setBankID(const QString& bankID);
0088 
0089     bool operator ==  (const MyMoneyTransaction& right) const;
0090     bool operator !=  (const MyMoneyTransaction& r) const;
0091     bool operator <   (const MyMoneyTransaction& r) const;
0092     bool operator <=  (const MyMoneyTransaction& r) const;
0093     bool operator >   (const MyMoneyTransaction& r) const;
0094 
0095     /**
0096       * This method is used to extract a split for a given accountId
0097       * from a transaction. A parameter controls, whether the accountId
0098       * should match or not. In case of 'not match', the first not-matching
0099       * split is returned.
0100       *
0101       * @param accountId the account to look for
0102       * @param match if true, the account Id must match
0103       *              if false, the account Id must not match
0104       *
0105       * @return reference to split within the transaction is returned
0106       */
0107     MyMoneySplit splitByAccount(const QString& accountId, const bool match = true) const;
0108 
0109     /**
0110       * This method is essentially the same as the previous method, except that
0111       * takes a list of accounts instead of just one.
0112       *
0113       * @param accountIds the list of accounts to look for
0114       * @param match if true, the account Id must match
0115       *              if false, the account Id must not match
0116       *
0117       * @return reference to split within the transaction is returned
0118       */
0119     MyMoneySplit splitByAccount(const QStringList& accountIds, const bool match = true) const;
0120 
0121     /**
0122       * This method is used to extract a split from a transaction.
0123       *
0124       * @param splitId the split to look for
0125       *
0126       * @return reference to split within the transaction is returned
0127       */
0128     MyMoneySplit splitById(const QString& splitId) const;
0129 
0130     /**
0131       * This method is used to extract a split for a given payeeId
0132       * from a transaction.
0133       *
0134       * @param payeeId the payee to look for
0135       *
0136       * @return reference to split within the transaction is returned
0137       */
0138     MyMoneySplit splitByPayee(const QString& payeeId) const;
0139 
0140     /**
0141       * This method is used to check if the given account is used
0142       * in any of the splits of this transaction
0143       *
0144       * @param id account id that should be checked for usage
0145       */
0146     bool accountReferenced(const QString& id) const;
0147 
0148     /**
0149       * This method is used to add a split to the transaction. The split
0150       * will be assigned an id. The id member must be empty and the
0151       * accountId member must be filled.
0152       *
0153       * @param split reference to the split that should be added
0154       *
0155       */
0156     void addSplit(MyMoneySplit &split);
0157 
0158     /**
0159       * This method is used to modify a split in a transaction
0160       */
0161     void modifySplit(const MyMoneySplit& split);
0162 
0163     /**
0164       * This method is used to remove a split from a transaction
0165       */
0166     void removeSplit(const MyMoneySplit& split);
0167 
0168     /**
0169       * This method is used to remove all splits from a transaction
0170       */
0171     void removeSplits();
0172 
0173     /**
0174       * This method is used to return the sum of all splits of this transaction
0175       *
0176       * @return MyMoneyMoney value of sum of all splits
0177       */
0178     MyMoneyMoney splitSum() const;
0179 
0180     /**
0181       * This method is used to reverse a transaction by reversing the values of each split
0182       */
0183     void reverse();
0184 
0185     /**
0186       * This method returns information if the transaction
0187       * contains information of a loan payment or not.
0188       * Loan payment transactions have at least one
0189       * split that is identified with a MyMoneySplit::action() of type
0190       * MyMoneySplit::actionName(eMyMoney::Split::Action::Amortization).
0191       *
0192       * @retval false transaction is no loan payment transaction
0193       * @retval true  transaction is a loan payment transaction
0194       *
0195       * @note Upon internal failures, the return value @p false will be used.
0196       */
0197     bool isLoanPayment() const;
0198 
0199     /**
0200       * This method returns a const reference to the amortization split.
0201       * In case none is found, a reference to an empty split will be returned.
0202       */
0203     MyMoneySplit amortizationSplit() const;
0204 
0205     /**
0206      * This method returns a const reference to the interest split.
0207      * In case none is found, a reference to an empty split will be returned.
0208      */
0209     MyMoneySplit interestSplit() const;
0210 
0211     /**
0212       * returns @a true if this is a stock split transaction
0213       */
0214     bool isStockSplit() const;
0215 
0216     /**
0217       * returns @a true if this is an imported transaction
0218       */
0219     bool isImported() const;
0220 
0221     /**
0222      * Sets the imported state of this transaction to be the value of @a state .
0223      * @p state defaults to @p true.
0224      */
0225     void setImported(bool state = true);
0226 
0227     /**
0228       * This static method returns the id which will be assigned to the
0229       * first split added to a transaction. This ID can be used to figure
0230       * out the split that references the account through which a transaction
0231       * was entered.
0232       *
0233       * @return QString with ID of the first split of transactions
0234       */
0235     static QString firstSplitID();
0236 
0237     /**
0238       * This method checks if a reference to the given object exists. It returns,
0239       * a @p true if the object is referencing the one requested by the
0240       * parameter @p id. If it does not, this method returns @p false.
0241       *
0242       * @param id id of the object to be checked for references
0243       * @retval true This object references object with id @p id.
0244       * @retval false This object does not reference the object with id @p id.
0245       */
0246     bool hasReferenceTo(const QString& id) const override;
0247 
0248     /**
0249       * Checks whether any split contains an autocalc split.
0250       *
0251       * @retval true at least one split has an autocalc value
0252       * @retval false all splits have fixed values
0253       */
0254     bool hasAutoCalcSplit() const;
0255 
0256     /**
0257       * Returns a signature consisting of the account ids and the
0258       * number of times they occur in the transaction if @a includeSplitCount
0259       * is @a true. The signature is independent from the order of splits.
0260       *
0261       * Example: Having splits referencing the account B, A and B, the returned
0262       * value will be "A-B" if @p includeSplitCount is @p false or A*1-B*2 if it
0263       * is @p true.
0264       *
0265       * The same result will be returned if the list of splits is A, B, B.
0266       *
0267       * @param includeSplitCount if @p true, the string @p *n with @p n being
0268       *        the number of splits referencing this account. The default for
0269       *        this parameter is @p false.
0270       */
0271     QString accountSignature(bool includeSplitCount = false) const;
0272 
0273     QString uniqueSortKey() const;
0274 
0275     /**
0276      * This module implements an algorithm used by P.J. Weinberger
0277      * for fast hashing. Source: COMPILERS by Alfred V. Aho,
0278      * pages 435-437.
0279      *
0280      * It converts the string passed in @p txt into a non-unique
0281      * unsigned long integer value.
0282      *
0283      * @param txt the text to be hashed
0284      * @param h initial hash value (default 0)
0285      * @return non-unique hash value of the text @p txt
0286      */
0287     static unsigned long hash(const QString& txt, unsigned long h = 0);
0288 
0289     /**
0290      * This method replaces all occurrences of id @a oldId with
0291      * @a newId.  All other ids are not changed.
0292      *
0293      * @return true if any change has been performed
0294      * @return false if nothing has been modified
0295      */
0296     bool replaceId(const QString& newId, const QString& oldId);
0297 };
0298 
0299 inline void swap(MyMoneyTransaction& first, MyMoneyTransaction& second) // krazy:exclude=inline
0300 {
0301     using std::swap;
0302     swap(first.MyMoneyObject::d_ptr, second.MyMoneyObject::d_ptr);
0303     swap(first.MyMoneyKeyValueContainer::d_ptr, second.MyMoneyKeyValueContainer::d_ptr);
0304 }
0305 
0306 inline MyMoneyTransaction::MyMoneyTransaction(MyMoneyTransaction && other) : MyMoneyTransaction() // krazy:exclude=inline
0307 {
0308     swap(*this, other);
0309 }
0310 
0311 inline MyMoneyTransaction & MyMoneyTransaction::operator=(MyMoneyTransaction other) // krazy:exclude=inline
0312 {
0313     swap(*this, other);
0314     return *this;
0315 }
0316 
0317 /**
0318   * Make it possible to hold @ref MyMoneyTransaction objects inside @ref QVariant objects.
0319   */
0320 Q_DECLARE_METATYPE(MyMoneyTransaction)
0321 
0322 #endif