> On Nov 13, 2021, at 8:41 PM, Lionel Élie Mamane <lio...@mamane.lu> wrote:
> 
> Hi,
> 
> I've started work on adding support to compute capital gains in
> multi-currency situations; that is, when a lot from a
> security-denominated account contains transactions with different
> common currencies.
> 
> I have a "it works" patch in bugzilla
> https://bugs.gnucash.org/show_bug.cgi?id=798366
> Not very thoroughly tested in many scenarios, and see point 5 below.
> 
> 1) It contains naked asserts, peeking at the rest of the code, I guess
>   I should replace them with g_assert
> 
> 2) It changes the declaration (argument list / return type) of
>   xaccSplitGetCapGains
>   gnc_lot_get_balance_before
> 
>   These had only one caller in the GnuCash code each.
>   I'm not sure if those are considered public stable API? The Debian
>   packaging doesn't have separate libgnucash / libgnucash-dev
>   packages, and the .so files seem not to be soname-versioned? So
>   there is no concept of stable API at all in libgnucash?
> 
> 3) Since the capital gain is not anymore in the same currency as every
>   split it is computed over, xaccSplitGetCapGains now needs to return
>   not only a value (a gnc_numeric), but also the associated currency.
> 
>   I created a struct for that, but I'm unhappy with the name. Any
>   better idea? And where to declare it? It sounds like it could
>   potentially be useful "throughout the code"? I'd call it "value_t"
>   or "amount_t" or some such (because a number without
>   unit/currency/commodity is meaningless, so in my mind a "value" or
>   an "amount" is with commodity), but this does not find with the how
>   these terms are used throughout the code...
> 
>   struct amount_s
>   {
>      gnc_numeric amount;
>      gnc_commodity *commodity;
>   };
>   typedef struct amount_s amount_commodity;
> 
> 
> 4) The design choice is that the capital gain is _always_ computed in
>   the currency of the first currency-denominated ancestor of the
>   security-denominated account, even when all the splits in the lot
>   are otherwise in a single other currency. This lets the user
>   control the behaviour through the account hierarchy:
> 
>   All investments under a EUR-denominated "investments" account: all
>   capital gains are in EUR, to follow the tax rule.
> 
>   Want to track different portfolios under different currencies
>   (e.g. because they belong to different branches in different
>   countries, or because that's more important than computing the
>   right capital gains according to tax rules)? Create a placeholder
>   account for each portfolio, denominated in the chosen currency, and
>   put the securities accounts as subaccounts of this one.
> 
> 
>   This will _change_ _behaviour_ from previous versions in the
>   aforementioned case (all the splits in the lot are otherwise in a
>   single other currency). I think making an exception, and computing
>   capital gains in the common currency of the splits in the lot (or
>   the whole account) when there is one, and in another currency when
>   there is no common currency in the lot, would be too messy
>   semantics, and a too "unstable" behaviour. By "unstable" I mean too
>   big behaviour changes in response to small changes in data. It
>   would also fail to serve the above scenarios which I have in mind.
> 
>   OTOH, the change of behaviour between versions is also not
>   attractive.
> 
>   What to do? Does GnuCash have a mechanism to mark files as
>   backwards-incompatible (e.g. a "minimum version needed" tag)? We
>   could then mark it so as soon as a capital gain is computed in a
>   currency different than any of the splits in the lot.
> 
>   Or, we could make the behaviour a per-file option, with:
> 
>   - The default for _new_ files being the new better behaviour.
>   - Any file where the option is not set (that is, an older file), is
>     considered as having the option set for the old behaviour.
>   - Any file that doesn't have the option set, the setting is _not_
>     written on save (so as not to confuse older versions with an XML
>     tag they don't know).
> 
>   This keeps backwards and upwards compatibility; it does have the
>   disadvantage that all existing users must explicitly opt in to the
>   better behaviour. Maybe we could automatically opt in any file
>   where all already computed capital gains are in the currency that
>   the new behaviour would choose, too?
> 
> 
> 5) Quite possibly my patch doesn't 100% deal correctly with scenarios
>   where the currency of the ancestor account changes; the code that
>   decides to mark capital gains as "dirty" needs to be made
>   currency-aware, and the code that changes the capital gains split
>   should reset the income account of the capital gains
>   transaction. Haven't looked into that yet. TOOD.

