Hi,
We have a customer who is looking to move from SuperOffice Windows to SuperOffice Web, and I am trying to develop an equivelent sentry plugin to stop end users from being able to edit approved appointments. We have a custom NetServer table, that stores the appointment id of the approved appointment and the id of the associate approving the appointment, along with the approval date.
However, whilst I think it is coded correctly it is not making the appointment read only when the appointment is approved. I have done some similar tests with the UDAppntSmall table, as per Dennis' example in the post here, to rule out the problem being with a custom table, but this does not work either.
My modify select is as follows.
public void ModifySelect(Select sql, TableInfo tableInfo)
{
AppointmentTableInfo ati = (AppointmentTableInfo)tableInfo;
AcedaappfieldsTableInfo aaf = CustomTablesInfo.GetAcedaappfieldsTableInfo();
UDAppntSmallTableInfo udti = TablesInfo.GetUDAppntSmallTableInfo();
sql.JoinRestriction.LeftOuterJoin(ati.AppointmentId.Equal(aaf.AppointmentId));
sql.JoinRestriction.LeftOuterJoin(ati.UserdefId.Equal(udti.UdappntsmallId));
sql.ReturnFields.Add(aaf.AuthorisedbyId);
sql.ReturnFields.Add(udti.Long14);
}
Now when I open the appointment the sentry code is fired several times (around about 14 times I think, from the point of double clicking the appointment to the appointment dialog being shown on screen with all the data loaded), and in most cases my custom table, and the UDAppntSmall table are found, and the code to limit the table rights to select only, fires (the results in the Watch window show the data from these tables being loaded correctly).
But once, about half way through this process, everytime the appointment is opened (after about the 6th instance of the code firing), both tables are not found, and it is here when you first see the appointment dialog showing in SuperOffice (the following 7 times or so, of the code running on the appointment open event, both tables are found in the code, and the correct AuthorisedbyId is visible, but the appointment is still not opened as read only).
Now if I move up the row where I set the table rights to row 42, as in the commented section above, outside the check on the custom table, the appointment does correctly load as read only. But of course this will not work for the customer as I need to check that the appointment is approved before making the appointment read only.
Whilst this code was running, all SQL traces that I ran whilst opening the appointment, did reference AuthorisedbyId field and return the correct value, so I don't know why this one instance on every appointment load the code does not correctly load the joined tables, and why the appointment is not made read only.
And when I move an appointment via drag and drop, this is not blocked by the sentry plugin either, and the "var Test" line of code is hit far more often (though the table rights row is also still hit at times during this process), so I am completely stuck on what to try next.
Finallly and, this is far less important, "SoLogger.LogError(ex)", no longer works. How should this now be written now, to prevent a compile error?
Many thanks,
Trevor
All Replies (7)
Hi Trevor!
It's been some years since working with Sentry, but I made a library that I think will help you understand what is going on...
https://github.com/SuperOffice/devnet-netserver-sentry
Use this tool to see why your sentry plugin is called so often, and I think you will see how it all starts to make more sense.
Hope this helps!
Hi All,
I tried getting the code for work a different way, creating the following function in the plugin.
public bool IsAppointmentApproved(Int32 AppointmentId)
{
bool returnValue = false;
AcedaappfieldsTableInfo aaf = CustomTablesInfo.GetAcedaappfieldsTableInfo();
var select = S.NewSelect();
select.ReturnFields.Add(aaf.AuthorisedbyId);
select.Restriction = aaf.AppointmentId.Equal(S.Parameter(AppointmentId));
using (var qeh = new QueryExecutionHelper(select))
{
while (qeh.Reader.Read())
{
if (qeh.Reader.GetInt32(aaf.AuthorisedbyId) > 0)
{
returnValue = true;
};
}
}
return returnValue;
}
Then running the following check
if (IsAppointmentApproved(Convert.ToInt32(GetFieldValue(AppointmentTable.AppointmentId))))
Instead of
if (Convert.ToInt32(GetFieldValue(aaf.AuthorisedbyId)) > 0)
And whist it does work, because it is running a query to the custom table everytime the pluging is run (which is thousands of times when loading a companies activities for some of the customer's company records), it causes the system to be unusably slow.
But it does seem to confirm to me that the original code should actually work, as both methods are querying the same field.
I am thinking of a worse case scenario of updating an appointment field when the appointment is approved, and using this field for the sentry plug in check. It is really not the way that I want to go, but if I cannot get the code to work referencing another table. Is the LeadTime or LagTime field used for anything? I cannot see many references to them in the documentation, apart from getting and setting the values to/from these fields. If I set either of these fields to 1 when the appointment is approved, and use this for the sentry plugin, it does work, and the performance loading 27k appointment only drops by a couple of seconds. But again this is not the approach I want to take, but not sure what else to do.
Many thanks,
Trevor
Hi David,
Thanks for your reply. I get the same issue when I try to access a user defined field, for the 14 or so times the code runs when opening an appointment, at least once the return value is null for any joined tables, including UDAppntSmall. Because of this the appointment is not being opened as read only. Unless you know of another way of accessing a user defined field value in the code, that I could try.
UDAppntSmallTableInfo udappSmall = TablesInfo.GetUDAppntSmallTableInfo();
var udefValue = GetFieldValue(udappSmall.Long14);
My other concern about using this approach, if I can get it to work, if that often they have multiple participants for the same appointment, and each participant's appointment is approved independantly, and in SuperOffice you can only set the user defined field on the parent appointment, and all appointments are linked to the same UDAppntSmall record.
Just really confused as to why it is not working using the custom NetServer table, as it looks to me like it should be, with the code I have written.
Many thanks,
Trevor
Fix coming in 10.2.9
Basically when reading row objects, the sentry was reading data from the row object - and the row object only has info about the row - any added custom fields or udef fields were lost when the row object was constructed.
When reading collections, entities or archives, the data reader with all the added fields was still available to provide values, but when dealing with individual row objects the sentry could not read values from the data reader (it had closed - it was an ex-reader). Added a temporary cache to hold the added values for the sentry, so that added fields are available via GetFieldValue.
Hi Christian,
Thanks for this reply, really good to know. One problem I reported on this to AppDev was that as soon as as I use the Modify Select in the plugin for recurring appointments (the customer has quite a few recurrences of the appointments) the time to load and open appointment increases by about 10 times the amount as when not using the Modify Select. Is this speed issue also resolved in 10.2.9.
Many thanks, and have a great weekend.
Trevor