Skip to main content

I am working to move a customer to Acumatica 2022 R2.

In their build, there was a delegate that we overrode (InsertDataIntoAppointmentDelegate)

The issue is we added some fields to the Service order that we want to carry over into the appointment automatically.

So, we called baseMethod.Invoke() 

and then added our code after that:

        {
baseMethod.Invoke(order, appt);

FSServiceOrderExt orderExt = order.GetExtension<FSServiceOrderExt>();
FSAppointmentExt aptExt = appt.GetExtension<FSAppointmentExt>();
//insert values
aptExt.UsrAuthorizedByContact = orderExt.UsrAuthorizedByContact;
aptExt.UsrFieldSiteContact = orderExt.UsrFieldSiteContact;
aptExt.UsrDoorLocation = orderExt.UsrDoorLocation;
aptExt.UsrLaborType = orderExt.UsrLaborType;
aptExt.UsrProductType = orderExt.UsrProductType;
aptExt.UsrCustomerIsExempt = orderExt.UsrCustomerIsExempt;
aptExt.UsrTaxExempt = orderExt.UsrTaxExempt;
}

 

It seems in this release, I need to change the PXAction of the Button. But I don’t see how I can do anything like the baseMethod.Invoke() 

I find it in the source code, but I am unclear as to how I can just add my code to the action

Any guidance on how to do that?

This is the Source of the existing action:

        public PXAction<FSServiceOrder> scheduleAppointment;
PXUIField(DisplayName = "Create Appointment", MapEnableRights = PXCacheRights.Select, MapViewRights = PXCacheRights.Select)]
PXButton(OnClosingPopup = PXSpecialButtonType.Cancel)]
public virtual IEnumerable ScheduleAppointment(PXAdapter adapter)
{
List<FSServiceOrder> list = adapter.Get<FSServiceOrder>().ToList();

foreach (FSServiceOrder fsServiceOrderRow in list)
{
ValidateContact(fsServiceOrderRow);
SkipTaxCalcAndSaveBeforeRunAction(ServiceOrderRecords.Cache, fsServiceOrderRow);

if (SharedFunctions.isThisAProspect(this, fsServiceOrderRow.CustomerID))
{
throw new PXException("Error");
}

var graphAppointmentEntry = PXGraph.CreateInstance<AppointmentEntry>();

FSAppointment fsAppointmentRow = new FSAppointment()
{
SrvOrdType = ServiceOrderRecords.Current.SrvOrdType,
SOID = ServiceOrderRecords.Current.SOID
};

fsAppointmentRow = graphAppointmentEntry.AppointmentRecords.Insert(fsAppointmentRow);

graphAppointmentEntry.AppointmentRecords.SetValueExt<FSAppointment.soRefNbr>(graphAppointmentEntry.AppointmentRecords.Current, fsServiceOrderRow.RefNbr);
graphAppointmentEntry.AppointmentRecords.SetValueExt<FSAppointment.customerID>(graphAppointmentEntry.AppointmentRecords.Current, fsServiceOrderRow.CustomerID);

throw new PXRedirectRequiredException(graphAppointmentEntry, null);
}

return list;
}

 

 

Hi @mjgrice32,

You can use delegate and invoke the baseMethod like below,

public class ServiceOrderEntry_Extension : PXGraphExtension<PX.Objects.FS.ServiceOrderEntry>
{
#region Event Handlers
public delegate IEnumerable ScheduleAppointmentDelegate(PXAdapter adapter);
PXOverride]
public IEnumerable ScheduleAppointment(PXAdapter adapter, ScheduleAppointmentDelegate baseMethod)
{
return baseMethod(adapter);
}
#endregion
}

Good Luck,


Hi @mjgrice32,

You can use delegate and invoke the baseMethod like below,

public class ServiceOrderEntry_Extension : PXGraphExtension<PX.Objects.FS.ServiceOrderEntry>
{
#region Event Handlers
public delegate IEnumerable ScheduleAppointmentDelegate(PXAdapter adapter);
PXOverride]
public IEnumerable ScheduleAppointment(PXAdapter adapter, ScheduleAppointmentDelegate baseMethod)
{
return baseMethod(adapter);
}
#endregion
}

Good Luck,

 

@Vignesh Ponnusamy : Hey thanks! This is a great help.

I was trying to run baseMethod(adapter) first -- and it was giving me an error that I couldn’t figure out.

I think it is because the baseMethod was causing a redirect, and that was where the error is.

Here’s the only issue, though… I need to add fields to the appointment. And to do that, I think the baseMethod has to be called, right?

How do I access the fields of the appointment that is being created by the ScheduleAppointment method?


Hi @mjgrice32,

You can try something like following,

    public class ServiceOrderEntry_Extension : PXGraphExtension<PX.Objects.FS.ServiceOrderEntry>
{
#region Event Handlers
public delegate IEnumerable ScheduleAppointmentDelegate(PXAdapter adapter);
[PXOverride]
public IEnumerable ScheduleAppointment(PXAdapter adapter, ScheduleAppointmentDelegate baseMethod)
{
//Adds RowInserting handler when the AppointmentEntry Graph is created
PXGraph.InstanceCreated.AddHandler<AppointmentEntry>((graphAppointmentEntry) =>
{
graphAppointmentEntry.RowInserting.AddHandler<FSAppointment>((sender, e) =>
{
FSAppointment appointmentObject = (FSAppointment)e.Row;
appointmentObject.DocDesc = "From Service Order: " + Base.ServiceOrderRecords.Current.RefNbr;
//Use the appointmentObject to get the DAC extension of the FSAppointment
//Use Base.ServiceOrderRecords.Current to get the DAC extension of the FSServiceOrder
//Set the custom field values as necessary
});
});
return baseMethod(adapter);
}
#endregion
}

In the above example, I am setting the Appointment Description. Similarly, you can set the custom field in the Appointments screen from the Service Order screen.  Feel free to post if you have any questions.!


@Vignesh Ponnusamy : Thank you so much! I have never used PXGraph.InstanceCreated before. 

That’s kind of a game changer. 

Thanks again!


BTW, for completeness, (and in case future me comes looking for this thread later...) I wanted to add, that the line: 

 

return baseMethod(adapter);

Will throw an exception when run in VS Studio debugger. And it can be ignored (just hit F5 to continue). It will not create an error when run outside of the debugger.

I assume this is because Acumatica is catching the thrown error and using that to drive the new window for the Appointments? IDK. But I know that when you want to create a pop up alert message, you throw an error to do it, so there must be some voodoo thread management going on there somehow?

(If someone can explain this to me, I would be appreciative. If not, I will mark it up as “Just one of those Acumatica things...”) 


Reply