Esempio n. 1
0
        private void AddComponentScheduleDetail(
            INComponent inventoryItemComponent,
            DRDeferredCode componentDeferralCode,
            InventoryItem inventoryItem,
            decimal amount,
            DRProcess.DRScheduleParameters tranInfo,
            int?overridenSubID)
        {
            if (amount == 0m)
            {
                return;
            }

            DRScheduleDetail scheduleDetail = InsertScheduleDetail(
                inventoryItem.InventoryID,
                componentDeferralCode,
                amount,
                GetDeferralAccountSubaccount(componentDeferralCode, inventoryItem, tranInfo),
                GetSalesOrExpenseAccountSubaccount(inventoryItemComponent, inventoryItem),
                overridenSubID);

            if (!_isDraft)
            {
                IEnumerable <DRScheduleTran> deferralTransactions
                    = _drEntityStorage.CreateDeferralTransactions(_schedule, scheduleDetail, componentDeferralCode, _branchID);

                _drEntityStorage.NonDraftDeferralTransactionsPrepared(scheduleDetail, componentDeferralCode, deferralTransactions);
            }
        }
Esempio n. 2
0
        /// <param name="deferralCode">The item-level deferral code for <paramref name="inventoryItem"/>.</param>
        /// <param name="inventoryItem">The inventory item from the document line.</param>
        /// <param name="transactionAmount">Total transaction amount (with ALL discounts applied).</param>
        /// <param name="fairUnitPrice">The item price from the price list.</param>
        /// <param name="compoundDiscountRate"> Compound discount rate of all discounts
        /// (including line, group and document discounts) that are applicable to deferred components.</param>
        public void CreateOriginalSchedule(
            DRProcess.DRScheduleParameters scheduleParameters,
            DRDeferredCode deferralCode,
            InventoryItem inventoryItem,
            AccountSubaccountPair salesOrExpenseAccountSubaccount,
            decimal?transactionAmount,
            decimal?fairUnitPrice,
            decimal?compoundDiscountRate,
            decimal?quantityInBaseUnit)
        {
            ValidateMDAConsistency(inventoryItem, deferralCode);

            _schedule = _drEntityStorage.CreateCopy(scheduleParameters);

            _schedule.IsDraft  = _isDraft;
            _schedule.IsCustom = false;

            _schedule = _drEntityStorage.Insert(_schedule);

            CreateDetails(
                scheduleParameters,
                deferralCode,
                inventoryItem,
                salesOrExpenseAccountSubaccount,
                transactionAmount,
                fairUnitPrice,
                compoundDiscountRate,
                quantityInBaseUnit);
        }
Esempio n. 3
0
        /// <param name="attachedToOriginalSchedule">
        /// Flag added to handle <see cref="DRScheduleDetail"/>'s status
        /// in the same way as <see cref="DRProcess"/> had done for documents
        /// attached to original schedule.
        /// </param>
        public void ReevaluateSchedule(
            DRSchedule schedule,
            DRProcess.DRScheduleParameters scheduleParameters,
            Amount lineAmount,
            bool attachedToOriginalSchedule)
        {
            if (schedule.IsOverridden == true && _isDraft == false)
            {
                decimal?totalComponentAmt = _drEntityStorage.GetScheduleDetails(schedule.ScheduleID).Sum(s => s.TotalAmt);
                if (totalComponentAmt != lineAmount.Cury)
                {
                    throw new PXException(Messages.CannotReleaseOverriden, totalComponentAmt, lineAmount.Base, _currencyInfo.BaseCuryID);
                }
            }

            _dataProvider.DeleteAllDetails(schedule.ScheduleID);

            _schedule               = schedule;
            _schedule.DocDate       = scheduleParameters.DocDate;
            _schedule.BAccountID    = scheduleParameters.BAccountID;
            _schedule.BAccountLocID = scheduleParameters.BAccountLocID;
            _schedule.FinPeriodID   = scheduleParameters.FinPeriodID;
            _schedule.TranDesc      = scheduleParameters.TranDesc;
            _schedule.IsCustom      = false;
            _schedule.IsDraft       = _isDraft;
            _schedule.BAccountType  = _schedule.Module == BatchModule.AP ? BAccountType.VendorType : BAccountType.CustomerType;
            _schedule.TermStartDate = scheduleParameters.TermStartDate;
            _schedule.TermEndDate   = scheduleParameters.TermEndDate;
            _schedule.ProjectID     = scheduleParameters.ProjectID;
            _schedule.TaskID        = scheduleParameters.TaskID;

            _schedule = _drEntityStorage.Update(_schedule);

            CreateScheduleDetails(scheduleParameters, lineAmount);
        }
