Business Central Approval Out of Office Check 🌴📧

This is a FAQ when the topic of approvals comes up with prospects or customers. Solving this conundrum requires you to determine where you will get a substitute or replacement approver from. In my case I have used the approval user setup in BC. To achieve this a custom api page needs to be generated. If you can’t do that then check out appsource for apps which help. At the time of writing the simple object designer is a good one. The process for building the flow can be seen in the image gallery below. The first two steps are just the regular BC workflow approval trigger and get record action. I have only done one out of office mailbox check but you can add more with the format I utilise. If you need an overview on the basics of using Power Automate for approvals check out this post: https://joshanglesea.wordpress.com/2022/04/29/business-central-customer-approval/

There are a few expressions that get used and I’ve added notes on all of the images of what expression is being used at that point:

I’ve exported the flow and you can grab it for import instead of building from scratch. The JSON format is available too if you use Azure logic apps instead of Power Automate: https://github.com/JAng13sea/Blogs/tree/master/Out%20of%20Office%20Approver%20Check

Business Central Horizontal page tabs ➡️

Back in the days when BC was NAV this was your typical card/document page:

Take note of the horizontal tabs as opposed to how BC currently does things with vertical tabs. It worth considering that this type of design can be seen in other ERP systems and it’s an efficient way of moving through details without scrolling. The switch over itself happened way before BC was even a idea:

This is where the history lesson stops and the new wave comes in. I’ve been dealing with a prospective client who uses an old version of AX and the switch to vertical tabs lacked some appeal. My initial thought of course was PowerApps but I wanted to challenge myself with BC page design. This blog is to show a concept which I think is nice but maybe on the novelty side for some. This is how it looks and functions on a card page for items:

You could argue that page actions could have been used but I felt this didn’t make it completely clear which “tab” the user is looking at if they have to marry the page part caption and page action caption together.

The main thing to share here is the code so please check it out if you would like to try this on a page you think this fits. So which is faster? Horizontal tabs or BC Fast tabs? who wins the fight? You decide! 😏

