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;
}