Esempio n. 4
0
        /// <param name="attachedToOriginalSchedule">
        /// Flag added to handle <see cref="DRScheduleDetail"/>'s status
        /// in the same way as <see cref="DRProcess"/> had done for documents
        /// attached to original schedule.
        /// </param>
        public void ReevaluateSchedule(
            DRSchedule schedule,
            DRProcess.DRScheduleParameters scheduleParameters,
            DRDeferredCode deferralCode,
            decimal?lineAmount,
            bool attachedToOriginalSchedule)
        {
            _schedule = schedule;

            _schedule.DocDate       = scheduleParameters.DocDate;
            _schedule.BAccountID    = scheduleParameters.BAccountID;
            _schedule.BAccountLocID = scheduleParameters.BAccountLocID;
            _schedule.FinPeriodID   = scheduleParameters.FinPeriodID;
            _schedule.TranDesc      = scheduleParameters.TranDesc;
            _schedule.IsCustom      = false;
            _schedule.IsDraft       = _isDraft;
            _schedule.BAccountType  = _schedule.Module == BatchModule.AP ? BAccountType.VendorType : BAccountType.CustomerType;
            _schedule.TermStartDate = scheduleParameters.TermStartDate;
            _schedule.TermEndDate   = scheduleParameters.TermEndDate;
            _schedule.ProjectID     = scheduleParameters.ProjectID;
            _schedule.TaskID        = scheduleParameters.TaskID;

            _schedule = _drEntityStorage.Update(_schedule);

            IList <DRScheduleDetail> scheduleDetails = _drEntityStorage.GetScheduleDetails(_schedule.ScheduleID);

            ReevaluateComponentAmounts(scheduleDetails, lineAmount);

            foreach (DRScheduleDetail scheduleDetail in scheduleDetails)
            {
                scheduleDetail.DocDate     = _schedule.DocDate;
                scheduleDetail.BAccountID  = _schedule.BAccountID;
                scheduleDetail.FinPeriodID = _schedule.FinPeriodID;

                if (!attachedToOriginalSchedule)
                {
                    scheduleDetail.Status = _isDraft ?
                                            DRScheduleStatus.Draft :
                                            (scheduleDetail.IsResidual == null ? DRScheduleStatus.Closed : DRScheduleStatus.Open);
                }
                else
                {
                    scheduleDetail.Status = _isDraft ?
                                            DRScheduleStatus.Draft :
                                            (scheduleDetail.IsOpen == true ? DRScheduleStatus.Open : DRScheduleStatus.Closed);
                }

                _drEntityStorage.Update(scheduleDetail);

                if (scheduleDetail.IsResidual != true)
                {
                    ReevaluateOrCreateTransactions(scheduleDetail);

                    if (_isDraft == false)
                    {
                        _drEntityStorage.CreateCreditLineTransaction(scheduleDetail, deferralCode, _branchID);
                    }
                }
            }
        }
