Alex,

I don’t think it’s necessary to explicitly remove the slot in 
xaccAccountGetTaxUSCopyNumber, the slot will get removed automatically in 
guI_to_accounts.  Just adding the *copy_number test is sufficient to deal with 
0 getting stored in the slot.

Regards,
John Ralls



> On Feb 5, 2025, at 17:02, Alex Aycinena <alex.aycin...@gmail.com> wrote:
> 
> John,
> 
> Thanks for your quick response.
> 
> If I followed you correctly, this is what I will change and test:
> 
> gint64
> xaccAccountGetTaxUSCopyNumber (const Account *acc)
> {
>     auto copy_number = get_kvp_int64_path (acc, {"tax-US", "copy-number"});
>     if (copy_number && *copy_number == 0) 
>            /* this is here to clean up any KVPs set to zero due to prior bug 
> */
>            /* if copy_number exists and its value is zero get rid of KVP and 
> return 1 */
>            {
>                   set_kvp_int64_path (acc, {"tax-US", "copy-number"}, 
> std::nullopt);
>                  return 1;
>             }
>        return (copy_number && *copy_number) ? *copy_number : 1;
> }
> 
> void
> xaccAccountSetTaxUSCopyNumber (Account *acc, gint64 copy_number)
> {
>           set_kvp_int64_path (acc, {"tax-US", "copy-number"}, (copy_number && 
> *copy_number != 0) ? copy_number : std::nullopt);
> }
> 
> In the 'Set' routine, I added the need for the copy_number to exist and the 
> value to not be zero, otherwise the KVP is removed.
> 
> Appreciate your feedback.
> 
> Reagrds,
> 
> Alex
> 
> On Tue, Feb 4, 2025 at 8:55 PM John Ralls <jra...@ceridwen.us 
> <mailto:jra...@ceridwen.us>> wrote:
>> Alex,
>> 
>> That commit is part of https://github.com/Gnucash/gnucash/pull/1965.
>> 
>> Your first proposed change isn’t quite right because a the 
>> std::optional<T>::operator==(T) returns false if the optional doesn’t 
>> contain a value (see cases 21-33 in 
>> https://en.cppreference.com/w/cpp/utility/optional/operator_cmp). You want
>>    (copy_number && *copy_number) ? *copy_number : 1;
>> 
>> *But* the assumption behind the original code is that if the copy_number was 
>> 0 then get_kvp_int64_path would have returned std::nullopt because 
>> set_kvp_path<T>(path, nullptr) calls (indirectly) 
>> KvpFrame::;set_impl(https://github.com/Gnucash/gnucash/blob/b5c1937702ca7a8fba772a47b2ac7fa6b8857bf5/libgnucash/engine/kvp-frame.cpp#L101)
>>  and that removes the path if it’s passed a false value; nulltpr is false. 
>> qof_instance_get_path_kvp 
>> https://github.com/Gnucash/gnucash/blob/b5c1937702ca7a8fba772a47b2ac7fa6b8857bf5/libgnucash/engine/qofinstance.cpp#L1068)
>>  bases that on getting a nullptr from KvpFrame::get_slot 
>> (https://github.com/Gnucash/gnucash/blob/b5c1937702ca7a8fba772a47b2ac7fa6b8857bf5/libgnucash/engine/kvp-frame.cpp#L144).
>>  
>> 
>> I think you’re right about 
>>> void
>>> xaccAccountSetTaxUSCopyNumber (Account *acc, gint64 copy_number)
>>> {
>>>     set_kvp_int64_path (acc, {"tax-US", "copy-number"}, copy_number);
>>> }
>> 
>> The problem is that it’s 
>>   set_kvp_int64_path (Account *acc, const Path& path, std::optional<gint64> 
>> value)
>> So gint64 copy_number is getting implicitly converted to 
>> std::optional<gint64> and that’s what’s passed to 
>> qof_instance_set_kvp_path<T> 
>> (https://github.com/Gnucash/gnucash/blob/b5c1937702ca7a8fba772a47b2ac7fa6b8857bf5/libgnucash/engine/qofinstance.cpp#L1076)
>>  it’s (quite reasonably) the optional that’s tested, not the optional’s 
>> contained value. After all, it’s copy_number that’s the special case where 0 
>> isn’t a valid value.
>> 
>> The fix (and answer to your question about how to get rid of the KVP) is
>> 
>> void
>> xaccAccountSetTaxUSCopyNumber (Account *acc, gint64 copy_number)
>> {
>>     set_kvp_int64_path (acc, {"tax-US", "copy-number"}, copy_number ? 
>> std::make_optional<gint64>(copy_number) : std::nullopt);
>> }
>> 
>> so that it will evaluate false in qof_instance_set_kvp_path.
>> 
>> Regards,
>> John Ralls
>> 
>> 
>>> On Feb 4, 2025, at 18:04, Alex Aycinena <alex.aycin...@gmail.com 
>>> <mailto:alex.aycin...@gmail.com>> wrote:
>>> 
>>> I would request some advice in solving a problem that has been discussed on 
>>> the gnucash-users list recently.
>>> 
>>> The symptom: a US-based user has reported that on the Accounts tab, when 
>>> the Tax Info column is displayed, some accounts show 'Sched B: Total 
>>> dividend income' for their assigned tax codes and others show 'Sched B(0): 
>>> Total dividend income'. The number in parentheses is the 'copy number' 
>>> which should never be zero and should only show up if it is greater than 1 
>>> (and the copy number issue doesn't even apply to Schedule B).
>>> 
>>> The problem: investigation shows that not only is the display in the Tax 
>>> Info column on the Accounts tab wrong and confusing, but the US Tax Report 
>>> can show incomplete information and the TXF export also comes out with 
>>> incomplete data and invalid data (there is a copy number field that comes 
>>> out as 'C0', which is not valid).
>>> 
>>> The cause: a commit was made on Oct 17, 2024, commit 63deaad, that changed 
>>> logic, in Account.cpp:
>>> 
>>> From:
>>> 
>>> gint64
>>> xaccAccountGetTaxUSCopyNumber (const Account *acc)
>>> {
>>>     gint64 copy_number = 0;
>>>     GValue v = G_VALUE_INIT;
>>>     g_return_val_if_fail(GNC_IS_ACCOUNT(acc), FALSE);
>>>     qof_instance_get_path_kvp (QOF_INSTANCE(acc), &v, {"tax-US", 
>>> "copy-number"});
>>>     if (G_VALUE_HOLDS_INT64 (&v))
>>>         copy_number = g_value_get_int64 (&v);
>>> 
>>>     return (copy_number == 0) ? 1 : copy_number;
>>> }
>>> 
>>>  to:
>>> 
>>> gint64
>>> xaccAccountGetTaxUSCopyNumber (const Account *acc)
>>> {
>>>     auto copy_number = get_kvp_int64_path (acc, {"tax-US", "copy-number"});
>>>     return copy_number ? *copy_number : 1;
>>>  }
>>> 
>>> If I read it correctly, this changed the logic from "if there is a copy 
>>> number of '0', return '1'", to "if there is a copy number (even if it is 
>>> zero) just return it, otherwise return '1'".
>>> 
>>> Also changed in commit 63deaad,
>>> 
>>> From:
>>> 
>>> void
>>> xaccAccountSetTaxUSCopyNumber (Account *acc, gint64 copy_number)
>>> {
>>>     g_return_if_fail(GNC_IS_ACCOUNT(acc));
>>>     xaccAccountBeginEdit (acc);
>>>     if (copy_number != 0)
>>>     {
>>>         GValue v = G_VALUE_INIT;
>>>         g_value_init (&v, G_TYPE_INT64);
>>>         g_value_set_int64 (&v, copy_number);
>>>         qof_instance_set_path_kvp (QOF_INSTANCE (acc), &v, {"tax-US", 
>>> "copy-number"});
>>>     }
>>>     else
>>>     {
>>>         qof_instance_set_path_kvp (QOF_INSTANCE (acc), nullptr, {"tax-US", 
>>> "copy-number"});
>>>     }
>>>     mark_account (acc);
>>>     xaccAccountCommitEdit (acc);
>>> }
>>> 
>>> to 
>>> 
>>> void
>>> xaccAccountSetTaxUSCopyNumber (Account *acc, gint64 copy_number)
>>> {
>>>     set_kvp_int64_path (acc, {"tax-US", "copy-number"}, copy_number);
>>> }
>>> 
>>> Again, if I read it correctly, this changed the logic from "if the copy 
>>> number is not zero, create a new KVP for it and save it or, if there is 
>>> already a KVP for 'copy number', change it to the new value, otherwise, 
>>> delete the KVP (but do not save a zero value)" to "just save the value, 
>>> even if it is zero".
>>> 
>>> This change caused the problem and symptoms.
>>> 
>>> The fix: first correct/retore the logic in ' xaccAccountGetTaxUSCopyNumber' 
>>> and ' xaccAccountGetTaxUSCopyNumber'. Second, if any of our users have used 
>>> 'Edit->Tax Report Options' to modify their tax code assignments for 
>>> releases since Oct 17, 2024, they may have data files with 'copy number' 
>>> KVPs with zeros and inaccurate US Income Tax Reports/TXF Exports. We need 
>>> to figure out how to clean up their data files.
>>> 
>>> The first correction (I implemented this first in 2009, so not sure of 
>>> current syntax, thus need your feedback):
>>> 
>>> for ' xaccAccountGetTaxUSCopyNumber'
>>> 
>>> -    return copy_number ? *copy_number : 1;
>>> +   return (copy_number == 0) ? 1 : copy_number;
>>> 
>>> for 'xaccAccountSetTaxUSCopyNumber'
>>> 
>>> -   set_kvp_int64_path (acc, {"tax-US", "copy-number"}, copy_number);
>>> +  if (copy_number != 0)
>>> +      {
>>> +          set_kvp_int64_path (acc, {"tax-US", "copy-number"}, copy_number);
>>> +      }
>>> +  else
>>> +     {
>>> +         Get rid of KVP {"tax-US", "copy-number"}); <- how do I do this 
>>> now!
>>> +     }
>>> 
>>> For the second correction (clean up users data files), I was thinking to 
>>> add logic to 'xaccAccountGetTaxUSCopyNumber' that would, if it gets a zero 
>>> value, delete the  KVP, so it would look like this:
>>> 
>>> gint64
>>> xaccAccountGetTaxUSCopyNumber (const Account *acc)
>>> {
>>>     auto copy_number = get_kvp_int64_path (acc, {"tax-US", "copy-number"});
>>>     if  (copy_number == 0) 
>>>        {
>>>              Get rid of KVP {"tax-US", "copy-number"}); <- how do I do this 
>>> now!
>>>              return 1;
>>>        }
>>>      return copy_number;
>>>  }
>>> 
>>> Since 'xaccAccountGetTaxUSCopyNumber' is basically used in only three 
>>> places ('Edit->Tax Report Options', the 'Tax Info' column of the Accounts 
>>> tab, and the 'US Tax Report"), the problem would simply be cleaned up by 
>>> being called through normal activity (looking at the data or running a 
>>> report).
>>> 
>>> Feedback welcome,
>>> 
>>> Alex
>>> _______________________________________________
>>> gnucash-devel mailing list
>>> gnucash-devel@gnucash.org <mailto:gnucash-devel@gnucash.org>
>>> https://lists.gnucash.org/mailman/listinfo/gnucash-devel
>> 

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

Reply via email to