File indexing completed on 2024-05-19 16:15:30
0001 /* 0002 SPDX-FileCopyrightText: 2000-2004 Michael Edwardes <mte@users.sourceforge.net> 0003 SPDX-FileCopyrightText: 2002-2018 Thomas Baumgart <tbaumgart@kde.org> 0004 SPDX-FileCopyrightText: 2005 Ace Jones <acejones@users.sourceforge.net> 0005 SPDX-License-Identifier: GPL-2.0-or-later 0006 */ 0007 0008 #ifndef MYMONEYSCHEDULE_H 0009 #define MYMONEYSCHEDULE_H 0010 0011 // ---------------------------------------------------------------------------- 0012 // QT Includes 0013 0014 #include <QMetaType> 0015 0016 // ---------------------------------------------------------------------------- 0017 // Project Includes 0018 0019 #include "kmm_mymoney_export.h" 0020 #include "mymoneyunittestable.h" 0021 #include "mymoneyobject.h" 0022 0023 class QString; 0024 class QDate; 0025 0026 class IMyMoneyProcessingCalendar; 0027 class MyMoneyAccount; 0028 class MyMoneyTransaction; 0029 0030 namespace eMyMoney { 0031 namespace Schedule { 0032 enum class Type; 0033 enum class Occurrence; 0034 enum class PaymentType; 0035 enum class WeekendOption; 0036 } 0037 } 0038 0039 template <typename T> class QList; 0040 0041 /** 0042 * @author Michael Edwardes 0043 */ 0044 0045 /** 0046 * This class represents a schedule. (A series of bills, deposits or 0047 * transfers). 0048 * 0049 * @short A class to represent a schedule. 0050 * @see MyMoneyScheduled 0051 */ 0052 class MyMoneySchedulePrivate; 0053 class KMM_MYMONEY_EXPORT MyMoneySchedule : public MyMoneyObject 0054 { 0055 Q_DECLARE_PRIVATE(MyMoneySchedule) 0056 0057 friend class MyMoneyStorageANON; 0058 KMM_MYMONEY_UNIT_TESTABLE 0059 0060 public: 0061 /** 0062 * Standard constructor 0063 */ 0064 MyMoneySchedule(); 0065 explicit MyMoneySchedule(const QString &id); 0066 0067 /** 0068 * Constructor for initialising the object. 0069 * 0070 * Please note that the optional fields are not set and the transaction 0071 * MUST be set before it can be used. 0072 * 0073 * @a startDate is not used anymore and internally set to QDate() 0074 */ 0075 explicit MyMoneySchedule(const QString& name, 0076 eMyMoney::Schedule::Type type, 0077 eMyMoney::Schedule::Occurrence occurrence, 0078 int occurrenceMultiplier, 0079 eMyMoney::Schedule::PaymentType paymentType, 0080 const QDate& startDate, 0081 const QDate& endDate, 0082 bool fixed, 0083 bool autoEnter); 0084 0085 MyMoneySchedule(const QString& id, 0086 const MyMoneySchedule& other); 0087 0088 MyMoneySchedule(const MyMoneySchedule & other); 0089 MyMoneySchedule(MyMoneySchedule && other); 0090 MyMoneySchedule & operator=(MyMoneySchedule other); 0091 friend void swap(MyMoneySchedule& first, MyMoneySchedule& second); 0092 0093 /** 0094 * Standard destructor 0095 */ 0096 ~MyMoneySchedule(); 0097 0098 /** 0099 * Simple get method that returns the base occurrence frequency. 0100 * 0101 * @return eMyMoney::Schedule::Occurrence The instance frequency 0102 * reduced to the simple units. 0103 */ 0104 eMyMoney::Schedule::Occurrence baseOccurrence() const; 0105 0106 /** 0107 * Simple get method that returns the occurrence period 0108 * multiplier and occurrence 0109 * 0110 * @return eMyMoney::Schedule::Occurrence The instance period 0111 * 0112 */ 0113 eMyMoney::Schedule::Occurrence occurrence() const; 0114 0115 /** 0116 * Simple get method that returns the occurrence period multiplier. 0117 * 0118 * @return int The frequency multiplier 0119 */ 0120 int occurrenceMultiplier() const; 0121 0122 /** 0123 * Simple get method that returns the schedule type. 0124 * 0125 * @return eMyMoney::Schedule::Type The instance type. 0126 */ 0127 eMyMoney::Schedule::Type type() const; 0128 0129 /** 0130 * Simple get method that returns the schedule startDate. If 0131 * the schedule has been executed once, the date of the first 0132 * execution is returned. Otherwise, the next due date is 0133 * returned. 0134 * 0135 * @return reference to QDate containing the start date. 0136 */ 0137 QDate startDate() const; 0138 0139 /** 0140 * Simple get method that returns the schedule paymentType. 0141 * 0142 * @return eMyMoney::Schedule::PaymentType The instance paymentType. 0143 */ 0144 eMyMoney::Schedule::PaymentType paymentType() const; 0145 0146 /** 0147 * Simple get method that returns true if the schedule is fixed. 0148 * 0149 * @return bool To indicate whether the instance is fixed. 0150 */ 0151 bool isFixed() const; 0152 0153 /** 0154 * Simple get method that returns true if the schedule will end 0155 * at some time. 0156 * 0157 * @return bool Indicates whether the instance will end. 0158 */ 0159 bool willEnd() const; 0160 0161 /** 0162 * Simple get method that returns the number of transactions remaining. 0163 * 0164 * @return int The number of transactions remaining for the instance. 0165 */ 0166 int transactionsRemaining() const; 0167 0168 /** 0169 * Simple method that returns the number of transactions remaining 0170 * until a given date. 0171 * 0172 * @param endDate Date to count transactions to. 0173 * @return int The number of transactions remaining for the instance. 0174 */ 0175 int transactionsRemainingUntil(const QDate& endDate) const; 0176 0177 /** 0178 * Simple get method that returns the schedule end date. 0179 * 0180 * @return QDate The end date for the instance. 0181 */ 0182 QDate endDate() const; 0183 0184 /** 0185 * Get the state if the schedule should be processed at the last day 0186 * of a month 0187 * 0188 * @return state of the flag 0189 */ 0190 bool lastDayInMonth() const; 0191 0192 /** 0193 * Simple get method that returns true if the transaction should be 0194 * automatically entered into the register. 0195 * 0196 * @return bool Indicates whether the instance will be automatically entered. 0197 */ 0198 bool autoEnter() const; 0199 0200 /** 0201 * Simple get method that returns the transaction data for the schedule. 0202 * 0203 * @return MyMoneyTransaction The transaction data for the instance. 0204 */ 0205 MyMoneyTransaction transaction() const; 0206 0207 /** 0208 * Simple method that sets the transaction for the schedule. 0209 * The transaction must have a valid postDate set, otherwise 0210 * it will not be accepted. This test is bypassed, if @a noDateCheck 0211 * is set to true 0212 * 0213 * @param transaction The new transaction. 0214 * @param noDateCheck if @a true, the date check is bypassed 0215 * @return none 0216 */ 0217 void setTransaction(const MyMoneyTransaction& transaction, bool noDateCheck); 0218 0219 /** 0220 * Simple method that returns the schedules last payment. If the 0221 * schedule has never been executed, QDate() will be returned. 0222 * 0223 * @return QDate The last payment for the schedule. 0224 */ 0225 QDate lastPayment() const; 0226 0227 /** 0228 * Simple method that returns the next due date for the schedule. 0229 * 0230 * @return reference to QDate containing the next due date. 0231 * 0232 * @note The date returned can represent a value that is past 0233 * a possible end of the schedule. Make sure to consider 0234 * the return value of isFinished() when using the value returned. 0235 */ 0236 QDate nextDueDate() const; 0237 0238 /** 0239 * This method returns the next due date adjusted 0240 * according to the rules specified by the schedule's weekend option. 0241 * 0242 * @return QDate containing the adjusted next due date. If the 0243 * schedule is finished (@sa isFinished()) then the method 0244 * returns an invalid QDate. 0245 * 0246 * @sa weekendOption() 0247 * @sa adjustedDate() 0248 */ 0249 QDate adjustedNextDueDate() const; 0250 0251 /** 0252 * This method adjusts returns the date adjusted according to the 0253 * rules specified by the schedule's weekend option. 0254 * 0255 * @return QDate containing the adjusted date. 0256 */ 0257 QDate adjustedDate(QDate date, eMyMoney::Schedule::WeekendOption option) const; 0258 0259 /** 0260 0261 * Get the weekendOption that determines how the schedule check code 0262 * will enter transactions that occur on a non-processing day (usually 0263 * a weekend). 0264 * 0265 * This not used by MyMoneySchedule but by the support code. 0266 **/ 0267 eMyMoney::Schedule::WeekendOption weekendOption() const; 0268 0269 /** 0270 * Simple method that sets the frequency for the schedule. 0271 * 0272 * @param occ The new occurrence (frequency). 0273 * @return none 0274 */ 0275 void setOccurrence(eMyMoney::Schedule::Occurrence occ); 0276 0277 /** 0278 * Simple method that sets the schedule period 0279 * 0280 * @param occ The new occurrence period (frequency) 0281 * @return none 0282 */ 0283 void setOccurrencePeriod(eMyMoney::Schedule::Occurrence occ); 0284 0285 /** 0286 * Simple method that sets the frequency multiplier for the schedule. 0287 * 0288 * @param occmultiplier The new occurrence (frequency) multiplier. 0289 * @return none 0290 */ 0291 void setOccurrenceMultiplier(int occmultiplier); 0292 0293 /** 0294 * Simple method that sets the type for the schedule. 0295 * 0296 * @param type The new type. 0297 * @return none 0298 */ 0299 void setType(eMyMoney::Schedule::Type type); 0300 0301 /** 0302 * Simple method that sets the start date for the schedule. 0303 * 0304 * @param date The new start date. 0305 * @return none 0306 */ 0307 void setStartDate(const QDate& date); 0308 0309 /** 0310 * Simple method that sets the payment type for the schedule. 0311 * 0312 * @param type The new payment type. 0313 * @return none 0314 */ 0315 void setPaymentType(eMyMoney::Schedule::PaymentType type); 0316 0317 /** 0318 * Simple method to set whether the schedule is fixed or not. 0319 * 0320 * @param fixed boolean to indicate whether the instance is fixed. 0321 * @return none 0322 */ 0323 void setFixed(bool fixed); 0324 0325 /** 0326 * Simple method that sets the transaction for the schedule. 0327 * The transaction must have a valid postDate set, otherwise 0328 * it will not be accepted. 0329 * 0330 * @param transaction The new transaction. 0331 * @return none 0332 */ 0333 void setTransaction(const MyMoneyTransaction& transaction); 0334 0335 /** 0336 * Simple set method to set the end date for the schedule. 0337 * 0338 * @param date The new end date. 0339 * @return none 0340 */ 0341 void setEndDate(const QDate& date); 0342 0343 /** 0344 * Simple method to set whether the schedule should be performed at 0345 * the last day of a month. 0346 * 0347 * @param state boolean The state to set 0348 * @return none 0349 */ 0350 void setLastDayInMonth(bool state); 0351 0352 /** 0353 * Simple set method to set whether this transaction should be automatically 0354 * entered into the journal whenever it is due. 0355 * 0356 * @param autoenter boolean to indicate whether we need to automatically 0357 * enter the transaction. 0358 * @return none 0359 */ 0360 void setAutoEnter(bool autoenter); 0361 0362 /** 0363 * Simple set method to set the schedule's next payment date. 0364 * 0365 * @param date The next payment date. 0366 * @return none 0367 */ 0368 void setNextDueDate(const QDate& date); 0369 0370 /** 0371 * Simple set method to set the schedule's last payment. If 0372 * this method is called for the first time on the object, 0373 * the @a m_startDate member will be set to @a date as well. 0374 * 0375 * This method should be called whenever a schedule is entered or skipped. 0376 * 0377 * @param date The last payment date. 0378 * @return none 0379 */ 0380 void setLastPayment(const QDate& date); 0381 0382 /** 0383 * Set the weekendOption that determines how the schedule check code 0384 * will enter transactions that occur on a non-processing day (usually 0385 * a weekend). The following values 0386 * are valid: 0387 * 0388 * - MoveNothing: don't modify date 0389 * - MoveBefore: modify the date to the previous processing day 0390 * - MoveAfter: modify the date to the next processing day 0391 * 0392 * If an invalid option is given, the option is set to MoveNothing. 0393 * 0394 * @param option See list in description 0395 * @return none 0396 * 0397 * @note This not used by MyMoneySchedule but by the support code. 0398 **/ 0399 void setWeekendOption(const eMyMoney::Schedule::WeekendOption option); 0400 0401 /** 0402 * Validates the schedule instance. 0403 * 0404 * Makes sure the paymentType matches the type and that the required 0405 * fields have been set. 0406 * 0407 * @param id_check if @p true, the method will check for an empty id. 0408 * if @p false, this check is skipped. Default is @p true. 0409 * 0410 * @return If this method returns, all checks are passed. Otherwise, 0411 * it will throw a MyMoneyException object. 0412 * 0413 * @exception MyMoneyException with detailed error information is thrown 0414 * in case of failure of any check. 0415 */ 0416 void validate(bool id_check = true) const; 0417 0418 /** 0419 * Calculates the date of the next payment adjusted according to the 0420 * rules specified by the schedule's weekend option. 0421 * 0422 * @param refDate The reference date from which the next payment 0423 * date will be calculated (defaults to current date) 0424 * 0425 * @return QDate The adjusted date the next payment is due. This date is 0426 * always past @a refDate. In case of an error or if there 0427 * are no more payments then an empty/invalid QDate() will 0428 * be returned. 0429 */ 0430 QDate adjustedNextPayment(const QDate& refDate) const; 0431 QDate adjustedNextPayment() const; 0432 0433 /** 0434 * Calculates the date of the next payment. 0435 * 0436 * @param refDate The reference date from which the next payment 0437 * date will be calculated (defaults to current date) 0438 * 0439 * @return QDate The date the next payment is due. This date is 0440 * always past @a refDate. In case of an error or 0441 * if there are no more payments then an empty/invalid QDate() 0442 * will be returned. 0443 */ 0444 QDate nextPayment(const QDate& refDate) const; 0445 QDate nextPayment() const; 0446 0447 /** 0448 * Calculates the date of the next payment and adjusts if asked. 0449 * 0450 * @param adjust Whether to adjust the calculated date according to the 0451 * rules specified by the schedule's weekend option. 0452 * @param refDate The reference date from which the next payment 0453 * date will be calculated (defaults to current date) 0454 * 0455 * @return QDate The date the next payment is due. This date is 0456 * always past @a refDate. In case of an error or 0457 * if there is no more payments then an empty/invalid QDate() 0458 * will be returned. 0459 */ 0460 QDate nextPaymentDate(const bool& adjust, const QDate& refDate) const; 0461 QDate nextPaymentDate(const bool& adjust) const; 0462 0463 /** 0464 * Calculates the dates of the payment over a certain period of time. 0465 * 0466 * An empty list is returned for no payments or error. 0467 * 0468 * @param startDate The start date for the range calculations 0469 * @param endDate The end date for the range calculations. 0470 * @return QList<QDate> The dates on which the payments are due. 0471 */ 0472 QList<QDate> paymentDates(const QDate& startDate, const QDate& endDate) const; 0473 0474 /** 0475 * Returns the instances name 0476 * 0477 * @return The name 0478 */ 0479 QString name() const; 0480 0481 /** 0482 * Changes the instance name 0483 * 0484 * @param nm The new name 0485 * @return none 0486 */ 0487 void setName(const QString& nm); 0488 0489 bool operator ==(const MyMoneySchedule& right) const; 0490 bool operator !=(const MyMoneySchedule& right) const; 0491 0492 bool operator <(const MyMoneySchedule& right) const; 0493 0494 MyMoneyAccount account(int cnt = 1) const; 0495 MyMoneyAccount transferAccount() const; 0496 QDate dateAfter(int transactions) const; 0497 0498 bool isOverdue() const; 0499 bool isFinished() const; 0500 bool hasRecordedPayment(const QDate&) const; 0501 void recordPayment(const QDate&); 0502 QList<QDate> recordedPayments() const; 0503 0504 /** 0505 * This method checks if a reference to the given object exists. It returns, 0506 * a @p true if the object is referencing the one requested by the 0507 * parameter @p id. If it does not, this method returns @p false. 0508 * 0509 * @param id id of the object to be checked for references 0510 * @retval true This object references object with id @p id. 0511 * @retval false This object does not reference the object with id @p id. 0512 */ 0513 virtual bool hasReferenceTo(const QString& id) const final override; 0514 0515 /** 0516 * This method replaces all occurrences of id @a oldId with 0517 * @a newId. All other ids are not changed. 0518 * 0519 * @return true if any change has been performed 0520 * @return false if nothing has been modified 0521 */ 0522 bool replaceId(const QString& newId, const QString& oldId); 0523 0524 /** 0525 * Returns the human-readable format of Schedule's occurrence 0526 * 0527 * @return QString representing the human readable format 0528 */ 0529 QString occurrenceToString() const; 0530 0531 /** 0532 * This method is used to convert the occurrence type from its 0533 * internal representation into a human readable format. 0534 * 0535 * @param type numerical representation of the MyMoneySchedule 0536 * occurrence type 0537 * 0538 * @return QString representing the human readable format 0539 */ 0540 static QString occurrenceToString(eMyMoney::Schedule::Occurrence type); 0541 0542 /** 0543 * This method is used to convert a multiplier and base occurrence type 0544 * from its internal representation into a human readable format. 0545 * When multiplier * occurrence is equivalent to a simple occurrence 0546 * the method returns the same as occurrenceToString of the simple occurrence 0547 * 0548 * @param mult occurrence multiplier 0549 * @param type occurrence period 0550 * 0551 * @return QString representing the human readable format 0552 */ 0553 static QString occurrenceToString(int mult, eMyMoney::Schedule::Occurrence type); 0554 0555 /** 0556 * This method is used to convert an occurrence period from 0557 * its internal representation into a human-readable format. 0558 * 0559 * @param type numerical representation of the MyMoneySchedule 0560 * occurrence type 0561 * 0562 * @return QString representing the human readable format 0563 */ 0564 static QString occurrencePeriodToString(eMyMoney::Schedule::Occurrence type); 0565 0566 /** 0567 * This method is used to convert the payment type from its 0568 * internal representation into a human readable format. 0569 * 0570 * @param paymentType numerical representation of the MyMoneySchedule 0571 * payment type 0572 * 0573 * @return QString representing the human readable format 0574 */ 0575 static QString paymentMethodToString(eMyMoney::Schedule::PaymentType paymentType); 0576 0577 /** 0578 * This method is used to convert the schedule weekend option from its 0579 * internal representation into a human readable format. 0580 * 0581 * @param weekendOption numerical representation of the MyMoneySchedule 0582 * weekend option 0583 * 0584 * @return QString representing the human readable format 0585 */ 0586 static QString weekendOptionToString(eMyMoney::Schedule::WeekendOption weekendOption); 0587 0588 /** 0589 * This method is used to convert the schedule type from its 0590 * internal representation into a human readable format. 0591 * 0592 * @param type numerical representation of the MyMoneySchedule 0593 * schedule type 0594 * 0595 * @return QString representing the human readable format 0596 */ 0597 static QString scheduleTypeToString(eMyMoney::Schedule::Type type); 0598 0599 int variation() const; 0600 void setVariation(int var); 0601 0602 /** 0603 * 0604 * Convert an occurrence to the maximum number of events possible during a single 0605 * calendar year. 0606 * A fortnight is treated as 15 days. 0607 * 0608 * @param occurrence The occurrence 0609 * 0610 * @return int Number of days between events 0611 */ 0612 static int eventsPerYear(eMyMoney::Schedule::Occurrence occurrence); 0613 0614 /** 0615 * 0616 * Convert an occurrence to the number of days between events 0617 * Treats a month as 30 days. 0618 * Treats a fortnight as 15 days. 0619 * 0620 * @param occurrence The occurrence 0621 * 0622 * @return int Number of days between events 0623 */ 0624 static int daysBetweenEvents(eMyMoney::Schedule::Occurrence occurrence); 0625 0626 /** 0627 * Helper method to convert simple occurrence to compound occurrence + multiplier 0628 * 0629 * @param multiplier Returned by reference. Adjusted multiplier 0630 * @param occurrence Returned by reference. Occurrence type 0631 */ 0632 static void simpleToCompoundOccurrence(int& multiplier, eMyMoney::Schedule::Occurrence& occurrence); 0633 0634 /** 0635 * Helper method to convert compound occurrence + multiplier to simple occurrence 0636 * 0637 * @param multiplier Returned by reference. Adjusted multiplier 0638 * @param occurrence Returned by reference. Occurrence type 0639 */ 0640 static void compoundToSimpleOccurrence(int& multiplier, eMyMoney::Schedule::Occurrence& occurrence); 0641 0642 /** 0643 * This method is used to set the static point to relevant 0644 * IMyMoneyProcessingCalendar. 0645 */ 0646 static void setProcessingCalendar(IMyMoneyProcessingCalendar* pc); 0647 0648 private: 0649 /** 0650 * This method returns a pointer to the processing calendar object. 0651 * 0652 * @return const pointer to the current attached processing calendar object. 0653 * If no object is attached, returns 0. 0654 */ 0655 IMyMoneyProcessingCalendar* processingCalendar() const; 0656 0657 /** 0658 * This method forces the day of the passed @p date to 0659 * be the day of the start date of this schedule kept 0660 * in m_startDate. It is internally used when calculating 0661 * the payment dates over several periods. 0662 * 0663 * @param date reference to QDate object to be checked and adjusted 0664 */ 0665 void fixDate(QDate& date) const; 0666 0667 /** 0668 * This method adds a number of Half Months to the given Date. 0669 * This is used for EveryHalfMonth occurrences. 0670 * The addition uses the following rules to add a half month: 0671 * Day 1-13: add 15 days 0672 * Day 14: add 15 days (except February: the last day of the month) 0673 * Day 15: last day of the month 0674 * Day 16-29 (not last day in February): subtract 15 days and add 1 month 0675 * 30 and last day: 15th of next month 0676 * 0677 * This calculation pairs days 1 to 12 with 16 to 27. 0678 * Day 15 is paired with the last day of every month. 0679 * Repeated addition has issues in the following cases: 0680 * - Days 13 to 14 are paired with 28 to 29 until addition hits the last day of February 0681 * after which the (15,last) pair will be used. 0682 * - Addition from Day 30 leads immediately to the (15th,last) day pair. 0683 * 0684 * @param date The date 0685 * @param mult The number of half months to add. Default is 1. 0686 * 0687 * @return QDate date with mult half months added 0688 */ 0689 QDate addHalfMonths(QDate date, int mult = 1) const; 0690 0691 /** 0692 * Checks if a given date should be considered a processing day 0693 * based on a calendar. See @a IMyMoneyProcessingCalendar and 0694 * setProcessingCalendar(). If no processingCalendar has been 0695 * setup using setProcessingCalendar it returns @c true on Mon..Fri 0696 * and @c false on Sat..Sun. 0697 */ 0698 bool isProcessingDate(const QDate& date) const; 0699 }; 0700 0701 inline void swap(MyMoneySchedule& first, MyMoneySchedule& second) // krazy:exclude=inline 0702 { 0703 using std::swap; 0704 swap(first.d_ptr, second.d_ptr); 0705 } 0706 0707 inline MyMoneySchedule::MyMoneySchedule(MyMoneySchedule && other) : MyMoneySchedule() // krazy:exclude=inline 0708 { 0709 swap(*this, other); 0710 } 0711 0712 inline MyMoneySchedule & MyMoneySchedule::operator=(MyMoneySchedule other) // krazy:exclude=inline 0713 { 0714 swap(*this, other); 0715 return *this; 0716 } 0717 0718 /** 0719 * Make it possible to hold @ref MyMoneySchedule objects inside @ref QVariant objects. 0720 */ 0721 Q_DECLARE_METATYPE(MyMoneySchedule) 0722 0723 #endif