|
|
|
/***************************************************************************
|
|
|
|
mymoneyscheduled.cpp
|
|
|
|
-------------------
|
|
|
|
copyright : (C) 2000-2002 by Michael Edwardes
|
|
|
|
(C) 2007 by Thomas Baumgart
|
|
|
|
email : mte@users.sourceforge.net
|
|
|
|
Thomas Baumgart <ipwizard@users.sourceforge.net>
|
|
|
|
***************************************************************************/
|
|
|
|
|
|
|
|
/***************************************************************************
|
|
|
|
* *
|
|
|
|
* This program is free software; you can redistribute it and/or modify *
|
|
|
|
* it under the terms of the GNU General Public License as published by *
|
|
|
|
* the Free Software Foundation; either version 2 of the License, or *
|
|
|
|
* (at your option) any later version. *
|
|
|
|
* *
|
|
|
|
***************************************************************************/
|
|
|
|
// ----------------------------------------------------------------------------
|
|
|
|
// QT Includes
|
|
|
|
|
|
|
|
// ----------------------------------------------------------------------------
|
|
|
|
// KDE Includes
|
|
|
|
|
|
|
|
#include <tdelocale.h>
|
|
|
|
|
|
|
|
// ----------------------------------------------------------------------------
|
|
|
|
// Project Includes
|
|
|
|
|
|
|
|
#include "mymoneyscheduled.h"
|
|
|
|
#include "mymoneyexception.h"
|
|
|
|
#include "mymoneyfile.h"
|
|
|
|
|
|
|
|
MyMoneySchedule::MyMoneySchedule() :
|
|
|
|
MyMoneyObject()
|
|
|
|
{
|
|
|
|
// Set up the default values
|
|
|
|
m_occurence = OCCUR_ANY;
|
|
|
|
m_occurenceMultiplier = 1;
|
|
|
|
m_type = TYPE_ANY;
|
|
|
|
m_paymentType = STYPE_ANY;
|
|
|
|
m_fixed = false;
|
|
|
|
m_autoEnter = false;
|
|
|
|
m_startDate = TQDate();
|
|
|
|
m_endDate = TQDate();
|
|
|
|
m_lastPayment = TQDate();
|
|
|
|
m_weekendOption = MoveNothing;
|
|
|
|
}
|
|
|
|
|
|
|
|
MyMoneySchedule::MyMoneySchedule(const TQString& name, typeE type,
|
|
|
|
occurenceE occurence, int occurenceMultiplier,
|
|
|
|
paymentTypeE paymentType,
|
|
|
|
const TQDate& /* startDate */,
|
|
|
|
const TQDate& endDate,
|
|
|
|
bool fixed, bool autoEnter) :
|
|
|
|
MyMoneyObject()
|
|
|
|
{
|
|
|
|
// Set up the default values
|
|
|
|
m_name = name;
|
|
|
|
m_occurence = occurence;
|
|
|
|
m_occurenceMultiplier = occurenceMultiplier;
|
|
|
|
simpleToCompoundOccurence(m_occurenceMultiplier,m_occurence);
|
|
|
|
m_type = type;
|
|
|
|
m_paymentType = paymentType;
|
|
|
|
m_fixed = fixed;
|
|
|
|
m_autoEnter = autoEnter;
|
|
|
|
m_startDate = TQDate();
|
|
|
|
m_endDate = endDate;
|
|
|
|
m_lastPayment = TQDate();
|
|
|
|
m_weekendOption = MoveNothing;
|
|
|
|
}
|
|
|
|
|
|
|
|
MyMoneySchedule::MyMoneySchedule(const TQDomElement& node) :
|
|
|
|
MyMoneyObject(node)
|
|
|
|
{
|
|
|
|
if("SCHEDULED_TX" != node.tagName())
|
|
|
|
throw new MYMONEYEXCEPTION("Node was not SCHEDULED_TX");
|
|
|
|
|
|
|
|
m_name = node.attribute("name");
|
|
|
|
m_startDate = stringToDate(node.attribute("startDate"));
|
|
|
|
m_endDate = stringToDate(node.attribute("endDate"));
|
|
|
|
m_lastPayment = stringToDate(node.attribute("lastPayment"));
|
|
|
|
|
|
|
|
m_type = static_cast<MyMoneySchedule::typeE>(node.attribute("type").toInt());
|
|
|
|
m_paymentType = static_cast<MyMoneySchedule::paymentTypeE>(node.attribute("paymentType").toInt());
|
|
|
|
m_occurence = static_cast<MyMoneySchedule::occurenceE>(node.attribute("occurence").toInt());
|
|
|
|
m_occurenceMultiplier = node.attribute("occurenceMultiplier", "1").toInt();
|
|
|
|
// Convert to compound occurence
|
|
|
|
simpleToCompoundOccurence(m_occurenceMultiplier,m_occurence);
|
|
|
|
m_autoEnter = static_cast<bool>(node.attribute("autoEnter").toInt());
|
|
|
|
m_fixed = static_cast<bool>(node.attribute("fixed").toInt());
|
|
|
|
m_weekendOption = static_cast<MyMoneySchedule::weekendOptionE>(node.attribute("weekendOption").toInt());
|
|
|
|
|
|
|
|
// read in the associated transaction
|
|
|
|
TQDomNodeList nodeList = node.elementsByTagName("TRANSACTION");
|
|
|
|
if(nodeList.count() == 0)
|
|
|
|
throw new MYMONEYEXCEPTION("SCHEDULED_TX has no TRANSACTION node");
|
|
|
|
|
|
|
|
setTransaction(MyMoneyTransaction(nodeList.item(0).toElement(), false), true);
|
|
|
|
|
|
|
|
// some old versions did not remove the entry date and post date fields
|
|
|
|
// in the schedule. So if this is the case, we deal with a very old transaction
|
|
|
|
// and can't use the post date field as next due date. Hence, we wipe it out here
|
|
|
|
if(m_transaction.entryDate().isValid()) {
|
|
|
|
m_transaction.setPostDate(TQDate());
|
|
|
|
m_transaction.setEntryDate(TQDate());
|
|
|
|
}
|
|
|
|
|
|
|
|
// readin the recorded payments
|
|
|
|
nodeList = node.elementsByTagName("PAYMENTS");
|
|
|
|
if(nodeList.count() > 0) {
|
|
|
|
nodeList = nodeList.item(0).toElement().elementsByTagName("PAYMENT");
|
|
|
|
for(unsigned int i = 0; i < nodeList.count(); ++i) {
|
|
|
|
m_recordedPayments << stringToDate(nodeList.item(i).toElement().attribute("date"));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// if the next due date is not set (comes from old version)
|
|
|
|
// then set it up the old way
|
|
|
|
if(!nextDueDate().isValid() && !m_lastPayment.isValid()) {
|
|
|
|
m_transaction.setPostDate(m_startDate);
|
|
|
|
// clear it, because the schedule has never been used
|
|
|
|
m_startDate = TQDate();
|
|
|
|
}
|
|
|
|
|
|
|
|
// There are reports that lastPayment and nextDueDate are identical or
|
|
|
|
// that nextDueDate is older than lastPayment. This could
|
|
|
|
// be caused by older versions of the application. In this case, we just
|
|
|
|
// clear out the nextDueDate and let it calculate from the lastPayment.
|
|
|
|
if(nextDueDate().isValid() && nextDueDate() <= m_lastPayment) {
|
|
|
|
m_transaction.setPostDate(TQDate());
|
|
|
|
}
|
|
|
|
|
|
|
|
if(!nextDueDate().isValid()) {
|
|
|
|
m_transaction.setPostDate(m_startDate);
|
|
|
|
m_transaction.setPostDate(nextPayment(m_lastPayment.addDays(1)));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
MyMoneySchedule::MyMoneySchedule(const TQString& id, const MyMoneySchedule& right) :
|
|
|
|
MyMoneyObject(id)
|
|
|
|
{
|
|
|
|
*this = right;
|
|
|
|
setId(id);
|
|
|
|
}
|
|
|
|
|
|
|
|
MyMoneySchedule::occurenceE MyMoneySchedule::occurence(void) const
|
|
|
|
{
|
|
|
|
MyMoneySchedule::occurenceE occ = m_occurence;
|
|
|
|
int mult = m_occurenceMultiplier;
|
|
|
|
compoundToSimpleOccurence(mult, occ);
|
|
|
|
return occ;
|
|
|
|
}
|
|
|
|
|
|
|
|
void MyMoneySchedule::setStartDate(const TQDate& date)
|
|
|
|
{
|
|
|
|
m_startDate = date;
|
|
|
|
}
|
|
|
|
|
|
|
|
void MyMoneySchedule::setPaymentType(paymentTypeE type)
|
|
|
|
{
|
|
|
|
m_paymentType = type;
|
|
|
|
}
|
|
|
|
|
|
|
|
void MyMoneySchedule::setFixed(bool fixed)
|
|
|
|
{
|
|
|
|
m_fixed = fixed;
|
|
|
|
}
|
|
|
|
|
|
|
|
void MyMoneySchedule::setTransaction(const MyMoneyTransaction& transaction)
|
|
|
|
{
|
|
|
|
setTransaction(transaction, false);
|
|
|
|
}
|
|
|
|
|
|
|
|
void MyMoneySchedule::setTransaction(const MyMoneyTransaction& transaction, bool noDateCheck)
|
|
|
|
{
|
|
|
|
MyMoneyTransaction t = transaction;
|
|
|
|
if(!noDateCheck) {
|
|
|
|
// don't allow a transaction that has no due date
|
|
|
|
// if we get something like that, then we use the
|
|
|
|
// the current next due date. If that is also invalid
|
|
|
|
// we can't help it.
|
|
|
|
if(!t.postDate().isValid()) {
|
|
|
|
t.setPostDate(m_transaction.postDate());
|
|
|
|
}
|
|
|
|
|
|
|
|
if(!t.postDate().isValid())
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// make sure to clear out some unused information in scheduled transactions
|
|
|
|
// we need to do this for the case that the transaction passed as argument
|
|
|
|
// is a matched or imported transaction.
|
|
|
|
TQValueList<MyMoneySplit> splits = t.splits();
|
|
|
|
if(splits.count() > 0) {
|
|
|
|
TQValueList<MyMoneySplit>::const_iterator it_s;
|
|
|
|
for(it_s = splits.begin(); it_s != splits.end(); ++it_s) {
|
|
|
|
MyMoneySplit s = *it_s;
|
|
|
|
// clear out the bankID
|
|
|
|
if(!(*it_s).bankID().isEmpty()) {
|
|
|
|
s.setBankID(TQString());
|
|
|
|
t.modifySplit(s);
|
|
|
|
}
|
|
|
|
|
|
|
|
// only clear payees from second split onwards
|
|
|
|
if(it_s == splits.begin())
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if(!(*it_s).payeeId().isEmpty()) {
|
|
|
|
// but only if the split references an income/expense category
|
|
|
|
MyMoneyFile* file = MyMoneyFile::instance();
|
|
|
|
// some unit tests don't have a storage attached, so we
|
|
|
|
// simply skip the test
|
|
|
|
// Don't check for accounts with an id of 'Phony-ID' which is used
|
|
|
|
// internally for non-existing accounts (during creation of accounts)
|
|
|
|
if(file->storageAttached() && s.accountId() != TQString("Phony-ID")) {
|
|
|
|
MyMoneyAccount acc = file->account(s.accountId());
|
|
|
|
if(acc.isIncomeExpense()) {
|
|
|
|
s.setPayeeId(TQString());
|
|
|
|
t.modifySplit(s);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
m_transaction = t;
|
|
|
|
// make sure that the transaction does not have an id so that we can enter
|
|
|
|
// it into the engine
|
|
|
|
m_transaction.clearId();
|
|
|
|
}
|
|
|
|
|
|
|
|
void MyMoneySchedule::setEndDate(const TQDate& date)
|
|
|
|
{
|
|
|
|
m_endDate = date;
|
|
|
|
}
|
|
|
|
|
|
|
|
void MyMoneySchedule::setAutoEnter(bool autoenter)
|
|
|
|
{
|
|
|
|
m_autoEnter = autoenter;
|
|
|
|
}
|
|
|
|
|
|
|
|
const TQDate& MyMoneySchedule::startDate(void) const
|
|
|
|
{
|
|
|
|
if(m_startDate.isValid())
|
|
|
|
return m_startDate;
|
|
|
|
return nextDueDate();
|
|
|
|
}
|
|
|
|
|
|
|
|
const TQDate& MyMoneySchedule::nextDueDate(void) const
|
|
|
|
{
|
|
|
|
return m_transaction.postDate();
|
|
|
|
}
|
|
|
|
|
|
|
|
TQDate MyMoneySchedule::adjustedNextDueDate(void) const
|
|
|
|
{
|
|
|
|
if(isFinished())
|
|
|
|
return TQDate();
|
|
|
|
|
|
|
|
return adjustedDate(nextDueDate(), weekendOption());
|
|
|
|
}
|
|
|
|
|
|
|
|
TQDate MyMoneySchedule::adjustedDate(TQDate date, weekendOptionE option) const
|
|
|
|
{
|
|
|
|
if (option == MyMoneySchedule::MoveNothing)
|
|
|
|
return date;
|
|
|
|
|
|
|
|
int step = 1;
|
|
|
|
if (option == MyMoneySchedule::MoveFriday)
|
|
|
|
step = -1;
|
|
|
|
|
|
|
|
while (date.dayOfWeek() > 5)
|
|
|
|
date = date.addDays(step);
|
|
|
|
|
|
|
|
return date;
|
|
|
|
}
|
|
|
|
|
|
|
|
void MyMoneySchedule::setNextDueDate(const TQDate& date)
|
|
|
|
{
|
|
|
|
if(date.isValid()) {
|
|
|
|
m_transaction.setPostDate(date);
|
|
|
|
m_startDate = date;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void MyMoneySchedule::setLastPayment(const TQDate& date)
|
|
|
|
{
|
|
|
|
// Delete all payments older than date
|
|
|
|
TQValueList<TQDate>::Iterator it;
|
|
|
|
TQValueList<TQDate> delList;
|
|
|
|
|
|
|
|
for (it=m_recordedPayments.begin(); it!=m_recordedPayments.end(); ++it)
|
|
|
|
{
|
|
|
|
if (*it < date || !date.isValid())
|
|
|
|
delList.append(*it);
|
|
|
|
}
|
|
|
|
|
|
|
|
for (it=delList.begin(); it!=delList.end(); ++it)
|
|
|
|
{
|
|
|
|
m_recordedPayments.remove(*it);
|
|
|
|
}
|
|
|
|
|
|
|
|
m_lastPayment = date;
|
|
|
|
if(!m_startDate.isValid())
|
|
|
|
m_startDate = date;
|
|
|
|
}
|
|
|
|
|
|
|
|
void MyMoneySchedule::setName(const TQString& nm)
|
|
|
|
{
|
|
|
|
m_name = nm;
|
|
|
|
}
|
|
|
|
|
|
|
|
void MyMoneySchedule::setOccurence(occurenceE occ)
|
|
|
|
{
|
|
|
|
MyMoneySchedule::occurenceE occ2 = occ;
|
|
|
|
int mult = 1;
|
|
|
|
simpleToCompoundOccurence(mult, occ2);
|
|
|
|
setOccurencePeriod( occ2 );
|
|
|
|
setOccurenceMultiplier( mult );
|
|
|
|
}
|
|
|
|
|
|
|
|
void MyMoneySchedule::setOccurencePeriod(occurenceE occ)
|
|
|
|
{
|
|
|
|
m_occurence = occ;
|
|
|
|
}
|
|
|
|
|
|
|
|
void MyMoneySchedule::setOccurenceMultiplier(int occmultiplier)
|
|
|
|
{
|
|
|
|
m_occurenceMultiplier = occmultiplier < 1 ? 1 : occmultiplier;
|
|
|
|
}
|
|
|
|
|
|
|
|
void MyMoneySchedule::setType(typeE type)
|
|
|
|
{
|
|
|
|
m_type = type;
|
|
|
|
}
|
|
|
|
|
|
|
|
void MyMoneySchedule::validate(bool id_check) const
|
|
|
|
{
|
|
|
|
/* Check the supplied instance is valid...
|
|
|
|
*
|
|
|
|
* To be valid it must not have the id set and have the following fields set:
|
|
|
|
*
|
|
|
|
* m_occurence
|
|
|
|
* m_type
|
|
|
|
* m_startDate
|
|
|
|
* m_paymentType
|
|
|
|
* m_transaction
|
|
|
|
* the transaction must contain at least one split (two is better ;-) )
|
|
|
|
*/
|
|
|
|
if (id_check && !m_id.isEmpty())
|
|
|
|
throw new MYMONEYEXCEPTION("ID for schedule not empty when required");
|
|
|
|
|
|
|
|
if(m_occurence == OCCUR_ANY)
|
|
|
|
throw new MYMONEYEXCEPTION("Invalid occurence type for schedule");
|
|
|
|
|
|
|
|
if(m_type == TYPE_ANY)
|
|
|
|
throw new MYMONEYEXCEPTION("Invalid type for schedule");
|
|
|
|
|
|
|
|
if(!nextDueDate().isValid())
|
|
|
|
throw new MYMONEYEXCEPTION("Invalid next due date for schedule");
|
|
|
|
|
|
|
|
if(m_paymentType == STYPE_ANY)
|
|
|
|
throw new MYMONEYEXCEPTION("Invalid payment type for schedule");
|
|
|
|
|
|
|
|
if(m_transaction.splitCount() == 0)
|
|
|
|
throw new MYMONEYEXCEPTION("Scheduled transaction does not contain splits");
|
|
|
|
|
|
|
|
// Check the payment types
|
|
|
|
switch (m_type)
|
|
|
|
{
|
|
|
|
case TYPE_BILL:
|
|
|
|
if (m_paymentType == STYPE_DIRECTDEPOSIT || m_paymentType == STYPE_MANUALDEPOSIT)
|
|
|
|
throw new MYMONEYEXCEPTION("Invalid payment type for bills");
|
|
|
|
break;
|
|
|
|
|
|
|
|
case TYPE_DEPOSIT:
|
|
|
|
if (m_paymentType == STYPE_DIRECTDEBIT || m_paymentType == STYPE_WRITECHEQUE)
|
|
|
|
throw new MYMONEYEXCEPTION("Invalid payment type for deposits");
|
|
|
|
break;
|
|
|
|
|
|
|
|
case TYPE_ANY:
|
|
|
|
throw new MYMONEYEXCEPTION("Invalid type ANY");
|
|
|
|
break;
|
|
|
|
|
|
|
|
case TYPE_TRANSFER:
|
|
|
|
// if (m_paymentType == STYPE_DIRECTDEPOSIT || m_paymentType == STYPE_MANUALDEPOSIT)
|
|
|
|
// return false;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case TYPE_LOANPAYMENT:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
TQDate MyMoneySchedule::adjustedNextPayment(const TQDate& refDate) const
|
|
|
|
{
|
|
|
|
TQDate date(nextPayment(refDate));
|
|
|
|
return date.isValid() ? adjustedDate(date, weekendOption()) : date;
|
|
|
|
}
|
|
|
|
|
|
|
|
TQDate MyMoneySchedule::nextPayment(const TQDate& refDate) const
|
|
|
|
{
|
|
|
|
// if the enddate is valid and it is before the reference date,
|
|
|
|
// then there will be no more payments.
|
|
|
|
if(m_endDate.isValid() && m_endDate < refDate) {
|
|
|
|
return TQDate();
|
|
|
|
}
|
|
|
|
|
|
|
|
TQDate paymentDate(nextDueDate());
|
|
|
|
|
|
|
|
if(refDate >= paymentDate) {
|
|
|
|
switch (m_occurence)
|
|
|
|
{
|
|
|
|
case OCCUR_ONCE:
|
|
|
|
// if the lastPayment is already set, then there will be no more payments
|
|
|
|
// otherwise, the start date is the payment date
|
|
|
|
if(m_lastPayment.isValid())
|
|
|
|
return TQDate();
|
|
|
|
// if the only payment should have been prior to the reference date,
|
|
|
|
// then don't show it
|
|
|
|
if(paymentDate < refDate)
|
|
|
|
return TQDate();
|
|
|
|
break;
|
|
|
|
|
|
|
|
case OCCUR_DAILY:
|
|
|
|
paymentDate = refDate.addDays(m_occurenceMultiplier);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case OCCUR_WEEKLY:
|
|
|
|
{
|
|
|
|
int step = 7*m_occurenceMultiplier;
|
|
|
|
do {
|
|
|
|
paymentDate = paymentDate.addDays(step);
|
|
|
|
}
|
|
|
|
while (paymentDate <= refDate);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case OCCUR_EVERYHALFMONTH:
|
|
|
|
do
|
|
|
|
{
|
|
|
|
paymentDate = addHalfMonths(paymentDate,m_occurenceMultiplier);
|
|
|
|
}
|
|
|
|
while (paymentDate <= refDate);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case OCCUR_MONTHLY:
|
|
|
|
do {
|
|
|
|
paymentDate = paymentDate.addMonths(m_occurenceMultiplier);
|
|
|
|
fixDate(paymentDate);
|
|
|
|
}
|
|
|
|
while (paymentDate <= refDate);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case OCCUR_YEARLY:
|
|
|
|
do {
|
|
|
|
paymentDate = paymentDate.addYears(m_occurenceMultiplier);
|
|
|
|
fixDate(paymentDate);
|
|
|
|
}
|
|
|
|
while (paymentDate <= refDate);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case OCCUR_ANY:
|
|
|
|
default:
|
|
|
|
paymentDate = TQDate();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if(paymentDate.isValid()) {
|
|
|
|
if(m_endDate.isValid() && paymentDate > m_endDate)
|
|
|
|
paymentDate = TQDate();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (paymentDate.isValid() && m_recordedPayments.contains(paymentDate))
|
|
|
|
paymentDate = nextPayment(paymentDate);
|
|
|
|
|
|
|
|
return paymentDate;
|
|
|
|
}
|
|
|
|
|
|
|
|
TQValueList<TQDate> MyMoneySchedule::paymentDates(const TQDate& _startDate, const TQDate& _endDate) const
|
|
|
|
{
|
|
|
|
TQDate paymentDate(nextDueDate());
|
|
|
|
TQValueList<TQDate> theDates;
|
|
|
|
|
|
|
|
TQDate endDate(_endDate);
|
|
|
|
if ( willEnd() && m_endDate < endDate )
|
|
|
|
endDate = m_endDate;
|
|
|
|
|
|
|
|
weekendOptionE option(weekendOption());
|
|
|
|
TQDate start_date(adjustedDate(startDate(), option));
|
|
|
|
// if the period specified by the parameters and the period
|
|
|
|
// defined for this schedule don't overlap, then the list remains empty
|
|
|
|
if ((willEnd() && m_endDate < _startDate)
|
|
|
|
|| start_date > endDate)
|
|
|
|
return theDates;
|
|
|
|
|
|
|
|
TQDate date(adjustedDate(paymentDate, option));
|
|
|
|
|
|
|
|
switch (m_occurence)
|
|
|
|
{
|
|
|
|
case OCCUR_ONCE:
|
|
|
|
if (start_date >= _startDate && start_date <= endDate)
|
|
|
|
theDates.append(start_date);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case OCCUR_DAILY:
|
|
|
|
while (date.isValid() && (date <= endDate))
|
|
|
|
{
|
|
|
|
if (date >= _startDate)
|
|
|
|
theDates.append(date);
|
|
|
|
paymentDate = paymentDate.addDays(m_occurenceMultiplier);
|
|
|
|
date = adjustedDate(paymentDate, option);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case OCCUR_WEEKLY:
|
|
|
|
{
|
|
|
|
int step = 7*m_occurenceMultiplier;
|
|
|
|
while (date.isValid() && (date <= endDate))
|
|
|
|
{
|
|
|
|
if (date >= _startDate)
|
|
|
|
theDates.append(date);
|
|
|
|
paymentDate = paymentDate.addDays(step);
|
|
|
|
date = adjustedDate(paymentDate, option);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case OCCUR_EVERYHALFMONTH:
|
|
|
|
while (date.isValid() && (date <= endDate))
|
|
|
|
{
|
|
|
|
if (date >= _startDate)
|
|
|
|
theDates.append(date);
|
|
|
|
paymentDate = addHalfMonths(paymentDate,m_occurenceMultiplier);
|
|
|
|
date = adjustedDate(paymentDate, option);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case OCCUR_MONTHLY:
|
|
|
|
while (date.isValid() && (date <= endDate))
|
|
|
|
{
|
|
|
|
if (date >= _startDate)
|
|
|
|
theDates.append(date);
|
|
|
|
paymentDate = paymentDate.addMonths(m_occurenceMultiplier);
|
|
|
|
fixDate(paymentDate);
|
|
|
|
date = adjustedDate(paymentDate, option);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case OCCUR_YEARLY:
|
|
|
|
while (date.isValid() && (date <= endDate))
|
|
|
|
{
|
|
|
|
if (date >= _startDate)
|
|
|
|
theDates.append(date);
|
|
|
|
paymentDate = paymentDate.addYears(m_occurenceMultiplier);
|
|
|
|
fixDate(paymentDate);
|
|
|
|
date = adjustedDate(paymentDate, option);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case OCCUR_ANY:
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return theDates;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool MyMoneySchedule::operator <(const MyMoneySchedule& right) const
|
|
|
|
{
|
|
|
|
return adjustedNextDueDate() < right.adjustedNextDueDate();
|
|
|
|
}
|
|
|
|
|
|
|
|
bool MyMoneySchedule::operator ==(const MyMoneySchedule& right) const
|
|
|
|
{
|
|
|
|
if ( MyMoneyObject::operator==(right) &&
|
|
|
|
m_occurence == right.m_occurence &&
|
|
|
|
m_occurenceMultiplier == right.m_occurenceMultiplier &&
|
|
|
|
m_type == right.m_type &&
|
|
|
|
m_startDate == right.m_startDate &&
|
|
|
|
m_paymentType == right.m_paymentType &&
|
|
|
|
m_fixed == right.m_fixed &&
|
|
|
|
m_transaction == right.m_transaction &&
|
|
|
|
m_endDate == right.m_endDate &&
|
|
|
|
m_autoEnter == right.m_autoEnter &&
|
|
|
|
m_lastPayment == right.m_lastPayment &&
|
|
|
|
((m_name.length() == 0 && right.m_name.length() == 0) || (m_name == right.m_name)))
|
|
|
|
return true;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
int MyMoneySchedule::transactionsRemaining(void) const
|
|
|
|
{
|
|
|
|
int counter=0;
|
|
|
|
|
|
|
|
if (m_endDate.isValid())
|
|
|
|
{
|
|
|
|
TQValueList<TQDate> dates = paymentDates(m_lastPayment, m_endDate);
|
|
|
|
// Dont include the last payment so -1
|
|
|
|
counter = dates.count();
|
|
|
|
}
|
|
|
|
return counter;
|
|
|
|
}
|
|
|
|
|
|
|
|
MyMoneyAccount MyMoneySchedule::account(int cnt) const
|
|
|
|
{
|
|
|
|
TQValueList<MyMoneySplit> splits = m_transaction.splits();
|
|
|
|
TQValueList<MyMoneySplit>::ConstIterator it;
|
|
|
|
MyMoneyFile* file = MyMoneyFile::instance();
|
|
|
|
MyMoneyAccount acc;
|
|
|
|
|
|
|
|
// search the first asset or liability account
|
|
|
|
for(it = splits.begin(); it != splits.end() && (acc.id().isEmpty() || cnt); ++it) {
|
|
|
|
try {
|
|
|
|
acc = file->account((*it).accountId());
|
|
|
|
if(acc.isAssetLiability())
|
|
|
|
--cnt;
|
|
|
|
|
|
|
|
if(!cnt)
|
|
|
|
return acc;
|
|
|
|
} catch(MyMoneyException *e) {
|
|
|
|
tqWarning("Schedule '%s' references unknown account '%s'", id().data(), (*it).accountId().data());
|
|
|
|
delete e;
|
|
|
|
return MyMoneyAccount();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return MyMoneyAccount();
|
|
|
|
}
|
|
|
|
|
|
|
|
TQDate MyMoneySchedule::dateAfter(int transactions) const
|
|
|
|
{
|
|
|
|
int counter=1;
|
|
|
|
TQDate paymentDate(startDate());
|
|
|
|
|
|
|
|
if (transactions<=0)
|
|
|
|
return paymentDate;
|
|
|
|
|
|
|
|
switch (m_occurence)
|
|
|
|
{
|
|
|
|
case OCCUR_ONCE:
|
|
|
|
break;
|
|
|
|
|
|
|
|
case OCCUR_DAILY:
|
|
|
|
while (counter++ < transactions)
|
|
|
|
paymentDate = paymentDate.addDays(m_occurenceMultiplier);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case OCCUR_WEEKLY:
|
|
|
|
{
|
|
|
|
int step = 7 * m_occurenceMultiplier;
|
|
|
|
while (counter++ < transactions)
|
|
|
|
paymentDate = paymentDate.addDays(step);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case OCCUR_EVERYHALFMONTH:
|
|
|
|
paymentDate = addHalfMonths(paymentDate,m_occurenceMultiplier*(transactions-1));
|
|
|
|
break;
|
|
|
|
|
|
|
|
case OCCUR_MONTHLY:
|
|
|
|
while (counter++ < transactions)
|
|
|
|
paymentDate = paymentDate.addMonths(m_occurenceMultiplier);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case OCCUR_YEARLY:
|
|
|
|
while (counter++ < transactions)
|
|
|
|
paymentDate = paymentDate.addYears(m_occurenceMultiplier);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case OCCUR_ANY:
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return paymentDate;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool MyMoneySchedule::isOverdue() const
|
|
|
|
{
|
|
|
|
if (isFinished())
|
|
|
|
return false;
|
|
|
|
|
|
|
|
if(adjustedNextDueDate() >= TQDate::currentDate())
|
|
|
|
return false;
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool MyMoneySchedule::isFinished() const
|
|
|
|
{
|
|
|
|
if(!m_lastPayment.isValid())
|
|
|
|
return false;
|
|
|
|
|
|
|
|
if (m_endDate.isValid()) {
|
|
|
|
if(m_lastPayment >= m_endDate
|
|
|
|
|| !nextDueDate().isValid()
|
|
|
|
|| nextDueDate() > m_endDate)
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Check to see if its a once off payment
|
|
|
|
if (m_occurence == MyMoneySchedule::OCCUR_ONCE)
|
|
|
|
return true;
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool MyMoneySchedule::hasRecordedPayment(const TQDate& date) const
|
|
|
|
{
|
|
|
|
// m_lastPayment should always be > recordedPayments()
|
|
|
|
if (m_lastPayment.isValid() && m_lastPayment >= date)
|
|
|
|
return true;
|
|
|
|
|
|
|
|
if (m_recordedPayments.contains(date))
|
|
|
|
return true;
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
void MyMoneySchedule::recordPayment(const TQDate& date)
|
|
|
|
{
|
|
|
|
m_recordedPayments.append(date);
|
|
|
|
}
|
|
|
|
|
|
|
|
void MyMoneySchedule::setWeekendOption(const weekendOptionE option)
|
|
|
|
{
|
|
|
|
// make sure only valid values are used. Invalid defaults to MoveNothing.
|
|
|
|
switch(option) {
|
|
|
|
case MoveFriday:
|
|
|
|
case MoveMonday:
|
|
|
|
m_weekendOption = option;
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
m_weekendOption = MoveNothing;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void MyMoneySchedule::fixDate(TQDate& date) const
|
|
|
|
{
|
|
|
|
TQDate fixDate(m_startDate);
|
|
|
|
if(fixDate.isValid()
|
|
|
|
&& date.day() != fixDate.day()
|
|
|
|
&& TQDate::isValid(date.year(), date.month(), fixDate.day())) {
|
|
|
|
date.setYMD(date.year(), date.month(), fixDate.day());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void MyMoneySchedule::writeXML(TQDomDocument& document, TQDomElement& parent) const
|
|
|
|
{
|
|
|
|
TQDomElement el = document.createElement("SCHEDULED_TX");
|
|
|
|
|
|
|
|
writeBaseXML(document, el);
|
|
|
|
|
|
|
|
el.setAttribute("name", m_name);
|
|
|
|
el.setAttribute("type", m_type);
|
|
|
|
el.setAttribute("occurence", m_occurence);
|
|
|
|
el.setAttribute("occurenceMultiplier", m_occurenceMultiplier);
|
|
|
|
el.setAttribute("paymentType", m_paymentType);
|
|
|
|
el.setAttribute("startDate", dateToString(m_startDate));
|
|
|
|
el.setAttribute("endDate", dateToString(m_endDate));
|
|
|
|
el.setAttribute("fixed", m_fixed);
|
|
|
|
el.setAttribute("autoEnter", m_autoEnter);
|
|
|
|
el.setAttribute("lastPayment", dateToString(m_lastPayment));
|
|
|
|
el.setAttribute("weekendOption", m_weekendOption);
|
|
|
|
|
|
|
|
//store the payment history for this scheduled task.
|
|
|
|
TQValueList<TQDate> payments = recordedPayments();
|
|
|
|
TQValueList<TQDate>::ConstIterator it;
|
|
|
|
TQDomElement paymentsElement = document.createElement("PAYMENTS");
|
|
|
|
for (it=payments.begin(); it!=payments.end(); ++it) {
|
|
|
|
TQDomElement paymentEntry = document.createElement("PAYMENT");
|
|
|
|
paymentEntry.setAttribute("date", dateToString(*it));
|
|
|
|
paymentsElement.appendChild(paymentEntry);
|
|
|
|
}
|
|
|
|
el.appendChild(paymentsElement);
|
|
|
|
|
|
|
|
//store the transaction data for this task.
|
|
|
|
m_transaction.writeXML(document, el);
|
|
|
|
|
|
|
|
parent.appendChild(el);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool MyMoneySchedule::hasReferenceTo(const TQString& id) const
|
|
|
|
{
|
|
|
|
return m_transaction.hasReferenceTo(id);
|
|
|
|
}
|
|
|
|
|
|
|
|
TQString MyMoneySchedule::occurenceToString() const
|
|
|
|
{
|
|
|
|
return occurenceToString( occurenceMultiplier(), occurencePeriod() );
|
|
|
|
}
|
|
|
|
|
|
|
|
TQString MyMoneySchedule::occurenceToString(occurenceE occurence)
|
|
|
|
{
|
|
|
|
TQString occurenceString = I18N_NOOP("Any");
|
|
|
|
|
|
|
|
if(occurence == MyMoneySchedule::OCCUR_ONCE)
|
|
|
|
occurenceString = I18N_NOOP("Once");
|
|
|
|
else if(occurence == MyMoneySchedule::OCCUR_DAILY)
|
|
|
|
occurenceString = I18N_NOOP("Daily");
|
|
|
|
else if(occurence == MyMoneySchedule::OCCUR_WEEKLY)
|
|
|
|
occurenceString = I18N_NOOP("Weekly");
|
|
|
|
else if(occurence == MyMoneySchedule::OCCUR_FORTNIGHTLY)
|
|
|
|
occurenceString = I18N_NOOP("Fortnightly");
|
|
|
|
else if(occurence == MyMoneySchedule::OCCUR_EVERYOTHERWEEK)
|
|
|
|
occurenceString = I18N_NOOP("Every other week");
|
|
|
|
else if(occurence == MyMoneySchedule::OCCUR_EVERYHALFMONTH)
|
|
|
|
occurenceString = I18N_NOOP("Every half month");
|
|
|
|
else if(occurence == MyMoneySchedule::OCCUR_EVERYTHREEWEEKS)
|
|
|
|
occurenceString = I18N_NOOP("Every three weeks");
|
|
|
|
else if(occurence == MyMoneySchedule::OCCUR_EVERYFOURWEEKS)
|
|
|
|
occurenceString = I18N_NOOP("Every four weeks");
|
|
|
|
else if(occurence == MyMoneySchedule::OCCUR_EVERYTHIRTYDAYS)
|
|
|
|
occurenceString = I18N_NOOP("Every thirty days");
|
|
|
|
else if(occurence == MyMoneySchedule::OCCUR_MONTHLY)
|
|
|
|
occurenceString = I18N_NOOP("Monthly");
|
|
|
|
else if(occurence == MyMoneySchedule::OCCUR_EVERYEIGHTWEEKS)
|
|
|
|
occurenceString = I18N_NOOP("Every eight weeks");
|
|
|
|
else if(occurence == MyMoneySchedule::OCCUR_EVERYOTHERMONTH)
|
|
|
|
occurenceString = I18N_NOOP("Every two months");
|
|
|
|
else if(occurence == MyMoneySchedule::OCCUR_EVERYTHREEMONTHS)
|
|
|
|
occurenceString = I18N_NOOP("Every three months");
|
|
|
|
else if(occurence == MyMoneySchedule::OCCUR_QUARTERLY)
|
|
|
|
occurenceString = I18N_NOOP("Quarterly");
|
|
|
|
else if(occurence == MyMoneySchedule::OCCUR_EVERYFOURMONTHS)
|
|
|
|
occurenceString = I18N_NOOP("Every four months");
|
|
|
|
else if(occurence == MyMoneySchedule::OCCUR_TWICEYEARLY)
|
|
|
|
occurenceString = I18N_NOOP("Twice yearly");
|
|
|
|
else if(occurence == MyMoneySchedule::OCCUR_YEARLY)
|
|
|
|
occurenceString = I18N_NOOP("Yearly");
|
|
|
|
else if(occurence == MyMoneySchedule::OCCUR_EVERYOTHERYEAR)
|
|
|
|
occurenceString = I18N_NOOP("Every other year");
|
|
|
|
return occurenceString;
|
|
|
|
}
|
|
|
|
|
|
|
|
TQString MyMoneySchedule::occurenceToString(int mult, occurenceE type)
|
|
|
|
{
|
|
|
|
TQString occurenceString = I18N_NOOP("Any");
|
|
|
|
|
|
|
|
if (type == MyMoneySchedule::OCCUR_ONCE)
|
|
|
|
switch (mult)
|
|
|
|
{
|
|
|
|
case 1: occurenceString = I18N_NOOP("Once"); break;
|
|
|
|
default: occurenceString = I18N_NOOP(static_cast<TQString>("%1 times").arg(mult));
|
|
|
|
}
|
|
|
|
else if(type == MyMoneySchedule::OCCUR_DAILY)
|
|
|
|
switch (mult)
|
|
|
|
{
|
|
|
|
case 1: occurenceString = I18N_NOOP("Daily"); break;
|
|
|
|
case 30: occurenceString = I18N_NOOP("Every thirty days"); break;
|
|
|
|
default: occurenceString = I18N_NOOP(static_cast<TQString>("Every %1 days").arg(mult));
|
|
|
|
}
|
|
|
|
else if(type == MyMoneySchedule::OCCUR_WEEKLY)
|
|
|
|
switch (mult)
|
|
|
|
{
|
|
|
|
case 1: occurenceString = I18N_NOOP("Weekly"); break;
|
|
|
|
case 2: occurenceString = I18N_NOOP("Every other week"); break;
|
|
|
|
case 3: occurenceString = I18N_NOOP("Every three weeks"); break;
|
|
|
|
case 4: occurenceString = I18N_NOOP("Every four weeks"); break;
|
|
|
|
case 8: occurenceString = I18N_NOOP("Every eight weeks"); break;
|
|
|
|
default: occurenceString = I18N_NOOP(static_cast<TQString>("Every %1 weeks").arg(mult));
|
|
|
|
}
|
|
|
|
else if(type == MyMoneySchedule::OCCUR_EVERYHALFMONTH)
|
|
|
|
switch (mult)
|
|
|
|
{
|
|
|
|
case 1: occurenceString = I18N_NOOP("Every half month"); break;
|
|
|
|
default: occurenceString = I18N_NOOP(static_cast<TQString>("Every %1 half months").arg(mult));
|
|
|
|
}
|
|
|
|
else if(type == MyMoneySchedule::OCCUR_MONTHLY)
|
|
|
|
switch (mult)
|
|
|
|
{
|
|
|
|
case 1: occurenceString = I18N_NOOP("Monthly"); break;
|
|
|
|
case 2: occurenceString = I18N_NOOP("Every two months"); break;
|
|
|
|
case 3: occurenceString = I18N_NOOP("Every three months"); break;
|
|
|
|
case 4: occurenceString = I18N_NOOP("Every four months"); break;
|
|
|
|
case 6: occurenceString = I18N_NOOP("Twice yearly"); break;
|
|
|
|
default: occurenceString = I18N_NOOP(static_cast<TQString>("Every %1 months").arg(mult));
|
|
|
|
}
|
|
|
|
else if(type == MyMoneySchedule::OCCUR_YEARLY)
|
|
|
|
switch (mult)
|
|
|
|
{
|
|
|
|
case 1: occurenceString = I18N_NOOP("Yearly"); break;
|
|
|
|
case 2: occurenceString = I18N_NOOP("Every other year"); break;
|
|
|
|
default: occurenceString = I18N_NOOP(static_cast<TQString>("Every %1 years").arg(mult));
|
|
|
|
}
|
|
|
|
return occurenceString;
|
|
|
|
}
|
|
|
|
|
|
|
|
TQString MyMoneySchedule::occurencePeriodToString(MyMoneySchedule::occurenceE type)
|
|
|
|
{
|
|
|
|
TQString occurenceString = I18N_NOOP("Any");
|
|
|
|
|
|
|
|
if(type == MyMoneySchedule::OCCUR_ONCE)
|
|
|
|
occurenceString = I18N_NOOP("Once");
|
|
|
|
else if(type == MyMoneySchedule::OCCUR_DAILY)
|
|
|
|
occurenceString = I18N_NOOP("Day");
|
|
|
|
else if(type == MyMoneySchedule::OCCUR_WEEKLY)
|
|
|
|
occurenceString = I18N_NOOP("Week");
|
|
|
|
else if(type == MyMoneySchedule::OCCUR_EVERYHALFMONTH)
|
|
|
|
occurenceString = I18N_NOOP("Half-month");
|
|
|
|
else if(type == MyMoneySchedule::OCCUR_MONTHLY)
|
|
|
|
occurenceString = I18N_NOOP("Month");
|
|
|
|
else if(type == MyMoneySchedule::OCCUR_YEARLY)
|
|
|
|
occurenceString = I18N_NOOP("Year");
|
|
|
|
return occurenceString;
|
|
|
|
}
|
|
|
|
|
|
|
|
TQString MyMoneySchedule::scheduleTypeToString(MyMoneySchedule::typeE type)
|
|
|
|
{
|
|
|
|
TQString text;
|
|
|
|
|
|
|
|
switch (type) {
|
|
|
|
case MyMoneySchedule::TYPE_BILL:
|
|
|
|
text = I18N_NOOP("Bill");
|
|
|
|
break;
|
|
|
|
case MyMoneySchedule::TYPE_DEPOSIT:
|
|
|
|
text = I18N_NOOP("Deposit");
|
|
|
|
break;
|
|
|
|
case MyMoneySchedule::TYPE_TRANSFER:
|
|
|
|
text = I18N_NOOP("Transfer");
|
|
|
|
break;
|
|
|
|
case MyMoneySchedule::TYPE_LOANPAYMENT:
|
|
|
|
text = I18N_NOOP("Loan payment");
|
|
|
|
break;
|
|
|
|
case MyMoneySchedule::TYPE_ANY:
|
|
|
|
default:
|
|
|
|
text = I18N_NOOP("Unknown");
|
|
|
|
}
|
|
|
|
return text;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
TQString MyMoneySchedule::paymentMethodToString(MyMoneySchedule::paymentTypeE paymentType)
|
|
|
|
{
|
|
|
|
TQString text;
|
|
|
|
|
|
|
|
switch (paymentType) {
|
|
|
|
case MyMoneySchedule::STYPE_DIRECTDEBIT:
|
|
|
|
text = I18N_NOOP("Direct debit");
|
|
|
|
break;
|
|
|
|
case MyMoneySchedule::STYPE_DIRECTDEPOSIT:
|
|
|
|
text = I18N_NOOP("Direct deposit");
|
|
|
|
break;
|
|
|
|
case MyMoneySchedule::STYPE_MANUALDEPOSIT:
|
|
|
|
text = I18N_NOOP("Manual deposit");
|
|
|
|
break;
|
|
|
|
case MyMoneySchedule::STYPE_OTHER:
|
|
|
|
text = I18N_NOOP("Other");
|
|
|
|
break;
|
|
|
|
case MyMoneySchedule::STYPE_WRITECHEQUE:
|
|
|
|
text = I18N_NOOP("Write check");
|
|
|
|
break;
|
|
|
|
case MyMoneySchedule::STYPE_STANDINGORDER:
|
|
|
|
text = I18N_NOOP("Standing order");
|
|
|
|
break;
|
|
|
|
case MyMoneySchedule::STYPE_BANKTRANSFER:
|
|
|
|
text = I18N_NOOP("Bank transfer");
|
|
|
|
break;
|
|
|
|
case MyMoneySchedule::STYPE_ANY:
|
|
|
|
text = I18N_NOOP("Any (Error)");
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return text;
|
|
|
|
}
|
|
|
|
|
|
|
|
TQString MyMoneySchedule::weekendOptionToString(MyMoneySchedule::weekendOptionE weekendOption)
|
|
|
|
{
|
|
|
|
TQString text;
|
|
|
|
|
|
|
|
switch (weekendOption) {
|
|
|
|
case MyMoneySchedule::MoveFriday:
|
|
|
|
text = I18N_NOOP("Change the date to the previous Friday");
|
|
|
|
break;
|
|
|
|
case MyMoneySchedule::MoveMonday:
|
|
|
|
text = I18N_NOOP("Change the date to the next Monday");
|
|
|
|
break;
|
|
|
|
case MyMoneySchedule::MoveNothing:
|
|
|
|
text = I18N_NOOP("Do Nothing");
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return text;
|
|
|
|
}
|
|
|
|
|
|
|
|
// until we don't have the means to store the value
|
|
|
|
// of the variation, we default to 10% in case this
|
|
|
|
// scheduled transaction is marked 'not fixed'.
|
|
|
|
//
|
|
|
|
// ipwizard 2009-04-18
|
|
|
|
|
|
|
|
int MyMoneySchedule::variation(void) const
|
|
|
|
{
|
|
|
|
int rc = 0;
|
|
|
|
if(!isFixed()) {
|
|
|
|
rc = 10;
|
|
|
|
#if 0
|
|
|
|
TQString var = value("kmm-variation");
|
|
|
|
if(!var.isEmpty())
|
|
|
|
rc = var.toInt();
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
|
|
|
void MyMoneySchedule::setVariation(int var)
|
|
|
|
{
|
|
|
|
#if 0
|
|
|
|
deletePair("kmm-variation");
|
|
|
|
if(var != 0)
|
|
|
|
setValue("kmm-variation", TQString("%1").arg(var));
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
int MyMoneySchedule::eventsPerYear(MyMoneySchedule::occurenceE occurence)
|
|
|
|
{
|
|
|
|
int rc = 0;
|
|
|
|
|
|
|
|
switch(occurence) {
|
|
|
|
case MyMoneySchedule::OCCUR_DAILY:
|
|
|
|
rc = 365;
|
|
|
|
break;
|
|
|
|
case MyMoneySchedule::OCCUR_WEEKLY:
|
|
|
|
rc = 52;
|
|
|
|
break;
|
|
|
|
case MyMoneySchedule::OCCUR_FORTNIGHTLY:
|
|
|
|
rc = 26;
|
|
|
|
break;
|
|
|
|
case MyMoneySchedule::OCCUR_EVERYOTHERWEEK:
|
|
|
|
rc = 26;
|
|
|
|
break;
|
|
|
|
case MyMoneySchedule::OCCUR_EVERYHALFMONTH:
|
|
|
|
rc = 24;
|
|
|
|
break;
|
|
|
|
case MyMoneySchedule::OCCUR_EVERYTHREEWEEKS:
|
|
|
|
rc = 17;
|
|
|
|
break;
|
|
|
|
case MyMoneySchedule::OCCUR_EVERYFOURWEEKS:
|
|
|
|
rc = 13;
|
|
|
|
break;
|
|
|
|
case MyMoneySchedule::OCCUR_MONTHLY:
|
|
|
|
case MyMoneySchedule::OCCUR_EVERYTHIRTYDAYS:
|
|
|
|
rc = 12;
|
|
|
|
break;
|
|
|
|
case MyMoneySchedule::OCCUR_EVERYEIGHTWEEKS:
|
|
|
|
rc = 6;
|
|
|
|
break;
|
|
|
|
case MyMoneySchedule::OCCUR_EVERYOTHERMONTH:
|
|
|
|
rc = 6;
|
|
|
|
break;
|
|
|
|
case MyMoneySchedule::OCCUR_EVERYTHREEMONTHS:
|
|
|
|
case MyMoneySchedule::OCCUR_QUARTERLY:
|
|
|
|
rc = 4;
|
|
|
|
break;
|
|
|
|
case MyMoneySchedule::OCCUR_EVERYFOURMONTHS:
|
|
|
|
rc = 3;
|
|
|
|
break;
|
|
|
|
case MyMoneySchedule::OCCUR_TWICEYEARLY:
|
|
|
|
rc = 2;
|
|
|
|
break;
|
|
|
|
case MyMoneySchedule::OCCUR_YEARLY:
|
|
|
|
rc = 1;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
tqWarning("Occurence not supported by financial calculator");
|
|
|
|
}
|
|
|
|
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
|
|
|
int MyMoneySchedule::daysBetweenEvents(MyMoneySchedule::occurenceE occurence)
|
|
|
|
{
|
|
|
|
int rc = 0;
|
|
|
|
|
|
|
|
switch(occurence) {
|
|
|
|
case MyMoneySchedule::OCCUR_DAILY:
|
|
|
|
rc = 1;
|
|
|
|
break;
|
|
|
|
case MyMoneySchedule::OCCUR_WEEKLY:
|
|
|
|
rc = 7;
|
|
|
|
break;
|
|
|
|
case MyMoneySchedule::OCCUR_FORTNIGHTLY:
|
|
|
|
rc = 14;
|
|
|
|
break;
|
|
|
|
case MyMoneySchedule::OCCUR_EVERYOTHERWEEK:
|
|
|
|
rc = 14;
|
|
|
|
break;
|
|
|
|
case MyMoneySchedule::OCCUR_EVERYHALFMONTH:
|
|
|
|
rc = 15;
|
|
|
|
break;
|
|
|
|
case MyMoneySchedule::OCCUR_EVERYTHREEWEEKS:
|
|
|
|
rc = 21;
|
|
|
|
break;
|
|
|
|
case MyMoneySchedule::OCCUR_EVERYFOURWEEKS:
|
|
|
|
rc = 28;
|
|
|
|
break;
|
|
|
|
case MyMoneySchedule::OCCUR_EVERYTHIRTYDAYS:
|
|
|
|
rc = 30;
|
|
|
|
break;
|
|
|
|
case MyMoneySchedule::OCCUR_MONTHLY:
|
|
|
|
rc = 30;
|
|
|
|
break;
|
|
|
|
case MyMoneySchedule::OCCUR_EVERYEIGHTWEEKS:
|
|
|
|
rc = 56;
|
|
|
|
break;
|
|
|
|
case MyMoneySchedule::OCCUR_EVERYOTHERMONTH:
|
|
|
|
rc = 60;
|
|
|
|
break;
|
|
|
|
case MyMoneySchedule::OCCUR_EVERYTHREEMONTHS:
|
|
|
|
case MyMoneySchedule::OCCUR_QUARTERLY:
|
|
|
|
rc = 90;
|
|
|
|
break;
|
|
|
|
case MyMoneySchedule::OCCUR_EVERYFOURMONTHS:
|
|
|
|
rc = 120;
|
|
|
|
break;
|
|
|
|
case MyMoneySchedule::OCCUR_TWICEYEARLY:
|
|
|
|
rc = 180;
|
|
|
|
break;
|
|
|
|
case MyMoneySchedule::OCCUR_YEARLY:
|
|
|
|
rc = 360;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
tqWarning("Occurence not supported by financial calculator");
|
|
|
|
}
|
|
|
|
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
|
|
|
TQDate MyMoneySchedule::addHalfMonths( TQDate date, int mult ) const
|
|
|
|
{
|
|
|
|
TQDate newdate = date;
|
|
|
|
int d, dm;
|
|
|
|
if ( mult > 0 )
|
|
|
|
{
|
|
|
|
d = newdate.day();
|
|
|
|
if ( d <= 12 )
|
|
|
|
{
|
|
|
|
if ( mult % 2 == 0 )
|
|
|
|
newdate = newdate.addMonths(mult>>1);
|
|
|
|
else
|
|
|
|
newdate = newdate.addMonths(mult>>1).addDays(15);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
for ( int i = 0; i < mult; i++ )
|
|
|
|
{
|
|
|
|
if ( d <= 13 )
|
|
|
|
newdate = newdate.addDays(15);
|
|
|
|
else
|
|
|
|
{
|
|
|
|
dm = newdate.daysInMonth();
|
|
|
|
if ( d == 14 )
|
|
|
|
newdate = newdate.addDays(( dm < 30 ) ? dm - d : 15);
|
|
|
|
else if ( d == 15 )
|
|
|
|
newdate = newdate.addDays(dm - d);
|
|
|
|
else if ( d == dm )
|
|
|
|
newdate = newdate.addDays(15 - d).addMonths(1);
|
|
|
|
else
|
|
|
|
newdate = newdate.addDays(-15).addMonths(1);
|
|
|
|
}
|
|
|
|
d = newdate.day();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if ( mult < 0 ) // Go backwards
|
|
|
|
for ( int i = 0; i > mult; i-- )
|
|
|
|
{
|
|
|
|
d = newdate.day();
|
|
|
|
dm = newdate.daysInMonth();
|
|
|
|
if ( d > 15 )
|
|
|
|
{
|
|
|
|
dm = newdate.daysInMonth();
|
|
|
|
newdate = newdate.addDays( (d == dm) ? 15 - dm : -15);
|
|
|
|
}
|
|
|
|
else if ( d <= 13 )
|
|
|
|
newdate = newdate.addMonths(-1).addDays(15);
|
|
|
|
else if ( d == 15 )
|
|
|
|
newdate = newdate.addDays(-15);
|
|
|
|
else // 14
|
|
|
|
{
|
|
|
|
newdate = newdate.addMonths(-1);
|
|
|
|
dm = newdate.daysInMonth();
|
|
|
|
newdate = newdate.addDays(( dm < 30 ) ? dm - d : 15 );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return newdate;
|
|
|
|
}
|
|
|
|
|
|
|
|
MyMoneySchedule::occurenceE MyMoneySchedule::stringToOccurence(const TQString& text)
|
|
|
|
{
|
|
|
|
MyMoneySchedule::occurenceE occurence = MyMoneySchedule::OCCUR_ANY;
|
|
|
|
TQString tmp = text.lower();
|
|
|
|
|
|
|
|
if(tmp == i18n("Once").lower())
|
|
|
|
occurence = MyMoneySchedule::OCCUR_ONCE;
|
|
|
|
else if(tmp == i18n("Daily").lower())
|
|
|
|
occurence = MyMoneySchedule::OCCUR_DAILY;
|
|
|
|
else if(tmp == i18n("Weekly").lower())
|
|
|
|
occurence = MyMoneySchedule::OCCUR_WEEKLY;
|
|
|
|
else if(tmp == i18n("Fortnightly").lower())
|
|
|
|
occurence = MyMoneySchedule::OCCUR_FORTNIGHTLY;
|
|
|
|
else if(tmp == i18n("Every other week").lower())
|
|
|
|
occurence = MyMoneySchedule::OCCUR_EVERYOTHERWEEK;
|
|
|
|
else if(tmp == i18n("Every half month").lower())
|
|
|
|
occurence = MyMoneySchedule::OCCUR_EVERYHALFMONTH;
|
|
|
|
else if(tmp == i18n("Every three weeks").lower())
|
|
|
|
occurence = MyMoneySchedule::OCCUR_EVERYTHREEWEEKS;
|
|
|
|
else if(tmp == i18n("Every four weeks").lower())
|
|
|
|
occurence = MyMoneySchedule::OCCUR_EVERYFOURWEEKS;
|
|
|
|
else if(tmp == i18n("Every thirty days").lower())
|
|
|
|
occurence = MyMoneySchedule::OCCUR_EVERYTHIRTYDAYS;
|
|
|
|
else if(tmp == i18n("Monthly").lower())
|
|
|
|
occurence = MyMoneySchedule::OCCUR_MONTHLY;
|
|
|
|
else if(tmp == i18n("Every eight weeks").lower())
|
|
|
|
occurence = MyMoneySchedule::OCCUR_EVERYEIGHTWEEKS;
|
|
|
|
else if(tmp == i18n("Every two months").lower())
|
|
|
|
occurence = MyMoneySchedule::OCCUR_EVERYOTHERMONTH;
|
|
|
|
else if(tmp == i18n("Every three months").lower())
|
|
|
|
occurence = MyMoneySchedule::OCCUR_EVERYTHREEMONTHS;
|
|
|
|
else if(tmp == i18n("Quarterly").lower())
|
|
|
|
occurence = MyMoneySchedule::OCCUR_QUARTERLY;
|
|
|
|
else if(tmp == i18n("Every four months").lower())
|
|
|
|
occurence = MyMoneySchedule::OCCUR_EVERYFOURMONTHS;
|
|
|
|
else if(tmp == i18n("Twice yearly").lower())
|
|
|
|
occurence = MyMoneySchedule::OCCUR_TWICEYEARLY;
|
|
|
|
else if(tmp == i18n("Yearly").lower())
|
|
|
|
occurence = MyMoneySchedule::OCCUR_YEARLY;
|
|
|
|
else if(tmp == i18n("Every other year").lower())
|
|
|
|
occurence = MyMoneySchedule::OCCUR_EVERYOTHERYEAR;
|
|
|
|
|
|
|
|
return occurence;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Helper method to convert simple occurence to compound occurence + multiplier
|
|
|
|
*
|
|
|
|
* @param multiplier Returned by reference. Adjusted multiplier
|
|
|
|
* @param occurence Returned by reference. Occurence type
|
|
|
|
*/
|
|
|
|
void MyMoneySchedule::simpleToCompoundOccurence(int& multiplier,occurenceE& occurence)
|
|
|
|
{
|
|
|
|
occurenceE newOcc = occurence;
|
|
|
|
int newMulti = 1;
|
|
|
|
if (occurence == MyMoneySchedule::OCCUR_ONCE ||
|
|
|
|
occurence == MyMoneySchedule::OCCUR_DAILY ||
|
|
|
|
occurence == MyMoneySchedule::OCCUR_WEEKLY ||
|
|
|
|
occurence == MyMoneySchedule::OCCUR_EVERYHALFMONTH ||
|
|
|
|
occurence == MyMoneySchedule::OCCUR_MONTHLY ||
|
|
|
|
occurence == MyMoneySchedule::OCCUR_YEARLY )
|
|
|
|
{ // Already a base occurence and multiplier
|
|
|
|
}
|
|
|
|
else if(occurence == MyMoneySchedule::OCCUR_FORTNIGHTLY ||
|
|
|
|
occurence == MyMoneySchedule::OCCUR_EVERYOTHERWEEK)
|
|
|
|
{
|
|
|
|
newOcc = MyMoneySchedule::OCCUR_WEEKLY;
|
|
|
|
newMulti = 2;
|
|
|
|
}
|
|
|
|
else if(occurence == MyMoneySchedule::OCCUR_EVERYTHREEWEEKS)
|
|
|
|
{
|
|
|
|
newOcc = MyMoneySchedule::OCCUR_WEEKLY;
|
|
|
|
newMulti = 3;
|
|
|
|
}
|
|
|
|
else if(occurence == MyMoneySchedule::OCCUR_EVERYFOURWEEKS)
|
|
|
|
{
|
|
|
|
newOcc = MyMoneySchedule::OCCUR_WEEKLY;
|
|
|
|
newMulti = 4;
|
|
|
|
}
|
|
|
|
else if(occurence == MyMoneySchedule::OCCUR_EVERYTHIRTYDAYS)
|
|
|
|
{
|
|
|
|
newOcc = MyMoneySchedule::OCCUR_DAILY;
|
|
|
|
newMulti = 30;
|
|
|
|
}
|
|
|
|
else if(occurence == MyMoneySchedule::OCCUR_EVERYEIGHTWEEKS)
|
|
|
|
{
|
|
|
|
newOcc = MyMoneySchedule::OCCUR_WEEKLY;
|
|
|
|
newMulti = 8;
|
|
|
|
}
|
|
|
|
else if(occurence == MyMoneySchedule::OCCUR_EVERYOTHERMONTH)
|
|
|
|
{
|
|
|
|
newOcc = MyMoneySchedule::OCCUR_MONTHLY;
|
|
|
|
newMulti = 2;
|
|
|
|
}
|
|
|
|
else if(occurence == MyMoneySchedule::OCCUR_EVERYTHREEMONTHS ||
|
|
|
|
occurence == MyMoneySchedule::OCCUR_QUARTERLY )
|
|
|
|
{
|
|
|
|
newOcc = MyMoneySchedule::OCCUR_MONTHLY;
|
|
|
|
newMulti = 3;
|
|
|
|
}
|
|
|
|
else if(occurence == MyMoneySchedule::OCCUR_EVERYFOURMONTHS)
|
|
|
|
{
|
|
|
|
newOcc = MyMoneySchedule::OCCUR_MONTHLY;
|
|
|
|
newMulti = 4;
|
|
|
|
}
|
|
|
|
else if(occurence == MyMoneySchedule::OCCUR_TWICEYEARLY)
|
|
|
|
{
|
|
|
|
newOcc = MyMoneySchedule::OCCUR_MONTHLY;
|
|
|
|
newMulti = 6;
|
|
|
|
}
|
|
|
|
else if(occurence == MyMoneySchedule::OCCUR_EVERYOTHERYEAR)
|
|
|
|
{
|
|
|
|
newOcc = MyMoneySchedule::OCCUR_YEARLY;
|
|
|
|
newMulti = 2;
|
|
|
|
}
|
|
|
|
else // Unknown
|
|
|
|
{
|
|
|
|
newOcc = MyMoneySchedule::OCCUR_ANY;
|
|
|
|
newMulti = 1;
|
|
|
|
}
|
|
|
|
if (newOcc != occurence)
|
|
|
|
{
|
|
|
|
occurence = newOcc;
|
|
|
|
multiplier = newMulti == 1 ? multiplier : newMulti * multiplier;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Helper method to convert compound occurence + multiplier to simple occurence
|
|
|
|
*
|
|
|
|
* @param multiplier Returned by reference. Adjusted multiplier
|
|
|
|
* @param occurence Returned by reference. Occurence type
|
|
|
|
*/
|
|
|
|
void MyMoneySchedule::compoundToSimpleOccurence(int& multiplier,occurenceE& occurence)
|
|
|
|
{
|
|
|
|
occurenceE newOcc = occurence;
|
|
|
|
if(occurence == MyMoneySchedule::OCCUR_ONCE)
|
|
|
|
{ // Nothing to do
|
|
|
|
}
|
|
|
|
else if(occurence == MyMoneySchedule::OCCUR_DAILY)
|
|
|
|
{
|
|
|
|
switch (multiplier)
|
|
|
|
{
|
|
|
|
case 1: break;
|
|
|
|
case 30: newOcc = MyMoneySchedule::OCCUR_EVERYTHIRTYDAYS; break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if(newOcc == MyMoneySchedule::OCCUR_WEEKLY)
|
|
|
|
{
|
|
|
|
switch (multiplier)
|
|
|
|
{
|
|
|
|
case 1: break;
|
|
|
|
case 2: newOcc = MyMoneySchedule::OCCUR_EVERYOTHERWEEK; break;
|
|
|
|
case 3: newOcc = MyMoneySchedule::OCCUR_EVERYTHREEWEEKS; break;
|
|
|
|
case 4: newOcc = MyMoneySchedule::OCCUR_EVERYFOURWEEKS; break;
|
|
|
|
case 8: newOcc = MyMoneySchedule::OCCUR_EVERYEIGHTWEEKS; break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if(occurence == MyMoneySchedule::OCCUR_MONTHLY)
|
|
|
|
switch (multiplier)
|
|
|
|
{
|
|
|
|
case 1: break;
|
|
|
|
case 2: newOcc = MyMoneySchedule::OCCUR_EVERYOTHERMONTH; break;
|
|
|
|
case 3: newOcc = MyMoneySchedule::OCCUR_EVERYTHREEMONTHS; break;
|
|
|
|
case 4: newOcc = MyMoneySchedule::OCCUR_EVERYFOURMONTHS; break;
|
|
|
|
case 6: newOcc = MyMoneySchedule::OCCUR_TWICEYEARLY; break;
|
|
|
|
}
|
|
|
|
else if(occurence == MyMoneySchedule::OCCUR_EVERYHALFMONTH)
|
|
|
|
switch (multiplier)
|
|
|
|
{
|
|
|
|
case 1: break;
|
|
|
|
}
|
|
|
|
else if(occurence == MyMoneySchedule::OCCUR_YEARLY)
|
|
|
|
{
|
|
|
|
switch (multiplier)
|
|
|
|
{
|
|
|
|
case 1: break;
|
|
|
|
case 2: newOcc = MyMoneySchedule::OCCUR_EVERYOTHERYEAR; break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (occurence != newOcc ) // Changed to derived type
|
|
|
|
{
|
|
|
|
occurence = newOcc;
|
|
|
|
multiplier = 1;
|
|
|
|
}
|
|
|
|
}
|