Set New Sale Ownter = Company Owner

Good afternoon,

I am writing a script that will set the owner of a new sale to that of the company owner it is referenced to. This would seem like a fairly straight-forward process (I admit I do not script much) in which case I would get the associate ID of the person who owns the company the sale is linked to and assign it to the sale associate ID that is being created.

Right now I have the following:

using SuperOffice.CRM.Rows;
using SuperOffice.CRM.Services;
using SuperOffice.Data;
using System;
using System.Data.SqlClient;

namespace SaleScriptClass
{
    public static class SaleScript
    {
        static void Main() { }

        public static void BeforeSaveSaleEntity(SaleEntity saleEntity, ref object eventState)
        {      
            SuperOffice.CRM.Entities.Sale sale = SuperOffice.CRM.Entities.Sale.GetFromIdxSaleId(saleEntity.SaleId);


            SuperOffice.CRM.Entities.Contact contact =                                                                                                                                        SuperOffice.CRM.Entities.Contact.GetFromIdxContactId(saleEntity.Contact.ContactId);


            sale.Associate.AssociateId = contact.Associate.AssociateId;
        }
    }
}

I am receiving an error in Visual Studio that "The type or namespace name 'SaleEntity' could not be found (are you missing a using directive or an assembly reference?)" I have no issue with a ContactEntity and I have seen other threads that use the SaleEntity. I am a bit confused why I receiving this error. I would think that the references that i have imported into Visual Studio would include a SaleEntity if they include a ContactEntity but again I am just getting back into SuperOffice scripting. If anyone has any suggestions it would be appreciated.

Brian

RE: Set New Sale Ownter = Company Owner

Ok - first

 

You don't need to load the sale.

The sale entity is being passed to the service call. The service call is executing your script, giving it the same sale entity.

 

You can modify the entity, and the modified entity will be passed to the save logic that implements the service.

Af: Christian Mogensen 2. jun 2018

RE: Set New Sale Ownter = Company Owner

Hi Brian, you could do this in (at least) two different approaches. Below are two examples. One which uses NetServer script (like the one you've started doing) and one using a "Trigger script".

NetServer script

Your script could be rewritten like this.

//$FullClass

using SuperOffice.CRM.Services;

namespace BrianExample
{
    public static class SaleScript
    {
        public static void Main() { ;}
           
        public static void BeforeSaveSaleEntity(ref SaleEntity sale, ref object state)
        {
			sale.Associate.AssociateId = sale.Contact.AssociateId;
        }
    }
}


Trigger script

A Trigger script is something relatively new. It uses the CRMScript (formerly ejscript) language. It has some resemblance to C++, but a lot easier to work with.

This Trigger script does what you want.

The script is:

#setLanguageLevel 3;

EventData ed = getEventData();

//Get info from Contact
Integer contactId = ed.getInputValue("SaleEntity.Contact.ContactId").toInteger();
NSContactAgent contactAgent;
NSContact contact = contactAgent.GetContact(contactId);

//Change the sale
ed.setOutputValue("SaleEntity.Associate.AssociateId", contact.GetAssociateId().toString());

The above example is actually longer than it needs to be because of, what I think is, a bug. If the "SaleEntity.Contact.AssociateId" had been set properly then this one-liner would also have worked.

#setLanguageLevel 3;

EventData ed = getEventData();
ed.setOutputValue("SaleEntity.Associate.AssociateId", ed.getInputValue("SaleEntity.Contact.AssociateId"));

Which approach to use?

Personally I lean towards the Trigger script.

A Trigger script can be edited directly in the browser from anywhere, while a NetServer script requires you to RDP into the server.

A Trigger script has better Intellisense (unless you spend some time configuring Visual Studio with NuGet packages, in which case NetServer scripts would have better intellisense).

Both scripts can be edited while users are using the system, but the NetServer script requires a ?flush to reload the new script.

Disabling a Trigger script is done by toggling the enable/disable button in GUI, while the NetServer script can be disabled by moving the file.

The Trigger script ONLY works in the Web-client, while a NetServer script is executed by anyone calling the NetServer webservices (meaning it can be run by PocketCRM, custom integrations etc).

NetServer scripts support more events than Trigger scripts do. For example, if you want to set a default value when creating a NEW sale you need to use the AfterCreateDefaultSaleEntity event, but those are not exposed in Trigger scripts. Hopefully they will be in the future.

Trigger scripts work in both Online and OnSite, but NetServer scripts only work OnSite.

A NetServer script can be used to change the rights of fields. So for example, you can set a field to be read-only when certain checks are done. Trigger scripts unfortunately do not expose the FieldRights.

Hope this helps :)

Af: Frode Lillerud 2. jun 2018

RE: Set New Sale Ownter = Company Owner

Come to think of it, your NetServer script could be even simpler. You don't need a fullclass here. These few lines are enough.

public static void BeforeSaveSaleEntity(ref SaleEntity sale, ref object state)
{
	sale.Associate.AssociateId = sale.Contact.AssociateId;
}
Af: Frode Lillerud 2. jun 2018

