/// <summary>
        /// Makes visible the group that corresponds to the selected FrequencyType.
        /// </summary>
        public static void SetControlsState(PXCache cache, FSSchedule fsScheduleRow)
        {
            bool isWeekly           = fsScheduleRow.FrequencyType == ID.Schedule_FrequencyType.WEEKLY;
            bool isDaily            = fsScheduleRow.FrequencyType == ID.Schedule_FrequencyType.DAILY;
            bool isMonthly          = fsScheduleRow.FrequencyType == ID.Schedule_FrequencyType.MONTHLY;
            bool isAnnually         = fsScheduleRow.FrequencyType == ID.Schedule_FrequencyType.ANNUAL;
            bool isMonthly2Selected = fsScheduleRow.Monthly2Selected == true;
            bool isMonthly3Selected = fsScheduleRow.Monthly3Selected == true;
            bool isMonthly4Selected = fsScheduleRow.Monthly4Selected == true;

            //Daily Frequency
            PXUIFieldAttribute.SetVisible <FSSchedule.dailyFrequency>(cache, fsScheduleRow, isDaily);
            PXUIFieldAttribute.SetVisible <FSSchedule.days>(cache, fsScheduleRow, isDaily);

            //Weekly Frequency
            PXUIFieldAttribute.SetVisible <FSSchedule.weeklyFrequency>(cache, fsScheduleRow, isWeekly);
            PXUIFieldAttribute.SetVisible <FSSchedule.weeklyOnSun>(cache, fsScheduleRow, isWeekly);
            PXUIFieldAttribute.SetVisible <FSSchedule.weeklyOnMon>(cache, fsScheduleRow, isWeekly);
            PXUIFieldAttribute.SetVisible <FSSchedule.weeklyOnTue>(cache, fsScheduleRow, isWeekly);
            PXUIFieldAttribute.SetVisible <FSSchedule.weeklyOnWed>(cache, fsScheduleRow, isWeekly);
            PXUIFieldAttribute.SetVisible <FSSchedule.weeklyOnThu>(cache, fsScheduleRow, isWeekly);
            PXUIFieldAttribute.SetVisible <FSSchedule.weeklyOnFri>(cache, fsScheduleRow, isWeekly);
            PXUIFieldAttribute.SetVisible <FSSchedule.weeklyOnSat>(cache, fsScheduleRow, isWeekly);
            PXUIFieldAttribute.SetVisible <FSSchedule.weeks>(cache, fsScheduleRow, isWeekly);

            ////Monthly Frequency
            SetMonthlyControlsState(cache, fsScheduleRow);
            PXUIFieldAttribute.SetVisible <FSSchedule.monthlyFrequency>(cache, fsScheduleRow, isMonthly);
            PXUIFieldAttribute.SetVisible <FSSchedule.months>(cache, fsScheduleRow, isMonthly);
            PXUIFieldAttribute.SetVisible <FSSchedule.monthly2Selected>(cache, fsScheduleRow, isMonthly);
            PXUIFieldAttribute.SetVisible <FSSchedule.monthly3Selected>(cache, fsScheduleRow, isMonthly);
            PXUIFieldAttribute.SetVisible <FSSchedule.monthly4Selected>(cache, fsScheduleRow, isMonthly);
            PXUIFieldAttribute.SetVisible <FSSchedule.monthlyRecurrenceType1>(cache, fsScheduleRow, isMonthly);
            PXUIFieldAttribute.SetVisible <FSSchedule.monthlyRecurrenceType2>(cache, fsScheduleRow, isMonthly && isMonthly2Selected);
            PXUIFieldAttribute.SetVisible <FSSchedule.monthlyRecurrenceType3>(cache, fsScheduleRow, isMonthly && isMonthly3Selected);
            PXUIFieldAttribute.SetVisible <FSSchedule.monthlyRecurrenceType4>(cache, fsScheduleRow, isMonthly && isMonthly4Selected);
            PXUIFieldAttribute.SetVisible <FSSchedule.monthlyOnDay1>(cache, fsScheduleRow, isMonthly && fsScheduleRow.MonthlyRecurrenceType1 == ID.Schedule_FrequencyType.DAILY);
            PXUIFieldAttribute.SetVisible <FSSchedule.monthlyOnDay2>(cache, fsScheduleRow, isMonthly && isMonthly2Selected && fsScheduleRow.MonthlyRecurrenceType2 == ID.Schedule_FrequencyType.DAILY);
            PXUIFieldAttribute.SetVisible <FSSchedule.monthlyOnDay3>(cache, fsScheduleRow, isMonthly && isMonthly3Selected && fsScheduleRow.MonthlyRecurrenceType3 == ID.Schedule_FrequencyType.DAILY);
            PXUIFieldAttribute.SetVisible <FSSchedule.monthlyOnDay4>(cache, fsScheduleRow, isMonthly && isMonthly4Selected && fsScheduleRow.MonthlyRecurrenceType4 == ID.Schedule_FrequencyType.DAILY);
            PXUIFieldAttribute.SetVisible <FSSchedule.monthlyOnWeek1>(cache, fsScheduleRow, isMonthly && fsScheduleRow.MonthlyRecurrenceType1 == ID.Schedule_FrequencyType.WEEKLY);
            PXUIFieldAttribute.SetVisible <FSSchedule.monthlyOnWeek2>(cache, fsScheduleRow, isMonthly && isMonthly2Selected && fsScheduleRow.MonthlyRecurrenceType2 == ID.Schedule_FrequencyType.WEEKLY);
            PXUIFieldAttribute.SetVisible <FSSchedule.monthlyOnWeek3>(cache, fsScheduleRow, isMonthly && isMonthly3Selected && fsScheduleRow.MonthlyRecurrenceType3 == ID.Schedule_FrequencyType.WEEKLY);
            PXUIFieldAttribute.SetVisible <FSSchedule.monthlyOnWeek4>(cache, fsScheduleRow, isMonthly && isMonthly4Selected && fsScheduleRow.MonthlyRecurrenceType4 == ID.Schedule_FrequencyType.WEEKLY);
            PXUIFieldAttribute.SetVisible <FSSchedule.monthlyOnDayOfWeek1>(cache, fsScheduleRow, isMonthly && fsScheduleRow.MonthlyRecurrenceType1 == ID.Schedule_FrequencyType.WEEKLY);
            PXUIFieldAttribute.SetVisible <FSSchedule.monthlyOnDayOfWeek2>(cache, fsScheduleRow, isMonthly && isMonthly2Selected && fsScheduleRow.MonthlyRecurrenceType2 == ID.Schedule_FrequencyType.WEEKLY);
            PXUIFieldAttribute.SetVisible <FSSchedule.monthlyOnDayOfWeek3>(cache, fsScheduleRow, isMonthly && isMonthly3Selected && fsScheduleRow.MonthlyRecurrenceType3 == ID.Schedule_FrequencyType.WEEKLY);
            PXUIFieldAttribute.SetVisible <FSSchedule.monthlyOnDayOfWeek4>(cache, fsScheduleRow, isMonthly && isMonthly4Selected && fsScheduleRow.MonthlyRecurrenceType4 == ID.Schedule_FrequencyType.WEEKLY);

            ////Annual Frequency
            PXUIFieldAttribute.SetVisible <FSSchedule.annualFrequency>(cache, fsScheduleRow, isAnnually);
            PXUIFieldAttribute.SetVisible <FSSchedule.years>(cache, fsScheduleRow, isAnnually);
            PXUIFieldAttribute.SetVisible <FSSchedule.annualRecurrenceType>(cache, fsScheduleRow, isAnnually);
            PXUIFieldAttribute.SetVisible <FSSchedule.annualOnDay>(cache, fsScheduleRow, isAnnually && fsScheduleRow.AnnualRecurrenceType == ID.Schedule_FrequencyType.DAILY);
            PXUIFieldAttribute.SetVisible <FSSchedule.annualOnWeek>(cache, fsScheduleRow, isAnnually && fsScheduleRow.AnnualRecurrenceType == ID.Schedule_FrequencyType.WEEKLY);
            PXUIFieldAttribute.SetVisible <FSSchedule.annualOnDayOfWeek>(cache, fsScheduleRow, isAnnually && fsScheduleRow.AnnualRecurrenceType == ID.Schedule_FrequencyType.WEEKLY);
            PXUIFieldAttribute.SetEnabled <FSSchedule.annualOnDay>(cache, fsScheduleRow, isAnnually && fsScheduleRow.AnnualRecurrenceType == ID.Schedule_FrequencyType.DAILY);
            PXUIFieldAttribute.SetEnabled <FSSchedule.annualOnWeek>(cache, fsScheduleRow, isAnnually && fsScheduleRow.AnnualRecurrenceType == ID.Schedule_FrequencyType.WEEKLY);
            PXUIFieldAttribute.SetEnabled <FSSchedule.annualOnDayOfWeek>(cache, fsScheduleRow, isAnnually && fsScheduleRow.AnnualRecurrenceType == ID.Schedule_FrequencyType.WEEKLY);
        }
        /// <summary>
        /// Update an Schedule (lastGeneratedAppointmentDate and lastProcessedDate).
        /// </summary>
        protected void UpdateGeneratedSchedule(int scheduleID, DateTime?toDate, DateTime?lastGeneratedElementDate, FSSchedule fsScheduleRow)
        {
            FSSchedule fsScheduleRowInDB = PXSelect <FSSchedule,
                                                     Where <
                                                         FSSchedule.scheduleID, Equal <Required <FSSchedule.scheduleID> > > >
                                           .SelectSingleBound(this, null, scheduleID);

            if (fsScheduleRowInDB != null)
            {
                if (lastGeneratedElementDate != null || toDate == null)
                {
                    if (fsScheduleRow != null)
                    {
                        fsScheduleRow.LastGeneratedElementDate = lastGeneratedElementDate;
                        fsScheduleRow.NextExecutionDate        = SharedFunctions.GetNextExecution(this.ScheduleSelected.Cache, fsScheduleRow);
                    }

                    PXUpdate <
                        Set <FSSchedule.lastGeneratedElementDate, Required <FSSchedule.lastGeneratedElementDate>,
                             Set <FSSchedule.nextExecutionDate, Required <FSSchedule.nextExecutionDate> > >, FSSchedule,
                        Where <
                            FSSchedule.scheduleID, Equal <Required <FSSchedule.scheduleID> > > >
                    .Update(this, lastGeneratedElementDate, fsScheduleRow.NextExecutionDate, scheduleID);
                }
            }
        }
        protected virtual void _(Events.RowSelected <FSStaffSchedule> e)
        {
            if (e.Row == null)
            {
                return;
            }

            FSStaffSchedule fsStaffScheduleRow = (FSStaffSchedule)e.Row;
            PXCache         cache = e.Cache;

            bool enableExpirationDate = fsStaffScheduleRow.EnableExpirationDate.HasValue ? (bool)fsStaffScheduleRow.EnableExpirationDate : false;

            SetControlsState(cache, fsStaffScheduleRow);

            PXUIFieldAttribute.SetEnabled <FSStaffSchedule.monthly3Selected>(cache, fsStaffScheduleRow, fsStaffScheduleRow.Monthly2Selected == true);
            PXUIFieldAttribute.SetEnabled <FSStaffSchedule.monthly4Selected>(cache, fsStaffScheduleRow, fsStaffScheduleRow.Monthly3Selected == true);
            PXUIFieldAttribute.SetEnabled <FSStaffSchedule.endDate>(cache, fsStaffScheduleRow, enableExpirationDate || IsCopyPasteContext);
            PXDefaultAttribute.SetPersistingCheck <FSStaffSchedule.endDate>(cache,
                                                                            fsStaffScheduleRow,
                                                                            enableExpirationDate ? PXPersistingCheck.NullOrBlank : PXPersistingCheck.Nothing);

            fsStaffScheduleRow.SrvOrdTypeMessage = TX.Messages.SERVICE_ORDER_TYPE_USED_FOR_RECURRING_APPOINTMENTS;
            CheckDates(cache, fsStaffScheduleRow);
            CheckTimes(cache, fsStaffScheduleRow);

            FSSchedule fsScheduleRow = (FSSchedule)e.Row;

            SharedFunctions.SetRecurrenceDescription(fsScheduleRow);

            bool existAnyGenerationProcess = SharedFunctions.ShowWarningScheduleNotProcessed(cache, fsScheduleRow);

            openStaffContractScheduleProcess.SetEnabled(existAnyGenerationProcess == false);
        }
        public static bool TryParse(object row, out FSSchedule fsScheduleRow)
        {
            fsScheduleRow = null;

            if (row is FSSchedule)
            {
                fsScheduleRow = (FSSchedule)row;
                return(true);
            }

            return(false);
        }
        /// <summary>
        /// Return the smallest date between schedule EndDate and Process EndDate.
        /// </summary>
        protected DateTime?GetProcessEndDate(Schedule fsScheduleRule, DateTime?toDate)
        {
            FSSchedule fsScheduleRow = PXSelect <FSSchedule,
                                                 Where <
                                                     FSSchedule.scheduleID, Equal <Required <FSSchedule.scheduleID> > > >
                                       .Select(this, fsScheduleRule.ScheduleID);

            if (fsScheduleRow.EnableExpirationDate == false)
            {
                return(toDate.Value);
            }
            else
            {
                return((fsScheduleRow.EndDate != null && fsScheduleRow.EndDate < toDate) ? fsScheduleRow.EndDate : toDate.Value);
            }
        }
        protected virtual void FSStaffSchedule_RowSelected(PXCache cache, PXRowSelectedEventArgs e)
        {
            if (e.Row == null)
            {
                return;
            }

            FSStaffSchedule fsStaffScheduleRow   = (FSStaffSchedule)e.Row;
            bool            enableExpirationDate = fsStaffScheduleRow.EnableExpirationDate.HasValue ? (bool)fsStaffScheduleRow.EnableExpirationDate : false;
            bool            requireBranchLocationInEmpSchedule = SetupRecord.Current.RequireBranchLocationInEmpSchedule == true;

            SetControlsState(cache, fsStaffScheduleRow);

            PXUIFieldAttribute.SetEnabled <FSStaffSchedule.monthly3Selected>(cache, fsStaffScheduleRow, fsStaffScheduleRow.Monthly2Selected == true);
            PXUIFieldAttribute.SetEnabled <FSStaffSchedule.monthly4Selected>(cache, fsStaffScheduleRow, fsStaffScheduleRow.Monthly3Selected == true);
            PXUIFieldAttribute.SetEnabled <FSStaffSchedule.endDate>(cache, fsStaffScheduleRow, enableExpirationDate || IsCopyPasteContext);
            PXDefaultAttribute.SetPersistingCheck <FSStaffSchedule.endDate>(
                cache,
                fsStaffScheduleRow,
                enableExpirationDate ? PXPersistingCheck.NullOrBlank : PXPersistingCheck.Nothing);
            PXUIFieldAttribute.SetRequired <FSStaffSchedule.branchLocationID>(cache, requireBranchLocationInEmpSchedule);
            PXDefaultAttribute.SetPersistingCheck <FSStaffSchedule.branchLocationID>(
                cache,
                fsStaffScheduleRow,
                requireBranchLocationInEmpSchedule ? PXPersistingCheck.NullOrBlank : PXPersistingCheck.Nothing);

            fsStaffScheduleRow.Days   = TX.RecurrenceDescription.DAYS;
            fsStaffScheduleRow.Weeks  = TX.RecurrenceDescription.WEEKS;
            fsStaffScheduleRow.Months = TX.RecurrenceDescription.MONTHS;
            fsStaffScheduleRow.Years  = TX.RecurrenceDescription.YEARS;

            fsStaffScheduleRow.SrvOrdTypeMessage = TX.Messages.SERVICE_ORDER_TYPE_USED_FOR_RECURRING_APPOINTMENTS;
            CheckDates(cache, fsStaffScheduleRow);
            CheckTimes(cache, fsStaffScheduleRow);

            FSSchedule fsScheduleRow = (FSSchedule)e.Row;

            SharedFunctions.SetRecurrenceDescription(fsScheduleRow);

            bool existAnyGenerationProcess = SharedFunctions.ShowWarningScheduleNotProcessed(cache, fsScheduleRow);

            openStaffContractScheduleProcess.SetEnabled(existAnyGenerationProcess == false);
        }
        public override void openServiceContractScreenByGenerationLogError()
        {
            RouteServiceContractEntry graphServiceContractEntry = PXGraph.CreateInstance <RouteServiceContractEntry>();

            FSSchedule fsScheduleRow = PXSelect <FSSchedule,
                                                 Where <
                                                     FSSchedule.scheduleID, Equal <Required <FSSchedule.scheduleID> > > >
                                       .Select(this, ErrorMessageRecords.Current.ScheduleID);

            FSServiceContract fsServiceContractRow =
                PXSelect <FSServiceContract,
                          Where <FSServiceContract.serviceContractID, Equal <Required <FSServiceContract.serviceContractID> > > >
                .Select(this, fsScheduleRow.EntityID);

            graphServiceContractEntry.ServiceContractRecords.Current = fsServiceContractRow;
            throw new PXRedirectRequiredException(graphServiceContractEntry, null)
                  {
                      Mode = PXBaseRedirectException.WindowMode.NewWindow
                  };
        }
        public static void SetMonthlyControlsState(PXCache cache, FSSchedule fsScheduleRow)
        {
            bool isMonthly = fsScheduleRow.FrequencyType == ID.Schedule_FrequencyType.MONTHLY;

            PXUIFieldAttribute.SetEnabled <FSSchedule.monthlyOnDay1>(cache, fsScheduleRow, isMonthly && fsScheduleRow.MonthlyRecurrenceType1 == ID.Schedule_FrequencyType.DAILY);
            PXUIFieldAttribute.SetEnabled <FSSchedule.monthlyOnWeek1>(cache, fsScheduleRow, isMonthly && fsScheduleRow.MonthlyRecurrenceType1 == ID.Schedule_FrequencyType.WEEKLY);
            PXUIFieldAttribute.SetEnabled <FSSchedule.monthlyOnDayOfWeek1>(cache, fsScheduleRow, isMonthly && fsScheduleRow.MonthlyRecurrenceType1 == ID.Schedule_FrequencyType.WEEKLY);

            PXUIFieldAttribute.SetEnabled <FSSchedule.monthlyOnDay2>(cache, fsScheduleRow, isMonthly && fsScheduleRow.MonthlyRecurrenceType2 == ID.Schedule_FrequencyType.DAILY);
            PXUIFieldAttribute.SetEnabled <FSSchedule.monthlyOnWeek2>(cache, fsScheduleRow, isMonthly && fsScheduleRow.MonthlyRecurrenceType2 == ID.Schedule_FrequencyType.WEEKLY);
            PXUIFieldAttribute.SetEnabled <FSSchedule.monthlyOnDayOfWeek2>(cache, fsScheduleRow, isMonthly && fsScheduleRow.MonthlyRecurrenceType2 == ID.Schedule_FrequencyType.WEEKLY);

            PXUIFieldAttribute.SetEnabled <FSSchedule.monthlyOnDay3>(cache, fsScheduleRow, isMonthly && fsScheduleRow.MonthlyRecurrenceType3 == ID.Schedule_FrequencyType.DAILY);
            PXUIFieldAttribute.SetEnabled <FSSchedule.monthlyOnWeek3>(cache, fsScheduleRow, isMonthly && fsScheduleRow.MonthlyRecurrenceType3 == ID.Schedule_FrequencyType.WEEKLY);
            PXUIFieldAttribute.SetEnabled <FSSchedule.monthlyOnDayOfWeek3>(cache, fsScheduleRow, isMonthly && fsScheduleRow.MonthlyRecurrenceType3 == ID.Schedule_FrequencyType.WEEKLY);

            PXUIFieldAttribute.SetEnabled <FSSchedule.monthlyOnDay4>(cache, fsScheduleRow, isMonthly && fsScheduleRow.MonthlyRecurrenceType4 == ID.Schedule_FrequencyType.DAILY);
            PXUIFieldAttribute.SetEnabled <FSSchedule.monthlyOnWeek4>(cache, fsScheduleRow, isMonthly && fsScheduleRow.MonthlyRecurrenceType4 == ID.Schedule_FrequencyType.WEEKLY);
            PXUIFieldAttribute.SetEnabled <FSSchedule.monthlyOnDayOfWeek4>(cache, fsScheduleRow, isMonthly && fsScheduleRow.MonthlyRecurrenceType4 == ID.Schedule_FrequencyType.WEEKLY);
        }
        public virtual IEnumerable GenerateProjection(PXAdapter adapter)
        {
            if (RouteAppointmentForecastingFilter.Current != null &&
                RouteAppointmentForecastingFilter.Current.DateBegin != null &&
                RouteAppointmentForecastingFilter.Current.DateEnd != null &&
                RouteAppointmentForecastingFilter.Current.DateBegin < RouteAppointmentForecastingFilter.Current.DateEnd)
            {
                DateTime beginFromFilter = RouteAppointmentForecastingFilter.Current.DateBegin.Value;
                DateTime endToFilter     = RouteAppointmentForecastingFilter.Current.DateEnd.Value;
                string   recordType      = ID.RecordType_ServiceContract.ROUTE_SERVICE_CONTRACT;

                int?serviceID          = RouteAppointmentForecastingFilter.Current.ServiceID;
                int?customerID         = RouteAppointmentForecastingFilter.Current.CustomerID;
                int?customerLocationID = RouteAppointmentForecastingFilter.Current.CustomerLocationID;
                int?routeID            = RouteAppointmentForecastingFilter.Current.RouteID;

                PXLongOperation.StartOperation(
                    this,
                    delegate
                {
                    using (PXTransactionScope ts = new PXTransactionScope())
                    {
                        if (beginFromFilter != null && endToFilter != null)
                        {
                            DateHandler requestDate = new DateHandler(endToFilter);

                            var period = new Period((DateTime)beginFromFilter, (DateTime)endToFilter);

                            List <Scheduler.Schedule> scheduleListToProcess = new List <Scheduler.Schedule>();
                            var generator = new TimeSlotGenerator();

                            var fsRouteContractScheduleRecords =
                                PXSelectJoinGroupBy <FSRouteContractSchedule,
                                                     InnerJoin <FSServiceContract,
                                                                On <FSServiceContract.serviceContractID, Equal <FSRouteContractSchedule.entityID> >,
                                                                InnerJoin <FSScheduleRoute,
                                                                           On <FSScheduleRoute.scheduleID, Equal <FSRouteContractSchedule.scheduleID> >,
                                                                           InnerJoin <FSScheduleDet,
                                                                                      On <FSScheduleDet.scheduleID, Equal <FSRouteContractSchedule.scheduleID> > > > >,
                                                     Where <
                                                         FSRouteContractSchedule.entityType, Equal <FSSchedule.entityType.Contract>,
                                                         And <FSServiceContract.recordType, Equal <FSServiceContract.recordType.RouteServiceContract>,
                                                              And <FSRouteContractSchedule.active, Equal <True>,
                                                                   And <FSServiceContract.status, Equal <FSServiceContract.status.Active>,
                                                                        And <FSRouteContractSchedule.startDate, LessEqual <Required <FSRouteContractSchedule.startDate> >,
                                                                             And2 <
                                                                                 Where <
                                                                                     Required <FSScheduleDet.inventoryID>, IsNull,
                                                                                     Or <FSScheduleDet.inventoryID, Equal <Required <FSScheduleDet.inventoryID> > > >,
                                                                                 And2 <
                                                                                     Where <
                                                                                         Required <FSRouteContractSchedule.customerID>, IsNull,
                                                                                         Or <FSRouteContractSchedule.customerID, Equal <Required <FSRouteContractSchedule.customerID> > > >,
                                                                                     And2 <
                                                                                         Where <
                                                                                             Required <FSRouteContractSchedule.customerLocationID>, IsNull,
                                                                                             Or <FSRouteContractSchedule.customerLocationID, Equal <Required <FSRouteContractSchedule.customerLocationID> > > >,
                                                                                         And2 <
                                                                                             Where <
                                                                                                 Required <FSScheduleRoute.dfltRouteID>, IsNull,
                                                                                                 Or <FSScheduleRoute.dfltRouteID, Equal <Required <FSScheduleRoute.dfltRouteID> > > >,
                                                                                             And <
                                                                                                 Where <FSRouteContractSchedule.endDate, IsNull,
                                                                                                        Or <FSRouteContractSchedule.endDate, GreaterEqual <Required <FSRouteContractSchedule.startDate> > > > > > > > > > > > > >,
                                                     Aggregate <
                                                         GroupBy <FSRouteContractSchedule.scheduleID> > >
                                .Select(this, beginFromFilter, serviceID, serviceID, customerID, customerID, customerLocationID, customerLocationID, routeID, routeID, endToFilter);

                            foreach (FSRouteContractSchedule fsRouteContractScheduleRecord in fsRouteContractScheduleRecords)
                            {
                                List <Scheduler.Schedule> mapScheduleResults = MapFSScheduleToSchedule.convertFSScheduleToSchedule(RouteAppointmentForecastingFilter.Cache, fsRouteContractScheduleRecord, endToFilter, recordType);

                                foreach (Scheduler.Schedule mapSchedule in mapScheduleResults)
                                {
                                    scheduleListToProcess.Add(mapSchedule);
                                }
                            }

                            if (recordType == ID.RecordType_ServiceContract.ROUTE_SERVICE_CONTRACT)
                            {
                                foreach (Scheduler.Schedule schedule in scheduleListToProcess)
                                {
                                    schedule.Priority      = (int?)RouteScheduleProcess.SetSchedulePriority(schedule, this);
                                    schedule.RouteInfoList = RouteScheduleProcess.getRouteListFromSchedule(schedule, this);
                                }
                            }

                            List <TimeSlot> timeSlots = generator.GenerateCalendar(period, scheduleListToProcess);

                            var fsRouteAppointmentForecastingRecords =
                                PXSelect <FSRouteAppointmentForecasting,
                                          Where <
                                              FSRouteAppointmentForecasting.startDate, GreaterEqual <Required <FSRouteAppointmentForecasting.startDate> >,
                                              And <
                                                  FSRouteAppointmentForecasting.startDate, LessEqual <Required <FSRouteAppointmentForecasting.startDate> > > > >
                                .Select(this, beginFromFilter, endToFilter);

                            PXCache <FSRouteAppointmentForecasting> cacheRouteForecasting = new PXCache <FSRouteAppointmentForecasting>(this);

                            foreach (FSRouteAppointmentForecasting fsRouteAppointmentDetailProjectionRecord in fsRouteAppointmentForecastingRecords)
                            {
                                cacheRouteForecasting.PersistDeleted(fsRouteAppointmentDetailProjectionRecord);
                            }

                            foreach (TimeSlot timeSlot in timeSlots)
                            {
                                requestDate.setDate(timeSlot.DateTimeBegin);

                                FSSchedule fsScheduleRow = ScheduleSelected.Select(timeSlot.ScheduleID);

                                FSScheduleRoute fsScheduleRouteRow = ScheduleRouteSelected.Select(fsScheduleRow.ScheduleID);

                                FSServiceContract fsServiceContractRow = ServiceContractSelected.Select(fsScheduleRow.EntityID);

                                FSRouteAppointmentForecasting fsRouteAppointmentForecastingRow = new FSRouteAppointmentForecasting();

                                fsRouteAppointmentForecastingRow.RouteID            = fsScheduleRouteRow.DfltRouteID;
                                fsRouteAppointmentForecastingRow.StartDate          = requestDate.StartOfDay();
                                fsRouteAppointmentForecastingRow.ScheduleID         = fsScheduleRow.ScheduleID;
                                fsRouteAppointmentForecastingRow.ServiceContractID  = fsServiceContractRow.ServiceContractID;
                                fsRouteAppointmentForecastingRow.CustomerLocationID = fsServiceContractRow.CustomerLocationID;
                                fsRouteAppointmentForecastingRow.CustomerID         = fsServiceContractRow.CustomerID;
                                fsRouteAppointmentForecastingRow.SequenceOrder      = int.Parse(fsScheduleRouteRow.GlobalSequence);

                                cacheRouteForecasting.PersistInserted(fsRouteAppointmentForecastingRow);
                            }
                        }

                        ts.Complete();
                    }
                });
            }

            return(adapter.Get());
        }
        /// <summary>
        /// Create a Service Order from a TimeSlot.
        /// </summary>
        protected void CreateServiceOrder(TimeSlot timeSlotServiceOrder, bool createAppointmentFlag = false, bool appointmentsBelongToRoute = false)
        {
            // This action allows to avoid errors related to cache
            if (graphServiceOrderEntry != null)
            {
                graphServiceOrderEntry.Clear(PXClearOption.ClearAll);
            }
            else
            {
                graphServiceOrderEntry = PXGraph.CreateInstance <ServiceOrderEntry>();
                graphServiceOrderEntry.DisableServiceOrderUnboundFieldCalc = true;
            }

            FSSchedule        fsScheduleRow        = ScheduleSelected.Select(timeSlotServiceOrder.ScheduleID);
            FSServiceContract fsServiceContractRow = ServiceContractSelected.Select(fsScheduleRow.EntityID);

            bool isPrepaidContract = fsServiceContractRow.BillingType == ID.Contract_BillingType.STANDARDIZED_BILLINGS;

            //Services from the Schedule
            var fsScheduleDetSet = ScheduleLinesSelected.Select(timeSlotServiceOrder.ScheduleID);

            //Templates from the Schedule
            var fsScheduleDetTemplateSet = ScheduleTemplatesSelected.Select(timeSlotServiceOrder.ScheduleID);

            FSServiceOrder fsServiceOrderRow = new FSServiceOrder();

            fsServiceOrderRow.SrvOrdType = fsScheduleRow.SrvOrdType;
            graphServiceOrderEntry.ServiceOrderRecords.Insert(fsServiceOrderRow);

            fsServiceOrderRow = graphServiceOrderEntry.ServiceOrderRecords.Cache.CreateCopy(graphServiceOrderEntry.ServiceOrderRecords.Current) as FSServiceOrder;

            fsServiceOrderRow.BranchID         = fsScheduleRow.BranchID;
            fsServiceOrderRow.BranchLocationID = fsScheduleRow.BranchLocationID;
            fsServiceOrderRow.OrderDate        = timeSlotServiceOrder.DateTimeBegin.Date;
            fsServiceOrderRow.CustomerID       = fsServiceContractRow.CustomerID;
            fsServiceOrderRow.LocationID       = fsScheduleRow.CustomerLocationID;

            graphServiceOrderEntry.ServiceOrderRecords.Update(fsServiceOrderRow);
            fsServiceOrderRow = graphServiceOrderEntry.ServiceOrderRecords.Cache.CreateCopy(graphServiceOrderEntry.ServiceOrderRecords.Current) as FSServiceOrder;

            // Currently Service-Management's contracts DO NOT support multi-currency specification
            // therefore their ServiceOrders MUST be created in customer base currency
            if (PXAccess.FeatureInstalled <FeaturesSet.multicurrency>())
            {
                string curyID = null;

                Customer customer = (Customer)PXSelect <Customer,
                                                        Where <Customer.bAccountID, Equal <Required <Customer.bAccountID> > > >
                                    .Select(this, fsServiceContractRow.CustomerID);

                if (customer != null)
                {
                    curyID = customer.CuryID;
                }

                if (string.IsNullOrEmpty(curyID) == true)
                {
                    curyID = this.Accessinfo.BaseCuryID ?? new PXSetup <PX.Objects.GL.Company>(this).Current?.BaseCuryID;
                }

                fsServiceOrderRow.CuryID = curyID;
            }

            fsServiceOrderRow.DocDesc           = timeSlotServiceOrder.Descr;
            fsServiceOrderRow.BillCustomerID    = fsServiceContractRow.BillCustomerID;
            fsServiceOrderRow.BillLocationID    = fsServiceContractRow.BillLocationID;
            fsServiceOrderRow.ServiceContractID = fsServiceContractRow.ServiceContractID;
            fsServiceOrderRow.ProjectID         = fsServiceContractRow.ProjectID;
            fsServiceOrderRow.DfltProjectTaskID = fsServiceContractRow.DfltProjectTaskID;

            if (isPrepaidContract == true &&
                graphServiceOrderEntry.BillingCycleRelated.Current != null &&
                graphServiceOrderEntry.BillingCycleRelated.Current.BillingBy == ID.Billing_By.SERVICE_ORDER)
            {
                fsServiceOrderRow.BillServiceContractID = fsServiceContractRow.ServiceContractID;
            }

            fsServiceOrderRow.ScheduleID        = timeSlotServiceOrder.ScheduleID;
            fsServiceOrderRow.ServiceContractID = fsServiceContractRow.ServiceContractID;
            fsServiceOrderRow.GenerationID      = timeSlotServiceOrder.GenerationID;

            fsServiceOrderRow.SalesPersonID  = fsServiceContractRow.SalesPersonID;
            fsServiceOrderRow.Commissionable = fsServiceContractRow.Commissionable;

            fsServiceOrderRow = graphServiceOrderEntry.ServiceOrderRecords.Update(fsServiceOrderRow);

            if (fsServiceOrderRow.SalesPersonID == null)
            {
                object salesPersonID;
                graphServiceOrderEntry.ServiceOrderRecords.Cache.RaiseFieldDefaulting <FSServiceOrder.salesPersonID>(fsServiceOrderRow, out salesPersonID);
                fsServiceOrderRow.SalesPersonID = (int?)salesPersonID;

                object commissionable;
                graphServiceOrderEntry.ServiceOrderRecords.Cache.RaiseFieldDefaulting <FSServiceOrder.commissionable>(fsServiceOrderRow, out commissionable);
                fsServiceOrderRow.Commissionable = (bool?)commissionable;
            }

            graphServiceOrderEntry.Answers.CopyAllAttributes(fsServiceOrderRow, fsScheduleRow);

            #region Setting Service Order Details
            foreach (FSScheduleDet fsScheduleDetRow in fsScheduleDetSet)
            {
                if (fsScheduleDetRow.LineType == ID.LineType_ServiceContract.SERVICE_TEMPLATE)
                {
                    foreach (FSScheduleDet fsScheduleDetLocalRow in fsScheduleDetTemplateSet.Where(x => ((FSScheduleDet)x).ServiceTemplateID == fsScheduleDetRow.ServiceTemplateID))
                    {
                        var fsServiceTemplateDetSet_Service = ServiceTemplateSelected.Select(fsScheduleDetRow.ServiceTemplateID);

                        foreach (FSServiceTemplateDet fsServiceTemplateDetRow_Service in fsServiceTemplateDetSet_Service)
                        {
                            FSSODet fsSODetRow = new FSSODet();

                            // Insert the new row with key fields
                            fsSODetRow.ScheduleID    = fsScheduleDetLocalRow.ScheduleID;
                            fsSODetRow.ScheduleDetID = fsScheduleDetLocalRow.ScheduleDetID;
                            fsSODetRow.LineType      = fsServiceTemplateDetRow_Service.LineType;

                            fsSODetRow = graphServiceOrderEntry.ServiceOrderDetails.Insert(fsSODetRow);

                            fsSODetRow.InventoryID = fsServiceTemplateDetRow_Service.InventoryID;

                            fsSODetRow = graphServiceOrderEntry.ServiceOrderDetails.Update(fsSODetRow);

                            PXNoteAttribute.CopyNoteAndFiles(ScheduleLinesSelected.Cache,
                                                             fsScheduleDetLocalRow,
                                                             graphServiceOrderEntry.ServiceOrderDetails.Cache,
                                                             fsSODetRow,
                                                             copyNotes: true,
                                                             copyFiles: true);

                            // Create a copy to update the other fields
                            fsSODetRow = (FSSODet)graphServiceOrderEntry.ServiceOrderDetails.Cache.CreateCopy(fsSODetRow);

                            fsSODetRow.TranDesc = fsServiceTemplateDetRow_Service.TranDesc;

                            InventoryItem inventoryItemRow = SharedFunctions.GetInventoryItemRow(this, fsServiceTemplateDetRow_Service.InventoryID);

                            if (inventoryItemRow != null)
                            {
                                FSxService fsxServiceRow = PXCache <InventoryItem> .GetExtension <FSxService>(inventoryItemRow);

                                if (fsxServiceRow != null && fsxServiceRow.BillingRule == ID.BillingRule.TIME)
                                {
                                    int?estimatedDuration = CalculateEstimatedDuration(fsSODetRow, fsServiceTemplateDetRow_Service.Qty);
                                    fsSODetRow.EstimatedDuration = estimatedDuration;
                                }
                                else
                                {
                                    fsSODetRow.EstimatedQty = fsServiceTemplateDetRow_Service.Qty;
                                }
                            }

                            if (fsServiceContractRow.SourcePrice == ID.SourcePrice.CONTRACT)
                            {
                                fsSODetRow.ManualPrice = true;
                                // TODO: Check where is assigned the contract price?
                            }

                            if (createAppointmentFlag)
                            {
                                fsSODetRow.Scheduled = true;
                                fsSODetRow.Status    = ID.Status_SODet.SCHEDULED;
                            }

                            fsSODetRow.EquipmentAction  = fsScheduleDetRow.EquipmentAction;
                            fsSODetRow.SMEquipmentID    = fsScheduleDetRow.SMEquipmentID;
                            fsSODetRow.ComponentID      = fsScheduleDetRow.ComponentID;
                            fsSODetRow.EquipmentLineRef = fsScheduleDetRow.EquipmentLineRef;
                            fsSODetRow.ProjectTaskID    = fsScheduleDetRow.ProjectTaskID;
                            fsSODetRow.CostCodeID       = fsScheduleDetRow.CostCodeID;

                            if (fsSODetRow.InventoryID != null)
                            {
                                fsSODetRow.ProjectTaskID = fsScheduleDetRow.ProjectTaskID;
                                fsSODetRow.CostCodeID    = fsScheduleDetRow.CostCodeID;
                            }

                            graphServiceOrderEntry.ServiceOrderDetails.Update(fsSODetRow);
                        }
                    }
                }
                else
                {
                    FSSODet fsSODetRow = new FSSODet();

                    // Insert the new row with key fields
                    fsSODetRow.ScheduleID    = fsScheduleDetRow.ScheduleID;
                    fsSODetRow.ScheduleDetID = fsScheduleDetRow.ScheduleDetID;
                    fsSODetRow.LineType      = fsScheduleDetRow.LineType;

                    fsSODetRow = graphServiceOrderEntry.ServiceOrderDetails.Insert(fsSODetRow);

                    fsSODetRow.InventoryID = fsScheduleDetRow.InventoryID;

                    fsSODetRow = graphServiceOrderEntry.ServiceOrderDetails.Update(fsSODetRow);

                    PXNoteAttribute.CopyNoteAndFiles(ScheduleLinesSelected.Cache,
                                                     fsScheduleDetRow,
                                                     graphServiceOrderEntry.ServiceOrderDetails.Cache,
                                                     fsSODetRow,
                                                     copyNotes: true,
                                                     copyFiles: true);

                    // Create a copy to update the other fields
                    fsSODetRow = (FSSODet)graphServiceOrderEntry.ServiceOrderDetails.Cache.CreateCopy(fsSODetRow);

                    fsSODetRow.TranDesc    = fsScheduleDetRow.TranDesc;
                    fsSODetRow.BillingRule = fsScheduleDetRow.BillingRule;

                    if (fsSODetRow.BillingRule == ID.BillingRule.TIME)
                    {
                        int?estimatedDuration = CalculateEstimatedDuration(fsSODetRow, fsScheduleDetRow?.Qty);
                        fsSODetRow.EstimatedDuration = estimatedDuration;
                    }
                    else
                    {
                        fsSODetRow.EstimatedQty = fsScheduleDetRow.Qty;
                    }

                    if (fsServiceContractRow.SourcePrice == ID.SourcePrice.CONTRACT)
                    {
                        fsSODetRow.ManualPrice = true;
                        // TODO: AC-142850 Check where is assigned the contract price?
                    }

                    if (createAppointmentFlag)
                    {
                        fsSODetRow.Scheduled = true;
                        fsSODetRow.Status    = ID.Status_SODet.SCHEDULED;
                    }

                    fsSODetRow.EquipmentAction  = fsScheduleDetRow.EquipmentAction;
                    fsSODetRow.SMEquipmentID    = fsScheduleDetRow.SMEquipmentID;
                    fsSODetRow.ComponentID      = fsScheduleDetRow.ComponentID;
                    fsSODetRow.EquipmentLineRef = fsScheduleDetRow.EquipmentLineRef;
                    fsSODetRow.ProjectTaskID    = fsScheduleDetRow.ProjectTaskID;
                    fsSODetRow.CostCodeID       = fsScheduleDetRow.CostCodeID;

                    if (fsSODetRow.InventoryID != null)
                    {
                        fsSODetRow.ProjectTaskID = fsScheduleDetRow.ProjectTaskID;
                        fsSODetRow.CostCodeID    = fsScheduleDetRow.CostCodeID;
                    }

                    graphServiceOrderEntry.ServiceOrderDetails.Update(fsSODetRow);
                }
            }

            if (fsScheduleRow.VendorID != null)
            {
                FSSOEmployee fsSOEmployeeRow = new FSSOEmployee();
                fsSOEmployeeRow.EmployeeID = fsScheduleRow.VendorID;
                graphServiceOrderEntry.ServiceOrderEmployees.Insert(fsSOEmployeeRow);
            }

            #endregion

            graphServiceOrderEntry.Save.Press();

            if (createAppointmentFlag)
            {
                string origStatus = graphServiceOrderEntry.ServiceOrderRecords.Current.Status;

                if (origStatus != ID.Status_ServiceOrder.OPEN)
                {
                    //Due to FSAppointment.sORefNbr selector, Service Order status must be OPEN to allow the SetValueExt<SORefNbr> inside createAppointment() work properly.
                    //PXUpdate is used to avoid raising any ServiceOrderEntry event.
                    PXUpdate <
                        Set <FSServiceOrder.status, FSServiceOrder.status.Open>,
                        FSServiceOrder,
                        Where <
                            FSServiceOrder.sOID, Equal <Required <FSServiceOrder.sOID> > > >
                    .Update(this, graphServiceOrderEntry.ServiceOrderRecords.Current.SOID);
                }

                CreateAppointment(graphServiceOrderEntry.ServiceOrderRecords.Current, timeSlotServiceOrder, fsScheduleRow, true, appointmentsBelongToRoute, isPrepaidContract);

                if (origStatus != ID.Status_ServiceOrder.OPEN)
                {
                    PXUpdate <
                        Set <FSServiceOrder.status, Required <FSServiceOrder.status> >,
                        FSServiceOrder,
                        Where <
                            FSServiceOrder.sOID, Equal <Required <FSServiceOrder.sOID> > > >
                    .Update(this, origStatus, graphServiceOrderEntry.ServiceOrderRecords.Current.SOID);
                }
            }
        }
        /// <summary>
        /// Generates Appointments (Routes Contract) or Service Orders (Service Contract) for each TimeSlot in the [scheduleRules] List.
        /// </summary>
        public void GenerateAPPSOUpdateContracts(List <Schedule> scheduleRules, string recordType, DateTime?fromDate, DateTime?toDate, FSSchedule fsScheduleRow)
        {
            var      generator      = new TimeSlotGenerator();
            DateTime processEndDate = (DateTime)GetProcessEndDate(scheduleRules.ElementAt(0), toDate);

            var period = new Period((DateTime)fromDate, processEndDate);

            // Determines the next generationID number
            if (nextGenerationID == null)
            {
                FSProcessIdentity fsProcessIdentityRow = new FSProcessIdentity();
                fsProcessIdentityRow.ProcessType  = recordType;
                fsProcessIdentityRow.FilterFromTo = fromDate;
                fsProcessIdentityRow.FilterUpTo   = toDate;

                ProcessIdentityMaint graphProcessIdentityMaint = PXGraph.CreateInstance <ProcessIdentityMaint>();
                graphProcessIdentityMaint.processIdentityRecords.Insert(fsProcessIdentityRow);
                graphProcessIdentityMaint.Save.Press();

                nextGenerationID = graphProcessIdentityMaint.processIdentityRecords.Current.ProcessID;
            }

            List <TimeSlot> timeSlots   = generator.GenerateCalendar(period, scheduleRules, nextGenerationID);
            DateTime?       failsOnDate = null;

            // Transaction to create the appointments (Routes Contract) or Service Orders (Service Contract)
            using (PXTransactionScope ts = new PXTransactionScope())
            {
                Customer customerRow = PXSelect <Customer,
                                                 Where <
                                                     Customer.bAccountID, Equal <Required <Customer.bAccountID> > > >
                                       .Select(this, fsScheduleRow.CustomerID)
                                       .FirstOrDefault();

                if (customerRow.Status != BAccount.status.Active && customerRow.Status != BAccount.status.OneTime)
                {
                    throw new PXException(PXMessages.LocalizeFormat(AR.Messages.CustomerIsInStatus, new Customer.status.ListAttribute().ValueLabelDic[customerRow.Status]));
                }

                try
                {
                    foreach (var timeSlot in timeSlots)
                    {
                        failsOnDate = timeSlot.DateTimeBegin;

                        if (recordType == ID.RecordType_ServiceContract.SERVICE_CONTRACT)
                        {
                            bool createAppointmnet = fsScheduleRow.ScheduleGenType == ID.ScheduleGenType_ServiceContract.APPOINTMENT;

                            CreateServiceOrder(timeSlot, createAppointmnet);
                        }
                        else if (recordType == ID.RecordType_ServiceContract.ROUTE_SERVICE_CONTRACT)
                        {
                            CreateServiceOrder(timeSlot, true, true);
                        }
                    }

                    DateTime?lastGenerationDate = null;

                    if (timeSlots.Count > 0)
                    {
                        lastGenerationDate = timeSlots.Max(a => a.DateTimeBegin);
                    }

                    CreateContractGenerationHistory((int)nextGenerationID,
                                                    scheduleRules.ElementAt(0).ScheduleID,
                                                    processEndDate,
                                                    lastGenerationDate,
                                                    recordType);

                    UpdateGeneratedSchedule(scheduleRules.ElementAt(0).ScheduleID, processEndDate, lastGenerationDate, fsScheduleRow);
                }
                catch (Exception e)
                {
                    var exceptionWithContextMessage = ExceptionHelper.GetExceptionWithContextMessage(PXMessages.Localize(TX.Messages.COULD_NOT_PROCESS_RECORD), e);

                    FSGenerationLogError fsGenerationLogErrorRow = new FSGenerationLogError();
                    fsGenerationLogErrorRow.ProcessType  = recordType;
                    fsGenerationLogErrorRow.ErrorMessage = exceptionWithContextMessage.Message;
                    fsGenerationLogErrorRow.ScheduleID   = scheduleRules.ElementAt(0).ScheduleID;
                    fsGenerationLogErrorRow.GenerationID = nextGenerationID;
                    fsGenerationLogErrorRow.ErrorDate    = failsOnDate;

                    ts.Dispose();

                    var grapGenerationLogErrorMaint = PXGraph.CreateInstance <GenerationLogErrorMaint>();

                    grapGenerationLogErrorMaint.LogErrorMessageRecords.Insert(fsGenerationLogErrorRow);
                    grapGenerationLogErrorMaint.Save.Press();
                    throw exceptionWithContextMessage;
                }

                ts.Complete(this);
            }
        }
        /// <summary>
        /// Create an Appointment from a TimeSlot.
        /// </summary>
        protected void CreateAppointment(FSServiceOrder fsServiceOrderRow,
                                         TimeSlot timeSlotAppointment,
                                         FSSchedule fsScheduleRow,
                                         bool insertingFromServiceOrder,
                                         bool isARouteAppointment,
                                         bool isPrepaidContract)
        {
            if (graphAppointmentEntry != null)
            {
                graphAppointmentEntry.Clear(PXClearOption.ClearAll);
            }
            else
            {
                graphAppointmentEntry = PXGraph.CreateInstance <AppointmentEntry>();
                graphAppointmentEntry.CalculateGoogleStats                = false;
                graphAppointmentEntry.AvoidCalculateRouteStats            = true;
                graphAppointmentEntry.IsGeneratingAppointment             = true;
                graphAppointmentEntry.DisableServiceOrderUnboundFieldCalc = true;
            }

            graphAppointmentEntry.SkipManualTimeFlagUpdate = true;

            FSScheduleRoute fsScheduleRouteRow = null;

            if (isARouteAppointment == true)
            {
                fsScheduleRouteRow = PXSelect <FSScheduleRoute,
                                               Where <
                                                   FSScheduleRoute.scheduleID, Equal <Required <FSScheduleRoute.scheduleID> > > >
                                     .Select(this, fsServiceOrderRow.ScheduleID);
            }

            FSAppointment fsAppointmentRow = new FSAppointment();

            fsAppointmentRow.SrvOrdType = fsServiceOrderRow.SrvOrdType;

            #region Setting flags for recurring appointments
            fsAppointmentRow.ValidatedByDispatcher = false;
            fsAppointmentRow.GeneratedBySystem     = true;
            fsAppointmentRow.Status = ID.Status_Appointment.AUTOMATIC_SCHEDULED;

            fsAppointmentRow = graphAppointmentEntry.AppointmentRecords.Insert(fsAppointmentRow);

            graphAppointmentEntry.AppointmentRecords.SetValueExt <FSAppointment.soRefNbr>(graphAppointmentEntry.AppointmentRecords.Current, fsServiceOrderRow.RefNbr);
            graphAppointmentEntry.AppointmentRecords.Cache.SetValueExt <FSAppointment.docDesc>(fsAppointmentRow, fsServiceOrderRow.DocDesc);

            if (isARouteAppointment)
            {
                graphAppointmentEntry.AppointmentRecords.Cache.SetValueExt <FSAppointment.scheduledDateTimeBegin>(fsAppointmentRow, timeSlotAppointment.DateTimeBegin);
                graphAppointmentEntry.AppointmentRecords.Cache.SetValueExt <FSAppointment.scheduledDateTimeEnd>(fsAppointmentRow, timeSlotAppointment.DateTimeEnd);
            }
            else
            {
                DateTime?scheduledDateTimeBegin = PXDBDateAndTimeAttribute.CombineDateTime(timeSlotAppointment.DateTimeBegin, fsScheduleRow.ScheduleStartTime);
                graphAppointmentEntry.AppointmentRecords.Cache.SetValueExt <FSAppointment.scheduledDateTimeBegin>(fsAppointmentRow, scheduledDateTimeBegin);
            }

            graphAppointmentEntry.AppointmentRecords.Cache.SetValueExt <FSAppointment.serviceContractID>(fsAppointmentRow, fsServiceOrderRow.ServiceContractID);

            if (isPrepaidContract == true &&
                graphAppointmentEntry.BillingCycleRelated.Current != null &&
                graphAppointmentEntry.BillingCycleRelated.Current.BillingBy == ID.Billing_By.APPOINTMENT)
            {
                graphAppointmentEntry.AppointmentRecords.Cache.SetValueExt <FSAppointment.billServiceContractID>(fsAppointmentRow, fsServiceOrderRow.ServiceContractID);
            }

            fsAppointmentRow = graphAppointmentEntry.AppointmentRecords.Current;

            //Total times get initialized
            fsAppointmentRow.EstimatedDurationTotal = 0;
            fsAppointmentRow.ActualDurationTotal    = 0;

            fsAppointmentRow.ScheduleID        = fsServiceOrderRow.ScheduleID;
            fsAppointmentRow.ServiceContractID = fsServiceOrderRow.ServiceContractID;
            fsAppointmentRow.GenerationID      = fsServiceOrderRow.GenerationID;

            fsAppointmentRow.SalesPersonID  = fsServiceOrderRow.SalesPersonID;
            fsAppointmentRow.Commissionable = fsServiceOrderRow.Commissionable;
            #endregion

            #region Setting route
            if (fsScheduleRouteRow != null)
            {
                switch (timeSlotAppointment.DateTimeBegin.DayOfWeek)
                {
                case DayOfWeek.Sunday:
                    if (fsScheduleRouteRow.RouteIDSunday != null)
                    {
                        fsAppointmentRow.RouteID = fsScheduleRouteRow.RouteIDSunday;
                    }

                    break;

                case DayOfWeek.Monday:
                    if (fsScheduleRouteRow.RouteIDMonday != null)
                    {
                        fsAppointmentRow.RouteID = fsScheduleRouteRow.RouteIDMonday;
                    }

                    break;

                case DayOfWeek.Tuesday:
                    if (fsScheduleRouteRow.RouteIDTuesday != null)
                    {
                        fsAppointmentRow.RouteID = fsScheduleRouteRow.RouteIDTuesday;
                    }

                    break;

                case DayOfWeek.Wednesday:
                    if (fsScheduleRouteRow.RouteIDWednesday != null)
                    {
                        fsAppointmentRow.RouteID = fsScheduleRouteRow.RouteIDWednesday;
                    }

                    break;

                case DayOfWeek.Thursday:
                    if (fsScheduleRouteRow.RouteIDThursday != null)
                    {
                        fsAppointmentRow.RouteID = fsScheduleRouteRow.RouteIDThursday;
                    }

                    break;

                case DayOfWeek.Friday:
                    if (fsScheduleRouteRow.RouteIDFriday != null)
                    {
                        fsAppointmentRow.RouteID = fsScheduleRouteRow.RouteIDFriday;
                    }

                    break;

                case DayOfWeek.Saturday:
                    if (fsScheduleRouteRow.RouteIDSaturday != null)
                    {
                        fsAppointmentRow.RouteID = fsScheduleRouteRow.RouteIDSaturday;
                    }

                    break;
                }

                if (fsAppointmentRow.RouteID == null)
                {
                    fsAppointmentRow.RouteID = fsScheduleRouteRow.DfltRouteID;
                }

                fsAppointmentRow.RoutePosition = int.Parse(fsScheduleRouteRow.GlobalSequence);

                if (fsAppointmentRow.DeliveryNotes == null)
                {
                    fsAppointmentRow.DeliveryNotes = fsScheduleRouteRow.DeliveryNotes;
                }
            }
            #endregion

            #region Setting Appointment Details
            foreach (FSSODet fsSODetRow in graphServiceOrderEntry.ServiceOrderDetails.Select())
            {
                var fsAppointmentDetRow = new FSAppointmentDet();

                fsAppointmentDetRow.ScheduleID    = fsSODetRow.ScheduleID;
                fsAppointmentDetRow.ScheduleDetID = fsSODetRow.ScheduleDetID;

                AppointmentEntry.InsertDetailLine <FSAppointmentDet, FSSODet>(graphAppointmentEntry.AppointmentDetails.Cache,
                                                                              fsAppointmentDetRow,
                                                                              graphServiceOrderEntry.ServiceOrderDetails.Cache,
                                                                              fsSODetRow,
                                                                              fsSODetRow.NoteID,
                                                                              fsSODetRow.SODetID,
                                                                              copyTranDate: false,
                                                                              tranDate: fsSODetRow.TranDate,
                                                                              SetValuesAfterAssigningSODetID: false,
                                                                              copyingFromQuote: false);
            }

            foreach (FSSOEmployee fsSOEmployeeRow in graphServiceOrderEntry.ServiceOrderEmployees.Select())
            {
                FSAppointmentEmployee fsAppointmentEmployeeRow = new FSAppointmentEmployee();
                fsAppointmentEmployeeRow.EmployeeID = fsSOEmployeeRow.EmployeeID;
                graphAppointmentEntry.AppointmentServiceEmployees.Insert(fsAppointmentEmployeeRow);
            }
            #endregion

            if (fsScheduleRow.VendorID != null)
            {
                FSAppointmentEmployee fsAppointmentEmployeeRow = new FSAppointmentEmployee();
                fsAppointmentEmployeeRow.EmployeeID = fsScheduleRow.VendorID;
                graphAppointmentEntry.AppointmentServiceEmployees.Insert(fsAppointmentEmployeeRow);
            }

            graphAppointmentEntry.Save.Press();
        }
