File indexing completed on 2024-05-12 05:06:44
0001 /* 0002 SPDX-FileCopyrightText: 2002-2019 Thomas Baumgart <tbaumgart@kde.org> 0003 SPDX-FileCopyrightText: 2004 Kevin Tambascio <ktambascio@users.sourceforge.net> 0004 SPDX-FileCopyrightText: 2005-2006 Ace Jones <acejones@users.sourceforge.net> 0005 SPDX-FileCopyrightText: 2017-2018 Łukasz Wojniłowicz <lukasz.wojnilowicz@gmail.com> 0006 SPDX-License-Identifier: GPL-2.0-or-later 0007 */ 0008 0009 #include "mymoneysplit.h" 0010 #include "mymoneysplit_p.h" 0011 0012 // ---------------------------------------------------------------------------- 0013 // QT Includes 0014 0015 #include <QSet> 0016 0017 // ---------------------------------------------------------------------------- 0018 // KDE Includes 0019 0020 // ---------------------------------------------------------------------------- 0021 // Project Includes 0022 0023 #include "mymoneyutils.h" 0024 #include "mymoneytransaction.h" 0025 #include "mymoneyexception.h" 0026 0027 MyMoneySplit::MyMoneySplit() : 0028 MyMoneyObject(*new MyMoneySplitPrivate) 0029 { 0030 } 0031 0032 MyMoneySplit::MyMoneySplit(const QString &id) : 0033 MyMoneyObject(*new MyMoneySplitPrivate, id) 0034 { 0035 Q_D(MyMoneySplit); 0036 d->m_reconcileFlag = eMyMoney::Split::State::NotReconciled; 0037 } 0038 0039 MyMoneySplit::MyMoneySplit(const MyMoneySplit& other) : 0040 MyMoneyObject(*new MyMoneySplitPrivate(*other.d_func()), other.id()), 0041 MyMoneyKeyValueContainer(other) 0042 { 0043 } 0044 0045 MyMoneySplit::MyMoneySplit(const QString& id, const MyMoneySplit& other) : 0046 MyMoneyObject(*new MyMoneySplitPrivate(*other.d_func()), id), 0047 MyMoneyKeyValueContainer(other) 0048 { 0049 } 0050 0051 MyMoneySplit::~MyMoneySplit() 0052 { 0053 } 0054 0055 bool MyMoneySplit::operator == (const MyMoneySplit& right) const 0056 { 0057 Q_D(const MyMoneySplit); 0058 auto d2 = static_cast<const MyMoneySplitPrivate *>(right.d_func()); 0059 // clang-format off 0060 return MyMoneyObject::operator==(right) 0061 && MyMoneyKeyValueContainer::operator==(right) 0062 && d->m_account == d2->m_account 0063 && d->m_costCenter == d2->m_costCenter 0064 && d->m_payee == d2->m_payee 0065 && d->m_tagList == d2->m_tagList 0066 && d->m_memo == d2->m_memo 0067 && d->m_action == d2->m_action 0068 && d->m_reconcileDate == d2->m_reconcileDate 0069 && d->m_reconcileFlag == d2->m_reconcileFlag 0070 && ((d->m_number.length() == 0 && d2->m_number.length() == 0) || d->m_number == d2->m_number) 0071 && d->m_shares == d2->m_shares 0072 && d->m_value == d2->m_value 0073 && d->m_price == d2->m_price 0074 && d->m_transactionId == d2->m_transactionId; 0075 // clang-format on 0076 } 0077 0078 MyMoneySplit MyMoneySplit::operator-() const 0079 { 0080 MyMoneySplit rc(*this); 0081 rc.d_func()->m_shares = -rc.d_func()->m_shares; 0082 rc.d_func()->m_value = -rc.d_func()->m_value; 0083 return rc; 0084 } 0085 0086 QString MyMoneySplit::accountId() const 0087 { 0088 Q_D(const MyMoneySplit); 0089 return d->m_account; 0090 } 0091 0092 void MyMoneySplit::setAccountId(const QString& account) 0093 { 0094 Q_D(MyMoneySplit); 0095 d->m_account = account; 0096 d->clearReferences(); 0097 } 0098 0099 QString MyMoneySplit::costCenterId() const 0100 { 0101 Q_D(const MyMoneySplit); 0102 return d->m_costCenter; 0103 } 0104 0105 void MyMoneySplit::setCostCenterId(const QString& costCenter) 0106 { 0107 Q_D(MyMoneySplit); 0108 d->m_costCenter = costCenter; 0109 d->clearReferences(); 0110 } 0111 0112 QString MyMoneySplit::memo() const 0113 { 0114 Q_D(const MyMoneySplit); 0115 return d->m_memo; 0116 } 0117 0118 void MyMoneySplit::setMemo(const QString& memo) 0119 { 0120 Q_D(MyMoneySplit); 0121 d->m_memo = memo; 0122 } 0123 0124 eMyMoney::Split::State MyMoneySplit::reconcileFlag() const 0125 { 0126 Q_D(const MyMoneySplit); 0127 return d->m_reconcileFlag; 0128 } 0129 0130 QDate MyMoneySplit::reconcileDate() const 0131 { 0132 Q_D(const MyMoneySplit); 0133 return d->m_reconcileDate; 0134 } 0135 0136 void MyMoneySplit::setReconcileDate(const QDate& date) 0137 { 0138 Q_D(MyMoneySplit); 0139 d->m_reconcileDate = date; 0140 } 0141 0142 void MyMoneySplit::setReconcileFlag(const eMyMoney::Split::State flag) 0143 { 0144 Q_D(MyMoneySplit); 0145 d->m_reconcileFlag = flag; 0146 } 0147 0148 MyMoneyMoney MyMoneySplit::shares() const 0149 { 0150 Q_D(const MyMoneySplit); 0151 return d->m_shares; 0152 } 0153 0154 void MyMoneySplit::setShares(const MyMoneyMoney& shares) 0155 { 0156 Q_D(MyMoneySplit); 0157 d->m_shares = shares; 0158 } 0159 0160 void MyMoneySplit::negateShares() 0161 { 0162 Q_D(MyMoneySplit); 0163 d->m_shares = -d->m_shares; 0164 } 0165 0166 QString MyMoneySplit::value(const QString& key) const 0167 { 0168 return MyMoneyKeyValueContainer::value(key); 0169 } 0170 0171 void MyMoneySplit::setValue(const QString& key, const QString& value, const QString& defaultValue) 0172 { 0173 MyMoneyKeyValueContainer::setValue(key, value, defaultValue); 0174 } 0175 0176 void MyMoneySplit::setValue(const MyMoneyMoney& value) 0177 { 0178 Q_D(MyMoneySplit); 0179 d->m_value = value; 0180 } 0181 0182 void MyMoneySplit::setValue(const MyMoneyMoney& value, const QString& transactionCurrencyId, const QString& splitCurrencyId) 0183 { 0184 if (transactionCurrencyId == splitCurrencyId) 0185 setValue(value); 0186 else 0187 setShares(value); 0188 } 0189 0190 void MyMoneySplit::negateValue() 0191 { 0192 Q_D(MyMoneySplit); 0193 d->m_value = -d->m_value; 0194 } 0195 0196 QString MyMoneySplit::payeeId() const 0197 { 0198 Q_D(const MyMoneySplit); 0199 return d->m_payee; 0200 } 0201 0202 void MyMoneySplit::setPayeeId(const QString& payee) 0203 { 0204 Q_D(MyMoneySplit); 0205 d->m_payee = payee; 0206 d->clearReferences(); 0207 } 0208 0209 QList<QString> MyMoneySplit::tagIdList() const 0210 { 0211 Q_D(const MyMoneySplit); 0212 return d->m_tagList; 0213 } 0214 0215 void MyMoneySplit::setTagIdList(const QList<QString>& tagList) 0216 { 0217 Q_D(MyMoneySplit); 0218 d->m_tagList = tagList; 0219 d->clearReferences(); 0220 } 0221 0222 void MyMoneySplit::setAction(eMyMoney::Split::InvestmentTransactionType type) 0223 { 0224 switch (type) { 0225 case eMyMoney::Split::InvestmentTransactionType::BuyShares: 0226 case eMyMoney::Split::InvestmentTransactionType::SellShares: 0227 setAction(actionName(Split::Action::BuyShares)); 0228 break; 0229 case eMyMoney::Split::InvestmentTransactionType::Dividend: 0230 setAction(actionName(Split::Action::Dividend)); 0231 break; 0232 case eMyMoney::Split::InvestmentTransactionType::Yield: 0233 setAction(actionName(Split::Action::Yield)); 0234 break; 0235 case eMyMoney::Split::InvestmentTransactionType::ReinvestDividend: 0236 setAction(actionName(Split::Action::ReinvestDividend)); 0237 break; 0238 case eMyMoney::Split::InvestmentTransactionType::AddShares: 0239 case eMyMoney::Split::InvestmentTransactionType::RemoveShares: 0240 setAction(actionName(Split::Action::AddShares)); 0241 break; 0242 case eMyMoney::Split::InvestmentTransactionType::SplitShares: 0243 setAction(actionName(Split::Action::SplitShares)); 0244 break; 0245 case eMyMoney::Split::InvestmentTransactionType::InterestIncome: 0246 setAction(actionName(Split::Action::InterestIncome)); 0247 break; 0248 case eMyMoney::Split::InvestmentTransactionType::UnknownTransactionType: 0249 break; 0250 } 0251 } 0252 0253 eMyMoney::Split::InvestmentTransactionType MyMoneySplit::investmentTransactionType() const 0254 { 0255 Q_D(const MyMoneySplit); 0256 switch(actionStringToAction(d->m_action)) { 0257 case Split::Action::BuyShares: 0258 return (d->m_shares.isNegative()) ? Split::InvestmentTransactionType::SellShares : Split::InvestmentTransactionType::BuyShares; 0259 0260 case Split::Action::Dividend: 0261 return Split::InvestmentTransactionType::Dividend; 0262 0263 case Split::Action::Yield: 0264 return Split::InvestmentTransactionType::Yield; 0265 0266 case Split::Action::ReinvestDividend: 0267 return Split::InvestmentTransactionType::ReinvestDividend; 0268 0269 case Split::Action::AddShares: 0270 return (d->m_shares.isNegative()) ? Split::InvestmentTransactionType::RemoveShares : Split::InvestmentTransactionType::AddShares; 0271 0272 case Split::Action::SplitShares: 0273 return Split::InvestmentTransactionType::SplitShares; 0274 0275 case Split::Action::InterestIncome: 0276 return Split::InvestmentTransactionType::InterestIncome; 0277 0278 default: 0279 return Split::InvestmentTransactionType::UnknownTransactionType; 0280 } 0281 } 0282 0283 QString MyMoneySplit::action() const 0284 { 0285 Q_D(const MyMoneySplit); 0286 return d->m_action; 0287 } 0288 0289 void MyMoneySplit::setAction(const QString& action) 0290 { 0291 Q_D(MyMoneySplit); 0292 d->m_action = action; 0293 } 0294 0295 bool MyMoneySplit::isAmortizationSplit() const 0296 { 0297 Q_D(const MyMoneySplit); 0298 return d->m_action == actionName(Split::Action::Amortization); 0299 } 0300 0301 bool MyMoneySplit::isInterestSplit() const 0302 { 0303 Q_D(const MyMoneySplit); 0304 return d->m_action == actionName(Split::Action::Interest); 0305 } 0306 0307 QString MyMoneySplit::number() const 0308 { 0309 Q_D(const MyMoneySplit); 0310 return d->m_number; 0311 } 0312 0313 void MyMoneySplit::setNumber(const QString& number) 0314 { 0315 Q_D(MyMoneySplit); 0316 d->m_number = number; 0317 } 0318 0319 bool MyMoneySplit::isAutoCalc() const 0320 { 0321 Q_D(const MyMoneySplit); 0322 return (d->m_shares == MyMoneyMoney::autoCalc) || (d->m_value == MyMoneyMoney::autoCalc); 0323 } 0324 0325 QString MyMoneySplit::bankID() const 0326 { 0327 Q_D(const MyMoneySplit); 0328 return d->m_bankID; 0329 } 0330 0331 void MyMoneySplit::setBankID(const QString& bankID) 0332 { 0333 Q_D(MyMoneySplit); 0334 d->m_bankID = bankID; 0335 } 0336 0337 QString MyMoneySplit::transactionId() const 0338 { 0339 Q_D(const MyMoneySplit); 0340 return d->m_transactionId; 0341 } 0342 0343 void MyMoneySplit::setTransactionId(const QString& id) 0344 { 0345 Q_D(MyMoneySplit); 0346 d->m_transactionId = id; 0347 } 0348 0349 0350 MyMoneyMoney MyMoneySplit::value() const 0351 { 0352 Q_D(const MyMoneySplit); 0353 return d->m_value; 0354 } 0355 0356 MyMoneyMoney MyMoneySplit::value(const QString& transactionCurrencyId, const QString& splitCurrencyId) const 0357 { 0358 Q_D(const MyMoneySplit); 0359 return (transactionCurrencyId == splitCurrencyId) ? d->m_value : d->m_shares; 0360 } 0361 0362 void MyMoneySplit::setPrice(const MyMoneyMoney& price) 0363 { 0364 Q_D(MyMoneySplit); 0365 d->m_price = price; 0366 } 0367 0368 MyMoneyMoney MyMoneySplit::price() const 0369 { 0370 Q_D(const MyMoneySplit); 0371 if (!d->m_price.isZero()) 0372 return d->m_price; 0373 if (!d->m_value.isZero() && !d->m_shares.isZero()) 0374 return d->m_value / d->m_shares; 0375 return MyMoneyMoney::ONE; 0376 } 0377 0378 bool MyMoneySplit::isMatched() const 0379 { 0380 Q_D(const MyMoneySplit); 0381 return d->m_isMatched; 0382 } 0383 0384 void MyMoneySplit::addMatch(const MyMoneyTransaction& _t) 0385 { 0386 Q_D(MyMoneySplit); 0387 // now we allow matching of two manual transactions 0388 d->m_matchedTransaction = _t; 0389 d->m_matchedTransaction.clearId(); 0390 d->m_isMatched = true; 0391 } 0392 0393 void MyMoneySplit::removeMatch() 0394 { 0395 Q_D(MyMoneySplit); 0396 d->m_matchedTransaction = MyMoneyTransaction(); 0397 d->m_isMatched = false; 0398 } 0399 0400 MyMoneyTransaction MyMoneySplit::matchedTransaction() const 0401 { 0402 Q_D(const MyMoneySplit); 0403 if (d->m_isMatched) 0404 return d->m_matchedTransaction; 0405 0406 return MyMoneyTransaction(); 0407 } 0408 0409 bool MyMoneySplit::replaceId(const QString& newId, const QString& oldId) 0410 { 0411 auto changed = false; 0412 Q_D(MyMoneySplit); 0413 0414 if (d->m_payee == oldId) { 0415 d->m_payee = newId; 0416 changed = true; 0417 } else if (d->m_account == oldId) { 0418 d->m_account = newId; 0419 changed = true; 0420 } else if (d->m_costCenter == oldId) { 0421 d->m_costCenter = newId; 0422 changed = true; 0423 } 0424 0425 if (isMatched()) { 0426 MyMoneyTransaction t = matchedTransaction(); 0427 if (t.replaceId(newId, oldId)) { 0428 removeMatch(); 0429 addMatch(t); 0430 changed = true; 0431 } 0432 } 0433 0434 return changed; 0435 } 0436 0437 QHash<Split::Action, QString> actionNamesLUT() 0438 { 0439 static const QHash<Split::Action, QString> actionNames { 0440 {Split::Action::Check, QStringLiteral("Check")}, 0441 {Split::Action::Deposit, QStringLiteral("Deposit")}, 0442 {Split::Action::Transfer, QStringLiteral("Transfer")}, 0443 {Split::Action::Withdrawal, QStringLiteral("Withdrawal")}, 0444 {Split::Action::ATM, QStringLiteral("ATM")}, 0445 {Split::Action::Amortization, QStringLiteral("Amortization")}, 0446 {Split::Action::Interest, QStringLiteral("Interest")}, 0447 {Split::Action::BuyShares, QStringLiteral("Buy")}, 0448 {Split::Action::Dividend, QStringLiteral("Dividend")}, 0449 {Split::Action::ReinvestDividend, QStringLiteral("Reinvest")}, 0450 {Split::Action::Yield, QStringLiteral("Yield")}, 0451 {Split::Action::AddShares, QStringLiteral("Add")}, 0452 {Split::Action::SplitShares, QStringLiteral("Split")}, 0453 {Split::Action::InterestIncome, QStringLiteral("IntIncome")}, 0454 }; 0455 return actionNames; 0456 } 0457 0458 QString MyMoneySplit::actionName(Split::Action action) 0459 { 0460 return actionNamesLUT().value(action); 0461 } 0462 0463 Split::Action MyMoneySplit::actionStringToAction(const QString &text) const 0464 { 0465 return actionNamesLUT().key(text, Split::Action::Unknown); 0466 }