API: Access 'Account' for a TransactionLine of type ControlAccount

I am currently using the API (Manager.dll) to attempt to generate a custom report my accountant would like. The main part of this report involves iterating all the Receipt and Payment objects, and logging details about each transaction. Each Receipt/Payment has one or more TransactionLine objects which describe the break up of each transaction.

The TransactionLine class has a field ‘Account’ which is a Guid that can be looked up, and most of the time (for me) this will be a GeneralLedgerAccount. From the GeneralLedgerAccount I can access the Name field, which will tell me what type of income/expense the transaction is (for example ‘Postage’, ‘Travel’, ‘Software Sales’, etc.) this is how the line has been categorised by the user (these categories are what appear in the P&L account).

Sometimes, instead of the Account being a GeneralLedgerAccount, it is instead a ControlAccount. In the case I am currently debugging it is a movement of money from our bank account into a ‘Tax payable’ liability. However, I am unable to find the ‘Tax payable’ string anywhere (I know it is this because I looked it up in the web-interface). So my question is:

Given a Receipt, which has a single TransactionLine, where the TransactionLine.Account is a ControlAccount, how can I find out what category (in this case Tax payable) the TransactionLine refers to.

EDIT: It is worth noting, the ControlAccount.Name field is an empty string.

Actually all control accounts are hard-coded. Yes, there is a ControlAccount class but it’s not required to be present.

There is a static class Manager.Model.ChartOfAccounts which contains fields for all control accounts. One of them is TaxLiability which translated in UI as Tax payable (not very consistent but the account was originally called Tax liability even in UI)

Anyway, I’m in the process of moving all domain logic into Manager.Query namespace so rather than manually enumerating through all receipts or payments, you will be able to pull all general ledger transactions or even better, pull higher-level reports such as profit & loss statement or balance sheet.

Thank you. Based on your answer I added this helper:

public static String SplitByCasing(String input)
{
    string output = "";
    foreach (char letter in input)
    {
        if (Char.IsUpper(letter) && output.Length > 0)
            output += " " + letter;
        else
            output += letter;
    }
    return output;
}

And then this:

ControlAccount c = objects[account.Value] as ControlAccount;
e.m_Category = c.Name;
if (e.m_Category == "")
{
    Type type = typeof(Manager.Model.ChartOfAccounts);
    FieldInfo[] fields = type.GetFields();
    foreach (FieldInfo field in fields)
    {
        if (field.FieldType == typeof(Guid))
        {
            if (c.Key == (Guid)field.GetValue(null))
            {
                e.m_Category = SplitByCasing(field.Name);
                break;
            }
        }
    }  
}  

This seems to be doing the right thing from limited testing.

Thanks again.

I guess that’s one way to do it. Keep in mind Manager.dll is extremely raw at this point. I’m surprised there is someone who has a patience with it.

My plan is to organize classes and namespace the same way as you see it in UI. That way if you are familiar with the program, you would be familiar with API.

Well I have managed to generate my cross cast (mentioned in in another thread).

The source code is, as you might expect, a mess, as I was learning as I was coding. But it’s on GitHub; the project is here and the source file is here.

What is nice is that my cross cost total matches (exactly) with the cash flow summary, each of the bank accounts increase/decrease over the year match (there are 7 accounts in our case), and each of the category totals match the P&L account (except for journal entries, which I am about to speak to my accountant about to see how he wants this processed, as I suspect he’ll want this as a separate sheet).

Ultimately I hope that something like this could be integrated (in a much tidier way I’m sure) directly into Manager, the script currently has some limitations which are fine for my use case (like when a payment from a bank goes on an invoice, it only allows one transaction line on that invoice). This stuff could obviously be resolved if it was going to go into ‘production’ (i.e. included into Manager itself).

Good job, @scraft. How well I remember the joys of learning a programming language on a project. :smiley:

Perhaps since you’ve gone to all this work and discovered that everything matches perfectly, you can use your results to convince your accountant to simply look at Manager. :wink:

@Tut my accountants issue is not that he believes Manager is doing anything wrong (he doesn’t hold an opinion either way as he knows nothing about the software). Any issues with our accounts are almost certainly going to be the fault of me inputting things incorrectly. As mentioned in the other thread, this includes things like categorising an expense incorrectly, specifying something is subject to VAT when it isn’t, etc. With a cross cast he has a complete picture of the year and can identify all of these issues. Sure I’d much rather he could just use Manager (it would make my life easier) but I do appreciate from an an accountants point of view they aren’t interested in learning every piece of accounting software that exists. Instead they want each piece of software to be able to dump out a cross cast (or similar) where they can analyse the years activity and identify any issues.

@scraft, I fully understand your accountant’s perspective. But in some ways, his is a belt-and-suspenders-and-safety-pins approach. After all, double entry accounting was developed (some aspects by early Romans, others in the 12th-century Islamic world, and basically everything else but today’s computer automation by the Medicis of Renaissance Florence) to prevent and detect errors. Obviously, no system can prevent all errors, but the standards of modern accounting and the classical accounting cycle have evolved to allow audits to root them out. In fact, I would think of your accountant’s cross cast as an auditing tool, not an accounting tool.

I simply thought it would be amusing (and ironic) if, after all your work, your accountant became convinced that a cross cast was unnecessary.

Cheers.

@Tut as it goes, the cross cast has found a bug in Manager (see Currency gain/loss). So it looks like the work has been useful already :smile:

Maybe it is a good idea to create a ‘compatibility layer’ in your code if you work with the api in it’s voletile state. That way you only have to change one thing if the api changes, as the api of your compatibility layer would not change.

The whole project was a bit of an experiment; I was about to manually start copying and pasting lots of stuff from Manager into a spreadsheet when I realized there was any API at all. Once I realized there was an API I thought I’d poke around and actually found it relatively straight forwards to extract the data I required.

In the project now it also brings through Journal entries, which is nice as it means that each of the cross cast columns (which represent expenses, income, assets, liabilities, etc.) has a total which matches up with the profit and loss account. It also handles multiple currencies, so essentially all columns are in native currency (for me GBP) except for accounts which are held in different currencies (for these the correct currency for the account is used). When when you look across the cross cast, if there is (for example) $25 taken from a US bank account, it will display as the native (GBP for us) amount in the total/cost/vat and correct cross cast column.

Our generated cross cast is now sitting with our accountant, so I’m waiting to hear back to see if he has any problems or has anything that I can tweak in the program to make it easier for him. Once it has all been signed of, my plan was to present it to @lubos again to see if my work has made it any more likely that this sort of functionality could be included into Manager itself. From my perspective this is the ideal outcome; I often end up having to maintain these sorts of code chunks to interact with other software, and in just about every case it becomes a pain. My hope was the fact I was willing to spend considerable time adding this feature (via the API) would at least be testament to it being a feature I really wanted (not just another forum feature request which isn’t particularly required/useful/necessary, more of a passing thought, etc.)

If it isn’t accepted as a first class citizen of Manager, maybe the code could do with some re-factoring/maintenance. If you have any ideas/expertise @ebunders please feel free to fork the repo and submit a push request with any changes/improvements and I’ll merge them back in (and unit test it again my current cross cast results to make sure no functionality has changed).