Take the 2-minute tour ×
Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free, no registration required.

I am developing a web application, this application will need to generate receipt number for every confirmed transaction.

What is a good receipt number? I think a receipt number should not be just a running number generated by database, but it should have some meaning beyond just a unique running number.

Here is what I have come up with so far,

Format: EYY-ddd-XXXXXXX
Example output: E13-146-0000001

Where:

E : It is just a to signify this receipt number was generated by my system. This value is always E.

YY : Is the current year the receipt was generated, so in this case it is 13

ddd : Is the day of the year, 146 is May 26 (in 2013).

XXXXXXX : Is a 7 digit running number, up to 9,999,999

So my system can generate up to 10 million unique receipt numbers daily until 2099.

What do you think? Is this sensible? Any suggestion is appreciated.

Update

Judging from the comments so far, it looks like there is no specific 'pattern' or 'best practices' for receipt number. My intention in asking the question is to know whether there is specific best practises in generating the number that I should know about. Looks like I am free to use whatever pattern I feel sensible.

Other requirements

  • As short as possible (that is why I didnt go for YYYYMMdd-XXXXXXX)
  • Somewhat not to obvious (YYYMMdd is way to obvious).
  • Should be fixed length. (Easier to detect if customer entered invalid receipt number)
  • Can generate fairly large numbers (10 million a day seems sensible, though I doubt my system will be that popular)
  • Can be made into QR code (so staff can scan and verify the number is valid)
  • Someone mentions about error detection code like ISBN, seems good but I havent read it yet.
share|improve this question

closed as not constructive by mattnz, MichaelT, Justin Cave, gnat, Dynamic May 26 '13 at 19:01

As it currently stands, this question is not a good fit for our Q&A format. We expect answers to be supported by facts, references, or expertise, but this question will likely solicit debate, arguments, polling, or extended discussion. If you feel that this question can be improved and possibly reopened, visit the help center for guidance.If this question can be reworded to fit the rules in the help center, please edit the question.

    
Could you please add the following information: does the number need to be human readable? Is there only one server generating the numbers, or could it happen that you need to scale out to multiple servers? Do you have any legal requirements on the number, e.g. does the number need to be sequential or even gapless? –  Andreas Huppert May 25 '13 at 18:14
    
why not include four digit numbers for the year? or else a sequential year of operation? Why specify a number of digits for the sequence number? why use base 10 instead of a hexadecimal or alphanumeric? (or a pseudo-alphanumeric, skipping L and o.) heck, why not just date/time and a sequential number? –  DougM May 25 '13 at 19:17
2  
Does it matter if someone can guess a receipt number? –  Peter K. May 25 '13 at 21:11
1  
You could add error detection and error correction digits as explained here: plus.maths.org/content/error-detection-and-correction –  Axel Kemper May 25 '13 at 21:31
1  
Vote to close: Whats it for, what are the requirements. Any answer can only be based on opinion –  mattnz May 26 '13 at 1:17

4 Answers 4

Unless encoding the extra information serves some useful purpose you didn't describe in your question, don't attempt to build any kind of intelligence into your numbers. It will eventually backfire, often in a way that will make recovery difficult and expensive.

My advice? Use an integer sequence number and be done with it. They're easy to deal with, and if you're using them as identifiers in a database, they store compactly and index much more quickly than strings.

As short as possible

If you're actually doing only 10,000 transactions per day, you're going to have three unnecessary zeros in every receipt number pretty much forever. That makes your numbers 30% larger than they need to be. More digits increases the odds there will be a communication or keying error. Someone unfamiliar with your scheme won't know that there should be seven digits in your sequence number and will have to count out a string of leading zeros for the low-numbered receipts -- you'll have a bunch of those daily -- and that will consume more time than having them will save.

An integer sequence number won't get any longer until it runs out of digits in its current size and can grow practically infinitely. Days when you do low volume will delay the addition of digits.

Somewhat not to obvious (YYYMMdd is way to obvious).

Don't think for a minute that someone wanting to do something nefarious with your receipt numbers isn't going to look up at his calendar and notice that you're using the year and Julian day. If the receipt number is your sole method of verifying that someone giving it to you is the customer who received it, you're going to get hacked hard. Amateurs hack systems, professionals hack people.

Should be fixed length. (Easier to detect if customer entered invalid receipt number)

It's not really any easier; if the number isn't in your database, it's not valid. There's plenty of potential for someone to enter an invalid number that's the right length.

Can generate fairly large numbers (10 million a day seems sensible, though I doubt my system will be that popular)

A 64-bit unsigned integer can hold a maximum value of 9,223,372,036,854,775,807. That will give you a billion unique numbers daily for the next 2.5 million years, longer if you're not doing that kind of volume.

Can be made into QR code (so staff can scan and verify the number is valid)

