Page 1651 Curr. Exch. Rate Service Card

App
Base Application
Namespace
Microsoft.Finance.Currency
Versions
17-28
Source table
1650

Events, 3

Versions171819202122232425262728

Source29

Source in 29

src/Layers/W1/BaseApp/Finance/Currency/CurrExchRateServiceCard.Page.al340 lines, Copyright (c) Microsoft Corporation. MIT

// ------------------------------------------------------------------------------------------------
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License. See License.txt in the project root for license information.
// ------------------------------------------------------------------------------------------------
namespace Microsoft.Finance.Currency;

using Microsoft.Utilities;
using System;
using System.Environment;
using System.Environment.Configuration;
using System.Integration;
using System.IO;
using System.Reflection;
using System.Xml;

/// <summary>
/// Provides a detailed card interface for configuring currency exchange rate service connections.
/// Manages service setup, authentication, data exchange mappings, and automated update scheduling.
/// </summary>
/// <remarks>
/// Source Table: Curr. Exch. Rate Update Setup (1650). Supports configuration of external
/// exchange rate providers, data transformation mappings, and job queue integration
/// for automated currency rate synchronization.
/// </remarks>
page 1651 "Curr. Exch. Rate Service Card"
{
    Caption = 'Currency Exch. Rate Service';
    SourceTable = "Curr. Exch. Rate Update Setup";

    layout
    {
        area(content)
        {
            group(General)
            {
                Caption = 'General';
                field("Code"; Rec.Code)
                {
                    ApplicationArea = Suite;
                    Editable = NotEnabledAndCurrPageEditable;
                }
                field(Description; Rec.Description)
                {
                    ApplicationArea = Suite;
                    Editable = NotEnabledAndCurrPageEditable;
                }
                field(Enabled; Rec.Enabled)
                {
                    ApplicationArea = Suite;

                    trigger OnValidate()
                    begin
                        NotEnabledAndCurrPageEditable := not Rec.Enabled and CurrPage.Editable;
                        EnabledAndCurrPageEditable := Rec.Enabled and CurrPage.Editable;
                        CurrPage.Update();
                    end;
                }
                field(ShowEnableWarning; ShowEnableWarning)
                {
                    ApplicationArea = Suite;
                    Editable = false;
                    ShowCaption = false;
                    Enabled = EnabledAndCurrPageEditable;

                    trigger OnDrillDown()
                    begin
                        DrilldownCode();
                    end;
                }
            }
            group(Service)
            {
                Caption = 'Service';
                field(ServiceURL; WebServiceURL)
                {
                    ApplicationArea = Suite;
                    Caption = 'Service URL';
                    Editable = NotEnabledAndCurrPageEditable;
                    MultiLine = true;
                    ToolTip = 'Specifies if the currency exchange rate service is enabled.';

                    trigger OnValidate()
                    begin
                        Rec.SetWebServiceURL(WebServiceURL);
                        GenerateXMLStructure();
                    end;
                }
                field("Service Provider"; Rec."Service Provider")
                {
                    ApplicationArea = Suite;
                    Editable = NotEnabledAndCurrPageEditable;
                }
                field("Terms of Service"; Rec."Terms of Service")
                {
                    ApplicationArea = Suite;
                    Editable = NotEnabledAndCurrPageEditable;
                }
                field("Log Web Requests"; Rec."Log Web Requests")
                {
                    ApplicationArea = Basic, Suite;
                    Editable = NotEnabledAndCurrPageEditable;
                    Visible = not IsSoftwareAsService;
                }
            }
            part(SimpleDataExchSetup; "Data Exch. Setup Subform")
            {
                ApplicationArea = Suite;
                Editable = NotEnabledAndCurrPageEditable;
            }
        }
    }

    actions
    {
        area(processing)
        {
            action(Preview)
            {
                ApplicationArea = Suite;
                Caption = 'Preview';
                Image = ReviewWorksheet;
                ToolTip = 'Test the setup of the currency exchange rate service to make sure the service is working.';

                trigger OnAction()
                var
                    TempCurrencyExchangeRate: Record "Currency Exchange Rate" temporary;
                    UpdateCurrencyExchangeRates: Codeunit "Update Currency Exchange Rates";
                begin
                    Rec.TestField(Code);
                    Rec.VerifyServiceURL();
                    Rec.VerifyDataExchangeLineDefinition();
                    UpdateCurrencyExchangeRates.GenerateTempDataFromService(TempCurrencyExchangeRate, Rec);
                    PAGE.Run(PAGE::"Currency Exchange Rates", TempCurrencyExchangeRate);
                end;
            }
            action(JobQueueEntry)
            {
                ApplicationArea = Suite;
                Caption = 'Job Queue Entry';
                Enabled = Rec.Enabled;
                Image = JobListSetup;
                ToolTip = 'View or edit the job that updates the exchange rates from the service. For example, you can see the status or change how often rates are updated.';

                trigger OnAction()
                begin
                    Rec.ShowJobQueueEntry();
                end;
            }
        }
        area(Promoted)
        {
            group(Category_Process)
            {
                Caption = 'Process', Comment = 'Generated from the PromotedActionCategories property index 1.';

                actionref(Preview_Promoted; Preview)
                {
                }
                actionref(JobQueueEntry_Promoted; JobQueueEntry)
                {
                }
            }
            group(Category_Report)
            {
                Caption = 'Report', Comment = 'Generated from the PromotedActionCategories property index 2.';
            }
            group(Category_Category4)
            {
                Caption = 'Setup', Comment = 'Generated from the PromotedActionCategories property index 3.';
            }
        }
    }

    trigger OnAfterGetCurrRecord()
    begin
        if not MakeWebServiceURL() then
            exit;

        UpdateSimpleMappingsPart();
        UpdateBasedOnEnable();
    end;

    trigger OnInsertRecord(BelowxRec: Boolean): Boolean
    var
        TempField: Record "Field" temporary;
        MapCurrencyExchangeRate: Codeunit "Map Currency Exchange Rate";
    begin
        MapCurrencyExchangeRate.GetSuggestedFields(TempField);
        CurrPage.SimpleDataExchSetup.PAGE.SetSuggestedField(TempField);
        UpdateSimpleMappingsPart();
    end;

    trigger OnOpenPage()
    var
        EnvironmentInfo: Codeunit "Environment Information";
        ApplicationAreaMgmtFacade: Codeunit "Application Area Mgmt. Facade";
    begin
        ApplicationAreaMgmtFacade.CheckAppAreaOnlyBasic();

        UpdateBasedOnEnable();
        IsSoftwareAsService := EnvironmentInfo.IsSaaS();
    end;

    trigger OnQueryClosePage(CloseAction: Action): Boolean
    begin
        if not Rec.Enabled then
            if not Confirm(StrSubstNo(EnableServiceQst, CurrPage.Caption), true) then
                exit(false);
    end;

    var
        TempXMLBuffer: Record "XML Buffer" temporary;
        WebServiceURL: Text;
        EnabledWarningTok: Label 'You must disable the service before you can make changes.';
        DisableEnableQst: Label 'Do you want to disable currency exchange rate service?';
        TheXMLStructureCannotBeReadMsg: Label 'The XML structure cannot be read. Try to verify if the service is valid.';
        PreviousWebServiceURL: Text;
        IsSoftwareAsService: Boolean;
        ShowEnableWarning: Text;
        EnableServiceQst: Label 'The %1 is not enabled. Are you sure you want to exit?', Comment = '%1 = This Page Caption (Currency Exch. Rate Service)';
        XmlStructureIsNotSupportedErr: Label ' The provided url does not contain a supported structure.';

    protected var
        NotEnabledAndCurrPageEditable: Boolean;
        EnabledAndCurrPageEditable: Boolean;

    local procedure UpdateSimpleMappingsPart()
    begin
        CurrPage.SimpleDataExchSetup.PAGE.SetDataExchDefCode(Rec."Data Exch. Def Code");
        CurrPage.SimpleDataExchSetup.PAGE.UpdateData();
        CurrPage.SimpleDataExchSetup.PAGE.Update(false);
        CurrPage.SimpleDataExchSetup.PAGE.SetSourceToBeMandatory(Rec."Web Service URL".HasValue);
    end;

    local procedure MakeWebServiceURL() Result: Boolean
    var
        ServiceURL: Text;
        IsHandled: Boolean;
    begin
        IsHandled := false;
        OnBeforeMakeWebServiceURL(Rec, Result, IsHandled, WebServiceURL);
        if IsHandled then
            exit(Result);

        WebServiceURL := Rec.GetWebServiceURL(ServiceURL);
        if WebServiceURL <> '' then
            if not GenerateXMLStructure() then begin
                if PreviousWebServiceURL <> ServiceUrl then
                    Message(TheXMLStructureCannotBeReadMsg);
                PreviousWebServiceURL := ServiceURL;
                ClearLastError();
                exit(false);
            end;

        exit(true);
    end;

    [TryFunction]
    local procedure GenerateXMLStructure()
    var
        ServiceURL: Text;
        IsHandled: Boolean;
    begin
        IsHandled := false;
        OnBeforeGenerateXMLStructure(Rec, IsHandled);
        if IsHandled then
            exit;

        TempXMLBuffer.Reset();
        TempXMLBuffer.DeleteAll();
        Rec.GetWebServiceURL(ServiceURL);
        if Rec.GetXMLStructure(TempXMLBuffer, ServiceURL) then begin
            TempXMLBuffer.Reset();
            CurrPage.SimpleDataExchSetup.PAGE.SetXMLDefinition(TempXMLBuffer);
        end else
            ShowHttpError();
    end;

    local procedure UpdateBasedOnEnable()
    begin
        NotEnabledAndCurrPageEditable := not Rec.Enabled and CurrPage.Editable;
        EnabledAndCurrPageEditable := Rec.Enabled and CurrPage.Editable;
        ShowEnableWarning := '';
        OnUpdateBasedOnEnableOnBeforeSetShowEnableWarning(Rec);
        if CurrPage.Editable and Rec.Enabled then
            ShowEnableWarning := EnabledWarningTok;
    end;

    local procedure DrilldownCode()
    begin
        if Confirm(DisableEnableQst, true) then begin
            Rec.Enabled := false;
            UpdateBasedOnEnable();
            CurrPage.Update();
        end;
    end;

    local procedure ShowHttpError()
    var
        ActivityLog: Record "Activity Log";
        WebRequestHelper: Codeunit "Web Request Helper";
        XMLDOMMgt: Codeunit "XML DOM Management";
        WebException: DotNet WebException;
        XmlNode: DotNet XmlNode;
        ResponseInputStream: InStream;
        ErrorText: Text;
    begin
        ErrorText := WebRequestHelper.GetWebResponseError(WebException, WebServiceURL);

        ActivityLog.LogActivity(Rec, ActivityLog.Status::Failed, Rec."Service Provider", Rec.Description, ErrorText);

        if IsNull(WebException.Response) then
            Error(ErrorText);

        ResponseInputStream := WebException.Response.GetResponseStream();

        XMLDOMMgt.LoadXMLNodeFromInStream(ResponseInputStream, XmlNode);

        ErrorText := XmlStructureIsNotSupportedErr;

        Error(ErrorText);
    end;

    [IntegrationEvent(false, false)]
    local procedure OnBeforeMakeWebServiceURL(var CurrExchRateUpdateSetup: Record "Curr. Exch. Rate Update Setup"; var Result: Boolean; var IsHandled: Boolean; var WebServiceURL: Text)
    begin
    end;

    [IntegrationEvent(false, false)]
    local procedure OnBeforeGenerateXMLStructure(var CurrExchRateUpdateSetup: Record "Curr. Exch. Rate Update Setup"; var IsHandled: Boolean)
    begin
    end;

    [IntegrationEvent(false, false)]
    local procedure OnUpdateBasedOnEnableOnBeforeSetShowEnableWarning(var CurrExchRateUpdateSetup: Record "Curr. Exch. Rate Update Setup")
    begin
    end;
}