Я бы реализовывал это так.
В таблице промокодов хранятся:
- тип промокода;
- его хэш;
- кол-во использований;
- флаг доступности;
1. Пользователь вводит полученный промокод.
2. Проходит проверка заполненности поля промокод.
3. Если не заполнено, то отрабатывает уже существующее решение, если нет плывем дальше.
4. Этот промокод сравнивается с хэшем, при совпадении смотрим на флаг доступности, и если доступен получаем данные этого промокода.
5. Из полученных данных из формы и базы формируем мэйл для пользователя и отсылаем мэйл в котором пишем что он получил используя свой промокод в дополнение к тому что и так отсылается.
6. Проводим модификацию поля кол-во использований (либо +1 либо -1, если храним в поле максимальное кол-во использований).
7. Когда кол-во использований достигает опр. значения меняем флаг доступности промокода.
Я бы ставил максимальное кол-во использований и уменьшал. Тогда будет ненужен флаг. Просто проверять на совпадение с хэшем и чтобы кол-во использований было >0.
Как-то так.