Open drobertson123 opened 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:
you can collect data from your database and compose an input text stream (formatted as an Ledger journal). I understand it sounds ugly, but, actually, it might be not so bad idea - you need to get your data into memory anyway; composing a text stream is a fast operation, so it may work quite efficient;
you can get the output stream and handle as you need. You can consider writing an own AnsiTextWriter in case you want to colorize the output on your own way (e.g. for Web). Another possible option is to specify own formatting templates (please, take a look at the original Ledger documentation; there are some examples - all they are supported). It might help you to adopt the output stream to be handled by your code in more convenient way. You can also look at the MainApplicationContext.Current and observe parsed data (Journal entries, accounts etc). Unfortunately, report data is not accessible.
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
@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?
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
@dmitry-merzlyakov Perfect. Thank-you!
I found your road map to version 1.0. How is that coming along?
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
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