0

I have a scenario where I need to generate 4 digit confirmation codes for individual orders. I don't want to just do random codes due to the off chance that two exact codes would be generated near the same time. Is there a way to use the id of each order and generate a 4 digit code from that? I know I am going to eventually have repetitive codes with this but it will be ok because they will not be generated around the same time.

TTDaVeTT
  • 127
  • 1
  • 9
  • Can you tell anything about the ids? (e.g. 0 <= id <= 9999 or 0 <= id <= 999999999999999999999999999999999999) – compman Jul 26 '11 at 00:03

2 Answers2

2

Do you really need to base the code on the ID? Four digits only gives you ten thousand possible values so you could generate them all with a script and toss them in a database table. Then just pull a random one out of the database when you need it and put it back in when you're done with it.

Your code table would look like this:

  • code: The code
  • uuid: A UUID, a NULL value here indicates that this code is free.

Then, to grab a code, first generate a UUID, uuid, and do this:

update code_table
set uuid = ?
where code = (
    select code
    from code_table
    where uuid is null
    order by random()
    limit 1
)
-- Depending on how your database handles transactions
-- you might want to add "and uuid is null" to the outer
-- WHERE clause and loop until it works

(where ? would be your uuid) to reserve the code in a safe manner and then this:

select code
from code_table
where uuid = ?

(where ? is again your uuid) to pull the code out of the database.

Later on, someone will use the code for something and then you just:

update code_table
set uuid = null
where code = ?

(where code is the code) to release the code back into the pool.

You only have ten thousand possible codes, that's pretty small for a database even if you are using order by random().

A nice advantage of this approach is that you can easily see how many codes are free; this lets you automatically check the code pool every day/week/month/... and complain if the number of free codes fall below, say, 20% of the entire code space.

You have to track the in-use codes anyway if you want to avoid duplicates so why not manage it all in one place?

mu is too short
  • 426,620
  • 70
  • 833
  • 800
0

If your order id has more than 4 digits, it is theoreticly impossible without checking the generated value in a array of already generated values, you can do something like this:

require 'mutex'
$confirmation_code_mutex = Mutex.new
$confirmation_codes_in_use = []

def generate_confirmation_code
  $confirmation_code_mutex.synchronize do
    nil while $confirmation_codes_in_use.include?(code = rand(8999) + 1000)
    $confirmation_codes_in_use << code
    return code
  end
end

Remember to clean up $confirmation_codes_in_use after using the code.

Guilherme Bernal
  • 8,183
  • 25
  • 43