Skip to content

Extending FreshFocus Logo

Overview

This article assumes familiarity with the methods and requirements for developing extensions in Microsoft Dynamics 365 Business Central.

The nature of produce means there are many unique characteristics needed to achieve compliance and the required business process, and these may vary from market to market. FreshFocus has been designed with extensibility in mind.

This article explains how FreshFocus has exposed integration events and extendable properties.

Setting up your AL Development environment

You need to set up a Business Central development environment in order to create extensions for FreshFocus.

You also need access to a Microsoft Dynamics 365 Business Central environment. We recommend using an existing test or development (sandbox) environment or create a new trial sandbox.

Info

Trials and Previews

Choosing Development Sandbox Environment

Are you new to AL development?

We highly recommend this article Getting Started With AL which will guide you through these required steps.

  1. Sign up for a Dynamics 365 Business Central sandbox.
  2. Download Visual Studio Code.
  3. Download the AL Language extension.

Extending the Solution

There are many ways a partner may wish to extend FreshFocus. We have provided the reference information below to assist developers to make best use of the business logic that FreshFocus employs.

Table Reference

FreshFocus adds tables and also extends tables in the Business Central Environment where it is installed.

Event Subscribers

FreshFocus provides many events that allow other extensions to utilise functions and perform custom calculations.

Once of the challenges of development is knowing where a specific event is being called. For this we suggest developers use the Event Recorder in Business Central.

You can record the events that are published and raised while performing the actions of your scenario. Then you can choose the Get AL Snippet on the selected event to get the event subscription code in AL. You can then use the AL snippet code in Codeunits to subscribe to those events.

Example - Adding a New Produce Posting Rule Criteria

In this example, we wish to introduce an additional produce posting rule parameter/criteria that allows us to define rules and charges to apply when a sales shipment occurs based on the Sell-to customer No. and Ship-to Code of the posted document.

We need to be able to add the required field to the rules table, and then have the rules engine select the rule, and post produce value entries accordingly. From there, the routines for calculation and produce invoicing rely on the posted entries, and treatments.

Warning

We assume that connecting to a development instance, downloading symbols, and creating an app dependency to FreshFocus has already been performed.

Table Extension

The relevant table to store the new criteria is the Produce Posting Rule table, so we create a table extension object in vsCode.

Table Extension
    tableextension 50100 ProducePostingRule extends "DLGFF Produce Posting Rule"
    {
    fields
        {
            field(50100; "Sell-to Customer No."; Code[20])
            {
                Caption = 'Sell-to Customer No.';
                DataClassification = CustomerContent;
                TableRelation = "Customer"."No.";
            }
            field(50101; "Ship-to Code"; Code[20])
            {
                Caption = 'Ship-to Code';
                DataClassification = CustomerContent;
                TableRelation = "Ship-to Address".code where("Customer No." = field("Sell-to Customer No."));
            }
        }
    }

Page Extension

With the additional fields added, we can add them to the Produce Posting Rules page worksheet, and we also want to control that the fields can be used only when the Movement Detail type is 'Sales Shipment'.

Page Extension
    pageextension 50100 ProducePostingRule extends "DLGFF Produce Posting Rules"
    {
        layout
        {
            addafter("Trade Account") 
            {
                field("Sell-to Customer No.";Rec."Sell-to Customer No.")
                {
                    ApplicationArea = All;
                    enabled = (Rec."Movement Detail" = Rec."Movement Detail"::SalesShipment);
                }
                field("Ship-to Code";Rec."Ship-to Code")
                {
                    ApplicationArea = All;
                    enabled = (Rec."Movement Detail" = Rec."Movement Detail"::SalesShipment ) AND (Rec."Sell-to Customer No." <> '');
                }
            }   
        }
    }

We can build and test this in our FreshFocus development environment.

ExtendingFreshFocus

Codeunit

Create a new codeunit for the purpose of subscribing (and we are not considering manual binding of the subscription). Then, to integrate the new rule criteria to the system, we locate and subscribe to an event.

