Page 1803 Assisted Company Setup Wizard, source in 29
Source29
src/Layers/W1/BaseApp/Utilities/AssistedCompanySetupWizard.Page.al620 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.Utilities;
using Microsoft.Bank.BankAccount;
using Microsoft.Foundation.Address;
using Microsoft.Foundation.Company;
using System.Azure.Identity;
using System.Email;
using System.Environment;
using System.Environment.Configuration;
using System.Integration;
using System.IO;
using System.Reflection;
using System.Utilities;
page 1803 "Assisted Company Setup Wizard"
{
Caption = 'Company Setup';
DeleteAllowed = false;
InsertAllowed = false;
LinksAllowed = false;
PageType = NavigatePage;
ShowFilter = false;
SourceTable = "Config. Setup";
SourceTableTemporary = true;
layout
{
area(content)
{
group(Control96)
{
Editable = false;
ShowCaption = false;
Visible = TopBannerVisible and not DoneVisible;
#pragma warning disable AA0100
field("MediaResourcesStandard.""Media Reference"""; MediaResourcesStandard."Media Reference")
#pragma warning restore AA0100
{
ApplicationArea = Basic, Suite;
Editable = false;
ShowCaption = false;
}
}
group(Control98)
{
Editable = false;
ShowCaption = false;
Visible = TopBannerVisible and DoneVisible;
#pragma warning disable AA0100
field("MediaResourcesDone.""Media Reference"""; MediaResourcesDone."Media Reference")
#pragma warning restore AA0100
{
ApplicationArea = Basic, Suite;
Editable = false;
ShowCaption = false;
}
}
group(Control8)
{
ShowCaption = false;
Visible = IntroVisible;
group("Welcome to Company Setup.")
{
Caption = 'Welcome to Company Setup.';
InstructionalText = 'To get started with Business Central, you must provide some basic information about your company. This information is used on external documents, such as sales invoices, and includes your company logo.';
}
group("Let's go!")
{
Caption = 'Let''s go!';
InstructionalText = 'Choose Next so you can specify basic company information.';
}
}
group(Control56)
{
ShowCaption = false;
Visible = CompanyDetailsVisible;
group("Specify your company's address information and logo.")
{
Caption = 'Specify your company''s address information and logo.';
InstructionalText = 'This is used in invoices and other documents where general information about your company is printed.';
field(Name; Rec.Name)
{
ApplicationArea = Basic, Suite;
Caption = 'Company Name';
NotBlank = true;
ShowMandatory = true;
}
field(Address; Rec.Address)
{
ApplicationArea = Basic, Suite;
}
field("Address 2"; Rec."Address 2")
{
ApplicationArea = Basic, Suite;
Visible = false;
}
field("Post Code"; Rec."Post Code")
{
ApplicationArea = Basic, Suite;
}
field(City; Rec.City)
{
ApplicationArea = Basic, Suite;
}
field("Country/Region Code"; Rec."Country/Region Code")
{
ApplicationArea = Basic, Suite;
TableRelation = "Country/Region".Code;
}
field("VAT Registration No."; Rec."VAT Registration No.")
{
ApplicationArea = Basic, Suite;
Visible = false;
}
field("Industrial Classification"; Rec."Industrial Classification")
{
ApplicationArea = Basic, Suite;
NotBlank = true;
ShowMandatory = true;
Visible = false;
}
field(Picture; Rec.Picture)
{
ApplicationArea = Basic, Suite;
Caption = 'Company Logo';
trigger OnValidate()
begin
LogoPositionOnDocumentsShown := Rec.Picture.HasValue;
if LogoPositionOnDocumentsShown then begin
if Rec."Logo Position on Documents" = Rec."Logo Position on Documents"::"No Logo" then
Rec."Logo Position on Documents" := Rec."Logo Position on Documents"::Right;
end else
Rec."Logo Position on Documents" := Rec."Logo Position on Documents"::"No Logo";
CurrPage.Update(true);
end;
}
}
}
group(Control45)
{
ShowCaption = false;
Visible = CommunicationDetailsVisible;
group("Specify the contact details for your company.")
{
Caption = 'Specify the contact details for your company.';
InstructionalText = 'This is used in invoices and other documents where general information about your company is printed.';
field("Phone No."; Rec."Phone No.")
{
ApplicationArea = Basic, Suite;
trigger OnValidate()
var
TypeHelper: Codeunit "Type Helper";
begin
if Rec."Phone No." = '' then
exit;
if not TypeHelper.IsPhoneNumber(Rec."Phone No.") then
Error(InvalidPhoneNumberErr)
end;
}
field("E-Mail"; Rec."E-Mail")
{
ApplicationArea = Basic, Suite;
ExtendedDatatype = EMail;
trigger OnValidate()
var
MailManagement: Codeunit "Mail Management";
begin
if Rec."E-Mail" = '' then
exit;
MailManagement.CheckValidEmailAddress(Rec."E-Mail");
end;
}
field("Home Page"; Rec."Home Page")
{
ApplicationArea = Basic, Suite;
trigger OnValidate()
var
WebRequestHelper: Codeunit "Web Request Helper";
begin
if Rec."Home Page" = '' then
exit;
WebRequestHelper.IsValidUriWithoutProtocol(Rec."Home Page");
end;
}
}
}
group(Control37)
{
ShowCaption = false;
Visible = PaymentDetailsVisible;
group("Specify your company's bank information.")
{
Caption = 'Specify your company''s bank information.';
InstructionalText = 'This information is included on documents that you send to customer and vendors to inform about payments to your bank account.';
field("Bank Name"; Rec."Bank Name")
{
ApplicationArea = Basic, Suite;
}
field("Bank Branch No."; Rec."Bank Branch No.")
{
ApplicationArea = Basic, Suite;
}
field("Bank Account No."; Rec."Bank Account No.")
{
ApplicationArea = Basic, Suite;
trigger OnValidate()
begin
ShowBankAccountCreationWarning := not ValidateBankAccountNotEmpty();
end;
}
field("SWIFT Code"; Rec."SWIFT Code")
{
ApplicationArea = Basic, Suite;
}
field(IBAN; Rec.IBAN)
{
ApplicationArea = Basic, Suite;
}
}
group(" ")
{
Caption = ' ';
InstructionalText = 'To create a bank account that is linked to the related online bank account, you must specify the bank account information above.';
Visible = ShowBankAccountCreationWarning;
}
}
group(Control9)
{
ShowCaption = false;
Visible = DoneVisible;
group("That's it!")
{
Caption = 'That''s it!';
InstructionalText = 'Choose Finish to prepare the application for first use. This will take a few moments.';
field(HelpLbl; HelpLbl)
{
ApplicationArea = Basic, Suite;
Editable = false;
ShowCaption = false;
trigger OnDrillDown()
begin
HyperLink(HelpLinkTxt);
end;
}
}
}
}
}
actions
{
area(processing)
{
action(ActionBack)
{
ApplicationArea = Basic, Suite;
Caption = 'Back';
Enabled = BackEnabled;
Image = PreviousRecord;
InFooterBar = true;
trigger OnAction()
begin
NextStep(true);
end;
}
action(ActionNext)
{
ApplicationArea = Basic, Suite;
Caption = 'Next';
Enabled = NextEnabled;
Image = NextRecord;
InFooterBar = true;
trigger OnAction()
begin
NextStep(false);
end;
}
action(ActionFinish)
{
ApplicationArea = Basic, Suite;
Caption = 'Finish';
Enabled = FinishEnabled;
Image = Approve;
InFooterBar = true;
trigger OnAction()
var
GuidedExperience: Codeunit "Guided Experience";
AssistedCompanySetup: Codeunit "Assisted Company Setup";
ErrorText: Text;
begin
BankAccount.TransferFields(TempBankAccount, true);
AssistedCompanySetup.ApplyUserInput(Rec, BankAccount, AccountingPeriodStartDate, false);
UpdateCompanyDisplayNameIfNameChanged();
GuidedExperience.CompleteAssistedSetup(ObjectType::Page, Page::"Assisted Company Setup Wizard");
if (BankAccount."No." <> '') and (not TempOnlineBankAccLink.IsEmpty) then
if not TryLinkBankAccount() then
ErrorText := GetLastErrorText;
CurrPage.Close();
if ErrorText <> '' then begin
Message(StrSubstNo(BankAccountLinkingFailedMsg, ErrorText));
PAGE.Run(PAGE::"Bank Account List");
end;
end;
}
}
}
trigger OnAfterGetRecord()
begin
LogoPositionOnDocumentsShown := Rec.Picture.HasValue;
end;
trigger OnInit()
begin
InitializeRecord();
LoadTopBanners();
end;
trigger OnOpenPage()
var
EnvironmentInfo: Codeunit "Environment Information";
begin
Clear(AccountingPeriodStartDate);
ResetWizardControls();
ShowIntroStep();
if EnvironmentInfo.IsSaaS() then
GetCompanyDetailsFromMicrosoft365();
end;
trigger OnQueryClosePage(CloseAction: Action): Boolean
var
GuidedExperience: Codeunit "Guided Experience";
begin
if CloseAction = ACTION::OK then
if GuidedExperience.AssistedSetupExistsAndIsNotComplete(ObjectType::Page, PAGE::"Assisted Company Setup Wizard") then
if not Confirm(NotSetUpQst, false) then
Error('');
end;
var
MediaRepositoryStandard: Record "Media Repository";
TempBankAccount: Record "Bank Account" temporary;
BankAccount: Record "Bank Account";
TempOnlineBankAccLink: Record "Online Bank Acc. Link" temporary;
MediaRepositoryDone: Record "Media Repository";
MediaResourcesStandard: Record "Media Resources";
MediaResourcesDone: Record "Media Resources";
ClientTypeManagement: Codeunit "Client Type Management";
CompanyInfoNotification: Notification;
AccountingPeriodStartDate: Date;
Step: Option Intro,"Company Details","Communication Details","Payment Details",Done;
BackEnabled: Boolean;
NextEnabled: Boolean;
FinishEnabled: Boolean;
TopBannerVisible: Boolean;
IntroVisible: Boolean;
CompanyDetailsVisible: Boolean;
CommunicationDetailsVisible: Boolean;
PaymentDetailsVisible: Boolean;
DoneVisible: Boolean;
ShowCompanyInfoDownloadedNotification: Boolean;
IsCompanyInfoDownloadedNotificationEnabled: Boolean;
NotificationSent: Boolean;
CompanyInfoDownloadedMsg: Label 'The information on this page was downloaded from Microsoft 365. Before you proceed, verify that it''s correct.';
NotSetUpQst: Label 'The application is not set up. This guide will display the next time you sign in. If you do not want the guide to start, go to the Companies page and turn off the guide.\\Are you sure that you want to close this guide?';
HelpLbl: Label 'Learn more about setting up your company';
HelpLinkTxt: Label 'http://go.microsoft.com/fwlink/?LinkId=746160', Locked = true;
LogoPositionOnDocumentsShown: Boolean;
ShowBankAccountCreationWarning: Boolean;
InvalidPhoneNumberErr: Label 'The phone number is invalid.';
BankAccountLinkingFailedMsg: Label 'Linking the company bank account failed with the following message:\''%1''\Link the company bank account from the Bank Accounts page.', Comment = '%1 - an error message';
GraphURLEndpointLbl: Label '%1v1.0/organization', Locked = true;
ResourceNameTxt: Label 'Azure Service', Locked = true;
BearerLbl: Label 'Bearer %1', Comment = '%1 = Access Token', Locked = true;
local procedure NextStep(Backwards: Boolean)
begin
ResetWizardControls();
if Backwards then
Step := Step - 1
else
Step := Step + 1;
case Step of
Step::Intro:
ShowIntroStep();
Step::"Company Details":
begin
SendCompanyInfoDownloadedFromOfficeNotification();
ShowCompanyDetailsStep();
end;
Step::"Communication Details":
ShowCommunicationDetailsStep();
Step::"Payment Details":
begin
ShowPaymentDetailsStep();
ShowBankAccountCreationWarning := not ValidateBankAccountNotEmpty();
end;
Step::Done:
begin
HideCompanyInfoDownloadedFromOfficeNotification();
ShowDoneStep();
end;
end;
CurrPage.Update(true);
end;
local procedure ShowIntroStep()
begin
IntroVisible := true;
BackEnabled := false;
end;
local procedure ShowCompanyDetailsStep()
begin
CompanyDetailsVisible := true;
end;
local procedure ShowCommunicationDetailsStep()
begin
CommunicationDetailsVisible := true;
end;
local procedure ShowPaymentDetailsStep()
begin
PaymentDetailsVisible := true;
end;
local procedure ShowDoneStep()
begin
DoneVisible := true;
NextEnabled := false;
FinishEnabled := true;
end;
local procedure ResetWizardControls()
begin
// Buttons
BackEnabled := true;
NextEnabled := true;
FinishEnabled := false;
// Tabs
IntroVisible := false;
CompanyDetailsVisible := false;
CommunicationDetailsVisible := false;
PaymentDetailsVisible := false;
DoneVisible := false;
end;
local procedure InitializeRecord()
var
CompanyInformation: Record "Company Information";
begin
Rec.Init();
if CompanyInformation.Get() then begin
Rec.TransferFields(CompanyInformation);
if Rec.Name = '' then
Rec.Name := CompanyName;
end else
Rec.Name := CompanyName;
Rec.Insert();
end;
local procedure LoadTopBanners()
begin
if MediaRepositoryStandard.Get('AssistedSetup-NoText-400px.png', Format(ClientTypeManagement.GetCurrentClientType())) and
MediaRepositoryDone.Get('AssistedSetupDone-NoText-400px.png', Format(ClientTypeManagement.GetCurrentClientType()))
then
if MediaResourcesStandard.Get(MediaRepositoryStandard."Media Resources Ref") and
MediaResourcesDone.Get(MediaRepositoryDone."Media Resources Ref")
then
TopBannerVisible := MediaResourcesDone."Media Reference".HasValue;
end;
local procedure ValidateBankAccountNotEmpty(): Boolean
begin
exit((Rec."Bank Account No." <> '') or TempOnlineBankAccLink.IsEmpty);
end;
[TryFunction]
local procedure TryLinkBankAccount()
begin
BankAccount.OnMarkAccountLinkedEvent(TempOnlineBankAccLink, BankAccount);
end;
local procedure UpdateCompanyDisplayNameIfNameChanged()
var
Company: Record Company;
begin
if COMPANYPROPERTY.DisplayName() = Rec.Name then
exit;
Company.Get(CompanyName);
Company."Display Name" := Rec.Name;
Company.Modify();
end;
local procedure GetCompanyDetailsFromMicrosoft365()
var
JsonCompanyInfo: JsonObject;
begin
if TryDownloadCompanyDetailsFromMicrosoft365(JsonCompanyInfo) then
if JsonCompanyInfo.Keys().Count > 0 then begin
SetCompanyInfo(JsonCompanyInfo);
ShowCompanyInfoDownloadedNotification := true;
end;
end;
[TryFunction]
local procedure TryDownloadCompanyDetailsFromMicrosoft365(var JsonCompanyInfo: JsonObject)
var
AzureADMgt: Codeunit "Azure AD Mgt.";
UrlHelper: Codeunit "Url Helper";
Client: HttpClient;
RequestMessage: HttpRequestMessage;
ResponseMessage: HttpResponseMessage;
JsonResponse: JsonObject;
JsonPropValue: JsonToken;
CompaniesJsonArray: JsonArray;
JsonContent: Text;
AccessToken: SecretText;
begin
AccessToken := AzureADMgt.GetAccessTokenAsSecretText(UrlHelper.GetGraphUrl(), ResourceNameTxt, false);
RequestMessage.Method('GET');
RequestMessage.SetRequestUri(StrSubstNo(GraphURLEndpointLbl, UrlHelper.GetGraphUrl()));
Client.DefaultRequestHeaders().Add('Authorization', SecretStrSubstNo(BearerLbl, AccessToken));
Client.DefaultRequestHeaders().Add('Accept', 'application/json');
if Client.Send(RequestMessage, ResponseMessage) then
if ResponseMessage.HttpStatusCode() = 200 then begin
ResponseMessage.Content.ReadAs(JsonContent);
JsonResponse.ReadFrom(JsonContent);
JsonResponse.Get('value', JsonPropValue);
CompaniesJsonArray := JsonPropValue.AsArray();
// if there are multiple companies do not automatically update the info
if CompaniesJsonArray.Count() <> 1 then
exit;
CompaniesJsonArray.Get(0, JsonPropValue);
JsonCompanyInfo := JsonPropValue.AsObject();
end
end;
local procedure SetCompanyInfo(CompanyInfoObj: JsonObject)
var
JsonPropValue: JsonToken;
begin
CompanyInfoObj.Get('displayName', JsonPropValue);
Rec.Name := CopyStr(ProcessJsonPropertyValue(JsonPropValue), 1, MaxStrLen(Rec.Name));
CompanyInfoObj.Get('street', JsonPropValue);
Rec.Address := CopyStr(ProcessJsonPropertyValue(JsonPropValue), 1, MaxStrLen(Rec.Address));
CompanyInfoObj.Get('postalCode', JsonPropValue);
Rec."Post Code" := CopyStr(ProcessJsonPropertyValue(JsonPropValue), 1, MaxStrLen(Rec."Post Code"));
CompanyInfoObj.Get('city', JsonPropValue);
Rec.City := CopyStr(ProcessJsonPropertyValue(JsonPropValue), 1, MaxStrLen(Rec.City));
CompanyInfoObj.Get('countryLetterCode', JsonPropValue);
Rec."Country/Region Code" := CopyStr(ProcessJsonPropertyValue(JsonPropValue), 1, MaxStrLen(Rec."Country/Region Code"));
CurrPage.Update();
end;
local procedure ProcessJsonPropertyValue(JsonPropValue: JsonToken): Text;
var
Str: Text;
begin
Str := Format(JsonPropValue);
Str := DelChr(Str, '=', '"');
if Str = 'null' then
exit('');
exit(Str);
end;
local procedure SendCompanyInfoDownloadedFromOfficeNotification()
begin
if ShowCompanyInfoDownloadedNotification and not NotificationSent then begin
NotificationSent := true;
IsCompanyInfoDownloadedNotificationEnabled := true;
CompanyInfoNotification.Message := CompanyInfoDownloadedMsg;
CompanyInfoNotification.Send();
end;
end;
local procedure HideCompanyInfoDownloadedFromOfficeNotification()
begin
if IsCompanyInfoDownloadedNotificationEnabled then begin
IsCompanyInfoDownloadedNotificationEnabled := false;
CompanyInfoNotification.Recall();
end;
end;
}