@cap-js/change-tracking 2.0.0-beta.2 → 2.0.0-beta.4

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.
package/index.cds CHANGED
@@ -33,27 +33,18 @@ entity aspect @(UI.Facets: [{
33
33
  view ChangeView as
34
34
  select from Changes as change
35
35
  left outer join i18nKeys as attributeI18n
36
- on attributeI18n.ID = change.attribute
37
- and (
38
- attributeI18n.locale = $user.locale
39
- or attributeI18n.locale = 'en'
40
- )
36
+ on attributeI18n.ID = change.attribute
37
+ and attributeI18n.locale = $user.locale
41
38
  left outer join i18nKeys as entityI18n
42
- on entityI18n.ID = change.entity
43
- and (
44
- entityI18n.locale = $user.locale
45
- or entityI18n.locale = 'en'
46
- )
39
+ on entityI18n.ID = change.entity
40
+ and entityI18n.locale = $user.locale
47
41
  left outer join i18nKeys as modificationI18n
48
- on modificationI18n.ID = change.modification
49
- and (
50
- modificationI18n.locale = $user.locale
51
- or modificationI18n.locale = 'en'
52
- )
42
+ on modificationI18n.ID = change.modification
43
+ and modificationI18n.locale = $user.locale
53
44
  {
54
- key change.ID @UI.Hidden,
55
- change.parent: redirected to ChangeView,
56
- change.children: redirected to ChangeView,
45
+ key change.ID @UI.Hidden,
46
+ change.parent : redirected to ChangeView,
47
+ change.children : redirected to ChangeView,
57
48
  change.attribute,
58
49
  change.valueChangedFrom,
59
50
  change.valueChangedTo,
@@ -66,25 +57,174 @@ view ChangeView as
66
57
  change.createdBy,
67
58
  change.transactionID,
68
59
  COALESCE(
69
- attributeI18n.text, change.attribute
70
- ) as attributeLabel : String(15) @title: '{i18n>Changes.attribute}',
60
+ attributeI18n.text, (
61
+ select text from i18nKeys
62
+ where
63
+ ID = change.attribute
64
+ and locale = 'en'
65
+ ), change.attribute
66
+ ) as attributeLabel : String(15) @title: '{i18n>Changes.attribute}',
71
67
  COALESCE(
72
- entityI18n.text, change.entity
73
- ) as entityLabel : String(24) @title: '{i18n>Changes.entity}',
68
+ entityI18n.text, (
69
+ select text from i18nKeys
70
+ where
71
+ ID = change.entity
72
+ and locale = 'en'
73
+ ), change.entity
74
+ ) as entityLabel : String(24) @title: '{i18n>Changes.entity}',
74
75
  COALESCE(
75
- modificationI18n.text, change.modification
76
- ) as modificationLabel : String(16) @title: '{i18n>Changes.modification}',
76
+ modificationI18n.text, (
77
+ select text from i18nKeys
78
+ where
79
+ ID = change.modification
80
+ and locale = 'en'
81
+ ), change.modification
82
+ ) as modificationLabel : String(16) @title: '{i18n>Changes.modification}',
77
83
  COALESCE(
78
84
  change.valueChangedFromLabel, change.valueChangedFrom
79
- ) as valueChangedFromLabel : String(5000) @title: '{i18n>Changes.valueChangedFrom}',
85
+ ) as valueChangedFromLabel : String(5000) @(
86
+ title: '{i18n>Changes.valueChangedFrom}',
87
+ UI.MultiLineText
88
+ ),
89
+ (
90
+ case
91
+ when valueDataType = 'cds.DateTime'
92
+ then COALESCE(
93
+ change.valueChangedFromLabel, change.valueChangedFrom
94
+ )
95
+ else null
96
+ end
97
+ ) as valueChangedFromLabelDateTime : DateTime @(title: '{i18n>Changes.valueChangedFrom}',
98
+ ),
99
+ (
100
+ case
101
+ when valueDataType = 'cds.DateTime' or valueDataType = 'cds.Timestamp'
102
+ then COALESCE(
103
+ change.valueChangedFromLabel, change.valueChangedFrom
104
+ )
105
+ else null
106
+ end
107
+ ) as valueChangedFromLabelDateTimeWTZ : DateTime @(
108
+ title : '{i18n>Changes.valueChangedFrom}',
109
+ Common.Timezone: valueTimeZone
110
+ ),
111
+ (
112
+ case
113
+ when valueDataType = 'cds.Time'
114
+ then COALESCE(
115
+ change.valueChangedFromLabel, change.valueChangedFrom
116
+ )
117
+ else null
118
+ end
119
+ ) as valueChangedFromLabelTime : Time @(title: '{i18n>Changes.valueChangedFrom}',
120
+ ),
121
+ (
122
+ case
123
+ when valueDataType = 'cds.Date'
124
+ then COALESCE(
125
+ change.valueChangedFromLabel, change.valueChangedFrom
126
+ )
127
+ else null
128
+ end
129
+ ) as valueChangedFromLabelDate : Date @(title: '{i18n>Changes.valueChangedFrom}',
130
+ ),
131
+ (
132
+ case
133
+ when valueDataType = 'cds.Timestamp'
134
+ then COALESCE(
135
+ change.valueChangedFromLabel, change.valueChangedFrom
136
+ )
137
+ else null
138
+ end
139
+ ) as valueChangedFromLabelTimestamp : Timestamp @(title: '{i18n>Changes.valueChangedFrom}',
140
+ ),
141
+ (
142
+ case
143
+ when valueDataType = 'cds.Decimal'
144
+ then COALESCE(
145
+ change.valueChangedFromLabel, change.valueChangedFrom
146
+ )
147
+ else null
148
+ end
149
+ ) as valueChangedFromLabelDecimal : Decimal @(title: '{i18n>Changes.valueChangedFrom}',
150
+ ),
80
151
  COALESCE(
81
152
  change.valueChangedToLabel, change.valueChangedTo
82
- ) as valueChangedToLabel : String(5000) @title: '{i18n>Changes.valueChangedTo}',
153
+ ) as valueChangedToLabel : String(5000) @(
154
+ title: '{i18n>Changes.valueChangedTo}',
155
+ UI.MultiLineText
156
+ ),
157
+ (
158
+ case
159
+ when valueDataType = 'cds.DateTime'
160
+ then COALESCE(
161
+ change.valueChangedToLabel, change.valueChangedTo
162
+ )
163
+ else null
164
+ end
165
+ ) as valueChangedToLabelDateTime : DateTime @(title: '{i18n>Changes.valueChangedTo}',
166
+ ),
167
+ (
168
+ case
169
+ when valueDataType = 'cds.DateTime' or valueDataType = 'cds.Timestamp'
170
+ then COALESCE(
171
+ change.valueChangedFromLabel, change.valueChangedTo
172
+ )
173
+ else null
174
+ end
175
+ ) as valueChangedToLabelDateTimeWTZ : DateTime @(
176
+ title : '{i18n>Changes.valueChangedTo}',
177
+ Common.Timezone: valueTimeZone
178
+ ),
179
+ (
180
+ case
181
+ when valueDataType = 'cds.Time'
182
+ then COALESCE(
183
+ change.valueChangedToLabel, change.valueChangedTo
184
+ )
185
+ else null
186
+ end
187
+ ) as valueChangedToLabelTime : Time @(title: '{i18n>Changes.valueChangedTo}',
188
+ ),
189
+ (
190
+ case
191
+ when valueDataType = 'cds.Date'
192
+ then COALESCE(
193
+ change.valueChangedToLabel, change.valueChangedTo
194
+ )
195
+ else null
196
+ end
197
+ ) as valueChangedToLabelDate : Date @(title: '{i18n>Changes.valueChangedTo}',
198
+ ),
199
+ (
200
+ case
201
+ when valueDataType = 'cds.Timestamp'
202
+ then COALESCE(
203
+ change.valueChangedToLabel, change.valueChangedTo
204
+ )
205
+ else null
206
+ end
207
+ ) as valueChangedToLabelTimestamp : Timestamp @(title: '{i18n>Changes.valueChangedTo}',
208
+ ),
209
+ (
210
+ case
211
+ when valueDataType = 'cds.Decimal'
212
+ then COALESCE(
213
+ change.valueChangedToLabel, change.valueChangedTo
214
+ )
215
+ else null
216
+ end
217
+ ) as valueChangedToLabelDecimal : Decimal @(title: '{i18n>Changes.valueChangedTo}',
218
+ ),
219
+ null as valueTimeZone : String @(
220
+ UI.Hidden,
221
+ Common.IsTimezone
222
+ ),
83
223
  // For the hierarchy
