Best way to generate order numbers for an online store?
As a customer I would be happy with:
year-month-day/short_uid
for example:
2009-07-27/KT1E
It gives room for about 33^4 ~ 1mln orders a day.
What is the best format for a customer number, order number?
Go with all numbers or all letters. If you must mix it up, then make sure there are no ambiguous characters (Il1m, O0, etc.).
When displayed/printed, put spaces in every 3-4 characters but make sure your systems can handle inputs without the spaces.
Edit:
Another thing to consider is having a built in way to distinguish orders, customers, etc. e.g. customers always start with 10, orders always start with 20, vendors always start with 30, etc.
How to generate Unique Order Id (just to show touser) with actual Order Id?
If your requirements are:
- It must be reversible (i.e. given just the "random" ID, you can find the original order_id)
- No extra columns
- You don't want to show the original/internal order_id to the user at all
then I would recommend some kind of two-way encryption. Hashing won't work as you can't find the original value from a hash.
I'm also adding that it should be human-friendly e.g. someone can call it out over the phone to you
I'm going to use a very simple two way encryption class located here, which was written by Tony Marston.
We want the solution to be human-friendly so let's remove some of the scramble chars. I've left only uppercase characters, numbers and the space and dash symbols. All of these can be easily communicated using the standard phonetic alphabet, and the forced use of uppercase removes any confusion as to what a character is.
These are the scramble strings I used (I used this online word scrambler rather than trying to scramble the string myself):
$this->scramble1 = '0123456789-ABCDEFGHIJKLMNOPQRSTUVWXYZ ';
$this->scramble2 = 'UKAH652LMOQ FBDIEG03JT17N4C89XPV-WRSYZ';
So the code to create our human-friendly order id is:
<?php
include 'encryption_class.php';
$crypt = new encryption_class();
$key = "A-COMPLETELY-RANDOM-KEY-THAT-I-HAVE-USED";
// Min length of 8 for encrypted string
$min_length = 8;
$order_id = 123456789;
print "Original: " . $order_id . PHP_EOL;
$encrypt_result = $crypt->encrypt($key, $order_id, $min_length);
print "Encrypted: " . $encrypt_result . PHP_EOL;
// DECRYPT
$decrypt_result = $crypt->decrypt($key, $encrypt_result);
print "Decrypted: " . $decrypt_result . PHP_EOL;
?>
(You need to download and save the *encryption_class* file locally, and include it).
I ran that code from the command line and received the following output:
Original: 123456789
Encrypted: 2UD5UIK9S
Decrypted: 123456789
Now we have our short, human-friendly order_id, which can be used in a URL such as http://myapp.example.com/order/view/2UD5UIK9S, and you never need to display or communicate the internal order_id to your users.
Notes:
The encrypted code will be unique once your order_id is unique (since it's a PK it will be)
This should not be used as a password encryption/decryption routine - don't store passwords, store hashes.
Make sure your secret key is random, complex and contains only the characters in your $scramble variables.
It obfuscates the order_id only.
Edit:
Although padding the input string (order_id) generates a certain amount of ramdomness, you could combine this with @biakaveron's answer to create a URL like http://myapp.example.com/order/view/5cc46aea44e898c3b4e1303eb18d8161302cd367/2UD5UIK9S
e-shop implementation: Status for Orders?
If you can calculate it, you should calculate it. Otherwise you have redundant data and run the risk of having inconsitencies.
That's not to say you can't add a status column for performance reasons or to make querying easier, but start without it and make sure your authoritative data stays that way. Personally I prefer to stick with the calculate-on-query approach unless I can prove the performance isn't good enough.
smart way to generate unique random number
You could build a table with all the possible numbers in it, give the record a 'used' field.
- Select all records that have not been 'used'
- Pick a random number (r) between 1 and record count
- Take record number r
- Get your 'random value' from the record
- Set the 'used' flag and update the db.
That should be more efficient than picking random numbers, querying the database and repeat until not found as that's just begging for an eternity for the last few values.
How to store complex product/order data in MySQL?
At the very least you need:
Products (one row per product)
ProductID
Size
Orders (one row per order)
OrderID
OrderDetails (one row per product per order)
ProductID
OrderID
Size
Note that each 'size' is its own ProductID. You'll probably want to have yet another ID that groups products that are the same 'base' product, but in different sizes.
So if Order #1 has three products, and Order #2 has four, then OrderDetails
will have seven rows:
OrderID ProductID Quantity
1 234 2
1 345 9
1 456 30
2 432 1
2 234 65
2 654 8
2 987 4
Related Topics
Respond_To' VS. 'Respond_To_Missing'
Renaming Uploaded Files with Carrierwave
Sorting: Sort Array Based on Multiple Conditions in Ruby
Ruby on Rails: Provide VS Content_For
Why Are Constants from Extended Module Not Available in Class Methods Declared with Self
Can Not Install JSON Gem with Ruby 2.2.3 on Ubuntu
Gem Install Nokogiri -V '1.6.8.1' Fails
How to Check from Ruby Whether a Process with a Certain Pid Is Running
How to Load a Spec_Helper.Rb Automatically in Rspec 2
How to Access a Ruby Module Method
How to Introspect Things in Ruby
Object.Valid? Returns False But Object.Errors.Full_Messages Is Empty
How to Validate the Date Such That It Is After Today in Rails