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