84
- null as LimitedDescendantCount : Int16 @UI.Hidden,
85
- null as DistanceFromRoot : Int16 @UI.Hidden,
86
- null as DrillState : String @UI.Hidden,
87
- null as LimitedRank : Int16 @UI.Hidden,
224
+ null as LimitedDescendantCount : Int16 @UI.Hidden,
225
+ null as DistanceFromRoot : Int16 @UI.Hidden,
226
+ null as DrillState : String @UI.Hidden,
227
+ null as LimitedRank : Int16 @UI.Hidden,
88
228
  };
89
229
 
90
230
  entity i18nKeys {
@@ -93,7 +233,7 @@ entity i18nKeys {
93
233
  text : String(5000);
94
234
  }
95
235
 
96
- // Dummy table necessary for HANA triggers
236
+ // Dummy table necessary for HANA triggers because DUMMY cannot be used in HDI
97
237
  @cds.persistence.skip
98
238
  entity CHANGE_TRACKING_DUMMY {
99
239
  key X : String(5);
@@ -162,11 +302,15 @@ annotate ChangeView with @(UI: {
162
302
  @UI.Importance: #Medium
163
303
  },
164
304
  {
165
- Value : valueChangedToLabel,
305
+ $Type : 'UI.DataFieldForAnnotation',
306
+ Target : '@UI.FieldGroup#valueChangedTo',
307
+ Label : '{i18n>Changes.valueChangedTo}',
166
308
  @UI.Importance: #High
167
309
  },
168
310
  {
169
- Value : valueChangedFromLabel,
311
+ $Type : 'UI.DataFieldForAnnotation',
312
+ Target : '@UI.FieldGroup#valueChangedFrom',
313
+ Label : '{i18n>Changes.valueChangedFrom}',
170
314
  @UI.Importance: #High
171
315
  },
172
316
  {
@@ -179,13 +323,103 @@ annotate ChangeView with @(UI: {
179
323
  },
180
324
  ],
181
325
  DeleteHidden : true,
326
+ FieldGroup #valueChangedFrom : {
327
+ Label: '{i18n>Changes.valueChangedFrom}',
328
+ Data : [
329
+ {
330
+ Value : valueChangedFromLabel,
331
+ @UI.Hidden: ($self.valueDataType = 'cds.Decimal'
332
+ or $self.valueDataType = 'cds.DateTime'
333
+ or $self.valueDataType = 'cds.Date'
334
+ or $self.valueDataType = 'cds.Time'
335
+ or $self.valueDataType = 'cds.Timestamp')
336
+ },
337
+ {
338
+ Value : valueChangedFromLabelDateTime,
339
+ @UI.Hidden: ($self.valueDataType != 'cds.DateTime'
340
+ or $self.valueTimeZone != null)
341
+ },
342
+ {
343
+ Value : valueChangedFromLabelDateTimeWTZ,
344
+ @UI.Hidden: ($self.valueDataType != 'cds.DateTime'
345
+ or $self.valueTimeZone = null)
346
+ },
347
+ {
348
+ Value : valueChangedFromLabelDate,
349
+ @UI.Hidden: ($self.valueDataType != 'cds.Date')
350
+ },
351
+ {
352
+ Value : valueChangedFromLabelTime,
353
+ @UI.Hidden: ($self.valueDataType != 'cds.Time')
354
+ },
355
+ {
356
+ Value : valueChangedFromLabelTimestamp,
357
+ @UI.Hidden: ($self.valueDataType != 'cds.Timestamp')
358
+ },
359
+ {
360
+ Value : valueChangedFromLabelDecimal,
361
+ @UI.Hidden: ($self.valueDataType != 'cds.Decimal')
362
+ }
363
+ ]
364
+ },
365
+ FieldGroup #valueChangedTo : {
366
+ Label: '{i18n>Changes.valueChangedTo}',
367
+ Data : [
368
+ {
369
+ Value : valueChangedToLabel,
370
+ @UI.Hidden: ($self.valueDataType = 'cds.Decimal'
371
+ or $self.valueDataType = 'cds.DateTime'
372
+ or $self.valueDataType = 'cds.Date'
373
+ or $self.valueDataType = 'cds.Time'
374
+ or $self.valueDataType = 'cds.Timestamp')
375
+ },
376
+ {
377
+ Value : valueChangedToLabelDateTime,
378
+ @UI.Hidden: ($self.valueDataType != 'cds.DateTime'
379
+ or $self.valueTimeZone != null)
380
+ },
381
+ {
382
+ Value : valueChangedToLabelDateTimeWTZ,
383
+ @UI.Hidden: ($self.valueDataType != 'cds.DateTime'
384
+ or $self.valueTimeZone = null)
385
+ },
386
+ {
387
+ Value : valueChangedToLabelDate,
388
+ @UI.Hidden: ($self.valueDataType != 'cds.Date')
389
+ },
390
+ {
391
+ Value : valueChangedToLabelTime,
392
+ @UI.Hidden: ($self.valueDataType != 'cds.Time')
393
+ },
394
+ {
395
+ Value : valueChangedToLabelTimestamp,
396
+ @UI.Hidden: ($self.valueDataType != 'cds.Timestamp')
397
+ },
398
+ {
399
+ Value : valueChangedToLabelDecimal,
400
+ @UI.Hidden: ($self.valueDataType != 'cds.Decimal')
401
+ }
402
+ ]
403
+ }
182
404
  }) {
183
- valueChangedFrom @UI.Hidden;
184
- valueChangedTo @UI.Hidden;
185
- parent @UI.Hidden;
186
- entityKey @UI.Hidden;
187
- entity @UI.Hidden;
188
- attribute @UI.Hidden;
405
+ valueChangedFrom @UI.Hidden;
406
+ valueChangedFromLabelDate @UI.AdaptationHidden @UI.Hidden: ($self.valueDataType != 'cds.Date');
407
+ valueChangedFromLabelDateTime @UI.AdaptationHidden @UI.Hidden: ($self.valueDataType != 'cds.DateTime');
408
+ valueChangedFromLabelDateTimeWTZ @UI.AdaptationHidden @UI.Hidden: ($self.valueDataType != 'cds.DateTime');
409
+ valueChangedFromLabelTime @UI.AdaptationHidden @UI.Hidden: ($self.valueDataType != 'cds.Time');
410
+ valueChangedFromLabelTimestamp @UI.AdaptationHidden @UI.Hidden: ($self.valueDataType != 'cds.Timestamp');
411
+ valueChangedFromLabelDecimal @UI.AdaptationHidden @UI.Hidden: ($self.valueDataType != 'cds.Decimal');
412
+ valueChangedTo @UI.Hidden;
413
+ valueChangedToLabelDate @UI.AdaptationHidden @UI.Hidden: ($self.valueDataType != 'cds.Date');
414
+ valueChangedToLabelDateTime @UI.AdaptationHidden @UI.Hidden: ($self.valueDataType != 'cds.DateTime');
415
+ valueChangedToLabelDateTimeWTZ @UI.AdaptationHidden @UI.Hidden: ($self.valueDataType != 'cds.DateTime');
416
+ valueChangedToLabelTime @UI.AdaptationHidden @UI.Hidden: ($self.valueDataType != 'cds.Time');
417
+ valueChangedToLabelTimestamp @UI.AdaptationHidden @UI.Hidden: ($self.valueDataType != 'cds.Timestamp');
418
+ valueChangedToLabelDecimal @UI.AdaptationHidden @UI.Hidden: ($self.valueDataType != 'cds.Decimal');
419
+ parent @UI.Hidden;
420
+ entityKey @UI.Hidden;
421
+ entity @UI.Hidden;
422
+ attribute @UI.Hidden;
189
423
  };
