Difference between revisions of "Credit Notes"

From GnuCash
Jump to: navigation, search
(gncInvoicePostToAccount (in gncInvoice.c))
m (Reverted edits by Eugene (talk) to last revision by Cstim)
 
(15 intermediate revisions by 6 users not shown)
Line 11: Line 11:
 
At present, GnuCash doesn't really support credit notes. The workaround suggested is to make a payment to the vendor for the amount of the credit note received. In this way at least GnuCash knows the vendor owes you this amount of money and will substract it automatically from the next invoice(s). This is not optimal in several ways:
 
At present, GnuCash doesn't really support credit notes. The workaround suggested is to make a payment to the vendor for the amount of the credit note received. In this way at least GnuCash knows the vendor owes you this amount of money and will substract it automatically from the next invoice(s). This is not optimal in several ways:
 
* There's no document tracking. GnuCash doesn't know anything about the credit note.
 
* There's no document tracking. GnuCash doesn't know anything about the credit note.
* Income/Expense accounts aren't updated properly. Say the credit note was for a book you bought before, then the original invoice would increase the "Books" expense account, yet the expense account isn't decreased when the credit note is processed. So you end up with an incorrect balance. And it gets even more complicated if the credit note has multiple entries (with or without taxes).
+
* Income/Expense/Tax accounts aren't updated properly. Say the credit note was for a book you bought before, then the original invoice would increase the "Books" expense account, yet the expense account isn't decreased when the credit note is processed. So you end up with an incorrect balance. And it gets even more complicated if the credit note has multiple entries (with or without taxes).
  
 
What follows is an analysis of what is required to fully support credit notes in GnuCash. This includes an interface to enter credit notes and how to handle credit note payments or invoice/credit note interactions.
 
What follows is an analysis of what is required to fully support credit notes in GnuCash. This includes an interface to enter credit notes and how to handle credit note payments or invoice/credit note interactions.
  
Since credit notes will somehow end up in the GnuCash data file, it can also happen that such a data file is opened with an older version of GnuCash not supporting credit notes. So it is equally important to analyse what impact the changes in the engine will have on older GnuCash releases.
+
The sections below will analyse parts of the GnuCash code that may be impacted when implementing credit notes. Each section starts with a rough description of the code in question, how it could be impacted and what has to be done to deal with this.  
  
Note that the basic premise for new features is always that the new version of GnuCash must be able to handle the new data, while the old version should at least be able to read it, but not modify it. Changes proposed will always be in this sense.
+
At the end of each section I will add summaries of the changes required in the code ('''TODO''').
 
 
The sections below will analyse parts of the GnuCash code that are may be impacted when implementing credit notes. Each section starts with a rough description of the code in question, how it could be impacted and what has to be done to deal with this.
 
 
 
