@linkup-ai/abap-ai 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (114) hide show
  1. package/README.md +384 -0
  2. package/dist/adt-client.js +364 -0
  3. package/dist/cli/activate.js +113 -0
  4. package/dist/cli/init.js +333 -0
  5. package/dist/cli/remove.js +80 -0
  6. package/dist/cli/status.js +229 -0
  7. package/dist/cli/systems.js +68 -0
  8. package/dist/cli.js +81 -0
  9. package/dist/index.js +1318 -0
  10. package/dist/knowledge/abap/abap-dictionary.md +199 -0
  11. package/dist/knowledge/abap/abap-sql.md +296 -0
  12. package/dist/knowledge/abap/amdp.md +273 -0
  13. package/dist/knowledge/abap/clean-code.md +293 -0
  14. package/dist/knowledge/abap/cloud-background-processing.md +250 -0
  15. package/dist/knowledge/abap/cloud-communication.md +265 -0
  16. package/dist/knowledge/abap/cloud-development.md +176 -0
  17. package/dist/knowledge/abap/cloud-extensibility.md +252 -0
  18. package/dist/knowledge/abap/cloud-released-apis.md +261 -0
  19. package/dist/knowledge/abap/constructor-expressions.md +289 -0
  20. package/dist/knowledge/abap/enhancements.md +232 -0
  21. package/dist/knowledge/abap/exceptions.md +271 -0
  22. package/dist/knowledge/abap/internal-tables.md +205 -0
  23. package/dist/knowledge/abap/object-orientation.md +298 -0
  24. package/dist/knowledge/abap/performance.md +216 -0
  25. package/dist/knowledge/abap/rap-abstract-entities.md +206 -0
  26. package/dist/knowledge/abap/rap-business-events.md +216 -0
  27. package/dist/knowledge/abap/rap-draft.md +191 -0
  28. package/dist/knowledge/abap/rap-eml.md +453 -0
  29. package/dist/knowledge/abap/rap-end-to-end.md +486 -0
  30. package/dist/knowledge/abap/rap-feature-control.md +185 -0
  31. package/dist/knowledge/abap/rap-numbering.md +280 -0
  32. package/dist/knowledge/abap/rap-service-exposure.md +163 -0
  33. package/dist/knowledge/abap/rap-unmanaged.md +468 -0
  34. package/dist/knowledge/abap/string-processing.md +180 -0
  35. package/dist/knowledge/abap/unit-testing.md +303 -0
  36. package/dist/knowledge/abap-cds/access-control.md +241 -0
  37. package/dist/knowledge/abap-cds/annotations.md +331 -0
  38. package/dist/knowledge/abap-cds/associations.md +254 -0
  39. package/dist/knowledge/abap-cds/expressions.md +230 -0
  40. package/dist/knowledge/abap-cds/functions.md +245 -0
  41. package/dist/knowledge/abap-cds/metadata-extensions.md +294 -0
  42. package/dist/knowledge/cap/authentication.md +278 -0
  43. package/dist/knowledge/cap/cdl-syntax.md +247 -0
  44. package/dist/knowledge/cap/cql-queries.md +266 -0
  45. package/dist/knowledge/cap/deployment.md +343 -0
  46. package/dist/knowledge/cap/event-handlers.md +287 -0
  47. package/dist/knowledge/cap/fiori-integration.md +303 -0
  48. package/dist/knowledge/cap/service-definitions.md +287 -0
  49. package/dist/knowledge/fiori/annotations.md +347 -0
  50. package/dist/knowledge/fiori/deployment.md +340 -0
  51. package/dist/knowledge/fiori/fiori-elements.md +332 -0
  52. package/dist/knowledge/fiori/fiori-side-effects.md +107 -0
  53. package/dist/knowledge/fiori/fiori-valuelist.md +144 -0
  54. package/dist/knowledge/fiori/ui5-controllers.md +358 -0
  55. package/dist/knowledge/fiori/ui5-data-binding.md +311 -0
  56. package/dist/knowledge/fiori/ui5-fragments-dialogs.md +330 -0
  57. package/dist/knowledge/fiori/ui5-manifest.md +411 -0
  58. package/dist/knowledge/fiori/ui5-routing.md +303 -0
  59. package/dist/knowledge/fiori/ui5-xml-views.md +294 -0
  60. package/dist/logger.js +114 -0
  61. package/dist/system-profile.js +207 -0
  62. package/dist/tools/abap-doc.js +72 -0
  63. package/dist/tools/abapgit.js +161 -0
  64. package/dist/tools/activate.js +68 -0
  65. package/dist/tools/atc-check.js +117 -0
  66. package/dist/tools/auth-object.js +56 -0
  67. package/dist/tools/breakpoints.js +76 -0
  68. package/dist/tools/call-hierarchy.js +84 -0
  69. package/dist/tools/cds-annotations.js +98 -0
  70. package/dist/tools/cds-dependencies.js +65 -0
  71. package/dist/tools/check.js +47 -0
  72. package/dist/tools/code-completion.js +70 -0
  73. package/dist/tools/code-coverage.js +111 -0
  74. package/dist/tools/create-amdp.js +111 -0
  75. package/dist/tools/create-dcl.js +81 -0
  76. package/dist/tools/create-transport.js +38 -0
  77. package/dist/tools/create.js +285 -0
  78. package/dist/tools/data-preview.js +37 -0
  79. package/dist/tools/delete.js +45 -0
  80. package/dist/tools/deploy-bsp.js +298 -0
  81. package/dist/tools/discovery.js +59 -0
  82. package/dist/tools/element-info.js +93 -0
  83. package/dist/tools/enhancements.js +186 -0
  84. package/dist/tools/extract-method.js +44 -0
  85. package/dist/tools/function-group.js +59 -0
  86. package/dist/tools/knowledge.js +275 -0
  87. package/dist/tools/lock-object.js +75 -0
  88. package/dist/tools/message-class.js +67 -0
  89. package/dist/tools/navigate.js +80 -0
  90. package/dist/tools/number-range.js +57 -0
  91. package/dist/tools/object-documentation.js +43 -0
  92. package/dist/tools/object-structure.js +78 -0
  93. package/dist/tools/object-versions.js +57 -0
  94. package/dist/tools/package-contents.js +60 -0
  95. package/dist/tools/pretty-printer.js +35 -0
  96. package/dist/tools/publish-binding.js +49 -0
  97. package/dist/tools/quick-fix.js +69 -0
  98. package/dist/tools/read.js +167 -0
  99. package/dist/tools/refactor-rename.js +60 -0
  100. package/dist/tools/release-transport.js +24 -0
  101. package/dist/tools/released-apis.js +51 -0
  102. package/dist/tools/repository-tree.js +90 -0
  103. package/dist/tools/scaffold-rap.js +642 -0
  104. package/dist/tools/search.js +73 -0
  105. package/dist/tools/shared/data-format.js +101 -0
  106. package/dist/tools/sql-console.js +17 -0
  107. package/dist/tools/system-info.js +270 -0
  108. package/dist/tools/traces.js +66 -0
  109. package/dist/tools/transport-contents.js +83 -0
  110. package/dist/tools/transports.js +67 -0
  111. package/dist/tools/unit-test.js +135 -0
  112. package/dist/tools/where-used.js +59 -0
  113. package/dist/tools/write.js +101 -0
  114. package/package.json +49 -0
