в вашей ситуации у вас может быть такая таблица:
pass: (id, user_id, start_time, end_time, credit)
каждый день вы можете сбрасывать неиспользованный кредит на любой просроченный пропуск:
update user join
(select user_id, sum(credit) as credit from pass
group by user_id where end_time <= now() and not flushed) b
set user.credit = max(user.credit - b.credit, 0)
where user.user_id = b.user_id
update pass set flushed = 1 where end_time <= now() and not flushed
с помощью end_time <= now () вы гарантируете, что кредит сбрасывается только после истечения срока годности. так как вы помните, какие проходы были сброшены, вы можете запускать их так часто, как вам нравится, и пропуск дня не является проблемой (это будет обнаружено при следующем запуске). </p>
эффективно работает предоплаченная телефонная карта - у вас есть определенное количество минут, которые действительны для X (30/60/90 независимо) дней, и минуты сбрасываются в конце.
Кстати, вы можете упростить все это, используя простую в использовании систему управления подписками, такую как recurly или chargify .