예제 #13
0
        /// <summary>
        /// Generates an FSTimeSlot for each TimeSlot in the [scheduleRules] List.
        /// </summary>
        protected void generateTimeSlotAndUpdateStaffSchedule(List <Schedule> scheduleRules, string recordType, DateTime?fromDate, DateTime?toDate, FSSchedule fsScheduleRow)
        {
            var      generator      = new TimeSlotGenerator();
            DateTime processEndDate = (DateTime)getProcessEndDate(scheduleRules.ElementAt(0), toDate);

            var period = new Period((DateTime)fromDate, (DateTime)toDate);

            // Determines the next generationID number
            if (nextGenerationID == null)
            {
                FSProcessIdentity fsProcessIdentityRow = new FSProcessIdentity()
                {
                    ProcessType  = recordType,
                    FilterFromTo = fromDate,
                    FilterUpTo   = toDate
                };
                var graphProcessIdentityMaint = PXGraph.CreateInstance <ProcessIdentityMaint>();

                graphProcessIdentityMaint.processIdentityRecords.Insert(fsProcessIdentityRow);

                graphProcessIdentityMaint.Save.Press();

                nextGenerationID = graphProcessIdentityMaint.processIdentityRecords.Current.ProcessID;
            }

            List <TimeSlot> timeSlots   = generator.GenerateCalendar(period, scheduleRules, nextGenerationID);
            DateTime?       failsOnDate = null;

            // Transaction to create the Time Slots
            using (PXTransactionScope ts = new PXTransactionScope())
            {
                try
                {
                    //Create all time slots
                    foreach (var timeSlot in timeSlots)
                    {
                        failsOnDate = timeSlot.DateTimeBegin;
                        createTimeSlot(timeSlot);
                    }

                    DateTime?lastGeneratedTimeSlotBySchedules = null;

                    if (timeSlots.Count > 0)
                    {
                        lastGeneratedTimeSlotBySchedules = timeSlots.Max(a => a.DateTimeBegin);
                    }

                    //Update and create a Contract Generation History
                    createContractGenerationHistory(
                        (int)nextGenerationID,
                        scheduleRules.ElementAt(0).ScheduleID,
                        processEndDate,
                        lastGeneratedTimeSlotBySchedules,
                        recordType);

                    //Update Last Generated Time Slot Date
                    updateGeneratedSchedule(scheduleRules.ElementAt(0).ScheduleID, processEndDate, lastGeneratedTimeSlotBySchedules, fsScheduleRow);
                }
                catch (PXException e)
                {
                    FSGenerationLogError fsGenerationLogError = new FSGenerationLogError()
                    {
                        ProcessType  = recordType,
                        ErrorMessage = e.Message,
                        ScheduleID   = scheduleRules.ElementAt(0).ScheduleID,
                        GenerationID = nextGenerationID,
                        ErrorDate    = failsOnDate
                    };
                    ts.Dispose();

                    var grapGenerationLogErrorMaint = PXGraph.CreateInstance <GenerationLogErrorMaint>();

                    grapGenerationLogErrorMaint.LogErrorMessageRecords.Insert(fsGenerationLogError);

                    grapGenerationLogErrorMaint.Save.Press();

                    throw new PXException(e.Message);
                }

                ts.Complete(this);
            }
        }