page 50204 "Horizontal Tab Item Card"
{
    Caption = 'Item Query';
    PageType = Card;
    SourceTable = Item;
    Editable = true;
    InsertAllowed = false;
    DeleteAllowed = false;

    layout
    {
        area(content)
        {
            group(ItemTabs)
            {
                Caption = '';
                grid(buttonrow)
                {
                    GridLayout = Rows;
                    field(GeneralTab; General)
                    {
                        ApplicationArea = All;
                        ShowCaption = false;
                        DrillDown = true;
                        StyleExpr = GeneralStyleText;
                        trigger OnDrillDown()
                        begin
                            VisOption := VisOption::General;
                            ChangeStyleExpr(VisOption);
                            CurrPage.Update(false);
                        end;
                    }
                    field(OnHand; OnHand)
                    {
                        ApplicationArea = All;
                        ShowCaption = false;
                        DrillDown = true;
                        StyleExpr = OnHandStyleText;
                        trigger OnDrillDown()
                        begin
                            VisOption := VisOption::OnHand;
                            ChangeStyleExpr(VisOption);
                            CurrPage.Update(false);
                        end;
                    }
                    field(SaleOrd; SaleOrd)
                    {
                        ApplicationArea = All;
                        ShowCaption = false;
                        DrillDown = true;
                        StyleExpr = SaleOrdStyleText;
                        trigger OnDrillDown()
                        var
                            SL: Record "Sales Line";
                        begin
                            VisOption := VisOption::SaleOrd;
                            ChangeStyleExpr(VisOption);
                            CurrPage.Update(false);
                        end;
                    }
                    field(PurchOrd; PurchOrd)
                    {
                        ApplicationArea = All;
                        ShowCaption = false;
                        DrillDown = true;
                        StyleExpr = PurchOrdStyleText;
                        trigger OnDrillDown()
                        var
                            PL: Record "Purchase Line";
                        begin
                            VisOption := VisOption::PurchOrd;
                            ChangeStyleExpr(VisOption);
                            CurrPage.Update(false);
                        end;
                    }
                    field(Transac; Transac)
                    {
                        ApplicationArea = All;
                        ShowCaption = false;
                        DrillDown = true;
                        StyleExpr = TransacStyleText;
                        trigger OnDrillDown()
                        var
                            ILE: Record "Item Ledger Entry";
                        begin
                            VisOption := VisOption::Transac;
                            ChangeStyleExpr(VisOption);
                            CurrPage.Update(false);
                        end;
                    }
                    field(Website; Website)
                    {
                        ApplicationArea = All;
                        ShowCaption = false;
                        DrillDown = true;
                        StyleExpr = WebsiteStyleText;
                        trigger OnDrillDown()
                        begin
                            VisOption := VisOption::Website;
                            ChangeStyleExpr(VisOption);
                            CurrPage.Update(false);
                        end;
                    }
                    field(Stats; Stats)
                    {
                        ApplicationArea = All;
                        ShowCaption = false;
                        DrillDown = true;
                        StyleExpr = StatsStyleText;
                        trigger OnDrillDown()
                        begin
                            VisOption := VisOption::Stats;
                            ChangeStyleExpr(VisOption);
                            CurrPage.Update(false);
                        end;
                    }
                }
            }

            part(AXItemCard; "Item Card General")
            {
                Visible = VisOption = VisOption::General;
                ApplicationArea = All;
                SubPageLink = "No." = FIELD("No."),
                              "Date Filter" = FIELD("Date Filter"),
                              "Global Dimension 1 Filter" = FIELD("Global Dimension 1 Filter"),
                              "Global Dimension 2 Filter" = FIELD("Global Dimension 2 Filter"),
                              "Location Filter" = FIELD("Location Filter"),
                              "Drop Shipment Filter" = FIELD("Drop Shipment Filter"),
                              "Bin Filter" = FIELD("Bin Filter"),
                              "Variant Filter" = FIELD("Variant Filter"),
                              "Lot No. Filter" = FIELD("Lot No. Filter"),
                              "Serial No. Filter" = FIELD("Serial No. Filter");
            }

            part(SalesOrdsPart; "Sales Orders List Part")
            {
                Visible = VisOption = VisOption::SaleOrd;
                ApplicationArea = All;
                SubPageLink = "No." = FIELD("No.");
            }
            part(PurchOrdsPart; "Purchase Order Line ListPart")
            {
                Visible = VisOption = VisOption::PurchOrd;
                ApplicationArea = All;
                SubPageLink = "No." = FIELD("No.");
            }
            part(Transactions; ItemTransactionsCardPart)
            {
                Visible = VisOption = VisOption::Transac;
                ApplicationArea = All;
                SubPageLink = "Item No." = FIELD("No.");
            }
            part(SKuList; "SKU List")
            {
                Visible = VisOption = VisOption::OnHand;
                ApplicationArea = All;
                SubPageLink = "Item No." = field("No.");
            }
            part(picture; "Item Picture")
            {
                Visible = VisOption = VisOption::Picture;
                ApplicationArea = All;
                SubPageLink = "No." = field("No.");
            }
        }
    }

    trigger OnOpenPage()
    begin
        VisOption := VisOption::General;
    end;

    procedure ChangeStyleExpr(VisOption: Option General,OnHand,SaleOrd,PurchOrd,Transac,Picture,Stats): Text[50]
    Begin
        ResetTabs();
        case VisOption of
            VisOption::General:
                GeneralStyleText := 'StrongAccent';
            VisOption::OnHand:
                OnHandStyleText := 'StrongAccent';
            VisOption::PurchOrd:
                PurchOrdStyleText := 'StrongAccent';
            VisOption::SaleOrd:
                SaleOrdStyleText := 'StrongAccent';
            VisOption::Stats:
                StatsStyleText := 'StrongAccent';
            VisOption::Transac:
                TransacStyleText := 'StrongAccent';
            VisOption::Website:
                WebsiteStyleText := 'StrongAccent';
        end;
    End;

    local procedure ResetTabs();
    begin
        GeneralStyleText := 'Standard';
        OnHandStyleText := 'Standard';
        SaleOrdStyleText := 'Standard';
        PurchOrdStyleText := 'Standard';
        TransacStyleText := 'Standard';
        WebsiteStyleText := 'Standard';
        StatsStyleText := 'Standard';
    end;


    var
        General: Label 'General';
        OnHand: Label 'On Hand';
        PurchOrd: Label 'Purchase Orders';
        SaleOrd: Label 'Sales Orders';
        Transac: Label 'Transactions';
        Website: Label 'Picture';
        Stats: Label 'Statistics';
        [InDataSet]
        VisOption: Option General,OnHand,SaleOrd,PurchOrd,Transac,Picture,Stats;
        [InDataSet]
        GeneralStyleText: Text;
        [InDataSet]
        OnHandStyleText: Text;
        [InDataSet]
        PurchOrdStyleText: Text;
        [InDataSet]
        SaleOrdStyleText: Text;
        [InDataSet]
        TransacStyleText: Text;
        [InDataSet]
        WebsiteStyleText: Text;
        [InDataSet]
        StatsStyleText: Text;
}