Codeunit 312 Cust-Check Cr. Limit

App
Base Application
Namespace
Microsoft.Sales.Customer
Versions
17-28

Procedures, 19Events, 17Obsolete, 9

Versions171819202122232425262728

Source29

Source in 29

src/Layers/W1/BaseApp/Sales/Customer/CustCheckCrLimit.Codeunit.al414 lines, Copyright (c) Microsoft Corporation. MIT

// ------------------------------------------------------------------------------------------------
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License. See License.txt in the project root for license information.
// ------------------------------------------------------------------------------------------------
namespace Microsoft.Sales.Customer;

using Microsoft.Finance.GeneralLedger.Journal;
using Microsoft.Sales.Document;
using Microsoft.Utilities;
using System.Environment.Configuration;

/// <summary>
/// Checks customer credit limits and overdue balances, sending notifications when thresholds are exceeded.
/// </summary>
codeunit 312 "Cust-Check Cr. Limit"
{
    Permissions = TableData "My Notifications" = rimd;

    trigger OnRun()
    begin
    end;

    var
        InstructionMgt: Codeunit "Instruction Mgt.";
        NotificationLifecycleMgt: Codeunit "Notification Lifecycle Mgt.";
        CustCheckCreditLimit: Page "Check Credit Limit";
        InstructionTypeTxt: Label 'Check Cr. Limit';
        GetDetailsTxt: Label 'Show details';
        CreditLimitNotificationMsg: Label 'The customer''s credit limit has been exceeded.';
        CreditLimitNotificationDescriptionTxt: Label 'Show warning when a sales document will exceed the customer''s credit limit.';
        OverdueBalanceNotificationMsg: Label 'This customer has an overdue balance.';
        OverdueBalanceNotificationDescriptionTxt: Label 'Show warning when a sales document is for a customer with an overdue balance.';

    /// <summary>
    /// Checks customer credit limit for a general journal line and sends notification if exceeded.
    /// </summary>
    /// <param name="GenJnlLine">Specifies the general journal line to check credit limit for.</param>
    procedure GenJnlLineCheck(GenJnlLine: Record "Gen. Journal Line")
    var
        SalesHeader: Record "Sales Header";
        AdditionalContextId: Guid;
        IsHandled: Boolean;
    begin
        IsHandled := false;
        OnBeforeGenJnlLineCheck(GenJnlLine, IsHandled);
        if IsHandled then
            exit;

        if not GuiAllowed then
            exit;

        if not SalesHeader.Get(GenJnlLine."Document Type", GenJnlLine."Document No.") then
            SalesHeader.Init();
        OnNewCheckRemoveCustomerNotifications(SalesHeader.RecordId, true);

        if CustCheckCreditLimit.GenJnlLineShowWarningAndGetCause(GenJnlLine, AdditionalContextId) then
            CreateAndSendNotification(SalesHeader.RecordId, AdditionalContextId, '');
    end;

    /// <summary>
    /// Checks customer credit limit for a sales header and sends notification if exceeded.
    /// </summary>
    /// <param name="SalesHeader">Specifies the sales header to check credit limit for.</param>
    /// <returns>True if the credit limit is exceeded, otherwise false.</returns>
    procedure SalesHeaderCheck(var SalesHeader: Record "Sales Header") CreditLimitExceeded: Boolean
    var
        AdditionalContextId: Guid;
        IsHandled: Boolean;
    begin
        IsHandled := false;
        OnBeforeSalesHeaderCheck(SalesHeader, IsHandled, CreditLimitExceeded);
        if IsHandled then
            exit(CreditLimitExceeded);

        if GuiAllowed then begin
            OnNewCheckRemoveCustomerNotifications(SalesHeader.RecordId, true);

            OnSalesHeaderCheckOnBeforeShowWarning(CustCheckCreditLimit);
            if not CustCheckCreditLimit.SalesHeaderShowWarningAndGetCause(SalesHeader, AdditionalContextId) then
                SalesHeader.CustomerCreditLimitNotExceeded()
            else begin
                CreditLimitExceeded := true;

                if InstructionMgt.IsEnabled(GetInstructionType(Format(SalesHeader."Document Type"), SalesHeader."No.")) then
                    CreateAndSendNotification(SalesHeader.RecordId, AdditionalContextId, '');

                SalesHeader.CustomerCreditLimitExceeded(CustCheckCreditLimit.GetNotificationId());
            end;
        end;
    end;

    /// <summary>
    /// Checks customer credit limit for a sales line and sends notification if exceeded.
    /// </summary>
    /// <param name="SalesLine">Specifies the sales line to check credit limit for.</param>
    /// <returns>True if the credit limit is exceeded, otherwise false.</returns>
    procedure SalesLineCheck(SalesLine: Record "Sales Line") CreditLimitExceeded: Boolean
    var
        SalesHeader: Record "Sales Header";
        AdditionalContextId: Guid;
        IsHandled: Boolean;
    begin
        IsHandled := false;
        OnBeforeSalesLineCheck(SalesLine, IsHandled, CreditLimitExceeded);
        if IsHandled then
            exit(CreditLimitExceeded);

        if not SalesHeader.Get(SalesLine."Document Type", SalesLine."Document No.") then
            SalesHeader.Init();

        if GuiAllowed then
            OnNewCheckRemoveCustomerNotifications(SalesHeader.RecordId, false);

        OnSalesLineCheckOnBeforeShowWarning(CustCheckCreditLimit);
        if not CustCheckCreditLimit.SalesLineShowWarningAndGetCause(SalesLine, AdditionalContextId) then
            SalesHeader.CustomerCreditLimitNotExceeded()
        else begin
            CreditLimitExceeded := true;

            if GuiAllowed then
                if InstructionMgt.IsEnabled(GetInstructionType(Format(SalesLine."Document Type"), SalesLine."Document No.")) then
                    CreateAndSendNotification(SalesHeader.RecordId, AdditionalContextId, '');

            SalesHeader.CustomerCreditLimitExceeded(CustCheckCreditLimit.GetNotificationId());
        end;
    end;




    /// <summary>
    /// Generates an instruction type code for credit limit checking based on document type and number.
    /// </summary>
    /// <param name="DocumentType">Specifies the document type code.</param>
    /// <param name="DocumentNumber">Specifies the document number.</param>
    /// <returns>The instruction type code for the credit limit check.</returns>
    procedure GetInstructionType(DocumentType: Code[30]; DocumentNumber: Code[20]): Code[50]
    begin
        exit(CopyStr(StrSubstNo('%1 %2 %3', DocumentType, DocumentNumber, InstructionTypeTxt), 1, 50));
    end;

    /// <summary>
    /// Checks customer credit limit when converting a blanket sales order to a sales order.
    /// </summary>
    /// <param name="SalesOrderHeader">Specifies the sales order header created from the blanket order.</param>
    procedure BlanketSalesOrderToOrderCheck(SalesOrderHeader: Record "Sales Header")
    var
        AdditionalContextId: Guid;
        IsHandled: Boolean;
    begin
        IsHandled := false;
        OnBeforeBlanketSalesOrderToOrderCheck(SalesOrderHeader, IsHandled);
        if IsHandled then
            exit;

        if not GuiAllowed then
            exit;

        OnNewCheckRemoveCustomerNotifications(SalesOrderHeader.RecordId, true);

        OnBlanketSalesOrderToOrderCheckOnBeforeSalesHeaderShowWarning(CustCheckCreditLimit);
        if CustCheckCreditLimit.SalesHeaderShowWarningAndGetCause(SalesOrderHeader, AdditionalContextId) then
            CreateAndSendNotification(SalesOrderHeader.RecordId, AdditionalContextId, '');
    end;

    /// <summary>
    /// Displays the credit limit notification details page with information from the notification.
    /// </summary>
    /// <param name="CreditLimitNotification">Specifies the notification containing credit limit details.</param>
    procedure ShowNotificationDetails(CreditLimitNotification: Notification)
    var
        CreditLimitNotificationPage: Page "Credit Limit Notification";
    begin
        CreditLimitNotificationPage.SetHeading(CreditLimitNotification.Message);
        CreditLimitNotificationPage.InitializeFromNotificationVar(CreditLimitNotification);
        CreditLimitNotificationPage.RunModal();
    end;

    local procedure CreateAndSendNotification(RecordId: RecordID; AdditionalContextId: Guid; Heading: Text[250])
    var
        NotificationToSend: Notification;
        IsHandled: Boolean;
    begin
        IsHandled := false;
        OnBeforeCreateAndSendNotification(RecordId, AdditionalContextId, Heading, NotificationToSend, IsHandled, CustCheckCreditLimit);
        if IsHandled then
            exit;

        if AdditionalContextId = GetBothNotificationsId() then begin
            CreateAndSendNotification(RecordId, GetCreditLimitNotificationId(), CustCheckCreditLimit.GetHeading());
            CreateAndSendNotification(RecordId, GetOverdueBalanceNotificationId(), CustCheckCreditLimit.GetSecondHeading());
            exit;
        end;

        if Heading = '' then
            Heading := CustCheckCreditLimit.GetHeading();

        case Heading of
            CreditLimitNotificationMsg:
                NotificationToSend.Id(GetCreditLimitNotificationId());
            OverdueBalanceNotificationMsg:
                NotificationToSend.Id(GetOverdueBalanceNotificationId());
            else
                NotificationToSend.Id(CreateGuid());
        end;

        NotificationToSend.Message(Heading);
        NotificationToSend.Scope(NOTIFICATIONSCOPE::LocalScope);
        NotificationToSend.AddAction(GetDetailsTxt, CODEUNIT::"Cust-Check Cr. Limit", 'ShowNotificationDetails');
        CustCheckCreditLimit.PopulateDataOnNotification(NotificationToSend);
        NotificationLifecycleMgt.SendNotificationWithAdditionalContext(NotificationToSend, RecordId, AdditionalContextId);
    end;

    /// <summary>
    /// Retrieves the unique identifier for the credit limit notification.
    /// </summary>
    /// <returns>The GUID identifier for the credit limit notification.</returns>
    procedure GetCreditLimitNotificationId(): Guid
    begin
        exit('C80FEEDA-802C-4879-B826-34A10FB77087');
    end;

    /// <summary>
    /// Retrieves the unique identifier for the overdue balance notification.
    /// </summary>
    /// <returns>The GUID identifier for the overdue balance notification.</returns>
    procedure GetOverdueBalanceNotificationId(): Guid
    begin
        exit('EC8348CB-07C1-499A-9B70-B3B081A33C99');
    end;

    /// <summary>
    /// Retrieves the unique identifier for combined credit limit and overdue balance notifications.
    /// </summary>
    /// <returns>The GUID identifier for both notifications combined.</returns>
    procedure GetBothNotificationsId(): Guid
    begin
        exit('EC8348CB-07C1-499A-9B70-B3B081A33D00');
    end;

    /// <summary>
    /// Checks if the credit limit notification is enabled for the specified customer.
    /// </summary>
    /// <param name="Customer">Specifies the customer record to check notification settings for.</param>
    /// <returns>True if the credit limit notification is enabled, otherwise false.</returns>
    procedure IsCreditLimitNotificationEnabled(Customer: Record Customer): Boolean
    var
        MyNotifications: Record "My Notifications";
    begin
        exit(MyNotifications.IsEnabledForRecord(GetCreditLimitNotificationId(), Customer));
    end;

    /// <summary>
    /// Checks if the overdue balance notification is enabled for the specified customer.
    /// </summary>
    /// <param name="Customer">Specifies the customer record to check notification settings for.</param>
    /// <returns>True if the overdue balance notification is enabled, otherwise false.</returns>
    procedure IsOverdueBalanceNotificationEnabled(Customer: Record Customer): Boolean
    var
        MyNotifications: Record "My Notifications";
    begin
        exit(MyNotifications.IsEnabledForRecord(GetOverdueBalanceNotificationId(), Customer));
    end;

    [EventSubscriber(ObjectType::Page, Page::"My Notifications", 'OnInitializingNotificationWithDefaultState', '', false, false)]
    local procedure OnInitializingNotificationWithDefaultState()
    var
        MyNotifications: Record "My Notifications";
    begin
        MyNotifications.InsertDefaultWithTableNum(GetCreditLimitNotificationId(),
          CreditLimitNotificationMsg,
          CreditLimitNotificationDescriptionTxt,
          DATABASE::Customer);
        MyNotifications.InsertDefaultWithTableNum(GetOverdueBalanceNotificationId(),
          OverdueBalanceNotificationMsg,
          OverdueBalanceNotificationDescriptionTxt,
          DATABASE::Customer);
    end;

    /// <summary>
    /// Raises an event to remove existing customer credit and overdue notifications before sending new ones.
    /// </summary>
    /// <param name="RecId">Specifies the record ID associated with the notifications to remove.</param>
    /// <param name="RecallCreditOverdueNotif">Specifies whether to recall credit and overdue notifications.</param>
    [IntegrationEvent(false, false)]
    procedure OnNewCheckRemoveCustomerNotifications(RecId: RecordID; RecallCreditOverdueNotif: Boolean)
    begin
    end;

    /// <summary>
    /// Retrieves the message text displayed for credit limit notifications.
    /// </summary>
    /// <returns>The credit limit notification message text.</returns>
    procedure GetCreditLimitNotificationMsg(): Text
    begin
        exit(CreditLimitNotificationMsg);
    end;

    /// <summary>
    /// Retrieves the message text displayed for overdue balance notifications.
    /// </summary>
    /// <returns>The overdue balance notification message text.</returns>
    procedure GetOverdueBalanceNotificationMsg(): Text
    begin
        exit(OverdueBalanceNotificationMsg);
    end;

    /// <summary>
    /// Raised before checking the credit limit for a general journal line.
    /// </summary>
    /// <param name="GenJnlLine">The general journal line to check.</param>
    /// <param name="IsHandled">Set to true to skip the default credit limit check.</param>
    [IntegrationEvent(false, false)]
    local procedure OnBeforeGenJnlLineCheck(GenJnlLine: Record "Gen. Journal Line"; var IsHandled: Boolean)
    begin
    end;

    /// <summary>
    /// Raised before checking the credit limit for a sales header.
    /// </summary>
    /// <param name="SalesHeader">The sales header to check.</param>
    /// <param name="IsHandled">Set to true to skip the default credit limit check.</param>
    /// <param name="CreditLimitExceeded">Returns whether the credit limit is exceeded.</param>
    [IntegrationEvent(false, false)]
    local procedure OnBeforeSalesHeaderCheck(var SalesHeader: Record "Sales Header"; var IsHandled: Boolean; var CreditLimitExceeded: Boolean);
    begin
    end;



    /// <summary>
    /// Raised before creating and sending a credit limit notification.
    /// </summary>
    /// <param name="RecordId">The record ID associated with the notification.</param>
    /// <param name="AdditionalContextId">The additional context identifier for the notification.</param>
    /// <param name="Heading">The heading text for the notification.</param>
    /// <param name="NotificationToSend">The notification object to send.</param>
    /// <param name="IsHandled">Set to true to skip the default notification creation.</param>
    /// <param name="CustCheckCreditLimit">The credit limit check page for retrieving notification data.</param>
    [IntegrationEvent(true, false)]
    local procedure OnBeforeCreateAndSendNotification(RecordId: RecordID; AdditionalContextId: Guid; Heading: Text[250]; NotificationToSend: Notification; var IsHandled: Boolean; var CustCheckCreditLimit: Page "Check Credit Limit");
    begin
    end;

    /// <summary>
    /// Raised before checking the credit limit for a sales line.
    /// </summary>
    /// <param name="SalesLine">The sales line to check.</param>
    /// <param name="IsHandled">Set to true to skip the default credit limit check.</param>
    /// <param name="CreditLimitExceeded">Returns whether the credit limit is exceeded.</param>
    [IntegrationEvent(false, false)]
    local procedure OnBeforeSalesLineCheck(var SalesLine: Record "Sales Line"; var IsHandled: Boolean; var CreditLimitExceeded: Boolean)
    begin
    end;

    /// <summary>
    /// Raised before showing the credit limit warning for a sales header.
    /// </summary>
    /// <param name="CustCheckCreditLimit">The credit limit check page to configure.</param>
    [IntegrationEvent(false, false)]
    local procedure OnSalesHeaderCheckOnBeforeShowWarning(var CustCheckCreditLimit: Page "Check Credit Limit")
    begin
    end;

    /// <summary>
    /// Raised before showing the credit limit warning for a sales line.
    /// </summary>
    /// <param name="CustCheckCreditLimit">The credit limit check page to configure.</param>
    [IntegrationEvent(false, false)]
    local procedure OnSalesLineCheckOnBeforeShowWarning(var CustCheckCreditLimit: Page "Check Credit Limit")
    begin
    end;

#if not CLEAN27
    [Obsolete('Moved to codeunit Serv. Check Credit Limit', '27.0')]
    [IntegrationEvent(false, false)]
    local procedure OnServiceHeaderCheckOnBeforeShowWarning(var CustCheckCreditLimit: Page "Check Credit Limit")
    begin
    end;

    [Obsolete('Moved to codeunit Serv. Check Credit Limit', '27.0')]
    [IntegrationEvent(false, false)]
    local procedure OnServiceLineCheckOnBeforeShowWarning(var CustCheckCreditLimit: Page "Check Credit Limit")
    begin
    end;

    [Obsolete('Moved to codeunit Serv. Check Credit Limit', '27.0')]
    [IntegrationEvent(false, false)]
    local procedure OnServiceContractHeaderCheckOnBeforeShowWarning(var CustCheckCreditLimit: Page "Check Credit Limit")
    begin
    end;
#endif

    /// <summary>
    /// Raised before showing the credit limit warning when converting a blanket order to a sales order.
    /// </summary>
    /// <param name="CustCheckCreditLimit">The credit limit check page to configure.</param>
    [IntegrationEvent(false, false)]
    local procedure OnBlanketSalesOrderToOrderCheckOnBeforeSalesHeaderShowWarning(var CustCheckCreditLimit: Page "Check Credit Limit")
    begin
    end;

    /// <summary>
    /// Raised before checking the credit limit when converting a blanket order to a sales order.
    /// </summary>
    /// <param name="SalesHeader">The sales header created from the blanket order.</param>
    /// <param name="IsHandled">Set to true to skip the default credit limit check.</param>
    [IntegrationEvent(false, false)]
    local procedure OnBeforeBlanketSalesOrderToOrderCheck(var SalesHeader: Record "Sales Header"; var IsHandled: Boolean)
    begin
    end;

}