Футбол и Dynamics 365 Business Central? Да, это возможно!

В этом примере я продемонстрирую насколько легко вы можете интегрировать продукты Microsoft Dynamics 365 (на примере Business Central) со сторонними сервисами, а также рассказу как использовать новый функционал Headlines.


Я создал небольшое приложение:

fifa dynamics 365 business central extension

Заинтригованы? Тогда предлагаю для начала взглянуть на этот API с массой ценной информации.

Используя этот VSCode extension создаем следующие объекты:

  1. Таблица
table 50018 "Russia 2018 Results"
{

    fields
    {
        field(1; MathNo; Integer)
        {
            DataClassification = ToBeClassified;
            Caption = 'Match No.';

        }
        field(2; HomeTeam; text[100])
        {
            DataClassification = ToBeClassified;
            Caption = 'Home Team';
        }
        field(3; AwayTeam; text[100])
        {
            DataClassification = ToBeClassified;
            Caption = 'Away Team';
        }
        field(4; HomeTeamResult; text[2])
        {
            DataClassification = ToBeClassified;
            Caption = 'Home Team Result';
        }   
        field(5; AwayTeamResult; Text[2])
        {
            DataClassification = ToBeClassified;
            Caption = 'Away Team Result';
        }   
        field(6; City; text[100])
        {
            DataClassification = ToBeClassified;
            Caption = 'City';
        }      
        field(7; DateAndTime; DateTime)
        {
            DataClassification = ToBeClassified;
            Caption = 'Match Date and Time';
        }        
        field(8; MatchStatus; Option)                  
        {
            DataClassification = ToBeClassified;
            Caption = 'Match Status';
            OptionMembers = Finished,"Not Started",,Playing,,,,,,,,,Preparing;

        }

    }

    procedure RefreshResults();
    var
        RefreshResults : Codeunit "Russia 2018 Results management";
    begin
        RefreshResults.Refresh();
    end;

}

2. Страница

page 50018 "Russia 2018 Results List"
{
    PageType = List;
    SourceTable = "Russia 2018 Results";
    CaptionML=ENU='Russia 2018 Results';
    Editable = false;
    ApplicationArea = All;
    UsageCategory = Lists;

    layout
    {
        area(content)
        {
            repeater(General)
            {
               field(MathNo;MathNo) 
               {
                   ApplicationArea = All;
               }
               field(MatchStatus;MatchStatus)
               {
                   ApplicationArea = All;
               }
               field(HomeTeam;HomeTeam)
               {
                   ApplicationArea = All;
               }
               field(HomeTeamResult;HomeTeamResult)
               {
                   ApplicationArea = All;
               }
               field(AwayTeam;AwayTeam)
               {
                   ApplicationArea = All;
               }
               field(AwayTeamResult;AwayTeamResult)
               {
                   ApplicationArea = All;
               }
               field(City;City)
               {
                   ApplicationArea = All;
               }
               field(DateAndTime;DateAndTime)
               {
                   ApplicationArea = All;
               }

            }
        }
    }

    actions
    {
        area(processing)
        {
            action(RefreshResults)
            {
                CaptionML=ENU='Refresh Results';
                Promoted=true;
                PromotedCategory=Process;
                Image=RefreshLines;
                ApplicationArea = All;
                trigger OnAction();
                begin
                    RefreshResults();
                    CurrPage.Update;
                    if FindFirst then;
                end;
            }
        }
    }
}

3. Код-юнит

