[office/kmymoney/5.2] kmymoney/mymoney: Fix detection logic of opening balance transactions
Thomas Baumgart <[email protected]>
| Newsgroups | gmane.comp.kde.cvs |
|---|---|
| Message-ID | <[email protected]> |
Git commit 560678371f6bca10c1a898fac66cb0c26485f3ee by Thomas Baumgart.
Committed on 28/07/2026 at 06:06.
Pushed by tbaumgart into branch '5.2'.
Fix detection logic of opening balance transactions
Also add testcase for the scenario described in the bug report
BUG: 523555
FIXED-IN: 5.2.3
(cherry picked from commit 3bbedfea0b90a367e0bb54edb7af801f845e98ed)
M +10 -9 kmymoney/mymoney/mymoneyfile.cpp
M +53 -0 kmymoney/mymoney/tests/mymoneyfile-test.cpp
M +1 -0 kmymoney/mymoney/tests/mymoneyfile-test.h
https://invent.kde.org/office/kmymoney/-/commit/560678371f6bca10c1a898fac66cb0c26485f3ee
diff --git a/kmymoney/mymoney/mymoneyfile.cpp b/kmymoney/mymoney/mymoneyfile.cpp
index 7c8f43c5f..d8d195292 100644
--- a/kmymoney/mymoney/mymoneyfile.cpp
+++ b/kmymoney/mymoney/mymoneyfile.cpp
@@ -2233,32 +2233,33 @@ QString MyMoneyFile::openingBalanceTransaction(const MyMoneyAccount& acc) const
const auto end = d->journalModel.rowCount();
// look for a transaction with two splits, one referencing
- // acc.id(), the other openAcc.id()
- int matchCount = 0;
+ // acc.id(), the other openAcc.id(). Keep in mind, that an
+ // account can be referenced in multiple splits of the same
+ // transaction
QString lastTxId;
QString txId;
QString splitAccoountId;
QModelIndex idx;
+ QSet<QString> matchedAccountIds;
for (int row = start; row < end; ++row) {
idx = d->journalModel.index(row, 0);
txId = idx.data(eMyMoney::Model::JournalTransactionIdRole).toString();
if (lastTxId != txId) {
- matchCount = 0;
+ matchedAccountIds.clear();
lastTxId = txId;
}
splitAccoountId = idx.data(eMyMoney::Model::SplitAccountIdRole).toString();
- if (splitAccoountId == acc.id())
- ++matchCount;
- else if (splitAccoountId == openAcc.id())
- ++matchCount;
+ if (splitAccoountId == acc.id() || (splitAccoountId == openAcc.id())) {
+ matchedAccountIds.insert(splitAccoountId);
+ }
// if we found both accounts in a transaction we have a match
- if (matchCount == 2) {
+ if (matchedAccountIds.count() == 2) {
return txId;
}
}
// no opening balance transaction found
- return QString();
+ return {};
}
MyMoneyAccount MyMoneyFile::openingBalanceAccount(const MyMoneySecurity& security)
diff --git a/kmymoney/mymoney/tests/mymoneyfile-test.cpp b/kmymoney/mymoney/tests/mymoneyfile-test.cpp
index 35f7bccc2..b67c8b92b 100644
--- a/kmymoney/mymoney/tests/mymoneyfile-test.cpp
+++ b/kmymoney/mymoney/tests/mymoneyfile-test.cpp
@@ -495,6 +495,7 @@ void MyMoneyFileTest::testAddAccounts()
QCOMPARE(a.id(), QLatin1String("A000001"));
QCOMPARE(a.institutionId(), QLatin1String("I000001"));
QCOMPARE(a.currencyId(), QLatin1String("EUR"));
+ QCOMPARE(a.openingDate(), QDate::currentDate());
QCOMPARE(m->dirty(), true);
QCOMPARE(m->asset().accountList().count(), 1);
QCOMPARE(m->asset().accountList().at(0), QLatin1String("A000001"));
@@ -1889,6 +1890,58 @@ void MyMoneyFileTest::testOpeningBalance()
}
}
+void MyMoneyFileTest::testOpeningBalanceMultipleSplits()
+{
+ testAddAccounts();
+
+ MyMoneyAccount openingAcc;
+
+ try {
+ openingAcc = m->openingBalanceAccount(m->baseCurrency());
+ QCOMPARE(openingAcc.parentAccountId(), m->equity().id());
+ QCOMPARE(openingAcc.name(), MyMoneyFile::openingBalancesPrefix());
+ QCOMPARE(openingAcc.openingDate(), QDate::currentDate());
+ } catch (const MyMoneyException& e) {
+ unexpectedException(e);
+ }
+
+ QDate postDate = QDate::currentDate().addDays(15);
+
+ MyMoneyFileTransaction ft;
+ MyMoneyTransaction t;
+
+ // construct a transaction at the day of the last transaction import and add it to the pool
+ t.setPostDate(postDate);
+
+ const auto firstAssetAccountId("A000001");
+ const auto secondAssetAccountId("A000002");
+
+ MyMoneySplit split1;
+
+ split1.setAccountId(firstAssetAccountId);
+ split1.setShares(MyMoneyMoney(-1000, 100));
+ split1.setValue(MyMoneyMoney(-1000, 100));
+ t.addSplit(split1);
+
+ MyMoneySplit split2;
+ split2.setAccountId(secondAssetAccountId);
+ split2.setShares(MyMoneyMoney(500, 100));
+ split2.setValue(MyMoneyMoney(500, 100));
+ for (int i = 0; i < 2; ++i) {
+ split2.clearId();
+ t.addSplit(split2);
+ }
+
+ m->addTransaction(t);
+ ft.commit();
+
+ const auto firstAssetAccount = m->account(firstAssetAccountId);
+ const auto secondAssetAccount = m->account(secondAssetAccountId);
+
+ QCOMPARE(m->openingBalanceTransaction(firstAssetAccount), QString());
+ QCOMPARE(m->openingBalanceTransaction(secondAssetAccount), QString());
+}
+
void MyMoneyFileTest::testModifyStdAccount()
{
QVERIFY(m->asset().currencyId().isEmpty());
diff --git a/kmymoney/mymoney/tests/mymoneyfile-test.h b/kmymoney/mymoney/tests/mymoneyfile-test.h
index b1bf209b8..63ccfb6f0 100644
--- a/kmymoney/mymoney/tests/mymoneyfile-test.h
+++ b/kmymoney/mymoney/tests/mymoneyfile-test.h
@@ -68,6 +68,7 @@ private Q_SLOTS:
void testBaseCurrency();
void testOpeningBalanceNoBase();
void testOpeningBalance();
+ void testOpeningBalanceMultipleSplits();
void testAddPrice();
void testRemovePrice();
void testGetPrice();