File indexing completed on 2024-05-12 16:41:58

0001 /*
0002     KMyMoney transaction importing module - base class for searching for a matching transaction
0003 
0004     SPDX-FileCopyrightText: 2012 Lukasz Maszczynski <lukasz@maszczynski.net>
0005     SPDX-License-Identifier: GPL-2.0-or-later
0006 */
0007 
0008 #ifndef TRANSACTIONMATCHFINDER_H
0009 #define TRANSACTIONMATCHFINDER_H
0010 
0011 #include <QScopedPointer>
0012 
0013 #include "mymoneysplit.h"
0014 #include "mymoneytransaction.h"
0015 #include "mymoneyschedule.h"
0016 
0017 /** The class provides an interface for finding a MyMoneyTransaction match with the one being imported
0018  */
0019 class TransactionMatchFinder
0020 {
0021 public:
0022     /// enumerates possible match results
0023     typedef enum {
0024         MatchNotFound,           ///< no matching transaction found
0025         MatchImprecise,          ///< matching transaction found
0026         MatchPrecise,            ///< matching transaction found with exactly the same parameters
0027         MatchDuplicate,          ///< found transaction duplicate
0028     } MatchResult;
0029 
0030     /** Initializes the match finder.
0031      * @param matchWindow max number of days the transactions may vary and still be considered to be matching
0032      */
0033     explicit TransactionMatchFinder(int m_matchWindow);
0034     virtual ~TransactionMatchFinder();
0035 
0036     /** Searches for a matching transaction. See derived classes to learn where the transaction is looked for.
0037      *
0038      * @param transactionToMatch the imported transaction we want to match
0039      * @param splitToMatch the split of that transaction referencing the account we import into
0040      * @return the search result. There are several possible results:
0041      *      - @ref MatchNotFound means that the imported transaction does not match any other transaction
0042      *      - @ref MatchDuplicate means that the imported transaction is a duplicate of another transaction,
0043      *      - @ref MatchImprecise means that the imported transaction matches another transaction, but the match
0044      *              is not precise (e.g. transaction dates are not equal, but within matchWindow range)
0045      *      - @ref MatchPrecise means that the imported transaction matches another transaction precisely
0046      */
0047     TransactionMatchFinder::MatchResult findMatch(const MyMoneyTransaction& transactionToMatch, const MyMoneySplit& splitToMatch);
0048 
0049     /** Returns the matched split.
0050      *
0051      * @throws MyMoneyException if no match is found
0052      */
0053     MyMoneySplit getMatchedSplit() const;
0054 
0055     /** Returns the matched transaction
0056      *
0057      * @throws MyMoneyException if no transaction was matched
0058      */
0059     MyMoneyTransaction getMatchedTransaction() const;
0060 
0061     /** Returns the matched schedule
0062      *
0063      * @throws MyMoneyException if no schedule was matched
0064      */
0065     MyMoneySchedule getMatchedSchedule() const;
0066 
0067 protected:
0068     int                                m_matchWindow;
0069 
0070     MyMoneyTransaction                 importedTransaction;    //!< the imported transaction that is being matched
0071     MyMoneySplit                       m_importedSplit;          //!< the imported transaction's split that is being matched
0072 
0073     MatchResult                        matchResult;            //!< match result
0074     QScopedPointer<MyMoneyTransaction> matchedTransaction;     //!< the transaction that matches the imported one
0075     QScopedPointer<MyMoneySchedule>    matchedSchedule;        //!< the schedule that matches the imported transaction
0076     QScopedPointer<MyMoneySplit>       matchedSplit;           //!< the split that matches the imported one
0077 
0078     /** Prepares a list of match candidates for further processing, must be implemented in subclass
0079      */
0080     virtual void createListOfMatchCandidates() = 0;
0081 
0082     /** Searches the list of match candidates for a real match, must be implemented in subclass
0083      */
0084     virtual void findMatchInMatchCandidatesList() = 0;
0085 
0086     /** Checks whether one split is a duplicate of the other
0087      * @param split1 the first split
0088      * @param split2 the second split
0089      * @param amountVariation the max number of percent the amounts may differ and still be considered matching
0090      * @return true, if split2 is a duplicate of split1 (and vice-versa); false otherwise
0091      *
0092      * Splits are considered duplicates if both have the same (non-empty) bankId assigned and same amounts.
0093      */
0094     bool splitsAreDuplicates(const MyMoneySplit & split1, const MyMoneySplit & split2, int amountVariation = 0) const;
0095 
0096     /** Checks whether one split matches the other
0097      * @param importedSplit the split being imported
0098      * @param existingSplit the existing split
0099      * @param amountVariation the max number of percent the amounts may differ and still be considered matching
0100      * @return true, if importedSplit matches existingSplit (not necessarily the other way around); false otherwise
0101      *
0102      * Splits are considered a match if both of them:
0103      * - reference the same account
0104      * - have matching bankID-s
0105      * - have matching amounts
0106      * - have empty or matching payees
0107      * - are not marked as matched already
0108      */
0109     bool splitsMatch(const MyMoneySplit & m_importedSplit, const MyMoneySplit & existingSplit, int amountVariation = 0) const;
0110 
0111     /** Checks whether splits reference the same account
0112      * @param split1 the first split
0113      * @param split2 the second split
0114      * @return true, if the same account is referenced by the splits; false otherwise
0115      */
0116     bool splitsAccountsMatch(const MyMoneySplit & split1, const MyMoneySplit & split2) const;
0117 
0118     /** Checks whether splits amounts match
0119      * @param split1 the first split
0120      * @param split2 the second split
0121      * @param amountVariation the max number of percent the amounts may differ and still be considered matching
0122      * @return true, if amounts match; false otherwise
0123      */
0124     bool splitsAmountsMatch(const MyMoneySplit & split1, const MyMoneySplit & split2, int amountVariation = 0) const;
0125 
0126     /** Checks whether the splits' bankId-s match
0127      * @param importedSplit the imported split
0128      * @param existingSplit the existing split
0129      * @return true, if bank ids match; false otherwise
0130      *
0131      * BankID-s match if any of the two occurs:
0132      * - they are equal
0133      * - bankId of existing split is empty
0134      */
0135     bool splitsBankIdsMatch(const MyMoneySplit & m_importedSplit, const MyMoneySplit & existingSplit) const;
0136 
0137     /** Checks whether the splits' bankId-s are duplicated
0138      * @param split1 the first split
0139      * @param split2 the second split
0140      * @return true, if bank ids are equal and non-empty; false otherwise
0141      */
0142     bool splitsBankIdsDuplicated(const MyMoneySplit & split1, const MyMoneySplit & split2) const;
0143 
0144     /** Checks whether payees of both splits match each other or at least one of them is empty
0145      * @param split1 the first split
0146      * @param split2 the second split
0147      * @return true, if splits reference the same payee or at least one payee is empty; false otherwise
0148      */
0149     bool splitsPayeesMatchOrEmpty(const MyMoneySplit & split1, const MyMoneySplit & split2) const;
0150 
0151     /** Searches for a split in the transaction which matches imported transaction's split
0152      * @param transaction the transaction to look for the split in
0153      * @param amountVariation the max number of percent the split amounts may differ and still be considered matching
0154      */
0155     void findMatchingSplit(const MyMoneyTransaction & transaction, int amountVariation);
0156 };
0157 
0158 #endif // TRANSACTIONMATCHFINDER_H