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