Esempio n. 5
0
        /// <param name="deferralCode">The item-level deferral code for the inventory item
        /// <param name="transactionAmount">Total transaction amount (with ALL discounts applied).</param>
        /// <param name="fairUnitPrice">The item price from the price list.</param>
        /// <param name="compoundDiscountRate"> Compound discount rate of all discounts
        /// (including line, group and document discounts) that are applicable to deferred components.</param>
        public void CreateOriginalSchedule(
            DRProcess.DRScheduleParameters scheduleParameters,
            Amount lineTotal)
        {
            _schedule = _drEntityStorage.CreateCopy(scheduleParameters);

            _schedule.IsDraft  = _isDraft;
            _schedule.IsCustom = false;

            _schedule = _drEntityStorage.Insert(_schedule);
            CreateScheduleDetails(scheduleParameters, lineTotal);
        }
Esempio n. 6
0
        private void CreateDetails(
            DRProcess.DRScheduleParameters scheduleParameters,
            DRDeferredCode deferralCode,
            InventoryItem inventoryItem,
            AccountSubaccountPair salesOrExpenseAccountSubaccount,
            decimal?transactionAmount,
            decimal?fairUnitPrice,
            decimal?compoundDiscountRate,
            decimal?quantityInBaseUnit)
        {
            if (deferralCode.MultiDeliverableArrangement == true && inventoryItem != null && inventoryItem.IsSplitted == true)
            {
                CreateDetailsForSplitted(
                    scheduleParameters,
                    inventoryItem,
                    salesOrExpenseAccountSubaccount.SubID,
                    transactionAmount,
                    fairUnitPrice,
                    compoundDiscountRate ?? 1.0m,
                    quantityInBaseUnit ?? 0.0m);
            }
            else
            {
                var deferralAccountSubaccount = GetDeferralAccountSubaccount(deferralCode, inventoryItem, scheduleParameters);

                int?componentID = inventoryItem == null ? DRScheduleDetail.EmptyComponentID : inventoryItem.InventoryID;

                DRScheduleDetail scheduleDetail = InsertScheduleDetail(
                    componentID,
                    deferralCode,
                    transactionAmount.Value,
                    deferralAccountSubaccount,
                    salesOrExpenseAccountSubaccount);

                if (!_isDraft)
                {
                    IEnumerable <DRScheduleTran> deferralTransactions =
                        _drEntityStorage.CreateDeferralTransactions(_schedule, scheduleDetail, deferralCode, _branchID);

                    _drEntityStorage.NonDraftDeferralTransactionsPrepared(scheduleDetail, deferralCode, deferralTransactions);
                }
            }
        }
Esempio n. 7
0
        private void AddComponentScheduleDetail(
            INComponent inventoryItemComponent,
            DRDeferredCode componentDeferralCode,
            InventoryItem inventoryItem,
            decimal amount,
            DRProcess.DRScheduleParameters tranInfo)
        {
            if (amount == 0m)
            {
                return;
            }

            DRScheduleDetail scheduleDetail = InsertScheduleDetail(
                inventoryItem.InventoryID,
                componentDeferralCode,
                amount,
                GetDeferralAccountSubaccount(componentDeferralCode, inventoryItem, tranInfo),
                GetSalesOrExpenseAccountSubaccount(inventoryItemComponent, inventoryItem));

            if (!_isDraft)
            {
                _drEntityStorage.CreateDeferralTransactions(_schedule, scheduleDetail, componentDeferralCode, _branchID);
            }
        }
