/// <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); }
private DRScheduleDetail InsertScheduleDetail( int?componentID, DRDeferredCode defCode, decimal amount, AccountSubaccountPair deferralAccountSubaccount, AccountSubaccountPair salesOrExpenseAccountSubaccount, int?overridenSubID = null) { FinPeriod detailFinPeriod = FinPeriodRepository .GetFinPeriodByMasterPeriodID(PXAccess.GetParentOrganizationID(_branchID), _schedule.FinPeriodID).GetValueOrRaiseError(); DRScheduleDetail scheduleDetail = new DRScheduleDetail { ScheduleID = _schedule.ScheduleID, BranchID = _branchID, ComponentID = componentID, CuryTotalAmt = amount, CuryDefAmt = amount, DefCode = defCode.DeferredCodeID, Status = _isDraft ? DRScheduleStatus.Draft : DRScheduleStatus.Open, IsCustom = false, IsOpen = true, Module = _schedule.Module, DocType = _schedule.DocType, RefNbr = _schedule.RefNbr, LineNbr = _schedule.LineNbr, FinPeriodID = detailFinPeriod.FinPeriodID, TranPeriodID = detailFinPeriod.MasterFinPeriodID, BAccountID = _schedule.BAccountID, AccountID = salesOrExpenseAccountSubaccount.AccountID, SubID = overridenSubID ?? salesOrExpenseAccountSubaccount.SubID, DefAcctID = deferralAccountSubaccount.AccountID, DefSubID = deferralAccountSubaccount.SubID, CreditLineNbr = 0, DocDate = _schedule.DocDate, BAccountType = _schedule.Module == BatchModule.AP ? BAccountType.VendorType : BAccountType.CustomerType, }; scheduleDetail = _drEntityStorage.Insert(scheduleDetail); if (!_isDraft) { _drEntityStorage.CreateCreditLineTransaction(scheduleDetail, defCode, _branchID); } return(scheduleDetail); }
private DRScheduleDetail InsertScheduleDetail( int?componentID, DRDeferredCode defCode, decimal amount, AccountSubaccountPair deferralAccountSubaccount, AccountSubaccountPair salesOrExpenseAccountSubaccount) { DRScheduleDetail scheduleDetail = new DRScheduleDetail { ScheduleID = _schedule.ScheduleID, ComponentID = componentID, TotalAmt = amount, DefAmt = amount, DefCode = defCode.DeferredCodeID, Status = _isDraft ? DRScheduleStatus.Draft : DRScheduleStatus.Open, IsCustom = false, IsOpen = true, Module = _schedule.Module, DocType = _schedule.DocType, RefNbr = _schedule.RefNbr, LineNbr = _schedule.LineNbr, FinPeriodID = _schedule.FinPeriodID, BAccountID = _schedule.BAccountID, AccountID = salesOrExpenseAccountSubaccount.AccountID, SubID = salesOrExpenseAccountSubaccount.SubID, DefAcctID = deferralAccountSubaccount.AccountID, DefSubID = deferralAccountSubaccount.SubID, CreditLineNbr = 0, DocDate = _schedule.DocDate, BAccountType = _schedule.Module == BatchModule.AP ? BAccountType.VendorType : BAccountType.CustomerType, }; scheduleDetail = _drEntityStorage.Insert(scheduleDetail); if (!_isDraft) { _drEntityStorage.CreateCreditLineTransaction(scheduleDetail, defCode, _branchID); } return(scheduleDetail); }
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); } } }
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); } }
private DRScheduleDetail CreateScheduleDetail( ARTran artran, INComponent component, DRDeferredCode defCode, AccountSubaccountPair deferralAccountSubaccount, AccountSubaccountPair salesAccountSubaccount, bool isFlexibleMethod) { string uom = artran.UOM; decimal?qty = artran.Qty; decimal coTermRate = 1m; if (component?.ComponentID != null) { uom = component.UOM; if (artran.UOM == component.UOM) { qty = artran.Qty * component.Qty; } else { var qtyBase = _salesPriceProvider.GetQuantityInBaseUOMs(artran); qty = qtyBase * component.Qty; } } if (isFlexibleMethod == true) { coTermRate = (((artran.DRTermEndDate.Value - artran.DRTermStartDate.Value).Days + 1.0m) / 365.0m); } FinPeriod detailFinPeriod = FinPeriodRepository .GetFinPeriodByMasterPeriodID(PXAccess.GetParentOrganizationID(artran.BranchID), artran.TranPeriodID).GetValueOrRaiseError(); DRScheduleDetail scheduleDetail = new DRScheduleDetail { ScheduleID = _schedule.ScheduleID, BranchID = artran.BranchID, ComponentID = component?.ComponentID ?? artran.InventoryID, ParentInventoryID = component?.ComponentID != null ? artran.InventoryID : null, DefCode = component?.DeferredCode ?? defCode.DeferredCodeID, Status = _isDraft ? DRScheduleStatus.Draft : DRScheduleStatus.Open, IsCustom = false, IsOpen = true, Module = _schedule.Module, DocType = _schedule.DocType, RefNbr = _schedule.RefNbr, LineNbr = artran.LineNbr, FinPeriodID = detailFinPeriod.FinPeriodID, TranPeriodID = detailFinPeriod.MasterFinPeriodID, BAccountID = _schedule.BAccountID, AccountID = salesAccountSubaccount.AccountID, SubID = salesAccountSubaccount.SubID, DefAcctID = deferralAccountSubaccount.AccountID, DefSubID = deferralAccountSubaccount.SubID, CreditLineNbr = 0, DocDate = _schedule.DocDate, UOM = uom, Qty = qty, BAccountType = _schedule.Module == BatchModule.AP ? BAccountType.VendorType : BAccountType.CustomerType, TermStartDate = artran.DRTermStartDate, TermEndDate = artran.DRTermEndDate, CoTermRate = coTermRate, }; return(scheduleDetail); }
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); } } }