Question

I'm working on a system where users have different types of 'Accounts' of the financial type. I'm struggling to come up with a design that works.

Background

A user has 2 types of accounts: A 'tab' account and a 'debt' account.

Debt

Here, the 'head office' pays for things for the user. Things like an event, a dinner,.. At some point the user adds money to the account to set the balance back to zero. I have no problem modelling this, as it are merely transactions

Tab

This account holds transactions related to orders the user has placed. A user, for example, orders 2 drinks from the bar. The cost of this, I think, should also be modelled as a transaction with a reference to the order that generated the transaction.

Here, the account also has a balance. Specific to the orders

Right now I've modelled it like this.

public abstract class Account
{
    public Guid Id { get; set; }

    public decimal Balance { get; set; }

    public DateTime LastUpdated { get; set; }


}

public class DebtAccount: Account
{

    public ICollection<DebtTransaction> Transactions { get; set; }
}

public class TabAccount: Account
{
    public ICollection<TabTransaction> Transactions { get; set; }
}

public abstract class Transaction
{
    public Guid Id { get; set; }

    public decimal Amount { get; set; }

    public DateTime Date { get; set; }

    public string Description { get; set; }
}

public class TabTransaction : Transaction
{
    public Orderline Consumption { get; set; }
}

public class DebtTransaction : Transaction
{

}



 public class User {

public DebtAccount DebtAccount {get;set;}
public TabAccount TabAccount {get;set;}

}

I keep looking at it, thinking something doesn't feel right, but I can't come up with a better solution.

I'm also struggling with how to translate it to a database design.

Extra information: I'm writing the application in C#, .NET and Entity Framework.

All advice, small or big would be much appreciated.

Was it helpful?

Solution

You are tying together different ideas that should be separate.

A transaction is the same regardless of the type of account it goes against, so there should not be different types. Think of buying something in a store. You don’t approach the process differently depending on whether you have cash or a credit card (which is basically a Tab). The transaction only cares that the amount specified is satisfied in some way.

The TabAccount and DebtAccount are also the same thing. It’s a container for holding transactions and a running balance. You should get rid of both of those and just keep Account. You would instantiate 2 accounts in memory – a TabAcount and a DebtAccount, but both would be of the class type Account.

One of the core principles of accounting is double entry. Every transaction MUST have a debit account AND a credit account. You should put a DebitAccount and a CreditAccount property in the transaction. With only a Debt and Tab account, you don’t have anything for the other side of the transaction. You need an InventoryValueOnHand account for that so InventoryValueOnHand decreases when the other account increases.

This leaves you with just 3 classes: User, Account, and Transaction. In the DB, a User has a one to many relationship with Account, Account has a one to many with Transaction, and Transaction has 2 one-to-one relationships with Account (debit and credit account).

OTHER TIPS

There is no model without behavior. Without knowing what functionality these objects must provide there is no point discussing details.

Collect all the relevant functionality these object must provide and let those functionalities drive the model. For example, if there is separate functionality for a Tab and for a Debt account, then those are separate objects, if not then they're not!

In essence you need to do the modelling the other way. Forget about the "data" and "relationships". Model the functions first. Those will give you the objects. After that you can decide who holds what data.

Licensed under: CC-BY-SA with attribution
scroll top