Note that the cvs importer in the Mercurial repo has an invert_sign
option now, which might do what you need.

                 invert_sign: Optional[bool] = False,

          invert_sign: If true, invert the amount's sign unconditionally.


* [email protected] <[email protected]> [2020-05-17 01:27]:
> Posting the previous made me think about this some more. 
> 
> I think this is more concise and generalised:
> 
> def normalise(func):
>     @wraps(func)
>     def wrapper(*args, **kwargs):
>         """Makes all debits negative, and all credits positive."""
>         debit, credit = func(*args, **kwargs)
>         return (
>             -abs(debit) if debit else debit,
>             abs(credit) if credit else credit
>         )
>     return wrapper
> 
> # Monkey patch function in csv module.
> csv.get_amounts = normalise(csv.get_amounts)
> 
> 
> On Sunday, May 17, 2020 at 12:00:44 PM UTC+10, [email protected] wrote:
> >
> > I recently encountered a very similar situation. I have transaction 
> > statements where values in the debit column are negative, but credit values 
> > are positive-valued. I am also subclassing the built-in csv importer 
> > class.   
> >
> > At first I thought about using a decorator to wrap the built-in 
> > `get_amounts()` function. But the values in rows passed to `get_amounts()` 
> > are strings. Stripping the `-` characters from these strings worked alright 
> > but didn't feel too clean (I guess transactions parsing is anything but 
> > clean!). Or maybe negating the debit values returned from the function.
> >
> > To make matters worse, I found that exporting CSV values from my bank's 
> > website sometimes had negative values, but other times they are positive -- 
> > for the same transactions!
> >
> > In the end I just decided to reimplement `get_values()` instead of 
> > decorating it. That resulted in a more general solution that handles the 
> > shitty situation above. I just negate the absolute value of debit values. I 
> > then monkey patch the function in the CSV module.
> >
> > If you haven't got a good handle on how Python namespaces work, you may 
> > get tripped up by monkey patching. Spend a bit of time getting familiar 
> > with it. You'll change the behaviour of your other importers depending on 
> > the CSV module if you're not careful.
> >
> > def get_amounts(iconfig, row):
> >     """Get the amount columns of a row.
> >
> >     This is based on the original function in the built-in CSV importer 
> > module.
> >     In the original function, debit amounts are negated before returning.
> >
> >     If you export transactions from the transaction listing screen, debit 
> > values
> >     are positive. But if you export transactions from the transaction 
> > search
> >     screen, the very same debit values are negative. How bizarre!
> >
> >     This is handled by negating the absolute value of debit values.
> >
> >     Credit values are positive regardless of where the CSV export came 
> > from.
> >
> >     Sometimes transactions are pending (authorisation only). In this case,
> >     the "Transaction Type" column is empty. We use this to ignore these
> >     transactions: None is returned for both debit and credit.
> >
> >     The `allow_zero_amounts` argument and corresponding logic has been 
> > removed
> >     from the original function.
> >
> >     Args:
> >       iconfig: A dict of Col to row index.
> >       row: A row array containing the values of the given row.
> >     Returns:
> >       A pair of (debit-amount, credit-amount), both of which are either an
> >       instance of Decimal or None, or not available.
> >     """
> >     # If transaction type is not populated, the transaction is pending. 
> > Return
> >     # None instead of actual values.
> >     if not row[iconfig[csv.Col.DRCR]]:
> >         return (None, None)
> >     debit, credit = None, None
> >     if csv.Col.AMOUNT in iconfig:
> >         credit = row[iconfig[csv.Col.AMOUNT]]
> >     else:
> >         debit, credit = [row[iconfig[col]] if col in iconfig else None
> >                          for col in [csv.Col.AMOUNT_DEBIT, 
> > csv.Col.AMOUNT_CREDIT]]
> >
> >     # Take the absolute debit value, then negate it.
> >     return (-abs(csv.D(debit)) if debit else None,
> >             csv.D(credit) if credit else None)
> >
> >
> > # Monkey patch function in csv module.
> > csv.get_amounts = get_amounts
> >
> >
> >
> >
> >
> > On Sunday, May 10, 2020 at 5:11:59 AM UTC+10, [email protected] wrote:
> >>
> >> Hello,
> >>
> >> I am working on csv importers by subclassing the provided csv class and 
> >> wrapping __init__ to setup config, etc. It worked well, but some of my csv 
> >> files have a different numbering format. The ones I run into are: debit 
> >> shown as negative number, and some gives me 0 for debit when it's a credit 
> >> so that I have an additional line of 0 amount.
> >>
> >> These are all easy fixes, through monkey patching the get_amounts (with 
> >> wrapping old) function in the csv module. The problem is that when I have 
> >> to patch it twice for the above 2 situations, the patches spill over and 
> >> change the outcomes depending on how I import my custom importers in 
> >> xxx.import file.
> >>
> >> I can pass the test for each individual importer, but not when I run all 
> >> tests.
> >>
> >> I can surely just copy and change the original csv module to move 
> >> get_amounts as a class method. But I just want to check if I am doing it 
> >> right.
> >>
> >> Thanks for any suggestion.
> >>
> >> W.E.
> >>
> >>
> 
> -- 
> You received this message because you are subscribed to the Google Groups 
> "Beancount" group.
> To unsubscribe from this group and stop receiving emails from it, send an 
> email to [email protected].
> To view this discussion on the web visit 
> https://groups.google.com/d/msgid/beancount/2bf01ddf-c99c-4507-8fc2-034ed07deba2%40googlegroups.com.


-- 
Martin Michlmayr
https://www.cyrius.com/

-- 
You received this message because you are subscribed to the Google Groups 
"Beancount" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/beancount/20200517084322.GA6721%40jirafa.cyrius.com.

Reply via email to