File indexing completed on 2024-05-12 16:42:43
0001 /* 0002 SPDX-FileCopyrightText: 2003-2019 Thomas Baumgart <tbaumgart@kde.org> 0003 SPDX-FileCopyrightText: 2004 Ace Jones <acejones@users.sourceforge.net> 0004 SPDX-FileCopyrightText: 2008-2010 Alvaro Soliverez <asoliverez@gmail.com> 0005 SPDX-FileCopyrightText: 2017-2018 Łukasz Wojniłowicz <lukasz.wojnilowicz@gmail.com> 0006 SPDX-License-Identifier: GPL-2.0-or-later 0007 */ 0008 0009 #ifndef MYMONEYTRANSACTIONFILTER_H 0010 #define MYMONEYTRANSACTIONFILTER_H 0011 0012 #include "kmm_mymoney_export.h" 0013 0014 // ---------------------------------------------------------------------------- 0015 // QT Includes 0016 0017 #include <QMetaType> 0018 0019 // ---------------------------------------------------------------------------- 0020 // KDE Includes 0021 0022 // ---------------------------------------------------------------------------- 0023 // Project Includes 0024 0025 class QString; 0026 class QDate; 0027 0028 template <typename T> class QList; 0029 0030 class MyMoneyMoney; 0031 class MyMoneySplit; 0032 class MyMoneyAccount; 0033 0034 namespace eMyMoney { 0035 namespace TransactionFilter { 0036 enum class Date; 0037 enum class Validity; 0038 } 0039 } 0040 0041 /** 0042 * @author Thomas Baumgart 0043 * @author Łukasz Wojniłowicz 0044 */ 0045 0046 class MyMoneyTransaction; 0047 class MyMoneyTransactionFilterPrivate; 0048 class KMM_MYMONEY_EXPORT MyMoneyTransactionFilter 0049 { 0050 Q_DECLARE_PRIVATE(MyMoneyTransactionFilter) 0051 0052 protected: 0053 MyMoneyTransactionFilterPrivate* d_ptr; // name shouldn't colide with the one in mymoneyreport.h 0054 0055 public: 0056 enum FilterFlags { 0057 textFilterActive = 0x0001, 0058 accountFilterActive = 0x0002, 0059 payeeFilterActive = 0x0004, 0060 tagFilterActive = 0x0008, 0061 categoryFilterActive = 0x0010, 0062 nrFilterActive = 0x0020, 0063 dateFilterActive = 0x0040, 0064 amountFilterActive = 0x0080, 0065 typeFilterActive = 0x0100, 0066 stateFilterActive = 0x0200, 0067 validityFilterActive = 0x0400 0068 }; 0069 Q_DECLARE_FLAGS(FilterSet, FilterFlags) 0070 0071 /** 0072 * This is the standard constructor for a transaction filter. 0073 * It creates the object and calls setReportAllSplits() to 0074 * report all matching splits as separate entries. Use 0075 * setReportAllSplits() to override this behaviour. 0076 */ 0077 MyMoneyTransactionFilter(); 0078 0079 /** 0080 * This is a convenience constructor to allow construction of 0081 * a simple account filter. It is basically the same as the 0082 * following: 0083 * 0084 * @code 0085 * : 0086 * MyMoneyTransactionFilter filter; 0087 * filter.setReportAllSplits(false); 0088 * filter.addAccount(id); 0089 * : 0090 * @endcode 0091 * 0092 * @param id reference to account id 0093 */ 0094 explicit MyMoneyTransactionFilter(const QString& id); 0095 0096 MyMoneyTransactionFilter(const MyMoneyTransactionFilter & other); 0097 MyMoneyTransactionFilter(MyMoneyTransactionFilter && other); 0098 MyMoneyTransactionFilter & operator=(MyMoneyTransactionFilter other); 0099 friend void swap(MyMoneyTransactionFilter& first, MyMoneyTransactionFilter& second); 0100 0101 virtual ~MyMoneyTransactionFilter(); 0102 0103 /** 0104 * This method is used to clear the filter. All settings will be 0105 * removed. 0106 */ 0107 void clear(); 0108 0109 /** 0110 * This method is used to clear the accounts filter only. 0111 */ 0112 void clearAccountFilter(); 0113 0114 /** 0115 * This method is used to set the regular expression filter to the value specified 0116 * as parameter @p exp. The following text based fields are searched: 0117 * 0118 * - Memo 0119 * - Payee 0120 * - Tag 0121 * - Category 0122 * - Shares / Value 0123 * - Number 0124 * 0125 * @param exp The regular expression that must be found in a transaction 0126 * before it is included in the result set. 0127 * @param invert If true, value must not be contained in any of the above mentioned fields 0128 * 0129 */ 0130 void setTextFilter(const QRegExp& exp, bool invert = false); 0131 0132 /** 0133 * This method will add the account with id @p id to the list of matching accounts. 0134 * If the list is empty, any transaction will match. 0135 * 0136 * @param id internal ID of the account 0137 */ 0138 void addAccount(const QString& id); 0139 0140 /** 0141 * This is a convenience method and behaves exactly like the above 0142 * method but for a list of id's. 0143 */ 0144 void addAccount(const QStringList& ids); 0145 0146 /** 0147 * This method will add the category with id @p id to the list of matching categories. 0148 * If the list is empty, only transaction with a single asset/liability account will match. 0149 * 0150 * @param id internal ID of the account 0151 */ 0152 void addCategory(const QString& id); 0153 0154 /** 0155 * This is a convenience method and behaves exactly like the above 0156 * method but for a list of id's. 0157 */ 0158 void addCategory(const QStringList& ids); 0159 0160 /** 0161 * This method sets the date filter to match only transactions with posting dates in 0162 * the date range specified by @p from and @p to. If @p from equal QDate() 0163 * all transactions with dates prior to @p to match. If @p to equals QDate() 0164 * all transactions with posting dates past @p from match. If @p from and @p to 0165 * are equal QDate() the filter is not activated and all transactions match. 0166 * 0167 * @param from from date 0168 * @param to to date 0169 */ 0170 void setDateFilter(const QDate& from, const QDate& to); 0171 0172 void setDateFilter(eMyMoney::TransactionFilter::Date range); 0173 0174 /** 0175 * This method sets the amount filter to match only transactions with 0176 * an amount in the range specified by @p from and @p to. 0177 * If a specific amount should be searched, @p from and @p to should be 0178 * the same value. 0179 * 0180 * @param from smallest value to match 0181 * @param to largest value to match 0182 */ 0183 void setAmountFilter(const MyMoneyMoney& from, const MyMoneyMoney& to); 0184 0185 /** 0186 * This method will add the payee with id @p id to the list of matching payees. 0187 * If the list is empty, any transaction will match. 0188 * 0189 * @param id internal id of the payee 0190 */ 0191 void addPayee(const QString& id); 0192 0193 /** 0194 * This method will add the tag with id @ta id to the list of matching tags. 0195 * If the list is empty, any transaction will match. 0196 * 0197 * @param id internal id of the tag 0198 */ 0199 void addTag(const QString& id); 0200 0201 /** 0202 */ 0203 void addType(const int type); 0204 0205 /** 0206 */ 0207 void addValidity(const int type); 0208 0209 /** 0210 */ 0211 void addState(const int state); 0212 0213 /** 0214 * This method sets the number filter to match only transactions with 0215 * a number in the range specified by @p from and @p to. 0216 * If a specific number should be searched, @p from and @p to should be 0217 * the same value. 0218 * 0219 * @param from smallest value to match 0220 * @param to largest value to match 0221 * 0222 * @note @p from and @p to can contain alphanumeric text 0223 */ 0224 void setNumberFilter(const QString& from, const QString& to); 0225 0226 /** 0227 * This method is used to check a specific transaction against the filter. 0228 * The transaction will match the whole filter, if all specified filters 0229 * match. If the filter is cleared using the clear() method, any transaction 0230 * matches. Matching splits from the transaction are returned by @ref 0231 * matchingSplits(). 0232 * 0233 * @param transaction A transaction 0234 * 0235 * @retval true The transaction matches the filter set 0236 * @retval false The transaction does not match at least one of 0237 * the filters in the filter set 0238 */ 0239 bool match(const MyMoneyTransaction& transaction); 0240 0241 /** 0242 * This method is used to check a specific split against the 0243 * text filter. The split will match if all specified and 0244 * checked filters match. If the filter is cleared using the clear() 0245 * method, any split matches. 0246 * 0247 * @param sp pointer to the split to be checked 0248 * 0249 * @retval true The split matches the filter set 0250 * @retval false The split does not match at least one of 0251 * the filters in the filter set 0252 */ 0253 bool matchText(const MyMoneySplit& s, const MyMoneyAccount &acc) const; 0254 0255 /** 0256 * This method is used to check a specific split against the 0257 * amount filter. The split will match if all specified and 0258 * checked filters match. If the filter is cleared using the clear() 0259 * method, any split matches. 0260 * 0261 * @param sp const reference to the split to be checked 0262 * 0263 * @retval true The split matches the filter set 0264 * @retval false The split does not match at least one of 0265 * the filters in the filter set 0266 */ 0267 bool matchAmount(const MyMoneySplit& s) const; 0268 0269 /** 0270 * Convenience method which actually returns matchText(sp) && matchAmount(sp). 0271 */ 0272 bool match(const MyMoneySplit& s) const; 0273 0274 /** 0275 * This method is used to switch the amount of splits reported 0276 * by matchingSplits(). If the argument @p report is @p true (the default 0277 * if no argument specified) then matchingSplits() will return all 0278 * matching splits of the transaction. If @p report is set to @p false, 0279 * then only the very first matching split will be returned by 0280 * matchingSplits(). 0281 * 0282 * @param report controls the behaviour of matchingsSplits() as explained above. 0283 */ 0284 void setReportAllSplits(const bool report = true); 0285 0286 /** 0287 * Consider splits in categories 0288 * 0289 * With this setting, splits in categories that are not considered 0290 * by default are taken into account. 0291 * 0292 * @param check check state 0293 */ 0294 void setConsiderCategorySplits(const bool check = true); 0295 0296 /** 0297 * Consider income and expense categories 0298 * 0299 * If the account or category filter is enabled, categories of 0300 * income and expense type are included if enabled with this 0301 * method. 0302 * 0303 * @param check check state 0304 */ 0305 void setConsiderCategory(const bool check = true); 0306 0307 void setTreatTransfersAsIncomeExpense(const bool check = true); 0308 0309 /** 0310 * This method is to avoid returning matching splits list 0311 * if only its count is needed 0312 * @return count of matching splits 0313 */ 0314 uint matchingSplitsCount(const MyMoneyTransaction& transaction); 0315 0316 /** 0317 * This method returns a list of the matching splits for the filter. 0318 * If m_reportAllSplits is set to false, then only the very first 0319 * split will be returned. Use setReportAllSplits() to change the 0320 * behaviour. 0321 * 0322 * @return reference list of MyMoneySplit objects containing the 0323 * matching splits. If multiple splits match, only the first 0324 * one will be returned. 0325 * 0326 * @note an empty list will be returned, if the filter only required 0327 * to check the data contained in the MyMoneyTransaction 0328 * object (e.g. posting-date, state, etc.). 0329 * 0330 * @note The constructors set m_reportAllSplits differently. Please 0331 * see the documentation of the constructors MyMoneyTransactionFilter() 0332 * and MyMoneyTransactionFilter(const QString&) for details. 0333 */ 0334 QVector<MyMoneySplit> matchingSplits(const MyMoneyTransaction& transaction); 0335 0336 /** 0337 * This method returns the from date set in the filter. If 0338 * no value has been set up for this filter, then QDate() is 0339 * returned. 0340 * 0341 * @return returns m_fromDate 0342 */ 0343 QDate fromDate() const; 0344 0345 /** 0346 * This method returns the to date set in the filter. If 0347 * no value has been set up for this filter, then QDate() is 0348 * returned. 0349 * 0350 * @return returns m_toDate 0351 */ 0352 QDate toDate() const; 0353 0354 /** 0355 * This method is used to return information about the 0356 * presence of a specific category in the category filter. 0357 * The category in question is included in the filter set, 0358 * if it has been set or no category filter is set. 0359 * 0360 * @param cat id of category in question 0361 * @return true if category is in filter set, false otherwise 0362 */ 0363 bool includesCategory(const QString& cat) const; 0364 0365 /** 0366 * This method is used to return information about the 0367 * presence of a specific account in the account filter. 0368 * The account in question is included in the filter set, 0369 * if it has been set or no account filter is set. 0370 * 0371 * @param acc id of account in question 0372 * @return true if account is in filter set, false otherwise 0373 */ 0374 bool includesAccount(const QString& acc) const; 0375 0376 /** 0377 * This method is used to return information about the 0378 * presence of a specific payee in the account filter. 0379 * The payee in question is included in the filter set, 0380 * if it has been set or no account filter is set. 0381 * 0382 * @param pye id of payee in question 0383 * @return true if payee is in filter set, false otherwise 0384 */ 0385 bool includesPayee(const QString& pye) const; 0386 0387 /** 0388 * This method is used to return information about the 0389 * presence of a specific tag in the account filter. 0390 * The tag in question is included in the filter set, 0391 * if it has been set or no account filter is set. 0392 * 0393 * @param tag id of tag in question 0394 * @return true if tag is in filter set, false otherwise 0395 */ 0396 bool includesTag(const QString& tag) const; 0397 0398 /** 0399 * This method is used to return information about the 0400 * presence of a date filter. 0401 * 0402 * @param from result value for the beginning of the date range 0403 * @param to result value for the end of the date range 0404 * @return true if a date filter is set 0405 */ 0406 bool dateFilter(QDate& from, QDate& to) const; 0407 0408 /** 0409 * This method is used to return information about the 0410 * presence of an amount filter. 0411 * 0412 * @param from result value for the low end of the amount range 0413 * @param to result value for the high end of the amount range 0414 * @return true if an amount filter is set 0415 */ 0416 bool amountFilter(MyMoneyMoney& from, MyMoneyMoney& to) const; 0417 0418 /** 0419 * This method is used to return information about the 0420 * presence of an number filter. 0421 * 0422 * @param from result value for the low end of the number range 0423 * @param to result value for the high end of the number range 0424 * @return true if a number filter is set 0425 */ 0426 bool numberFilter(QString& from, QString& to) const; 0427 0428 /** 0429 * This method returns whether a payee filter has been set, 0430 * and if so, it returns all the payees set in the filter. 0431 * 0432 * @param list list to append payees into 0433 * @return return true if a payee filter has been set 0434 */ 0435 bool payees(QStringList& list) const; 0436 0437 /** 0438 * This method returns whether a tag filter has been set, 0439 * and if so, it returns all the tags set in the filter. 0440 * 0441 * @param list list to append tags into 0442 * @return return true if a tag filter has been set 0443 */ 0444 bool tags(QStringList& list) const; 0445 0446 /** 0447 * This method returns whether an account filter has been set, 0448 * and if so, it returns all the accounts set in the filter. 0449 * 0450 * @param list list to append accounts into 0451 * @return return true if an account filter has been set 0452 */ 0453 bool accounts(QStringList& list) const; 0454 0455 /** 0456 * This method returns whether a category filter has been set, 0457 * and if so, it returns all the categories set in the filter. 0458 * 0459 * @param list list to append categories into 0460 * @return return true if a category filter has been set 0461 */ 0462 bool categories(QStringList& list) const; 0463 0464 /** 0465 * This method returns whether a type filter has been set, 0466 * and if so, it returns the first type in the filter. 0467 * 0468 * @param i int to replace with first type filter, untouched otherwise 0469 * @return return true if a type filter has been set 0470 */ 0471 bool firstType(int& i) const; 0472 0473 bool types(QList<int>& list) const; 0474 0475 /** 0476 * This method returns whether a state filter has been set, 0477 * and if so, it returns the first state in the filter. 0478 * 0479 * @param i reference to int to replace with first state filter, untouched otherwise 0480 * @return return true if a state filter has been set 0481 */ 0482 bool firstState(int& i) const; 0483 0484 bool states(QList<int>& list) const; 0485 0486 /** 0487 * This method returns whether a validity filter has been set, 0488 * and if so, it returns the first validity in the filter. 0489 * 0490 * @param i reference to int to replace with first validity filter, untouched otherwise 0491 * @return return true if a validity filter has been set 0492 */ 0493 bool firstValidity(int& i) const; 0494 0495 bool validities(QList<int>& list) const; 0496 0497 /** 0498 * This method returns whether a text filter has been set, 0499 * and if so, it returns the text filter. 0500 * 0501 * @param text regexp to replace with text filter, or blank if none set 0502 * @return return true if a text filter has been set 0503 */ 0504 bool textFilter(QRegExp& text) const; 0505 0506 /** 0507 * This method returns whether the text filter should return 0508 * that DO NOT contain the text 0509 */ 0510 bool isInvertingText() const; 0511 0512 /** 0513 * This method returns whether transfers should be treated as 0514 * income/expense transactions or not 0515 */ 0516 bool treatTransfersAsIncomeExpense() const; 0517 0518 /** 0519 * This method translates a plain-language date range into QDate 0520 * start & end 0521 * 0522 * @param range Plain-language range of dates, e.g. 'CurrentYear' 0523 * @param start QDate will be set to corresponding to the first date in @p range 0524 * @param end QDate will be set to corresponding to the last date in @p range 0525 * @return return true if a range was successfully set, or false if @p range was invalid 0526 */ 0527 static bool translateDateRange(eMyMoney::TransactionFilter::Date range, QDate& start, QDate& end); 0528 0529 static void setFiscalYearStart(int firstMonth, int firstDay); 0530 0531 FilterSet filterSet() const; 0532 0533 /** 0534 * This member removes all references to object identified by @p id. Used 0535 * to remove objects which are about to be removed from the engine. 0536 */ 0537 void removeReference(const QString& id); 0538 0539 private: 0540 /** 0541 * This is a conversion tool from eMyMoney::Split::State 0542 * to MyMoneyTransactionFilter::stateE types 0543 * 0544 * @param split reference to split in question 0545 * 0546 * @return converted reconcile flag of the split passed as parameter 0547 */ 0548 int splitState(const MyMoneySplit& split) const; 0549 0550 /** 0551 * This is a conversion tool from MyMoneySplit::action 0552 * to MyMoneyTransactionFilter::typeE types 0553 * 0554 * @param t reference to transaction 0555 * @param split reference to split in question 0556 * 0557 * @return converted action of the split passed as parameter 0558 */ 0559 int splitType(const MyMoneyTransaction& t, const MyMoneySplit& split, const MyMoneyAccount &acc) const; 0560 0561 /** 0562 * This method checks if a transaction is valid or not. A transaction 0563 * is considered valid, if the sum of all splits is zero, invalid otherwise. 0564 * 0565 * @param transaction reference to transaction to be checked 0566 * @retval valid transaction is valid 0567 * @retval invalid transaction is invalid 0568 */ 0569 eMyMoney::TransactionFilter::Validity validTransaction(const MyMoneyTransaction& transaction) const; 0570 }; 0571 0572 inline void swap(MyMoneyTransactionFilter& first, MyMoneyTransactionFilter& second) // krazy:exclude=inline 0573 { 0574 using std::swap; 0575 swap(first.d_ptr, second.d_ptr); 0576 } 0577 0578 inline MyMoneyTransactionFilter::MyMoneyTransactionFilter(MyMoneyTransactionFilter && other) : MyMoneyTransactionFilter() // krazy:exclude=inline 0579 { 0580 swap(*this, other); 0581 } 0582 0583 inline MyMoneyTransactionFilter & MyMoneyTransactionFilter::operator=(MyMoneyTransactionFilter other) // krazy:exclude=inline 0584 { 0585 swap(*this, other); 0586 return *this; 0587 } 0588 0589 /** 0590 * Make it possible to hold @ref MyMoneyTransactionFilter objects inside @ref QVariant objects. 0591 */ 0592 Q_DECLARE_METATYPE(MyMoneyTransactionFilter) 0593 Q_DECLARE_OPERATORS_FOR_FLAGS(MyMoneyTransactionFilter::FilterSet) 0594 0595 #endif