Skip to content

Automatic posting matches multiple unrelated currencies when using query cur:X #1582

Closed

Description

@bcashlol
  • Minimum reproducible example:
= cur:USD
  (b:USD)  *1

2017-12-14
  revenue:job  -10 EUR
  revenue:job  -10 USD
  assets

Output:

 hledger -f test.hledger print --auto
2017-12-14  ; modified:
    revenue:job         -10 EUR
    revenue:job         -10 USD
    (b:USD)             -10 USD  ; generated-posting: = cur:USD
    assets
    (b:USD)              10 EUR  ; generated-posting: = cur:USD
    (b:USD)              10 USD  ; generated-posting: = cur:USD

Notice this is creating an automatic posting for EUR, and also two automatic postings for USD. The expected behavior is a single automatic posting for only USD.

  • The output of hledger --version
    1.21

Activity

  1. added
    A-BUGSomething wrong, confusing or sub-standard in the software, docs, or user experience.
    on Jun 25, 2021
  2. bcashlol commented on Jun 25, 2021

    @bcashlol
    Author

    Note this works as expected:

    = revenue & cur:USD
      (b:USD)  *1
    
    2017-12-14
      revenue:job  -10 EUR
      revenue:job  -10 USD
      assets  
    

    Output:

    hledger -f test.hledger print --auto
    2017-12-14  ; modified:
        revenue:job         -10 EUR
        revenue:job         -10 USD
        (b:USD)             -10 USD  ; generated-posting: = revenue & cur:USD
        assets
    

    But this does not work as expected:

    = assets & cur:USD
      (b:USD)  *1
    
    2017-12-14
      revenue:job  -10 EUR
      revenue:job  -10 USD
      assets  
    

    Output:

    hledger -f test.hledger print --auto
    2017-12-14  ; modified:
        revenue:job         -10 EUR
        revenue:job         -10 USD
        assets
        (b:USD)              10 EUR  ; generated-posting: = assets & cur:USD
        (b:USD)              10 USD  ; generated-posting: = assets & cur:USD
    

    Notice there are now two automatic postings on the inferred amounts, instead of just one as before.

    If we do not use inferred amounts, it works as expected:

    = assets & cur:USD
      (b:USD)  *1
    
    2017-12-14
      revenue:job  10 EUR
      revenue:job  10 USD
      assets  -10 EUR
      assets  -10 USD
    

    Output:

    hledger -f test.hledger print --auto
    2017-12-14  ; modified:
        revenue:job         -10 EUR
        revenue:job         -10 USD
        assets               10 EUR
        assets               10 USD
        (b:USD)              10 USD  ; generated-posting: = assets & cur:USD
    
  3. simonmichael commented on Jun 25, 2021

    @simonmichael
    Member

    Thanks for the report @bcashlol. Just looking at your first example, hledger is working as expected. Consider:

    = cur:USD
      (b:USD)  *1
    
    2017-12-14
      revenue:job  -10 EUR
      revenue:job  -10 USD
      assets
    
    $ hledger print -x
    2017-12-14
        revenue:job         -10 EUR
        revenue:job         -10 USD
        assets               10 EUR
        assets               10 USD
    

    Your auto posting rule also matches the inferred balancing postings, you'll need to restrict it by account as well, eg:

    = cur:USD revenue
      (b:USD)  *1
    
  4. bcashlol commented on Jun 25, 2021

    @bcashlol
    Author

    @simonmichael Actually I already tried to address your example in my second comment. It is not working as expected, since it gives different results if you manually write out the postings versus let hledger infer the exact same postings.

    Consider that these two examples I gave give two different outputs, even though using your logic, they should be the same:

    = assets & cur:USD
      (b:USD)  *1
    
    2017-12-14
      revenue:job  -10 EUR
      revenue:job  -10 USD
      assets  10 EUR
      assets  10 USD
    

    The above gives a correct output.

    = assets & cur:USD
      (b:USD)  *1
    
    2017-12-14
      revenue:job  -10 EUR
      revenue:job  -10 USD
      assets
    

    The above equivalent transaction gives an incorrect output (with an extra automatic posting for EUR).

    you'll need to restrict it by account as well

    Notice that in one of the above examples where we do restrict by account both EUR and USD are matched, but in the other only USD is matched. Regardless of whether we restrict by account, EUR should not be matched. Also notice in other examples where we do not match by account, EUR is matched in some cases when it should not be.

  5. simonmichael commented on Jun 25, 2021

    @simonmichael
    Member

    Trying the examples in your latest comment, again I don't see a problem. Maybe I'm missing it. Can you show an actual repro (input, command, output with problem highlighted) ? Or if it's easier, come to chat.

    Incidentally & is not part of hledger query syntax, and I'm surprised it doesn't seem to cause trouble.

  6. bcashlol commented on Jun 25, 2021

    @bcashlol
    Author

    Yes, the same example from my 2nd comment:

    Input:

    = assets cur:USD
      (b:USD)  *1
    
    2017-12-14
      revenue:job  -10 EUR
      revenue:job  -10 USD
      assets  
    

    Output:

    hledger -f test.hledger print --auto
    2017-12-14  ; modified:
        revenue:job         -10 EUR
        revenue:job         -10 USD
        assets
        (b:USD)              10 EUR  ; generated-posting: = assets cur:USD
        (b:USD)              10 USD  ; generated-posting: = assets cur:USD
    

    This auto generated posting is wrong:

     (b:USD)              10 EUR  ; generated-posting: = assets cur:USD
    

    The query is to match USD. This auto posting matched EUR!

    Also note that if you change the input file by manually writing out the assets postings instead of letting them be inferred, then you get a different (and correct) output. #1582 (comment) See "If we do not use inferred amounts, it works as expected:"

  7. simonmichael commented on Jun 25, 2021

    @simonmichael
    Member

    That did it. You're right, it's a bug [since the beginning it seems]. Good catch, thanks!

  8. Xitian9 commented on Jun 28, 2021

    @Xitian9
    Collaborator

    I'm willing to bet this is due to an confusion I ran across when changing the internal representation of MixedAmount. I have a strong tendency to view the content of a Posting as an Amount, as it will always have just a single entry when read from the journal. However, it is actually a MixedAmount, and will sometimes have multiple entries when it's an auto posting. It's obvious to state, but easily forgotten when coding. My guess is some piece of code is checking whether a commodity is present in a MixedAmount, and then assuming all amounts in there have that commodity.

    There is actually a fair amount of code which manually checks whether there is a single Amount in a MixedAmount and only works if there is. If we wanted to encode this in the type system, we could have pamount :: Either Amount MixedAmount, but this is probably more effort than it's worth.

  9. simonmichael commented on Jun 28, 2021

    @simonmichael
    Member

    You could be right, but it's not a regression, I think ? At least it didn't seem so to me, I tried some old versions.

  10. Xitian9 commented on Jun 28, 2021

    @Xitian9
    Collaborator

    No, I don't think it's a regression. It's just a point that I frequently encountered and had to deal with: it wouldn't surprise me if it got missed earlier.

  11. simonmichael commented on Jul 1, 2021

    @simonmichael
    Member

    Fixed by @Xitian9.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-BUGSomething wrong, confusing or sub-standard in the software, docs, or user experience.journalThe journal file format, and its features.

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions