2

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.

3
  • Can you elaborate what doesn't feel right to you? What doesn't feel right to me is that a TabTransaction refers to a single consumption. Personally, I wouldn't add those at all, as I don't see value in keeping track of that besides the monetary value of the transactions. Commented Nov 5, 2019 at 11:25
  • The best database design is to follow established patterns for accountancy records: account headers, journal entries (consisting of headers and lines), ledger lines, and periodic summary balances.
    – Steve
    Commented Nov 5, 2019 at 13:51
  • @BartvanIngenSchenau I'd like to know where the transaction comes from so I can reference to it (e.g. in the frontend). For me it doesn't feel right to create two Account types, just to have the same property but from a differen type. Same for the transaction. The logic itself probably won't be different all that much but for the reference of the Orderline. Commented Nov 5, 2019 at 17:41

2 Answers 2

3

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).

4
  • Thank you for your input! A user can have only one of each account. With that info, do you think it's a good idea to have 2 columns in the db referencing the ID's of the tab and debt account respectively? Commented Nov 10, 2019 at 19:00
  • 1
    Though that would satisfy the requirements, I would go the User having a list of "owned" accounts. It is easy enough to enforce the limit of only 1 of each type of account, but if requirements change later, it's also trivial to allow more than one account. If you have 2 properties then changing to support multiple accounts later is much more difficult. With a list it's also easier to introduce a new type of account later.
    – Brad Irby
    Commented Nov 11, 2019 at 18:24
  • Thank you. I actuallu went with the solution just suggested. Commented Nov 14, 2019 at 13:17
  • Just a short PS, I was thinking about this later and realized Transaction should have 2 many-to-many relationships to Account, one for debits and one for credits. This lets you buy more than one item at a time, and pay with more than one account at a time (i.e. buy a tooth brush and tooth paste, then pay with half cash and half credit card). They need to be many-to-many because multiple people can buy tooth paste, and you can use your debit card for multiple transactions.
    – Brad Irby
    Commented Nov 14, 2019 at 14:06
1

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.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.