adamcharnock / django-hordak

Double entry accounting in Django
http://django-hordak.readthedocs.io
MIT License
231 stars 55 forks source link

Credits and Debits #59

Closed the-solipsist closed 2 weeks ago

the-solipsist commented 2 years ago

The accounting for developers says that:

Debits decrease the value of an account. Always. [1] Credits increase the value of an account. Always. [1]

This statement is meaningless unless you clarify what "decrease" and "increase" mean. Instead, it would be better to write:

Debits are inflows to an account. Always. [2] Credits are outflows from an account. Always. [2]

To understand why your explanation is wrong, let's take two separate cases.

Unsigned Accounting

If by the terms "increase" and "decrease" you're referring to unsigned accounting (i.e., traditional accounting, where all values are positive), then this is wrong.

Let's take a simple example: You purchase an apple using cash. In this case:

This is the opposite of what you say debit and credit mean.

Signed Accounting

If you're referring to "increase" and "decrease" in terms of signed accounting, where you have both positive and negative numbers (as is the case, for instance, with plaintext accounting), then too this statement is wrong.

If we take "increase the value" to mean "move towards the right / towards the positive direction on a number line", then "debits" increase the value of an account. Always.

If we take "decrease in value" to mean "move towards the left / towards the negative direction on a number line", then "credits" decrease the value of an account. Always.

This table summarises whether an absolute increase (i.e., in either direction on a number line, away from zero) in a particular account is indicated by a credit or debit / addition of a positive number or addition of a negative number.