190
424
 
191
425
  annotate ChangeView with @(
@@ -206,13 +440,64 @@ annotate ChangeView with @(
206
440
  'LimitedDescendantCount',
207
441
  'DistanceFromRoot',
208
442
  'DrillState',
209
- 'LimitedRank'
443
+ 'LimitedRank',
444
+ valueChangedFromLabelDate,
445
+ valueChangedFromLabelDateTime,
446
+ valueChangedFromLabelDateTimeWTZ,
447
+ valueChangedFromLabelTime,
448
+ valueChangedFromLabelTimestamp,
449
+ valueChangedFromLabelDecimal,
450
+ valueChangedToLabelDate,
451
+ valueChangedToLabelDateTime,
452
+ valueChangedToLabelDateTimeWTZ,
453
+ valueChangedToLabelTime,
454
+ valueChangedToLabelTimestamp,
455
+ valueChangedToLabelDecimal,
456
+ valueTimeZone
210
457
  ],
211
458
  // Disallow sorting on these properties from Fiori UIs
212
459
  Capabilities.SortRestrictions.NonSortableProperties : [
213
460
  'LimitedDescendantCount',
214
461
  'DistanceFromRoot',
215
462
  'DrillState',
216
- 'LimitedRank'
463
+ 'LimitedRank',
464
+ valueChangedFromLabelDate,
465
+ valueChangedFromLabelDateTime,
466
+ valueChangedFromLabelDateTimeWTZ,
467
+ valueChangedFromLabelTime,
468
+ valueChangedFromLabelTimestamp,
469
+ valueChangedFromLabelDecimal,
470
+ valueChangedToLabelDate,
471
+ valueChangedToLabelDateTime,
472
+ valueChangedToLabelDateTimeWTZ,
473
+ valueChangedToLabelTime,
474
+ valueChangedToLabelTimestamp,
475
+ valueChangedToLabelDecimal,
476
+ valueTimeZone
217
477
  ],
218
478
  );
