-
Notifications
You must be signed in to change notification settings - Fork 26
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
txn-filters: prototype implementation of transaction filters. PR is for review of design and for comments. #78
Conversation
This is prototype of stackable transaction filter system. Those filters operate on AST level and can be glued together with filter stacks. With filter stacks it is possible to define different semantics for combined filters, for example AND or OR filter stacks, or define some totally different logic. - base/main/../Ast: TxnFilters and TxnFilterStacks - trait TransactionFilter => EndDateTxnFilter, BeginDateTxnFilter, PayeeTxnFilter - trait TxnFilterStack => ANDTxnFilterStack - base/main/../Process: Processor.process: use TxnFilters - base/main/../App: Demo usage of Filters - base/test/../ProcessorTest, ComplexProcessorTest: TxnFilters = None
Filtering would be useful; so this is welcome. However, who is this intended for? Will the user specify filters in the config file, or is it for programmers that directly use the API? If former, then we don't really need a hierarchy of filter classes; they would only be useful for programmers. Am I right? |
These should be useful and handy way to implement filters, which user selects, so I don't think these are usefull only for programmers. Original idea was that user will specify filters on from the command line or from GUI, and there could be several different filter from which to choose: Time, account names, annotations, and user can freely combine these. For example usecase could be you would like to investigate some special transactions and filtering semantic could be period of time, and name of some accounts (all transactions touching those accounts) and certain payee (and so on). So idea is that filters will be applied dynamically based user's selection and we can support different usecases which user builds from CLI or from GUI. For that reason there are those different types, and that stacking system. E.g. ANDTxnFilter stack will be build based on users selections, and whole thing can be filtered on one go. Also I think this should not be supported from conf-file, or at least there should be big notice on reports, which states that reports are based on filtered transactions. It's too easy to forget a filter to config file and "lose" some transactions ... |
(Feel free to disagree with me and push back)
Well, what you are essentially building is a combinator library for filtering expressions. If the filtering feature is for end-users (who are not expressing the filters in Scala), then the combinators aren't that useful; they are an extra layer of abstraction. A simple function that returns a boolean is sufficient.
In that case, what do you think about making these filters report-level rather than AST-level? It is rare for txns to be enabled / disabled dynamically; what one typically wants is to (a) drill down into details of a report, or (b) get a larger picture and hide the details (without changing the result). Some of this is already supported in GUI, but it needs a proper filtering framework like this and support in the CLI as well.
I totally agree about the warning. |
I will think about that, it could be that I am missing something about how it would be possible to chain multiple filters dynamically in Scala.
That's interesting opton and I thought about that. First of, personally I have usecases where I run balance over some criteria, and it's nice to see resulting data related to only that criteria. It could be payee, annotation or tag for example. With that feature you could generate for example profit-loss report for some specific event or work. If filtering is done on AST level, then this kind of reporting is really easy to do. Also, with AST level filtering it could be possible to create "streams" where you are watching accounts and transactions which are matching only certain conditions. And if there is huge pool of transactions readily on AST-form (e.g. on some reporting server), then it would be nice to do AST level filtering on that pool. On the other hand, there are some other kind of questions which can not be answered on AST level, for example "list all transaction where debit/credit total is over XXX ", "at which point this account tripped certain level" etc. So there is need also for those other, report level filters. |
This is still prototype/demo level implementation, but it's functional and it is possible to play with system (from command line). - base/main/../Ast: mechanisms (description, xmlDescription) to get filter descriptions. - base/main/../Config: Handle cli arguments with getCompleteSettings - base/main/../Report: xmlExport, xmlJournalExport, xmlBalanceExport: Print notice/info about filters. - cli/main/../App: Use filters, and print notice. - gui/main/../UI: Use filteres, NO NOTICE atm.
Hi, this is "proto v2" of txn-filters. It's possible to play with filters from CLI interfcase
It could have been possible to implement combined filters with function compositions, but on that route it would have been more difficult implement notice/warning functionality for reports, exports etc? If there is some better way to implement it, it could be fixed fairly localized way in future. If this is way to go, then there are still missing some features:
|
This adds filter support with configuration files, and adds initial, basic documentation about filters.
- base/src/main/../Ast: AnnotationTxnFilter and AccountTxnFilter - base/src/main/../Config: CLI/Conf switches for those
When exporting in ledger format, warning was missing "ACTIVE FILTER" text.
Test cases and variations are listend on readme.md. All test cases use filter-targets.ledger as an input. At the moment following filters are tested: - begin - end - annotation - payee - account
Hello,
One big thing which is missing is that there isn't any warning on GUI if there are active filters affecting results. There are also some things which should be fixed (scallop will exit with wrong arguments), but those are not related to these changes. Also behaviour with unknown filter names could be better - now it will just throw runtime error. Other than that, this should be start shaping as functional filter system. |
This commit implements transactions filter descriptions on info tab and notice also on statusbar on bottom. - base/src/main/Ast: New helper which is shared with cli and gui FilterStackHelper.getFilterWarnings - cli/src/main/App: Use new helper - gui/src/main/UI: Filter description on info tab and on status bar
(521fca8) Implements GUI warnings, so that missing part of functionality is now implemented. |
|
||
val txnFilters = | ||
if (cliConf.filters.isEmpty) { | ||
None |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If you create an AcceptAllFilter
, you could avoid the extra layer of Option[Filter]
throughout the code and just use Filter
everywhere.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
On second thoughts, the current code is better because you can issue warnings about filters more easily.
Overall, this is awesome! I think the And, I would like to see a proper expression grammar for filters, that can be used in command line as well as config files. For example, I would like to specify filters like this:
It should be easy to add support for such a grammar using parser combinators. And you can directly map to the filter case classes in the combinator itself. |
Note to myself: Check if txn filtering happens before or after the constraints check (eod constraints for example). |
Cool, that's nice to hear and thank you for review and comments!
I agree about ambiquity of terms, but disagree Typical usecase is probably some natural timespan or start of timespan. Eg. Jan 2016 or Y2015 It's getting even more interesting with March, eg. March 2016. For removing abiquity of how many days there are on each month, Summary
Actually inclusive The
Yes, that would be nice and handy in some cases. However, I would like to first finish these basic filters first and leave that expression grammar for some later time. It could be implemented backwards compatible way, which is also quite natural from UX point:
That way it would be possible to support "simple" filter definitions, and more complex expression definitions on same time. What do you think, is that ok plan? |
Changed `end` to be exclusive and renamed AccountTxnFilter to AccountNameTxnFilter. Improved documentation. - base/src/main/../Ast: Renamed AccountTxnFilter -> AccountNameTxnFilter Changed end from inclusive to exclusive - doc/abandon.md: document all filters, add example and link to testcases. - testCases/sclT0005-filters: Adjust end dates and ref-files.
Hello, Please see (b1bad32), this commit changed If you like, we can think something else for If there isn't anything else, then this should be in state to be merged. |
It would be highly confusing if one of them is exclusive and the other inclusive. I strongly prefer not relying on explanations. The more straightforward the better. How about the following filters:
The on-or-after style of specifying dates is common in my part of the world. Even if someone is not familiar with it, this wording doesn't require any explanations. It is a little verbose but I prefer verbosity over ambiguity.
Here again, I would strongly prefer a bit of verbosity instead of implied behaviour. What might seem natural to one person might be confusing to another. Let's go for filter expressions! |
Hi, names could be However, more I have thought about it, more I think begin of span (left condition) should be inclusive and end of span (right condition) exclusive. There are several reasons for that:
These would be cool and nice, however there are more urgent features (personally for me), which I am working on at the moment (groupby, strict account validation, and probably some commodity conversion functionality). So I would like to postpone that part of filter expression. If there is need for you, I don't mind if you implement this. I also believe that implied AND on that case is not too confusing. |
Thanks for fixing coveralls! I merged the master (no renaming yet), so now there is clean table to move forward when we have decided what to do with this filter stuff. |
Hello, This is getting to be quite big changeset, and it would be nice to not have this lingering in branch and conflicting with other future changes. |
Hey @jaa127 ! I appreciate your efforts here and looking forward for more. I didn't find time to review your latest changes yet; will try to do this weekend. However, I feel it is better to address all points before the merge. If you get the time, please go ahead and address them now. Else, I will do them myself as soon as I get free time. cheers, |
Hi, Then there is also question of how that query language should be implemented in abandon, and how much could/should be lifted to external engine. For example Abandon could do AST processing, and then feed each transaction to in-memory, transient SQLite database. SQLite supports Common Table Expressions (with recursive) and hence you can make really complex expressions leveraging those recursive queries. So IMHO, I think it doesn't make sense to progress too far with these filters in Abandon alone and without support some query engine. |
I did a quick review and the code looks good. 👍 Merging with the hope that the UI changes are done soon in a follow up PR. Thanks @jaa127 |
Another simpler solution is to allow scripting via Scala. |
This is prototype of stackable transaction filter system. Those filters
operate on AST level and can be glued together with filter stacks.
With filter stacks it is possible to define different semantics for combined filters,
for example AND or OR filter stacks, or define some totally different logic.
=> EndDateTxnFilter, BeginDateTxnFilter, PayeeTxnFilter
=> ANDTxnFilterStack
It would be nice if you could review this design. If design is ok, I will refine PR with actual command line switches and tests, docs etc.