public static int CompareFinPeriod(ScheduledTran a, ScheduledTran b)
 {
     return(a.FinPeriodID.CompareTo(b.FinPeriodID));
 }
        protected virtual IEnumerable items()
        {
            ScheduleRecognitionFilter filter = Filter.Current;

            if (filter == null)
            {
                yield break;
            }
            bool found = false;

            foreach (ScheduledTran item in Items.Cache.Inserted)
            {
                found = true;
                yield return(item);
            }
            if (found)
            {
                yield break;
            }


            PXSelectBase <DRScheduleTran> select = new PXSelectJoin <DRScheduleTran,
                                                                     InnerJoin <DRScheduleDetail, On <DRScheduleTran.scheduleID, Equal <DRScheduleDetail.scheduleID>, And <DRScheduleTran.componentID, Equal <DRScheduleDetail.componentID> > >,
                                                                                InnerJoin <DRSchedule, On <DRScheduleTran.scheduleID, Equal <DRSchedule.scheduleID> >,
                                                                                           LeftJoin <InventoryItem, On <DRScheduleTran.componentID, Equal <InventoryItem.inventoryID> > > > >,
                                                                     Where <DRScheduleTran.recDate, LessEqual <Current <ScheduleRecognitionFilter.recDate> >,
                                                                            And <DRScheduleTran.status, Equal <DRScheduleTranStatus.OpenStatus>,
                                                                                 And <DRScheduleDetail.status, NotEqual <DRScheduleStatus.DraftStatus> > > >,
                                                                     OrderBy <Asc <DRScheduleTran.scheduleID, Asc <DRScheduleTran.componentID, Asc <DRScheduleTran.recDate, Asc <DRScheduleTran.lineNbr> > > > > >(this);

            if (!string.IsNullOrEmpty(filter.DeferredCode))
            {
                select.WhereAnd <Where <DRScheduleDetail.defCode, Equal <Current <ScheduleRecognitionFilter.deferredCode> > > >();
            }

            if (filter.BranchID != null)
            {
                select.WhereAnd <Where <DRScheduleDetail.branchID, Equal <Current <ScheduleRecognitionFilter.branchID> > > >();
            }

            Dictionary <string, string> added = new Dictionary <string, string>();

            foreach (PXResult <DRScheduleTran, DRScheduleDetail, DRSchedule, InventoryItem> resultSet in select.Select())
            {
                DRScheduleTran   tran           = (DRScheduleTran)resultSet;
                DRSchedule       schedule       = (DRSchedule)resultSet;
                DRScheduleDetail scheduleDetail = (DRScheduleDetail)resultSet;
                InventoryItem    item           = (InventoryItem)resultSet;

                string key = string.Format("{0}.{1}", tran.ScheduleID, tran.ComponentID);

                bool doInsert = false;

                if (added.ContainsKey(key))
                {
                    string addedFinPeriod = added[key];

                    if (tran.FinPeriodID == addedFinPeriod)
                    {
                        doInsert = true;
                    }
                }
                else
                {
                    doInsert = true;
                    added.Add(key, tran.FinPeriodID);
                }

                if (doInsert)
                {
                    ScheduledTran result = new ScheduledTran();
                    result.BranchID    = tran.BranchID;
                    result.AccountID   = tran.AccountID;
                    result.Amount      = tran.Amount;
                    result.ComponentID = tran.ComponentID;
                    result.DefCode     = scheduleDetail.DefCode;
                    result.FinPeriodID = tran.FinPeriodID;
                    result.LineNbr     = tran.LineNbr;
                    result.RecDate     = tran.RecDate;
                    result.ScheduleID  = tran.ScheduleID;
                    result.ScheduleNbr = schedule.ScheduleNbr;
                    result.SubID       = tran.SubID;
                    result.ComponentCD = item.InventoryCD;
                    result.DocType     = DRScheduleDocumentType.BuildDocumentType(scheduleDetail.Module, scheduleDetail.DocType);

                    Items.Cache.SetStatus(result, PXEntryStatus.Inserted);
                    yield return(result);                   // Items.Insert(result);
                }
            }


            //Virtual Records (CashReceipt):

            PXSelectBase <ARInvoice> s = null;

            if (!string.IsNullOrEmpty(filter.DeferredCode))
            {
                s = new PXSelectJoinGroupBy <ARInvoice,
                                             InnerJoin <ARTran, On <ARTran.tranType, Equal <ARInvoice.docType>,
                                                                    And <ARTran.refNbr, Equal <ARInvoice.refNbr> > >,
                                                        InnerJoin <DRDeferredCode, On <ARTran.deferredCode, Equal <DRDeferredCode.deferredCodeID>,
                                                                                       And <DRDeferredCode.method, Equal <DeferredMethodType.cashReceipt>,
                                                                                            And <DRDeferredCode.deferredCodeID, Equal <Current <ScheduleRecognitionFilter.deferredCode> > > > >,
                                                                   InnerJoin <DRSchedule, On <ARTran.tranType, Equal <DRSchedule.docType>,
                                                                                              And <ARTran.refNbr, Equal <DRSchedule.refNbr>,
                                                                                                   And <ARTran.lineNbr, Equal <DRSchedule.lineNbr> > > >,
                                                                              InnerJoin <DRScheduleDetail, On <DRSchedule.scheduleID, Equal <DRScheduleDetail.scheduleID> > > > > >,
                                             Where <ARInvoice.released, Equal <True>,
                                                    And <DRScheduleDetail.isOpen, Equal <True> > >,
                                             Aggregate <GroupBy <ARInvoice.docType, GroupBy <ARInvoice.refNbr> > > >(this);
            }
            else
            {
                s = new PXSelectJoinGroupBy <ARInvoice,
                                             InnerJoin <ARTran, On <ARTran.tranType, Equal <ARInvoice.docType>,
                                                                    And <ARTran.refNbr, Equal <ARInvoice.refNbr> > >,
                                                        InnerJoin <DRDeferredCode, On <ARTran.deferredCode, Equal <DRDeferredCode.deferredCodeID>,
                                                                                       And <DRDeferredCode.method, Equal <DeferredMethodType.cashReceipt> > >,
                                                                   InnerJoin <DRSchedule, On <ARTran.tranType, Equal <DRSchedule.docType>,
                                                                                              And <ARTran.refNbr, Equal <DRSchedule.refNbr>,
                                                                                                   And <ARTran.lineNbr, Equal <DRSchedule.lineNbr> > > >,
                                                                              InnerJoin <DRScheduleDetail, On <DRSchedule.scheduleID, Equal <DRScheduleDetail.scheduleID> > > > > >,
                                             Where <ARInvoice.released, Equal <True>,
                                                    And <DRScheduleDetail.isOpen, Equal <True> > >,
                                             Aggregate <GroupBy <ARInvoice.docType, GroupBy <ARInvoice.refNbr> > > >(this);
            }


            foreach (ARInvoice inv in s.Select())
            {
                PXSelectBase <ARTran> trs =
                    new PXSelectJoin <ARTran,
                                      InnerJoin <DRDeferredCode, On <ARTran.deferredCode, Equal <DRDeferredCode.deferredCodeID>,
                                                                     And <DRDeferredCode.method, Equal <DeferredMethodType.cashReceipt> > > >,
                                      Where <ARTran.tranType, Equal <Required <ARTran.tranType> >,
                                             And <ARTran.refNbr, Equal <Required <ARTran.refNbr> > > > >(this);

                foreach (PXResult <ARTran, DRDeferredCode> res in trs.Select(inv.DocType, inv.RefNbr))
                {
                    List <ScheduledTran> virtualRecords       = new List <ScheduledTran>();
                    List <ScheduledTran> virtualVoidedRecords = new List <ScheduledTran>();

                    ARTran         tr = (ARTran)res;
                    DRDeferredCode dc = (DRDeferredCode)res;

                    decimal trPart = 0;
                    if (inv.LineTotal.Value != 0)
                    {
                        trPart = tr.TranAmt.Value / inv.LineTotal.Value;
                    }
                    decimal trPartRest = tr.TranAmt.Value;

                    InventoryItem invItem = PXSelect <InventoryItem, Where <InventoryItem.inventoryID, Equal <Required <InventoryItem.inventoryID> > > > .Select(this, tr.InventoryID);

                    //NOTE: Multiple Components are not supported in CashReceipt Deferred Revenue Recognition.
                    DRSchedule       schedule       = GetScheduleByFID(BatchModule.AR, inv.DocType, inv.RefNbr, tr.LineNbr);
                    DRScheduleDetail scheduleDetail = GetScheduleDetailbyID(schedule.ScheduleID, tr.InventoryID != null ? tr.InventoryID : DRScheduleDetail.EmptyComponentID);
                    int lineNbr = scheduleDetail.LineCntr ?? 0;


                    PXSelectBase <ARAdjust> ads =
                        new PXSelectJoin <ARAdjust,
                                          LeftJoin <DRScheduleTran, On <ARAdjust.adjgDocType, Equal <DRScheduleTran.adjgDocType>,
                                                                        And <ARAdjust.adjgRefNbr, Equal <DRScheduleTran.adjgRefNbr> > > >,
                                          Where <ARAdjust.adjdDocType, Equal <Required <ARAdjust.adjdDocType> >,
                                                 And <ARAdjust.adjdRefNbr, Equal <Required <ARAdjust.adjdRefNbr> >,
                                                      And <DRScheduleTran.scheduleID, IsNull,
                                                           And <ARAdjust.adjgDocType, NotEqual <ARDocType.creditMemo> > > > >,
                                          OrderBy <Asc <ARAdjust.adjgDocDate> > >(this);

                    foreach (ARAdjust ad in ads.Select(inv.DocType, inv.RefNbr))
                    {
                        lineNbr++;
                        decimal amtRaw = Math.Min(trPart * ad.AdjAmt.Value, trPartRest);
                        trPartRest -= amtRaw;
                        decimal amt = PXDBCurrencyAttribute.BaseRound(this, amtRaw);

                        ScheduledTran result = new ScheduledTran();

                        result.BranchID    = ad.AdjgBranchID;
                        result.Amount      = amt;
                        result.ComponentID = tr.InventoryID;
                        result.DefCode     = tr.DeferredCode;
                        result.FinPeriodID = FinPeriodRepository.GetPeriodIDFromDate(ad.AdjgDocDate, PXAccess.GetParentOrganizationID(ad.AdjgBranchID));
                        result.LineNbr     = lineNbr;
                        result.Module      = schedule.Module;
                        result.RecDate     = ad.AdjgDocDate;
                        result.ScheduleID  = schedule.ScheduleID;
                        result.ScheduleNbr = schedule.ScheduleNbr;
                        result.DocType     = schedule.DocType;
                        result.AdjgDocType = ad.AdjgDocType;
                        result.AdjgRefNbr  = ad.AdjgRefNbr;
                        result.AdjNbr      = ad.AdjNbr;
                        result.IsVirtual   = true;
                        result.AccountID   = scheduleDetail.AccountID;
                        result.SubID       = scheduleDetail.SubID;
                        result.ComponentCD = invItem == null ? "" : invItem.InventoryCD;

                        if (ad.Voided == true)
                        {
                            if (ad.AdjgDocType == ARDocType.VoidPayment && virtualVoidedRecords.Count > 0)
                            {
                                ScheduledTran tran = virtualVoidedRecords.Where <ScheduledTran>(v => (v.AdjgDocType == ARDocType.Payment && v.AdjgRefNbr == ad.AdjgRefNbr && v.AdjNbr == ad.AdjNbr)).First <ScheduledTran>();
                                if (tran != null)
                                {
                                    virtualVoidedRecords.Remove(tran);
                                }
                            }
                            else
                            {
                                virtualVoidedRecords.Add(result);
                            }
                        }
                        else
                        {
                            virtualRecords.Add(result);
                        }
                    }

                    foreach (ScheduledTran v in virtualRecords)
                    {
                        Items.Cache.SetStatus(v, PXEntryStatus.Inserted);
                        yield return(v);                       // Items.Insert(v);
                    }

                    foreach (ScheduledTran v in virtualVoidedRecords)
                    {
                        Items.Cache.SetStatus(v, PXEntryStatus.Inserted);
                        yield return(v);                       // Items.Insert(v);
                    }
                }
            }


            Items.Cache.IsDirty = false;
        }