479
+
480
+ // Annotations for searching
481
+ annotate ChangeView with @(cds.search: {
482
+ valueChangedFrom: false,
483
+ valueChangedTo : false,
484
+ entity : false,
485
+ attribute : false,
486
+ modification : false,
487
+ valueDataType : false,
488
+ modificationLabel,
489
+ entityLabel,
490
+ entityKey,
491
+ objectID,
492
+ attributeLabel,
493
+ valueChangedFromLabel,
494
+ valueChangedToLabel,
495
+ createdBy,
496
+ }) {
497
+ entityLabel @Search.ranking: HIGH;
498
+ attributeLabel @Search.ranking: HIGH;
499
+ objectID @Search.ranking: HIGH;
500
+
501
+ entityKey @Search.ranking: LOW;
502
+ modificationLabel @Search.ranking: LOW;
503
+ };
@@ -0,0 +1,77 @@
1
+ const cds = require('@sap/cds');
2
+ const LOG = cds.log('change-tracking');
3
+ const DEBUG = cds.debug('change-tracking');
4
+
5
+ /**
6
+ * Add side effects annotations for actions to refresh the changes association.
7
+ */
8
+ function addSideEffects(actions, entityName, hierarchyMap, model) {
9
+ const isRootEntity = !hierarchyMap.has(entityName);
10
+
11
+ // If not a root entity, find the parent association name
12
+ let parentAssociationName = null;
13
+ if (!isRootEntity) {
14
+ const parentEntityName = hierarchyMap.get(entityName);
15
+ const parentEntity = model.definitions[parentEntityName];
16
+ if (parentEntity?.elements) {
17
+ // Find the composition element in the parent that points to this entity
18
+ for (const [elemName, elem] of Object.entries(parentEntity.elements)) {
19
+ if (elem.type === 'cds.Composition' && elem.target === entityName) {
20
+ parentAssociationName = elemName;
21
+ break;
22
+ }
23
+ }
24
+ }
25
+ }
26
+
27
+ for (const se of Object.values(actions)) {
28
+ const target = isRootEntity ? 'TargetProperties' : 'TargetEntities';
29
+ const sideEffectAttr = se[`@Common.SideEffects.${target}`];
30
+ const property = isRootEntity ? 'changes' : { '=': `${parentAssociationName}.changes` };
31
+ if (sideEffectAttr?.length >= 0) {
32
+ sideEffectAttr.findIndex((item) => (item['='] ? item['='] : item) === (property['='] ? property['='] : property)) === -1 && sideEffectAttr.push(property);
33
+ } else {
34
+ se[`@Common.SideEffects.${target}`] = [property];
35
+ }
36
+ }
37
+ }
38
+
39
+ function addUIFacet(entity, m) {
40
+ const { 'sap.changelog.aspect': aspect } = m.definitions;
41
+ const {
42
+ '@UI.Facets': [facet],
43
+ elements: { changes }
44
+ } = aspect;
45
+ if (entity['@changelog.disable_facet'] !== undefined) {
46
+ LOG.warn(
47
+ `@changelog.disable_facet is deprecated! You can just define your own Facet for the changes association or annotate the changes association on ${entity.name} with not readable via @Capabilities.NavigationRestrictions.RestrictedProperties`
48
+ );
49
+ }
50
+
51
+ let facets = entity['@UI.Facets'];
52
+
53
+ if (!facets) {
54
+ DEBUG?.(`${entity.name} does not have a @UI.Facets annotation and thus the change tracking section is not added.`);
55
+ }
56
+ // Add UI.Facet for Change History List
57
+ if (
58
+ facets &&
59
+ !entity['@changelog.disable_facet'] &&
60
+ !hasFacetForComp(changes, entity['@UI.Facets']) &&
61
+ !entity['@Capabilities.NavigationRestrictions.RestrictedProperties']?.some((restriction) => restriction.NavigationProperty?.['='] === 'changes' && restriction.ReadRestrictions?.Readable === false)
62
+ ) {
63
+ facets.push(facet);
64
+ }
65
+ }
66
+
67
+ /**
68
+ * Check if a facet already exists for the changes composition.
69
+ */
70
+ function hasFacetForComp(comp, facets) {
71
+ return facets.some((f) => f.Target === `${comp.name}/@UI.LineItem` || (f.Facets && hasFacetForComp(comp, f.Facets)));
72
+ }
73
+
74
+ module.exports = {
75
+ addSideEffects,
76
+ addUIFacet
77
+ };
@@ -1,42 +1,9 @@
1
1
  const cds = require('@sap/cds');