Esempio n. 8
0
        private AccountSubaccountPair GetDeferralAccountSubaccount(
            DRDeferredCode deferralCode,
            InventoryItem item,
            DRProcess.DRScheduleParameters scheduleParameters)
        {
            int?accountID = deferralCode.AccountID;

            string subaccountCD = null;
            int?   subaccountID = null;

            if (deferralCode.AccountSource == DeferralAccountSource.Item)
            {
                accountID = item != null ? item.DeferralAcctID : subaccountID;
                // this is fishy. subID is always null at this point.
            }

            if (deferralCode.CopySubFromSourceTran == true)
            {
                subaccountID = scheduleParameters.SubID;
            }
            else if (scheduleParameters.Module == BatchModule.AP)
            {
                int?itemSubID = item?.DeferralSubID;

                Location location = _businessAccountProvider
                                    .GetLocation(scheduleParameters.BAccountID, scheduleParameters.BAccountLocID);

                int?locationSubID = location?.VExpenseSubID;

                EPEmployee employee = _businessAccountProvider
                                      .GetEmployee(scheduleParameters.EmployeeID);

                int?employeeSubaccountID = employee?.ExpenseSubID;

                subaccountCD = _subaccountProvider.MakeSubaccount <DRScheduleDetail.subID>(
                    deferralCode.DeferralSubMaskAP,
                    new object[] { locationSubID, itemSubID, employeeSubaccountID, deferralCode.SubID },
                    new []
                {
                    typeof(Location.vExpenseSubID),
                    typeof(InventoryItem.deferralSubID),
                    typeof(EPEmployee.expenseSubID),
                    typeof(DRDeferredCode.subID)
                });
            }
            else if (scheduleParameters.Module == BatchModule.AR)
            {
                int?itemSubID = item?.DeferralSubID;

                Location location = _businessAccountProvider
                                    .GetLocation(scheduleParameters.BAccountID, scheduleParameters.BAccountLocID);

                int?locationSubaccountID = location?.CSalesSubID;

                EPEmployee employee = _businessAccountProvider
                                      .GetEmployee(scheduleParameters.EmployeeID);

                int?employeeSubaccountID = employee?.SalesSubID;

                SalesPerson salesPerson = _businessAccountProvider
                                          .GetSalesPerson(scheduleParameters.SalesPersonID);

                int?salesPersonSubaccountID = salesPerson?.SalesSubID;

                subaccountCD = _subaccountProvider.MakeSubaccount <DRScheduleDetail.subID>(
                    deferralCode.DeferralSubMaskAR,
                    new object[] { locationSubaccountID, itemSubID, employeeSubaccountID, deferralCode.SubID, salesPersonSubaccountID },
                    new []
                {
                    typeof(Location.cSalesSubID),
                    typeof(InventoryItem.deferralSubID),
                    typeof(EPEmployee.salesSubID),
                    typeof(DRDeferredCode.subID),
                    typeof(SalesPerson.salesSubID)
                });
            }

            if (subaccountCD != null)
            {
                subaccountID = _subaccountProvider.GetSubaccountID(subaccountCD);
            }

            return(new AccountSubaccountPair(accountID, subaccountID));
        }
Esempio n. 9
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);
            }
        }
