1
1
const cds = require ( "@sap/cds" )
2
2
const getTemplate = require ( "@sap/cds/libx/_runtime/common/utils/template" ) // REVISIT: bad usage of internal stuff
3
3
const templateProcessor = require ( "./template-processor" )
4
- const { big } = require ( "@sap/cds-foss" ) // REVISIT: Do we really need that?
5
4
const LOG = cds . log ( "change-log" )
6
- const {
7
- OBJECT_PATH_DELIMITER ,
8
- TX_CONTEXT_PATH_DELIMITER ,
9
- VALUE_DELIMITER ,
10
- } = require ( "./constants" )
11
- const CHANGE_LOG_ANNOTATION = "@changelog"
12
5
13
6
const {
14
7
getNameFromPathVal,
@@ -17,11 +10,8 @@ const {
17
10
getCurObjFromDbQuery,
18
11
getObjectId,
19
12
getDBEntity,
20
- getEntity,
21
13
getEntityByContextPath,
22
- hasComposition,
23
14
getObjIdElementNamesInArray,
24
- getAssociationCompositionEntity,
25
15
getValueEntityType,
26
16
} = require ( "./entity-helper" )
27
17
const { localizeLogFields } = require ( "./localization" )
@@ -31,7 +21,7 @@ const _getRootEntityPathVals = function (txContext, entity, entityKey) {
31
21
const serviceEntityPathVals = [ ]
32
22
const entityIDs = _getEntityIDs ( txContext . params )
33
23
34
- let path = txContext . path . split ( TX_CONTEXT_PATH_DELIMITER )
24
+ let path = txContext . path . split ( '/' )
35
25
36
26
if ( txContext . event === "CREATE" ) {
37
27
const curEntityPathVal = `${ entity . name } (${ entityKey } )`
@@ -61,7 +51,7 @@ const _getRootEntityPathVals = function (txContext, entity, entityKey) {
61
51
62
52
const _getAllPathVals = function ( txContext ) {
63
53
const pathVals = [ ]
64
- const paths = txContext . path . split ( TX_CONTEXT_PATH_DELIMITER )
54
+ const paths = txContext . path . split ( '/' )
65
55
const entityIDs = _getEntityIDs ( txContext . params )
66
56
67
57
for ( let idx = 0 ; idx < paths . length ; idx ++ ) {
@@ -91,10 +81,6 @@ const _getEntityIDs = function (txParams) {
91
81
return entityIDs
92
82
}
93
83
94
- const _pick = ( element ) => {
95
- return element [ CHANGE_LOG_ANNOTATION ]
96
- }
97
-
98
84
/**
99
85
*
100
86
* @param {* } tx
@@ -113,10 +99,10 @@ const _pick = (element) => {
113
99
*/
114
100
const _formatAssociationContext = async function ( changes ) {
115
101
for ( const change of changes ) {
116
- const a = getEntity ( change . serviceEntity ) . elements [ change . attribute ]
102
+ const a = cds . model . definitions [ change . serviceEntity ] . elements [ change . attribute ]
117
103
if ( a ?. type !== "cds.Association" ) continue
118
104
119
- const semkeys = getObjIdElementNamesInArray ( a [ CHANGE_LOG_ANNOTATION ] )
105
+ const semkeys = getObjIdElementNamesInArray ( a [ "@changelog" ] )
120
106
if ( ! semkeys . length ) continue
121
107
122
108
const ID = a . keys [ 0 ] . ref [ 0 ] || 'ID'
@@ -142,8 +128,8 @@ const _getChildChangeObjId = async function (
142
128
curNodePathVal ,
143
129
reqData
144
130
) {
145
- const composition = getAssociationCompositionEntity ( change . serviceEntity , change . attribute )
146
- const objIdElements = composition ? composition [ CHANGE_LOG_ANNOTATION ] : null
131
+ const composition = cds . model . definitions [ change . serviceEntity ] . elements [ change . attribute ]
132
+ const objIdElements = composition ? composition [ "@changelog" ] : null
147
133
const objIdElementNames = getObjIdElementNamesInArray ( objIdElements )
148
134
149
135
return _getObjectIdByPath (
@@ -164,7 +150,7 @@ const _formatCompositionContext = async function (changes, reqData) {
164
150
}
165
151
for ( const childNodeChange of change . valueChangedTo ) {
166
152
const curChange = Object . assign ( { } , change )
167
- const path = childNodeChange . _path . split ( OBJECT_PATH_DELIMITER )
153
+ const path = childNodeChange . _path . split ( '/' )
168
154
const curNodePathVal = path . pop ( )
169
155
curChange . modification = childNodeChange . _op
170
156
const objId = await _getChildChangeObjId (
@@ -211,11 +197,8 @@ const _formatCompositionValue = function (
211
197
}
212
198
213
199
const _formatCompositionEntityType = function ( change ) {
214
- const composition = getAssociationCompositionEntity (
215
- change . serviceEntity ,
216
- change . attribute
217
- )
218
- const objIdElements = composition ? composition [ CHANGE_LOG_ANNOTATION ] : null
200
+ const composition = cds . model . definitions [ change . serviceEntity ] . elements [ change . attribute ]
201
+ const objIdElements = composition ? composition [ '@changelog' ] : null
219
202
220
203
if ( Array . isArray ( objIdElements ) ) {
221
204
// In this case, the attribute is a composition
@@ -242,7 +225,7 @@ const _getObjectIdByPath = async function (
242
225
const _formatObjectID = async function ( changes , reqData ) {
243
226
const objectIdCache = new Map ( )
244
227
for ( const change of changes ) {
245
- const path = change . serviceEntityPath . split ( OBJECT_PATH_DELIMITER )
228
+ const path = change . serviceEntityPath . split ( '/' )
246
229
const curNodePathVal = path . pop ( )
247
230
const parentNodePathVal = path . pop ( )
248
231
@@ -278,68 +261,35 @@ const _isCompositionContextPath = function (aPath) {
278
261
if ( aPath . length < 2 ) return false
279
262
const target = getEntityByContextPath ( aPath )
280
263
const parent = getEntityByContextPath ( aPath . slice ( 0 , - 1 ) )
281
- return hasComposition ( parent , target )
264
+ if ( ! parent . compositions ) return false
265
+ return Object . values ( parent . compositions ) . some ( c => c . _target === target )
282
266
}
283
267
284
268
const _formatChangeLog = async function ( changes , req ) {
285
269
await _formatObjectID ( changes , req . data )
286
270
await _formatAssociationContext ( changes )
287
271
await _formatCompositionContext ( changes , req . data )
288
- // _formatFromTo(req, changes)
289
272
}
290
273
291
- // function _formatFromTo (req, changes) {
292
- // const contentType = req.context.req?.headers["content-type"] // the service API do not have a req header
293
- // const isExponentialDecimals = contentType?.includes("ExponentialDecimals=true")
294
- // for (const change of changes) {
295
- // if (!isExponentialDecimals)
296
- // _formatDecimalValue(change)
297
- // }
298
- // }
299
-
300
- // const _formatDecimalValue = function (change) {
301
- // const valueDataTypes = change.valueDataType.split(VALUE_DELIMITER)
302
- // const valueChangedFroms = change.valueChangedFrom.split(VALUE_DELIMITER)
303
- // const valueChangedTos = change.valueChangedTo.split(VALUE_DELIMITER)
304
- // for (const idx in valueDataTypes) {
305
- // if (valueDataTypes[idx] === "cds.Decimal") {
306
- // if (valueChangedFroms[idx]) {
307
- // const bigFrom = big(valueChangedFroms[idx])
308
- // valueChangedFroms[idx] = bigFrom.toFixed()
309
- // }
310
-
311
- // if (valueChangedTos[idx]) {
312
- // const bigTo = big(valueChangedTos[idx])
313
- // valueChangedTos[idx] = bigTo.toFixed()
314
- // }
315
- // }
316
- // }
317
- // change.valueChangedFrom = valueChangedFroms.join(VALUE_DELIMITER)
318
- // change.valueChangedTo = valueChangedTos.join(VALUE_DELIMITER)
319
- // }
320
-
321
- const _afterReadChangeView = async function ( data , req ) {
322
- if ( ! data ) {
323
- return
324
- }
325
-
326
- localizeLogFields ( Array . isArray ( data ) ? data : [ data ] , req . user . locale )
274
+ const _afterReadChangeView = function ( data , req ) {
275
+ if ( ! data ) return
276
+ if ( ! Array . isArray ( data ) ) data = [ data ]
277
+ localizeLogFields ( data , req . locale )
327
278
}
328
279
329
280
330
281
function _trackedChanges4 ( srv , target , diff ) {
331
- const template = getTemplate ( "change-logging" , srv , target , { pick : _pick } )
282
+ const template = getTemplate ( "change-logging" , srv , target , { pick : e => e [ '@changelog' ] } )
332
283
if ( ! template . elements . size ) return
333
284
334
285
const changes = [ ]
335
286
diff . _path = `${ target . name } (${ diff . ID } )`
336
287
337
288
templateProcessor ( {
338
289
template, row : diff , processFn : ( { row, key, element } ) => {
339
- const from = row . _old ?. [ key ] ? row . _old [ key ] : undefined
340
- const to = row [ key ] ? row [ key ] : undefined
341
- if ( from === to )
342
- return
290
+ const from = row . _old ?. [ key ]
291
+ const to = row [ key ]
292
+ if ( from === to ) return
343
293
344
294
const keys = Object . keys ( element . parent . keys )
345
295
. filter ( k => k !== "IsActiveEntity" )
@@ -373,10 +323,10 @@ const _prepareChangeLogForComposition = async function (entity, entityKey, chang
373
323
374
324
const parentEntityPathVal = rootEntityPathVals [ rootEntityPathVals . length - 2 ]
375
325
const parentKey = getUUIDFromPathVal ( parentEntityPathVal )
376
- const serviceEntityPath = rootEntityPathVals . join ( OBJECT_PATH_DELIMITER )
326
+ const serviceEntityPath = rootEntityPathVals . join ( '/' )
377
327
const parentServiceEntityPath = _getAllPathVals ( req . context )
378
328
. slice ( 0 , rootEntityPathVals . length - 2 )
379
- . join ( OBJECT_PATH_DELIMITER )
329
+ . join ( '/' )
380
330
381
331
for ( const change of changes ) {
382
332
change . parentEntityID = await _getObjectIdByPath ( req . data , parentEntityPathVal , parentServiceEntityPath )
0 commit comments