예제 #1
0
        async Task BuildLineItem(IList <BillLineItem> container, BillRequest request,
                                 BillRequestLineItem item)
        {
            // No stage 2 payments
            if (request.Type == BillType.Stage2 &&
                (item.Scheme == Scheme.Endorsement ||
                 item.SubScheme == SubScheme.Canteen ||
                 item.SubScheme == SubScheme.ShortTerm))
            {
                return;
            }

            var codes = await GetCertFeeCodes(request.ReferenceDate, item.Scheme, item.SubScheme);

            var code = codes.Count() == 1
        ? codes.First()
        : codes.FirstOrDefault(e => ConditionEvaluator.Evaluate(item.Area, e.Conditions?.ToArray()));

            if (code == null)
            {
                return;
            }

            if (request.Type == BillType.Stage1)
            {
                await Stage1CertFee(container, code, item);
            }
            else if (request.Type == BillType.Stage2)
            {
                await Stage2CertFee(request.RequestType, container, code, item);
            }
        }
예제 #2
0
        async Task Stage1CertFee(IList <BillLineItem> container, TransactionCode code,
                                 BillRequestLineItem item)
        {
            var duration = item.SubScheme == SubScheme.ShortTerm
        ? (item.ExpiresOn - item.StartsFrom).Days + 1
        : BillingUtils.CalculateNoOfMonths(item.StartsFrom.Date, item.ExpiresOn.Date);

            var factor = await _context.Stage1Factor();

            // Full payment for stage 1
            if (item.Scheme == Scheme.Endorsement ||
                item.SubScheme == SubScheme.Canteen ||
                item.SubScheme == SubScheme.ShortTerm)
            {
                factor = 1M;
            }
            // Short term billed per 7 days
            else if (item.SubScheme == SubScheme.ShortTerm)
            {
                factor = Math.Ceiling(duration / 7M);
            }
            else
            {
                factor = Math.Min(factor, duration / 12M);
            }

            // For case where the pro-rated value is less than stage 1 expected factor.
            factor = Math.Min(duration / 12, factor);

            var unitPrice = code.GetLatestPriceAmount();
            var gst       = await _context.GST();

            var qty       = factor;
            var fee       = qty * unitPrice;
            var gstAmount = fee * gst;

            var section = BillingUtils.LineItemSection(BillType.Stage1);

            var    yearPrefix  = duration > 12 ? " - Year 1" : "";
            string prorateText = duration < 12 ? $" ({duration} of 12 months)" : "";

            container.Add(new BillLineItem
            {
                SectionIndex = section.Item1,
                Section      = section.Item2,
                Qty          = qty,
                CodeID       = code.ID,
                Code         = code.Code,
                Descr        = $"{code.Text}{yearPrefix}{prorateText}",
                UnitPrice    = code.GetLatestPriceAmount(),
                Amount       = decimal.Round(fee, 2),
                GSTAmount    = decimal.Round(gstAmount, 2),
                GST          = gst,
                WillRecord   = true
            });
        }
예제 #3
0
        async Task Stage2CertFee(BillRequestType requestType, IList <BillLineItem> container,
                                 TransactionCode code, BillRequestLineItem item)
        {
            var totalDuration = BillingUtils.CalculateNoOfMonths(item.StartsFrom.Date, item.ExpiresOn.Date);

            var stage1Factor = await _context.Stage1Factor();

            var prorate = Math.Round(totalDuration / 12M, 2);

            // No stage 2 payment for prorated application whose factor is less than stage 1 payment.
            if (prorate < stage1Factor &&
                requestType != BillRequestType.Renewal)
            {
                return;
            }

            var section = BillingUtils.LineItemSection(BillType.Stage2);

            decimal factor;

            int i        = 0;
            var duration = (decimal)totalDuration;

            do
            {
                prorate = Math.Min(Math.Round(duration / 12M, 2), 1M);

                // First year factor. Renewal will only have stage 2 payment.
                if (i == 0 &&
                    requestType != BillRequestType.Renewal)
                {
                    factor = Math.Max(Math.Min(
                                          1M - stage1Factor,
                                          prorate - stage1Factor), 0);
                }
                else
                {
                    factor = Math.Min(1M, prorate);
                }

                if (factor == 0M)
                {
                    break;
                }

                var unitPrice = code.GetLatestPriceAmount();
                var gst       = await _context.GST();

                var qty       = factor;
                var fee       = qty * unitPrice;
                var gstAmount = fee * gst;

                var yearPrefix  = totalDuration > 12 ? $" - Year {i + 1}" : "";
                var prorateText = duration < 12 ? $" ({(int)duration} of 12 months)" : "";

                container.Add(new BillLineItem
                {
                    SectionIndex = section.Item1,
                    Section      = section.Item2,
                    Qty          = qty,
                    CodeID       = code.ID,
                    Code         = code.Code,
                    Descr        = $"{code.Text}{yearPrefix}{prorateText}",
                    UnitPrice    = code.GetLatestPriceAmount(),
                    Amount       = decimal.Round(fee, 2),
                    GSTAmount    = decimal.Round(gstAmount, 2),
                    GST          = gst,
                    WillRecord   = true
                });

                duration -= 12;
                i++;
            } while (duration > 0);
        }