At the end of each section I will add two summaries the changes required in the code for GnuCash versions that do support credit notes ('''New''') and versions that don't support it yet, but must still deal with data files that might have credit notes ('''Old''').
 
  
 
== Artificial limitation... ==
 
== Artificial limitation... ==
Line 33: Line 29:
 
== New approach ==
 
== New approach ==
  
Preferred design limitation: change the existing data format (xml data definition or SQL schema) as little as possible. That way an older version of GnuCash can still read the data file unmodified. As you will see below, that doesn't mean it will interpret the data completely correctly though.
+
'''Note''' A first attempt was made to implement Credit Notes in a way that was more or less backwards compatible. There were several drawbacks to this attempt and it would remain clumsy for future extensions. So after some discussion on IRC, I decided to forgo backwards compatibility and work on a cleaner design. The original attempt can still be found [[http://wiki.gnucash.org/wiki/index.php?title=Credit_Notes&oldid=7819 here]]. It may be useful to understand the origin of some design decisions.
  
The direct consequence of this restriction is that the current data format has to be reused to store our additional data. I can't add a field to an invoice data structure (on disk or on the database, that is) indicating whether the invoice represents a true invoice or a credit note. The one thing we can play with is that the price fields for invoice entries are currently always stored as a positive value. We could extend this that for credit notes the field stores a negative value.
+
Since invoices and credit notes are mostly the same thing except for their sense, the code for both objects is largely the same. But the GUI has to know which type it is handling to update various labels and internal sign of the values entered. To accommodate for this '''a new field will be added''' to the invoice object. This field will hold the invoice object "type", being invoice or credit note. Together with the owner type (Vendor/Customer/Employee) the code can reliably determine which labelling to use and the sign of the associated values.
  
That causes a practical limitation upfront: with this implementation GnuCash won't be able to distinguish between a negative invoice and a credit note. Both would be saved in the data file with negative amounts. As mentioned in my introduction, I consider this distinction as an accounting detail, which doesn't really affect the numbers, so for a first implementation I believe this limitation should be ok.
+
Note that this design decision means that the data format is no longer compatible with older GnuCash versions.
  
A second practical limitation is that GnuCash doesn't know how to interpret an invoice with a 0 total amount when loading from file. Should this be seen as an invoice or a credit note ?
+
The user must be able to enter Credit Notes just as he can enter invoices. The invoice dialog and register can mostly be reused. One particular detail to keep in mind: a normal document be it invoice, bill or customer/vendor credit note is always entered with positive values in the ledger, even if these values have opposite effects on the balance. The proper sign of these values is dealt with internally. For bills and invoices this is already so, but for customer/vendor credit notes, the logic for this still has to be extended.
  
Let me clarify the relevance of this question:
+
Posting a credit note is exactly the same as posting an invoice. However the logic to post invoices will not work properly with credit notes, though this can probably easily be fixed. For more details, see below.
  
When you receive a normal vendor bill the values on it are positive. The same goes for an invoice you send to your customer. You put positive values on it. Yet from an accounting point of view these documents have an opposite effect on your balance. So GnuCash considers one of both as a negative document internally by reversing its sign (From the code I gather customer invoices are treated as negative documents). Extend this to credit notes. When you receive a credit note the values on it are positive. Yet its impact on your balance is the opposite of that of an invoice. So from the above logic, a credit note from a vendor is internally treated as a negative document and should have its sign reversed.
+
At some point the credit note has to be "paid". In real life this is usually done by substracting it from the amount still due on other invoices of the same business partner. This would mean that the payment logic should be extended to allow this. There are two parts to this:
 +
* The automatic payment assignment logic: this logic currently automatically assigns payments to open invoices, but doesn't know anything about credit notes yet and would definitely handle those wrongly. See later for more details on this.
 +
* The payment dialog: this is what the user uses to assign payments. It doesn't allow to link a credit note to an invoice though. This may be extended to show all open documents for a business partner and allowing the user to select multiple ones.
  
Back to loading from file. With the combined knowledge of the invoice's owner type (vendor/customer) and the sign of the values stored (positive for invoices, negative for credit notes), GnuCash can clearly determine if the loaded invoice object actually represents an invoice or a credit note.
+
I'm not sure how difficult these improvements would be. In the first phase at least I intend to ignore this part. Instead invoices and credit notes will be totally unaware of one another. Instead you pay each one separately. This will mean one superfluous transaction, but the total balance is still correct.
  
But what if an invoice object with 0 total balance was saved ? This can happen for an incomplete invoice (no entries yet) or an invoice/credit note that really has a zero balance. In that case GnuCash doesn't have sufficient data to determine if the invoice object originally was an invoice or a credit note.
+
If the code behind all the user actions above makes sure the sign of all splits introduces remains correct, then the generic accounting logic continues to work unaltered. The same goes for all reports that are only interested in transactions.
  
This has some implications for the GUI code, but for that let's first see which improvements are needed in that area:
+
There are only a few improvements required for reports:
 +
- A user may want to print a credit note at some point (particularly a credit note to a customer). The reports used to print invoices are reusable, but will have to state "Credit Note" instead of "Invoice" and they will have to take care of using the proper sign of the values.
 +
- A business partner overview (vendor report/customer report) may want to distinguish between invoices and credit notes as well. It doesn't right now.
  
To be able to enter credit notes there either has to be an additional New Credit Note... menu item or the current New Invoice... menu item has to be reworked to be more flexible. In the first case a dialog should pop up with the title "New Credit Note" and all other labels adapted accordingly. The latter case could be done by adding a combo box to the New Invoice... dialog which lets the user choose Invoice or Credit note. In that case "New Invoice" doesn't reflect the functionality very well anymore, so a new name is desirable, for example "Sales statement"/"Purchase statement".
+
= Analysis of affected parts=
  
The next GUI related to invoices/credit notes is the invoice ledger. It holds all the entries. Note that for user convenience, you currently can enter both a bill and invoices with positive values, exactly as on the document they reflect. That same convenience should also be extended to credit notes. You should simply use the positive values from your document. It's up to GnuCash to internally decide when the signs have to be reversed to balance everything properly.
+
== xml backend ==
  
So when GnuCash brings up invoice ledger it needs to know if it is dealing with an invoice or a credit note and that for a vendor or a customer. It needs to know this to
+
Since I'm adding a new field invoice type field to the invoice object, the xml backend will need to know how to save or load this new field.
* do the proper sign reversals such that the user can enter positive values no matter what the document type is
 
* use the proper names and labels (Invoice/Bill/Credit Note,...) throughout the page
 
  
When you just created a new document using the above New Credit Note/New Credit Note dialog or the Sales statement dialog, GnuCash has all the information it needs. If it loads an invoice object from file with a positive or negative total value, it also has all the information it needs. But when it loads an invoice object with 0 total value, it suddenly is missing a piece. Both invoices and credit notes may have zero balances, so both could be present in a data file. So what should GnuCash do in this case ?
+
:'''TODO'''
It can either assume all 0 value invoice objects are real invoices or ask the user how to interpret the invoice object. Neither are optimal and so far I haven't figured out yet which one is best to use. And if neither is acceptable, that means the original design goal (don't add data fields) can't be held. For now, I'll assume it does.
+
:*A new row will have to be added to the invoice_handlers_v2 table in gnc-invoice-xml-v2.c for the invoice type field
 +
:*A handler for this field should be written.
  
Continuing the required changes: payments. As explained above, the payment logic depends on the use of lots. Obviously this logic should be improved to take credit notes into account. Details on that follow later in the analysis. Note that the automatic payment assignment logic is not ready to handle credit notes. See below for more details on this as well.
+
:'''UPDATE'''
 +
:To avoid unnecessary backward compatibility issues, the invoice type field is implemented as a kvp (is_credit_note). '''''DONE'''''
  
In it's simplest form, invoices and credit notes are treated independently during payment. Just as you can't assign multiple invoices in one payment, you can't assign one or more invoices and credit notes together in one payment. So with the invoice payment dialog, you simply select one document at the time and pay it regardless of whether the document was an invoice or a credit note. What has to be taken care of is again the necessary sign reversals, so that you always can enter payments as positive values.
+
== sql backend ==
  
This is slightly confusing and cumbersome though. Ideally, payment-wise a credit note reduces the payment amount of an invoice, just like a pre-payment would. And ideally, you could also add multiple documents into one payment, be it credit notes or invoices. That would call for a more extended GUI, that allows you to select multiple documents instead of to single document now to pay. This is likely outside the scope of the Credit Notes project though, but may be added as a follow up.
+
Like with the xml backend, we need to know how to save or load the invoice type field.
  
= Analysis =
+
:'''TODO'''
 
+
:*A new row will have to be added to col_table in gnc-invoice-sql.c.
The first step of this analysis is to uncover all parts of GnuCash that may be influenced if negative invoices were allowed.
 
  
 
== Engine ==
 
== Engine ==
Line 76: Line 75:
 
=== gncInvoiceGetTotalInteral and friends (in gncInvoice.c) ===
 
=== gncInvoiceGetTotalInteral and friends (in gncInvoice.c) ===
  
As explained above, internally some invoice types are considered negative internally, while they are presented positive to the user. The functions calculating the totals take this into account. There are several totals that can be calculated, but all use the gncInvoiceGetTotalInternal as a basis. And this function currently determines when to reverse the value. Since we are adding new invoice types, this reversal check must be adapted. For older versions of GnuCash, credit notes are simply considered as read-only negative invoices and I allow the GUI to display them as negative even. That way, no changes are required in the old gnucash version.
+
As explained above, internally some invoice types are considered negative internally, while they are presented positive to the user. The functions calculating the totals take this into account. There are several totals that can be calculated, but all use the gncInvoiceGetTotalInternal as a basis. And this function currently determines when to reverse the value. Since we are adding new invoice types, this reversal check must be adapted.
 +
 
 +
:'''TODO'''
 +
:*The reverse logic should be updated. Probably it should be refactored in an independent function to be used by later modules as well.
  
:'''Old'''
+
'''Update'''
:*No changes required.
+
This is actually not the case. The gncInvoiceGetTotalInternal function uses the "reverse" parameter only to determine if the sum should use the entry's i_* values or the b_* values. The first one stores customer invoice amounts (and future customer credit note amounts), the latter stores vendor bill amounts (and future vendor credit note amounts).
  
:'''New'''
+
To avoid confusion I will rename the "reverse" parameter to a more telling "is_cust_doc". This better reflects what the parameter is actually used for. '''''DONE'''''
:*The reverse logic should be updated. Probably it should be refactored in an independent function to be used by later modules as well.
 
  
 
=== gncInvoicePostToAccount (in gncInvoice.c) ===
 
=== gncInvoicePostToAccount (in gncInvoice.c) ===
Line 91: Line 92:
 
By the way this check is not in gncInvoicePostToAccount but in the helper function gnc_lot_match_owner_payment in the same file.
 
By the way this check is not in gncInvoicePostToAccount but in the helper function gnc_lot_match_owner_payment in the same file.
  
These checks together mean that posting a credit note will never accidentally try to post it to an open invoice lot, which simplifies backwards compatibility considerably.
+
These checks together mean that posting a credit note will never accidentally try to post it to an open invoice lot.
  
 
The code as is however will fail to work for posting credit notes because of the simple sign evaluation. To enable posting for credit notes the gncInvoicePostToAccount the calculation of the "reverse" parameter will have to be extended.
 
The code as is however will fail to work for posting credit notes because of the simple sign evaluation. To enable posting for credit notes the gncInvoicePostToAccount the calculation of the "reverse" parameter will have to be extended.
  
:'''Old'''
+
:'''TODO'''
:*No changes required.
+
:*The code to find lots eligible to post to should be revised. One way to do this is to set the "reverse" parameter not only on owner type but also on invoice vs credit note. '''''DONE'''''
 
 
:'''New'''
 
:*The code to find lots eligible to post to should be revised. One way to do this is to set the "reverse" parameter not only on owner type but also on invoice vs credit note.
 
  
 
=== gncOwnerApplyPayment (in gncOwner.c) ===
 
=== gncOwnerApplyPayment (in gncOwner.c) ===
Line 106: Line 104:
  
 
When filtering the lots, there's no check on sign. All open lots will be selected. When later the routine starts applying payments the sign is checked. Note that in this context a payment is considered negative, compared to an invoice balance being positive. Since a credit note has the opposite sign of an invoice it's also considered negative in this context.
 
When filtering the lots, there's no check on sign. All open lots will be selected. When later the routine starts applying payments the sign is checked. Note that in this context a payment is considered negative, compared to an invoice balance being positive. Since a credit note has the opposite sign of an invoice it's also considered negative in this context.
Lots for which the sign is "negative" (hence payments and credit notes) are skipped, although the first one found is retain to add overpayments to in the end.
+
Lots for which the sign is "negative" (so: payments and credit notes) are skipped, although the first one found is retain to add overpayments to in the end.
  
 
This can cause problems.
 
This can cause problems.
Line 123: Line 121:
 
Note that eventually the totals will add up again so the complete owner balance remains correct. It's just in the payment interface that things get confusing.
 
Note that eventually the totals will add up again so the complete owner balance remains correct. It's just in the payment interface that things get confusing.
  
New code can be easily made to deal with this. But when a data file is shared between new and old versions of GnuCash this can lead into the situation described above (a credit note is added in a new GnuCash version and then a prepayment and an invoice are added in an old version).
+
To prevent this situation from happening, an additional check can be added that prevents any lot having an invoice associated already to be reserved as a pre-payment lot. The net result would be that credit notes will completely be ignored for payments on an invoice.
 
 
To prevent this situation from happening, I think it's best to add an additional check in the old GnuCash version that prevents any lot having an invoice associated already to be reserved as a pre-payment lot. The net result would be that credit notes will completely be ignored for payments in the older version of GnuCash.
 
  
 
The code as is won't work for Credit Notes either. A lot is considered for a payment when its balance is "positive", but with the current evaluation of "positive" a credit note has a "negative" balance and is simply skipped. Additionally when a payment for a credit note is entered (assuming the GUI allows this), this code will add this payment to the first invoice found instead. But that's the wrong sign, so the invoice lot would be increased instead of decreased. To fix this, lots to be considered shouldn't be of a predefined "positive" or "negative", but rather of the opposite sign of the payment and have a document attached to it. And conversely to be eligible as a pre-payment lot (used at the end to save overpayments) a lot should be of the same sign as the payment and '''not''' have a document associated with it. This way payments are never accidentally assigned to lots that don't make sense.
 
The code as is won't work for Credit Notes either. A lot is considered for a payment when its balance is "positive", but with the current evaluation of "positive" a credit note has a "negative" balance and is simply skipped. Additionally when a payment for a credit note is entered (assuming the GUI allows this), this code will add this payment to the first invoice found instead. But that's the wrong sign, so the invoice lot would be increased instead of decreased. To fix this, lots to be considered shouldn't be of a predefined "positive" or "negative", but rather of the opposite sign of the payment and have a document attached to it. And conversely to be eligible as a pre-payment lot (used at the end to save overpayments) a lot should be of the same sign as the payment and '''not''' have a document associated with it. This way payments are never accidentally assigned to lots that don't make sense.
Line 133: Line 129:
 
Alternatively or additionally the payment code could already be improved to separate invoice and credit note lots at the beginning, first creating transactions that reduce open invoice and credit note lots to a minimum ("pay" open invoices with open credit notes or the other way around depending on which kind has the highest balance) and only then try to assign the payment to the still open lots. This may turn up its own set of problems though and should be carefully tested.
 
Alternatively or additionally the payment code could already be improved to separate invoice and credit note lots at the beginning, first creating transactions that reduce open invoice and credit note lots to a minimum ("pay" open invoices with open credit notes or the other way around depending on which kind has the highest balance) and only then try to assign the payment to the still open lots. This may turn up its own set of problems though and should be carefully tested.
  
:'''Old'''
+
:'''TODO'''
:*Add a check that prevents a lot to be marked as the pre-payment lot if this lot has a document associated with it.
+
:*Add a check that prevents a lot to be marked as the pre-payment lot if this lot has a document associated with it. '''''DONE'''''
 
+
:*Automatic payments should be made against lots of a different sign, not to lots of a precalculated specific sign. '''''DONE'''''
:'''New'''
 
:*Add a check that prevents a lot to be marked as the pre-payment lot if this lot has a document associated with it.
 
:*Automatic payments should be made against lots of a different sign, not to lots of a precalculated specific sign.
 
 
:*A more flexible gui to associate payments with invoices/credit notes may be needed.
 
:*A more flexible gui to associate payments with invoices/credit notes may be needed.
  
 
== GUI ==
 
== GUI ==
  
=== gnc_ui_invoice_edit (in dialog-invoice.c) ===
+
=== gnc_entry_ledger_model.c ===
  
This function is responsible for opening an invoice for viewing or editing. Since old GnuCash versions shouldn't suppport editing credit notes, a restriction should be built in here to prevent this. It is ok on the other hand to view the credit note. This signs will be reverted and the summary will show negative values, but that's not really a problem since a credit note is mathematically equivalent to a negative invoice.
+
This file represents the data model used by the invoice ledger. Since we want to keep the signs positive while editing entries, some of the functions in this file may have to be made sign aware. To reduce the amount of reports that have to be changed, it would make sense to store credit note values as negative in entries..
  
:'''Old'''
+
:'''TODO'''
:*Make sure credit notes can only be viewed, not edited.
+
:*Potentially deal with sign reversals. '''''DONE'''''
  
:'''New'''
+
=== General GUI changes to create/edit view credit notes ===
:*No changes required.
 
  
=== gnc_invoice_update_window (in dialog-invoice.c) ===
+
The gui code in the new GnuCash version has to be updated to allow the creation and modification of credit notes. There are two ways of doing this:
 
+
*Either separate menu options are added for credit notes in the Customer/Vendor/Employee menus. In this case the new invoice dialog can be reused mostly unchanged, with the exception of updating some labels ("Credit Note" instead of "Invoice").
This function is responsible to showing/hiding or enabling/disabling widgets based on the invoice state. Among these things it controls the widgets on the toolbar for posting and unposting. Since older GnuCash versions shouldn't be allowed to manipulate credit notes, these buttons should be disabled. Newer GnuCash versions are unaffected.
+
*Or the current Bill/Invoice interfaces are adapted to offer the choice between invoice/credit note in the new invoice dialog. This would require the addition of a type selection widget in the new invoice dialog. Additionally a more generic title for the menu items "New Bill"/"New Invoice" should be found.
 
 
:'''Old'''
 
:*Make sure credit notes can't be posted/unposted/paid.
 
 
 
:'''New'''
 
:*No changes required.
 
 
 
 
 
=== GUI changes to create/edit view credit notes ===
 
  
Other than the above gui changes to protect the data in older GnuCash versions, the gui code in the new GnuCash version has to be updated to allow the creation and modification of credit notes. There are two ways of doing this:
+
I'm in favoru of the second approach, mainly to avoid too many menu items. A suitable name for the menus could simply be "New Document..." and "Find Document". The subsequend dialogs will have the proper labels or buttons to clearly mark a document as an invoice or a credit note.
*Either separate menu options are added for credit notes in the Customer/Vendor/Employee menus. In this case the new invoice dialog can be reused mostly unchanged, with the exception of updating some lables ("Credit Note" instead of "Invoice").
 
*Or the current Bill/Invoice interfaces are adapted to offer the choice between invoice/credit note in the new invoice dialog. This would require the addition of a type selection widget in the new invoice dialog. Additionally a more generic title for the menu items "New Bill"/"New Invoice" should be found.
 
  
 
In both cases the new invoice dialog and associated callbacks can mostly be reused.
 
In both cases the new invoice dialog and associated callbacks can mostly be reused.
Line 186: Line 167:
 
Note that this is so for both old and new versions of GnuCash. However, since old versions aren't supposed to support credit notes, and the numbers aren't wrong per se (sums should still be correct, albeit with an inverted sign), I think no changes should be made to the pre-credit note version of GnuCash.
 
Note that this is so for both old and new versions of GnuCash. However, since old versions aren't supposed to support credit notes, and the numbers aren't wrong per se (sums should still be correct, albeit with an inverted sign), I think no changes should be made to the pre-credit note version of GnuCash.
  
:'''Old'''
+
:'''TODO'''
:*No changes are required.
 
 
 
:'''New'''
 
 
:*Allow for a proper document type printed on the document ("Credit note" instead of "Invoice").
 
:*Allow for a proper document type printed on the document ("Credit note" instead of "Invoice").
 
:*Calculate sign reversals based both on owner type and document type (invoice/credit note).
 
:*Calculate sign reversals based both on owner type and document type (invoice/credit note).
Line 199: Line 177:
 
If however a new transaction type is introduced for credit notes (say 'C'), this report will no longer show the credit note splits.
 
If however a new transaction type is introduced for credit notes (say 'C'), this report will no longer show the credit note splits.
  
:'''Old'''
+
:'''TODO'''
:*No changes required, unless a new transaction type is introduced for credit notes.
 
 
 
:'''New'''
 
 
:*No changes required, unless a new transaction type is introduced for credit notes.
 
:*No changes required, unless a new transaction type is introduced for credit notes.
  
Line 211: Line 186:
 
This report uses the positive=invoice, negative=payment assumption. It doesn't however list separate splits in detail. It only creates sums for splits that increase or decrease open invoices or overpayments. In that calculation it doesn't really matter whether a split was actually an invoice or a payment split. The sums still add up correctly with credit notes (negative invoice splits) and credit note payments (positive invoice splits). So this report is most likely not affected.
 
This report uses the positive=invoice, negative=payment assumption. It doesn't however list separate splits in detail. It only creates sums for splits that increase or decrease open invoices or overpayments. In that calculation it doesn't really matter whether a split was actually an invoice or a payment split. The sums still add up correctly with credit notes (negative invoice splits) and credit note payments (positive invoice splits). So this report is most likely not affected.
  
:'''Old'''
+
:'''TODO'''
:*No changes required.
 
 
 
:'''New'''
 
 
:*No changes required.
 
:*No changes required.

Latest revision as of 14:59, 15 October 2012

Introduction

Credit notes are a common document in business transactions mostly used to correct items/services that were incorrectly invoiced before.

Note upfront GnuCash makes a distinction between invoices and bills in the user interface. A bill is received from a vendor, while an invoice is sent to a customer. This distinction is only made to avoid user confusion. The document received from a vendor could just as well be called an invoice in accounting terms. For the remainder of this page I will only talk about invoices, but it can mean either bill or invoice in the GnuCash sense of the words.

From an accounting perspective a credit note is very similar to an invoice. The document has got all the same properties as an invoice, but the sign is reversed. When you send your customer an invoice, the customer owes you money. Yet when you send your customer a credit note, you owe your customer some money.

Since technically invoices and credit notes are that similar, it makes sense to treat both documents very similarly in GnuCash as well, at least in the processing. To avoid confusion the user interface could make a distinction between the two document types, but the user should be allowed more or less the same set of actions on either.

At present, GnuCash doesn't really support credit notes. The workaround suggested is to make a payment to the vendor for the amount of the credit note received. In this way at least GnuCash knows the vendor owes you this amount of money and will substract it automatically from the next invoice(s). This is not optimal in several ways:

  • There's no document tracking. GnuCash doesn't know anything about the credit note.
  • Income/Expense/Tax accounts aren't updated properly. Say the credit note was for a book you bought before, then the original invoice would increase the "Books" expense account, yet the expense account isn't decreased when the credit note is processed. So you end up with an incorrect balance. And it gets even more complicated if the credit note has multiple entries (with or without taxes).

What follows is an analysis of what is required to fully support credit notes in GnuCash. This includes an interface to enter credit notes and how to handle credit note payments or invoice/credit note interactions.

The sections below will analyse parts of the GnuCash code that may be impacted when implementing credit notes. Each section starts with a rough description of the code in question, how it could be impacted and what has to be done to deal with this.

At the end of each section I will add summaries of the changes required in the code (TODO).

Artificial limitation...

The core issue regarding credit notes is a design assumption from a long time back:

  • to track invoice payments, invoice splits and its related payment splits are grouped in lots. Some parts of GnuCash assume invoices to be in one sign (say positive) and payments in the opposite sign (say negative for this example). Note that for bills the signs are exactly opposite but that's irrelevant for this discussion.
  • From a business logic perspective, a credit note is a negative invoice. With the above assumption (invoice=positive, payment=negative) that would mean that some parts of the business logic would incorrectly interpret a credit note split as a payment and a credit note payment as an invoice.

To avoid this unwanted confusion "negative" invoices are prohibited.

New approach

Note A first attempt was made to implement Credit Notes in a way that was more or less backwards compatible. There were several drawbacks to this attempt and it would remain clumsy for future extensions. So after some discussion on IRC, I decided to forgo backwards compatibility and work on a cleaner design. The original attempt can still be found [here]. It may be useful to understand the origin of some design decisions.

Since invoices and credit notes are mostly the same thing except for their sense, the code for both objects is largely the same. But the GUI has to know which type it is handling to update various labels and internal sign of the values entered. To accommodate for this a new field will be added to the invoice object. This field will hold the invoice object "type", being invoice or credit note. Together with the owner type (Vendor/Customer/Employee) the code can reliably determine which labelling to use and the sign of the associated values.

Note that this design decision means that the data format is no longer compatible with older GnuCash versions.

The user must be able to enter Credit Notes just as he can enter invoices. The invoice dialog and register can mostly be reused. One particular detail to keep in mind: a normal document be it invoice, bill or customer/vendor credit note is always entered with positive values in the ledger, even if these values have opposite effects on the balance. The proper sign of these values is dealt with internally. For bills and invoices this is already so, but for customer/vendor credit notes, the logic for this still has to be extended.

Posting a credit note is exactly the same as posting an invoice. However the logic to post invoices will not work properly with credit notes, though this can probably easily be fixed. For more details, see below.

At some point the credit note has to be "paid". In real life this is usually done by substracting it from the amount still due on other invoices of the same business partner. This would mean that the payment logic should be extended to allow this. There are two parts to this:

  • The automatic payment assignment logic: this logic currently automatically assigns payments to open invoices, but doesn't know anything about credit notes yet and would definitely handle those wrongly. See later for more details on this.
  • The payment dialog: this is what the user uses to assign payments. It doesn't allow to link a credit note to an invoice though. This may be extended to show all open documents for a business partner and allowing the user to select multiple ones.

I'm not sure how difficult these improvements would be. In the first phase at least I intend to ignore this part. Instead invoices and credit notes will be totally unaware of one another. Instead you pay each one separately. This will mean one superfluous transaction, but the total balance is still correct.

If the code behind all the user actions above makes sure the sign of all splits introduces remains correct, then the generic accounting logic continues to work unaltered. The same goes for all reports that are only interested in transactions.

There are only a few improvements required for reports: - A user may want to print a credit note at some point (particularly a credit note to a customer). The reports used to print invoices are reusable, but will have to state "Credit Note" instead of "Invoice" and they will have to take care of using the proper sign of the values. - A business partner overview (vendor report/customer report) may want to distinguish between invoices and credit notes as well. It doesn't right now.

Analysis of affected parts

xml backend

Since I'm adding a new field invoice type field to the invoice object, the xml backend will need to know how to save or load this new field.

TODO
  • A new row will have to be added to the invoice_handlers_v2 table in gnc-invoice-xml-v2.c for the invoice type field
  • A handler for this field should be written.
UPDATE
To avoid unnecessary backward compatibility issues, the invoice type field is implemented as a kvp (is_credit_note). DONE

sql backend

Like with the xml backend, we need to know how to save or load the invoice type field.

TODO
  • A new row will have to be added to col_table in gnc-invoice-sql.c.

Engine

gncInvoiceGetTotalInteral and friends (in gncInvoice.c)

As explained above, internally some invoice types are considered negative internally, while they are presented positive to the user. The functions calculating the totals take this into account. There are several totals that can be calculated, but all use the gncInvoiceGetTotalInternal as a basis. And this function currently determines when to reverse the value. Since we are adding new invoice types, this reversal check must be adapted.

TODO
  • The reverse logic should be updated. Probably it should be refactored in an independent function to be used by later modules as well.

Update This is actually not the case. The gncInvoiceGetTotalInternal function uses the "reverse" parameter only to determine if the sum should use the entry's i_* values or the b_* values. The first one stores customer invoice amounts (and future customer credit note amounts), the latter stores vendor bill amounts (and future vendor credit note amounts).

To avoid confusion I will rename the "reverse" parameter to a more telling "is_cust_doc". This better reflects what the parameter is actually used for. DONE

gncInvoicePostToAccount (in gncInvoice.c)

When posting an invoice the code checks for an open lot for the invoice's owner that can be used to associate with this invoice. The check is twofold:

  • Is this lot a "payment" ? This actually checks if the lot has the opposite sign of the invoice. If not the evaluated lot is skipped.
  • Does the lot have an invoice associated with it ? If so, the lot is skipped as well. This prevents that the code accidentally attempts to associate two invoices with the same lot (which would seriously mess up things).

By the way this check is not in gncInvoicePostToAccount but in the helper function gnc_lot_match_owner_payment in the same file.

These checks together mean that posting a credit note will never accidentally try to post it to an open invoice lot.

The code as is however will fail to work for posting credit notes because of the simple sign evaluation. To enable posting for credit notes the gncInvoicePostToAccount the calculation of the "reverse" parameter will have to be extended.

TODO
  • The code to find lots eligible to post to should be revised. One way to do this is to set the "reverse" parameter not only on owner type but also on invoice vs credit note. DONE

gncOwnerApplyPayment (in gncOwner.c)

When applying a payment, this code will iterate over all open lots for a given owner. This can include a specific lot associated with a preselected invoice, but that's not relevant to this discussion.

When filtering the lots, there's no check on sign. All open lots will be selected. When later the routine starts applying payments the sign is checked. Note that in this context a payment is considered negative, compared to an invoice balance being positive. Since a credit note has the opposite sign of an invoice it's also considered negative in this context. Lots for which the sign is "negative" (so: payments and credit notes) are skipped, although the first one found is retain to add overpayments to in the end.

This can cause problems.

Use case
  • suppose we have an unpaid credit note and no unpaid invoices. For simplicity I'll also assume there are no other overpayments.
  • Now let's apply a payment for this owner.
  • When the routine iterates over the open lots, it will find the credit note lot, consider it a "negative" lot and take it for a valid pre-payment lot.
  • Since there are no open invoice lots, the payment is considered an overpayment which is to be added to a pre-payment lot.
  • The credit note lot was set apart as the pre-payment lot, so the overpayment will be added there.
  • We now still have only one lot, but holding the credit note and a payment, effectively increasing the lot.
  • Next step: Create and post a new invoice.
  • As described above when posting an invoice the lots which already have a document associated with them are skipped. So the credit note lot with the pre-payment is skipped and a new lot is created for the invoice.
  • The prepayment didn't get linked with the invoice. So when the time comes to pay the invoice, GnuCash will propose its full amount, instead of the invoice amount minus the credit note and the prepayment.
  • Also when selecting the credit note to pay (assuming the sign issues for this have been dealt with) GnuCash would now propose a payment of the credit note amount plus the prepayment.

Note that eventually the totals will add up again so the complete owner balance remains correct. It's just in the payment interface that things get confusing.

To prevent this situation from happening, an additional check can be added that prevents any lot having an invoice associated already to be reserved as a pre-payment lot. The net result would be that credit notes will completely be ignored for payments on an invoice.

The code as is won't work for Credit Notes either. A lot is considered for a payment when its balance is "positive", but with the current evaluation of "positive" a credit note has a "negative" balance and is simply skipped. Additionally when a payment for a credit note is entered (assuming the GUI allows this), this code will add this payment to the first invoice found instead. But that's the wrong sign, so the invoice lot would be increased instead of decreased. To fix this, lots to be considered shouldn't be of a predefined "positive" or "negative", but rather of the opposite sign of the payment and have a document attached to it. And conversely to be eligible as a pre-payment lot (used at the end to save overpayments) a lot should be of the same sign as the payment and not have a document associated with it. This way payments are never accidentally assigned to lots that don't make sense.

Note that combined with the restrictions in posting invoices/credit notes, a credit note is never automatically used to reduce the amount due for an invoice. This is slightly inconvenient and may call for a more flexible user interface to handle payments.

Alternatively or additionally the payment code could already be improved to separate invoice and credit note lots at the beginning, first creating transactions that reduce open invoice and credit note lots to a minimum ("pay" open invoices with open credit notes or the other way around depending on which kind has the highest balance) and only then try to assign the payment to the still open lots. This may turn up its own set of problems though and should be carefully tested.

TODO
  • Add a check that prevents a lot to be marked as the pre-payment lot if this lot has a document associated with it. DONE
  • Automatic payments should be made against lots of a different sign, not to lots of a precalculated specific sign. DONE
  • A more flexible gui to associate payments with invoices/credit notes may be needed.

GUI

gnc_entry_ledger_model.c

This file represents the data model used by the invoice ledger. Since we want to keep the signs positive while editing entries, some of the functions in this file may have to be made sign aware. To reduce the amount of reports that have to be changed, it would make sense to store credit note values as negative in entries..

TODO
  • Potentially deal with sign reversals. DONE

General GUI changes to create/edit view credit notes

The gui code in the new GnuCash version has to be updated to allow the creation and modification of credit notes. There are two ways of doing this:

  • Either separate menu options are added for credit notes in the Customer/Vendor/Employee menus. In this case the new invoice dialog can be reused mostly unchanged, with the exception of updating some labels ("Credit Note" instead of "Invoice").
  • Or the current Bill/Invoice interfaces are adapted to offer the choice between invoice/credit note in the new invoice dialog. This would require the addition of a type selection widget in the new invoice dialog. Additionally a more generic title for the menu items "New Bill"/"New Invoice" should be found.

I'm in favoru of the second approach, mainly to avoid too many menu items. A suitable name for the menus could simply be "New Document..." and "Find Document". The subsequend dialogs will have the proper labels or buttons to clearly mark a document as an invoice or a credit note.

In both cases the new invoice dialog and associated callbacks can mostly be reused.

For editing/viewing a credit note, the invoice edit window can mostly be reused, except the signs have to be reverted once more to have positive document balances in all normal cases. And some labels have to be set properly.

Note that the balance is not strictly required to be positive anymore with all the changes so far. It is perfectly possible to have a truly negative invoice, which is mathematically the same as a credit note, but is treated differently from an accounting point of view.

Reports

easy-invoice.scm/fancy-invoice.scm/invoice.scm

These are three reports to display one particular invoice. They are influenced in two aspects:

  • Each of them write the document type somewhere, currently being "Invoice", "Bill" or "Employee Voucher". Credit notes will need their own document type displayed, being "Credit note" and perhaps "Debit note". What names to use still has to be decided.
  • The invoiced amounts are always positive on the documents and the payment amounts negative. This is checked based on the owner type. However for credit notes this logic would result in inverted signs. So to get a proper credit note report the owner checks have to be extended with a invoice/credit note check to result in proper signs of all values.

Note that this is so for both old and new versions of GnuCash. However, since old versions aren't supposed to support credit notes, and the numbers aren't wrong per se (sums should still be correct, albeit with an inverted sign), I think no changes should be made to the pre-credit note version of GnuCash.

TODO
  • Allow for a proper document type printed on the document ("Credit note" instead of "Invoice").
  • Calculate sign reversals based both on owner type and document type (invoice/credit note).

owner-report.scm

This report will display a transaction history for an owner (invoices and payments). It distinguishes between invoice splits and payment splits based on the transaction type (currently can be 'I' for invoice and 'P' for payment). If credit notes are introduced in the business logic as a negative invoice, the invoice splits would still have the 'I' transaction type and payment splits would still have the 'P' transaction type. Hence this report is not affected. If however a new transaction type is introduced for credit notes (say 'C'), this report will no longer show the credit note splits.

TODO
  • No changes required, unless a new transaction type is introduced for credit notes.

aging.scm

Note: this is the base report for both the payables aging and the receivables aging reports.

This report uses the positive=invoice, negative=payment assumption. It doesn't however list separate splits in detail. It only creates sums for splits that increase or decrease open invoices or overpayments. In that calculation it doesn't really matter whether a split was actually an invoice or a payment split. The sums still add up correctly with credit notes (negative invoice splits) and credit note payments (positive invoice splits). So this report is most likely not affected.

TODO
  • No changes required.