RE: Set New Sale Ownter = Company Owner

Hi Frode,

First of all, I would like to say thanks for the responses. The time you took to explain everything was great. I can't believe I saying this but I am still having some issues.

In your last response you mentioned that I did not need a full class. This is in fact what i had tried originally but could never get it to execute. In addition to the ?flush I also restarted the NetServer as well. For whatever reason though I am not getting the results I expected. Really, I am not getting any results at all as nothing seems to happen.

Your explantaion on the trigger script was very helpful and I will be digging into that more. However, when I try to execute the script i get the following:

Script

Is there any type of additional configuration that needs to happen to make trigger scripts work? Again, thank you for your help. I greatly appreciate it.

Af: Brian Huelsman 7. jun 2018

RE: Set New Sale Ownter = Company Owner

Hi Brian, you're very welcome. We'll figure out what's going on here.

First, which version of SuperOffice is this?

For the Trigger-script, you do have the Trigger-tab? Did you type the script manually or copy it from the forum? There is a common issue with getting some invisible characters when copying, so recommend you retype the line it complains about manually.

In web.config, have you enabled scripting and set a path for where scripts are found?

Lastly, what does the logfile say? It should give errors if it is unable to compile the Netserver-script.

Af: Frode Lillerud 7. jun 2018

RE: Set New Sale Ownter = Company Owner

Hi Frode,

Right now we are using SuperOffice 8.1 Build Release81_C-2017.11.23-01. I think you may be on to something as I do not have a trigger tab, just a script tab as in the screenshot below:

I originally did copy and paste your code but after your response I then typed the code in manually. However, I received the same message as before. I also have scripting enabled and the script path set. I was running the short script below just to test that I could get the associate contact id and I did get the desired results:

public static void AfterGetContactEntity(int contactId, ref ContactEntity contact, ref object state)
{
    contact.Department += " Associate ID: (" + contact.Associate.AssociateId + ")";
}

-----------------------------------------------------------------------------------------------------------

The only thing i am seeing in the logfile is the following:

Level:   Error
At:      10:49:02 AM

Element:
Message: http://superofficecrm.com/Web/Default.aspx
Details:
   at SuperOffice.DCF.Web.SoFormsAuthentication.InitSession()
   at SuperOffice.DCF.Web.ApplicationUtility.ExecuteAjaxMethodImplementation(AjaxMethodPreImplementation preAuthenticateImplementation, AjaxMethodImplementation implementation)

Inner Element:
Message: User is not authenticated with NetServer (HttpContext)
Type:    SuperOffice.Exceptions.SoSessionException
Details:
   at SuperOffice.DCF.Web.SoFormsAuthentication.InitSession()

 

Af: Brian Huelsman 7. jun 2018

RE: Set New Sale Ownter = Company Owner

8.1 from November didn't have Triggers, you need to upgrade to get it. There are many SuperOffice versions since that ancient version :)

So you got the AfterGetContactEntity script working? Then scripting is working, and the problem is either you need a ?flush (which is not the same as a iisreset), or the script had an invalid method signature. Recommend you try a few different event methods, and see which ones work and which ones don't.

Af: Frode Lillerud 7. jun 2018

RE: Set New Sale Ownter = Company Owner

Hi Frode,

I see the issue now. The original script we were discussing was this:

public static void BeforeSaveSaleEntity(ref SaleEntity sale, ref object state)
{
    sale.Associate.AssociateId = sale.Contact.AssociateId;
}

If I hardcode an associate ID value in place of sale.Contact.AssociateID like in the method below it works correctly and the owner of the sale is the associate that has that associate Id:

public static void BeforeSaveSaleEntity(ref SaleEntity sale, ref object state)
{
    sale.Associate.AssociateId = 131;
}

There seems to be an issue with assigning a value to sale.Contact.AssociateID when the script executes. As I am using the BeforeSaveSaleEntity I would think the associateId for the corresponding company would be obtained when the script executes but before anything is written to the database. Would this be correct? Or, is it possible the sale.Contact.AssociateId is obtained after the script actually executes?

Af: Brian Huelsman 7. jun 2018

RE: Set New Sale Ownter = Company Owner

Hi Brian, good that you've got one step further.

I tested the script when I wrote the initial forum post, and it does work. In the BeforeSaveSaleEntity event the sale.contact.associateid field has a value. But it assumes that the sale actually has a company set. 

It might be a typo, but you write about setting sale.contact.associateid. That won't work. You can change the owner of the sale, but not the owner of the company.

Af: Frode Lillerud 7. jun 2018

RE: Set New Sale Ownter = Company Owner

Very likely the client has not filled in the contact beyond the id.

You need to guard against nulls.

You also need to read the contact from the db since you can't trust the data from the client.

 

Var cont = ContactRow.GetByContactId( sale.contact.contactId);

Sale.associate = sale. Associate ?? New associate ()

Sale.associate.associateid = cont.associateid;

Af: Christian Mogensen 9. jun 2018