Sorry I didn't intervene sooner. You need to read through 
https://bugs.gnucash.org/show_bug.cgi?id=797796 
<https://bugs.gnucash.org/show_bug.cgi?id=797796> before doing any more work 
because your approach doesn't support the GAAP/IAS requirements. Much of the 
rest of GnuCash doesn't either, but there's no point in doing a lot of work 
that doesn't move us in the direction of being legal.

To your specific questions:

1. assert vs. g_assert: Doesn't really matter, they do the same thing. Neither 
is particularly useful in production code because they're macros that are 
disabled in release builds. They're useful for catching programming errors with 
unit tests. Your patch doesn't have any of those so there's no point in 
asserting anything. If you need to do things like null-checks to prevent 
crashes use g_return_if_fail or g_return_value_if_fail, which log a critical 
error and return, preventing the crash.

2. We make no stability guarantees for libgnucash at present. We have a 
long-term goal to do so, but the current API is rather haphazard and needs 
substantial clean up before we'd be willing to do so. It also has serious 
memory-management issues when used outside of the application so part of the 
required work is to rewrite the whole thing in C++, replacing the already 
incorrect GObject implementation. This has been discussed at great length over 
the last 10-12 years. If you're interested you can look through the mailing 
list archives.

3. There's already a struct combining commodity with gnc_numeric amount called 
gnc_monetary, declared in libgnucash/engine/gnc-commodity.h.

4a. The GAAP/IAS requirement is that all transactions get valued in the book's 
home currency on the day of the transaction using either an actual exchange 
rate if funds were converted that day or an average rate for the day if they 
weren't. One of the participants in bug 797796, CDB-Man, is a licensed 
accountant. The discussion on that bug is quite comprehensive and I won't 
attempt to summarize it. It's actually a pretty substantial simplification over 
what you've planned.

4b. Yes, GnuCash has a backward compatibility policy and a GncFeature component 
(libgnucash/engine/gnc-feature.[hc]) to test whether an older version of 
GnuCash can safely work with a book.

4c. Apropos the book property proposal, do you know about and understand 
Trading Accounts? Enabling use of trading accounts changes the behavior of the 
register in multi-commodity transactions. Neither cap-gains.c nor 
dialog-lot-viewer.c check for using trading accounts; perhaps they should.

5. I'm not sure what you mean here. If the code doesn't mark the splits dirty 
then they won't get saved in the SQL backends and all of your changes are for 
naught. If you mean that nothing marks the capital gain needing to be 
recomputed if the user edits the sell transaction that's OK, re-running the lot 
scrub from the dialog will find the imbalance and create an additional split.

Some general observations: 

First, it will be far more productive for both of us if you'll resubmit your 
patch as a Github pull request. Code reviewing patch files in bug reports and 
keeping track of the changes is quite painful, and the larger the patch is the 
more painful managing the reviews and review comment corrections gets.

No patch containing commented code is acceptable. Remove it instead. It makes 
the diff more understandable and prevents the accumulation of cruft.

As evidenced by bug 797796 and the bugs you've created and commented on in the 
last few days this problem is quite a bit bigger than just the lot scrubber. 
Addressing it piecemeal, particularly with piecemeal design goals, will just 
add to the huge amount of technical debt we have already. 

Regards,
John Ralls



_______________________________________________
gnucash-devel mailing list
gnucash-devel@gnucash.org
https://lists.gnucash.org/mailman/listinfo/gnucash-devel

Reply via email to