dmitry-merzlyakov / nledger

.Net Ledger: Double-Entry Accounting System
Other
180 stars 51 forks source link

Core double entry components in nLedger #2

Open drobertson123 opened 6 years ago

drobertson123 commented 6 years ago

Thanks for the work, I apreciate it.

I am attempting to use nLedger in a bit unconventional way. I need to incorporate it into a portfolio tracking system for complex derivatives trades.

The entries will actually be in a database instead of a text file. I could certainly export it, but it would make more sense to just work directly with that data.

I also need to run micro ledgers for trade analysis. These would just be a regular ledger but only focus on the entries related to a specific trade.

My question is what classes should I be focusing on as the entry point for doing this. Basically where would I start if I just wanted to use the Double Entry Accounting functionality of the code?

Anything you can share would be very helpful, but don't feel like you need to do my homework. I am just looking for basic guidance.

Thanks

dmitry-merzlyakov commented 6 years ago

Hi Doug,

Thank you for interest to this product. At this moment, I see two general strategies to integrate NLedger with external applications:

1) Deal with it as with a black box that consumes a text stream and produces a formatted output; 2) Manually populate Journal entries (Xacts, Posts) and Accounts and run the reporter;

In my opinion, the first way is preferable (at least, at this moment) because it is easier and more stable. I understand we all like to work with domain objects, but in case of NLedger it might be too complicated. The drawbacks are:

Of course, everything is possible and if you decide to follow the second option - do not hesitate to ask any questions about the code.

If you decide to follow the first option, I suggest to look at either Program.cs or TestRunner.cs - they both have a code to run NLedger as a black box:

Further (in about three +/- months) I want to complete and publish a much more convenient integration way. My plan is to implement the way how Ledger is integrated with Python - but make it more generalized. In two words:

So, people will be able to communicate with NLedger in the same way as the original Ledger is called from Python environment. Unfortunately, this feature is currently in development so it is only a plan.

Thank you! Dmitry

VagyokC4 commented 4 years ago

@dmitry-merzlyakov

I have a question regarding "black box" usage:

I have a console app that has a consumer listening to a queue, and it consumes messages which identify the specific ledger file and query to run like so:

public class NLedgerRequestConsumer : IConsumer<NLedgerRequest>
{
    private static readonly object lockObject = new object();

    public Task Consume(ConsumeContext<NLedgerRequest> context)
    {
        context.Respond(new NLedgerResponse
        {
            Result = QueryLedger(context.Message.LedgerFile, context.Message.LedgerQuery)
        });

        return Task.CompletedTask;
    }

    public string QueryLedger(string ledgerFile, string query)
    {
        lock (lockObject)
        {
            // Capture Output
            var       sb = new StringBuilder();
            using var sw = new StringWriter(sb);
            Console.SetOut(sw);

            // Initialize NLedger
            var main = new Main();
            new NLedgerConfiguration().ConfigureConsole(MainApplicationContext.Current);

            // Execute Query
            return main.Execute($@"-f {ledgerFile} {query}") == 0
                ? sb.ToString()
                : nameof(Exception);
        }
    }
}

Since you are very intimate with the inner workings of the code, my question is:

Do you see any issues that could arise from using the NLedger library like this as a black box implementation? or is more needed to isolate the statics being used internally?

dmitry-merzlyakov commented 4 years ago

Hi @VagyokC4,

Yes, it should work. Basically, I would recommend to check TestRunner class; it mostly does the same work. See how you can extract error messages, add post-processing for the output etc.

In regards to multi-threading: though I did not make special tests, I would tell that everything inside your QueryLeadger method should be thread-safe. All static variables are [ThreadStatis] and managed by MainApplicationContext class. So, you should be able to run QueryLedger in parallel without a global lock.

And, just a comment - you can consider implementing your own providers to simplify interop with NLedger (check "Abstract Application Services" in MainApplicationContext). E.g. input files might be kept somewhere in DB, not in the file system.

If you have any further questions - please, ask.

Thanks, Dmitry

VagyokC4 commented 4 years ago

@dmitry-merzlyakov Perfect. Thank-you!

I found your road map to version 1.0. How is that coming along?

dmitry-merzlyakov commented 4 years ago

Hi @VagyokC4

The road map is more or less still on track; the goals are not changed. Basically, I would tell that my current priorities are:

I am going to include this stuff into 0.8.

Thanks, Dmitry