Work at SourceForge, help us to make it a better place! We have an immediate need for a Support Technician in our San Francisco or Denver office.
I have looked through the forums and noticed that you have debated about adding split transactions to buddi. I have just recently started using your software. It has been a goal of mine this year to contribute to an open source project. I use so much open source software it is about time. Anyhow I debated a bunch and this is the project that I would most like to try and help and I would like to help you out with adding the ability to split transactions if you want my help.
Let me know what you think....
The main reason which I was reluctant to include split transactions is because of the UI difficulties. Buddi is designed to be simple and not cluttered, and I have not been able to think of a way to include the ability to include an arbitrary number of split transactions without losing this simplicity.
How do you propose to do this? Please let me know what approaches you think would work (screen mock-ups and / or storyboards would be a great help), and we can discuss this. If you can come up with a simple implementation of this, then by all means, I would love your help!
Please keep us informed about the development of such a feature as it will mean that the plugin i am writing will not have to make dummy transactions when splitting transactions!
Just an update... I have finished the screen mockups and I am just finishing up some text that describes how I think the feature could work. I should have it all posted later on tonight.
I will put together some screen mock-ups this weekend. My ideas to me seem extremely simple on the front end but I wouldn't be surprised if you shoot them up at first. Based on your previous post you have been thinking about this longer then me. But I can't think of no better way to get started and we'll just deal with the problems as we come to them.
As far as the backend goes, it should be pretty simple - I'm thinking one of a few approaches:
1) Include on each transaction a list (by default empty) of other transactions. This will let you include an arbitrary number of multi-split transactions (for instance, you can split both the source and destination).
2) Include a flag on each transaction which says which of the [source,destination] is split; then include a list of (amount,category) tuples for the splits. This will only let you split one side of the transaction (either to or from).
There are a few other things I have thought of... which we choose will probably depend on your GUI styles, as I like to keep the GUI following the model as much as possible.
I look forward to your proposal!
OK Everybody.... Sorry for the delay. September turned into a busy month for me and I did not get a chance to get back to this... I have posted my proposal for split transaction support here...
Please let me know what you think. It is just my first shot at it so I am expecting it to get beaten up, but it's a start.
Thanks for this, Kevin,
Well, to be honest, this looks very interesting. I think that you may be on to something here...
A couple comments / questions:
1) How can you determine if it is the TO or the FROM source which is being split? I can think of use cases for either one (paying for something using cash / credit card, buying groceries and a prescription at the supermarket on the same bill, etc). Something that may work for this is to remove the split button, and instead add a <split> entry at the bottom of each pulldown. When you click it, the window pops up, like how you have it now. (I suppose that we would have to have it so that one you select Split for one of To / From, the other one disappears, so that you can't have splits on both).
2) Just to confirm: your proposal does not include the ability to split on both? (This is probably a good thing, as splitting on both would be quite complicated, from both a model and a UI point of view).
3) I like the idea of keeping the unsplit remainder at the bottom of the window... I would even think of going a step further, and disabling Save until the remainder is 0.
4) I'm not sure of having a separate dialog for the splits... I wonder if it would be possible to include it on the same transaction window? The reason for this is that there are potentially multiple transaction windows open at a single time. I suppose that we could make that dialog modal to prevent confusion, although in general I don't like arbitrarily forcing the user to do one particular thing first. I suppose that for the Mac, we could use a JSheet (via Quaqua), but this doesn't address Windows / Linux at all... Maybe we could do a pull-down like how I show the search / stats at the top / bottom of the transaction window right now... (although that wouldn't work for many-way splits, due to size constraints; I know that there are some users running on EEE PCs, with tiny screens...) Any ideas? Maybe a dialog is the best bet after all.
I think that this can work - you seem to have a very good understanding of my requirements for Buddi (simplicity, usability, etc), and I really do like your approach.
Sounds like it is definitely "do-able".
I am more interested in the backend implementation as it what my plug in will be interfacing with when importing split transactions.
Wyatt, now that we may have a user interface for splitting transations do you have an implementation in mind? And what would be the expected behaviour for import plugins which are able to create split transations?
Hmm... might have to only limit the plugin to only allow splits in the TO field as you will be importing from one source at a time. I am not sure splitting on the FROM field would make sense in that context.
Well, this is what I am thinking in regards to the model side of things. Please let me know any comments / suggestions / complaints you may have with it. You may want to view the model diagram at http://devel.buddi.thecave.homeunix.org/en/diagrams.jsp to see the current state of the model, and how it will change.
First, there will be a new data structure called "TransactionSplit", containing the fields "amount (long)", "source (Source)".
In the "Transaction" interface, we will include a List of TransactionSplit objects, with this field being called "splits".
By default (i.e., when there are only a single to / from source), the splits list is null. In the event that a split is entered, the source which is split (one of the fields "to" or "from" in Transaction) will be set to null (or possibly set to a special value; not quite sure of this yet). In this case, we will look at the splits list for information.
How does this sound? Note that this describes how the underlying data model is constructed; the implementation as exposed via the API may be different.
For the API, I'm thinking that perhaps we may want to add two new setters to the Transaction API object: setTo(List<TransactionSplit>), and setFrom(List<TransactionSplit>) By using these two methods, the API will automatically make sure that the state of the object is correct (only one of to or from may be set for any one transaction, the single to / from will be set to null when a list is set, and vice versa, etc)
If you can think of a simpler way to interface with this, that still maintains backwards compatibility, please let me know - I am still in the early planning stages, and am open to suggestions.
I think your current thinking is the way to go, overloading the setTo and setFrom methods on the will keep backwards compatability with older plugins.
As for the null/special symbol representing a split... it depends on how backwards compatible you want to be. If null is used, this would be compatible with plugins which do not understand split transactions. They are most likely stop functioning or display an error when hitting a null. Which will give feedback to the user that there is a problem with plugin.
If using a special symbol, plugins will probably not fail however the results of the plugin may not be as the user expects. e.g. an export plugin may "successfully" export the data... however the data will be nonsense with an extra category (the special symbol) being defined as either the TO or FROM category.
I tend to think it would be safer for the end user to use null to represent split transactions.
Well, after some more thinking, the 'special character' would most likely be an implementation of Source (currently there are two, Account and Category. I would add another one, Split). Depending on how correct plugins are (do they check the type of Source they get from the getTo() / getFrom() methods?) it may still fail noisily or silently, but then again it is still possible to fail silently with a null as well.... This would also help with keeping things clean internally in Buddi, as currently null is used in the SourceComboBoxModel for the default entry. Oh well, I will think about it some more, and see what I come up with.
A question to anyone out there that knows: are you aware of any way to overload a getter to provide one or more values of an object? I.e., I want getTo() / getFrom() on the API to return either a single Source object (if no split), or a list / array of Sources (if split). Similar to varargs, but on the return instead of the call. I am pretty sure (OK, I'm pretty much certain) that it won't work in Java (Python handles this beautifully, BTW), but I'm open for suggestions.
If there is nothing like this, do you have any good ideas on how to handle the getters? I would like to have API users just call one getTo() / getFrom(), and not need to check getFrom() and then, if it is null, call getFromSplits() or something.
You definitely cannot differentiate methods based on return type. think about the following:
value = getVal() + getVal();
The jvm has no idea which getVal to call.
I would think the only way to is to have the split transactions object inherit/extend from MutableSource and for it to have Mutable Source or one of its parents define the abstract method "isASplit" so that the plugins can cast appropriately. This should mean that plugins which do not understand splits will still function albeit strangely, however plugins which do understand splits will be able to check whether a source is a split list.
Perhaps something like this
abstract boolean isASplit();
class Account extends MutableSource
class MultipleSources extends Account
I would suggest that the most correct solution is to always to return a list of sources. But this would break compatability with plugins. when there is only one split then it is a normal transaction.
Oh well, it was worth a shot 8-P
I'll try to hack something out over the next few days, and show you guys what I come up with. Feel free to shoot it full of holes.
I have committed some changes to trunk (after branching 3.2_stable) which include support for split transactions, as discussed (i.e., a single list of TransactionSplit objects, which are used for whichever source [to | from] is set to the special type Split (extended from Source).
However, I am re-thinking perhaps going for dual-split support, at least at the model level (we can discuss GUI at a later time, if needed). It may even be simpler (from a user point of view) than single-split would be. The major feature for this would be that I could have two lists of TransactionSplit objects, one called toSplits and the other fromSplits. This would save plugin developers (and myself) from needing to use special logic to figure out which of to | from is split.
Plugins and Buddi itself would choose to use the TransactionSplit lists for the to / from sources, if and only if the getTo() / getFrom() methods respectively return an object of type Split. When creating a transaction, Buddi will check that all amounts in the To list, the From list, and the Amount value all add up to the same number.
Using this scheme, the API would also be essentially identical to the underlying model.
That does sound like a valid solution. I agree, having dual splits would be conceptually easier to undersdand.
I think that we're good to go here - I just updated the model / checked into Trunk, and added new diagrams on http://devel.buddi.thecave.homeunix.org/en/diagrams.jsp . I think that we are ready to start looking at coding the model - Kevin, when you get a bit of spare time, please contact me (either via this forum or directly to email), and we can start looking at how to approach the coding.
As for the model / API code, please let me know if you have any suggestions for changes or anything - the sooner I hear any complaints, the more likely I will be to change them 8-) In it's current implementation, I think that things are pretty self explanatory. One thing to note is the 'setter' for ToSplit / FromSplit on the MutableTransaction in the API - instead of using a standard setter, which takes a list of MutableTransactionSplits, I have two methods addFromSplit() and removeFromSplit() (with the equivalent ones for To). The getter returns an unmodifiable list. This should make things simpler and less error prone, but if you can think of an instance where you would need direct write access to the underlying list, or if there are cases where add / remove won't suffice, please let me know.
Just a heads up... I have been busy preparing for a big Halloween Party I have every year. After this Saturday, I will have time to start working on this.
Sounds like fun! 8-)
I have started experimenting with a couple of panels and frames and stuff. Let me know when you start, and I will make sure that everything is checked in. Feel free to use what I have, or if you were thinking of something different, that's cool too.
Do you have everything checked in? I'm planning on taking a stroll through the code today.
Wyatt.... I mean Wyatt..
For some reason when I glance in at your user id I think owen.....
Oh maybe it's just because it's Monday.
Yep, everything is checked in and ready to go.
Any updates on this? I have been getting a number of other features into 22.214.171.124, and will shortly (next couple of weeks, probably) be ready for a development release. Let me know if you are not going to have time to complete this by then, and I can perhaps take what you already have and see if I can finish it.
Let me know if you need me to do anything.
I have not had time to get much of a start on it yet. When you say development release do you mean a beta or a regular release? Perhaps if I have a date it will make me get it done.
No problem - I know how life tends to get in the way of your 'Real Work'! ;-)
This would be a development release, but publicly available on the SF.net site and ready for real use with production data. (I always use development releases on my own data files, to get in as much 'real life' testing as possible.)
As for a date... could we shoot for a tentative Dec. 14th release? This would mean that a feature freeze / beta testing stage would be happening for about a week before - could you get your changes done no later than the 7th? That can give me time to look over the code and integrate with the changes I have made, do some preliminary testing, and get a pre-release version out to you and whoever else is interested. If all goes well with that, the official public Development release will go out on the 14th.
(For information on how I classify my releases, check out http://buddi.thecave.homeunix.org/en/faq.jsp, near the bottom "How do I interpret your version numbers?". Short version: my development versions are pretty close to Google's Beta products - technically they are non-release, but in practice you should be completely fine with them, even for production use. What I call 'Pre-release' is probably closer to Microsoft's Beta - you would be insane to use this for production, but it gives you a pretty good idea of what will be included. Hope this clarifies things a bit).