Account Type Credit / Debit Positive / Negative
Asset Debit Positive
Expense / Loss / Cost / Dividend Debit Positive
Liability Credit Negative
Shareholders' Equity Credit Negative
Revenue / Gain Credit Negative
Contra Asset (e.g., Accumulated depreciation, or Allowance for doubtful accounts) Credit Negative
Contra Expense (e.g., Cash back rebates) Credit Negative
Contra Liability (e.g., Discount on bonds payable) Debit Positive
Contra Equity (e.g., Owner's drawing account / treasury stock account of reacquired shares) Debit Positive
Contra Revenue (e.g., Sales discounts) Debit Positive
PetrDlouhy commented 1 year ago

I am maintaining this package, but I don't have deep enough knowledge of double-entry accounting for this to judge. I would say, that PRs are always welcome, especially if they are improving the documentation. But I would be glad if somebody could help me with the review of such PR.

nitsujri commented 1 year ago

I'm just entering this space and learning a lot (so typing this is helping me too). I agree with @the-solipsist that the statement "always" increase/decreases actually makes it more confusing at face value especially if you try to "manually write out a T-account" or understand manual ledger entries.

BUT - the always increases/decreases actually does work if you include statement #4, "The sign of any asset or expense account balance is always flipped upon display (i.e. multiply by -1)".

This is because the original accounting equation is Assets + Expenses = Liabilities + Income (and more), Left Hand Side (LHS) says debits increase and credits decrease while the Right Hand Side (RHS) says debits decrease and credits increase (confusing af, so watch the videos below).

By saying "credits always increase...", the meaning of the LHS has been flipped. That would be incorrect, but then you go to statement #4 which flips the account back the other way, correcting the "error".

These individual accounts are rolled together to create a general ledger, so the math evens out.

Watching Debits & Credits Explained while doing T-account exercises really helped me understand it.


Not sure if it's more confusing or helpful, but if you use the other form (refactor?) of the equation 0 = Liabilities + Income - Expense - Assets now the LHS is flipped in direction so the statement "credits always increase...." works.


In the end, I think the statements, while confusing, are valid because that is actually what's happening under the hood in hordak.

adamcharnock commented 1 year ago

I just saw some email notifications so just thought I'd leave a quick comment.

I know some people have not been hugely impressed with how I chose to model the accounting system. I came at this from the perspective of a software developer, and I did spend quite a long time reading into it. I also validated the choices I made with pretty thorough testing against validated examples I got from third parties. That being said, that does not mean I made the best or most optimal choices. Plus I'm pretty hands-off with this project right now, so my opinion should only count for so much.

I will say that in software it is common to separate the idea of data modelling and data presentation. Just because it may make sense to store data in a particular way does not mean that is how it is presented to the user. I suspect (but do not know) that this idea is less prevalent in the accounting world, which can make my 'double entry accounting for software developers' page seem somewhat abhorrent to seasoned accountants.

We store data in a way that makes sense for the software and its ongoing development, and then we present it to the user in a way that makes sense for the user.

However, if the way we are storing data is not serving the software/code well, then that would definitely be a reason to change it. Or if that means we cannot present the information to users that they need, that would also be a reason to change it. But users not liking how we store data really doesn't matter (not saying that anyone here is making that point).

I've only lightly skimmed the comments above, and none of this is aimed at anyone. I'm just adding it here for context and to share my opinion. It is always wonderful to see my old projects being worked on and maintained.

the-solipsist commented 1 year ago

Whether debits increase or decrease an amount will necessarily depend on the sign. If the sign is a presentation issue, not a modelling issue, then the terms "increase" and "decrease" have no meaning in relation to "debit" and "credit" since they inherently depend on the signs of the accounts. Either the text, keeping in mind Assets as positive-signed, should say:

Debits increase the value of an account. Always. Credits decrease the value of an account. Always.

Or the far clearer alternative that I suggested:

Debits are inflows to an account. Always. [2] Credits are outflows from an account. Always. [2]

Given that point # 5 says, "money must come from somewhere and then go somewhere", the terms "inflow" (money that comes in) and "outflow" (money that goes out) are preferable to "increase and "decrease".

In -50 + -10 = -60, is the total -60 an "increase" or a "decrease" from -50? One could justify using either term. Given this, it is best to avoid "increase" and "decrease", and stick to "inflow" and "outflow", which is clearer and applicable in every case, regardless of whether the number is positive or negative, and regardless of the account type.

nitsujri commented 1 year ago

@the-solipsist again you're correct from an accounting perspective but not when it comes to this codebase:

# https://github.com/adamcharnock/django-hordak/blob/master/hordak/models/core.py#L502
def type(self):
    if self.amount.amount < 0:
        return DEBIT
    elif self.amount.amount > 0:
        return CREDIT

The documentation's wording is accurate to the code (not to accounting). The DB does not store debit/credit. It stores a value positive/negative. So why does it work?

Effectively the meaning of inflow/outflow is assigned at a higher level than the database. It goes against convention because it's using 0 = Liabilities + Income - Expense - Assets version of the equation.


@adamcharnock I don't think the danger is in the database's model itself because positive amount always means inflow and negative always means outflow.

The danger is in Leg.is_debit and Leg.is_credit because convention says that changes depending on the account type because convention is always using this form of the equation: Assets + Expenses = Liabilities + Income where RHS and LHS are flipping debit/credit.

This means we can't build T-Accounts to the normal convention (the legs will appear in the wrong position for Assets, Expenses).

What do you think about - Two options:

Thoughts? @adamcharnock @PetrDlouhy

Related: https://github.com/adamcharnock/django-hordak/issues/53

the-solipsist commented 1 year ago

One simple suggestion:

Add a line near the top noting, "This guide isn't about accounting for developers", but "how Hordak does accounting, for developers. The terms 'credit' and 'debit' as used in Hordak's code follows the convention of Assets and Expenses normally being negative quantities and hence 'credit' and 'debit' don't mean what they mean when it comes to traditional double-entry accounting (which uses unsigned numbers), plaintext accounting (most of which follow the convention of having Assets and Expenses normally being positive), etc."

The confusion really is in developers misunderstanding this to represent accounting rather accounting in Hordak.

adamcharnock commented 1 month ago

Re @nitsujri (cc @PetrDlouhy):

Ah yes, I can certainly see your point there. Maybe I was thinking something different back in 2016, but presenting credits and debits in this way is clearly wrong.

  1. Making is_debit, is_credit and Leg.type functions private so they don't confuse those expecting a particular convention. Probably depreciation warning first.
  2. Changing is_debit, is_credit and Leg.type to adhere to accounting convention.

Certainly option 2 seems the cleanest to me. It is backwards incompatible, but I have to hope that no one is relying on the current behaviour of is_debit and is_credit given it is plainly incorrect.

Perhaps this would justify a jump to version 2.0 too.

Edit: Add to the list LegManager.debits() and LegManager.credits()

adamcharnock commented 1 month ago

Ok, I've been refreshing my memory on this this afternoon. My original understanding was that is_credit and is_debit were mis-reporting debits as being credits, and vice-versa. But as I have investigated the various plans for architecture change I've realised this is not the case. And perhaps this was never meant to be implied, I'm not sure.

Changing is_debit, is_credit and Leg.type to adhere to accounting convention

So it seems that my new opinion is that these do indeed adhere to accounting convention. But am I misunderstanding somehow?

adamcharnock commented 2 weeks ago

I've created #120 which relates to this, also I add a line to the docs in relation to this too (4106f982fdf7094b787fe9b16755a47a56a39676).

I'm gong to close this now, but feel free to create a new issue/PR if there is something actionable to be done.