Data binding heirarchy mis-match

Data binding heirarchy mis-match

Old forum URL: forums.lhotka.net/forums/t/3536.aspx


Q Johnson posted on Thursday, September 13, 2007

I'm looking ahead to an app I'll build next month to handle timesheet entry.  At the core of the class structure will be the Timesheet.  The Timesheet is a root collection of TimeRecords.  And if it had a simple set of properties, binding those to a grid would be easy, obviously.  However, each TimeRecord object will have as one of its properties a collection of segment code values for the accounting system.  If the number of segments was going to be the same for all my customers, this would also be no problem.  They would just each be a property and I'd still have a 2D hierarchy - the second dimension would just be wider by the number of segments.

But, alas, I have to allow for a dynamic number of segments because I will (hopefully <g>) have lots of customers and they'll all have different structures to their charts of account.  So it seems to me that I should be creating a collection property for the TimeRecord object to hold its segment values. 

And now you can see how the binding is going to be a problem.  I'd like to have a column in the entry grid for each "regular property" of the TimeRecord class (start time, end time, Job Title, EarningType, etc.) and a column for each account code segment value.  Any ideas how to manage this without flattening the heirarchy?  How about an elegant way of flattening the heirarchy?  Any ideas on how to create a class with a dynamic number of properties that isn't resolved until run time?

[FYI, I have done this in the past with the flattening techinque.  But it seemed like such a hack.  Using it here I would create ten (an obviously arbitrarily chosen number) string properties for those account code values in the TimeRecord class; there would be no children in a collection property.  Then I would manage the population, fetching, updating, and saving of those properties by referring to them by index numbers using hideous volumes of CallByName statements.  All over my DP_xxx methods I'd have loops iterating from zero to MaxSegCount (to build dynamic SQL and set and retrieve values) so that I don't try to populate properties or access data which doesn't exist in the customer's data.  And MaxSegCount is a property, too, of course.  And this certainly worked in that older CSLA app.  But yuck!]

So, to repeat the questions if you read this far: Any ideas how to manage this without flattening the heirarchy?  How about an elegant way of flattening the heirarchy?  Any ideas on how to create a class with a dynamic number of properties that isn't resolved until run time?

Thanks in advance,

 

JoeFallon1 replied on Thursday, September 13, 2007

Taking a step back - why not use a fixed number of segments and save yourself all the trouble?

Granted, many clients will have many different accounting systems. But I have dozens of clients in various industries (many in the Fortune 500) and am able to segment their chart of accounts into 3 tables.

A G/L code is typically made of these 3 segments:

1. Company

2. Cost Center

3. Account Code

Some clients will tell you they have other accounts. But they can all fit inside the Account table if you are just a bit creative.

e.g. Account = 123

But clients have projects as sub-accounts.

So you put this in your table instead:

123-proj1

123-proj2

123-proj3

etc.

There was only one client in the last 10 years that could not work with this style. They produced TV shows and had an account code for every episode. It was 26 million account codes and growing when I last checked.

Joe

 

Q Johnson replied on Thursday, September 13, 2007

Joe,

I wish I had the luxury of those kinds of assumptions.  But all my clients are nonprofit and government organizations whose chart structure complexity varies widely.  I know of one of my clients with only three segments but I have a client that is a state agency who actually uses 23!!!  In my experience (of about 17 years) about 3/4 of them use between 4 and 7.  That's why I was willing to use 10 in the last app. 

Not only do they have multiple segments, but they also have to balance by a variable number of them.  So if they have segments called Grant, Fund, Location, Program, GL, and Restriction (to comply with FASB117 reporting), they might have to make entries in which the debits and credits balance BY FUND  or even by Fund AND BY GRANT.  These kinds of variations in their structure and expected behavior are just the every day challenges in my problem domain.  Furthermore, different kinds of entry line items require that different numbers of the segments be populated with a code value (making Validation Rules really interesting). 

I'll give is some more thought and see if I can find away to apply that in a generic enough manner to take on bulk of situations I'll like face.  But I'm not optimistic.

