public static void InsertFSSODetFromOpportunity(ServiceOrderEntry graphServiceOrder, PXCache cacheOpportunityProducts, CRSetup crSetupRow, CROpportunityProducts crOpportunityProductRow, FSxCROpportunityProducts fsxCROpportunityProductsRow, InventoryItem inventoryItemRow) { if (graphServiceOrder == null || crOpportunityProductRow == null || fsxCROpportunityProductsRow == null || inventoryItemRow == null) { return; } if (inventoryItemRow.StkItem == true) { //Insert a new SODet line FSSODetPart fsSODetPartRow = new FSSODetPart(); UpdateFSSODetFromOpportunity(graphServiceOrder.ServiceOrderDetParts.Cache, fsSODetPartRow, crOpportunityProductRow, fsxCROpportunityProductsRow, SharedFunctions.GetLineTypeFromInventoryItem(inventoryItemRow)); SharedFunctions.CopyNotesAndFiles(cacheOpportunityProducts, graphServiceOrder.ServiceOrderDetParts.Cache, crOpportunityProductRow, graphServiceOrder.ServiceOrderDetParts.Current, crSetupRow.CopyNotes, crSetupRow.CopyFiles); } else { //Insert a new SODet line FSSODetService fsSODetServiceRow = new FSSODetService(); UpdateFSSODetFromOpportunity(graphServiceOrder.ServiceOrderDetServices.Cache, fsSODetServiceRow, crOpportunityProductRow, fsxCROpportunityProductsRow, SharedFunctions.GetLineTypeFromInventoryItem(inventoryItemRow)); SharedFunctions.CopyNotesAndFiles(cacheOpportunityProducts, graphServiceOrder.ServiceOrderDetServices.Cache, crOpportunityProductRow, graphServiceOrder.ServiceOrderDetServices.Current, crSetupRow.CopyNotes, crSetupRow.CopyFiles); } }
/// <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 fsScheduleDetServiceSet = ScheduleServicesSelected.Select(timeSlotServiceOrder.ScheduleID); //Parts from the Schedule var fsScheduleDetPartSet = SchedulePartsSelected.Select(timeSlotServiceOrder.ScheduleID); //Templates from the Schedule var fsScheduleDetTemplateSet = ScheduleTemplatesSelected.Select(timeSlotServiceOrder.ScheduleID); FSServiceOrder fsServiceOrderRow = new FSServiceOrder(); fsServiceOrderRow.SrvOrdType = fsScheduleRow.SrvOrdType; fsServiceOrderRow = graphServiceOrderEntry.ServiceOrderRecords.Insert(fsServiceOrderRow); graphServiceOrderEntry.ServiceOrderRecords.Current.SrvOrdType = fsScheduleRow.SrvOrdType; graphServiceOrderEntry.ServiceOrderRecords.Cache.SetValueExt <FSServiceOrder.branchID>(graphServiceOrderEntry.ServiceOrderRecords.Current, fsScheduleRow.BranchID); graphServiceOrderEntry.ServiceOrderRecords.Cache.SetValueExt <FSServiceOrder.branchLocationID>(graphServiceOrderEntry.ServiceOrderRecords.Current, fsScheduleRow.BranchLocationID); graphServiceOrderEntry.ServiceOrderRecords.Cache.SetValueExt <FSServiceOrder.orderDate>(graphServiceOrderEntry.ServiceOrderRecords.Current, timeSlotServiceOrder.DateTimeBegin); graphServiceOrderEntry.ServiceOrderRecords.Cache.SetValueExt <FSServiceOrder.promisedDate>(graphServiceOrderEntry.ServiceOrderRecords.Current, timeSlotServiceOrder.DateTimeBegin); //It has to be handled this way because SetValueExt is not triggering the events nor assigning the correct value graphServiceOrderEntry.ServiceOrderRecords.Current.CustomerID = fsServiceContractRow.CustomerID; graphServiceOrderEntry.ServiceOrderRecords.Cache.RaiseFieldUpdated <FSServiceOrder.customerID>(graphServiceOrderEntry.ServiceOrderRecords.Current, null); graphServiceOrderEntry.ServiceOrderRecords.Current.LocationID = fsScheduleRow.CustomerLocationID; graphServiceOrderEntry.ServiceOrderRecords.Cache.RaiseFieldUpdated <FSServiceOrder.locationID>(graphServiceOrderEntry.ServiceOrderRecords.Current, null); // Currently Service-Management's contracts DO NOT support multi-currency specification // therefore their ServiceOrders MUST be created in base currency if (PXAccess.FeatureInstalled <FeaturesSet.multicurrency>()) { graphServiceOrderEntry.ServiceOrderRecords.Cache.SetValueExt <FSServiceOrder.curyID>(fsServiceOrderRow, this.Accessinfo.BaseCuryID ?? new PXSetup <PX.Objects.GL.Company>(this).Current?.BaseCuryID); } graphServiceOrderEntry.ServiceOrderRecords.Cache.SetValueExt <FSServiceOrder.docDesc>(fsServiceOrderRow, timeSlotServiceOrder.Descr); graphServiceOrderEntry.ServiceOrderRecords.Cache.SetValueExt <FSServiceOrder.billCustomerID>(fsServiceOrderRow, fsServiceContractRow.BillCustomerID); graphServiceOrderEntry.ServiceOrderRecords.Cache.SetValueExt <FSServiceOrder.billLocationID>(fsServiceOrderRow, fsServiceContractRow.BillLocationID); graphServiceOrderEntry.ServiceOrderRecords.Cache.SetValueExt <FSServiceOrder.serviceContractID>(fsServiceOrderRow, fsServiceContractRow.ServiceContractID); if (isPrepaidContract == true && graphServiceOrderEntry.BillingCycleRelated.Current != null && graphServiceOrderEntry.BillingCycleRelated.Current.BillingBy == ID.Billing_By.SERVICE_ORDER) { graphServiceOrderEntry.ServiceOrderRecords.Cache.SetValueExt <FSServiceOrder.billServiceContractID>(fsServiceOrderRow, fsServiceContractRow.ServiceContractID); } fsServiceOrderRow = graphServiceOrderEntry.ServiceOrderRecords.Current; fsServiceOrderRow.ScheduleID = timeSlotServiceOrder.ScheduleID; fsServiceOrderRow.ServiceContractID = fsServiceContractRow.ServiceContractID; fsServiceOrderRow.GenerationID = timeSlotServiceOrder.GenerationID; fsServiceOrderRow.SalesPersonID = fsServiceContractRow.SalesPersonID; fsServiceOrderRow.Commissionable = fsServiceContractRow.Commissionable; 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 (FSScheduleDetService fsScheduleDetServiceRow in fsScheduleDetServiceSet) { if (fsScheduleDetServiceRow.LineType == ID.LineType_ServiceContract.SERVICE_TEMPLATE) { foreach (FSScheduleDet fsScheduleDetRow in fsScheduleDetTemplateSet.Where(x => ((FSScheduleDet)x).ServiceTemplateID == fsScheduleDetServiceRow.ServiceTemplateID)) { var fsServiceTemplateDetSet_Service = ServiceTemplateSelected.Select(fsScheduleDetServiceRow.ServiceTemplateID); foreach (FSServiceTemplateDet fsServiceTemplateDetRow_Service in fsServiceTemplateDetSet_Service) { FSSODetService fsSODetServiceRow = new FSSODetService(); // Insert the new row with key fields fsSODetServiceRow.ScheduleID = fsScheduleDetRow.ScheduleID; fsSODetServiceRow.ScheduleDetID = fsScheduleDetRow.ScheduleDetID; fsSODetServiceRow.LineType = fsServiceTemplateDetRow_Service.LineType; fsSODetServiceRow = graphServiceOrderEntry.ServiceOrderDetServices.Insert(fsSODetServiceRow); fsSODetServiceRow.InventoryID = fsServiceTemplateDetRow_Service.InventoryID; fsSODetServiceRow = graphServiceOrderEntry.ServiceOrderDetServices.Update(fsSODetServiceRow); PXNoteAttribute.CopyNoteAndFiles( ScheduleServicesSelected.Cache, fsScheduleDetRow, graphServiceOrderEntry.ServiceOrderDetServices.Cache, fsSODetServiceRow, copyNotes: true, copyFiles: true); // Create a copy to update the other fields fsSODetServiceRow = (FSSODetService)graphServiceOrderEntry.ServiceOrderDetServices.Cache.CreateCopy(fsSODetServiceRow); fsSODetServiceRow.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(fsSODetServiceRow, fsServiceTemplateDetRow_Service.Qty); fsSODetServiceRow.EstimatedDuration = estimatedDuration; } else { fsSODetServiceRow.EstimatedQty = fsServiceTemplateDetRow_Service.Qty; } } if (fsServiceContractRow.SourcePrice == ID.SourcePrice.CONTRACT) { fsSODetServiceRow.ManualPrice = true; // TODO: Check where is assigned the contract price? } if (createAppointmentFlag) { fsSODetServiceRow.Scheduled = true; } fsSODetServiceRow.EquipmentAction = fsScheduleDetServiceRow.EquipmentAction; fsSODetServiceRow.SMEquipmentID = fsScheduleDetServiceRow.SMEquipmentID; fsSODetServiceRow.ComponentID = fsScheduleDetServiceRow.ComponentID; fsSODetServiceRow.EquipmentLineRef = fsScheduleDetServiceRow.EquipmentLineRef; graphServiceOrderEntry.ServiceOrderDetServices.Update(fsSODetServiceRow); } var fsServiceTemplateDetSet_Part = PartTemplateSelected.Select(fsScheduleDetServiceRow.ServiceTemplateID); foreach (FSServiceTemplateDet fsServiceTemplateDetRow_Part in fsServiceTemplateDetSet_Part) { FSSODetPart fsSODetPartRow = new FSSODetPart(); // Insert the new row with key fields fsSODetPartRow.ScheduleID = fsScheduleDetRow.ScheduleID; fsSODetPartRow.ScheduleDetID = fsScheduleDetRow.ScheduleDetID; fsSODetPartRow.LineType = fsServiceTemplateDetRow_Part.LineType; fsSODetPartRow.InventoryID = fsServiceTemplateDetRow_Part.InventoryID; fsSODetPartRow = graphServiceOrderEntry.ServiceOrderDetParts.Insert(fsSODetPartRow); PXNoteAttribute.CopyNoteAndFiles( ScheduleServicesSelected.Cache, fsScheduleDetRow, graphServiceOrderEntry.ServiceOrderDetParts.Cache, fsSODetPartRow, copyNotes: true, copyFiles: true); // Create a copy to update the other fields fsSODetPartRow = (FSSODetPart)graphServiceOrderEntry.ServiceOrderDetParts.Cache.CreateCopy(fsSODetPartRow); fsSODetPartRow.TranDesc = fsServiceTemplateDetRow_Part.TranDesc; fsSODetPartRow.EstimatedQty = fsServiceTemplateDetRow_Part.Qty; if (fsServiceContractRow.SourcePrice == ID.SourcePrice.CONTRACT) { fsSODetPartRow.ManualPrice = true; // TODO: Check where is assigned the contract price? } fsSODetPartRow.EquipmentAction = fsScheduleDetServiceRow.EquipmentAction; fsSODetPartRow.SMEquipmentID = fsScheduleDetServiceRow.SMEquipmentID; fsSODetPartRow.ComponentID = fsScheduleDetServiceRow.ComponentID; fsSODetPartRow.EquipmentLineRef = fsScheduleDetServiceRow.EquipmentLineRef; graphServiceOrderEntry.ServiceOrderDetParts.Update(fsSODetPartRow); } } } else { FSSODetService fsSODetServiceRow = new FSSODetService(); // Insert the new row with key fields fsSODetServiceRow.ScheduleID = fsScheduleDetServiceRow.ScheduleID; fsSODetServiceRow.ScheduleDetID = fsScheduleDetServiceRow.ScheduleDetID; fsSODetServiceRow.LineType = fsScheduleDetServiceRow.LineType; fsSODetServiceRow = graphServiceOrderEntry.ServiceOrderDetServices.Insert(fsSODetServiceRow); fsSODetServiceRow.InventoryID = fsScheduleDetServiceRow.InventoryID; fsSODetServiceRow = graphServiceOrderEntry.ServiceOrderDetServices.Update(fsSODetServiceRow); PXNoteAttribute.CopyNoteAndFiles( ScheduleServicesSelected.Cache, fsScheduleDetServiceRow, graphServiceOrderEntry.ServiceOrderDetServices.Cache, fsSODetServiceRow, copyNotes: true, copyFiles: true); // Create a copy to update the other fields fsSODetServiceRow = (FSSODetService)graphServiceOrderEntry.ServiceOrderDetServices.Cache.CreateCopy(fsSODetServiceRow); fsSODetServiceRow.TranDesc = fsScheduleDetServiceRow.TranDesc; fsSODetServiceRow.BillingRule = fsScheduleDetServiceRow.BillingRule; if (fsSODetServiceRow.BillingRule == ID.BillingRule.TIME) { int?estimatedDuration = CalculateEstimatedDuration(fsSODetServiceRow, fsScheduleDetServiceRow?.Qty); fsSODetServiceRow.EstimatedDuration = estimatedDuration; } else { fsSODetServiceRow.EstimatedQty = fsScheduleDetServiceRow.Qty; } if (fsServiceContractRow.SourcePrice == ID.SourcePrice.CONTRACT) { fsSODetServiceRow.ManualPrice = true; // TODO: Check where is assigned the contract price? } if (createAppointmentFlag) { fsSODetServiceRow.Scheduled = true; } fsSODetServiceRow.EquipmentAction = fsScheduleDetServiceRow.EquipmentAction; fsSODetServiceRow.SMEquipmentID = fsScheduleDetServiceRow.SMEquipmentID; fsSODetServiceRow.ComponentID = fsScheduleDetServiceRow.ComponentID; fsSODetServiceRow.EquipmentLineRef = fsScheduleDetServiceRow.EquipmentLineRef; graphServiceOrderEntry.ServiceOrderDetServices.Update(fsSODetServiceRow); } } foreach (FSScheduleDetPart fsScheduleDetPartRow in fsScheduleDetPartSet) { FSSODetPart fsSODetPartRow = new FSSODetPart(); // Insert the new row with key fields fsSODetPartRow.ScheduleID = fsScheduleDetPartRow.ScheduleID; fsSODetPartRow.ScheduleDetID = fsScheduleDetPartRow.ScheduleDetID; fsSODetPartRow.LineType = fsScheduleDetPartRow.LineType; fsSODetPartRow.InventoryID = fsScheduleDetPartRow.InventoryID; fsSODetPartRow = graphServiceOrderEntry.ServiceOrderDetParts.Insert(fsSODetPartRow); PXNoteAttribute.CopyNoteAndFiles( SchedulePartsSelected.Cache, fsScheduleDetPartRow, graphServiceOrderEntry.ServiceOrderDetParts.Cache, fsSODetPartRow, copyNotes: true, copyFiles: true); // Create a copy to update the other fields fsSODetPartRow = (FSSODetPart)graphServiceOrderEntry.ServiceOrderDetParts.Cache.CreateCopy(fsSODetPartRow); fsSODetPartRow.TranDesc = fsScheduleDetPartRow.TranDesc; fsSODetPartRow.EstimatedQty = fsScheduleDetPartRow.Qty; if (fsServiceContractRow.SourcePrice == ID.SourcePrice.CONTRACT) { fsSODetPartRow.ManualPrice = true; // TODO: Check where is assigned the contract price? } fsSODetPartRow.EquipmentAction = fsScheduleDetPartRow.EquipmentAction; fsSODetPartRow.SMEquipmentID = fsScheduleDetPartRow.SMEquipmentID; fsSODetPartRow.ComponentID = fsScheduleDetPartRow.ComponentID; fsSODetPartRow.EquipmentLineRef = fsScheduleDetPartRow.EquipmentLineRef; graphServiceOrderEntry.ServiceOrderDetParts.Update(fsSODetPartRow); } 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); } } }