When using check forms that contain a log for record keeping it is needed to print out all of the splits associated with a transaction when printing a check. This cannot be done since the split variables are not present in the check printing plugin. This patch will add the variables SplitAccountName and SplitValue for up to 11 splits within a transaction. The check template will then be able to access the split variables and print them when printing a check.
Details
- Reviewers
tbaumgart - Group Reviewers
KMyMoney - Commits
- R261:d12a2e01a35a: Adding additional variable to check printing
R261:170802710724: Adding additional variable to check printing
Diff Detail
- Repository
- R261 KMyMoney
- Lint
Automatic diff as part of commit; lint not applicable. - Unit
Automatic diff as part of commit; unit tests not applicable.
kmymoney/plugins/checkprinting/checkprinting.cpp | ||
---|---|---|
209 | Indentation seems to be off here. | |
218 | A bit of improved and more Qt style version of the above: for (int i = 0; i < 11; ++i) { const QString valueVariable = QString("$SPLITVALUE%1").arg(i); const QString accountVariable = QString("$SPLITACCOUNTNAME%1").arg(i); if (i < numSplits) { so no need to use std::string and a lot of conversion back and forth. | |
219 | A split could be denominated in a different currency (depending on the account found in splits()[i].accountId() ). This is not supported with your code. See e.g. line 206 above how to do a possible conversion. | |
222 | Variable names need to be adjusted according to the above change. |
Thanks for the feedback, my C++ skills are way out of date. I have made two of the three changes that were suggested. I do not understand the one about the currency and you reference line 206. That line gives the value in text not numbers. Line 207 gives the value in numbers and should be modified by the currency. My line 214 should give the value in numbers and is identical to line 207. It should be modified by the currency. If I am wrong please let me know.
I hope these changes fix the problems. Again thanks.
kmymoney/plugins/checkprinting/checkprinting.cpp | ||
---|---|---|
10 | Change these checkHTML.replace( valueVariable, MyMoneyUtils::formatMoney((*it).transaction().splits()[i].shares().abs(), currency)); checkHTML.replace( accountVariable, (file->account((*it).transaction().splits()[i].accountId())).name()); to const MyMoneyAccount splitAccount = file->account((*it).transaction().splits()[i].accountId()); const MyMoneySecurity accountCurrency = file->currency(account.currencyId()); checkHTML.replace( valueVariable, MyMoneyUtils::formatMoney((*it).transaction().splits()[i].shares().abs(), accountCurrency)); checkHTML.replace( accountVariable, splitAccount.name()); | |
215 | Change these checkHTML.replace( valueVariable, MyMoneyUtils::formatMoney((*it).transaction().splits()[i].shares().abs(), currency)); checkHTML.replace( accountVariable, (file->account((*it).transaction().splits()[i].accountId())).name()); to const MyMoneyAccount splitAccount = file->account((*it).transaction().splits()[i].accountId()); const MyMoneySecurity accountCurrency = file->currency(account.currencyId()); checkHTML.replace( valueVariable, MyMoneyUtils::formatMoney((*it).transaction().splits()[i].shares().abs(), accountCurrency)); checkHTML.replace( accountVariable, splitAccount.name()); See also my explanation in the other comment. | |
219 | Sorry about the confusion. Not seeing the full context of the function here in the patch, I thought convert() does currency conversion but it rather converts a number into text. Nevertheless, we need to take into account here that a split can be denominated in a different currency than the original one (multi-currency). The shares() method of a split always returns the amount in the currency of the account/category of the split. The value() method of the split returns the value in the common currency of the transaction, hence shares()/value() is the exchange rate used when entering the transaction. Using shares() with the currency of the transaction might therefore not be correct and you get false results. Of course, you won't notice any of the above if you only have one currency on file. |
I have replaced shares with value in: checkHTML.replace( valueVariable, MyMoneyUtils::formatMoney((*it).transaction().splits()[i].value().abs(), currency));.
As has been pointed out if one or more of the splits are in a different currency shares will give the wrong amount for the split.
kmymoney/plugins/checkprinting/checkprinting.cpp | ||
---|---|---|
219 | I have replaced shares with value due to the potential currency problems. This should give the proper amount. |
kmymoney/plugins/checkprinting/checkprinting.cpp | ||
---|---|---|
207 | The two lines here should then also use the split().value() method. Also, see my comment below. | |
219 | This might bite you. currency currently represents the currency in which the selected split's account/category is denominated. Depending on the circumstances, this may not be the currency in which the value is represented. The split's value is always given in the currency provided as (*it).transaction().commodity(). But this may be different from the currency of your split. I know this will never happen in a single currency dataset, but it can if you manage your finances in multiple currencies and we shoud be prepared, since I know of users who do that. |
questions
kmymoney/plugins/checkprinting/checkprinting.cpp | ||
---|---|---|
219 | Thomas, Thanks for all of your advice, it has been helpful. I haven't written C++ in over 15 years so I am very rusty. With that said I am somewhat confused. I thought that by changing to value() is would show in the amount of the currency for the split but I don't understand wat else I should do here? Should I be showing the exchange rate? or something else? any advice will be appreciated. Phil |
kmymoney/plugins/checkprinting/checkprinting.cpp | ||
---|---|---|
209 | It must have slipped through, but could you name the variable numSplits (lowercase initial letter). Also, you can safely make it a const int instead of int because it may not change anyway in this context. | |
210 | Can you make the 11 a named constant? E.g. in the beginning of this function around line 166 by saying const int maxSplits = 11; and using maxSplits in the above for-loop? | |
219 | This is not C++ related but how the application manages the data. Each split has two attributes: shares and value. Each transaction is denominated in a currency (transaction.currency()). The sum of the value attributes over all splits of a transaction must be zero for the transaction to be balanced (that is what double entry accounting is all about), where it does not matter in which currency that happens. The shares attribute represents the units in the currency of the account that the split references. So the sum of all shares over all splits of a specific account provides the balance of the account. In the end, it depends on how you want the different currencies printed on the check. All this is only important in case one has multiple currencies. I just want to avoid that we add some code that works in single currency environments but gives the user a headache when using it with multiple currencies. My initial code suggestion was to use the share value and print the respective currency symbol. This is correct and easy to accomplish. Everything else is much more complex as there are more corner cases. Hope that makes it a bit more meaningful. If not, please let me know. |
kmymoney/plugins/checkprinting/checkprinting.cpp | ||
---|---|---|
219 | Thanks, I agree I want this to be a generalized solution, not one that just works for me. I will add a variable to allow the curriency for the transaction to be printed. I am not sure if that is enough, though. Is there anything ese that I should include? Any I do realize that this is not a C++ issue but one of properly offering clear data to the user. Thanks again for your help. Phil |
kmymoney/plugins/checkprinting/checkprinting.cpp | ||
---|---|---|
219 | I do notice that for the transaction this seems to be transaction().commodity(). Phil |
kmymoney/plugins/checkprinting/checkprinting.cpp | ||
---|---|---|
219 | transaction.commodity() is the currency of the account in which the transaction was entered (either manually or via import). So in most cases (when the user also prints the check from this account) it is OK to use it for our purpose here. |
kmymoney/plugins/checkprinting/checkprinting.cpp | ||
---|---|---|
209 | If I look at what is in the database for my user, I see "USD" not the ISO code. If the ISO code is stored for other currencies, how do I convert it to the currenctSysmbol()? Something like: |
kmymoney/plugins/checkprinting/checkprinting.cpp | ||
---|---|---|
209 | Well, USD is the ISO 4217 code said currency. See https://en.wikipedia.org/wiki/ISO_4217 To get the currency symbol you go as follows: const auto currencyId = (*it).transaction().commodity(); const auto currency = MyMoneyFile::instance()->currency(currencyId); checkHTML.replace("$TRANSACTIONCURRENCY", currency.tradingSymbol()); |
Please change NumSplits into numSplits before you commit. Or do you want me do add it to the repository?
Corrected variable name numSplits.
Thomas, What needs to be done now? I am at a loss now - how does this get merged into the code base?
Phil