Esempio n. 10
0
        /// <param name="attachedToOriginalSchedule">
        /// Flag added to handle <see cref="DRScheduleDetail"/>'s status
        /// in the same way as <see cref="DRProcess"/> had done for documents
        /// attached to original schedule.
        /// </param>
        public void ReevaluateSchedule(
            DRSchedule schedule,
            DRProcess.DRScheduleParameters scheduleParameters,
            DRDeferredCode deferralCode,
            decimal?lineAmount,
            bool attachedToOriginalSchedule)
        {
            _schedule = schedule;

            _schedule.DocDate       = scheduleParameters.DocDate;
            _schedule.BAccountID    = scheduleParameters.BAccountID;
            _schedule.BAccountLocID = scheduleParameters.BAccountLocID;
            _schedule.FinPeriodID   = scheduleParameters.FinPeriodID;
            _schedule.TranDesc      = scheduleParameters.TranDesc;
            _schedule.IsCustom      = false;
            _schedule.IsDraft       = _isDraft;
            _schedule.BAccountType  = _schedule.Module == BatchModule.AP ? BAccountType.VendorType : BAccountType.CustomerType;
            _schedule.TermStartDate = scheduleParameters.TermStartDate;
            _schedule.TermEndDate   = scheduleParameters.TermEndDate;
            _schedule.ProjectID     = scheduleParameters.ProjectID;
            _schedule.TaskID        = scheduleParameters.TaskID;

            _schedule = _drEntityStorage.Update(_schedule);

            IList <DRScheduleDetail> scheduleDetails = _drEntityStorage.GetScheduleDetails(_schedule.ScheduleID);

            ReevaluateComponentAmounts(scheduleDetails, lineAmount);

            foreach (DRScheduleDetail scheduleDetail in scheduleDetails)
            {
                scheduleDetail.DocDate    = _schedule.DocDate;
                scheduleDetail.BAccountID = _schedule.BAccountID;

                FinPeriod detailFinPeriod = FinPeriodRepository
                                            .GetFinPeriodByMasterPeriodID(PXAccess.GetParentOrganizationID(scheduleDetail.BranchID),
                                                                          _schedule.FinPeriodID).GetValueOrRaiseError();

                scheduleDetail.FinPeriodID  = detailFinPeriod.FinPeriodID;
                scheduleDetail.TranPeriodID = detailFinPeriod.MasterFinPeriodID;

                if (!attachedToOriginalSchedule)
                {
                    scheduleDetail.Status = _isDraft ?
                                            DRScheduleStatus.Draft :
                                            (scheduleDetail.IsResidual == null ? DRScheduleStatus.Closed : DRScheduleStatus.Open);
                }
                else
                {
                    scheduleDetail.Status = _isDraft ?
                                            DRScheduleStatus.Draft :
                                            (scheduleDetail.IsOpen == true ? DRScheduleStatus.Open : DRScheduleStatus.Closed);
                }

                _drEntityStorage.Update(scheduleDetail);

                if (scheduleDetail.IsResidual != true)
                {
                    DRDeferredCode detailDeferralCode = _drEntityStorage.GetDeferralCode(scheduleDetail.DefCode);

                    IEnumerable <DRScheduleTran> componentTransactions =
                        _drEntityStorage.GetDeferralTransactions(scheduleDetail.ScheduleID, scheduleDetail.ComponentID, scheduleDetail.DetailLineNbr);

                    if (componentTransactions.Any())
                    {
                        ReevaluateTransactionAmounts(scheduleDetail, detailDeferralCode, componentTransactions);
                    }

                    if (!_isDraft)
                    {
                        if (!componentTransactions.Any())
                        {
                            componentTransactions = _drEntityStorage.CreateDeferralTransactions(_schedule, scheduleDetail, detailDeferralCode, _branchID);
                        }

                        _drEntityStorage.CreateCreditLineTransaction(scheduleDetail, deferralCode, _branchID);
                        _drEntityStorage.NonDraftDeferralTransactionsPrepared(scheduleDetail, detailDeferralCode, componentTransactions);
                    }
                }
            }
        }
