Example #1
0
        public override IEnumerable <ComponentAmount> Distribute(decimal tranAmt, decimal amountToDistribute)
        {
            base.Distribute(tranAmt, amountToDistribute);

            if (amountToDistribute - _amounts.Sum(componentAmount => componentAmount.Item2) < 0)
            {
                _amounts = new PercentageDistribution(_inventoryItemProvider, _percentageComponents, _roundingFunction)
                           .Distribute(tranAmt, amountToDistribute)
                           .ToList();
            }

            return(_amounts);
        }
Example #2
0
        private void CreateDetailsForSplitted(
            DRProcess.DRScheduleParameters scheduleParameters,
            InventoryItem inventoryItem,
            int?subaccountID,
            decimal?transactionAmount,
            decimal?fairUnitPrice,
            decimal compoundDiscountRate,
            decimal qtyInBaseUnit)
        {
            int?salesExpenseSubIDOverride = inventoryItem.UseParentSubID == true ? null : subaccountID;

            IEnumerable <InventoryItemComponentInfo> fixedAllocationComponents =
                _inventoryItemProvider.GetInventoryItemComponents(inventoryItem.InventoryID, INAmountOption.FixedAmt);

            IEnumerable <InventoryItemComponentInfo> percentageAllocationComponents =
                _inventoryItemProvider.GetInventoryItemComponents(inventoryItem.InventoryID, INAmountOption.Percentage);

            IEnumerable <InventoryItemComponentInfo> residualAllocationComponents =
                _inventoryItemProvider.GetInventoryItemComponents(inventoryItem.InventoryID, INAmountOption.Residual);

            if (residualAllocationComponents.Any() && !residualAllocationComponents.IsSingleElement())
            {
                throw new PXException(Messages.TooManyResiduals);
            }

            bool canUseResidual = residualAllocationComponents.Any();

            decimal fixedTotalAmount = 0;

            foreach (InventoryItemComponentInfo componentInfo in fixedAllocationComponents)
            {
                INComponent component = componentInfo.Component;

                decimal amountRaw = (component.FixedAmt ?? 0) * qtyInBaseUnit * compoundDiscountRate;
                decimal amount    = _roundingFunction(amountRaw);

                fixedTotalAmount += amount;

                AddComponentScheduleDetail(
                    componentInfo.Component,
                    componentInfo.DeferralCode,
                    componentInfo.Item,
                    Math.Sign((decimal)transactionAmount) * amount,
                    scheduleParameters,
                    salesExpenseSubIDOverride);
            }

            decimal fixedPerUnit =
                fixedAllocationComponents.Sum(componentInfo => componentInfo.Component.FixedAmt ?? 0);

            decimal amountToDistribute = transactionAmount.Value - fixedTotalAmount;

            if (transactionAmount >= 0 && amountToDistribute < 0 ||
                transactionAmount < 0 && amountToDistribute > 0)
            {
                throw new PXException(Messages.FixedAmtSumOverload);
            }

            if (!percentageAllocationComponents.Any() && amountToDistribute != 0 && !canUseResidual)
            {
                throw new PXException(Messages.NoResidual);
            }

            if (percentageAllocationComponents.Any())
            {
                bool canUseResidualInPercentageDistribution =
                    canUseResidual && fairUnitPrice != null && fairUnitPrice != 0.0m;

                PercentageDistribution distribution;

                if (canUseResidualInPercentageDistribution)
                {
                    distribution = new PercentageWithResidualDistribution(
                        _inventoryItemProvider,
                        percentageAllocationComponents,
                        fairUnitPrice.Value,
                        fixedPerUnit,
                        compoundDiscountRate,
                        qtyInBaseUnit,
                        _roundingFunction);
                }
                else
                {
                    distribution = new PercentageDistribution(
                        _inventoryItemProvider,
                        percentageAllocationComponents,
                        _roundingFunction);
                }

                IEnumerable <ComponentAmount> percentageAmounts =
                    distribution.Distribute(transactionAmount.Value, amountToDistribute);

                foreach (var componentAmount in percentageAmounts)
                {
                    AddComponentScheduleDetail(
                        componentAmount.Item1.Component,
                        componentAmount.Item1.DeferralCode,
                        componentAmount.Item1.Item,
                        componentAmount.Item2,
                        scheduleParameters,
                        salesExpenseSubIDOverride);
                }

                amountToDistribute -= percentageAmounts.Sum(componentAmount => componentAmount.Item2);
            }

            if (canUseResidual && amountToDistribute > 0m)
            {
                INComponent   residualComponent     = residualAllocationComponents.Single().Component;
                InventoryItem residualComponentItem = residualAllocationComponents.Single().Item;

                AccountSubaccountPair salesOrExpenseAccountSubaccount =
                    GetSalesOrExpenseAccountSubaccount(residualComponent, residualComponentItem);

                InsertResidualScheduleDetail(
                    residualComponent.ComponentID,
                    amountToDistribute,
                    salesOrExpenseAccountSubaccount.AccountID,
                    salesExpenseSubIDOverride ?? salesOrExpenseAccountSubaccount.SubID);
            }
        }