microsoft / microsoft/BCApps

[W1][Table][6010][Service Header Archive] Make SetSecurityFilterOnRespCenter public and add its OnBefore event

Open Beginner friendly
#11,450 4 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

missing-info Team: SCM
Dominant language
AL
Stars
683
Forks
459
Avg merge
3d 26m
Merged PRs (30d)
633

Description

Why do you need this change?

Table 6010 "Service Header Archive" implements internal procedure SetSecurityFilterOnRespCenter(). It is the only table in the W1 Base Application that carries this method but keeps it internal and publishes no OnBeforeSetSecurityFilterOnRespCenter.

A scan of src/Layers/W1 at commit 2f3b868 finds 30 tables that define SetSecurityFilterOnRespCenter. Of those:

Count Detail
Public procedure with the OnBefore... publisher 29 every sales, purchase, service and return document table, including both other archive tables
internal procedure, no publisher 1 6010 Service Header Archive

The current implementation, for reference:

internal procedure SetSecurityFilterOnRespCenter()
var
    UserSetupManagement: Codeunit "User Setup Management";
begin
    if UserSetupManagement.GetServiceFilter() <> '' then begin
        FilterGroup(2);
        SetRange("Responsibility Center", UserSetupManagement.GetServiceFilter());
        FilterGroup(0);
    end;
end;

Compare the direct sibling, table 5107 "Sales Header Archive", which is a public procedure with an IsHandled publisher.

What makes this different from a normal parity gap

Nothing in the W1 Base Application calls table 6010's method. Five pages are
bound to the table and none of them calls SetSecurityFilterOnRespCenter or
applies any responsibility-center filter:

  • 6270 Service Order Archives
  • 6267 Service Quote Archives
  • 6271 Service Order Archive
  • 6268 Service Quote Archive
  • 6274 Service List Archive

Two of them do have an OnOpenPage trigger — 6271 calls ActivateFields() and
sets VATDateEnabled, 6268 calls ActivateFields() — but neither touches
"Responsibility Center".

The equivalent sales and purchase archive list pages do call it, for example Sales Order Archives and Purchase Order Archives, both from OnOpenPage.

So an extension is currently the only plausible consumer of this method, and internal is precisely what prevents it from being one. An extension that wants responsibility-center security on archived service documents can neither call the standard implementation nor substitute its own through an event. Its only fallback is to re-implement the filter inside an OnOpenPage subscriber for each of the five pages by name, which covers nothing else that reads the table - reports, APIs, or any future Base Application caller.

Repro
  1. In a new extension, add a codeunit:
procedure Test()
var
    SalesHeaderArchive: Record "Sales Header Archive";
    ServiceHeaderArchive: Record "Service Header Archive";
begin
    SalesHeaderArchive.SetSecurityFilterOnRespCenter();     // compiles
    ServiceHeaderArchive.SetSecurityFilterOnRespCenter();   // does not compile
end;
  1. Compile against application 27.0.
    Expected: both lines compile, since both tables carry "Responsibility Center" and both implement the method.
    Actual: only the sales archive line compiles. The service archive line fails because the member is internal to the Base Application and therefore not accessible from an extension.

  2. Then try to override the filter on either table by subscribing to OnBeforeSetSecurityFilterOnRespCenter. The subscription resolves for Sales Header Archive and there is no such publisher to subscribe to for Service Header Archive.

Describe the request

Two changes to table 6010 "Service Header Archive", both confined to the existing SetSecurityFilterOnRespCenter method.

  1. Change internal procedure SetSecurityFilterOnRespCenter() to procedure SetSecurityFilterOnRespCenter(), matching the other 29 tables.
  2. Add the OnBeforeSetSecurityFilterOnRespCenter publisher, identical in shape and placement to the one on Sales Header Archive.

Resulting method:

procedure SetSecurityFilterOnRespCenter()
var
    UserSetupManagement: Codeunit "User Setup Management";
    IsHandled: Boolean;
begin
    IsHandled := false;
    OnBeforeSetSecurityFilterOnRespCenter(Rec, IsHandled);
    if IsHandled then
        exit;

    if UserSetupManagement.GetServiceFilter() <> '' then begin
        FilterGroup(2);
        SetRange("Responsibility Center", UserSetupManagement.GetServiceFilter());
        FilterGroup(0);
    end;
