microsoft / ALAppExtensions

Repository for collaboration on Microsoft AL application add-on and localization extensions for Microsoft Dynamics 365 Business Central.
MIT License
796 stars 622 forks source link

[Event Request] Codeunit 5940 ServContractManagement - procedure InsertMultipleServLedgEntries #27687

Open matthiasrabus opened 1 week ago

matthiasrabus commented 1 week ago

Describe the request

To implement a complex change in the calculation of the service ledger entry, i need the following four events. Please add them, if possible.

procedure InsertMultipleServLedgEntries(var NoOfPayments: Integer; var DueDate: Date; var NonDistrAmount: array[4] of Decimal; var InvRoundedAmount: array[4] of Decimal; var ServHeader: Record "Service Header"; InvFrom: Date; NextInvDate: Date; AddingNewLines: Boolean; CountOfEntryLoop: Integer; ServContractLine: Record "Service Contract Line"; AmountRoundingPrecision: Decimal)
var
    ServContractHeader: Record "Service Contract Header";
    Index: Integer;
    IsHandled: Boolean;
begin
    if CountOfEntryLoop = 0 then
        exit;

    OnBeforeInsertMultipleServLedgEntries(ServLedgEntry, ServContractLine);

    CheckMParts := false;
    if DueDate <> CalcDate('<CM>', DueDate) then begin
        DueDate := CalcDate('<-CM-1D>', DueDate);
        ServContractHeader.Get(ServContractLine."Contract Type", ServContractLine."Contract No.");
        CheckMParts := true;
    end;

    //FIRST EVENT BEGIN
    OnInsertMultipleServLedgEntriesUpdateDateFieldsBeforeCalcNonDistrAmount(InvFrom, DueDate, NoOfPayments);
    //FIRST EVENT END

    NonDistrAmount[AmountType::Amount] :=
      -CalcContractLineAmount(ServContractLine."Line Amount", InvFrom, DueDate);
    NonDistrAmount[AmountType::UnitPrice] :=
      -CalcContractLineAmount(ServContractLine."Line Value", InvFrom, DueDate);
    NonDistrAmount[AmountType::UnitCost] :=
      CalcContractLineAmount(ServContractLine."Line Cost", InvFrom, DueDate);
    NonDistrAmount[AmountType::DiscAmount] :=
      CalcContractLineAmount(ServContractLine."Line Discount Amount", InvFrom, DueDate);
    ServLedgEntry."Service Item No. (Serviced)" := ServContractLine."Service Item No.";
    ServLedgEntry."Item No. (Serviced)" := ServContractLine."Item No.";
    ServLedgEntry."Serial No. (Serviced)" := ServContractLine."Serial No.";
    DueDate := NextInvDate;
    if CheckMParts and (NoOfPayments > 1) then begin
        //SECOND EVENT BEGIN
          IsHandled := false;
        OnInsertMultipleServLedgEntriesUpdateOnBeforeUpdateNoOfPayments(CheckMParts, NoOfPayments, IsHandled);
        if not IsHandled then
        //SECOND EVENT END
        NoOfPayments := NoOfPayments - 1;
        // the count of invoice lines should never exceed the count of payments
        if CountOfEntryLoop > NoOfPayments then
            CountOfEntryLoop := NoOfPayments;
    end;

    if AddingNewLines then
        DueDate := InvFrom;
    for Index := 1 to CountOfEntryLoop do begin
        //THIRD EVENT BEGIN
        IsHandled := false;     
        OnInsertMultipleServLedgEntriesOnBeforeSetSetServLedgEntryAmounts(ServLedgEntry,InvRoundedAmount,NonDistrAmount,NoOfPayments,Index,CountOfEntryLoop,AmountRoundingPrecision,DueDate,IsHandled);
        if not IsHandled then
        //THIRD EVENT END
        SetServLedgEntryAmounts(
          ServLedgEntry, InvRoundedAmount,
          NonDistrAmount[AmountType::Amount] / (NoOfPayments + 1 - Index),
          NonDistrAmount[AmountType::UnitPrice] / (NoOfPayments + 1 - Index),
          NonDistrAmount[AmountType::UnitCost] / (NoOfPayments + 1 - Index),
          NonDistrAmount[AmountType::DiscAmount] / (NoOfPayments + 1 - Index),
          AmountRoundingPrecision);
        ServLedgEntry."Cost Amount" := ServLedgEntry."Charged Qty." * ServLedgEntry."Unit Cost";

        NonDistrAmount[AmountType::Amount] -= ServLedgEntry."Amount (LCY)";
        NonDistrAmount[AmountType::UnitPrice] -= ServLedgEntry."Unit Price";
        NonDistrAmount[AmountType::UnitCost] -= ServLedgEntry."Unit Cost";
        NonDistrAmount[AmountType::DiscAmount] -= ServLedgEntry."Contract Disc. Amount";

        ServLedgEntry."Entry No." := NextEntry;
        UpdateServLedgEntryAmount(ServLedgEntry, ServHeader);
        ServLedgEntry."Posting Date" := DueDate;
        ServLedgEntry.Prepaid := true;
        IsHandled := false;
        OnInsertMultipleServLedgEntriesOnBeforeServLedgEntryInsert(ServLedgEntry, ServContractHeader, ServContractLine, NonDistrAmount, IsHandled, ServHeader);
        if IsHandled then
            exit;
        ServLedgEntry.Insert();
        NextEntry += 1;
        DueDate := CalcDate('<1M>', DueDate);
        //FOURTH EVENT BEGIN
        OnInsertMultipleServLedgEntriesOnAfterSetDueDate(Index, DueDate, ServLedgEntry, CountOfEntryLoop, InvRoundedAmount, NonDistrAmount, ServHeader, AmountRoundingPrecision);
        //FOURTH EVENT END
    end;