Esempio n. 11
0
        private void CreateScheduleDetails(DRProcess.DRScheduleParameters scheduleParameters, Amount lineTotal)
        {
            decimal scheduleFairTotal = 0;

            var errors = new List <string>();

            foreach (PXResult <ARTran, InventoryItem, DRDeferredCode, INComponent,
                               DRSingleProcess.ComponentINItem, DRSingleProcess.ComponentDeferredCode> item in _singleScheduleViewProvider.GetParentDocumentDetails())
            {
                ARTran         artran        = item;
                InventoryItem  inventoryItem = item;
                DRDeferredCode deferredCode  = item;
                INComponent    component     = item;
                DRSingleProcess.ComponentINItem       componentINItem       = item;
                DRSingleProcess.ComponentDeferredCode componentDeferredCode = item;

                bool isMDA = deferredCode.MultiDeliverableArrangement == true;

                AccountSubaccountPair deferralAccountSubaccount = GetDeferralAccountSubaccount(
                    isMDA ? componentDeferredCode: deferredCode,
                    isMDA ? componentINItem : inventoryItem,
                    scheduleParameters,
                    artran.SubID);

                AccountSubaccountPair salesAccountSubaccount = GetSalesAccountSubaccount(deferredCode, inventoryItem, component, artran);

                bool isFlexibleMethod = deferredCode.Method == DeferredMethodType.FlexibleProrateDays ||
                                        deferredCode.Method == DeferredMethodType.FlexibleExactDays ||
                                        componentDeferredCode?.Method == DeferredMethodType.FlexibleProrateDays ||
                                        componentDeferredCode?.Method == DeferredMethodType.FlexibleExactDays;

                try
                {
                    DRScheduleDetail detail = CreateScheduleDetail(
                        artran,
                        component,
                        deferredCode,
                        deferralAccountSubaccount,
                        salesAccountSubaccount,
                        isFlexibleMethod);

                    detail = _drEntityStorage.Insert(detail);
                    SetFairValuePrice(detail);
                    detail = _drEntityStorage.Update(detail);

                    if (!_isDraft)
                    {
                        _drEntityStorage.CreateCreditLineTransaction(detail, deferredCode, _branchID);
                    }

                    scheduleFairTotal += detail.EffectiveFairValuePrice.Value * detail.Qty.Value;
                }
                catch (NoFairValuePriceFoundException e)
                {
                    errors.Add(e.Message);
                    continue;
                }
            }

            if (errors.Any())
            {
                throw new NoFairValuePricesFoundException(string.Join(Environment.NewLine, errors));
            }

            if (scheduleFairTotal == 0m)
            {
                throw new PXException(Messages.SumOfFairValuePricesEqualToZero);
            }

            IEnumerable <DRScheduleDetail> scheduleDetails = _drEntityStorage.GetScheduleDetails(_schedule.ScheduleID)
                                                             .RowCast <DRScheduleDetail>()
                                                             .ToList();

            if (scheduleDetails.IsSingleElement())
            {
                DRScheduleDetail scheduleDetail = scheduleDetails.Single();
                scheduleDetail.CuryTotalAmt = lineTotal.Cury;
                scheduleDetail.CuryDefAmt   = lineTotal.Cury;
                scheduleDetail.Percentage   = 1m;
                _drEntityStorage.Update(scheduleDetail);
            }
            else if (scheduleDetails.HasAtLeastTwoItems())
            {
                decimal          sumPercent = 0m;
                decimal          sumResult  = 0m;
                DRScheduleDetail maxAmtLine = null;

                scheduleDetails.ForEach(scheduleDetail =>
                {
                    scheduleDetail.Percentage = scheduleDetail.EffectiveFairValuePrice * scheduleDetail.Qty / scheduleFairTotal;
                    sumPercent += scheduleDetail.Percentage ?? 0m;

                    decimal?rawResult = lineTotal.Cury * scheduleDetail.Percentage;
                    decimal?result    = _roundingFunction(rawResult.Value);
                    sumResult        += result ?? 0m;

                    scheduleDetail.CuryTotalAmt = result;
                    scheduleDetail.CuryDefAmt   = result;

                    var detail = _drEntityStorage.Update(scheduleDetail);

                    if ((maxAmtLine?.CuryTotalAmt ?? 0m) < detail.CuryTotalAmt)
                    {
                        maxAmtLine = detail;
                    }
                });

                if (sumPercent != 1m || sumResult != lineTotal.Cury)
                {
                    decimal?amtDiff = lineTotal.Cury - sumResult;

                    maxAmtLine.CuryTotalAmt += amtDiff;
                    maxAmtLine.CuryDefAmt   += amtDiff;
                    maxAmtLine.Percentage   += 1m - sumPercent;

                    _drEntityStorage.Update(maxAmtLine);
                }
            }

            if (!_isDraft)
            {
                foreach (PXResult <DRScheduleDetail, DRDeferredCode> detail in _dataProvider.GetScheduleDetailsResultset(_schedule.ScheduleID))
                {
                    DRScheduleDetail scheduleDetail = detail;
                    DRDeferredCode   deferralCode   = detail;

                    IEnumerable <DRScheduleTran> deferralTransactions =
                        _drEntityStorage.CreateDeferralTransactions(_schedule, scheduleDetail, deferralCode, _branchID);

                    _drEntityStorage.NonDraftDeferralTransactionsPrepared(scheduleDetail, deferralCode, deferralTransactions);
                }
            }
        }