Skip to content

[Event Request] Codeunit 5900 "ServOrderManagement".InsertServCost #30421

Description

@fridrichovsky

Why do you need this change?

Problem statement:
The logic change introduces an extension point for travel fee determination. The new publisher allows extensions to override the standard Service Zone Code-based lookup logic by handling the process before the Service Zone Code validation and cost search. If handled, a custom logic can be implemented to determine the appropriate travel cost record. After finding the relevant cost record, a new service document line with type Cost is created and the required values are populated automatically.

Alternatives evaluated:
No other alternative solution exists for this change.

Proposed publisher location:
Object: Codeunit 5900 "ServOrderManagement"
Procedure: InsertServCost

Placement rationale:
The publisher is placed before the Service Zone Code validation and travel cost lookup logic. This allows extensions to override the standard travel fee determination logic by setting the IsHandled parameter and providing their own implementation.

Performance & data considerations:
The event is triggered only when a travel fee is being created in the InsertServCost procedure. The frequency depends on service document processing and is expected to be low. The event does not introduce additional database operations by itself. Subscribers should implement efficient logic when searching for alternative Service Cost records. No sensitive data is exposed; only Service Header, Service Cost and IsHandled parameters are provided.

Multi‑extension interaction:
Multiple extensions may subscribe to this event. Since the event uses the IsHandled pattern, only one subscriber should take responsibility for overriding the standard behavior. Extensions should avoid conflicting implementations and ensure that IsHandled is set only when they fully handle the travel fee determination logic.

Justification for using IsHandled over alternatives:
The IsHandled pattern is used because the purpose of this publisher is to allow extensions to replace the standard travel fee determination logic. Alternative approaches, such as adding events after the standard lookup or after the record insertion, would not allow extensions to prevent the execution of the existing Service Zone Code validation and cost lookup logic.

Describe the request

Proposed code snippet (before -> after):

procedure InsertServCost(ServInvLine: Record "Service Line"; CostType: Integer; LinktoServItemLine: Boolean): Boolean
    var
        ServCost: Record "Service Cost";
        ServHeader: Record "Service Header";
        ServInvLine2: Record "Service Line";
        ServMgtSetup: Record "Service Mgt. Setup";
        //----------------------------OnInsertServCostOnCostTypeOneOnAfterServCostGet::BEGIN
        IsHandled: Boolean;
        //----------------------------OnInsertServCostOnCostTypeOneOnAfterServCostGet::END
        NextLine: Integer;
    begin
        ServHeader.Get(ServInvLine."Document Type", ServInvLine."Document No.");

        ServInvLine2.Reset();
        ServInvLine2.SetRange("Document Type", ServInvLine."Document Type");
        ServInvLine2.SetRange("Document No.", ServInvLine."Document No.");
        ServInvLine2 := ServInvLine;

        NextLine := ServInvLine.GetNextLineNo(ServInvLine, false);
        if NextLine = 0 then
            Error(Text008, ServInvLine.TableCaption());

        case CostType of
            0: // Travel Fee
                begin
                    //-----------------------------------------------------------OnInsertServCostOnCostTypeZeroOnBeforeTestServiceZoneCode::BEGIN
                    OnInsertServCostOnCostTypeZeroOnBeforeTestServiceZoneCode(ServHeader, ServCost, IsHandled);
                    if not IsHandled then begin
                        ServHeader.TestField("Service Zone Code");
                        ServCost.Reset();
                        ServCost.SetCurrentKey("Service Zone Code");
                        ServCost.SetRange("Service Zone Code", ServHeader."Service Zone Code");
                        ServCost.SetRange("Cost Type", ServCost."Cost Type"::Travel);
                        if not ServCost.FindFirst() then
                            Error(
                              Text009,
                              ServCost.TableCaption(), ServCost.FieldCaption("Service Zone Code"), ServHeader."Service Zone Code");
                    end;
                    //-----------------------------------------------------------OnInsertServCostOnCostTypeZeroOnBeforeTestServiceZoneCode::END
                    ServInvLine2.Init();
                    if LinktoServItemLine then begin
                        ServInvLine2."Service Item Line No." := ServInvLine."Service Item Line No.";
                        ServInvLine2."Service Item No." := ServInvLine."Service Item No.";
                        ServInvLine2."Service Item Serial No." := ServInvLine."Service Item Serial No.";
                    end;
                    ServInvLine2."Document Type" := ServHeader."Document Type";
                    ServInvLine2."Document No." := ServHeader."No.";
                    ServInvLine2."Line No." := NextLine;
                    ServInvLine2.Type := ServInvLine2.Type::Cost;
                    ServInvLine2.Validate("No.", ServCost.Code);
                    ServInvLine2.Validate("Unit of Measure Code", ServCost."Unit of Measure Code");
                    ServInvLine2.Insert(true);
                    exit(true);
                end;
            1: // Starting Fee
                begin
                    ServMgtSetup.Get();
                    ServMgtSetup.TestField("Service Order Starting Fee");
                    ServCost.Get(ServMgtSetup."Service Order Starting Fee");
                    OnInsertServCostOnCostTypeOneOnAfterServCostGet(ServHeader, ServCost);
                    ServInvLine2.Init();
                    if LinktoServItemLine then begin
                        ServInvLine2."Service Item Line No." := ServInvLine."Service Item Line No.";
                        ServInvLine2."Service Item No." := ServInvLine."Service Item No.";
                        ServInvLine2."Service Item Serial No." := ServInvLine."Service Item Serial No.";
                    end;
                    ServInvLine2."Document Type" := ServHeader."Document Type";
                    ServInvLine2."Document No." := ServHeader."No.";
                    ServInvLine2."Line No." := NextLine;
                    ServInvLine2.Type := ServInvLine2.Type::Cost;
                    ServInvLine2.Validate("No.", ServCost.Code);
                    ServInvLine2.Validate("Unit of Measure Code", ServCost."Unit of Measure Code");
                    ServInvLine2.Insert(true);
                    exit(true);
                end;
            else
                exit(false);
        end;
    end;

    //----------------------------OnInsertServCostOnCostTypeOneOnAfterServCostGet::BEGIN
    [IntegrationEvent(false, false)]
    local procedure OnInsertServCostOnCostTypeZeroOnBeforeTestServiceZoneCode(ServHeader: Record "Service Header"; var ServCost: Record "Service Cost"; var IsHandled: Boolean)
    begin
    end;
    //----------------------------OnInsertServCostOnCostTypeOneOnAfterServCostGet::END

Metadata

Metadata

Assignees

No one assigned

    Labels

    missing-infoThe issue misses information that prevents it from completion.

    Type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions