I am working on an application that needs to handle expiring airline miles. The miles can be used, but if they are not used by a certain date, they will expire. I want to make sure I expire the proper amount of miles but don't expire them if they have been used. Therefore, I have to check if enough miles have been used in a given date range before they expire. Here are my initial thoughts:
Have a miles table with the following columns:
- user_id - Foreign key to the use开发者_运维知识库rs table
- number_miles - The number of miles for this record
- miles_type - Indicates if miles were added, used, or expired
- miles_expire - Boolean value to indicate if these miles expire or not
- miles_date - The date this record was added
- exipration_date - The date these miles expire (if the
miles_expire
flag is true) - processed - Indicates if this record has been processed - only applicable when the
miles_type
is set to expire
If I have a record every time miles are added, used, or expired from a particular user account, I figure I can calculate the expired miles as such:
- For each user, get the dates of the records where the
miles_expire
flag set to true, theexpiration_date
is before the current date, and theprocessed
flag is set to false. This will get the records for all miles that should be expired. - Get the first and last
expiration_date
from the previous query. - Using the first and last
expiration_date
values from the previous step, get a list of all used miles within that date range. - If the sum of the used miles from the previous step is less than the sum of the expiring points, expire the difference. If the used miles are equal or greater, nothing has to be expired.
- Set the
processed
flag to true for all records within the first and lastexpiration_date
range. Either these miles have been expired or ignored as they have been used.
It appears this meets the following requirements:
- Expiring miles are used first
- It will only check the used miles for the same time frame as the used miles so using many miles in the past won't save future miles from expiring
- Miles are only expired after the date and won't be if the user has used enough miles
Are there other considerations I need to take into account? Will this work to properly expire miles?
Your method won't work for several reasons. The easiest to explain is probably this:
For each user, get the dates of the records where the miles_expire flag set to true, the expiration_date is before the current date, and the processed flag is set to false. This will get the records for all miles that should be expired.
Note that this could be only one record. If you run your check very often, it will typically be only one record in fact. Let's assume for simplicity that max one record expires each day (if more than one expires, your algorithm still fails, it's just harder to explain).
Get the first and last expiration_date from the previous query.
You'll get the same date here, because there's only one record.
Using the first and last expiration_date values from the previous step, get a list of all used miles within that date range.
Since first and last are equal, there is no range and so there will never be used miles in that range.
If the sum of the used miles from the previous step is less than the sum of the expiring points, expire the difference. If the used miles are equal or greater, nothing has to be expired.
Since the previous step returned no rows, the sum is zero, so you will always expire the difference between 'expired miles' and '0'. Even if the miles have been used.
This process will repeat.
Overall your design seems unnecessarily compilcated. I would just store a list of unused vouchers for each user. When they pay, vouchers used are marked as used. If a voucher is half used, it is marked as used and a new voucher is issued with the same expiration date, but with a smaller amount. If there are more vouchers than needed, soon to expire vouchers are used up first, and non-expiring vouchers are used last. Vouchers that have expired can never be used for payment, so you don't need to do anything to expire them.
So in summary: you don't need to expire any vouchers, just make sure the payment code does not allow usage of expired or used vouchers.
I don't think you need to worry about which miles are used first like in an inventory application; they're either expired or not (based on expiration date). The key is: how many miles remain? Expired miles, just like used miles, would be like a debit to an account (Only you don't need a separate transaction to indicate expiration, you only exclude them from the formula used to calculate the current balance.).
精彩评论