Exercise - Custom functions

Completed

You're a business systems developer for CRONUS International Ltd. You're learning how to develop customizations for Business Central and how to program in AL to customize solutions for customers. You want to customize the Customer Card page by adding an action that adjusts a customer's credit limit based on the customer's previous sales history or resets the limit to zero if no transactions occurred.

You've been given the following requirements:

  • A customer's credit limit can't exceed 50 percent of total sales revenue for the customer in the past 12 months.

  • The customer's credit limit must always be rounded to the nearest 10,000.

  • If the credit limit is rounded during the process, the application must send notification to the user.

  • If the new credit limit doesn't differ from the old one, the application must send notification to the user.

  • If the customer has no sales history over the past 12 months, the credit limit must be reset to zero.

  • The function that sets the credit limit must be available to other objects.

  • The Customer Card page must include an action that calls the function.

  • If the function is called from the page action, and credit limit would be increased, the function must ask the user for confirmation before updating the credit limit.

Tasks

  • Create a new extension.

  • Create a table extension.

  • Create a page extension.

Steps

  1. Start Visual Studio Code.

  2. Create a new AL extension project. Select View > Command Palette... (Ctrl+Shift+P).

  3. Enter AL: Go! in the search box and then select the command from the list.

  4. Accept the suggested path but change the name to CreditLimit (or enter another path).

  5. Select the latest target platform.

  6. Select Microsoft cloud sandbox as the development endpoint.

  7. Download the application symbols. Select View > Command Palette... (Ctrl+Shift+P).

  8. Enter AL: Download symbols in the search box and then select the command from the list.

  9. If requested, provide your organizational credentials (Microsoft 365 account/Microsoft Entra ID account).

  10. Open the app.json file and change the name setting to Credit Limit. Change the publisher setting to Cronus International Ltd.

  11. Change the idRanges to from 50400 to 50450.

  12. Remove the HelloWorld.al file.

  13. Add a folder named: src

  14. In the src folder, create a file named Customer.TableExt.al.

  15. Create a new table extension in this file by using code snippets. Enter ttableext and then press the Tab key.

  16. Change the ID to 50400 and the name to Customer.

  17. Set the Extends parameter to Customer to extend the Customer table.

  18. Add a non local procedure to the Customer table extension and name it UpdateCreditLimit.

  19. Modify the UpdateCreditLimit function so that it receives a parameter named NewCreditLimit, of type Decimal, by reference.

  20. Add another non local procedure and name it CalculateCreditLimit, which returns a value of type Decimal.

  21. Create a new file in the src folder named: CustomerCard.PageExt.al.

  22. Create a new page extension in this file by using code snippets. Enter tpageext and then press the Tab key.

  23. Change the ID to 50130 and the name to CustomerCard.

  24. Set the Extends parameter to Customer Card.

  25. Create a local procedure and name it CallUpdateCreditLimit.

  26. Add an action to the Function action group of ActionItems action container. In the Actions section, enter addAfter("F&unctions).

  27. Add an action with the name UpdateCreditLimit in the addafter section and then set the Caption and Tooltip properties to Update Credit Limit. Set the Image property to CalculateCost.

  28. In the OnAction trigger, call the CallUpdateCreditLimit action.

  29. Modify the CalculateCreditLimit function of the table extension. Add a local variable with the name Customer of type Record Customer.

  30. Add code to the CalculateCreditLimit function that calculates the Sales (LCY) field for the past 12 months.

    Cust := Rec;
    Cust.SetRange("Date Filter",CalcDate('<-12M>',WorkDate()),WorkDate());
    Cust.CalcFields("Sales (LCY)","Balance (LCY)");
    exit(Round(Cust."Sales (LCY)" * 0.5));
    

    One of the requirements is: A customer's credit limit can't exceed 50 percent of total sales revenue for the customer in the past 12 months.

  31. Add code to the UpdateCreditLimit function to round the NewCreditLimit formal parameter to the nearest 10,000, to validate the value of NewCreditLimit into the Credit Limit (LCY) field, and to modify the record.

    NewCreditLimit := Round(NewCreditLimit, 10000);
    Rec.Validate("Credit Limit (LCY)", NewCreditLimit);
    Rec.Modify();
    

    One of the requirements is: The customer's credit limit must always be rounded to the nearest 10,000.

  32. Add three global labels to the page extension with the following text:

    • Confirmation message

    • Information about the rounded credit limit

    • Information about an up-to-date credit limit

    Name ConstValue
    AreYouSureQst Are you sure that you want to set the %1 to %2?
    CreditLimitRoundedTxt The credit limit was rounded to %1 to comply with company policies.
    CreditLimitUpToDateTxt The credit limit is up to date.
  33. Add two local decimal variables to the CallUpdateCreditLimit function and call them CreditLimitCalculated and CreditLimitActual, both of type Decimal.

  34. Add the following code to the CallUpdateCreditLimit function:

    CreditLimitCalculated := Rec.CalculateCreditLimit();
    if CreditLimitCalculated = Rec."Credit Limit (LCY)" then begin
        Message(CreditLimitUpToDateTxt);
        exit;
    end;
    
    if GuiAllowed() then
        if not Confirm(AreYouSureQst, false, FieldCaption("Credit Limit (LCY)"),CreditLimitCalculated) then
            exit;
    
    CreditLimitActual := CreditLimitCalculated;
    Rec.UpdateCreditLimit(CreditLimitActual);
    if CreditLimitActual <> CreditLimitCalculated then
        Message(CreditLimitROundedTxt, CreditLimitActual);
    

    If the new credit limit doesn't differ from the old one, the application must send notification to the user.

  35. The Customer table extension now resembles the following code block:

    tableextension 50400 Customer extends Customer
    {
        procedure UpdateCreditLimit(var NewCreditLimit: Decimal)
        begin
            NewCreditLimit := Round(NewCreditLimit, 10000);
            Rec.Validate("Credit Limit (LCY)", NewCreditLimit);
            Rec.Modify();
        end;
    
        procedure CalculateCreditLimit(): Decimal
        var
            Customer: Record Customer;
        begin
            Customer := Rec;
            Customer.SetRange("Date Filter", CalcDate('<-12M>', WorkDate()), WorkDate());
            Customer.CalcFields("Sales (LCY)", "Balance (LCY)");
            exit(Round(Customer."Sales (LCY)" * 0.5));
        end;
    }
    
  36. The CustomerCard page extension now resembles the following code block:

    pageextension 50400 CustomerCard extends "Customer Card"
    {
        layout
        {
            // Add changes to page layout here
        }
    
        actions
        {
            // Add changes to page actions here
            addafter("F&unctions")
            {
                action(UpdateCreditLimit)
                {
                    ApplicationArea = All;
                    Caption = 'Update Credit Limit';
                    Image = CalculateCost;
                    ToolTip = 'Update Credit Limit';
    
                    trigger OnAction()
                    begin
                        CallUpdateCreditLimit();
                    end;
                }
            }
        }
        var
            AreYouSureQst: Label 'Are you sure that you want to set the %1 to %2?',  Comment = '%1 is Credit Limit caption and %2 is the new Credit Limit value.' ;
            CreditLimitRoundedTxt: Label 'The credit limit was rounded to %1 to comply with company policies.',  Comment = '%1 is new Credit Limit value';
            CreditLimitUpToDateTxt: Label 'The credit limit is up to date.';
    
        local procedure CallUpdateCreditLimit()
        var
            CreditLimitCalculated, CreditLimitActual : Decimal;
        begin
            CreditLimitCalculated := Rec.CalculateCreditLimit();
            if CreditLimitCalculated = Rec."Credit Limit (LCY)" then begin
                Message(CreditLimitUpToDateTxt);
                exit;
            end;
    
            if GuiAllowed() then
                if not Confirm(AreYouSureQst, false, Rec.FieldCaption("Credit Limit (LCY)"), CreditLimitCalculated) then
                    exit;
    
            CreditLimitActual := CreditLimitCalculated;
            Rec.UpdateCreditLimit(CreditLimitActual);
            if CreditLimitActual <> CreditLimitCalculated then
                Message(CreditLimitROundedTxt, CreditLimitActual);
        end;
    }
    

    If the customer has no sales history over the past 12 months, the credit limit must be reset to zero.

  37. Open the launch.json file in the .vscode folder. Set the startupObjectId setting to 22 and the startupObjectType to Page.

  38. Publish your extension to the sandbox. Select View > Command Palette... (Ctrl+Shift+P).

  39. Enter AL: Publish in the search box (or press the F5 key) and then select the command from the list.

  40. Verify that the Microsoft Dynamics 365 Business Central application launches and that the Customer List page appears.

  41. Open a random customer card. In the Customer Card page, find the Update Credit Limit action, in the actions menu, after Functions.

  42. Test the action.