2
- const LOG = cds.log('change-tracking');
3
2
  const DEBUG = cds.debug('change-tracking');
4
3
 
5
- const { isChangeTracked, getBaseEntity, analyzeCompositions, getService } = require('./utils/entity-collector.js');
6
-
7
- /**
8
- * Add side effects annotations for actions to refresh the changes association.
9
- */
10
- function addSideEffects(actions, entityName, hierarchyMap, model) {
11
- const isRootEntity = !hierarchyMap.has(entityName);
12
-
13
- // If not a root entity, find the parent association name
14
- let parentAssociationName = null;
15
- if (!isRootEntity) {
16
- const parentEntityName = hierarchyMap.get(entityName);
17
- const parentEntity = model.definitions[parentEntityName];
18
- if (parentEntity?.elements) {
19
- // Find the composition element in the parent that points to this entity
20
- for (const [elemName, elem] of Object.entries(parentEntity.elements)) {
21
- if (elem.type === 'cds.Composition' && elem.target === entityName) {
22
- parentAssociationName = elemName;
23
- break;
24
- }
25
- }
26
- }
27
- }
28
-
29
- for (const se of Object.values(actions)) {
30
- const target = isRootEntity ? 'TargetProperties' : 'TargetEntities';
31
- const sideEffectAttr = se[`@Common.SideEffects.${target}`];
32
- const property = isRootEntity ? 'changes' : { '=': `${parentAssociationName}.changes` };
33
- if (sideEffectAttr?.length >= 0) {
34
- sideEffectAttr.findIndex((item) => (item['='] ? item['='] : item) === (property['='] ? property['='] : property)) === -1 && sideEffectAttr.push(property);
35
- } else {
36
- se[`@Common.SideEffects.${target}`] = [property];
37
- }
38
- }
39
- }
4
+ const { isChangeTracked, getBaseEntity, analyzeCompositions, getService } = require('../utils/entity-collector.js');
5
+ const { addSideEffects, addUIFacet } = require('./annotations.js');
6
+ const { enhanceChangeViewWithTimeZones } = require('./timezoneProperties.js');
40
7
 