end;

The integration events:

[IntegrationEvent(false,false)]
local procedure OnInsertMultipleServLedgEntriesUpdateDateFieldsBeforeCalcNonDistrAmount(var InvFrom: Date; var DueDate: Date; NoOfPayments: Integer)
begin
end;

[IntegrationEvent(false,false)]
local procedure OnInsertMultipleServLedgEntriesUpdateOnBeforeUpdateNoOfPayments(CheckMParts: Boolean; var NoOfPayments: Integer; var IsHandled: Boolean)
begin
end;

[IntegrationEvent(false,false)]
local procedure OnInsertMultipleServLedgEntriesOnBeforeSetSetServLedgEntryAmounts(var ServLedgEntry: Record "Service Ledger Entry"; var InvRoundedAmount: array[4] of Decimal; NonDistrAmount: array[4] of Decimal; NoOfPayments: Integer; Index: Integer; CountOfEntryLoop: Integer; AmountRoundingPrecision: Decimal; DueDate: Date; var IsHandled: Boolean)
begin
end;

[IntegrationEvent(false, false)]
local procedure OnInsertMultipleServLedgEntriesOnAfterSetDueDate(Index: Integer; var DueDate: Date; ServLedgEntry: Record "Service Ledger Entry"; CountOfEntryLoop: Integer; InvRoundedAmount: array[4] of Decimal; var NonDistrAmount: array[4] of Decimal; var ServHeader: Record "Service Header"; AmountRoundingPrecision: Decimal)
begin
end;

Additional context

Please add these events to allow me to implement the necessary changes Internal work item: AB#558846

tomasevicst commented 3 days ago

Where is FirstServEntryNo? Is this in some localization? There is no variable on W1?

matthiasrabus commented 1 day ago

Hi, i'm sorry, FirstServEntryNo shouldn't be part of event.

I need this events to move a code customization from BC14 to BC SaaS. The variable FirstServEntryNo is part of that but as a local, not as event parameter. I corrected the integration event and the call in my first post. Sorry for the inconvenience.