Using the AL Explorer to find events

Within vsCode you can use the command pallette and search for "AL: Explorer" or use the Ctrl+Shift+F12 shortcut combination.

ExtendingFreshFocus

In the image below we have selected 'Events' and filtered by module for the extension we want 'FreshFocus', and entered a search for 'produce posting rule' to see all events that might involve this table.

ExtendingFreshFocus

In this case, we want the rules engine to include our criteria when checking for valid posting rules as it runs across the tracking for a produce agreement.

We can see the 'OnAfterGetProducePostingRules' event is available, and we can then use the Subscribe action to generate a code snippet that we can paste into our codeunit.

Codeunit
1
2
3
4
5
6
7
    codeunit 50100 MySubscribers
    {
        [EventSubscriber(ObjectType::Codeunit, Codeunit::"DLGFF Produce Agreement Mgt.", 'OnAfterGetProducePostingRules', '', false, false)]
        local procedure OnAfterGetProducePostingRules(ProduceTrackingEntry: Record "DLGFF Produce Tracking Entry"; LotNoInformation: Record "Lot No. Information"; var ProducePostingRule: Record "DLGFF Produce Posting Rule");
        begin
        end;
    }

Add the event to our codeunit

Now we have the subscriber event and can see it will run with a tracking entry, lot information record and produce posting rule.

We can use the tracking entry to find the source document, obtain the 'sell-to customer' and 'ship-to' if specified and handle how we want the rules engine to respond.

We can create a variable SalesShipmentHdr to the Sales Shipment Header, and perform some checks such as; if the tracking entry is not a shipment, then there is no need to assess the rule at all, and we can directly GET the related information from the Document No. of the tracking entry.

Then we simply set filters for the Sell-to Customer No., and Ship-to Code .

In both cases, we set a filter for the criteria that is specified and also blank. This ensures that if the rule does not include the criteria, then it is still valid (ie blank means all).

The finished codeunit is below, and you can deploy the extension to your development environment and test.

Codeunit
    codeunit 50100 MySubscribers
    {
        [EventSubscriber(ObjectType::Codeunit, Codeunit::"DLGFF Produce Agreement Mgt.", 'OnAfterGetProducePostingRules', '', false, false)]
        local procedure OnAfterGetProducePostingRules(ProduceTrackingEntry: Record "DLGFF Produce Tracking Entry"; LotNoInformation: Record "Lot No. Information"; var ProducePostingRule: Record "DLGFF Produce Posting Rule");
        var
            SalesShipmentHdr: Record "Sales Shipment Header";
        begin

            IF ProduceTrackingEntry."Document Type" <> ProduceTrackingEntry."Document Type"::"Sales Shipment" Then
                Exit;   // test that the tracking entry is a sales shipment

            IF NOT SalesShipmentHdr.GET(ProduceTrackingEntry."Document No.") Then
                Exit;   // test that the posted document is found

            //Set filters on the produce posting rules if the customer or ship-to has been specified
            ProducePostingRule.SETFILTER("Sell-to Customer No.", '%1|%2', SalesShipmentHdr."Sell-to Customer No.", '');
            ProducePostingRule.SETFILTER("Ship-to Code", '%1|%2', SalesShipmentHdr."Ship-to Code", '');
        end;
    }

Testing

We have created some Produce Posting Rules that will invoke a 'LOGISTICS' trade account posting on shipment with different rates for different customers.

ExtendingFreshFocus

We have activated the rules and allowed them to apply retrospectively, we can then use the Produce Value Journal to calculate and recall any charges that apply.

ExtendingFreshFocus

In the above simple example, we can see the different charges that are to apply a single produce agreement, and the rates that are to be applied. The source code for this can be downloaded using the button below.

Sample Extension

See Also

For more information about FreshFocus refer to these links

Frequently Asked Questions

Release Notes

Planned Features