Ejemplo n.º 1
0
        protected static DateRange GetInvoiceItemDateRange(IPackageItem packageItem, IList <InvoiceDomain> packageInvoices, DateTimeOffset invoiceEndDate)
        {
            var startDate = GetActualStartDate(packageItem, packageInvoices);
            var endDate   = Dates.Min(packageItem.EndDate, invoiceEndDate);

            return(new DateRange(startDate, endDate));
        }
Ejemplo n.º 2
0
        /// <summary>
        /// This function parse frame from data
        /// </summary>
        /// <param name="data">Data to parse</param>
        /// <param name="action">Function to get frame item type</param>
        private void InternalParseFrame(Byte[] data, Func <UInt16, UInt32, PackageItemTypes> action)
        {
            //vriables
            UInt32 address = 0x00;
            UInt16 length  = 0x00;

            Byte[]           dataItem = null;
            PackageItemTypes type     = PackageItemTypes.Unkown;
            int count = data.Length;

            //parse frame
            for (int i = 0; i < count; i++)
            {
                //read address
                address = (UInt32)(data[i + 3] << 24 | data[i + 2] << 16 | data[i + 1] << 8 | data[i]);
                length  = (UInt16)(data[i + 5] << 8 | data[i + 4]);

                //read frame item type
                type = action != null?action(this.Address, address) : PackageItemTypes.Unkown;

                //read data
                dataItem = new Byte[length];
                Buffer.BlockCopy(data, i + 6, dataItem, 0, length);

                //parse
                IPackageItem item = this.InternalParseFrame(type, address, length, dataItem);
                if (item != null)
                {
                    this.m_items.Add(item);
                }

                //next
                i += 5 + length;
            }
        }
Ejemplo n.º 3
0
        private static Refund TryRefundBeforeFirstPaidDate(
            IPackageItem packageItem, List <InvoiceItem> paidInvoiceItems,
            Func <DateRange, decimal, decimal> calculateCurrentCost)
        {
            var unpaidRange = new DateRange(
                Dates.Max(packageItem.StartDate, PayrunConstants.DefaultStartDate),
                paidInvoiceItems.Min(item => item.FromDate).AddDays(-1));

            if (unpaidRange.WeeksInclusive <= 0)
            {
                return(null);
            }

            // package item start date has been shifted before previously paid invoices - create adjustment for this unpaid period
            // ............[--inv1--][--inv2--]
            // ..[--ref0--][--ref1--][--ref2--]
            var currentCost = calculateCurrentCost(unpaidRange, unpaidRange.WeeksInclusive);

            return(new Refund
            {
                StartDate = unpaidRange.StartDate,
                EndDate = unpaidRange.EndDate,
                Quantity = unpaidRange.WeeksInclusive,
                Amount = currentCost.Round(2)
            });
        }
Ejemplo n.º 4
0
        protected static DateTimeOffset GetActualStartDate(IPackageItem packageItem, IList <InvoiceDomain> packageInvoices)
        {
            var latestInvoiceItem = GetLatestInvoiceItem(packageItem, packageInvoices);

            return(latestInvoiceItem != null
                ? latestInvoiceItem.ToDate.AddDays(1)
                : Dates.Max(packageItem.StartDate, PayrunConstants.DefaultStartDate));
        }