@@ -0,0 +1,303 @@
1
+ # ABAP Unit Testing — test classes, assertions, test doubles, RAP BO testing
2
+
3
+ ## Test Class Definition
4
+
5
+ ```abap
6
+ CLASS ltc_order_processor DEFINITION FINAL FOR TESTING
7
+ DURATION SHORT RISK LEVEL HARMLESS.
8
+
9
+ PRIVATE SECTION.
10
+ DATA mo_cut TYPE REF TO zcl_order_processor. " class under test
11
+
12
+ METHODS setup.
13
+ METHODS teardown.
14
+ METHODS test_create_order FOR TESTING.
15
+ METHODS test_invalid_customer FOR TESTING.
16
+ METHODS test_calculate_total FOR TESTING.
17
+ ENDCLASS.
18
+
19
+ CLASS ltc_order_processor IMPLEMENTATION.
20
+ METHOD setup.
21
+ mo_cut = NEW #( ).
22
+ ENDMETHOD.
23
+
24
+ METHOD teardown.
25
+ CLEAR mo_cut.
26
+ ENDMETHOD.
27
+
28
+ METHOD test_create_order.
29
+ DATA(lv_result) = mo_cut->create_order(
30
+ iv_customer = 'CUST100'
31
+ iv_amount = 500 ).
32
+
33
+ cl_abap_unit_assert=>assert_not_initial( lv_result ).
34
+ cl_abap_unit_assert=>assert_equals( exp = 'O' act = lv_result-status ).
35
+ ENDMETHOD.
36
+
37
+ METHOD test_invalid_customer.
38
+ TRY.
39
+ mo_cut->create_order( iv_customer = '' iv_amount = 500 ).
40
+ cl_abap_unit_assert=>fail( msg = 'Expected exception' ).
41
+ CATCH zcx_order_error INTO DATA(lx).
42
+ cl_abap_unit_assert=>assert_bound( lx ).
43
+ ENDTRY.
44
+ ENDMETHOD.
45
+
46
+ METHOD test_calculate_total.
47
+ DATA(lv_total) = mo_cut->calculate_total(
48
+ it_items = VALUE #( ( price = 100 qty = 2 )
49
+ ( price = 50 qty = 3 ) ) ).
50
+
51
+ cl_abap_unit_assert=>assert_equals( exp = 350 act = lv_total ).
52
+ ENDMETHOD.
53
+ ENDCLASS.
54
+ ```
55
+
56
+ ## Assertion Methods
57
+
58
+ ```abap
59
+ " Equality
60
+ cl_abap_unit_assert=>assert_equals( exp = 'A' act = lv_status msg = 'Status should be A' ).
61
+
62
+ " Not initial
63
+ cl_abap_unit_assert=>assert_not_initial( act = lv_id ).
64
+
65
+ " Initial
66
+ cl_abap_unit_assert=>assert_initial( act = lv_error ).
67
+
68
+ " Bound / not bound (references)
69
+ cl_abap_unit_assert=>assert_bound( act = lo_ref ).
70
+ cl_abap_unit_assert=>assert_not_bound( act = lo_ref ).
71
+
72
+ " True / false
73
+ cl_abap_unit_assert=>assert_true( act = lv_flag ).
74
+ cl_abap_unit_assert=>assert_false( act = lv_flag ).
75
+
76
+ " Table content
77
+ cl_abap_unit_assert=>assert_equals( exp = 3 act = lines( lt_items ) ).
78
+
79
+ " Subrc
80
+ cl_abap_unit_assert=>assert_subrc( exp = 0 msg = 'SELECT should find record' ).
81
+
82
+ " Fail explicitly
83
+ cl_abap_unit_assert=>fail( msg = 'Should not reach here' ).
84
+
85
+ " Char contains
86
+ cl_abap_unit_assert=>assert_char_cp(
87
+ exp = '*error*' act = lv_message msg = 'Should contain error' ).
88
+ ```
89
+
90
+ ## Test Doubles — SQL (CDS)
91
+
92
+ ```abap
93
+ " Mock database access for CDS entities
94
+ CLASS ltc_with_sql_double DEFINITION FINAL FOR TESTING
95
+ DURATION SHORT RISK LEVEL HARMLESS.
96
+
97
+ PRIVATE SECTION.
98
+ CLASS-DATA environment TYPE REF TO if_cds_test_environment.
99
+
100
+ CLASS-METHODS class_setup.
101
+ CLASS-METHODS class_teardown.
102
+ METHODS setup.
103
+ METHODS test_read FOR TESTING.
104
+ ENDCLASS.
105
+
106
+ CLASS ltc_with_sql_double IMPLEMENTATION.
107
+ METHOD class_setup.
108
+ environment = cl_cds_test_environment=>create( i_for_entity = 'ZI_ORDER' ).
109
+ ENDMETHOD.
110
+
111
+ METHOD class_teardown.
112
+ environment->destroy( ).
113
+ ENDMETHOD.
114
+
115
+ METHOD setup.
116
+ environment->clear_doubles( ).
117
+ ENDMETHOD.
118
+
119
+ METHOD test_read.
120
+ " Prepare test data
121
+ DATA lt_orders TYPE STANDARD TABLE OF ztab_order.
122
+ lt_orders = VALUE #(
123
+ ( order_id = '0000000001' customer_id = 'CUST100' status = 'O' total_amount = 500 )
124
+ ( order_id = '0000000002' customer_id = 'CUST200' status = 'A' total_amount = 800 ) ).
125
+
126
+ environment->insert_test_data( lt_orders ).
127
+
128
+ " Execute code under test
129
+ SELECT * FROM ZI_Order INTO TABLE @DATA(lt_result).
130
+
131
+ cl_abap_unit_assert=>assert_equals( exp = 2 act = lines( lt_result ) ).
132
+ ENDMETHOD.
133
+ ENDCLASS.
134
+ ```
135
+
136
+ ## Test Doubles — ABAP OO (Interface Mock)
137
+
138
+ ```abap
139
+ " Using CL_ABAP_TESTDOUBLE
140
+ CLASS ltc_with_mock DEFINITION FINAL FOR TESTING
141
+ DURATION SHORT RISK LEVEL HARMLESS.
142
+
143
+ PRIVATE SECTION.
144
+ METHODS test_with_mock FOR TESTING.
145
+ ENDCLASS.
146
+
147
+ CLASS ltc_with_mock IMPLEMENTATION.
148
+ METHOD test_with_mock.
149
+ " Create test double for interface
150
+ DATA lo_double TYPE REF TO zif_customer_service.
151
+ lo_double ?= cl_abap_testdouble=>create( 'zif_customer_service' ).
152
+
153
+ " Configure behavior
154
+ cl_abap_testdouble=>configure_call( lo_double
155
+ )->returning( VALUE zs_customer( id = 'C100' name = 'Test Customer' ) ).
156
+ lo_double->get_customer( 'C100' ). " records the call
157
+
158
+ " Inject and test
159
+ DATA(lo_cut) = NEW zcl_order_processor( io_customer_svc = lo_double ).
160
+ DATA(ls_order) = lo_cut->create_order( iv_customer = 'C100' ).
161
+
162
+ cl_abap_unit_assert=>assert_equals( exp = 'Test Customer' act = ls_order-customer_name ).
163
+
164
+ " Verify call was made
165
+ cl_abap_testdouble=>verify_expectations( lo_double ).
166
+ ENDMETHOD.
167
+ ENDCLASS.
168
+ ```
169
+
170
+ ## RAP BO Test — Managed BO with EML
171
+
172
+ ```abap
173
+ CLASS ltc_travel_bo DEFINITION FINAL FOR TESTING
174
+ DURATION SHORT RISK LEVEL HARMLESS.
175
+
176
+ PRIVATE SECTION.
177
+ CLASS-DATA environment TYPE REF TO if_cds_test_environment.
178
+ CLASS-DATA bo_test_env TYPE REF TO if_botd_txbufdbl_bo_test_env.
179
+
180
+ CLASS-METHODS class_setup.
181
+ CLASS-METHODS class_teardown.
182
+ METHODS setup.
183
+ METHODS test_create_travel FOR TESTING.
184
+ METHODS test_accept_travel FOR TESTING.
185
+ METHODS test_validate_dates FOR TESTING.
186
+ ENDCLASS.
187
+
188
+ CLASS ltc_travel_bo IMPLEMENTATION.
189
+ METHOD class_setup.
190
+ " Create BO test double environment
191
+ bo_test_env = cl_botd_txbufdbl_bo_test_env=>create(
192
+ VALUE #( ( 'ZI_TRAVEL' ) ) ).
193
+
194
+ " CDS test environment for related entities
195
+ environment = cl_cds_test_environment=>create(
196
+ i_for_entity = 'ZI_TRAVEL'
197
+ i_dependency_list = VALUE #( ( '/DMO/I_AGENCY' ) ( '/DMO/I_CUSTOMER' ) ) ).
198
+ ENDMETHOD.
199
+
200
+ METHOD class_teardown.
201
+ bo_test_env->destroy( ).
202
+ environment->destroy( ).
203
+ ENDMETHOD.
204
+
205
+ METHOD setup.
206
+ environment->clear_doubles( ).
207
+ ENDMETHOD.
208
+
209
+ METHOD test_create_travel.
210
+ MODIFY ENTITIES OF ZI_Travel
211
+ ENTITY Travel
212
+ CREATE FIELDS ( AgencyID CustomerID BeginDate EndDate Description )
213
+ WITH VALUE #( (
214
+ %cid = 'CID_1'
215
+ AgencyID = '000001'
216
+ CustomerID = '000001'
217
+ BeginDate = sy-datum
218
+ EndDate = sy-datum + 10
219
+ Description = 'Test Travel' ) )
220
+ MAPPED DATA(mapped)
221
+ FAILED DATA(failed)
222
+ REPORTED DATA(reported).
223
+
224
+ cl_abap_unit_assert=>assert_not_initial( mapped-travel ).
225
+ cl_abap_unit_assert=>assert_initial( failed-travel ).
226
+ ENDMETHOD.
227
+
228
+ METHOD test_accept_travel.
229
+ " First create
230
+ MODIFY ENTITIES OF ZI_Travel
231
+ ENTITY Travel
232
+ CREATE FIELDS ( AgencyID CustomerID BeginDate EndDate )
233
+ WITH VALUE #( ( %cid = 'CID_1' AgencyID = '000001' CustomerID = '000001'
234
+ BeginDate = sy-datum EndDate = sy-datum + 10 ) )
235
+ MAPPED DATA(mapped) FAILED DATA(failed) REPORTED DATA(reported).
236
+
237
+ " Then execute action
238
+ MODIFY ENTITIES OF ZI_Travel
239
+ ENTITY Travel
240
+ EXECUTE acceptTravel
241
+ FROM VALUE #( ( %tky = mapped-travel[ 1 ]-%tky ) )
242
+ RESULT DATA(result)
243
+ FAILED failed
244
+ REPORTED reported.
245
+
246
+ cl_abap_unit_assert=>assert_equals(
247
+ exp = 'A' act = result[ 1 ]-%param-OverallStatus ).
248
+ ENDMETHOD.
249
+
250
+ METHOD test_validate_dates.
251
+ " Create with invalid dates (end before begin)
252
+ MODIFY ENTITIES OF ZI_Travel
253
+ ENTITY Travel
254
+ CREATE FIELDS ( AgencyID CustomerID BeginDate EndDate )
255
+ WITH VALUE #( ( %cid = 'CID_1' AgencyID = '000001' CustomerID = '000001'
256
+ BeginDate = '20260315' EndDate = '20260310' ) )
257
+ MAPPED DATA(mapped) FAILED DATA(failed) REPORTED DATA(reported).
258
+
259
+ COMMIT ENTITIES
260
+ RESPONSE OF ZI_Travel
261
+ FAILED DATA(commit_failed)
262
+ REPORTED DATA(commit_reported).
263
+
264
+ " Validation should have produced error
265
+ cl_abap_unit_assert=>assert_not_initial( commit_failed-travel ).
266
+ ENDMETHOD.
267
+ ENDCLASS.
268
+ ```
269
+
270
+ ## Test Class Annotations
271
+
272
+ ```abap
273
+ " Duration
274
+ DURATION SHORT " < 1 second per method (default)
275
+ DURATION MEDIUM " < 5 seconds
276
+ DURATION LONG " > 5 seconds
277
+
278
+ " Risk level
279
+ RISK LEVEL HARMLESS " No DB changes (default)
280
+ RISK LEVEL DANGEROUS " May change DB
281
+ RISK LEVEL CRITICAL " May change system config
282
+ ```
283
+
284
+ ## Rules
285
+ - Test class: `FOR TESTING` + `DURATION SHORT` + `RISK LEVEL HARMLESS`
286
+ - Use `setup` for per-test initialization, `class_setup` for one-time setup
287
+ - One assertion per logical check — multiple assertions OK if testing one behavior
288
+ - Use CDS test environment (`cl_cds_test_environment`) for SQL test doubles
289
+ - Use `cl_abap_testdouble` for OO interface mocking
290
+ - RAP BO tests: use `cl_botd_txbufdbl_bo_test_env` for transaction buffer doubles
291
+ - Always `destroy()` environments in `class_teardown`
292
+ - Test method names should describe what is tested: `test_<scenario>`
293
+
294
+ ## Anti-Patterns
295
+ | Anti-Pattern | Correct |
296
+ |---|---|
297
+ | Testing private methods directly | Test via public interface |
298
+ | No assertions in test method | Always assert expected outcome |
299
+ | `CATCH cx_root` hiding test failures | Let exceptions propagate or assert them |
300
+ | DB access in RISK LEVEL HARMLESS | Use test doubles or set RISK LEVEL DANGEROUS |
301
+ | Missing `setup` / `class_setup` | Initialize test data properly |
302
+ | Huge test methods testing everything | One scenario per test method |
303
+ | Hardcoded dates that expire | Use `sy-datum` + offset |
@@ -0,0 +1,241 @@
1
+ # CDS Access Control — DCL Row-Level Authorization
2
+
3
+ ## DCL Structure
4
+
5
+ ```sql
6
+ @EndUserText.label: 'Access Control for Z_SALES'
7
+ @MappingRole: true
8
+ define role Z_SALES_DCL {
9
+ grant select on Z_SALES
10
+ where condition;
11
+ }
12
+ ```
13
+
14
+ ## PFCG Authorization — Single Object
15
+
16
+ ```sql
17
+ @MappingRole: true
18
+ define role Z_FIN_DCL {
19
+ grant select on Z_FINANCIAL_DATA
20
+ where (bukrs) = aspect pfcg_auth(F_BKPF_BUK, BUKRS, ACTVT = '03');
21
+ }
22
+ ```
23
+
24
+ Syntax: `(cds_field) = aspect pfcg_auth(AUTH_OBJECT, AUTH_FIELD, ACTVT = 'value')`
25
+
26
+ ## PFCG — Multiple Fields
27
+
28
+ ```sql
29
+ @MappingRole: true
30
+ define role Z_SD_DCL {
31
+ grant select on Z_SALES_ORDER
32
+ where (vkorg, vtweg, spart) =
33
+ aspect pfcg_auth(V_VBAK_VKO, VKORG, VTWEG, SPART, ACTVT = '03');
34
+ }
35
+ ```
36
+
37
+ Fields map positionally to authorization fields.
38
+
39
+ ## PFCG — Multiple Objects
40
+
41
+ ```sql
42
+ @MappingRole: true
43
+ define role Z_MULTI_DCL {
44
+ grant select on Z_VIEW
45
+ where (bukrs) = aspect pfcg_auth(F_BKPF_BUK, BUKRS, ACTVT = '03')
46
+ and (vkorg, vtweg, spart) =
47
+ aspect pfcg_auth(V_VBAK_VKO, VKORG, VTWEG, SPART, ACTVT = '03');
48
+ }
49
+ ```
50
+
51
+ ## Literal Condition
52
+
53
+ ```sql
54
+ @MappingRole: true
55
+ define role Z_ACTIVE_DCL {
56
+ grant select on Z_VIEW
57
+ where status = 'ACTIVE';
58
+ }
59
+ ```
60
+
61
+ Operators: `=`, `<>`, `<`, `>`, `<=`, `>=`, `between ... and ...`, `like`
62
+
63
+ ## User Aspect
64
+
65
+ ```sql
66
+ @MappingRole: true
67
+ define role Z_OWN_DCL {
68
+ grant select on Z_TASKS
69
+ where assigned_to ?= aspect user;
70
+ }
71
+ ```
72
+
73
+ `?=` allows NULL/initial values to pass.
74
+
75
+ ## Environment Aspect
76
+
77
+ ```sql
78
+ where client = aspect environment.client
79
+ ```
80
+
81
+ ## Combining Conditions — AND
82
+
83
+ ```sql
84
+ where (bukrs) = aspect pfcg_auth(F_BKPF_BUK, BUKRS, ACTVT = '03')
85
+ and status = 'ACTIVE'
86
+ and created_by ?= aspect user;
87
+ ```
88
+
89
+ ## Combining Conditions — OR
90
+
91
+ ```sql
92
+ where status = 'PUBLIC'
93
+ or created_by ?= aspect user;
94
+ ```
95
+
96
+ ## Complex Logic
97
+
98
+ ```sql
99
+ where (
100
+ (bukrs) = aspect pfcg_auth(F_BKPF_BUK, BUKRS, ACTVT = '03')
101
+ and status = 'ACTIVE'
102
+ )
103
+ or status = 'PUBLIC';
104
+ ```
105
+
106
+ ## Sales Org + Status Filter
107
+
108
+ ```sql
109
+ @MappingRole: true
110
+ define role Z_SALES_FILTER_DCL {
111
+ grant select on Z_SALES_ORDER
112
+ where (vkorg, vtweg, spart) =
113
+ aspect pfcg_auth(V_VBAK_VKO, VKORG, VTWEG, SPART, ACTVT = '03')
114
+ and status <> 'DELETED';
115
+ }
116
+ ```
117
+
118
+ ## Public + Owned Records
119
+
120
+ ```sql
121
+ @MappingRole: true
122
+ define role Z_MIXED_DCL {
123
+ grant select on Z_DOCUMENTS
124
+ where visibility = 'PUBLIC'
125
+ or created_by ?= aspect user;
126
+ }
127
+ ```
128
+
129
+ ## Multi-level Authorization
130
+
131
+ ```sql
132
+ @MappingRole: true
133
+ define role Z_MATERIAL_DCL {
134
+ grant select on Z_MATERIAL_DATA
135
+ where (werks) = aspect pfcg_auth(M_MATE_WRK, WERKS, ACTVT = '03')
136
+ and (mtart) = aspect pfcg_auth(M_MATE_MAR, MTART, ACTVT = '03');
137
+ }
138
+ ```
139
+
140
+ ## CDS View Annotation
141
+
142
+ ```sql
143
+ @AccessControl.authorizationCheck: #CHECK
144
+ define view Z_SECURED as select from ...
145
+ ```
146
+
147
+ | Value | Behavior |
148
+ |-------|----------|
149
+ | `#NOT_REQUIRED` | No DCL needed, full access |
150
+ | `#CHECK` | Warning if DCL missing |
151
+ | `#MANDATORY` | Syntax error if DCL missing |
152
+ | `#NOT_ALLOWED` | DCL ignored |
153
+
154
+ ## Common Authorization Objects
155
+
156
+ | Object | Fields | Domain |
157
+ |--------|--------|--------|
158
+ | `F_BKPF_BUK` | BUKRS, ACTVT | Company code |
159
+ | `F_BKPF_GSB` | GSBER, ACTVT | Business area |
160
+ | `V_VBAK_VKO` | VKORG, VTWEG, SPART, ACTVT | Sales org |
161
+ | `V_VBAK_AAT` | AUART, ACTVT | Order type |
162
+ | `M_MATE_WRK` | WERKS, ACTVT | Plant |
163
+ | `M_MATE_MAR` | MTART, ACTVT | Material type |
164
+ | `K_CCA` | KOKRS, KOSTL, ACTVT | Cost center |
165
+ | `K_ORDER` | AUFNR, ACTVT | Internal order |
166
+
167
+ ## Activity Values (ACTVT)
168
+
169
+ | Value | Activity |
170
+ |-------|----------|
171
+ | `01` | Create |
172
+ | `02` | Change |
173
+ | `03` | Display |
174
+ | `06` | Delete |
175
+ | `16` | Execute |
176
+
177
+ Most CDS views use `ACTVT = '03'`.
178
+
179
+ ## ABAP — Bypass Check
180
+
181
+ ```abap
182
+ " DCL automatically applied
183
+ SELECT * FROM z_secured INTO TABLE @DATA(lt_data).
184
+
185
+ " BYPASSING BUFFER does NOT bypass DCL
186
+ " There is no way to bypass DCL from ABAP
187
+ ```
188
+
189
+ ## Full Example — Sales Order DCL
190
+
191
+ ```sql
192
+ @EndUserText.label: 'Sales Order Access Control'
193
+ @MappingRole: true
194
+ define role Z_SO_FULL_DCL {
195
+ grant select on Z_SALES_ORDER
196
+ where (vkorg, vtweg, spart) =
197
+ aspect pfcg_auth(V_VBAK_VKO, VKORG, VTWEG, SPART, ACTVT = '03')
198
+ and (bukrs) = aspect pfcg_auth(F_BKPF_BUK, BUKRS, ACTVT = '03')
199
+ and status <> 'DELETED';
200
+ }
201
+ ```
202
+
203
+ ## Hierarchy Pattern — Consistent DCL
204
+
205
+ ```sql
206
+ -- Interface view
207
+ @MappingRole: true
208
+ define role Z_I_SO_DCL {
209
+ grant select on Z_I_SALES_ORDER
210
+ where (bukrs) = aspect pfcg_auth(F_BKPF_BUK, BUKRS, ACTVT = '03');
211
+ }
212
+
213
+ -- Consumption view (same auth, different entity)
214
+ @MappingRole: true
215
+ define role Z_C_SO_DCL {
216
+ grant select on Z_C_SALES_ORDER
217
+ where (bukrs) = aspect pfcg_auth(F_BKPF_BUK, BUKRS, ACTVT = '03');
218
+ }
219
+ ```
220
+
221
+ ## Rules
222
+
223
+ - `@MappingRole: true` is required on every DCL role
224
+ - DCL does NOT inherit to consuming views — each view needs its own DCL
225
+ - Use `?=` (optional operator) for fields that may be NULL/initial
226
+ - Most CDS views use ACTVT = '03' (display)
227
+ - Use `#CHECK` or `#MANDATORY` on sensitive views
228
+ - Create DCL for all views in a hierarchy, not just the base
229
+ - Find auth objects in SU21, test with SU53
230
+
231
+ ## Anti-Patterns
232
+
233
+ | Anti-Pattern | Correct |
234
+ |---|---|
235
+ | `#NOT_REQUIRED` on sensitive data | Use `#CHECK` or `#MANDATORY` |
236
+ | Assuming DCL inheritance from base view | Create DCL per view in chain |
237
+ | Using `=` instead of `?=` when field can be NULL | Use `?=` for nullable fields |
238
+ | Missing `@MappingRole: true` | Always add — required for role mapping |
239
+ | Complex OR chains without parentheses | Use explicit parentheses for logic clarity |
240
+ | Relying only on app-level auth checks | Add DCL as defense in depth |
241
+ | Using ACTVT = '02' for read-only views | Use ACTVT = '03' for display |