Codeunit 1315 Chart Management, source in 29
Source29
src/Layers/W1/BaseApp/System/GenericChart/ChartManagement.Codeunit.al501 lines, Copyright (c) Microsoft Corporation. MIT
namespace System.Visualization;
using Microsoft.Finance.FinancialReports;
using Microsoft.Finance.ReceivablesPayables;
using Microsoft.Inventory.Analysis;
using Microsoft.Sales.Analysis;
using Microsoft.Sales.Customer;
using Microsoft.Utilities;
codeunit 1315 "Chart Management"
{
EventSubscriberInstance = Manual;
trigger OnRun()
begin
end;
var
AccountSchedulesChartSetup: Record "Account Schedules Chart Setup";
TempEntryNoAmountBuf: Record "Entry No. Amount Buffer" temporary;
SalesByCustGrpChartSetup: Record "Sales by Cust. Grp.Chart Setup";
AccSchedChartManagement: Codeunit "Acc. Sched. Chart Management";
TopTenCustomersChartMgt: Codeunit "Top Ten Customers Chart Mgt.";
TopFiveCustomersChartMgt: Codeunit "Top Five Customers Chart Mgt.";
AgedInventoryChartMgt: Codeunit "Aged Inventory Chart Mgt.";
SalesByCustGrpChartMgt: Codeunit "Sales by Cust. Grp. Chart Mgt.";
AgedAccReceivable: Codeunit "Aged Acc. Receivable";
AgedAccPayable: Codeunit "Aged Acc. Payable";
Period: Option " ",Next,Previous;
MediumStatusTxt: Label '%1 | View by %2', Comment = '%1 Account Schedule Chart Setup Name, %2 Period Length, %3 Current time';
LongStatusTxt: Label '%1 | %2..%3 | %4', Comment = '%1 Account Schedule Chart Setup Name, %2 = Start Date, %3 = End Date, %4 Period Length, %5 Current time';
TopTenCustomerChartNameTxt: Label 'Top Ten Customers by Sales Value';
TopFiveCustomerChartNameTxt: Label 'Top Five Customers by Sales Value';
SalesByCustomerGroupNameTxt: Label 'Sales Trends by Customer Groups';
SalesByCustomerGroupDescriptionTxt: Label 'This chart shows sales trends by customer group in the selected period.';
TopTenCustomersChartDescriptionTxt: Label 'This chart shows the ten customers with the highest total sales value. The last column shows the sum of sales values of all other customers.';
TopFiveCustomersChartDescriptionTxt: Label 'This Pie chart shows the five customers with the highest total sales value.';
AgedInventoryChartDescriptionTxt: Label 'This chart shows the total inventory value, grouped by the number of days that the items are on inventory.';
AgedAccReceivableNameTxt: Label 'Aged Accounts Receivable';
AgedAccPayableNameTxt: Label 'Aged Accounts Payable';
XCashFlowChartNameTxt: Label 'Cash Flow';
XIncomeAndExpenseChartNameTxt: Label 'Income & Expense';
XCashCycleChartNameTxt: Label 'Cash Cycle';
NoEnabledChartsFoundErr: Label 'There are no enabled charts. Choose Select Chart to see a list of charts that you can display.';
ChartDefinitionMissingErr: Label 'There are no charts defined.';
procedure AddinReady(var ChartDefinition: Record "Chart Definition"; var BusinessChartBuffer: Record "Business Chart Buffer")
var
LastUsedChart: Record "Last Used Chart";
LastChartRecorded: Boolean;
LastChartExists: Boolean;
LastChartEnabled: Boolean;
begin
LastChartRecorded := LastUsedChart.Get(UserId);
LastChartExists :=
LastChartRecorded and ChartDefinition.Get(LastUsedChart."Code Unit ID", LastUsedChart."Chart Name");
LastChartEnabled := LastChartExists and ChartDefinition.Enabled;
if ChartDefinition.IsEmpty() then
exit;
if not LastChartEnabled then begin
ChartDefinition.SetRange(Enabled, true);
if not ChartDefinition.FindLast() then
DIALOG.Error(NoEnabledChartsFoundErr);
end;
SetDefaultPeriodLength(ChartDefinition, BusinessChartBuffer);
UpdateChart(ChartDefinition, BusinessChartBuffer, Period::" ");
end;
procedure ChartDescription(ChartDefinition: Record "Chart Definition"): Text
var
ChartDescription: Text;
IsHandled: Boolean;
begin
IsHandled := false;
OnBeforeChartDescription(ChartDefinition, ChartDescription, IsHandled);
if IsHandled then
exit(ChartDescription);
case ChartDefinition."Code Unit ID" of
CODEUNIT::"Acc. Sched. Chart Management":
exit(AccountSchedulesChartSetup.Description);
CODEUNIT::"Top Ten Customers Chart Mgt.":
exit(TopTenCustomersChartDescriptionTxt);
CODEUNIT::"Aged Inventory Chart Mgt.":
exit(AgedInventoryChartDescriptionTxt);
CODEUNIT::"Sales by Cust. Grp. Chart Mgt.":
exit(SalesByCustomerGroupDescriptionTxt);
CODEUNIT::"Aged Acc. Receivable":
exit(AgedAccReceivable.Description(false));
CODEUNIT::"Aged Acc. Payable":
exit(AgedAccPayable.Description(false));
CODEUNIT::"Top Five Customers Chart Mgt.":
exit(TopFiveCustomersChartDescriptionTxt);
end;
end;
procedure CashFlowChartName(): Text[30]
begin
exit(XCashFlowChartNameTxt)
end;
procedure CashCycleChartName(): Text[30]
begin
exit(XCashCycleChartNameTxt)
end;
procedure IncomeAndExpenseChartName(): Text[30]
begin
exit(XIncomeAndExpenseChartNameTxt)
end;
procedure DataPointClicked(var BusinessChartBuffer: Record "Business Chart Buffer"; var ChartDefinition: Record "Chart Definition")
var
IsHandled: Boolean;
begin
IsHandled := false;
OnBeforeDataPointClicked(ChartDefinition, BusinessChartBuffer, IsHandled);
if IsHandled then
exit;
case ChartDefinition."Code Unit ID" of
CODEUNIT::"Acc. Sched. Chart Management":
AccSchedChartManagement.DrillDown(BusinessChartBuffer, AccountSchedulesChartSetup);
CODEUNIT::"Top Ten Customers Chart Mgt.":
TopTenCustomersChartMgt.DrillDown(BusinessChartBuffer);
CODEUNIT::"Top Five Customers Chart Mgt.":
TopFiveCustomersChartMgt.DrillDown(BusinessChartBuffer);
CODEUNIT::"Aged Inventory Chart Mgt.":
AgedInventoryChartMgt.DrillDown(BusinessChartBuffer);
CODEUNIT::"Sales by Cust. Grp. Chart Mgt.":
SalesByCustGrpChartMgt.DrillDown(BusinessChartBuffer);
CODEUNIT::"Aged Acc. Receivable":
AgedAccReceivable.DrillDownByGroup(BusinessChartBuffer, TempEntryNoAmountBuf);
CODEUNIT::"Aged Acc. Payable":
AgedAccPayable.DrillDownByGroup(BusinessChartBuffer, TempEntryNoAmountBuf);
end;
end;
procedure PopulateChartDefinitionTable()
begin
InsertChartDefinition(CODEUNIT::"Top Five Customers Chart Mgt.", TopFiveCustomerChartNameTxt);
InsertChartDefinition(CODEUNIT::"Top Ten Customers Chart Mgt.", TopTenCustomerChartNameTxt);
InsertChartDefinition(CODEUNIT::"Sales by Cust. Grp. Chart Mgt.", SalesByCustomerGroupNameTxt);
InsertChartDefinition(CODEUNIT::"Aged Acc. Receivable", AgedAccReceivableNameTxt);
InsertChartDefinition(CODEUNIT::"Aged Acc. Payable", AgedAccPayableNameTxt);
InsertChartDefinition(CODEUNIT::"Acc. Sched. Chart Management", XCashFlowChartNameTxt);
InsertChartDefinition(CODEUNIT::"Acc. Sched. Chart Management", XIncomeAndExpenseChartNameTxt);
InsertChartDefinition(CODEUNIT::"Acc. Sched. Chart Management", XCashCycleChartNameTxt);
OnAfterPopulateChartDefinitionTable();
end;
procedure SelectChart(var BusinessChartBuffer: Record "Business Chart Buffer"; var ChartDefinition: Record "Chart Definition")
var
ChartList: Page "Chart List";
begin
if ChartDefinition.IsEmpty() then
if ChartDefinition.WritePermission then begin
PopulateChartDefinitionTable();
Commit();
end else
Error(ChartDefinitionMissingErr);
ChartList.LookupMode(true);
if ChartList.RunModal() = ACTION::LookupOK then begin
ChartList.GetRecord(ChartDefinition);
SetDefaultPeriodLength(ChartDefinition, BusinessChartBuffer);
UpdateChart(ChartDefinition, BusinessChartBuffer, Period::" ");
end;
end;
procedure SetDefaultPeriodLength(ChartDefinition: Record "Chart Definition"; var BusChartBuf: Record "Business Chart Buffer")
var
BusChartUserSetup: Record "Business Chart User Setup";
begin
case ChartDefinition."Code Unit ID" of
CODEUNIT::"Aged Inventory Chart Mgt.":
SetPeriodLength(ChartDefinition, BusChartBuf, BusChartBuf."Period Length"::Month, true);
CODEUNIT::"Aged Acc. Receivable":
begin
BusChartUserSetup.InitSetupCU(CODEUNIT::"Aged Acc. Receivable");
SetPeriodLength(ChartDefinition, BusChartBuf, BusChartUserSetup."Period Length", true);
end;
CODEUNIT::"Aged Acc. Payable":
begin
BusChartUserSetup.InitSetupCU(CODEUNIT::"Aged Acc. Payable");
SetPeriodLength(ChartDefinition, BusChartBuf, BusChartUserSetup."Period Length", true);
end;
CODEUNIT::"Acc. Sched. Chart Management":
begin
AccountSchedulesChartSetup.Get('', ChartDefinition."Chart Name");
SetPeriodLength(ChartDefinition, BusChartBuf, AccountSchedulesChartSetup."Period Length", true);
end;
end;
end;
procedure SetPeriodLength(ChartDefinition: Record "Chart Definition"; var BusChartBuf: Record "Business Chart Buffer"; PeriodLength: Option; IsInitState: Boolean)
var
NewStartDate: Date;
IsHandled: Boolean;
begin
IsHandled := false;
OnBeforeSetPeriodLength(ChartDefinition, PeriodLength, IsHandled);
if IsHandled then
exit;
case ChartDefinition."Code Unit ID" of
CODEUNIT::"Acc. Sched. Chart Management":
begin
AccountSchedulesChartSetup.Get('', ChartDefinition."Chart Name");
AccountSchedulesChartSetup.SetPeriodLength(PeriodLength);
BusChartBuf."Period Length" := PeriodLength;
if AccountSchedulesChartSetup."Look Ahead" then
NewStartDate := GetBaseDate(BusChartBuf, IsInitState)
else
NewStartDate :=
CalcDate(
StrSubstNo(
'<-%1%2>', AccountSchedulesChartSetup."No. of Periods", BusChartBuf.GetPeriodLength()),
GetBaseDate(BusChartBuf, IsInitState));
if AccountSchedulesChartSetup."Start Date" <> NewStartDate then begin
AccountSchedulesChartSetup.Validate("Start Date", NewStartDate);
AccountSchedulesChartSetup.Modify(true);
end;
end;
CODEUNIT::"Sales by Cust. Grp. Chart Mgt.":
SalesByCustGrpChartSetup.SetPeriodLength(PeriodLength);
else
BusChartBuf."Period Length" := PeriodLength;
end;
end;
procedure UpdateChartSafe(var ChartDefinition: Record "Chart Definition"; var BusinessChartBuffer: Record "Business Chart Buffer"; Period: Option; var ErrorMessage: Text): Boolean
begin
ClearLastError();
OnUpdateChartSafe(ChartDefinition, BusinessChartBuffer, Period);
ErrorMessage := GetLastErrorText();
if ErrorMessage = '' then
exit(true);
ClearLastError();
exit(false);
end;
procedure UpdateChart(var ChartDefinition: Record "Chart Definition"; var BusinessChartBuffer: Record "Business Chart Buffer"; Period: Option)
var
IsHandled: Boolean;
begin
IsHandled := false;
OnBeforeUpdateChart(ChartDefinition, BusinessChartBuffer, Period, IsHandled);
if IsHandled then
exit;
case ChartDefinition."Code Unit ID" of
CODEUNIT::"Acc. Sched. Chart Management":
begin
AccSchedChartManagement.GetSetupRecordset(AccountSchedulesChartSetup, ChartDefinition."Chart Name", 0);
AccSchedChartManagement.UpdateData(BusinessChartBuffer, Period, AccountSchedulesChartSetup);
end;
CODEUNIT::"Aged Inventory Chart Mgt.":
AgedInventoryChartMgt.UpdateChart(BusinessChartBuffer);
CODEUNIT::"Sales by Cust. Grp. Chart Mgt.":
begin
SalesByCustGrpChartSetup.SetPeriod(Period);
SalesByCustGrpChartMgt.UpdateChart(BusinessChartBuffer);
end;
CODEUNIT::"Aged Acc. Receivable":
begin
BusinessChartBuffer."Period Filter Start Date" := WorkDate();
AgedAccReceivable.UpdateDataPerGroup(BusinessChartBuffer, TempEntryNoAmountBuf);
AgedAccReceivable.SaveSettings(BusinessChartBuffer);
end;
CODEUNIT::"Aged Acc. Payable":
begin
BusinessChartBuffer."Period Filter Start Date" := WorkDate();
AgedAccPayable.UpdateData(BusinessChartBuffer, TempEntryNoAmountBuf);
AgedAccPayable.SaveSettings(BusinessChartBuffer)
end;
CODEUNIT::"Top Five Customers Chart Mgt.":
TopFiveCustomersChartMgt.UpdateChart(BusinessChartBuffer);
else
TopTenCustomersChartMgt.UpdateChart(BusinessChartBuffer);
end;
UpdateLastUsedChart(ChartDefinition);
end;
procedure UpdateNextPrevious(var ChartDefinition: Record "Chart Definition"): Boolean
var
IsHandled: Boolean;
Result: Boolean;
begin
IsHandled := false;
OnBeforeUpdateNextPrevious(ChartDefinition, Result, IsHandled);
if IsHandled then
exit(Result);
exit(ChartDefinition."Code Unit ID" in
[CODEUNIT::"Acc. Sched. Chart Management",
CODEUNIT::"Sales by Cust. Grp. Chart Mgt."]);
end;
procedure UpdateStatusText(var ChartDefinition: Record "Chart Definition"; var BusinessChartBuffer: Record "Business Chart Buffer"; var StatusText: Text)
var
StartDate: Date;
EndDate: Date;
IsHandled: Boolean;
begin
IsHandled := false;
OnBeforeUpdateStatusText(ChartDefinition, BusinessChartBuffer, StatusText, IsHandled);
if IsHandled then
exit;
StartDate := BusinessChartBuffer."Period Filter Start Date";
EndDate := BusinessChartBuffer."Period Filter End Date";
case ChartDefinition."Code Unit ID" of
CODEUNIT::"Acc. Sched. Chart Management":
case AccountSchedulesChartSetup."Base X-Axis on" of
AccountSchedulesChartSetup."Base X-Axis on"::Period:
StatusText := StrSubstNo(MediumStatusTxt, ChartDefinition."Chart Name", AccountSchedulesChartSetup."Period Length");
AccountSchedulesChartSetup."Base X-Axis on"::"Acc. Sched. Line",
AccountSchedulesChartSetup."Base X-Axis on"::"Acc. Sched. Column":
StatusText := StrSubstNo(LongStatusTxt, ChartDefinition."Chart Name", StartDate, EndDate, AccountSchedulesChartSetup."Period Length");
end;
CODEUNIT::"Sales by Cust. Grp. Chart Mgt.",
CODEUNIT::"Aged Acc. Receivable",
CODEUNIT::"Aged Acc. Payable",
CODEUNIT::"Aged Inventory Chart Mgt.":
StatusText := StrSubstNo(MediumStatusTxt, ChartDefinition."Chart Name", BusinessChartBuffer."Period Length");
else
StatusText := ChartDefinition."Chart Name";
end;
end;
local procedure UpdateLastUsedChart(ChartDefinition: Record "Chart Definition")
var
LastUsedChart: Record "Last Used Chart";
begin
if LastUsedChart.Get(UserId) then begin
if (LastUsedChart."Code Unit ID" <> ChartDefinition."Code Unit ID") or (LastUsedChart."Chart Name" <> ChartDefinition."Chart Name") then begin
LastUsedChart.Validate("Code Unit ID", ChartDefinition."Code Unit ID");
LastUsedChart.Validate("Chart Name", ChartDefinition."Chart Name");
LastUsedChart.Modify();
end;
end else begin
LastUsedChart.Validate(UID, UserId);
LastUsedChart.Validate("Code Unit ID", ChartDefinition."Code Unit ID");
LastUsedChart.Validate("Chart Name", ChartDefinition."Chart Name");
LastUsedChart.Insert();
end;
end;
local procedure InsertChartDefinition(ChartCodeunitId: Integer; ChartName: Text[60])
var
ChartDefinition: Record "Chart Definition";
begin
if not ChartDefinition.Get(ChartCodeunitId, ChartName) then begin
ChartDefinition."Code Unit ID" := ChartCodeunitId;
ChartDefinition."Chart Name" := ChartName;
EnableChart(ChartDefinition);
ChartDefinition.Insert();
end;
end;
procedure EnableChart(var ChartDefinition: Record "Chart Definition")
begin
if ChartDefinition."Code Unit ID" = CODEUNIT::"Acc. Sched. Chart Management" then begin
if not ChartDefinition.IsSetupComplete(ChartDefinition) then
exit;
ChartDefinition.Enabled := true;
end else
ChartDefinition.Enabled := true;
end;
local procedure GetPeriodLength(): Text[1]
begin
case AccountSchedulesChartSetup."Period Length" of
AccountSchedulesChartSetup."Period Length"::Day:
exit('D');
AccountSchedulesChartSetup."Period Length"::Week:
exit('W');
AccountSchedulesChartSetup."Period Length"::Month:
exit('M');
AccountSchedulesChartSetup."Period Length"::Quarter:
exit('Q');
AccountSchedulesChartSetup."Period Length"::Year:
exit('Y');
end;
end;
local procedure GetBaseDate(var BusChartBuf: Record "Business Chart Buffer"; IsInitState: Boolean): Date
var
ColumnIndex: Integer;
StartDate: Date;
EndDate: Date;
begin
if AccountSchedulesChartSetup."Look Ahead" then
ColumnIndex := 0
else
ColumnIndex := AccountSchedulesChartSetup."No. of Periods" - 1;
if IsInitState then
exit(WorkDate());
BusChartBuf.GetPeriodFromMapColumn(ColumnIndex, StartDate, EndDate);
if AccountSchedulesChartSetup."Look Ahead" then
exit(StartDate);
exit(CalcDate(StrSubstNo('<1%1>', GetPeriodLength()), EndDate));
end;
procedure AgedAccReceivableName(): Text[60]
begin
exit(AgedAccReceivableNameTxt)
end;
procedure AgedAccPayableName(): Text[60]
begin
exit(AgedAccPayableNameTxt)
end;
[Scope('OnPrem')]
procedure ScheduleTopCustomerListRefreshTask()
var
LastCustomerLedgerEntryNo: Integer;
begin
if TopCustomerListUpdatedRecently(LastCustomerLedgerEntryNo) then
exit;
if TaskScheduler.CanCreateTask() then
TASKSCHEDULER.CreateTask(CODEUNIT::"Top Customers By Sales Job", 0, true, CompanyName, 0DT);
end;
[Scope('OnPrem')]
procedure TopCustomerListUpdatedRecently(var LastCustomerLedgerEntryNo: Integer): Boolean
var
TopCustomersBySalesBuffer: Record "Top Customers By Sales Buffer";
LastBufferUpdateDateTime: DateTime;
TwelveHourDuration: Duration;
ZeroDayTime: DateTime;
begin
if TopCustomersBySalesBuffer.FindFirst() then begin
LastBufferUpdateDateTime := TopCustomersBySalesBuffer.DateTimeUpdated;
ZeroDayTime := 0DT;
TwelveHourDuration := 43200000;
LastCustomerLedgerEntryNo := TopCustomersBySalesBuffer.LastCustLedgerEntryNo;
if LastBufferUpdateDateTime = ZeroDayTime then
exit(false);
if CurrentDateTime - LastBufferUpdateDateTime < TwelveHourDuration then
exit(true);
end;
exit(false);
end;
[EventSubscriber(ObjectType::Codeunit, Codeunit::"Chart Management", 'OnUpdateChartSafe', '', false, false)]
local procedure HandleUpdateChartSafe(var ChartDefinition: Record "Chart Definition"; var BusinessChartBuffer: Record "Business Chart Buffer"; Period: Option)
begin
UpdateChart(ChartDefinition, BusinessChartBuffer, Period);
end;
[IntegrationEvent(false, false)]
local procedure OnAfterPopulateChartDefinitionTable()
begin
end;
[IntegrationEvent(false, false)]
local procedure OnBeforeChartDescription(ChartDefinition: Record "Chart Definition"; var ChartDescription: Text; var IsHandled: Boolean)
begin
end;
[IntegrationEvent(false, false)]
local procedure OnBeforeDataPointClicked(var ChartDefinition: Record "Chart Definition"; var BusinessChartBuffer: Record "Business Chart Buffer"; var IsHandled: Boolean)
begin
end;
[IntegrationEvent(false, false)]
local procedure OnBeforeSetPeriodLength(ChartDefinition: Record "Chart Definition"; PeriodLength: Option; var IsHandled: Boolean)
begin
end;
[IntegrationEvent(false, false)]
local procedure OnBeforeUpdateChart(var ChartDefinition: Record "Chart Definition"; var BusinessChartBuffer: Record "Business Chart Buffer"; Period: Option; var IsHandled: Boolean)
begin
end;
[IntegrationEvent(false, false)]
local procedure OnBeforeUpdateNextPrevious(var ChartDefinition: Record "Chart Definition"; var Result: Boolean; var IsHandled: Boolean)
begin
end;
[IntegrationEvent(false, false)]
local procedure OnBeforeUpdateStatusText(ChartDefinition: Record "Chart Definition"; BusinessChartBuffer: Record "Business Chart Buffer"; var StatusText: Text; var IsHandled: Boolean)
begin
end;
[IntegrationEvent(false, false, true)]
local procedure OnUpdateChartSafe(var ChartDefinition: Record "Chart Definition"; var BusinessChartBuffer: Record "Business Chart Buffer"; Period: Option)
begin
end;
}