[W1][MultiObjects] Add SetSecurityFilterOnRespCenter on Sales Line and Purchase Line
Nobody has claimed this yet.
- Dominant language
- AL
- Stars
- 683
- Forks
- 459
- Avg merge
- 3d 26m
- Merged PRs (30d)
- 633
Description
Why do you need this change?
Tables 37 "Sales Line" and 39 "Purchase Line" both carry field(5700; "Responsibility Center"; Code[10]), but neither implements SetSecurityFilterOnRespCenter() nor publishes OnBeforeSetSecurityFilterOnRespCenter. Every other document line table in the W1 Base Application that carries that field does implement both.
Exhaustive list from a scan of src/Layers/W1 at commit 2f3b868. 12 line-level tables implement the method:
| Table ID | Table name |
|---|---|
| 111 | Sales Shipment Line |
| 113 | Sales Invoice Line |
| 115 | Sales Cr.Memo Line |
| 121 | Purch. Rcpt. Line |
| 123 | Purch. Inv. Line |
| 125 | Purch. Cr. Memo Line |
| 5901 | Service Item Line |
| 5991 | Service Shipment Line |
| 5993 | Service Invoice Line |
| 5995 | Service Cr.Memo Line |
| 6651 | Return Shipment Line |
| 6661 | Return Receipt Line |
2 line-level tables do not, despite carrying the same field: 37 Sales Line and 39 Purchase Line.
The consequence is an inconsistent extension surface. An extension that applies responsibility-center security to line-level data - a report data item over Sales Line, an API page, or a list page bound directly to the line table - has a supported hook on all twelve posted and archived line tables and none on the two open-document ones. Its only fallback is a page-level OnOpenPageEvent subscriber, which covers just the pages it names and does nothing for reports, APIs, or any future Base Application caller of a table method.
To be explicit about what this request is not. Open sales and purchase documents are not left unprotected today. Tables 36 Sales Header and 38 Purchase Header both implement SetSecurityFilterOnRespCenter, and a document's lines are normally reached through the already-filtered header. This is a consistency request about the extension surface on the line tables themselves, not a report of a security hole.
Repro
- In a new extension, add a codeunit:
procedure Test()
var
PurchInvLine: Record "Purch. Inv. Line";
PurchaseLine: Record "Purchase Line";
begin
PurchInvLine.SetSecurityFilterOnRespCenter(); // compiles
PurchaseLine.SetSecurityFilterOnRespCenter(); // does not compile
end;
- Compile against application 27.0.
Expected: both lines compile, since both tables carry"Responsibility Center".
Actual: only the posted line table compiles; the compiler reports thatPurchase Linehas no such member. The same applies toSales Invoice LineversusSales Line.
Describe the request
Add to table 37 "Sales Line" and table 39 "Purchase Line" the same member that the twelve sibling line tables already have.
Relationship to #11448. That request asks for multi-value responsibility-center filters, which changes how every implementation of this method resolves its filter. The two requests are independent in scope - this one is pure parity on two tables - but if #11448 is accepted, the implementation added here should use the text variant and SetFilter rather than SetRange, so that these two tables do not become the only ones stuck on a single center. Both shapes are given below.
Shape matching the current siblings
procedure SetSecurityFilterOnRespCenter()
var
UserSetupMgt: Codeunit "User Setup Management";
IsHandled: Boolean;
begin
IsHandled := false;
OnBeforeSetSecurityFilterOnRespCenter(Rec, IsHandled);
if IsHandled then
exit;
if UserSetupMgt.GetPurchasesFilter() <> '' then begin // GetSalesFilter() on Sales Line
FilterGroup(2);
SetRange("Responsibility Center", UserSetupMgt.GetPurchasesFilter());
FilterGroup(0);
end;
end;
Shape if #11448 is accepted
procedure SetSecurityFilterOnRespCenter()
var
UserSetupMgt: Codeunit "User Setup Management";
RespCenterFilter: Text;
IsHandled: Boolean;
begin
IsHandled := false;
OnBeforeSetSecurityFilterOnRespCenter(Rec, IsHandled);
if IsHandled then
exit;
RespCenterFilter := UserSetupMgt.GetPurchasesFilterText(); // GetSalesFilterText() on Sales Line
if RespCenterFilter <> '' then begin
FilterGroup(2);
SetFilter("Responsibility Center", RespCenterFilter);
FilterGroup(0);
end;
end;
Event publishers
EventRequest
[W1][Table][39][Purchase Line]
[SetSecurityFilterOnRespCenter]
___
Raised before the responsibility-center security filter is applied, so an extension can replace it, matching the publisher that already exists on Purch. Inv. Line and the other posted line tables.
___
[IntegrationEvent(false, false)]
local procedure OnBeforeSetSecurityFilterOnRespCenter(var PurchaseLine: Record "Purchase Line"; var IsHandled: Boolean)
begin
end;
EventRequest
[W1][Table][37][Sales Line]
[SetSecurityFilterOnRespCenter]
___
Raised before the responsibility-center security filter is applied, so an extension can replace it, matching the publisher that already exists on Sales Invoice Line and the other posted line tables.
___
[IntegrationEvent(false, false)]
local procedure OnBeforeSetSecurityFilterOnRespCenter(var SalesLine: Record "Sales Line"; var IsHandled: Boolean)
begin
end;
Minimum requirements for the new IsHandled events
This request copies an existing IsHandled publisher, so per minimum requirements for new IsHandled events:
- Problem statement: the two open-document line tables carry
"Responsibility Center"but expose no way to apply or override responsibility-center security, unlike the twelve sibling line tables. - Alternatives evaluated: subscribing to the publisher on
Purch. Inv. LineorSales Invoice Linedoes not help, because those events never fire for open lines. A pageOnOpenPageEventon the line pages works but is page-scoped and invisible to reports and APIs. Asking for the procedure without the event would still leave no way to substitute a different filter, which is the actual need. - Proposed publisher location: tables 37 and 39, inside
SetSecurityFilterOnRespCenter, immediately before the filter is applied - identical placement toPurch. Inv. Line. - Proposed code: the snippets above. Before: the member does not exist. After: a copy of the sibling implementation.
- Subscriber example:
IsHandled := true;followed byFilterGroup(2); SetFilter("Responsibility Center", <multi-value filter>); FilterGroup(0);. - Performance and data: called once per page open or report data item, never in a record loop. Parameters are the line 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 setIsHandledwins, and subscribers are expected to exit when it is already true. Acceptable because a security filter should have a single owner. - Justification for
IsHandledrather than a different pattern: consistency. A skip-style event would arguably be higher quality in the abstract, but introducing a different shape on two of fourteen line tables would force partners to write two subscriber shapes for one rule.
Affected objects
- Table 37
"Sales Line"and table 39"Purchase Line"in W1. - Per the W1-first layering convention, the same-named counterparts that already exist in the localization layers, all of which carry field 5700:
SalesLine.Table.al: APAC, BE, CH, ES, FI, GB, IT, NA, NO, RU, SEPurchaseLine.Table.al: APAC, BE, CH, DACH, ES, FI, GB, IT, NA, NL, NO, RU, SE
Compatibility
Purely additive. The new procedure is not called from anywhere in the Base Application, so no existing behaviour changes and no signature is modified or removed. It simply becomes available to extensions, and to any future Base Application caller, on the same terms as the twelve sibling line tables.
Provide an implementation (optional)
- I will provide the implementation for this extensibility request
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start by comparing W1 tables 37 "Sales Line" and 39 "Purchase Line" with the existing sibling line-table implementations of SetSecurityFilterOnRespCenter and OnBeforeSetSecurityFilterOnRespCenter. Review SalesLine.Table.al and PurchaseLine.Table.al in the listed localization layers, then compile the provided application 27.0 repro. Done means both open-document line tables and their counterparts expose the matching procedure and event publisher.
Written by the indexing model from the issue text.
Assessment
- Domain
- backend
- Issue type
- Feature
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Active
- Clarity
- Clearly specified
- Newbie friendliness
- 76/100