Overview

The Email skill template is provided to you in your ASK Extension Kit. You can use this template to help you write email skills in PrecisionLender. You can modify the code in the template or use it as a reference when writing your skill. In this article, we'll walk through the template provided in the kit along with aspects of email functionality that will apply whether you're using this template or using the 'skill' template to write your email skills.

This article assumes you have previously reviewed or have knowledge of the information contained in Navigating Your Andi® Skills Kit in the IDE and Getting Started. 

 

'Email' Skill Template Code

The template skill code is written to send an email when an opportunity is saved in PrecisionLender. The email will be sent to the designated recipients in the skill code and contain the opportunity id and a link to the opportunity.

skillmanifest.json

In the template, the skillmanifest is essentially a blank file. However, when you write a skill, you should always add a description so that users or skill writers know what the skill is supposed to do.

If you want to make your email more dynamic, you can add configurations and other settings, some of which would be defined in the skillmanifest.

Email skills are a great use case for configuration keys. Although this template skill doesn't use those, they provide the ability to have email parameters, such as recipients, managed outside of the skill code, so that the skill doesn't need to be updated every time one of those values changes.

{
  "description": "Andi New Skill",
  "skillConfigKeys": [],
  "locales": ["en-us"]
}

shouldIRun.ts

In the template, the shouldIRun defines a variable as a condition that must be met in order for the skill to run. Because the goal of the skill is to send an email when an opportunity is saved, an isOpportunitySaveClickEvent variable is defined using the isOpportunitySavedClickEvent power.

let isOpportunitySaveClickEvent = skillContext.powers.precisionLender.opportunity.isOpportunitySavedClickEvent();

Next, because the skill should run when this event occurs, a conditional is set that if an event occurs that does not match the criteria for isOpportunitySaveEvent, then the skill shouldn't run using the shouldIRunFalse power

if(!isOpportunitySaveClickEvent)
    return skillContext.powers.andi.shouldIRun.shouldIRunFalse();

If the event is an isOpportunitySaveEvent, then the skill should run, and the shouldIRun concludes with the shouldIRunTrue power.

return skillContext.powers.andi.shouldIRun.shouldIRunTrue();

In total, the shouldIRun code is as follows:

import * as andiSkills from 'andiskills';
import * as andiExternal from 'andiexternal';

// shouldIRun is used by the andi skills platform to determine if the given
// skill's current context needs to be executed. 
// this particular skill should run if the event is an Opportunity Saved
export function shouldIRun(skillContext: andiSkills.ISkillContext): andiSkills.ShouldIRunResponse {
       
    let isOpportunitySaveClickEvent = skillContext.powers.precisionLender.opportunity.isOpportunitySavedClickEvent();
   
    if(!isOpportunitySaveClickEvent)
        return skillContext.powers.andi.shouldIRun.shouldIRunFalse(); 
    
    return skillContext.powers.andi.shouldIRun.shouldIRunTrue();
}

run.ts

In the template, the run defines the email that will be sent when the skill runs. First, two variables are defined that will allow for event data to be pulled into the email when the save event occurs. Defining the email message components as a variable first isn't required when writing email skills, but can help with keeping your code neat and organized, especially if the email will contain multiple items of information.

let applicationEvent = skillContext.powers.andi.event.getApplicationEvent(skillContext);
let applicationEventData = applicationEvent.applicationEventData;

Then, email parameters are defined that the email power will use for generating the content of the email. As mentioned in the skillManifest section, this is an area where skill configuration keys can prove valuable.

let emailSubject = "Opportunity saved event"; 
let emailMessage =`<ul><li>Opportunity Id: ${applicationEventData.opportunityId} saved - <a href="${applicationEventData.opportunityUrl}" >click here to view</a> </li></ul>`;
let toAddress = "andi-devs@precisionlender.com"; 
let toName = "Andi Dev Team"; 
let fromAddress = "andi@precisionlender.com";

