Apply Coupon Validation in Order I have created a mvc application for booking space. In this for booking user can applied coupon for booking.

I have implemented one coupon service and validate coupon.

public class Coupon 
{
    public int ID { get; set; }
    public string Name { get; set; }
    public string Description { get; set; }
    public Enum.Enum_DiscountType DiscountType { get; set; }
    public Enum_DiscountTypeAppliedOn DiscountTypeAppliedOn { get; set; }
    public decimal DiscountValue { get; set; }
    public decimal? MaximumDiscountAmount { get; set; }
    public string CouponCode { get; set; }        
    public DateTimeOffset StartDate { get; set; }
    public DateTimeOffset EndDate { get; set; }
    public Enum_CouponLimitationType CouponLimitationType { get; set; }
    public int? LimitationTimes { get; set; }
    public bool Status { get; set; }
    public Enum_CouponStatus CouponStatus
    {
        get
        {
            return Status ? Enum_CouponStatus.Active: Enum_CouponStatus.InActive;
        }
    }
    public Enum_CouponAssignedTo CouponAssignedTo { get; set; }
    public string Postcodes { get; set; }
    public bool UseMaximumDiscountAmount { get; set; }
    public virtual ICollection&lt;CouponUsageHistory&gt; CouponUsageHistory { get; set; }
    public virtual ICollection&lt;Order&gt; Orders { get; set; }
}


My coupon service contains below class for validation

 public async Task&lt;bool&gt; IsAppliedCouponValid(Coupon coupon, string userID, Order order, int? categoryID)
    {
        if (coupon == null)
            return false;

        if (coupon.Status == false)
            return false;


        //check date range
        var now = DateTime.UtcNow;
        var startDate = coupon.StartDate;
        if (startDate.CompareTo(now) &gt; 0)
            return false;

        var endDate = coupon.EndDate;
        if (endDate.CompareTo(now) &lt; 0)
            return false;

        //check coupon applied limitations
        var isValid = await CheckCouponLimitations(coupon, userID);
        if (!isValid)
            return false;


        return true;
    }


CheckCouponLimitations method contains

 private async Task&lt;bool&gt; CheckCouponLimitations(Coupon coupon, string userID)
    {
        if (coupon == null)
            throw new ArgumentNullException("coupon");

        switch (coupon.CouponLimitationType)
        {
            case Model.Enum.Enum_CouponLimitationType.Unlimited:
                {
                    return true;
                }
            case Model.Enum.Enum_CouponLimitationType.NTimesOnly:
                {
                    var totalUsage = await GetAllCouponUsageHistory(coupon.ID);
                    return totalUsage.Count &lt; coupon.LimitationTimes.Value;
                }
            case Model.Enum.Enum_CouponLimitationType.NTimesPerCustomer:
                {
                    //registered customer
                    var totalUsage = await GetAllCouponUsageHistory(coupon.ID, userID);
                    return totalUsage.Count &lt; coupon.LimitationTimes.Value;
                }
            default:
                break;
        }
        return false;

    }


I have implemented like above and also calculate order after applied coupon also generate new coupon dynamically.

Please suggest me to best way to design this code and give some feedback for review code.
IsAppliedCouponValid()


Don't omit braces although they might be optional. Omitting braces can lead to hidden and therfor hard to find bugs.  
The intermediate variables startDate and endDate won't buy you much. Instead I would just use the coupon.StartDate and coupon.EndDate. Don't get me wrong, using intermediate variables can be a good thing but not for such simple stuff.  
A construct like  

if (!bool)  
{
    return false;
}
return true;  


can be rewritten as return bool;  
You "validate"  the passed Coupon coupon but you don't validate string userID. The method parameters Order order, int? categoryID aren't used and should be removed.  
Sometimes you use if (bool == false) and sometimes you use if (!bool) where I prefer the first because it is easier to see that we check if the value is false. Whatever style you choose, you should stick to it. 
The check for the coupon regarding null and coupon.Status could be added in a condition using ||.  
Comments like //check date range or //check coupon applied limitations are superflous and unneeded comments because they tell the reader of the code what is done by the code. Telling what the code is doing should be done by the code itself by having meaningful names. The why something is done in the way it is done is where we need and want comments.


Applying these points will lead to  

public async Task&lt;bool&gt; IsAppliedCouponValid(Coupon coupon, string userID)
{
    if (userID==null) { throw new ArgumentNullException(nameof(userID)); }

    if (coupon == null || coupon.Status == false)
    {
        return false;
    }

    var now = DateTime.UtcNow;

    if (coupon.StartDate.CompareTo(now) &gt; 0)
    {
        return false;
    }

    if (coupon.EndDate.CompareTo(now) &lt; 0)
    {
        return false;
    }

    return await CheckCouponLimitations(coupon, userID);
}