Starting a CLI Finance Tool
Tags: csharp
Published: 2021-08-05 22:04:13

## Motivation

This is a finance tool project based heavily on [beancount](https://github.com/beancount/beancount) but with less features and way less complexity. After reviewing the beancount repo and documentation, I noticed that there are many more features available that I will use. In an attempt to create a new project with a new language, C#, this project was born.

## Outline

This is a console application. As of right now the only major dependency is the `System.CommandLine` package. The commands code is written in `namespace Controllers.Commands` and the parsing and formatting of entries is written in `namespace Controllers.VaultAccess`.

### Commands

Here is an example of one of my commands.

```
using System;
using System.CommandLine;
using System.CommandLine.Invocation;
using Controllers.VaultAccess;
using Config;

namespace Controllers.Commands
{

    public class NewCommand : Command
    {

        public NewCommand() : base("new", "Create a new vault entry")
        {
            AddArgument(DetailsArgument());
            AddOption(DateOption());
            AddOption(DirectiveOption());
            AddOption(ValueOption());
            Handler = CommandHandler.Create((DateTime date, string directiveType, string details, double currency) =>
            {
                JournalEntry entry = new JournalEntry(date, directiveType, details, currency);
                Console.WriteLine(entry.ToString());
            });
        }
```

The logic is unfinished but clear. My command class inherits from `System.CommandLine.Command` and abstracts away all of its logic when initialized. Using this format I am able to encapsulate the Options and Arguments into their own private methods.

```
 private Argument<string> DetailsArgument()
        {
            Argument<string> details = new Argument<string>("details");
            details.Description = "The details of this journal entry";

            return details;
        }

        private Option<DateTime> DateOption()
        {
            Option<DateTime> date = new Option<DateTime>("--date");
            date.AddAlias("-d");
            date.Description = "Date of entry";
            date.SetDefaultValue(DateTime.Now);

            return date;
        }
```

### Journal Entry

Beancount is a very mature program and they have tested and perfected the input format for their entries. I am matching their input formats and created the `JournalEntry` class to handle the input, parsing, formatting, and output of the journal entry.
Here is an example of the format that I am expecting to output into my journal files
`<Date>   <Directive>      <Details>         <Value><Currency>`
`08/05/2021 open    Liability:Food:Restaurant    -35 USD`

```
public class JournalEntry
    {
        private readonly int DATE_MAX_WIDTH = 13;
        private readonly int DIRECTIVE_MAX_WIDTH = 7;
        private readonly int DETAILS_MAX_WIDTH = 45;
        private DateTime entryDate { get; set; }
        private string directive { get; set; }
        private string details { get; set; }
        private double currency { get; set; }
        public JournalEntry(DateTime date, string dir, string det, double cur)
        {
            entryDate = date;
            directive = dir;
            details = det;
            currency = cur;
        }

        public override string ToString()
        {
            return string.Format("{0}{1}{2}{3}",
            entryDate.ToShortDateString().PadRight(DATE_MAX_WIDTH),
            directive.PadRight(DIRECTIVE_MAX_WIDTH),
            details.PadRight(DETAILS_MAX_WIDTH),
            currency);
        }
```

## Next Steps

The hardest feature that I have yet to implement are the accounting logic and maybe more importantly the parsing of each line in the journal to make the various accounting reports. I intend to add reports for all the open assets and liabilities, balances of accounts, and history of expenditures.
The benefit of this project is that it is not the first. I can copy over some of the logic from existing accounting tools and then build and better them.

## [Github Repo](https://github.com/Ces-D/cobblepot)