Ejemplo n.º 5
0
 public static bool IsReferenced(this IPackageItem packageItem, InvoiceItem invoiceItem)
 {
     return(packageItem switch
     {
         CarePackageDetail _ => packageItem.Id == invoiceItem.CarePackageDetailId,
         CarePackageReclaim _ => packageItem.Id == invoiceItem.CarePackageReclaimId,
         _ => throw new InvalidOperationException($"Unsupported package item type {packageItem.GetType()}")
     });
Ejemplo n.º 6
0
 private static List <InvoiceItem> GetPaidInvoiceItems(IPackageItem packageItem, IList <InvoiceDomain> packageInvoices)
 {
     return(packageInvoices
            .Where(invoice => invoice.Status is InvoiceStatus.Accepted &&
                   invoice.PayrunStatus.In(PayrunStatus.Paid, PayrunStatus.PaidWithHold, PayrunStatus.Approved))
            .SelectMany(invoice => invoice.Items)
            .Where(packageItem.IsReferenced)
            .ToList());
 }
Ejemplo n.º 7
0
        public static IEnumerable <Refund> Calculate(
            IPackageItem packageItem, IList <InvoiceDomain> packageInvoices,
            Func <DateRange, decimal, decimal> calculateCurrentCost)
        {
            var paidInvoiceItems = GetPaidInvoiceItems(packageItem, packageInvoices);

            if (!paidInvoiceItems.Any())
            {
                yield break;                          // no payments. no refunds
            }
            // package item has some significant updates (cost, dates etc.) -> create a new refund
            if (packageItem.Version > paidInvoiceItems.Max(item => item.SourceVersion))
            {
                // handle possible shift of package item start date before first paid invoice
                var refund = TryRefundBeforeFirstPaidDate(packageItem, paidInvoiceItems, calculateCurrentCost);
                if ((refund != null) && (refund.Amount != 0.0m))
                {
                    yield return(refund);
                }

                // always create a refund in range of first invoice to avoid
                // tricky cases with jagged diapasons of refunds / rejected / normal items
                // [--inv1--][--inv2--][--inv2--]
                // [--ref1--][--ref2--][--ref2--]
                var invoiceItemsGroups = paidInvoiceItems.GroupBy(item => item.FromDate);

                foreach (var paidItems in invoiceItemsGroups)
                {
                    var currentRange = new DateRange(
                        Dates.Max(packageItem.StartDate, paidItems.First().FromDate),
                        Dates.Min(packageItem.EndDate, paidItems.First().ToDate));

                    // if package item date range moved into future, its start date can be greater than last invoice date
                    // no payments now needed for new range, but we still need to refund already paid.
                    // So set quantity and current cost to 0 and let the rest of logic flow.
                    var quantity = Math.Max(currentRange.WeeksInclusive, 0);

                    var currentCost  = calculateCurrentCost(currentRange, quantity).Round(2);
                    var refundAmount = CalculateRefundAmount(packageItem, currentCost, paidItems.ToList()).Round(2);

                    if (refundAmount != 0.0m)
                    {
                        yield return(new Refund
                        {
                            StartDate = paidItems.First().FromDate,
                            EndDate = paidItems.First().ToDate,
                            Quantity = quantity,
                            Amount = refundAmount
                        });
                    }
                }
            }
        }
Ejemplo n.º 8
0
 /// <summary>
 ///  Removes the first occurrence of a specific object with address
 /// </summary>
 /// <param name="address">Specific address</param>
 public void Remove(UInt16 address)
 {
     for (int i = 0; i < this.m_items.Count; i++)
     {
         IPackageItem item = this.m_items[i];
         if (item.Address == address)
         {
             this.Remove(item);
             return;
         }
     }
 }
        private static string CalculatePackageStatus(CarePackage package, IPackageItem coreCost)
        {
            var today = DateTimeOffset.UtcNow.Date;

            return(package.Status switch
            {
                PackageStatus.Approved when coreCost.EndDate != null &&
                coreCost.EndDate.GetValueOrDefault().Date < today => "Ended",
                PackageStatus.Approved when IsValidDateRange(coreCost.StartDate, coreCost.EndDate) => "Active",
                PackageStatus.Approved => "Future",
                _ => package.Status.GetDisplayName()
            });
Ejemplo n.º 10
0
        /// <summary>
        /// This function serializes object to frame group
        /// </summary>
        /// <typeparam name="T">Data type</typeparam>
        /// <param name="data">Data object</param>
        /// <param name="reflection">reflection info for this data type</param>
        /// <param name="PackageGroupAttribute">Current group attribute</param>
        /// <returns>Group | null</returns>
        private static PackageGroupItem InternalSerializeV2ToGroup <T>(T data, ReflectionType reflection, PackageGroupAttribute PackageGroupAttribute)
        {
            //variables
            Object value = null;

            //create group
            PackageGroupItem group = new PackageGroupItem(PackageGroupAttribute.Address);

            //set property
            foreach (ReflectionProperty item in reflection.PropertyCollection.Values)
            {
                //check property type
                if (item.Property.CanRead)
                {
                    //get current attribute
                    PackageItemAttribute attribute = item.GetCustomAttribute <PackageItemAttribute>();
                    if (attribute != null)
                    {
                        try
                        {
                            value = item.Property.GetValue(data, null);
                            if (value != null)
                            {
                                IPackageItem frameItem = Package.CreatePackageItem(attribute.Type, attribute.Address, value);
                                if (frameItem != null)
                                {
                                    group.Add(frameItem);
                                }
                            }
                        }
                        catch (Exception ex)
                        {
                            throw new Exception(String.Format("Error type: {0} -> {1} [{2}]", attribute.Type, item.Property.Name, value), ex);
                        }
                    }
                }
            }

            //return current group
            return(group);
        }
Ejemplo n.º 11
0
        /// <summary>
        /// Serializes the specified Object to Frame
        /// </summary>
        /// <typeparam name="T">The type of the object to serialize to.</typeparam>
        /// <param name="obj">The object to serialize.</param>
        /// <param name="frame">Frame</param>
        /// <param name="reflection">Reflection information for the Object to deserialize</param>
        /// <returns>Frame | null</returns>
        private static Package InternalSerialize <T>(T obj, Package frame, ReflectionType reflection)
        {
            //set property
            foreach (ReflectionProperty item in reflection.PropertyCollection.Values)
            {
                //check property type
                if (item.Property.CanRead)
                {
                    //get current attribute
                    PackageItemAttribute attribute = item.GetCustomAttribute <PackageItemAttribute>();
                    if (attribute != null)
                    {
                        Object value = null;
                        try
                        {
                            value = item.Property.GetValue(obj, null);
                            if (value != null)
                            {
                                IPackageItem frameItem = Package.CreatePackageItem(attribute.Type, attribute.Address, value);
                                if (frameItem != null)
                                {
                                    frame.Add(frameItem);
                                }
                            }
                        }
                        catch (Exception ex)
                        {
                            throw new Exception(String.Format("Error type: {0} -> {1} [{2}]", attribute.Type, item.Property.Name, value), ex);
                        }
                    }
                }
            }

            //return result
            return(frame);
        }
Ejemplo n.º 12
0
 private static decimal CalculateRefundAmount(IPackageItem packageItem, decimal currentCost, IList <InvoiceItem> paidInvoiceItems)
 {
     return(packageItem is CarePackageDetail
         ? CalculatePaymentRefundAmount(currentCost, paidInvoiceItems)
         : CalculateReclaimRefundAmount((CarePackageReclaim)packageItem, currentCost, paidInvoiceItems));
 }
Ejemplo n.º 13
0
 public bool Match(IPackageItem item)
 {
     return(true);
 }
Ejemplo n.º 14
0
 /// <summary>
 /// Adds an item to the end of the Frame
 /// </summary>
 /// <param name="item">The item to be added to the end of the Frame</param>
 public void Add(IPackageItem item)
 {
     this.m_items.Add(item);
 }
Ejemplo n.º 15
0
 /// <summary>
 ///  Removes the first occurrence of a specific object
 /// </summary>
 /// <param name="item">The object to remove</param>
 public void Remove(IPackageItem item)
 {
     this.m_items.Remove(item);
 }
Ejemplo n.º 16
0
 /// <summary>
 /// Inserts an item into the Frame at the specified index.
 /// </summary>
 /// <param name="item">The object to insert. The value can be null for reference types.</param>
 /// <param name="index">The zero-based index at which item should be inserted.</param>
 public void Add(IPackageItem item, int index)
 {
     this.m_items.Insert(index, item);
 }
Ejemplo n.º 17
0
        /// <summary>
        /// This function parse frame from data
        /// </summary>
        /// <param name="data">Data to parse</param>
        /// <param name="action">Function to get frame item type</param>
        private void InternalParseFrame(Byte[] data, Func <UInt16, UInt16, UInt32, PackageItemTypes> action)
        {
            //vriables
            UInt32 address = 0x00;
            UInt16 length  = 0x00;

            Byte[]           dataItem = null;
            PackageItemTypes type     = PackageItemTypes.Unkown;
            int    count        = data.Length;
            UInt16 itemCount    = 0x00;
            UInt16 dataAddress  = 0x00;
            int    currentIndex = 0x00;

            //parse data
            while (currentIndex < count)
            {
                //check group value
                if (data[currentIndex++] != 0x67)
                {
                    throw new Exception("Data are not valid!");
                }

                //get data address
                dataAddress = (UInt16)(data[currentIndex + 1] << 8 | data[currentIndex]);

                //get count+
                itemCount     = (UInt16)(data[currentIndex + 3] << 8 | data[currentIndex + 2]);
                currentIndex += 0x04;

                //create group
                PackageGroupItem group = new PackageGroupItem(dataAddress);

                //parse items
                for (int i = 0; i < itemCount; i++)
                {
                    //read address
                    address = (UInt32)(data[currentIndex + 3] << 24 | data[currentIndex + 2] << 16 | data[currentIndex + 1] << 8 | data[currentIndex]);
                    length  = (UInt16)(data[currentIndex + 5] << 8 | data[currentIndex + 4]);

                    //read frame item type
                    type = action != null?action(this.Address, dataAddress, address) : PackageItemTypes.Unkown;

                    //read data
                    dataItem = new Byte[length];
                    Buffer.BlockCopy(data, currentIndex + 6, dataItem, 0, length);

                    //parse
                    IPackageItem item = this.InternalParseFrame(type, address, length, dataItem);
                    if (item != null)
                    {
                        group.Add(item);
                    }

                    //next
                    currentIndex += 0x06 + length;
                }

                //add group to frame
                this.m_groups.Add(group);
            }
        }
Ejemplo n.º 18
0
 public void OnItemRemoved(BasePackage basePackage, int index, IPackageItem lastItem)
 {
     UpdateItem(index, null);
 }