41
8
  /**
42
9
  * Returns a CQN expression for the composite key of an entity.
@@ -82,13 +49,6 @@ function _replaceTablePlaceholders(on, tableName) {
82
49
  });
83
50
  }
84
51
 
85
- /**
86
- * Check if a facet already exists for the changes composition.
87
- */
88
- function hasFacetForComp(comp, facets) {
89
- return facets.some((f) => f.Target === `${comp.name}/@UI.LineItem` || (f.Facets && hasFacetForComp(comp, f.Facets)));
90
- }
91
-
92
52
  /**
93
53
  * Enhance the CDS model with change tracking associations, facets, and side effects.
94
54
  * Returns the updated hierarchyMap and collectedEntities for use by trigger generation.
@@ -107,7 +67,6 @@ function enhanceModel(m) {
107
67
  const { 'sap.changelog.aspect': aspect } = m.definitions;
108
68
  if (!aspect) return; // some other model
109
69
  const {
110
- '@UI.Facets': [facet],
111
70
  elements: { changes }
112
71
  } = aspect;
113
72
 
@@ -143,6 +102,7 @@ function enhanceModel(m) {
143
102
  m.definitions['sap.changelog.ChangeView'].elements[parents.join('_') + '_' + 'entityKey'] = structuredClone(m.definitions['sap.changelog.ChangeView'].elements.entityKey);
144
103
  m.definitions['sap.changelog.ChangeView'].elements[parents.join('_') + '_' + 'entity'] = structuredClone(m.definitions['sap.changelog.ChangeView'].elements.entity);
145
104
  }
105
+ enhanceChangeViewWithTimeZones(m.definitions['sap.changelog.ChangeView'], m);
146
106
  }
147
107
  for (let name in m.definitions) {
148
108
  const entity = m.definitions[name];
@@ -228,35 +188,12 @@ function enhanceModel(m) {
228
188
  (query.columns ??= ['*']).push({ as: 'changes', cast: assoc });
229
189
  entity.elements.changes = assoc;
230
190
  }
231
-
232
- if (entity['@changelog.disable_facet'] !== undefined) {
233
- LOG.warn(
234
- `@changelog.disable_facet is deprecated! You can just define your own Facet for the changes association or annotate the changes association on ${entity.name} with not readable via @Capabilities.NavigationRestrictions.RestrictedProperties`
235
- );
236
- }
237
-
238
- let facets = entity['@UI.Facets'];
239
-
240
- if (!facets) {
241
- DEBUG?.(`${entity.name} does not have a @UI.Facets annotation and thus the change tracking section is not added.`);
242
- }
243
- // Add UI.Facet for Change History List
244
- if (
245
- facets &&
246
- !entity['@changelog.disable_facet'] &&
247
- !hasFacetForComp(changes, entity['@UI.Facets']) &&
248
- !entity['@Capabilities.NavigationRestrictions.RestrictedProperties']?.some((restriction) => restriction.NavigationProperty?.['='] === 'changes' && restriction.ReadRestrictions?.Readable === false)
249
- ) {
250
- facets.push(facet);
251
- }
191
+ addUIFacet(entity, m);
252
192
  }
253
193
 
254
194
  if (entity.actions) {
255
- const baseInfo = getBaseEntity(entity, m);
256
- if (baseInfo) {
257
- const { baseRef: dbEntityName } = baseInfo;
258
- addSideEffects(entity.actions, dbEntityName, hierarchyMap, m);
259
- }
195
+ const { baseRef: dbEntityName } = baseInfo;
196
+ addSideEffects(entity.actions, dbEntityName, hierarchyMap, m);
260
197
  }
261
198
  }
262
199
  }