代码之家  ›  专栏  ›  技术社区  ›  user3127554

创建动态优惠券检查器

  •  4
  • user3127554  · 技术社区  · 7 年前

    我正在尝试创建一个优惠券计数器,用于检查可组合优惠券的可用性,该优惠券可用于获得发票的折扣。

    如果可用优惠券等于所需优惠券,则不需要发票。

    例子:

    XYZ公司需要为他们的发票支付100美元(金额总是可以除以25,剩余部分为0),但他们可以使用优惠券支付。

    一张优惠券值25美元,所以我需要检查公司是否在动态选择的月份内存了4张。

    我的优惠券桌看起来像:

    优惠券总数

    • 身份证件
    • 公司ID
    • 优惠券总数

    示例续:

    xyz公司3月份有0张优惠券,4月份有1张,5月份有0张,6月份有2张,7月份有1张。

    xyz公司可以在3个月前保存优惠券(所以优惠券可以在5月、6月、7月保存)

    此示例的结果需要是:

    已使用3张优惠券(6月2张,7月1张),客户仍需支付25美元。

    我的程序需要做的是:

    • 获取公司可以为其保存优惠券的月数(在本例中为3)

    • 减去优惠券直到0

    • 获取发票的其余部分并将其显示给用户

    这是我现在的代码:

            //While the needed amount of coupons for the invoice is smaller than the total available coupons 
            while(neededCoupons < cv.combinableAmount)
            {
                //We start at the earliest month we can go back to (this month - the combinable months)
                for (int i = int.Parse(DateTime.Now.AddMonths(DateTime.Now.Month - cv.monthsCombinable).ToString()); i >= int.Parse(DateTime.Now.Month.ToString()) ; i++ )
                {
                    int amountForMonth = GetCouponAmountByMonth(companyID, i);
                    if (amountForMonth >= neededCoupons)
                    {
                        //The amount is enough, we can stop
                        Result += "Coupons used from " + new DateTime(DateTime.Now.Year, i, 1).ToString("MMMM") + " amount: " + amountForMonth;
                        //To save the data, we subtract the neededCoupons from that month 
                        SubtractCoupons(companyID, i, amountForMonth);
                    }
                    else
                    {
                        //The amount for that month is not enough (or zero), we need to subtract it, get the remaining and continue to the following month) 
                        if (amountForMonth != 0)
                        {
                            SubtractCoupons(companyID, i, amountForMonth);
                            Result += "Coupons used from " + new DateTime(DateTime.Now.Year, i, 1).ToString("MMMM") + " amount: " + amountForMonth;
                            neededCoupons = neededCoupons - amountForMonth;
                        }
                    }
                }
    

    我没有测试我的代码,但我知道我没有走上正确的道路,因为我没有考虑到以下因素:

    • 剩余价值,如果所有的优惠券都用过了,而且还需要付钱
    • 我的代码明年一月能用吗?
    • 我的while循环,我应该继续循环直到我有足够的凭证(当然不是)

    我想我已经快到了。我只是想知道如何实现rest变量,以检查在旅程结束时,是否所有优惠券都已用完,而rest仍然需要支付。

    2 回复  |  直到 7 年前
        1
  •  3
  •   dana    7 年前

    为了帮助生成和打印发票,我创建了两个模型,如下所示:

    public class Invoice
    {
        public int TotalCouponsNeeded { get; set; }
        public int UsedCouponCount { get; set; }
        public List<UsedCouponsForMonth> UsedCoupons { get; set; }
    
        public override string ToString()
        {
            StringBuilder sb = new StringBuilder();
            if (UsedCouponCount == 0)
            {
                sb.Append("0 coupons have been used");
            }
            else
            {
                sb.AppendFormat("{0} have been used ({1})",
                        UsedCouponCount,
                        String.Join(", ", UsedCoupons.Select(x => String.Format("{0} in {1:MMM yyyy}", x.Count, new DateTime(x.Year, x.Month, 1))))
                    );
            }
            sb.AppendFormat(", {0} dollars still needs to be paid by client.", 25 * (TotalCouponsNeeded - UsedCouponCount));
            return sb.ToString();
        }       
    }
    
    public class UsedCouponsForMonth
    {
        public int Month { get; set; }
        public int Year { get; set; }
        public int Count { get; set; }
    }
    

    一个 Invoice 包含需要多少优惠券和使用了多少优惠券。它还知道如何以所需的格式打印自己。

    生成发票的算法如下:

    public Invoice GenerateInvoice(int companyId, int maxMonths, int couponsNeeded)
    {
        Invoice invoice = new Invoice
        {
            TotalCouponsNeeded = couponsNeeded,
            UsedCouponCount = 0,
            UsedCoupons = new List<UsedCouponsForMonth>(),
        };
    
        for (int i = 0; i < maxMonths && invoice.UsedCouponCount < invoice.TotalCouponsNeeded; i++)
        {
            DateTime month = DateTime.Now.AddMonths(i - maxMonths + 1);
            int availableForMonth = GetCouponAmountByMonth(companyId, month.Year, month.Month);
            if (availableForMonth <= 0)
            {
                continue;
            }
            int usedThisMonth = (invoice.UsedCouponCount + availableForMonth < invoice.TotalCouponsNeeded)
                ? availableForMonth
                : (couponsNeeded - invoice.UsedCouponCount);
            invoice.UsedCouponCount += usedThisMonth;
            SubtractCoupons(companyId, month.Year, month.Month, usedThisMonth);
        }
    
        return invoice;
    }
    

    想法是从最早的一个月开始,用 GetCouponAmountByMonth ,并根据需要使用 SubtractCoupons .注意,我修改了这些函数作为输入 year 以及 month 是的。同时,在 invoice.UsedCouponCount 变量。当使用的计数等于所需的数目时,循环自动中断。

        2
  •  2
  •   L0uis    7 年前

    我做了一些与问题相对应的类,然后一个经理可以得到有效的优惠券,最老的先,然后从未使用的有效优惠券中计算出发票金额。您可以更改优惠券有效期的月数,代码将根据需要作出反应。

    public class Company
        {
            public int ID { get; set; }
            public string Name { get; set; }
            public List<Coupon> Coupons { get; set; }
            public Company()
            {
                Coupons = new List<Coupon>();
            }
        }
        public class Coupon
        {
            public bool IsUsed { get; set; }
            public double Amount { get; set; }
            public DateTime Date { get; set; }
        }
    
    
    
    public static class CouponManager
        {
            public const int MONTHS_BACK = 3;
    
            /// <summary>
            /// Returns all coupons within X months not used by the company
            /// </summary>
            /// <param name="c"></param>
            /// <returns></returns>
            public static List<Coupon> GetValidCoupons(Company c)
            {
                return c.Coupons.Where(
                    t => !t.IsUsed &&
                (Math.Abs((DateTime.Now.Month - t.Date.Month) + 12 * (DateTime.Now.Year - t.Date.Year))<   MONTHS_BACK))
                .OrderBy(t=>t.Date).ToList();
            }
            /// <summary>
            /// Find valid coupons, subtract from invoice each coupon amount until invoice is 0
            /// </summary>
            /// <param name="company"></param>
            /// <param name="invoice"></param>
            /// <returns></returns>
            public static double CalculateInvoice(Company company, double invoice)
            {
                double amountOwed = invoice;
                List<Coupon> coupons = GetValidCoupons(company);
                coupons.ForEach(c => {
                    if(invoice <= 0) //we are done with coupons
                        { return; }
                    if (c.Amount > invoice) //no credits to give
                    { return; }
                    invoice = invoice - c.Amount; //subtract amount from invoice
                    c.IsUsed = true; //mark coupon as used then update in db later
                });
                return invoice;
            }
            public static Company GetMockedCompany()
            {
                //mock data
                Company myCompany = new Company();
                bool used = false;
                for (int i = 0; i < 215; i++)
                {
                    Coupon c = new Coupon();
                    c.Date = DateTime.Now.AddDays(-i);
                    c.Amount = 5.00;
                    c.IsUsed = used;
                    used = !used;
                    myCompany.Coupons.Add(c);
                    Coupon d = new Coupon();
                    d.Date = DateTime.Now.AddDays(-i * 4);
                    d.Amount = 5.00;
                    d.IsUsed = used;
                    used = !used;
                    myCompany.Coupons.Add(d);
                }
                return myCompany;
            }
        }
    

    然后,您可以与一家被嘲笑的公司测试该例程,如下所示:

     double invoice = CouponManager.CalculateInvoice(CouponManager.GetMockedCompany(), 1400); //returns 1070