codeunit 50018 "Russia 2018 Results management"
{
    trigger OnRun()
    begin
        Refresh();
    end;

    procedure Refresh();
    var
        Results : Record "Russia 2018 Results";
        HttpClient : HttpClient;
        ResponseMessage : HttpResponseMessage;
        JsonToken : JsonToken;
        JsonValue : JsonValue;
        JsonObject : JsonObject;
        JsonArray : JsonArray;
        JsonText : text;
        i : Integer;

    begin
        Results.DeleteAll;
        HttpClient.DefaultRequestHeaders.Add('User-Agent','Dynamics 365');
        if not HttpClient.Get('https://api.fifa.com/api/v1/calendar/matches?idseason=254645&idcompetition=17&language=en-GB&count=100',
                              ResponseMessage)
        then
            Error('The call to the web service failed.');

        if not ResponseMessage.IsSuccessStatusCode then
            error('The web service returned an error message:\' +
                  'Status code: %1' +
                  'Description: %2',
                  ResponseMessage.HttpStatusCode,
                  ResponseMessage.ReasonPhrase);
        
        ResponseMessage.Content.ReadAs(JsonText);
        
        JsonToken.ReadFrom(JsonText);
        JsonObject := JsonToken.AsObject;
        JsonObject.SelectToken('Results', JsonToken);
        Jsonarray := JsonToken.AsArray;
        for i := 0 to JsonArray.Count - 1 do
        begin
            JsonArray.Get(i, JsonToken);
            InsertResults(JsonToken);
        end;
    end;

    procedure InsertResults(JsonToken : JsonToken);
    var
        JsonObject : JsonObject;
        Results : Record "Russia 2018 Results";
        JsonObjectChild : JsonObject;
        JsonTokenChild : JsonToken;
        JsonArrayChild : JsonArray;
    begin
        JsonObject := JsonToken.AsObject;

        Results.init;
        Evaluate(Results.MathNo, SelectJsonToken(JsonObject, '$.MatchNumber'));
        if JsonObject.SelectToken('$.Home.TeamName', JsonTokenChild) then
            Results.HomeTeam := GetChildArrayValue(JsonTokenChild, '$.Description');
        Results.HomeTeamResult := SelectJsonToken(JsonObject, '$.HomeTeamScore');

        if JsonObject.SelectToken('$.Away.TeamName', JsonTokenChild) then
            Results.AwayTeam := GetChildArrayValue(JsonTokenChild, '$.Description');        
        Results.AwayTeamResult := SelectJsonToken(JsonObject, '$.AwayTeamScore');

        Evaluate(Results.MatchStatus, SelectJsonToken(JsonObject, '$.MatchStatus')); 

        if JsonObject.SelectToken('$.Stadium.CityName', JsonTokenChild) then
            Results.City := GetChildArrayValue(JsonTokenChild, '$.Description');

        Results.DateAndTime := GetDateTime(SelectJsonToken(JsonObject, '$.LocalDate')); 
        Results.Insert;
    end;

    local procedure SelectJsonToken(JsonObject: JsonObject; Path: text): text;
    var
        JsonToken: JsonToken;
    begin
        if not JsonObject.SelectToken(Path, JsonToken) then
            exit('');
        if JsonToken.AsValue.IsNull then
            exit('');
        exit(jsontoken.asvalue.astext);
    end;

    local procedure GetChildArrayValue(JsonTokenChild : JsonToken; ChildName : text) : Text
    var
        JsonObjectChild : JsonObject;
        JsonArrayChild : JsonArray;
    begin
        JsonArrayChild := JsonTokenChild.AsArray;
        JsonArrayChild.Get(0, JsonTokenChild);
        JsonObjectChild := JsonTokenChild.AsObject;
        exit(SelectJsonToken(JsonObjectChild, ChildName));
    end;

    local procedure GetDateTime(Json : text) :  DateTime
    var
        Day : Integer;
        Month : Integer;       
        Year : Integer;       
        TheTime : Time; 
    begin
        evaluate(Day, copystr(Json,9,2));
        evaluate(Month, copystr(Json,6,2));
        evaluate(Year, copystr(Json,1,4));
        evaluate(TheTime, copystr(Json,12,8));
        Exit(createdatetime(DMY2DATE(Day, Month, Year), TheTime));  
    end;
}

Затем публикуем расширение и ищем страницу “Russia 2018”

dynamics 365 business central extension russia

Открываем и обновляем страницу. Появляются результаты – список всех матчей.

dynamics 365 business central football

Однако это еще не все. Давайте выведем эту информацию в ролевой центр чтобы видеть результаты матчей не делая лишних кликов.

Для этого потребуется еще один page extension для ролевого центра.

pageextension 50018 Headline extends "Headline RC Business Manager"
{
    layout
    {
        addafter(Control4)
        {
            field(NowPlaying;NowPlaying)
            {
                ApplicationArea = All;
            }
            field(LastGame;LastGame)
            {
                ApplicationArea = All;
            }            
        }
    }
    
  
    var
        LastGame: Text;
        NowPlaying : Text;

    trigger OnOpenPage()
    var
        Result : Record "Russia 2018 Results";
        ResultMgt : Codeunit "Russia 2018 Results management";
        HeadlineMgt : Codeunit "Headline Management";
    begin
        ResultMgt.Refresh();
        Result.SetRange(MatchStatus, Result.MatchStatus::Finished);
        If Result.FindLast() then
            LastGame := 'Last game: ' + Result.HomeTeam + ' ' + Result.HomeTeamResult + ' - ' +
                            Result.AwayTeamResult + ' ' + Result.AwayTeam;
        HeadlineMgt.GetHeadlineText('Russia 2018 World Cup', LastGame, LastGame);

        Result.SetRange(MatchStatus, Result.MatchStatus::Playing);
        If Result.FindLast() then
            NowPlaying := 'Now playing: ' + Result.HomeTeam + ' ' + Result.HomeTeamResult + ' - ' +
                            Result.AwayTeamResult + ' ' + Result.AwayTeam
        else
            NowPlaying := 'No games at current time';
        HeadlineMgt.GetHeadlineText('Russia 2018 World Cup', NowPlaying, NowPlaying);
    end;
}

Теперь ролевой центр выглядит вот так: Football Manager вместо Business Manager:

dynamics 365 role center

Надеюсь пример понравился, кстати *.app файл можно скачать вот здесь.

Блог Андрея Балудина