@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,331 @@
1
+ # CDS Annotations — view entity, element, header
2
+
3
+ ## Syntax
4
+
5
+ ```sql
6
+ -- Header level (before define)
7
+ @AnnotationName: value
8
+
9
+ -- Element level (before field)
10
+ @AnnotationName.property: value
11
+
12
+ -- Array
13
+ @AnnotationName: [{ property1: value1, property2: value2 }]
14
+ ```
15
+
16
+ ## AccessControl
17
+
18
+ ```sql
19
+ @AccessControl.authorizationCheck: #CHECK
20
+ define view entity ZI_Order as select from ztab_order
21
+ ```
22
+
23
+ | Value | Effect |
24
+ |-------|--------|
25
+ | `#NOT_REQUIRED` | No DCL needed |
26
+ | `#CHECK` | Warning if DCL missing |
27
+ | `#MANDATORY` | Syntax error if DCL missing |
28
+ | `#NOT_ALLOWED` | DCL ignored |
29
+
30
+ ## Metadata
31
+
32
+ ```sql
33
+ @Metadata.allowExtensions: true
34
+ define view entity ZI_Order as select from ztab_order
35
+ ```
36
+
37
+ Allows Metadata Extensions (DDLX) to add UI annotations separately.
38
+
39
+ ## EndUserText
40
+
41
+ ```sql
42
+ @EndUserText.label: 'Sales Order'
43
+ define view entity ZI_SalesOrder as select from vbak
44
+ {
45
+ @EndUserText.label: 'Order Number'
46
+ @EndUserText.quickInfo: 'Unique sales document identifier'
47
+ vbeln as SalesOrder
48
+ }
49
+ ```
50
+
51
+ ## Semantics — Currency and Amount
52
+
53
+ ```sql
54
+ {
55
+ @Semantics.currencyCode: true
56
+ currency_code as CurrencyCode,
57
+
58
+ @Semantics.amount.currencyCode: 'CurrencyCode'
59
+ total_price as TotalPrice
60
+ }
61
+ ```
62
+
63
+ ## Semantics — Quantity and Unit
64
+
65
+ ```sql
66
+ {
67
+ @Semantics.unitOfMeasure: true
68
+ unit as Unit,
69
+
70
+ @Semantics.quantity.unitOfMeasure: 'Unit'
71
+ quantity as Quantity
72
+ }
73
+ ```
74
+
75
+ ## Semantics — Administrative Fields (RAP)
76
+
77
+ ```sql
78
+ {
79
+ @Semantics.user.createdBy: true
80
+ created_by as CreatedBy,
81
+
82
+ @Semantics.systemDateTime.createdAt: true
83
+ created_at as CreatedAt,
84
+
85
+ @Semantics.user.localInstanceLastChangedBy: true
86
+ last_changed_by as LastChangedBy,
87
+
88
+ @Semantics.systemDateTime.localInstanceLastChangedAt: true
89
+ last_changed_at as LastChangedAt,
90
+
91
+ @Semantics.systemDateTime.lastChangedAt: true
92
+ local_last_changed_at as LocalLastChangedAt
93
+ }
94
+ ```
95
+
96
+ - `lastChangedAt` → etag master (per-record)
97
+ - `localInstanceLastChangedAt` → total etag (per-BO, includes child changes)
98
+
99
+ ## Semantics — Boolean, Language, Text
100
+
101
+ ```sql
102
+ @Semantics.booleanIndicator: true
103
+ is_active as IsActive,
104
+
105
+ @Semantics.language: true
106
+ language as Language,
107
+
108
+ @Semantics.text: true
109
+ description as Description
110
+ ```
111
+
112
+ ## UI — List Report (lineItem + selectionField)
113
+
114
+ ```sql
115
+ {
116
+ @UI.lineItem: [{ position: 10, importance: #HIGH }]
117
+ @UI.selectionField: [{ position: 10 }]
118
+ SalesOrder,
119
+
120
+ @UI.lineItem: [{ position: 20 }]
121
+ CreatedAt,
122
+
123
+ @UI.hidden: true
124
+ InternalID
125
+ }
126
+ ```
127
+
128
+ ## UI — Object Page (headerInfo + facets + fieldGroup)
129
+
130
+ ```sql
131
+ @UI.headerInfo: {
132
+ typeName: 'Sales Order',
133
+ typeNamePlural: 'Sales Orders',
134
+ title: { value: 'SalesOrder' },
135
+ description: { value: 'CustomerName' }
136
+ }
137
+
138
+ @UI.facet: [
139
+ { id: 'General', type: #IDENTIFICATION_REFERENCE, label: 'General', position: 10 },
140
+ { id: 'Items', type: #LINEITEM_REFERENCE, label: 'Items', position: 20,
141
+ targetElement: '_Item' },
142
+ { id: 'Details', type: #FIELDGROUP_REFERENCE, label: 'Details', position: 30,
143
+ targetQualifier: 'DetailInfo' }
144
+ ]
145
+
146
+ {
147
+ @UI.identification: [{ position: 10 }]
148
+ SalesOrder,
149
+
150
+ @UI.identification: [{ position: 20 }]
151
+ CustomerName,
152
+
153
+ @UI.fieldGroup: [{ qualifier: 'DetailInfo', position: 10 }]
154
+ PaymentTerms,
155
+
156
+ @UI.dataPoint: { qualifier: 'Status', title: 'Order Status' }
157
+ @UI.textArrangement: #TEXT_ONLY
158
+ OverallStatus
159
+ }
160
+ ```
161
+
162
+ `#TEXT_FIRST` | `#TEXT_LAST` | `#TEXT_ONLY` | `#TEXT_SEPARATE`
163
+
164
+ ## Consumption — Value Help
165
+
166
+ ```sql
167
+ @Consumption.valueHelpDefinition: [{
168
+ entity: { name: 'I_Currency', element: 'Currency' },
169
+ additionalBinding: [{
170
+ localElement: 'CompanyCode',
171
+ element: 'CompanyCode',
172
+ usage: #FILTER_AND_RESULT
173
+ }]
174
+ }]
175
+ CurrencyCode;
176
+ ```
177
+
178
+ → see fiori-valuelist.md for complete reference
179
+
180
+ ## Consumption — Filter
181
+
182
+ ```sql
183
+ @Consumption.filter: {
184
+ selectionType: #RANGE,
185
+ multipleSelections: true,
186
+ mandatory: true
187
+ }
188
+ CompanyCode;
189
+ ```
190
+
191
+ ## ObjectModel
192
+
193
+ ```sql
194
+ @ObjectModel.text.element: ['StatusText']
195
+ OverallStatus,
196
+
197
+ @ObjectModel.text.association: '_StatusText'
198
+ OverallStatus,
199
+
200
+ @ObjectModel.foreignKey.association: '_Customer'
201
+ CustomerID,
202
+
203
+ @ObjectModel.composition: true
204
+ _Item
205
+ ```
206
+
207
+ ## Search
208
+
209
+ ```sql
210
+ @Search.searchable: true
211
+ define view entity ZC_Order as projection on ZI_Order
212
+ {
213
+ @Search.defaultSearchElement: true
214
+ @Search.fuzzinessThreshold: 0.8
215
+ @Search.ranking: #HIGH
216
+ SalesOrder,
217
+
218
+ @Search.defaultSearchElement: true
219
+ @Search.ranking: #MEDIUM
220
+ Description
221
+ }
222
+ ```
223
+
224
+ ## Analytics
225
+
226
+ ```sql
227
+ @Analytics.dataCategory: #FACT
228
+ define view entity ZI_SalesFact as select from vbap
229
+ {
230
+ @DefaultAggregation: #SUM
231
+ total_price as TotalPrice,
232
+
233
+ @DefaultAggregation: #COUNT
234
+ item_number as ItemCount
235
+ }
236
+ ```
237
+
238
+ `#DIMENSION` | `#FACT` | `#CUBE`
239
+ `#SUM` | `#MIN` | `#MAX` | `#AVG` | `#COUNT`
240
+
241
+ ## Environment — Parameter Defaults
242
+
243
+ ```sql
244
+ define view entity ZI_WithDefaults
245
+ with parameters
246
+ @Environment.systemField: #SYSTEM_DATE
247
+ p_date : abap.dats,
248
+ @Environment.systemField: #SYSTEM_LANGUAGE
249
+ p_lang : spras,
250
+ @Environment.systemField: #USER
251
+ p_user : syuname
252
+ as select from ztab
253
+ ```
254
+
255
+ ## Full Annotated View Entity Example
256
+
257
+ ```sql
258
+ @AccessControl.authorizationCheck: #CHECK
259
+ @EndUserText.label: 'Sales Order'
260
+ @Metadata.allowExtensions: true
261
+ @Search.searchable: true
262
+ define view entity ZI_SalesOrder
263
+ as select from vbak as h
264
+ composition [0..*] of ZI_SalesOrderItem as _Item
265
+ association [0..1] to kna1 as _Customer
266
+ on $projection.CustomerID = _Customer.kunnr
267
+ association [0..1] to I_Currency as _Currency
268
+ on $projection.CurrencyCode = _Currency.Currency
269
+ {
270
+ @UI.lineItem: [{ position: 10, importance: #HIGH }]
271
+ @UI.selectionField: [{ position: 10 }]
272
+ @Search.defaultSearchElement: true
273
+ key h.vbeln as SalesOrder,
274
+
275
+ @UI.lineItem: [{ position: 20 }]
276
+ @UI.selectionField: [{ position: 20 }]
277
+ @ObjectModel.foreignKey.association: '_Customer'
278
+ h.kunnr as CustomerID,
279
+
280
+ @UI.lineItem: [{ position: 30 }]
281
+ h.erdat as CreatedAt,
282
+
283
+ @Semantics.currencyCode: true
284
+ h.waers as CurrencyCode,
285
+
286
+ @UI.lineItem: [{ position: 40 }]
287
+ @Semantics.amount.currencyCode: 'CurrencyCode'
288
+ h.netwr as NetAmount,
289
+
290
+ @Semantics.user.createdBy: true
291
+ h.ernam as CreatedBy,
292
+
293
+ @ObjectModel.text.element: ['CustomerName']
294
+ _Customer.name1 as CustomerName,
295
+
296
+ _Item,
297
+ _Customer,
298
+ _Currency
299
+ }
300
+ ```
301
+
302
+ ## Annotation Placement
303
+
304
+ | Level | Position | Example |
305
+ |-------|----------|---------|
306
+ | Header | Before `define view entity` | `@AccessControl.authorizationCheck` |
307
+ | Element | Before field in projection | `@UI.lineItem` |
308
+ | Parameter | Before parameter definition | `@Environment.systemField` |
309
+
310
+ ## Rules
311
+
312
+ - Always set `@AccessControl.authorizationCheck` on every view entity
313
+ - Always annotate CURR fields with `@Semantics.amount.currencyCode`
314
+ - Always annotate QUAN fields with `@Semantics.quantity.unitOfMeasure`
315
+ - Number `position` values by 10s for easy insertion
316
+ - Use `@ObjectModel.text.element` for code-text field pairs
317
+ - Use `@Metadata.allowExtensions: true` to enable Metadata Extensions (DDLX)
318
+ - Use `define view entity` (not legacy `define view`) for new development
319
+ - `@AbapCatalog.sqlViewName` is NOT needed for view entities (only legacy `define view`)
320
+
321
+ ## Anti-Patterns
322
+
323
+ | Anti-Pattern | Correct |
324
+ |---|---|
325
+ | Missing `@Semantics.amount.currencyCode` on CURR field | Always pair amount with currency reference |
326
+ | `@AccessControl.authorizationCheck: #NOT_REQUIRED` on sensitive data | Use `#CHECK` or `#MANDATORY` |
327
+ | `@UI.lineItem` position: 1, 2, 3 | Use 10, 20, 30 for insertion gaps |
328
+ | Skipping `@Semantics.unitOfMeasure` on QUAN field | Always pair quantity with unit reference |
329
+ | Using `@UI.hidden` when field is never needed | Omit from projection entirely |
330
+ | Using `define view` with `@AbapCatalog.sqlViewName` for new development | Use `define view entity` (no sqlViewName needed) |
331
+ | UI annotations in interface CDS (ZI_*) | Use `@Metadata.allowExtensions` + Metadata Extension (DDLX) |
@@ -0,0 +1,254 @@
1
+ # CDS Associations — Join-on-Demand Relationship Definitions
2
+
3
+ ## Syntax
4
+
5
+ ```sql
6
+ define view Z_ORDER as select from vbak as h
7
+ association [cardinality] to target as _Alias
8
+ on condition
9
+ {
10
+ key h.vbeln,
11
+ _Alias
12
+ }
13
+ ```
14
+
15
+ ## Cardinality
16
+
17
+ | Syntax | Meaning | Join |
18
+ |--------|---------|------|
19
+ | `[0..1]` | Zero or one | LEFT OUTER MANY TO ONE |
20
+ | `[1]` | Shorthand for [0..1] | LEFT OUTER MANY TO ONE |
21
+ | `[1..1]` | Exactly one | LEFT OUTER MANY TO ONE |
22
+ | `[0..*]` | Zero or more | LEFT OUTER MANY TO MANY |
23
+ | `[*]` | Shorthand for [0..*] | LEFT OUTER MANY TO MANY |
24
+ | `[1..*]` | One or more | LEFT OUTER MANY TO MANY |
25
+ | (omitted) | Default [0..1] | LEFT OUTER MANY TO ONE |
26
+
27
+ ### New Syntax (S/4HANA 2302+ / NW 7.57+)
28
+
29
+ ```sql
30
+ association to one _Target on ...
31
+ association to many _Targets on ...
32
+ ```
33
+
34
+ ## Cardinality Examples
35
+
36
+ ```sql
37
+ -- Optional single record
38
+ association [0..1] to kna1 as _Customer
39
+ on $projection.kunnr = _Customer.kunnr
40
+
41
+ -- Required single record
42
+ association [1..1] to t001 as _Company
43
+ on $projection.bukrs = _Company.bukrs
44
+
45
+ -- Multiple records
46
+ association [0..*] to vbap as _Items
47
+ on $projection.vbeln = _Items.vbeln
48
+
49
+ -- At least one
50
+ association [1..*] to spfli as _Flights
51
+ on $projection.carrid = _Flights.carrid
52
+ ```
53
+
54
+ ## Join Conditions
55
+
56
+ ### Using $projection
57
+
58
+ ```sql
59
+ association [0..1] to makt as _Text
60
+ on $projection.matnr = _Text.matnr
61
+ and $projection.spras = _Text.spras
62
+ ```
63
+
64
+ ### Using Source Alias
65
+
66
+ ```sql
67
+ define view Z_MAT as select from mara as m
68
+ association [0..1] to makt as _Text
69
+ on m.matnr = _Text.matnr
70
+ ```
71
+
72
+ ### Complex Condition
73
+
74
+ ```sql
75
+ association [0..*] to zcond as _Prices
76
+ on $projection.matnr = _Prices.matnr
77
+ and $projection.vkorg = _Prices.vkorg
78
+ and _Prices.valid_from <= $session.system_date
79
+ and _Prices.valid_to >= $session.system_date
80
+ ```
81
+
82
+ ## Exposing Associations
83
+
84
+ ### Direct
85
+
86
+ ```sql
87
+ { key vbeln, _Customer, _Items }
88
+ ```
89
+
90
+ ### Redirected
91
+
92
+ ```sql
93
+ _Customer : redirected to Z_CUSTOMER_VIEW
94
+ ```
95
+
96
+ ### Filtered
97
+
98
+ ```sql
99
+ _Items[Status = 'ACTIVE'] as _ActiveItems
100
+ ```
101
+
102
+ ## Using Associations — Field Access
103
+
104
+ ```sql
105
+ {
106
+ key vbeln,
107
+ _Customer.name1 as CustomerName,
108
+ _Customer.ort01 as CustomerCity
109
+ }
110
+ ```
111
+
112
+ ## Path Expressions
113
+
114
+ ```sql
115
+ -- Multi-level navigation
116
+ _Header._Customer._Country.name as CountryName
117
+
118
+ -- Path filter with cardinality indicator
119
+ _Items[1: ItemNumber = '000010'].Material as FirstItemMaterial
120
+ ```
121
+
122
+ ## Association vs Join
123
+
124
+ ### Association (join-on-demand)
125
+
126
+ ```sql
127
+ define view Z_WITH_ASSOC as select from vbak
128
+ association [0..1] to kna1 as _Customer
129
+ on $projection.kunnr = _Customer.kunnr
130
+ {
131
+ key vbeln,
132
+ kunnr,
133
+ _Customer -- join NOT executed until fields accessed
134
+ }
135
+ -- SELECT vbeln, kunnr FROM z_with_assoc => no join
136
+ ```
137
+
138
+ ### Join (always executed)
139
+
140
+ ```sql
141
+ define view Z_WITH_JOIN as select from vbak as v
142
+ left outer join kna1 as c on v.kunnr = c.kunnr
143
+ {
144
+ key v.vbeln,
145
+ v.kunnr,
146
+ c.name1 -- join ALWAYS executed
147
+ }
148
+ -- SELECT vbeln, kunnr FROM z_with_join => join runs anyway
149
+ ```
150
+
151
+ ## Text Association Pattern
152
+
153
+ ```sql
154
+ association [0..1] to makt as _Text
155
+ on $projection.matnr = _Text.matnr
156
+ and _Text.spras = $session.system_language
157
+ {
158
+ key matnr,
159
+ _Text.maktx as MaterialDescription
160
+ }
161
+ ```
162
+
163
+ ## Self-Reference / Hierarchy
164
+
165
+ ```sql
166
+ define view Z_ORG as select from zorg_unit as o
167
+ association [0..1] to Z_ORG as _Parent
168
+ on $projection.parent_id = _Parent.org_id
169
+ association [0..*] to Z_ORG as _Children
170
+ on $projection.org_id = _Children.parent_id
171
+ {
172
+ key org_id,
173
+ parent_id,
174
+ name,
175
+ _Parent,
176
+ _Children
177
+ }
178
+ ```
179
+
180
+ ## Propagated Associations
181
+
182
+ ```sql
183
+ -- Base view
184
+ define view Z_BASE as select from mara
185
+ association [0..1] to makt as _Text on ...
186
+ { key matnr, _Text }
187
+
188
+ -- Consumer: _Text propagated automatically
189
+ define view Z_CONSUMER as select from Z_BASE
190
+ { key matnr, _Text }
191
+ ```
192
+
193
+ Block propagation:
194
+
195
+ ```sql
196
+ @Metadata.ignorePropagatedAnnotations: true
197
+ define view Z_NO_PROP as select from Z_BASE
198
+ { key matnr } -- _Text NOT available
199
+ ```
200
+
201
+ ## Composition (RAP)
202
+
203
+ ```sql
204
+ define view entity Z_SO_HDR as select from vbak
205
+ composition [0..*] of Z_SO_ITEM as _Items
206
+ {
207
+ key vbeln,
208
+ erdat,
209
+ _Items
210
+ }
211
+
212
+ define view entity Z_SO_ITEM as select from vbap
213
+ association to parent Z_SO_HDR as _Header
214
+ on $projection.vbeln = _Header.vbeln
215
+ {
216
+ key vbeln,
217
+ key posnr,
218
+ matnr,
219
+ _Header
220
+ }
221
+ ```
222
+
223
+ ## ABAP Consumption
224
+
225
+ ```abap
226
+ SELECT
227
+ vbeln,
228
+ \_Customer-name1 AS customer_name,
229
+ \_Customer-ort01 AS city
230
+ FROM z_sales_order
231
+ INTO TABLE @DATA(lt_result).
232
+ ```
233
+
234
+ ## Rules
235
+
236
+ - Prefix association aliases with underscore: `_Customer`, `_Items`
237
+ - Use `[0..1]` for to-one, `[0..*]` for to-many
238
+ - Set correct cardinality to avoid duplicate rows and enable HANA optimization
239
+ - Use associations over joins when fields are optional or for OData/RAP
240
+ - Use joins when all fields are always needed or for aggregation
241
+ - Always expose associations in the projection list
242
+ - Use `$projection` in ON conditions for reusability
243
+
244
+ ## Anti-Patterns
245
+
246
+ | Anti-Pattern | Correct |
247
+ |---|---|
248
+ | `association [0..*]` when target is always single record | Use `[0..1]` for HANA join pruning |
249
+ | Not exposing association in field list | Always add `_Alias` to projection |
250
+ | Deep path chains (5+ levels) | Flatten with intermediate views |
251
+ | Using join for optional lookup | Use association for join-on-demand |
252
+ | Missing `_Text.spras = $session.system_language` in text assoc | Always filter on language |
253
+ | Association alias without underscore prefix | Use `_Customer` not `Customer` |
254
+ | `association [1..1]` when data may not exist | Use `[0..1]` for nullable FKs |