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); }
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); } }