microsoft / ALAppExtensions

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

[Code Change] Codeunit 80 - Sales-Post - CreatePrepaymentLines #15070

Closed MattiLE closed 2 years ago

MattiLE commented 3 years ago

Hi Al-team, in the function CreatePrepaymentLines from Codeunit Sales-Post a GLAcc record is read. Which record is read can be changed via the function GetSalesPrepmtAccount.

GLAcc.Get(GenPostingSetup.GetSalesPrepmtAccount);

Normally, the "Sales Prepayment Account" G/L account is returned in the GetSalesPrepmtAccount function. The function uses the Handled Pattern to change the return value.

A few lines later in the CreatePrepaymentLines function a new TempPrepmtSalesLine is to be written where the "No." field is validated.

TempPrepmtSalesLine.Validate("No.", GenPostingSetup."Sales Prepayments Account"); Here, the field "Sales Prepayments Account" from the table GenPostingSetup is now used directly. My suggestion is to now simply use the G/L account read above for this assignment.

Here is the complete code snippet:

local procedure CreatePrepaymentLines(SalesHeader: Record "Sales Header"; CompleteFunctionality: Boolean)
    var
        GLAcc: Record "G/L Account";
        TempSalesLine: Record "Sales Line" temporary;
        TempExtTextLine: Record "Extended Text Line" temporary;
        GenPostingSetup: Record "General Posting Setup";
        TempPrepmtSalesLine: Record "Sales Line" temporary;
        TransferExtText: Codeunit "Transfer Extended Text";
        NextLineNo: Integer;
        Fraction: Decimal;
        VATDifference: Decimal;
        TempLineFound: Boolean;
        PrepmtAmtToDeduct: Decimal;
        IsHandled: Boolean;
    begin
        IsHandled := false;
        OnBeforeCreatePrepaymentLines(SalesHeader, TempPrepmtSalesLine, CompleteFunctionality, IsHandled, TempSalesLineGlobal);
        if IsHandled then
            exit;

        GetGLSetup();
        with TempSalesLine do begin
            // Get Sales lines
            FillTempLines(SalesHeader, TempSalesLineGlobal);
            // Copy TempSalesLineGlobal to TempSalesLine
            ResetTempLines(TempSalesLine);

            if not FindLast then
                exit;

            NextLineNo := "Line No." + 10000;
            SetFilter(Quantity, '>0');
            SetFilter("Qty. to Invoice", '>0');
            TempPrepmtSalesLine.SetHasBeenShown;

            // Get all sales lines
            if FindSet() then begin
                if CompleteFunctionality and ("Document Type" = "Document Type"::Invoice) then
                    TestGetShipmentPPmtAmtToDeduct;
                repeat
                    if CompleteFunctionality then
                        if SalesHeader."Document Type" <> SalesHeader."Document Type"::Invoice then begin
                            if not SalesHeader.Ship and ("Qty. to Invoice" = Quantity - "Quantity Invoiced") then
                                if "Qty. Shipped Not Invoiced" < "Qty. to Invoice" then
                                    Validate("Qty. to Invoice", "Qty. Shipped Not Invoiced");
                            Fraction := ("Qty. to Invoice" + "Quantity Invoiced") / Quantity;

                            if "Prepayment %" <> 100 then
                                case true of
                                    ("Prepmt Amt to Deduct" <> 0) and
                                  ("Prepmt Amt to Deduct" > Round(Fraction * "Line Amount", Currency."Amount Rounding Precision")):
                                        FieldError(
                                          "Prepmt Amt to Deduct",
                                          StrSubstNo(CannotBeGreaterThanErr,
                                            Round(Fraction * "Line Amount", Currency."Amount Rounding Precision")));
                                    ("Prepmt. Amt. Inv." <> 0) and
                                  (Round((1 - Fraction) * "Line Amount", Currency."Amount Rounding Precision") <
                                   Round(
                                     Round(
                                       Round("Unit Price" * (Quantity - "Quantity Invoiced" - "Qty. to Invoice"),
                                         Currency."Amount Rounding Precision") *
                                       (1 - ("Line Discount %" / 100)), Currency."Amount Rounding Precision") *
                                     "Prepayment %" / 100, Currency."Amount Rounding Precision")):
                                        FieldError(
                                          "Prepmt Amt to Deduct",
                                          StrSubstNo(CannotBeSmallerThanErr,
                                            Round(
                                              "Prepmt. Amt. Inv." - "Prepmt Amt Deducted" - (1 - Fraction) * "Line Amount",
                                              Currency."Amount Rounding Precision")));
                                end;
                        end;
                    if "Prepmt Amt to Deduct" <> 0 then begin
                        if ("Gen. Bus. Posting Group" <> GenPostingSetup."Gen. Bus. Posting Group") or
                           ("Gen. Prod. Posting Group" <> GenPostingSetup."Gen. Prod. Posting Group")
                        then
                            GenPostingSetup.Get("Gen. Bus. Posting Group", "Gen. Prod. Posting Group");
                        GLAcc.Get(GenPostingSetup.GetSalesPrepmtAccount);
                        TempLineFound := false;
                        if SalesHeader."Compress Prepayment" then begin
                            TempPrepmtSalesLine.SetRange("No.", GLAcc."No.");
                            TempPrepmtSalesLine.SetRange("Dimension Set ID", "Dimension Set ID");
                            OnCreatePrepaymentLinesOnAfterTempPrepmtSalesLineSetFilters(TempPrepmtSalesLine);
                            TempLineFound := TempPrepmtSalesLine.FindFirst();
                        end;
                        if TempLineFound then begin
                            PrepmtAmtToDeduct :=
                              TempPrepmtSalesLine."Prepmt Amt to Deduct" +
                              InsertedPrepmtVATBaseToDeduct(
                                SalesHeader, TempSalesLine, TempPrepmtSalesLine."Line No.", TempPrepmtSalesLine."Unit Price");
                            VATDifference := TempPrepmtSalesLine."VAT Difference";
                            TempPrepmtSalesLine.Validate(
                              "Unit Price", TempPrepmtSalesLine."Unit Price" + "Prepmt Amt to Deduct");
                            TempPrepmtSalesLine.Validate("VAT Difference", VATDifference - "Prepmt VAT Diff. to Deduct");
                            TempPrepmtSalesLine."Prepmt Amt to Deduct" := PrepmtAmtToDeduct;
                            if "Prepayment %" < TempPrepmtSalesLine."Prepayment %" then
                                TempPrepmtSalesLine."Prepayment %" := "Prepayment %";
                            OnBeforeTempPrepmtSalesLineModify(TempPrepmtSalesLine, TempSalesLine, SalesHeader, CompleteFunctionality);
                            TempPrepmtSalesLine.Modify();
                        end else begin
                            TempPrepmtSalesLine.Init();
                            TempPrepmtSalesLine."Document Type" := SalesHeader."Document Type";
                            TempPrepmtSalesLine."Document No." := SalesHeader."No.";
                            TempPrepmtSalesLine."Line No." := 0;
                            TempPrepmtSalesLine."System-Created Entry" := true;
                            if CompleteFunctionality then
                                TempPrepmtSalesLine.Validate(Type, TempPrepmtSalesLine.Type::"G/L Account")
                            else
                                TempPrepmtSalesLine.Type := TempPrepmtSalesLine.Type::"G/L Account";

                            // deduct from prepayment 
                            // NEW >>>>
                            // TempPrepmtSalesLine.Validate("No.", GenPostingSetup."Sales Prepayments Account");
                             TempPrepmtSalesLine.Validate("No.", GLAcc."No.");
                            // NEW <<<<
                            TempPrepmtSalesLine.Validate(Quantity, -1);
                            TempPrepmtSalesLine."Qty. to Ship" := TempPrepmtSalesLine.Quantity;
                            TempPrepmtSalesLine."Qty. to Invoice" := TempPrepmtSalesLine.Quantity;
                            PrepmtAmtToDeduct := InsertedPrepmtVATBaseToDeduct(SalesHeader, TempSalesLine, NextLineNo, 0);
                            TempPrepmtSalesLine.Validate("Unit Price", "Prepmt Amt to Deduct");
                            TempPrepmtSalesLine.Validate("VAT Difference", -"Prepmt VAT Diff. to Deduct");
                            TempPrepmtSalesLine."Prepmt Amt to Deduct" := PrepmtAmtToDeduct;
                            TempPrepmtSalesLine."Prepayment %" := "Prepayment %";
                            TempPrepmtSalesLine."Prepayment Line" := true;
                            TempPrepmtSalesLine."Shortcut Dimension 1 Code" := "Shortcut Dimension 1 Code";
                            TempPrepmtSalesLine."Shortcut Dimension 2 Code" := "Shortcut Dimension 2 Code";
                            TempPrepmtSalesLine."Dimension Set ID" := "Dimension Set ID";
                            TempPrepmtSalesLine."Line No." := NextLineNo;
                            NextLineNo := NextLineNo + 10000;
                            OnBeforeTempPrepmtSalesLineInsert(TempPrepmtSalesLine, TempSalesLine, SalesHeader, CompleteFunctionality);
                            TempPrepmtSalesLine.Insert();

                            TransferExtText.PrepmtGetAnyExtText(
                              TempPrepmtSalesLine."No.", DATABASE::"Sales Invoice Line",
                              SalesHeader."Document Date", SalesHeader."Language Code", TempExtTextLine);
                            if TempExtTextLine.Find('-') then
                                repeat
                                    TempPrepmtSalesLine.Init();
                                    TempPrepmtSalesLine.Description := TempExtTextLine.Text;
                                    TempPrepmtSalesLine."System-Created Entry" := true;
                                    TempPrepmtSalesLine."Prepayment Line" := true;
                                    TempPrepmtSalesLine."Line No." := NextLineNo;
                                    NextLineNo := NextLineNo + 10000;
                                    TempPrepmtSalesLine.Insert();
                                until TempExtTextLine.Next() = 0;
                        end;
                    end;
                until Next() = 0;
                OnCreatePrepaymentLinesOnAfterProcessSalesLines(SalesHeader, TempPrepmtSalesLine);
            end;
        end;
        DividePrepmtAmountLCY(TempPrepmtSalesLine, SalesHeader);
        if TempPrepmtSalesLine.FindSet() then
            repeat
                TempSalesLineGlobal := TempPrepmtSalesLine;
                TempSalesLineGlobal.Insert();
            until TempPrepmtSalesLine.Next() = 0;
    end;
JesperSchulz commented 2 years ago

Thanks for reporting this. We agree, and we’ll publish a fix asap, either in an update for the current version or in the next major release. Please do not reply to this, as we do not monitor closed issues. If you have follow-up questions or requests, please create a new issue where you reference this one.