end;
Event publisher

EventRequest

[W1][Table][6010][Service Header Archive]
[SetSecurityFilterOnRespCenter]
___
Raised before the responsibility-center security filter is applied, so an extension can replace it, matching the publisher that already exists on Sales Header Archive and Purchase Header Archive.
___
[IntegrationEvent(false, false)]
local procedure OnBeforeSetSecurityFilterOnRespCenter(var ServiceHeaderArchive: Record "Service Header Archive"; var IsHandled: Boolean)
begin
end;
Minimum requirements for the new IsHandled event

This request copies an existing IsHandled publisher, so per minimum requirements for new IsHandled events:

  • Problem statement: Service Header Archive filters "Responsibility Center" but exposes no way to reuse or replace that logic, unlike the 29 other tables that implement the same method.
  • Alternatives evaluated: subscribing to the publisher on Sales Header Archive does not fire for service archives. An OnOpenPage subscriber on each of the five archive pages is page-scoped and invisible to reports and APIs. Making the method public without the event would let an extension call the standard filter but still not substitute a different one, which is the actual need.
  • Proposed publisher location: table 6010, inside SetSecurityFilterOnRespCenter, immediately before the filter is applied - identical placement to Sales Header Archive.
  • Proposed code: the snippet above. Before: internal, no event. After: a copy of the sibling implementation.
  • Subscriber example: IsHandled := true; followed by FilterGroup(2); SetFilter("Responsibility Center", <filter>); FilterGroup(0);.
  • Performance and data: called once per page open or report data item, never in a record loop. Parameters are the record and a Boolean. No new fields and no new data exposure.
  • Multi-extension interaction: the same contract as every existing OnBeforeSetSecurityFilterOnRespCenter - the first subscriber to set IsHandled wins, and subscribers are expected to exit when it is already true. Acceptable because a security filter should have a single owner.
  • Justification for IsHandled rather than a different pattern: consistency. A skip-style event would arguably be higher quality in the abstract, but introducing a different shape on one of thirty tables would force partners to write two subscriber shapes for one rule.
Explicitly out of scope

This request does not ask you to change what the five archive pages do. Whether Service Order Archives and the others should call SetSecurityFilterOnRespCenter from OnOpenPage, the way the sales and purchase archive list pages do, is a separate question about product behaviour and would change what existing users see. It is mentioned above only to explain why the method currently has no caller, and why an extension is the only party that can use it. If that call is ever added, the publisher requested here is what makes it overridable.

Affected objects

Table 6010 "Service Header Archive" in W1 only. Unlike Sales Line or Purchase Header, this table has no localization-layer copies - ServiceHeaderArchive.Table.al exists in src/Layers/W1 and nowhere else in the repository, so there are no counterparts to keep in sync.

Compatibility

Purely additive. Widening internal to procedure removes no member and changes no signature. The new publisher has no subscribers on an existing installation, so IsHandled stays false and the method behaves exactly as it does today. Since no Base Application code currently calls the method, there is no call site whose behaviour could change.

Relationship to #11448

#11448 asks for multi-value responsibility-center filters, which would change how every implementation of this method resolves its filter. That request originally also contained this table-6010 parity item; it has been removed from it and filed here so that each request covers one change. The two are independent: if #11448 is accepted, the body of this method would use the text variant and SetFilter like all the others, but the internal to procedure widening and the missing publisher are needed either way.

Provide an implementation (optional)
  • I will provide the implementation for this extensibility request

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with the W1 ServiceHeaderArchive.Table.al implementation of SetSecurityFilterOnRespCenter and compare its placement and publisher shape with SalesHeaderArchive.Table.al. Make the requested accessibility and event changes only in table 6010, then compile the extension repro to confirm both archive methods are accessible and the new event can be subscribed to.

Written by the indexing model from the issue text.

Assessment

Domain
backend-api-design
Issue type
Feature
Difficulty
2/5
Estimated time
1-3 hours
Activity status
Active
Clarity
Clearly specified
Newbie friendliness
88/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.