Function Sample
This is the overview of the sample implementation of a Function Communication Method.
Objects
The following table includes links to each of the objects that are being created in this sample
| Object Type | Object Name | See | 
|---|---|---|
| Codeunit | My Sample Function Handler | link | 
| Table | My IQ Sample Function | link | 
| Page | My IQ Sample Function Card | link | 
| Table | My Sample Function Snapshot | link | 
| Page | My Sample Function Snapshot | link | 
| Enum Extension | My Sample Function | link | 
Codeunit My Sample Function Handler
/// <summary>
/// This is a sample implementation of a "IQ Communication Method".
///
/// All Communication Methods must implement the IQCM Interface and at least one of "IQCM Import", "IQCM Export" and "IQCM Function".
///
/// This sample implements the Function interface.
/// </summary>
codeunit 50010 "My Sample Function Handler" implements "QWESR IQCM", "QWESR IQCM Function"
{
    Access = Public;
    // ***********************************************************************************************************************************************
    //
    //     All code in between "CUSTOMIZATION begin" and "CUSTOMIZATION end" must be updated to your specific needs
    //
    // ***********************************************************************************************************************************************
    // "IQCM" Interface implementation (documented in the Interface object):
    procedure SetCommunicationMethodCode(IQCommunicationMethodCode: Code[20]) rHandled: Boolean
    begin
        // CUSTOMIZATION begin
        if not IQCMSampleFunction.Get(IQCommunicationMethodCode) then begin
            IQCMSampleFunction.Init();
            IQCMSampleFunction.Code := IQCommunicationMethodCode;
            IQCMSampleFunction.Insert(true);
        end;
        exit(true);
        // CUSTOMIZATION end
    end;
    procedure OpenCommunicationMethodCardPage() rHandled: Boolean
    begin
        AssertInit();
        // CUSTOMIZATION begin
        IQCMSampleFunction.FilterGroup := 2;
        IQCMSampleFunction.SetRecFilter();
        IQCMSampleFunction.FilterGroup := 0;
        Page.Run(Page::"My IQ Sample Function Card", IQCMSampleFunction); // Change to the Setup Card for this Communication Method
        exit(true);
        // CUSTOMIZATION end
    end;
    procedure ClearCommunicationMethod() rHandled: Boolean
    begin
        AssertInit();
        // CUSTOMIZATION begin
        IQCMSampleFunction.Delete(true);
        exit(true);
        // CUSTOMIZATION end
    end;
    procedure GetCommunicationMethodSnapshot(var Snapshot: RecordRef) rHandled: Boolean
    // CUSTOMIZATION begin
    var
        IQCMSampleFunctionSnapshot: Record "My Sample Function Snapshot"; // Change to this implementation's Snapshot record
    begin
        // This is a working sample implementation of how Communication Method Snapshot can be handled.
        // "The trick" is to use the "Record Time Stamp" of this Communication Method record as primary key in the snapshot table,
        // in this way we will create a new snapshot record every time a Release Wave of the Communication Method record is being used
        if not IQCMSampleFunctionSnapshot.Get(IQCMSampleFunction."Record Time Stamp") then begin
            IQCMSampleFunctionSnapshot.Init();
            IQCMSampleFunction.CalcFields(Description);
            IQCMSampleFunctionSnapshot.TransferFields(IQCMSampleFunction);
            IQCMSampleFunctionSnapshot.Description := IQCMSampleFunction.Description; // TransferFields not working with FlowField, must be done manually
            IQCMSampleFunctionSnapshot.Insert();
        end;
        Snapshot.GetTable(IQCMSampleFunctionSnapshot);
        exit(true);
        // CUSTOMIZATION end
    end;
    procedure OpenCommunicationMethodSnapshotCard(var Snapshot: RecordRef) rHandled: Boolean
    var
        // CUSTOMIZATION begin
        IQCMSampleFunctionSnapshot: Record "My Sample Function Snapshot"; // Change to this implementation's Snapshot record
    begin
        Snapshot.SetTable(IQCMSampleFunctionSnapshot);
        Page.Run(Page::"Sample Function Snapshot", IQCMSampleFunctionSnapshot); // Change to this implementation's Snapshot Card
        exit(true);
        // CUSTOMIZATION end
    end;
    // "IQCM Function" Interface implementation (documented in the Interface object):
    procedure FunctionIsSupported(): Boolean;
    begin
        // CUSTOMIZATION begin
        exit(true);
        // CUSTOMIZATION end
    end;
    procedure CheckFunctionSettings() Handled: Boolean
    begin
        AssertInit();
        // CUSTOMIZATION begin
        // Change to whatever setting checks that needs to be done for this function
        IQCMSampleFunction.TestField("Base Url");
        exit(true);
        // CUSTOMIZATION end
    end;
    procedure InvokeFunction(var IQ: Record "QWESR Integration Queue") Handled: Boolean;
    var
        tTempBlob: Record "QWETB tTempBlob" temporary;
        tTempBlobResponse: Record "QWETB tTempBlob" temporary;
        Parameters: JsonObject;
    begin
        AssertInit();
        // CUSTOMIZATION begin
        IQ.CalcFields("Function Data");
        tTempBlob.Blob := IQ."Function Data";
        Parameters.ReadFrom(tTempBlob.GetAsText());
        CallSampleFunction(Parameters, tTempBlobResponse);
        IQ.Data := tTempBlobResponse.Blob;
        exit(true);
        // CUSTOMIZATION end
    end;
    procedure DirectInvokeFunction(Parameters: JsonObject; var Result: Codeunit "Temp Blob") Handled: Boolean;
    var
        tTempBlobResponse: Record "QWETB tTempBlob" temporary;
    begin
        AssertInit();
        // CUSTOMIZATION begin
        CallSampleFunction(Parameters, tTempBlobResponse);
        tTempBlobResponse.GetAsTempBlob(Result);
        exit(true);
        // CUSTOMIZATION end
    end;
    // Public support functions
    // CUSTOMIZATION begin
    /// <summary>
    /// This function sets up a WebWrapper according to the settings in this Communication Method.
    /// </summary>
    /// <param name="IQCMSampleFunction">The setup record.</param>
    /// <param name="WebWrapper">The WebWrapper that will be configured.</param>
    procedure SetupSampleService(IQCMSampleFunction: Record "My IQ Sample Function"; var WebWrapper: Codeunit "QWETB Web Wrapper")
    begin
        // This is a "dummy implementation" on how a service could be setup
        // This function should configure the service according to the current settings
        Clear(WebWrapper);
        // Configure service
    end;
    /// <summary>
    /// This function returns a parameter object formatted in a way that this Communication Method expects.
    /// This parameter object will then be passed as a parameter when this function is invoked.
    /// </summary>
    /// <param name="AppendToBaseUrl">The Url that will be appended to the base url.</param>
    /// <returns>A JsonObject with all parameters.</returns>
    procedure CreateParameterObject(AppendToBaseUrl: Text): JsonObject
    var
        Param: JsonObject;
    begin
        // This is a sample implementation on how a parameter object could be created.
        // Add all needed parameters as parameter to this function and as JsonObjects in this Parameter object.
        // When this function is invoked with this parameter object, the function ParseParameters() below is used to parse this
        Param.Add('AppendToBaseUrl', AppendToBaseUrl);
        exit(Param);
    end;
    // CUSTOMIZATION end
    // Local support functions:
    /// <summary>
    /// This function makes sure that the SetCommunicationMethodCode() function has been called before doing any other calls that depends on this.
    /// </summary>
    local procedure AssertInit()
    var
        // CUSTOMIZATION begin
        NotInitiatedErr: Label 'Sample Function Handler is not initiated, SetCommunicationMethodCode must be called first. This is a programming error', Locked = true;  // Update this text
    // CUSTOMIZATION end
    begin
        if IQCMSampleFunction.Code = '' then
            Error(NotInitiatedErr);
    end;
    // CUSTOMIZATION begin
    local procedure ParseParameters(Parameter: JsonObject; var pvAppendToBaseUrl: Text)
    var
        JsonHelper: Codeunit "QWESR Json Helper";
    begin
        // This is a sample implementation on how a parameter object, created by CreateParameterObject() above, could be parsed.
        // Update this function to correspond to the parameters added to CreateParameterObject()
        pvAppendToBaseUrl := JsonHelper.GetJSONValue(Parameter, 'AppendToBaseUrl').AsText();
    end;
    local procedure CombineUrlParts(BaseUrl: Text; AppendToBaseUrl: Text): Text
    begin
        // A sample support function
        exit(BaseUrl + AppendToBaseUrl);
    end;
    local procedure CallSampleFunction(Parameters: JsonObject; var TempBlobResponse: Record "QWETB tTempBlob" temporary)
    var
        WebWrapper: Codeunit "QWETB Web Wrapper";
        UrlPart: Text;
        Url: Text;
    begin
        // This is a sample on how this function will be called.
        SetupSampleService(IQCMSampleFunction, WebWrapper); // Setup the service according to any settings
        ParseParameters(Parameters, UrlPart); // This parses the parameter needed
        Url := CombineUrlParts(IQCMSampleFunction."Base Url", UrlPart); // Calculate the url to use
        WebWrapper.CallHttpGet(Url, TempBlobResponse); // Perform the function call
    end;
    var
        IQCMSampleFunction: Record "My IQ Sample Function";
    // CUSTOMIZATION end
}
Enum Extension My Sample Function
An Enum Extension is created to make the new Communication Method a selectable in the UI.
The codeunit "My Sample Function Handler" implements the interfaces "QWESR IQCM" and "QWESR IQCM Function", the enum value Implementation property should reflect that.
enumextension 50010 "My IQIT Sample" extends "QWESR IQCM"
{
    value(50010; "My Sample Function")
    {
        Caption = 'My Sample Function';
        Implementation = "QWESR IQCM" = "My Sample Function Handler",
                         "QWESR IQCM Function" = "My Sample Function Handler";
    }
}
Table My IQ Sample Function
/// <summary>
/// This is the Setup Table for a sample implementation of a "IQ Communication Method".
/// </summary>
table 50010 "My IQ Sample Function"
{
    // ***********************************************************************************************************************************************
    //
    //     All code in between "CUSTOMIZATION begin" and "CUSTOMIZATION end" must be updated to your specific needs
    //
    // ***********************************************************************************************************************************************
    // CUSTOMIZATION begin
    Caption = 'Sample Function Communication Method';
    // CUSTOMIZATION end
    fields
    {
        field(1; "Code"; Code[20])
        {
            DataClassification = CustomerContent;
            Caption = 'Code';
            NotBlank = true;
            TableRelation = "QWESR IQ Communication Method";
        }
        field(9; "Record Time Stamp"; BigInteger)
        {
            DataClassification = CustomerContent;
            Caption = 'Record Time Stamp';
            SqlTimestamp = true; // This is used to know if a new Snapshot records should be created or not
        }
        field(10; Description; Text[50])
        {
            Caption = 'Description';
            FieldClass = FlowField;
            CalcFormula = lookup("QWESR IQ Communication Method".Description where(Code = field(Code)));
            Editable = false;
        }
        // CUSTOMIZATION begin
        field(11; "Base Url"; Text[2000])
        {
            DataClassification = CustomerContent;
            Caption = 'Base Url';
        }
        // CUSTOMIZATION end
    }
    keys
    {
        key(Key1; "Code")
        {
        }
    }
}
Page My IQ Sample Function Card
/// <summary>
/// This is the Setup Page for a sample implementation of a "IQ Communication Method".
/// </summary>
page 50010 "My IQ Sample Function Card"
{
    // ***********************************************************************************************************************************************
    //
    //     All code in between "CUSTOMIZATION begin" and "CUSTOMIZATION end" must be updated to your specific needs
    //
    // ***********************************************************************************************************************************************
    // CUSTOMIZATION begin
    Caption = 'Sample Function Communication Method Card';
    // CUSTOMIZATION end
    PageType = Card;
    DeleteAllowed = false;
    InsertAllowed = false;
    LinksAllowed = false;
    // CUSTOMIZATION begin
    SourceTable = "My IQ Sample Function";
    // CUSTOMIZATION end
    UsageCategory = None;
    layout
    {
        area(content)
        {
            group(Http)
            {
                // CUSTOMIZATION begin
                Caption = 'Sample';
                // CUSTOMIZATION end
                field("Code"; Rec.Code)
                {
                    ApplicationArea = All;
                    Editable = false;
                    ToolTip = 'Specifies the code.';
                }
                field(Description; Rec.Description)
                {
                    ApplicationArea = All;
                    DrillDown = false;
                    ToolTip = 'Specifies the description.';
                }
                // CUSTOMIZATION begin
                field(URL; Rec."Base Url")
                {
                    ApplicationArea = All;
                    ToolTip = 'Specifies the Base Url that will be used when doing the Http Call. This url will prefix any call specific parts of the final url.';
                }
                // CUSTOMIZATION end
            }
        }
    }
}
Table My Sample Function Snapshot
/// <summary>
/// This is the Setup Snapshot Table for a sample implementation of a "IQ Communication Method".
/// This is populated by a TransferFields from the Setup Table (below referred to as "Base Setup Table") of this Communication Method, so the fields should match between the two tables.
///
/// This table is created by:
///
///  - Copy the "Base Setup Table", rename and renumber
///  - Rename field 9 from "Record Time Stamp" to "Snapshot Id"
///  - Remove SqlTimestamp = true; from field 9
///  - Change field 10, Description from FlowField to a normal field and set DataClassification = CustomerContent. Do the same for other FlowFields, if any.
///  - Change Primary Key to field 9, "Snapshot Id"
///  - Add a secondary key for Code
///  - Remove any code
/// </summary>
table 50011 "My Sample Function Snapshot"
{
    // ***********************************************************************************************************************************************
    //
    //     All code in between "CUSTOMIZATION begin" and "CUSTOMIZATION end" must be updated to your specific needs
    //
    // ***********************************************************************************************************************************************
    // CUSTOMIZATION begin
    Caption = 'Sample Function Communication Method Snapshot';
    // CUSTOMIZATION end
    fields
    {
        field(1; "Code"; Code[20])
        {
            DataClassification = CustomerContent;
            Caption = 'Code';
            NotBlank = true;
            TableRelation = "QWESR IQ Communication Method";
        }
        field(9; "Snapshot Id"; BigInteger)
        {
            DataClassification = CustomerContent;
            Caption = 'Snapshot Id';
        }
        field(10; Description; Text[50])
        {
            DataClassification = CustomerContent;
            Caption = 'Description';
        }
        // CUSTOMIZATION begin
        field(11; "Base Url"; Text[2000])
        {
            DataClassification = CustomerContent;
            Caption = 'Base Url';
        }
        // CUSTOMIZATION end
    }
    keys
    {
        key(Key1; "Snapshot Id")
        {
        }
        key(Key2; "Code")
        {
        }
    }
}
Page My Sample Function Snapshot
/// <summary>
/// This is the Setup Snapshot Page for a sample implementation of a "IQ Communication Method".
///
/// This page is created by:
///
///  - Copy the "Base Setup page", rename and renumber
///  - Change SourceTable to the snapshot table
///  - Change to Editable = false
///  - Remove any DeleteAllowed/InsertAllowed properties
///  - Add the GetDataCaptionExpression() function
///  - Set DataCaptionExpression = GetDataCaptionExpression()
///  - Add the "Snapshot Id" page field
///  - Remove any Editable, ShowMandatory or DrillDown properties on fields
///  - Remove any other code
/// </summary>
page 50011 "My Sample Function Snapshot"
{
    // ***********************************************************************************************************************************************
    //
    //     All code in between "CUSTOMIZATION begin" and "CUSTOMIZATION end" must be updated to your specific needs
    //
    // ***********************************************************************************************************************************************
    // CUSTOMIZATION begin
    Caption = 'Sample Function Communication Method Snapshot Card';
    // CUSTOMIZATION end
    PageType = Card;
    LinksAllowed = false;
    // CUSTOMIZATION begin
    SourceTable = "My Sample Function Snapshot";
    // CUSTOMIZATION end
    UsageCategory = None;
    Editable = false;
    DataCaptionExpression = GetDataCaptionExpression();
    layout
    {
        area(content)
        {
            group(Sample)
            {
                // CUSTOMIZATION begin
                Caption = 'Sample';
                // CUSTOMIZATION end
                field("Snapshot Id"; Rec."Snapshot Id")
                {
                    ApplicationArea = All;
                    ToolTip = 'Specifies the unique snapshot ID. This is used to identify this version of the settings.';
                }
                field("Code"; Rec.Code)
                {
                    ApplicationArea = All;
                    ToolTip = 'Specifies the code.';
                }
                field(Description; Rec.Description)
                {
                    ApplicationArea = All;
                    ToolTip = 'Specifies the description.';
                }
                // CUSTOMIZATION begin
                field("Base Url"; Rec."Base Url")
                {
                    ApplicationArea = All;
                    ToolTip = 'Specifies the Base Url that will be used when doing the Http Call. This url will prefix any call specific parts of the final url.';
                }
                // CUSTOMIZATION end
            }
        }
    }
    local procedure GetDataCaptionExpression(): Text
    var
        DataCaptionLbl: Label '%1, %2', Comment = '%1 = Code, %2 = Snapshot Id', Locked = true;
    begin
        // CUSTOMIZATION begin
        exit(StrSubstNo(DataCaptionLbl, Rec.Code, Rec."Snapshot Id"))
        // CUSTOMIZATION end
    end;
}