Report 1131 Cost Allocation

App
Base Application
Namespace
Microsoft.CostAccounting.Allocation
Versions
17-28

Procedures, 1Events, 1

Versions171819202122232425262728

Source29

Source in 29

src/Layers/W1/BaseApp/CostAccounting/Allocation/CostAllocation.Report.al542 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.CostAccounting.Allocation;

using Microsoft.CostAccounting.Account;
using Microsoft.CostAccounting.Budget;
using Microsoft.CostAccounting.Journal;
using Microsoft.CostAccounting.Ledger;
using Microsoft.CostAccounting.Posting;
using Microsoft.CostAccounting.Reports;
using Microsoft.CostAccounting.Setup;
using Microsoft.Foundation.AuditCodes;

report 1131 "Cost Allocation"
{
    ApplicationArea = CostAccounting;
    Caption = 'Allocate Costs';
    ToolTip = 'Specifies the cost allocation options.';
    ProcessingOnly = true;
    UsageCategory = Tasks;

    dataset
    {
        dataitem(CostAllocationSource; "Cost Allocation Source")
        {
            DataItemTableView = sorting(Level, "Valid From", "Valid To", "Cost Type Range") order(ascending);
            dataitem(CostAllocationTarget; "Cost Allocation Target")
            {
                DataItemLink = ID = field(ID);
                DataItemTableView = sorting(ID, "Line No.") order(ascending);

                trigger OnAfterGetRecord()
                begin
                    if not AllocTargetErrorFound then
                        AllocTargetErrorFound := ("Target Cost Center" = '') and ("Target Cost Object" = '')
                    else
                        CurrReport.Break();
                end;
            }

            trigger OnAfterGetRecord()
            begin
                if not AllocSourceErrorFound then
                    AllocSourceErrorFound := ("Cost Center Code" = '') and ("Cost Object Code" = '')
                else
                    CurrReport.Skip();
            end;

            trigger OnPostDataItem()
            begin
                if AllocSourceErrorFound or AllocTargetErrorFound then begin
                    ShowAllocations(not AllocSourceErrorFound);
                    CurrReport.Quit();
                end;
            end;

            trigger OnPreDataItem()
            begin
                SetRange(Level, FromLevel, ToLevel);
                SetRange(Variant, AllocVariant);
            end;
        }
        dataitem("Cost Allocation Source"; "Cost Allocation Source")
        {
            DataItemTableView = sorting(Level, "Valid From", "Valid To", "Cost Type Range");
            dataitem("Cost Entry"; "Cost Entry")
            {
                DataItemTableView = sorting("Entry No.") order(ascending);

                trigger OnAfterGetRecord()
                begin
                    SourceTotalAmount := SourceTotalAmount + Amount;
                    NoOfEntries := NoOfEntries + 1;
                    Window.Update(3, Format(NoOfEntries));
                end;

                trigger OnPostDataItem()
                begin
                    if AllocateBudget then
                        CurrReport.Break();

                    if CostRegister.FindLast() then;
                    ModifyAll("Allocated with Journal No.", CostRegister."No." + 1);
                    ModifyAll(Allocated, true);
                end;

                trigger OnPreDataItem()
                begin
                    if AllocateBudget then
                        CurrReport.Break();

                    if "Cost Allocation Source"."Cost Center Code" <> '' then begin
                        SetCurrentKey("Cost Center Code", "Cost Type No.", Allocated);
                        SetFilter("Cost Center Code", "Cost Allocation Source"."Cost Center Code");
                    end else begin
                        SetCurrentKey("Cost Object Code", "Cost Type No.", Allocated);
                        SetFilter("Cost Object Code", "Cost Allocation Source"."Cost Object Code");
                    end;
                    SetFilter("Cost Type No.", "Cost Allocation Source"."Cost Type Range");
                    SetRange(Allocated, false);
                    SetRange("Posting Date", 0D, AllocDate);

                    SourceTotalAmount := 0;
                end;
            }
            dataitem("Cost Budget Entry"; "Cost Budget Entry")
            {
                DataItemTableView = sorting("Entry No.") order(ascending);

                trigger OnAfterGetRecord()
                begin
                    SourceTotalAmount := SourceTotalAmount + Amount;
                    NoOfEntries := NoOfEntries + 1;
                    Window.Update(3, Format(NoOfEntries));
                end;

                trigger OnPostDataItem()
                begin
                    if not AllocateBudget then
                        CurrReport.Break();

                    if CostBudgetRegister.FindLast() then;
                    ModifyAll("Allocated with Journal No.", CostBudgetRegister."No." + 1);
                    ModifyAll(Allocated, true);
                end;

                trigger OnPreDataItem()
                begin
                    if not AllocateBudget then
                        CurrReport.Break();

                    if "Cost Allocation Source"."Cost Center Code" <> '' then begin
                        SetCurrentKey("Budget Name", "Cost Center Code", "Cost Type No.", Allocated, Date);
                        SetFilter("Cost Center Code", "Cost Allocation Source"."Cost Center Code");
                    end else begin
                        SetCurrentKey("Budget Name", "Cost Object Code", "Cost Type No.", Allocated, Date);
                        SetFilter("Cost Object Code", "Cost Allocation Source"."Cost Object Code");
                    end;
                    SetRange("Budget Name", CostBudgetName.Name);
                    SetFilter("Cost Type No.", "Cost Allocation Source"."Cost Type Range");
                    SetRange(Allocated, false);
                    SetRange(Date, 0D, AllocDate);

                    SourceTotalAmount := 0;
                end;
            }
            dataitem("Cost Allocation Target"; "Cost Allocation Target")
            {
                DataItemTableView = sorting(ID, "Line No.");

                trigger OnAfterGetRecord()
                begin
                    case "Allocation Target Type" of
                        "Allocation Target Type"::"All Costs":
                            begin
                                ReminderAmount += SourceTotalAmount / 100 * Percent;
                                AllocAmount := Round(ReminderAmount, 0.01);
                                ReminderAmount -= AllocAmount;
                                AllocRatio := StrSubstNo(Text010,
                                    Share, "Cost Allocation Source"."Total Share", SourceTotalAmount);
                            end;
                        "Allocation Target Type"::"Percent per Share":
                            begin
                                AllocAmount := Round(Share / 100 * "Percent per Share", 0.01);
                                AllocRatio := StrSubstNo(Text011,
                                    "Percent per Share", Share);
                            end;
                        "Allocation Target Type"::"Amount per Share":
                            begin
                                AllocAmount := Round(Share * "Amount per Share", 0.01);
                                AllocRatio := StrSubstNo(Text012,
                                    "Amount per Share", Share);
                            end;
                    end;

                    if StrLen(AllocTargetText) < MaxStrLen(TempCostJnlLine.Description) then
                        if "Target Cost Center" <> '' then
                            AllocTargetText := AllocTargetText + "Target Cost Center" + ', '
                        else
                            AllocTargetText := AllocTargetText + "Target Cost Object" + ', ';

                    AllocTotalAmount := AllocTotalAmount + AllocAmount;

                    WriteJournalLine("Target Cost Type", "Target Cost Center", "Target Cost Object", AllocAmount,
                      AllocSourceText, AllocRatio, "Cost Allocation Source".ID, false);
                end;

                trigger OnPostDataItem()
                begin
                    if StrLen(AllocTargetText) > MaxStrLen(TempCostJnlLine.Description) then
                        AllocTargetText := CopyStr(AllocTargetText, 1, MaxStrLen(TempCostJnlLine.Description) - 10) + Text013;

                    AllocRatio := StrSubstNo(Text014, "Cost Allocation Source".Level, AllocDate);

                    WriteJournalLine("Cost Allocation Source"."Credit to Cost Type", "Cost Allocation Source"."Cost Center Code",
                      "Cost Allocation Source"."Cost Object Code", -AllocTotalAmount,
                      AllocTargetText, AllocRatio, "Cost Allocation Source".ID, true);

                    CostAccSetup."Last Allocation Doc. No." := IncStr(CostAccSetup."Last Allocation Doc. No.");
                    CostAccSetup.Modify();
                end;

                trigger OnPreDataItem()
                begin
                    SetRange(ID, "Cost Allocation Source".ID);
                    "Cost Allocation Source".CalcFields("Total Share");
                    AllocTotalAmount := 0;
                    ReminderAmount := 0;

                    AllocSourceText := Text008;
                    if "Cost Allocation Source"."Cost Type Range" <> '' then
                        AllocSourceText := AllocSourceText + ' ' + "Cost Allocation Source"."Cost Type Range" + ' (' + Text017 + ')';
                    if "Cost Allocation Source"."Cost Center Code" <> '' then
                        AllocSourceText := AllocSourceText + ' ' + "Cost Allocation Source"."Cost Center Code" + ' (' + Text018 + ')';
                    if "Cost Allocation Source"."Cost Object Code" <> '' then
                        AllocSourceText := AllocSourceText + ' ' + "Cost Allocation Source"."Cost Object Code" + ' (' + Text019 + ')';

                    AllocTargetText := Text009;
                end;
            }

            trigger OnAfterGetRecord()
            begin
                if (LastLevel <> 0) and (Level > LastLevel) then begin
                    if EntriesPerLevel > 0 then
                        PostCostJournalLines();
                    LastCostJourLineNo := 0;
                    EntriesPerLevel := 0;
                end;

                LastLevel := Level;

                SourceTotalAmount := 0;
                Window.Update(1, Format(Level));
                Window.Update(2, Format(ID));
            end;

            trigger OnPostDataItem()
            begin
                if TotalEntries = 0 then
                    Error(Text006);

                if EntriesPerLevel > 0 then
                    PostCostJournalLines();

                Window.Close();
                if CurrReport.UseRequestPage then
                    Message(Text007, TotalEntries);
            end;

            trigger OnPreDataItem()
            begin
                "Cost Entry".LockTable();
                CostRegister.LockTable();
                CostBudgetRegister.LockTable();
                LockTable();
                "Cost Allocation Target".LockTable();
                "Cost Budget Entry".LockTable();

                CostAccSetup.Get();
                SourceCodeSetup.Get();
                SourceCodeSetup.TestField("Cost Allocation");

                if AllocDate = 0D then
                    Error(Text000);

                if FromLevel > ToLevel then
                    Error(Text001);

                if CostBudgetName.Name <> '' then begin
                    AllocateBudget := true;
                    MsgText := Text002 + ' ' + CostBudgetName.Name;
                end else
                    MsgText := Text003;

                if CurrReport.UseRequestPage then
                    if not Confirm(Text004, true, MsgText, FromLevel, ToLevel, AllocDate, AllocVariant) then
                        Error('');

                SetRange(Level, FromLevel, ToLevel);
                SetRange(Variant, AllocVariant);
                SetRange("Valid From", 0D, AllocDate);
                SetFilter("Valid To", '%1|>=%2', 0D, AllocDate);
                SetRange(Blocked, false);

                if AllocateBudget then
                    SetFilter("Allocation Source Type", '%1|%2', "Allocation Source Type"::Both, "Allocation Source Type"::Budget)
                else
                    SetRange("Allocation Source Type", "Allocation Source Type"::Both, "Allocation Source Type"::Actual);

                Window.Open(Text005)
            end;
        }
    }

    requestpage
    {
        SaveValues = true;

        layout
        {
            area(content)
            {
                group(Options)
                {
                    Caption = 'Options';
                    field("From Alloc. Level"; FromLevel)
                    {
                        ApplicationArea = CostAccounting;
                        Caption = 'From Alloc. Level';
                        MaxValue = 99;
                        MinValue = 1;
                        ToolTip = 'Specifies a level. If you do not want to perform the allocation of costs to all the levels in the same process, you should fill in the field.';
                    }
                    field("To Alloc. Level"; ToLevel)
                    {
                        ApplicationArea = CostAccounting;
                        Caption = 'To Alloc. Level';
                        MaxValue = 99;
                        MinValue = 1;
                        ToolTip = 'Specifies a level. If you do not want to perform the allocation of costs to all the levels in the same process, you should fill in the field.';
                    }
                    field("Allocation Date"; AllocDate)
                    {
                        ApplicationArea = CostAccounting;
                        Caption = 'Allocation Date';
                        ToolTip = 'Specifies the date of the cost allocation.';
                    }
                    field(Group; AllocVariant)
                    {
                        ApplicationArea = CostAccounting;
                        Caption = 'Group';
                        ToolTip = 'Specifies the variant code if you have assigned it to an allocation. Leave it blank if you do not use variant.';
                    }
                    field("Budget Name"; CostBudgetName.Name)
                    {
                        ApplicationArea = CostAccounting;
                        Caption = 'Budget Name';
                        Lookup = true;
                        TableRelation = "Cost Budget Name";
                        ToolTip = 'Specifies the name of the budget.';
                    }
                }
            }
        }

        actions
        {
        }

        trigger OnOpenPage()
        begin
            CostBudgetName.Init();
        end;
    }

    labels
    {
    }

    trigger OnInitReport()
    begin
        InitializeRequest(1, 99, WorkDate(), '', '');
    end;

    var
        TempCostJnlLine: Record "Cost Journal Line" temporary;
        SourceCodeSetup: Record "Source Code Setup";
        Window: Dialog;
        FromLevel: Integer;
        ToLevel: Integer;
        AllocVariant: Code[10];
        LastLevel: Integer;
        NoOfEntries: Integer;
        EntriesPerLevel: Integer;
        TotalEntries: Integer;
        AllocDate: Date;
        SourceTotalAmount: Decimal;
        AllocAmount: Decimal;
        AllocSourceText: Text;
        AllocTargetText: Text;
        AllocRatio: Text;
        AllocTotalAmount: Decimal;
        ReminderAmount: Decimal;
        LastCostJourLineNo: Integer;
        TotalDebit: Decimal;
        TotalCredit: Decimal;
        AllocateBudget: Boolean;
        MsgText: Text;
        AllocSourceErrorFound: Boolean;
        AllocTargetErrorFound: Boolean;
#pragma warning disable AA0074
        Text000: Label 'Allocation date must be defined.';
        Text001: Label 'From Alloc. Level must not be higher than To Alloc. Level.';
        Text002: Label 'Budget cost from budget';
        Text003: Label 'Actual cost';
#pragma warning disable AA0470
        Text004: Label '%1 will be allocated for levels %2 to %3.\Posting date: %4,  group: "%5"\Do you want to start the job?';
        Text005: Label 'Cost allocation\Level                      #1####### \Source ID                  #2####### \Sum source entries         #3####### \Write allocation entries   #4####### ';
#pragma warning restore AA0470
        Text006: Label 'No entries have been created for the selected allocations.';
#pragma warning disable AA0470
        Text007: Label '%1 allocation entries have been generated and processed.';
#pragma warning restore AA0470
        Text008: Label 'Alloc. Source:';
        Text009: Label 'Alloc. Target: ';
#pragma warning disable AA0470
        Text010: Label 'Alloc: %1 of %2 shares. Base LCY %3';
        Text011: Label 'Alloc: %1 pct of %2 shares';
        Text012: Label 'Alloc: %1 LCY of %2 shares';
#pragma warning restore AA0470
        Text013: Label ' ... etc.';
#pragma warning disable AA0470
        Text014: Label 'Alloc. level %1 of %2';
        Text015: Label 'Not all cost types for debit and credit are defined for allocation ID %1.';
        Text016: Label 'For allocation ID %1, cost center or cost object must be defined for debit and credit. Cost center: "%2", cost object "%3".';
#pragma warning restore AA0470
        Text017: Label 'Cost Type';
        Text018: Label 'Cost Center';
        Text019: Label 'Cost Object';
        Text020: Label 'One or more allocation targets do not have a cost center or cost object defined. The allocation cannot continue.';
        Text021: Label 'One or more allocation sources do not have a cost center or cost object defined. The allocation cannot continue.';
        Text022: Label 'Posting Cost Entries @1@@@@@@@@@@\';
#pragma warning restore AA0074

    protected var
        CostAccSetup: Record "Cost Accounting Setup";
        CostBudgetName: Record "Cost Budget Name";
        CostBudgetRegister: Record "Cost Budget Register";
        CostRegister: Record "Cost Register";

    local procedure ShowAllocations(CheckTargets: Boolean)
    var
        CostAllocations: Report "Cost Allocations";
        ConfirmText: Text[1024];
        SkipSourcesWithoutTargets: Boolean;
    begin
        if CheckTargets then begin
            ConfirmText := Text020;
            CostAllocationTarget.SetFilter("Target Cost Center", '%1', '');
            CostAllocationTarget.SetFilter("Target Cost Object", '%1', '');
        end else begin
            ConfirmText := Text021;
            CostAllocationSource.SetFilter("Cost Center Code", '%1', '');
            CostAllocationSource.SetFilter("Cost Object Code", '%1', '');
            CostAllocationTarget.SetFilter(ID, '<%1', '');
        end;
        if Confirm(ConfirmText, true) then begin
            SkipSourcesWithoutTargets := CheckTargets;
            CostAllocations.InitializeRequest(CostAllocationSource, CostAllocationTarget, SkipSourcesWithoutTargets);
            CostAllocations.Run();
        end;
    end;

    local procedure WriteJournalLine(CostTypeCode: Code[20]; CostCenterCode: Code[20]; CostObjectCode: Code[20]; PostAmount: Decimal; Text: Text; AllocKey: Text; AllocID: Code[10]; Allocated2: Boolean)
    var
        CostCenter: Record "Cost Center";
    begin
        if PostAmount = 0 then
            exit;

        if CostCenterCode <> '' then
            if CostCenter.Get(CostCenterCode) then
                CostCenter.TestField(Blocked, false);

        if CostTypeCode = '' then
            Error(Text015, "Cost Allocation Source".ID);

        if ((CostCenterCode = '') and (CostObjectCode = '')) or ((CostCenterCode <> '') and (CostObjectCode <> '')) then
            Error(Text016, "Cost Allocation Source".ID, CostCenterCode, CostObjectCode);

        LastCostJourLineNo := LastCostJourLineNo + 10000;
        TempCostJnlLine."Line No." := LastCostJourLineNo;
        TempCostJnlLine."Posting Date" := AllocDate;
        TempCostJnlLine."Cost Type No." := CostTypeCode;
        TempCostJnlLine."Cost Center Code" := CostCenterCode;
        TempCostJnlLine."Cost Object Code" := CostObjectCode;
        TempCostJnlLine."Document No." := IncStr(CostAccSetup."Last Allocation Doc. No.");
        TempCostJnlLine.Description := CopyStr(Text, 1, MaxStrLen(TempCostJnlLine.Description));
        TempCostJnlLine.Amount := PostAmount;
        TempCostJnlLine."System-Created Entry" := true;
        TempCostJnlLine.Allocated := Allocated2;
        TempCostJnlLine."Allocation Description" := CopyStr(AllocKey, 1, MaxStrLen(TempCostJnlLine."Allocation Description"));
        TempCostJnlLine."Allocation ID" := AllocID;
        TempCostJnlLine."Source Code" := SourceCodeSetup."Cost Allocation";
        TempCostJnlLine."Budget Name" := CostBudgetName.Name;
        OnWriteJournalLineOnBeforeInsertTempCostJournalLine(TempCostJnlLine, "Cost Allocation Source");
        TempCostJnlLine.Insert();

        if TempCostJnlLine.Amount > 0 then
            TotalDebit := TotalDebit + TempCostJnlLine.Amount
        else
            TotalCredit := TotalCredit + TempCostJnlLine.Amount;

        EntriesPerLevel := EntriesPerLevel + 1;
        TotalEntries := TotalEntries + 1;
        Window.Update(4, Format(TotalEntries));
    end;

    local procedure PostCostJournalLines()
    var
        CostJnlLine: Record "Cost Journal Line";
        CAJnlPostLine: Codeunit "CA Jnl.-Post Line";
        Window2: Dialog;
        CostJnlLineStep: Integer;
        JournalLineCount: Integer;
    begin
        TempCostJnlLine.Reset();
        Window2.Open(
          Text022);
        if TempCostJnlLine.Count > 0 then
            JournalLineCount := 10000 * 100000 div TempCostJnlLine.Count();
        if TempCostJnlLine.FindSet() then begin
            repeat
                CostJnlLineStep := CostJnlLineStep + JournalLineCount;
                Window2.Update(1, CostJnlLineStep div 100000);
                CostJnlLine := TempCostJnlLine;
                CAJnlPostLine.RunWithCheck(CostJnlLine);
            until TempCostJnlLine.Next() = 0;
            TempCostJnlLine.DeleteAll();
        end;
        Window2.Close();
    end;

    procedure InitializeRequest(NewFromLevel: Integer; NewToLevel: Integer; NewAllocDate: Date; NewAllocVariant: Code[10]; NewCostBudgetName: Code[10])
    begin
        FromLevel := NewFromLevel;
        ToLevel := NewToLevel;
        AllocDate := NewAllocDate;
        AllocVariant := NewAllocVariant;
        CostBudgetName.Name := NewCostBudgetName;
    end;

    [IntegrationEvent(false, false)]
    local procedure OnWriteJournalLineOnBeforeInsertTempCostJournalLine(var TempCostJournalLine: Record "Cost Journal Line" temporary; CostAllocationSource: Record "Cost Allocation Source")
    begin
    end;
}