btw, I also have a TV station client (they're PBS, of course) and they managed to avoid making THAT mistake you mentioned at least <g>. But they required some very special treatment that required maintenance of a cash basis and accrual basis set of books at the same time.  That was fun.

Anyway, thanks as always for the response.  I really will give it some thought. 

Regards,

Q

JoeFallon1 replied on Friday, September 14, 2007

Q,

You have a lot of experience with complex G/Ls. If your app was one where you had to balance all these possible G/Ls I would completely agree with you.

But you said this was a Timesheet app. So your users are only going to have to use some subset of possible accounts. Maybe Projects or something. You have to keep track of this value and when you post the data to the accounting system only then do you need to build out the full G/L code. So couldn't you keep your UI simplified and add the complexity on the back end somehow?

Just an idea.

I built a Swipecard time tracking system a decade ago for Nestle. It was pretty straightforward. But then again it was only one client.

Joe

 

Q Johnson replied on Friday, September 14, 2007

re: >>  "But you said this was a Timesheet app. So your users are only going to have to use some subset of possible accounts. Maybe Projects or something." <<

Right.  But ususually I only get to omit one of the many segments (the restrictions one because the default value of Unrestricted is always valid for Payroll). The rest are all needed.

>> "You have to keep track of this value and when you post the data to the accounting system only then do you need to build out the full G/L code. So couldn't you keep your UI simplified and add the complexity on the back end somehow?" <<

Good thought.  But I want to offer a combobox for each segment's codes so that they can choose from among valid values (that I'm fetching from the acctg system's SQL Server db) so it seems I need a separate column for each, doesn't it?  So I'm afraid that combining them in a single column like this, 123-45221-678-A27, probably isn't going to work for this.  Otherwise I think it would be fine. 

I could offer a hot-key that will bring up a modal "account selector" dialog that offers comboboxes for all of the segments.  Then the user could make their choices and when they click OK, the values are put into that single field with the hyphens.  But it is a lot of extra work for them to have to bring up that dialog for every line (though it can be argued that they'll learn the values and key them eventually) in the timesheet and it complicates the validation code significantly, too.  I think the kludge I have isn't any worse than these would be.  Maybe I shouldn't discard that design quite so soon??? <g>

 

JoeFallon1 replied on Friday, September 14, 2007

"But I want to offer a combobox for each segment's codes so that they can choose from among valid values "

Be careful with this one.

One of the gotchas in breaking up segments is that not all combinations are valid within the G/L.

e.g.

================

CostCenter = 1

Acctcode = 123

Acctcode = 456

================

CostCenter = 2

Acctcode = 123

Acctcode = 789

================

So if the user selects CostCenter = 1 the Acctcode dropdown needs to be

Acctcode = 123

Acctcode = 456

but NOT Acctcode = 789 which is only valid for CostCenter=2.

================

I have a table of all valid AcctCodes and all valid Cost Centers.

But I have to validate the COMBINATION of the 2 against the G/L of my clients.

 

Joe

 

Q Johnson replied on Friday, September 14, 2007

Actually, that's one of the real strong points of the target accounting system: all combinations ARE valid.  When they create a new Program code, for example, it is automatically able to work in combination with any other account code in any other segment.  (And it also makes reporting a breeze because you don't have to parse the "account field" to build criteria for your queries.  So there's a payoff for all the work I have to do in data entry: my reports are a piece of cake.)

Now it DOES have the flexibility to let the user restrict those combinations if they choose to.  They can set up a table of valid combinations or invalid combinations.  And my own validation checks against those, too, once the whole line item is coded.  But I do NOT change the codes in the combobox dynamically to limit them.  I'm not much of a fan of catching validation problems at the keystoke.  I let them code a whole line before I check.  Particularly in the case of combination edits, you really can't catch it at the keystroke unless you can read their mind.  By the time you realize the combination is invalid, it may have been the fault of the FIRST segment value they entered, not the one they're on NOW.  So I just don't even attempt that kind of assistance.  And my clients seem to prefer that anyway.  It works just like their accounting system and this is often a criteria in my own decisions about application behavior.  I want mine to work like the one they spend most of their time in.

I was just hoping there was some elegant way to make the binding process see the data from different levels of this heirarchy in such a way that it can render them in the grid without a lot of custom code on my part.  I was thinking that there might be a way to render the heirarchy as flat for the data entry use case only, while preserving the parent child relationship elsewhere.  But if that elegance isn't there, I can live with flattening it for all contexts and supporting a maximum of ten segments as I did in the other app.  And with code generation, extending it to support 20 isn't really that big a deal (for a customer who comes along with a great enough need to pay for that enhancement <g>). 

I just have to admit that I cringe when I scroll past all those property declarations for the ones that will likely never get used. It just makes me feel slimy.  But I could get over that rather than go down an even more ugly road <g>.

Thanks for your input.  Have a great weekend.

 

Copyright (c) Marimer LLC