Codeunit 5612 Calculate Custom 1 Depr.

App
Base Application
Namespace
Microsoft.FixedAssets.Depreciation
Versions
17-28

Procedures, 1Events, 5

Versions171819202122232425262728

Source29

Source in 29

src/Layers/W1/BaseApp/FixedAssets/Depreciation/CalculateCustom1Depr.Codeunit.al477 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.FixedAssets.Depreciation;

using Microsoft.FixedAssets.FixedAsset;
using Microsoft.FixedAssets.Ledger;
using Microsoft.FixedAssets.Posting;

codeunit 5612 "Calculate Custom 1 Depr."
{
    Permissions = TableData "FA Ledger Entry" = r,
                  TableData "FA Posting Type Setup" = r;

    trigger OnRun()
    begin
    end;

    var
        FA: Record "Fixed Asset";
        DeprBook: Record "Depreciation Book";
        FADeprBook: Record "FA Depreciation Book";
        FAPostingTypeSetup: Record "FA Posting Type Setup";
        DepreciationCalc: Codeunit "Depreciation Calculation";
        DeprBookCode: Code[10];
        UntilDate: Date;
        Sign: Integer;
        FirstDeprDate: Date;
        DaysInFiscalYear: Integer;
        NumberOfDays: Integer;
        NumberOfDays4: Integer;
        DaysInPeriod: Integer;
        EntryAmounts: array[4] of Decimal;
        DateFromProjection: Date;
        UseDeprStartingDate: Boolean;
        BookValue: Decimal;
        MinusBookValue: Decimal;
        SalvageValue: Decimal;
        AcquisitionDate: Date;
        DisposalDate: Date;
        DeprMethod: Enum "FA Depreciation Method";
        DeprStartingDate: Date;
        FirstUserDefinedDeprDate: Date;
        SLPercent: Decimal;
        DBPercent: Decimal;
        FixedAmount: Decimal;
        DeprYears: Decimal;
        DeprTable: Code[10];
        FinalRoundingAmount: Decimal;
        EndingBookValue: Decimal;
        Custom1DeprStartingDate: Date;
        Custom1DeprUntil: Date;
        Custom1AccumPercent: Decimal;
        Custom1PercentThisYear: Decimal;
        Custom1PropertyClass: Option " ","Personal Property","Real Property";
        AcquisitionCost: Decimal;
        Custom1Depr: Decimal;
        ExtraDays: Integer;

#pragma warning disable AA0074
#pragma warning disable AA0470
        Text000: Label 'A depreciation entry must be posted on %2 = %3 for %1.';
        Text001: Label '%2 is positive on %3 = %4 for %1.';
        Text002: Label '%2 must not be 100 for %1.';
        Text003: Label '%2 is later than %3 for %1.';
        Text004: Label 'You must not specify %2 together with %3 = %4 for %1.';
#pragma warning restore AA0470
#pragma warning restore AA0074

    procedure Calculate(var DeprAmount: Decimal; var Custom1DeprAmount: Decimal; var NumberOfDays3: Integer; var Custom1NumberOfDays3: Integer; FANo: Code[20]; DeprBookCode2: Code[10]; UntilDate2: Date; EntryAmounts2: array[4] of Decimal; DateFromProjection2: Date; DaysInPeriod2: Integer)
    var
        i: Integer;
        IsHandled: Boolean;
    begin
        IsHandled := false;
        OnBeforeCalculate(DeprAmount, Custom1DeprAmount, NumberOfDays3, Custom1NumberOfDays3, FANo, DeprBookCode2, UntilDate2, EntryAmounts2, DateFromProjection2, DaysInPeriod2, IsHandled);
        if IsHandled then
            exit;

        ClearAll();
        DeprAmount := 0;
        Custom1DeprAmount := 0;
        NumberOfDays3 := 0;
        Custom1NumberOfDays3 := 0;
        DeprBookCode := DeprBookCode2;
        FA.Get(FANo);
        DeprBook.Get(DeprBookCode);
        if not FADeprBook.Get(FANo, DeprBookCode) then
            exit;
        OnAfterGetDeprBooks(DeprBook, FADeprBook);

        DeprBook.TestField("Fiscal Year 365 Days", false);
        for i := 1 to 4 do
            EntryAmounts[i] := EntryAmounts2[i];
        DateFromProjection := DateFromProjection2;
        DaysInPeriod := DaysInPeriod2;
        UntilDate := UntilDate2;
        DeprBook.TestField("Allow Depr. below Zero", false);
        FADeprBook.TestField("Fixed Depr. Amount below Zero", 0);
        FADeprBook.TestField("Depr. below Zero %", 0);
        FADeprBook.TestField("Use Half-Year Convention", false);
        DeprBook.TestField(
          "Periodic Depr. Date Calc.", DeprBook."Periodic Depr. Date Calc."::"Last Entry");

        FADeprBook.TestField("Property Class (Custom 1)");
        FAPostingTypeSetup.Get(
          DeprBookCode, FAPostingTypeSetup."FA Posting Type"::"Custom 1");
        FAPostingTypeSetup.TestField("Part of Book Value", true);
        FAPostingTypeSetup.TestField("Part of Depreciable Basis", false);
        FAPostingTypeSetup.TestField("Include in Depr. Calculation", true);
        FAPostingTypeSetup.TestField(Sign, FAPostingTypeSetup.Sign::Credit);

        TransferValues();
        if not SkipRecord() then begin
            Sign := 1;
            if not FADeprBook."Use FA Ledger Check" then begin
                if DeprBook."Use FA Ledger Check" then
                    FADeprBook.TestField("Use FA Ledger Check", true);
                Sign :=
                  DepreciationCalc.GetCustom1Sign(
                    BookValue, AcquisitionCost, Custom1Depr, SalvageValue, MinusBookValue);
                if Sign = 0 then
                    exit;
                if Sign = -1 then
                    DepreciationCalc.GetNewCustom1Signs(
                      BookValue, AcquisitionCost, Custom1Depr, SalvageValue, MinusBookValue);
            end;
            if BookValue + SalvageValue <= 0 then
                exit;
            if (SalvageValue >= 0) and (BookValue <= EndingBookValue) then
                exit;
            if DateFromProjection > 0D then
                FirstDeprDate := DateFromProjection
            else begin
                FirstDeprDate := DepreciationCalc.GetFirstDeprDate(FANo, DeprBookCode, false, DeprBook."Use Accounting Period");
                if (FirstDeprDate > UntilDate) or (FirstDeprDate = 0D) then
                    exit;
                if (Custom1DeprUntil = 0D) or (FirstDeprDate <= Custom1DeprUntil) then begin
                    UseDeprStartingDate := DepreciationCalc.UseDeprStartingDate(FANo, DeprBookCode);
                    if UseDeprStartingDate then
                        FirstDeprDate := DeprStartingDate;
                end;
                if FirstDeprDate < DeprStartingDate then
                    FirstDeprDate := DeprStartingDate;
                if FirstDeprDate > UntilDate then
                    exit;
            end;
            if UseDeprStartingDate then
                ExtraDays := DepreciationCalc.DeprDays(
                    Custom1DeprStartingDate, DeprStartingDate, false, DeprBook."Use Accounting Period") - 1;
            if (Custom1DeprUntil > 0D) and (FirstDeprDate <= Custom1DeprUntil) and
               (UntilDate > Custom1DeprUntil)
            then
                Error(
                  Text000,
                  FAName(), FADeprBook.FieldCaption("Depr. Ending Date (Custom 1)"), Custom1DeprUntil);
            NumberOfDays := DepreciationCalc.DeprDays(FirstDeprDate, UntilDate, false, DeprBook."Use Accounting Period");

            if NumberOfDays <= 0 then
                exit;

            if DaysInPeriod > 0 then begin
                NumberOfDays4 := NumberOfDays;
                NumberOfDays := DaysInPeriod;
                ExtraDays := 0;
            end;

            CalcDeprBasis();

            case DeprMethod of
                DeprMethod::"Straight-Line":
                    DeprAmount := CalcSLAmount();
                DeprMethod::"Declining-Balance 1":
                    DeprAmount := CalcDB1Amount();
                DeprMethod::"Declining-Balance 2":
                    DeprAmount := CalcDB2Amount();
                DeprMethod::"DB1/SL":
                    DeprAmount := CalcDBSLAmount();
                DeprMethod::"DB2/SL",
              DeprMethod::Manual:
                    DeprAmount := 0;
                DeprMethod::"User-Defined":
                    DeprAmount := CalcCustom1Amount();
            end;

            OnCalculateOnBeforeCalcCustom1DeprAmount(DeprMethod, DeprAmount);

            Custom1DeprAmount := CalcCustom1DeprAmount();
            DepreciationCalc.AdjustCustom1(
              DeprBookCode, DeprAmount, Custom1DeprAmount, BookValue, SalvageValue,
              EndingBookValue, FinalRoundingAmount);
            DeprAmount := Sign * DeprAmount;
            Custom1DeprAmount := Sign * Custom1DeprAmount;
            NumberOfDays3 := NumberOfDays;
            Custom1NumberOfDays3 := NumberOfDays + ExtraDays;
        end;
    end;

    local procedure SkipRecord(): Boolean
    begin
        exit(
          (DisposalDate > 0D) or
          (AcquisitionDate = 0D) or
          (DeprMethod = DeprMethod::Manual) or
          (AcquisitionDate > UntilDate) or
          FA.Inactive or
          FA.Blocked);
    end;

    local procedure CalcSLAmount(): Decimal
    var
        RemainingLife: Decimal;
    begin
        if SLPercent > 0 then
            exit(-CalcDeprBasis() * CalcSLPercent() / 100);

        if FixedAmount > 0 then
            exit(-FixedAmount * NumberOfDays / DaysInFiscalYear);

        if DeprYears > 0 then begin
            if (Custom1DeprUntil = 0D) or (UntilDate > Custom1DeprUntil) then begin
                RemainingLife :=
                  (DeprYears * DaysInFiscalYear) -
                  DepreciationCalc.DeprDays(
                    DeprStartingDate, DepreciationCalc.Yesterday(FirstDeprDate, false, DeprBook."Use Accounting Period"),
                    false, DeprBook."Use Accounting Period");
                OnCalcSLAmountOnAfterSetRemainingLife(RemainingLife, Custom1PropertyClass, Custom1DeprStartingDate, Custom1DeprUntil);
                if RemainingLife < 1 then
                    exit(-BookValue);

                exit(-(BookValue + SalvageValue - MinusBookValue) * NumberOfDays / RemainingLife);
            end;
            exit(-AcquisitionCost * NumberOfDays / DeprYears / DaysInFiscalYear);
        end;
        exit(0);
    end;

    local procedure CalcDBSLAmount(): Decimal
    var
        SLAmount: Decimal;
        DBAmount: Decimal;
    begin
        if DeprMethod = DeprMethod::"DB1/SL" then
            DBAmount := CalcDB1Amount()
        else
            DBAmount := CalcDB2Amount();
        if UntilDate <= Custom1DeprUntil then
            exit(DBAmount);
        SLAmount := CalcSLAmount();
        if SLAmount < DBAmount then
            exit(SLAmount);

        exit(DBAmount)
    end;

    local procedure CalcDB2Amount(): Decimal
    begin
        exit(
          -(1 - Power(1 - DBPercent / 100, NumberOfDays / DaysInFiscalYear)) *
          (BookValue - MinusBookValue));
    end;

    local procedure CalcDB1Amount(): Decimal
    var
        DeprInFiscalYear: Decimal;
    begin
        if DateFromProjection = 0D then
            DeprInFiscalYear := DepreciationCalc.DeprInFiscalYear(FA."No.", DeprBookCode, UntilDate)
        else
            DeprInFiscalYear := EntryAmounts[3];
        exit(
          -(DBPercent / 100) * (NumberOfDays / DaysInFiscalYear) *
          (BookValue - MinusBookValue - Sign * DeprInFiscalYear));
    end;

    local procedure CalcCustom1Amount(): Decimal
    var
        TableDeprCalc: Codeunit "Table Depr. Calculation";
        Factor: Decimal;
    begin
        Factor := 1;
        if DaysInPeriod > 0 then
            Factor := DaysInPeriod / NumberOfDays4;
        exit(
          -TableDeprCalc.GetTablePercent(
            DeprBook.Code, DeprTable, FirstUserDefinedDeprDate, FirstDeprDate, UntilDate) *
          AcquisitionCost * Factor);
    end;

    local procedure CalcSLPercent(): Decimal
    var
        FractionOfFiscalYear: Decimal;
        CalcDeprYears: Decimal;
        YearsOfCustom1Depr: Decimal;
    begin
        FractionOfFiscalYear := NumberOfDays / DaysInFiscalYear;
        if SLPercent <= 0 then
            exit(0);
        if (Custom1PropertyClass = Custom1PropertyClass::"Real Property") or
           (Custom1DeprUntil = 0D) or (UntilDate <= Custom1DeprUntil)
        then
            exit(SLPercent * FractionOfFiscalYear);

        YearsOfCustom1Depr :=
          DepreciationCalc.DeprDays(
            Custom1DeprStartingDate, Custom1DeprUntil, false, DeprBook."Use Accounting Period")
          / DaysInFiscalYear;
        CalcDeprYears := 100 / SLPercent;
        if (CalcDeprYears - YearsOfCustom1Depr) <= 0.001 then
            exit(0);
        exit(100 * FractionOfFiscalYear / (CalcDeprYears - YearsOfCustom1Depr));
    end;

    local procedure CalcCustom1DeprPercent(): Decimal
    var
        MaxPercent: Decimal;
        CurrentPercent: Decimal;
    begin
        if (Custom1DeprUntil = 0D) or (UntilDate > Custom1DeprUntil) or (AcquisitionCost < 0.01) then
            exit(0);

        MaxPercent := Custom1AccumPercent - (-Custom1Depr * 100 / AcquisitionCost);
        if MaxPercent < 0 then
            exit(0);
        CurrentPercent := Custom1PercentThisYear * (NumberOfDays + ExtraDays) / DaysInFiscalYear;
        if CurrentPercent > MaxPercent then
            CurrentPercent := MaxPercent;
        exit(CurrentPercent);
    end;

    local procedure CalcCustom1DeprAmount(): Decimal
    begin
        exit(-AcquisitionCost * CalcCustom1DeprPercent() / 100);
    end;

    local procedure CalcDeprBasis(): Decimal
    var
        FALedgEntry: Record "FA Ledger Entry";
    begin
        if (Custom1DeprUntil = 0D) or (UntilDate <= Custom1DeprUntil) then
            exit(AcquisitionCost);
        FALedgEntry.SetCurrentKey("FA No.", "Depreciation Book Code", "Part of Book Value", "FA Posting Date");
        FALedgEntry.SetRange("FA No.", FA."No.");
        FALedgEntry.SetRange("Depreciation Book Code", DeprBookCode);
        FALedgEntry.SetRange("Part of Book Value", true);
        FALedgEntry.SetRange("FA Posting Date", 0D, Custom1DeprUntil);
        FALedgEntry.ReadIsolation(IsolationLevel::ReadCommitted);
        FALedgEntry.CalcSums(Amount);
        if (Sign = -1) and (FALedgEntry.Amount > 0) then
            Error(
              Text001,
              FAName(), FADeprBook.FieldCaption("Book Value"),
              FADeprBook.FieldCaption("Depr. Ending Date (Custom 1)"), Custom1DeprUntil);
        if DateFromProjection = 0D then
            exit(Abs(FALedgEntry.Amount));

        exit(EntryAmounts[4]);
    end;

    local procedure TransferValues()
    begin
        FADeprBook.TestField("Depreciation Starting Date");
        if FADeprBook."Depreciation Method" = FADeprBook."Depreciation Method"::"User-Defined" then begin
            FADeprBook.TestField("Depreciation Table Code");
            FADeprBook.TestField("First User-Defined Depr. Date");
        end;
        case FADeprBook."Depreciation Method" of
            FADeprBook."Depreciation Method"::"Declining-Balance 1",
          FADeprBook."Depreciation Method"::"Declining-Balance 2":
                if FADeprBook."Declining-Balance %" >= 100 then
                    Error(Text002, FAName(), FADeprBook.FieldCaption("Declining-Balance %"));
        end;
        if DateFromProjection = 0D then begin
            FADeprBook.CalcFields("Book Value", "Acquisition Cost", "Custom 1", "Salvage Value");
            BookValue := FADeprBook."Book Value";
            Custom1Depr := FADeprBook."Custom 1";
        end else begin
            FADeprBook.CalcFields("Acquisition Cost", "Salvage Value");
            BookValue := EntryAmounts[1];
            Custom1Depr := EntryAmounts[2];
        end;
        MinusBookValue := DepreciationCalc.GetMinusBookValue(FA."No.", DeprBookCode, 0D, 0D) + DepreciationCalc.GetUnpostedBonusDepreciationForCalc(FADeprBook, 0D, 0D);
        AcquisitionCost := FADeprBook."Acquisition Cost";
        SalvageValue := FADeprBook."Salvage Value";
        DeprMethod := FADeprBook."Depreciation Method";
        DeprStartingDate := FADeprBook."Depreciation Starting Date";
        DeprTable := FADeprBook."Depreciation Table Code";
        FirstUserDefinedDeprDate := FADeprBook."First User-Defined Depr. Date";
        if (FADeprBook."Depreciation Method" = FADeprBook."Depreciation Method"::"User-Defined") and
           (FirstUserDefinedDeprDate > DeprStartingDate)
        then
            Error(
              Text003,
              FAName(), FADeprBook.FieldCaption("First User-Defined Depr. Date"), FADeprBook.FieldCaption("Depreciation Starting Date"));
        SLPercent := FADeprBook."Straight-Line %";
        DeprYears := FADeprBook."No. of Depreciation Years";
        DBPercent := FADeprBook."Declining-Balance %";
        if FADeprBook."Depreciation Ending Date" > 0D then begin
            if FADeprBook."Depreciation Starting Date" > FADeprBook."Depreciation Ending Date" then
                Error(
                  Text003,
                  FAName(), FADeprBook.FieldCaption("Depreciation Starting Date"), FADeprBook.FieldCaption("Depreciation Ending Date"));
            DeprYears :=
              DepreciationCalc.DeprDays(
                FADeprBook."Depreciation Starting Date", FADeprBook."Depreciation Ending Date", false,
                DeprBook."Use Accounting Period") / 360;
        end;
        FixedAmount := FADeprBook."Fixed Depr. Amount";
        FinalRoundingAmount := FADeprBook."Final Rounding Amount";
        if FinalRoundingAmount = 0 then
            FinalRoundingAmount := DeprBook."Default Final Rounding Amount";
        EndingBookValue := FADeprBook."Ending Book Value";
        if not FADeprBook."Ignore Def. Ending Book Value" and (EndingBookValue = 0) then
            EndingBookValue := DeprBook."Default Ending Book Value";
        AcquisitionDate := FADeprBook."Acquisition Date";
        DisposalDate := FADeprBook."Disposal Date";
        DaysInFiscalYear := DeprBook."No. of Days in Fiscal Year";
        if DaysInFiscalYear = 0 then
            DaysInFiscalYear := 360;
        Custom1DeprStartingDate := FADeprBook."Depr. Starting Date (Custom 1)";
        Custom1DeprUntil := FADeprBook."Depr. Ending Date (Custom 1)";
        Custom1AccumPercent := FADeprBook."Accum. Depr. % (Custom 1)";
        Custom1PercentThisYear := FADeprBook."Depr. This Year % (Custom 1)";
        Custom1PropertyClass := FADeprBook."Property Class (Custom 1)";
        if Custom1DeprStartingDate = 0D then
            Custom1DeprStartingDate := DeprStartingDate;
        if Custom1DeprStartingDate > DeprStartingDate then
            Error(
              Text003,
              FAName(), FADeprBook.FieldCaption("Depr. Starting Date (Custom 1)"), FADeprBook.FieldCaption("Depreciation Starting Date"));
        if (Custom1DeprUntil > 0D) and (Custom1DeprUntil < DeprStartingDate) then
            Error(
              Text003,
              FAName(), FADeprBook.FieldCaption("Depreciation Starting Date"), FADeprBook.FieldCaption("Depr. Ending Date (Custom 1)"));
        if (DeprMethod = DeprMethod::"DB2/SL") and (Custom1DeprUntil > 0D) then
            Error(
              Text004,
              FAName(), FADeprBook.FieldCaption("Depr. Ending Date (Custom 1)"),
              FADeprBook.FieldCaption("Depreciation Method"), FADeprBook."Depreciation Method");
        OnAfterTransferValues(FA, DeprBook, FADeprBook, DeprMethod, UntilDate, SalvageValue, AcquisitionCost);
    end;

    local procedure FAName(): Text[200]
    var
        DepreciationCalc: Codeunit "Depreciation Calculation";
    begin
        exit(DepreciationCalc.FAName(FA, DeprBookCode));
    end;

    [IntegrationEvent(false, false)]
    local procedure OnAfterTransferValues(FixedAsset: Record "Fixed Asset"; DepreciationBook: Record "Depreciation Book"; FADepreciationBook: Record "FA Depreciation Book"; DeprMethod: Enum "FA Depr. Method Internal"; UntilDate: Date; var SalvageValue: Decimal; var AcquisitionCost: Decimal)
    begin
    end;

    [IntegrationEvent(false, false)]
    local procedure OnBeforeCalculate(var DeprAmount: Decimal; var Custom1DeprAmount: Decimal; var NumberOfDays3: Integer; var Custom1NumberOfDays3: Integer; FANo: Code[20]; DeprBookCode2: Code[10]; UntilDate2: Date; EntryAmounts2: array[4] of Decimal; DateFromProjection2: Date; DaysInPeriod2: Integer; var IsHandled: Boolean)
    begin
    end;

    [IntegrationEvent(false, false)]
    local procedure OnAfterGetDeprBooks(var DepreciationBook: Record "Depreciation Book"; var FADepreciationBook: Record "FA Depreciation Book")
    begin
    end;

    [IntegrationEvent(false, false)]
    local procedure OnCalculateOnBeforeCalcCustom1DeprAmount(var FADepreciationMethod: Enum "FA Depreciation Method"; var DeprAmount: Decimal)
    begin
    end;

    [IntegrationEvent(false, false)]
    local procedure OnCalcSLAmountOnAfterSetRemainingLife(var RemainingLife: Decimal; Custom1PropertyClass: Option " ","Personal Property","Real Property"; Custom1DeprStartingDate: Date; Custom1DeprUntil: Date)
    begin
    end;
}