Using digits only assures that you'll be able to use any barcode format out there. Linear barcodes scan a lot faster than QR and are readable under much worse conditions. That should be taken into account if there's a warehouse involved.

share|improve this answer
1  
I learned (the hard way) a long time ago when doing mechanical design and assigning part numbers that "intelligent" numbering systems always have an Achilles heel. Someday, someone will want to distinguish receipts by country, or by payment method, or by.... These all become impossible to accommodate with intelligent numbers, whereas with a simple integer look-up all of that information is contained in a separate data store. –  DaveNay May 26 '13 at 15:25
1  
It isn't uncommon to have a trans number that rolls over and a date. This way accounts for scale up to large transactions per day without leaving zeros stuck in it. –  MichaelT May 26 '13 at 15:46
    
My system is a venue reservation system, sometimes computer / internet isn't available to lookup the details. so I want the clerk to be able to know whether the receipt is valid for that particular venue and date. But you made very valid points.., I think a receipt number isn't meant for that. Maybe I will have to generate other number to convey those info. –  Random Alphabets May 27 '13 at 6:27

Without more information it appears reasonable, if not overly complex. No one here can say for sure it will meet your needs, as you have not said what they are.

Whats wrong with a sequential number starting at 0? - You state "you think its not good enough", what requirement does that not meet?.

What happens after 2099 - whats the requirement, what happens after 9,999,999 transactions in a day - whats the requirement, 'E' - what requirement does that meet?

share|improve this answer
    
I just want the number to have some meaning instead of just a running number. By looking at the number E13-146... we know the receipt was generated on May 26, 2013. But if I use E-YYYYMMDD.. pattern then it would be too obvious and too long. –  Random Alphabets May 26 '13 at 2:02
    
After 99 I can switch to alphanumeric until ZZ. Or I can choose to ignore it since I will no longer around at that time. :-D –  Random Alphabets May 26 '13 at 2:27
    
@RosdiKasim 'too obvious' - unless you are actively trying to obscure the information, YYDDD isn't significantly less obvious than YYYYMMDD (especially so for purchases in January or December). –  MichaelT May 26 '13 at 4:58
1  
"some meaning instead of just a running number" .. WHY -what is the requirement? –  mattnz May 27 '13 at 2:29
    
@mattnz My system is a venue booking/reservation system. I want the support staff to be able to tell the booking receipt is valid for that venue and date by just looking at the receipt number whenever computer and internet isn't available to lookup the details. But then again after some pondering and feedback from you guys I think a receipt number isn't meant for that. –  Random Alphabets May 27 '13 at 6:20

I would add a checksum digit. Makes it easier to tell if someone types it out and makes a mistake.

share|improve this answer
    
Yes I like the idea, right now studying this is implemented by ISBN. en.wikipedia.org/wiki/International_Standard_Book_Number. Or do you have any simpler way of doing this? –  Random Alphabets May 26 '13 at 2:28
    
@RosdiKasim consider also the Luhn algorithm - you likely already have it somewhere (its the check digit on a credit card). –  MichaelT May 26 '13 at 4:55
    
WHY -what is the requirement? –  mattnz May 27 '13 at 2:29

Will many systems be generating these numbers at once? If so, then neither your system nor sequential numbers will be sufficient; there will be days when the internet isn't working, or a bug somewhere results in collisions, and so on. If these things are true, I'd use a GUID (which is "unique enough"). If GUIDs aren't an option, I'd switch to hex and use a semantic numeric string like this:

EDDDDLLLLNNNNNNNNC

Where E is your generic "I did this" flag, D is a hex string representing the year and date in hex, L is a hex string representing the source location (allowing 65,000 separate POS systems or other sources to use your system without collision), N is a simple sequence number for that source, and C is a check digit.

An example:

E3FDF00A2000000D2C

3FDF represents 16351, or June 12, 2051. 00A2 represents your POS system. The 000000D2 represents that day's sequence number, and C is a check digit (calculated simply as (3FDF + A2 + D2) % F, which may not be algorithmically perfect).

If you are willing to relax the requirement that it be the same length every time, you can easily make it elastic, so that the above is rendered as:

E3FDF00A2D2C

The first 9 digits are always the same, and the last digit is the check digit, so the remainder is the sequence number. If you are open to having a divider character, you could make it even shorter:

E3FDFA2-D2C
share|improve this answer
    
WHY -what is the requirement? – –  mattnz May 27 '13 at 2:31
1  
If numbers are expected to represent a single event--as in a single transaction--they must be unique. In a concurrent environment, a sequence cannot be guaranteed to be unique. You can either use randomness to guarantee uniqueness (a GUID, in other words), or you can use semantics to guarantee uniqueness. In this case, the latter allows the number to be shorter and carry information with it. –  syrion May 27 '13 at 3:19
    
I like this, I think I will be incorporating a lot of this ideas. –  Random Alphabets May 27 '13 at 6:32

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