views:

310

answers:

4

Some background: In Germany (at least) invoice numbers have to follow certain rules:

  1. The have to be ordered
  2. They have to be continuous (may not have gaps)

Since a few months they are allowed to contain characters. Some customers want to use that possibility and customers don't know that or are afraid and they insist on digit-only invoice numbers.

Additionally the customers don't want to start them at zero.

Is I can think of many ways to generate such a number I wonder: What's the best way to do this?

+1  A: 

My two ideas:

  1. (without chars): a sequence, starting at 1, left-padded with zeroes (or beginning with another number and padded with zeroes) - example: 1000002554
  2. (with chars): a sequence in hexadecimal base, padded with zeroes (eventually with a prefix) - example: AF00CAFE01

It would be cool to have invoice numbers in hex :)

friol
Yeah until your catering company sends you invoice #BADF00D.
Matt Hamilton
LOL, nice one :)
friol
He-he... wish I could upvote Matt's comment :-)
Sandman
@Matt, or the canonical 0xDEADBEEF.
paxdiablo
Or, more worryingly from a caterer: DADDEAD
Will Dean
+5  A: 

In order to avoid starting at 0 - just start at 10000. Forget about the zero-padding.

You have to consider when the number is going to be allocated.

If you allocate the number when the invoice is first opened for edit, for instance the number 10014 is allocated, and the user cancels the invoice then you have a gap, since you have to keep in mind that someone else could already have begun to create an invoice with the id 10015, so you can't just rollback the number.

If you allocate the number when the invoice has been completely written and is being saved then you'll avoid the scenario, and you'll avoid having gaps, but you will not know which invoice number the invoice is going to have before it is saved.

Also, you need to make sure that it is threadsafe, so that two users can't create the same invoice number.

static object _invoiceNumberLock = new object();
public static string GetInvoiceNumber()
{
    lock(_invoiceNumberLock)
    {
        //Connect to database and get MAX(invoicenumber)+1
        //Increase the invoicenumber in SQL database by one
        //Perhaps also add characters
    }
}

Also consider backing up the uniqueness by having a UNIQUE INDEX on the invoicenumber column in the SQL database.

Frode Lillerud
Allocating the number at commit is not trivial, in general, even though it is necessary. You have to worry about doing the INSERT (of the invoice) with a newly allocated sequence number and an immediate COMMIT - or use auto-commit, perhaps.
Jonathan Leffler
A: 

For my invoices, they always consist of the last digit of the year followed by a 4-digit invoice number starting at 4096, so you would get a value like 85021. This was to easily handle billing my (up to) 15 clients twice a month.

It's irrelevant now since I raise only about 6 invoices a year (I went permanent and now only do small bits of work, mostly leaving the company for investment purposes) but this scheme always worked for me.

It stopped the clients from feeling that they were getting work done by a small company (no invoice number 1 or even 80001).

In terms of the sequential nature, the invoices were simply stored in files with the invoice number in the file name, so it was easy to create the next one. No database was required - it really depends on how big your shop is.

paxdiablo
A: 

Some more ideas:

Pick an arbitrary sequence of bits to be the top of the number. This will work as a "magic key" so you can recognize that number out of context. For example, Newegg product IDs seem to start with "N82E" and UPS tracking numbers seem to start with "1Z".

If you can bend the "contiguous" rule, make the last bit be a parity bit, for error checking.

Jay Bazuzi