Codeunit 2114 O365 HTML Templ. Mgt.
- App
- Base Application
- Versions
- 17-28
Procedures, 8Events, 3Obsolete, 1
Versions171819202122232425262728
Source29
Source in 29
src/Layers/W1/BaseApp/Invoicing/O365HTMLTemplMgt.Codeunit.al498 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.
// ------------------------------------------------------------------------------------------------
#pragma warning disable AA0247
codeunit 2114 "O365 HTML Templ. Mgt."
{
Permissions = TableData "Payment Reporting Argument" = rimd;
trigger OnRun()
begin
end;
var
InvoiceNoTxt: Label 'Invoice No.';
EstimateNoTxt: Label 'Estimate No.';
ValidUntilTxt: Label 'Valid until';
TotalTxt: Label 'Total %1', Comment = '%1 = Currency Code';
YourInvoiceTxt: Label 'Your Invoice';
YourEstimateTxt: Label 'Your Estimate';
WantToPayOnlineQst: Label 'Want to pay online?';
PaymentInvitationTxt: Label 'You can pay this invoice online. It''s quick and easy.';
CompanyInformation: Record "Company Information";
CompanyInfoRead: Boolean;
EmailSentToTxt: Label 'This email was sent to';
ThankYouForYourBusinessTxt: Label 'Thank you for your business.';
InvoiceFromTitleTxt: Label 'Invoice from %1', Comment = 'This is a mail title. %1 - company name';
EstimateFromTitleTxt: Label 'Estimate from %1', Comment = 'This is a mail title. %1 - company name';
#if not CLEAN27
[Obsolete('Replaced with CreateEmailBodyFromReportSelections that accepts a TempBlob as additional parameter.', '27.0')]
procedure CreateEmailBodyFromReportSelections(ReportSelections: Record "Report Selections"; RecordVariant: Variant; MailTo: Text; MailText: Text) OutputFileName: Text[250]
var
FileMgt: Codeunit "File Management";
HTMLText: Text;
begin
OutputFileName := CopyStr(FileMgt.ServerTempFileName('html'), 1, 250);
HTMLText := CreateHTMLTextFromReportSelections(ReportSelections, RecordVariant, MailTo, MailText);
SaveHTML(OutputFileName, HTMLText);
end;
#endif
/// <summary>
/// Creates an email body from the report selections into TempBlob.
/// </summary>
/// <param name="ReportSelections">Report Selections used to create email body</param>
/// <param name="RecordVariant">Related record variant</param>
/// <param name="MailTo">Recipient email address</param>
/// <param name="MailText">Additional mail text</param>
/// <param name="TempBlob">Return value: TempBlob containing the body</param>
procedure CreateEmailBodyFromReportSelections(ReportSelections: Record "Report Selections"; RecordVariant: Variant; MailTo: Text; MailText: Text; var TempBlob: Codeunit "Temp Blob")
var
HTMLText: Text;
EmailBodyOutStream: OutStream;
begin
Clear(TempBlob);
HTMLText := CreateHTMLTextFromReportSelections(ReportSelections, RecordVariant, MailTo, MailText);
TempBlob.CreateOutStream(EmailBodyOutStream, TextEncoding::UTF8);
EmailBodyOutStream.WriteText(HTMLText);
end;
local procedure CreateHTMLTextFromReportSelections(ReportSelections: Record "Report Selections"; RecordVariant: Variant; MailTo: Text; MailText: Text) HTMLText: Text
begin
HTMLText := GetTemplateContent(ReportSelections."Email Body Layout Code");
case ReportSelections.Usage of
ReportSelections.Usage::"S.Invoice":
FillSalesInvoiceHTML(RecordVariant, HTMLText, MailTo, MailText);
ReportSelections.Usage::"S.Invoice Draft":
FillSalesDraftInvoiceHTML(RecordVariant, HTMLText, MailTo, MailText);
ReportSelections.Usage::"S.Quote":
FillSalesEstimateHTML(RecordVariant, HTMLText, MailTo, MailText);
end;
end;
local procedure FillSalesDraftInvoiceHTML(SalesHeader: Record "Sales Header"; var HTMLText: Text; MailTo: Text; MailText: Text)
var
PaymentServicesSectionHTMLText: Text;
PaymentServiceRowHTMLText: Text;
SocialNetworksSectionHTMLText: Text;
SocialNetworkRowSectionHTMLText: Text;
begin
SliceSalesCoverLetterTemplate(HTMLText, PaymentServicesSectionHTMLText, PaymentServiceRowHTMLText,
SocialNetworksSectionHTMLText, SocialNetworkRowSectionHTMLText);
FillCommonParameters(HTMLText, SocialNetworksSectionHTMLText, SocialNetworkRowSectionHTMLText, MailTo, MailText);
FillParameterValueEncoded(HTMLText, 'MailTitle', StrSubstNo(InvoiceFromTitleTxt, CompanyInformation.Name));
FillParameterValueEncoded(HTMLText, 'YourDocument', YourInvoiceTxt);
FillParameterValueEncoded(HTMLText, 'DocumentNoLbl', InvoiceNoTxt);
FillParameterValueEncoded(HTMLText, 'DocumentNo', SalesHeader."No.");
FillParameterValueEncoded(HTMLText, 'DateLbl', SalesHeader.FieldCaption("Due Date"));
FillParameterValueEncoded(HTMLText, 'Date', Format(SalesHeader."Due Date"));
FillParameterValueEncoded(HTMLText, 'TotalAmountLbl', StrSubstNo(TotalTxt, SalesHeader.GetCurrencySymbol()));
FillParameterValueEncoded(HTMLText, 'TotalAmount', Format(CalcAndGetAmountIncludingVAT(SalesHeader)));
FillSalesDraftInvoicePaymentServices(HTMLText, PaymentServicesSectionHTMLText, PaymentServiceRowHTMLText, SalesHeader);
end;
local procedure FillSalesInvoiceHTML(SalesInvoiceHeader: Record "Sales Invoice Header"; var HTMLText: Text; MailTo: Text; MailText: Text)
var
PaymentServicesSectionHTMLText: Text;
PaymentServiceRowHTMLText: Text;
SocialNetworksSectionHTMLText: Text;
SocialNetworkRowSectionHTMLText: Text;
begin
SliceSalesCoverLetterTemplate(HTMLText, PaymentServicesSectionHTMLText, PaymentServiceRowHTMLText,
SocialNetworksSectionHTMLText, SocialNetworkRowSectionHTMLText);
FillCommonParameters(HTMLText, SocialNetworksSectionHTMLText, SocialNetworkRowSectionHTMLText, MailTo, MailText);
FillParameterValueEncoded(HTMLText, 'MailTitle', StrSubstNo(InvoiceFromTitleTxt, CompanyInformation.Name));
FillParameterValueEncoded(HTMLText, 'YourDocument', YourInvoiceTxt);
FillParameterValueEncoded(HTMLText, 'DocumentNoLbl', InvoiceNoTxt);
FillParameterValueEncoded(HTMLText, 'DocumentNo', SalesInvoiceHeader."No.");
FillParameterValueEncoded(HTMLText, 'DateLbl', SalesInvoiceHeader.FieldCaption("Due Date"));
FillParameterValueEncoded(HTMLText, 'Date', Format(SalesInvoiceHeader."Due Date"));
FillParameterValueEncoded(HTMLText, 'TotalAmountLbl', StrSubstNo(TotalTxt, SalesInvoiceHeader.GetCurrencySymbol()));
SalesInvoiceHeader.CalcFields("Amount Including VAT");
FillParameterValueEncoded(HTMLText, 'TotalAmount', Format(SalesInvoiceHeader."Amount Including VAT"));
if not IsSalesInvoiceCanceled(SalesInvoiceHeader) then
FillSalesInvoicePaymentServices(HTMLText, PaymentServicesSectionHTMLText, PaymentServiceRowHTMLText, SalesInvoiceHeader);
end;
local procedure FillSalesEstimateHTML(SalesHeader: Record "Sales Header"; var HTMLText: Text; MailTo: Text; MailText: Text)
var
PaymentServicesSectionHTMLText: Text;
PaymentServiceRowHTMLText: Text;
SocialNetworksSectionHTMLText: Text;
SocialNetworkRowSectionHTMLText: Text;
begin
SliceSalesCoverLetterTemplate(HTMLText, PaymentServicesSectionHTMLText, PaymentServiceRowHTMLText,
SocialNetworksSectionHTMLText, SocialNetworkRowSectionHTMLText);
FillCommonParameters(HTMLText, SocialNetworksSectionHTMLText, SocialNetworkRowSectionHTMLText, MailTo, MailText);
FillParameterValueEncoded(HTMLText, 'MailTitle', StrSubstNo(EstimateFromTitleTxt, CompanyInformation.Name));
FillParameterValueEncoded(HTMLText, 'YourDocument', YourEstimateTxt);
FillParameterValueEncoded(HTMLText, 'DocumentNoLbl', EstimateNoTxt);
FillParameterValueEncoded(HTMLText, 'DocumentNo', SalesHeader."No.");
FillParameterValueEncoded(HTMLText, 'DateLbl', ValidUntilTxt);
FillParameterValueEncoded(HTMLText, 'Date', Format(SalesHeader."Quote Valid Until Date"));
FillParameterValueEncoded(HTMLText, 'TotalAmountLbl', StrSubstNo(TotalTxt, SalesHeader.GetCurrencySymbol()));
FillParameterValueEncoded(HTMLText, 'TotalAmount', Format(CalcAndGetAmountIncludingVAT(SalesHeader)));
end;
local procedure GetCompanyInfo()
begin
if CompanyInfoRead then
exit;
CompanyInformation.Get();
CompanyInfoRead := true;
end;
local procedure CalcAndGetAmountIncludingVAT(var SalesHeader: Record "Sales Header") AmountIncludingVAT: Decimal
begin
SalesHeader.CalcFields("Amount Including VAT");
AmountIncludingVAT := SalesHeader."Amount Including VAT";
OnAfterCalcAndGetAmountIncludingVAT(SalesHeader, AmountIncludingVAT);
end;
local procedure GetCompanyLogoScaledDimensions(var TempBlob: Codeunit "Temp Blob"; var ScaledWidth: Integer; var ScaledHeight: Integer; ScaleToWidth: Integer; ScaleToHeight: Integer)
var
Image: DotNet Image;
InStream: InStream;
HorizontalFactor: Decimal;
VerticalFactor: Decimal;
begin
if not TempBlob.HasValue() then
exit;
TempBlob.CreateInStream(InStream);
Image := Image.FromStream(InStream);
if Image.Height <> 0 then
HorizontalFactor := ScaleToHeight / Image.Height;
if Image.Width <> 0 then
VerticalFactor := ScaleToWidth / Image.Width;
if HorizontalFactor < VerticalFactor then
VerticalFactor := HorizontalFactor
else
HorizontalFactor := VerticalFactor;
ScaledHeight := Round(Image.Height * HorizontalFactor, 1);
ScaledWidth := Round(Image.Width * VerticalFactor, 1);
end;
procedure GetTemplateContent(TemplateCode: Code[20]) TemplateContent: Text
var
O365HTMLTemplate: Record "O365 HTML Template";
MediaResources: Record "Media Resources";
InStream: InStream;
Buffer: Text;
begin
O365HTMLTemplate.Get(TemplateCode);
O365HTMLTemplate.TestField("Media Resources Ref");
MediaResources.Get(O365HTMLTemplate."Media Resources Ref");
MediaResources.CalcFields(Blob);
MediaResources.Blob.CreateInStream(InStream, TEXTENCODING::UTF8);
while not InStream.EOS do begin
InStream.Read(Buffer);
TemplateContent += Buffer;
end;
end;
local procedure GetPaymentServiceLogoAsText(PaymentReportingArgument: Record "Payment Reporting Argument"): Text
var
ImageHelpers: Codeunit "Image Helpers";
TempBlob: Codeunit "Temp Blob";
InStream: InStream;
begin
TempBlob.FromRecord(PaymentReportingArgument, PaymentReportingArgument.FieldNo(Logo));
ResizePaymentServiceLogoIfNeeded(TempBlob);
TempBlob.CreateInStream(InStream);
exit(ImageHelpers.GetHTMLImgSrc(InStream));
end;
local procedure GetPrimaryColorValue(): Code[10]
var
O365BrandColor: Record "O365 Brand Color";
begin
GetCompanyInfo();
if CompanyInformation."Brand Color Value" = '' then
if O365BrandColor.FindFirst() then
exit(O365BrandColor."Color Value");
exit(CompanyInformation."Brand Color Value");
end;
local procedure FillCompanyInfoSection(var HTMLText: Text)
var
FormatAddr: Codeunit "Format Address";
CompanyAddr: array[8] of Text[100];
begin
GetCompanyInfo();
FormatAddr.Company(CompanyAddr, CompanyInformation);
FillParameterValueEncoded(HTMLText, 'CompanyName', CompanyInformation.Name);
FillParameterValueEncoded(HTMLText, 'CompanyAddress', MakeFullCompanyAddress(CompanyAddr));
FillParameterValueEncoded(HTMLText, 'CompanyPhoneNo', CompanyInformation."Phone No.");
end;
local procedure FillCompanyLogo(var HTMLText: Text)
var
TempBlob: Codeunit "Temp Blob";
ImageHelpers: Codeunit "Image Helpers";
ImageHandlerManagement: Codeunit "Image Handler Management";
InStream: InStream;
Width: Integer;
Height: Integer;
MaxWidth: Integer;
MaxHeight: Integer;
begin
MaxWidth := 246;
MaxHeight := 80;
GetCompanyInfo();
TempBlob.FromRecord(CompanyInformation, CompanyInformation.FieldNo(Picture));
if ImageHandlerManagement.ScaleDownFromBlob(TempBlob, MaxWidth, MaxHeight) then;
OnResizeCompanyLogo(TempBlob);
GetCompanyLogoScaledDimensions(TempBlob, Width, Height, MaxWidth, MaxHeight);
TempBlob.CreateInStream(InStream);
FillParameterValue(HTMLText, 'CompanyLogo', ImageHelpers.GetHTMLImgSrc(InStream));
FillParameterValueEncoded(HTMLText, 'CompanyLogoWidth', Format(Width, 0, 9));
FillParameterValueEncoded(HTMLText, 'CompanyLogoHeight', Format(Height, 0, 9));
end;
procedure FillCommonParameters(var HTMLText: Text; SocialNetworksSectionHTMLText: Text; SocialNetworkRowSectionHTMLText: Text; MailTo: Text; MailText: Text)
begin
FillCompanyLogo(HTMLText);
FillParameterValueEncoded(HTMLText, 'ThankYouForYourBusiness', ThankYouForYourBusinessTxt);
FillCompanyInfoSection(HTMLText);
FillParameterValueEncoded(HTMLText, 'EmailSentToLbl', EmailSentToTxt);
FillParameterValueEncoded(HTMLText, 'MailTo', MailTo);
FillParameterValueEncoded(HTMLText, 'PrimaryColor', GetPrimaryColorValue());
FillParameterValue(HTMLText, 'MailText', EncodeMessage(MailText, false));
end;
procedure FillParameterValueEncoded(var HTMLText: Text; ParamenterName: Text; ParameterValue: Text)
var
TypeHelper: Codeunit "Type Helper";
begin
FillParameterValue(HTMLText, ParamenterName, TypeHelper.HtmlEncode(ParameterValue));
end;
procedure FillParameterValue(var HTMLText: Text; ParamenterName: Text; ParameterValue: Text)
begin
ReplaceHTMLText(HTMLText, MakeParameterNameString(ParamenterName), ParameterValue);
end;
local procedure FillSalesDraftInvoicePaymentServices(var HTMLText: Text; PaymentServicesSectionHTMLText: Text; PaymentServiceRowHTMLText: Text; SalesHeader: Record "Sales Header")
var
PaymentServiceSetup: Record "Payment Service Setup";
TempPaymentReportingArgument: Record "Payment Reporting Argument" temporary;
begin
PaymentServiceSetup.CreateReportingArgs(TempPaymentReportingArgument, SalesHeader);
FillPaymentServicesPart(HTMLText, TempPaymentReportingArgument, PaymentServicesSectionHTMLText, PaymentServiceRowHTMLText);
end;
local procedure FillSalesInvoicePaymentServices(var HTMLText: Text; PaymentServicesSectionHTMLText: Text; PaymentServiceRowHTMLText: Text; SalesInvoiceHeader: Record "Sales Invoice Header")
var
PaymentServiceSetup: Record "Payment Service Setup";
TempPaymentReportingArgument: Record "Payment Reporting Argument" temporary;
begin
PaymentServiceSetup.CreateReportingArgs(TempPaymentReportingArgument, SalesInvoiceHeader);
FillPaymentServicesPart(HTMLText, TempPaymentReportingArgument, PaymentServicesSectionHTMLText, PaymentServiceRowHTMLText);
end;
local procedure FillPaymentServicesPart(var HTMLText: Text; var TempPaymentReportingArgument: Record "Payment Reporting Argument" temporary; PaymentServicesSectionHTMLText: Text; PaymentServiceRowHTMLText: Text)
var
PaymentServicesHTMLText: Text;
PaymentServicesRowsHTMLText: Text;
begin
if TempPaymentReportingArgument.FindSet() then begin
PaymentServicesHTMLText := PaymentServicesSectionHTMLText;
FillParameterValueEncoded(PaymentServicesHTMLText, 'WantToPayOnline', WantToPayOnlineQst);
FillParameterValueEncoded(PaymentServicesHTMLText, 'PaymentInvitation', PaymentInvitationTxt);
repeat
PaymentServicesRowsHTMLText += FillPaymentServiceRowPart(TempPaymentReportingArgument, PaymentServiceRowHTMLText);
until TempPaymentReportingArgument.Next() = 0;
FillParameterValue(PaymentServicesHTMLText, 'PaymentServicesRows', PaymentServicesRowsHTMLText);
FillParameterValue(HTMLText, 'PaymentSevices', PaymentServicesHTMLText);
end;
end;
local procedure FillPaymentServiceRowPart(var TempPaymentReportingArgument: Record "Payment Reporting Argument" temporary; PaymentServiceRowHTMLText: Text) PaymentServiceHTMLText: Text
var
PaymentServiceUrl: Text;
begin
PaymentServiceHTMLText := PaymentServiceRowHTMLText;
PaymentServiceUrl := TempPaymentReportingArgument.GetTargetURL();
FillParameterValueEncoded(PaymentServiceHTMLText, 'PaymentServiceUrl', PaymentServiceUrl);
FillParameterValueEncoded(PaymentServiceHTMLText, 'PaymentServiceAlt', TempPaymentReportingArgument."URL Caption");
FillParameterValue(PaymentServiceHTMLText, 'PaymentServiceLogo',
GetPaymentServiceLogoAsText(TempPaymentReportingArgument));
FillParameterValueEncoded(PaymentServiceHTMLText, 'PrimaryColor', GetPrimaryColorValue());
end;
local procedure MakeFullCompanyAddress(CompanyAddr: array[8] of Text[100]) FullCompanyAddress: Text
var
i: Integer;
begin
FullCompanyAddress := CompanyAddr[2];
for i := 3 to 8 do
if CompanyAddr[i] <> '' then
FullCompanyAddress += ', ' + CompanyAddr[i];
end;
local procedure MakeParameterNameString(ParameterName: Text): Text
begin
exit(StrSubstNo('<!--%1-->', ParameterName));
end;
local procedure ReplaceHTMLText(var HTMLText: Text; OldValue: Text; NewValue: Text)
var
Regex: DotNet Regex;
begin
Regex := Regex.Regex(OldValue);
if Regex.IsMatch(HTMLText) then
HTMLText := Regex.Replace(HTMLText, NewValue);
end;
[Scope('OnPrem')]
procedure ReplaceBodyFileSendTo(BodyFileName: Text; OldSendTo: Text; NewSendTo: Text)
var
InStream: InStream;
BodyFile: File;
HTMLText: Text;
Buffer: Text;
begin
BodyFile.Open(BodyFileName, TEXTENCODING::UTF8);
BodyFile.CreateInStream(InStream);
while not InStream.EOS do begin
InStream.Read(Buffer);
HTMLText += Buffer;
end;
BodyFile.Close();
ReplaceHTMLText(HTMLText, OldSendTo, NewSendTo);
SaveHTML(BodyFileName, HTMLText);
end;
procedure SaveHTML(OutputFileName: Text; HTMLText: Text)
var
OutStream: OutStream;
OutputFile: File;
begin
OutputFile.WriteMode(true);
OutputFile.Create(OutputFileName, TEXTENCODING::UTF8);
OutputFile.CreateOutStream(OutStream);
OutStream.Write(HTMLText, StrLen(HTMLText));
OutputFile.Close();
end;
local procedure SliceSalesCoverLetterTemplate(var HTMLText: Text; var PaymentServicesSectionHTMLText: Text; var PaymentServiceRowHTMLText: Text; var SocialNetworksSectionHTMLText: Text; var SocialNetworkRowSectionHTMLText: Text)
begin
SliceSection(HTMLText, PaymentServicesSectionHTMLText, 'PaymentSevicesSection', 'PaymentSevices');
SliceSection(PaymentServicesSectionHTMLText, PaymentServiceRowHTMLText, 'PaymentServiceRowSection', 'PaymentServicesRows');
SliceSection(HTMLText, SocialNetworksSectionHTMLText, 'SocialNetworksSection', 'SocialNetworks');
SliceSection(SocialNetworksSectionHTMLText, SocialNetworkRowSectionHTMLText, 'SocialNetworkRowSection', 'CoverLetterSocialRow');
end;
local procedure SliceSection(var HTMLText: Text; var SectionHTMLText: Text; SectionName: Text; SectionHolderName: Text)
var
StartPosition: Integer;
EndPosition: Integer;
StartSectionParameter: Text;
EndSectionParameter: Text;
SectionHolderParameter: Text;
begin
StartSectionParameter := MakeParameterNameString(StrSubstNo('%1.Start', SectionName));
EndSectionParameter := MakeParameterNameString(StrSubstNo('%1.End', SectionName));
SectionHolderParameter := MakeParameterNameString(SectionHolderName);
StartPosition := StrPos(HTMLText, StartSectionParameter);
EndPosition := StrPos(HTMLText, EndSectionParameter);
SectionHTMLText :=
CopyStr(
HTMLText,
StartPosition + StrLen(StartSectionParameter) + 1,
EndPosition - StartPosition - StrLen(StartSectionParameter) - 1);
HTMLText :=
CopyStr(HTMLText, 1, StartPosition - 1) +
SectionHolderParameter +
CopyStr(HTMLText, EndPosition + StrLen(EndSectionParameter));
end;
local procedure EncodeMessage(Message: Text; CarriageReturn: Boolean): Text
var
TypeHelper: Codeunit "Type Helper";
String: DotNet String;
NewLineChar: Char;
CarriageReturnChar: Char;
begin
if Message = '' then
exit('');
String := TypeHelper.HtmlEncode(Message);
NewLineChar := 10;
CarriageReturnChar := 13;
if CarriageReturn then
exit(String.Replace(Format(CarriageReturnChar) + Format(NewLineChar), '<br />'));
exit(String.Replace(Format(NewLineChar), '<br />'));
end;
[IntegrationEvent(false, false)]
local procedure OnResizeCompanyLogo(var TempBlob: Codeunit "Temp Blob")
begin
end;
local procedure ResizePaymentServiceLogoIfNeeded(var TempBlob: Codeunit "Temp Blob")
var
ImageHandlerManagement: Codeunit "Image Handler Management";
ImageWidth: Integer;
ImageHeight: Integer;
AdvisedImageHeightPixels: Integer;
begin
AdvisedImageHeightPixels := 35;
if ImageHandlerManagement.GetImageSizeBlob(TempBlob, ImageWidth, ImageHeight) then
if ImageHeight > AdvisedImageHeightPixels then
if ImageHandlerManagement.ScaleDownFromBlob(TempBlob, ImageWidth, AdvisedImageHeightPixels) then;
end;
local procedure IsSalesInvoiceCanceled(var SalesInvoiceHeader: Record "Sales Invoice Header") Result: Boolean
begin
Result := SalesInvoiceHeader.CalcFields(Cancelled);
OnAfterIsSalesInvoiceCanceled(SalesInvoiceHeader, Result);
end;
[IntegrationEvent(false, false)]
local procedure OnAfterCalcAndGetAmountIncludingVAT(var SalesHeader: Record "Sales Header"; var AmountIncludingVAT: Decimal)
begin
end;
[IntegrationEvent(false, false)]
local procedure OnAfterIsSalesInvoiceCanceled(var SalesInvoiceHeader: Record "Sales Invoice Header"; var Result: Boolean)
begin
end;
}