'Field Tag' Skill Template

Overview

The Field Tag skill template is provided to you in your ASK Extension Kit. You can use this template to help you write field tag 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 field tag functionality that will apply whether you're using this template or using the 'skill' template to write your field tag 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. 

 

'Field Tag' Skill Template Code

The template skill code is written to display an information field tag when new deposit accounts are priced in an opportunity in PrecisionLender. The message will appear in the Andi® window as long as the opportunity contains at least one new deposit account and states "Awesome job pricing deposits!".

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 field tag more dynamic, you can add configurations and other settings, some of which would be defined in the skillmanifest.

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

shouldIRun.ts

In the template, the shouldIRun defines two variables as part of conditions that must be met in order for the skill to run. Because the goal of the skill is to display a message when new deposit accounts are priced in an opportunity, the first variable to define is for a change event that occurs with deposit accounts in an opportunity. The isDepositAccountChangeEvent power is used to define that variable as

let isDepositAccountChangeEvent = skillContext.powers.precisionLender.opportunity.isDepositAccountChangeEvent();

Next, because the skill should run when this event occurs, a conditional is set that if an event occurs that is not a deposit account change event, then the skill shouldn't run using the shouldIRunFalse power

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

Then, because numerous actions can take place when pricing deposits, including removing deposits, a variable is defined to also check that if a deposit account change event occurs, that the resulting change still includes a deposit account. The getDepositAccounts power is used to define a depositAccounts variable that is then used to define another variable that ensures the number of deposit accounts in the opportunity is a positive, non-zero number.

let depositAccounts = skillContext.powers.precisionLender.opportunity.getDepositAccounts();
let hasDeposits = depositAccounts.length > 0;

Then, the condition is set that if there is not a positive, non-zero number of deposit accounts, then the skill shouldn't run using the shouldIRunFalse power.

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

Therefore, if one or both conditions aren't met, then the skill shouldn't run. If both conditions are met, 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 checks for existing deposits on the opportunity 
// if none exist it should run
export function shouldIRun(skillContext: andiSkills.ISkillContext): Promise | boolean {
    
    let isDepositAccountChangeEvent = skillContext.powers.precisionLender.opportunity.isDepositAccountChangeEvent();
    if(!isDepositAccountChangeEvent) return  skillContext.powers.andi.shouldIRun.shouldIRunFalse();

    let depositAccounts = skillContext.powers.precisionLender.opportunity.getDepositAccounts();
    let hasDeposits = depositAccounts.length > 0;
    
    // if the opportunity doesn't have deposits, don't run
    if(!hasDeposits)
        return skillContext.powers.andi.shouldIRun.shouldIRunFalse(); 

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

}

run.ts

In the template, the run defines the field tag to be displayed when the skill runs. First, a variable is defined for the message that will be displayed in the Andi® window when new deposits accounts are priced in an opportunity. Defining the message as a variable first isn't required when writing field tag skills, but can help with keeping your code neat and organized, especially if more than one field tag will be defined in a skill.

let messageToDisplay = "Awesome job pricing deposits!";

Next, the field tag power is used to define the parameters of the field tag. This power will always need to be used in order to create a field tag. For more information about the field tag power and its parameters, see the Field Tag Power article.

return skillContext.powers.andi.fieldTag.sendFieldTag(
        andiSkills.FieldTagTypes.Info,
        "opportunity-change-deposit-hello-skill", 
        1, 
        messageToDisplay,
        [],
        null, 
        function(api, model, comparehash, custom){

            var eventData = model.applicationEventData; 

            var shouldIShow = eventData.engineModel.depositAccounts &&  eventData.engineModel.depositAccounts.length > 0;

            return shouldIShow;
        },
        null, 
        null, 
        null 
    );

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 a field tag skill with a specified message
// relating to deposits on the opportunity
export function run(skillContext: andiSkills.ISkillContext) : Promise | andiSkills.ISkillActivity{

    let messageToDisplay = "Awesome job pricing deposits!"; 

    // send field tag using powers
    // consult powers documentation for more details
    return skillContext.powers.andi.fieldTag.sendFieldTag(
        andiSkills.FieldTagTypes.Info,
        // this is just a key to uniquely identify your fieldtag
        "opportunity-change-deposit-hello-skill", 
        1, 
        messageToDisplay,
        [],
        null, 
        function(api, model, comparehash, custom){

            var eventData = model.applicationEventData; 

            // make sure that anytime deposits are removed - it stops showing this message
            var shouldIShow = eventData.engineModel.depositAccounts &&  eventData.engineModel.depositAccounts.length > 0;

            return shouldIShow;
        },
        null, 
        null, 
        null 
    );
    
    
}

 

'Field Tag' 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 

The first unit test verifies that if there are no deposits in the opportunity, then the shouldIRun returns false.

The second unit test verifies that if there are deposits in the opportunity, 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("Field Tag Skill ShouldIRun Tests", () => {

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

        let skillContext: andiSkills.ISkillContext = andiExternal.MockSkillContextBuilder
            .forDepositAccountChangeEvent()
            .build();

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

    // Defines a Mocha unit test
    it("Logs that it returned true when deposit accounts are present", (done) => {
      
        let accountId: "1234";
        let accountAverageBalance: number = 500;
        let skillContext: andiSkills.ISkillContext = andiExternal.MockSkillContextBuilder
            .forDepositAccountChangeEvent()
            .addSimpleDepositAccount(accountId,accountAverageBalance)
            .build();
     
        andiExternal.ShouldIRunScenario
            .forGiven(skillContext)
            .execute(shouldIRun)
            .then((result) => {
                assert.equal(result,true);
                done();
            });
      
    });
    
});

 

run.spec.ts 

This unit test verifies that the run does not return null.

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

describe("Field Tag Skill Run Tests", () => {

    // Defines a Mocha unit test
    it("Logs that it ran", (done) => {
      
        let skillContext: andiSkills.ISkillContext = andiExternal.MockSkillContextBuilder
            .forDepositAccountChangeEvent()
            .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