Next, the email power is used to define the parameters of the email. This power will always need to be used in order to create an email. For more information about the email power and its parameters, see our email power article.

return skillContext.powers.andi.email.sendEmail(
    "opportunity-saved-email", 
    andiSkills.EmailFrequencyTypes.OneMinute, 
    [new andiSkills.EmailUserModel(toName, toAddress)], 
    fromAddress,
    emailSubject,
    emailMessage, 
    "",
    ""
);

In total, the run code is as follows:

import * as andiSkills from 'andiskills';
import * as andiExternal from 'andiexternal';

// this is main execution of the skill which is called after the andi
// skills platforms determines if it should run
// this particular skill will send an email with information pertaining
// to the opportunity saved event
export function run(skillContext: andiSkills.ISkillContext) : Promise | andiSkills.ISkillActivity{

    // get pertinent information from the event to be used in the email message
    let applicationEvent = skillContext.powers.andi.event.getApplicationEvent();
    let applicationEventData = applicationEvent.applicationEventData;
    
    // compose your email here - body can be html
    let emailSubject = "Opportunity saved event"; 
    let emailMessage = `<ul><li>Opportunity Id: ${applicationEventData.opportunityId} saved - <a href="${applicationEventData.opportunityUrl}" >click here to view</a> </li></ul>`;
    let toAddress = "andi-devs@precisionlender.com"; 
    let toName = "Andi Dev Team"; 
    let fromAddress = "andi@precisionlender.com"; 

    // send email through andi powers 
    // consult powers documentation for more details
    return skillContext.powers.andi.email.sendEmail(
        // email category to best describe purpose of this skill 
        "opportunity-saved-email", 
        // change frequency of emails being sent
        andiSkills.EmailFrequencyTypes.OneMinute, 
        [new andiSkills.EmailUserModel(toName, toAddress)], 
        fromAddress,
        emailSubject,
        emailMessage, 
        "",
        ""
    );
        
}

 

'Email' Skill Template Code - Mocha Test

Mocha unit tests, while a good practice, are not required and will typically be utilized by skill writers with more programming experience.

shouldIRun.ts 

This unit test verifies that if the event is an OpportunitySaved event, then the shouldIRun returns true.

import * as assert from 'assert';
import { shouldIRun } from '../shouldIRun';
import * as andiSkills from 'andiskills';
import * as andiExternal from 'andiexternal';

describe("Email Skill ShouldIRun Tests", () => {

    // Defines a Mocha unit test
    it("Logs that it tried to run", (done) => {

        let eventName: string = "OpportunitySavedClick";
        let applicationEventData: any = {};
        let skillContext: andiSkills.ISkillContext = andiExternal.MockSkillContextBuilder
            .forOpportunitySavedClickEvent()
            .addApplicationEvent(eventName,applicationEventData)
            .build();

        andiExternal.ShouldIRunScenario
            .forGiven(skillContext)
            .execute(shouldIRun)
            .then((result) => {
                assert.equal(result,true);
                done();
            });

    });
});

run.spec.ts 

This unit test verifies that the run method returns a result that would send an email.

import * as assert from 'assert';
import { run } from '../run';
import * as andiSkills from 'andiskills';
import * as andiExternal from 'andiexternal';

describe("Email Skill Run Tests", () => {

    // Defines a Mocha unit test
    it("Logs that it ran", (done) => {

        let eventName: string = "OpportunitySavedClick";
        let applicationEventData: any = {};
        let skillContext: andiSkills.ISkillContext = andiExternal.MockSkillContextBuilder
            .forOpportunitySavedClickEvent()
            .addApplicationEvent(eventName,applicationEventData)
            .build();

        andiExternal.RunScenario
            .forGiven(skillContext)
            .execute(run)
            .then((result) => {
                assert.notEqual(result,null);
                done();
            }); 
            
    });

});

 

Was this article helpful?
0 out of 0 found this helpful