Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
78 changes: 51 additions & 27 deletions lib/change-log.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ const {
} = require("./entity-helper")
const { localizeLogFields } = require("./localization")
const isRoot = "change-tracking-isRootEntity"

const hasParent = "change-tracking-parentEntity"

function formatDecimal(str, scale) {
if (typeof str === "number" && !isNaN(str)) {
Expand Down Expand Up @@ -439,12 +439,12 @@ async function generatePathAndParams (req, entityKey) {
hasComp: true
};

if (hasParentAndForeignKey && parentEntity[isRoot]) {
if (hasParentAndForeignKey && isRootEntity(parentEntity)) {
return compContext;
}

let parentAssoc = await processEntity(targetEntity, targetKey, compContext);
while (parentAssoc && !parentAssoc.entity[isRoot]) {
while (parentAssoc && !isRootEntity(parentAssoc.entity)) {
parentAssoc = await processEntity(
parentAssoc.entity,
parentAssoc.ID,
Expand All @@ -454,36 +454,59 @@ async function generatePathAndParams (req, entityKey) {
return compContext;
}

async function processEntity (entity, entityKey, compContext) {
async function processEntity(entity, entityKey, compContext) {
if (!entity || !entityKey || !compContext) return;

const { ID, foreignKey, parentEntity } = getAssociationDetails(entity);

if (foreignKey && parentEntity) {
const parentResult =
(await SELECT.one
.from(entity.name)
.where({ [ID]: entityKey })
.columns(foreignKey)) || {};
const hasForeignKey = parentResult[foreignKey];
if (!hasForeignKey) return;
compContext.path = `${parentEntity.name}/${compContext.path}`;
compContext.params.unshift({ [ID]: parentResult[foreignKey] });
return {
entity: parentEntity,
[ID]: hasForeignKey ? parentResult[foreignKey] : undefined
};
}
if (!foreignKey || !parentEntity) return;

const parentResult = await SELECT.one
.from(entity.name)
.where({ [ID]: entityKey })
.columns(foreignKey);

if (!parentResult || typeof parentResult !== 'object') return;

const hasForeignKey = parentResult[foreignKey];
if (!hasForeignKey) return;

compContext.path = `${parentEntity.name}/${compContext.path}`;
compContext.params.unshift({ [ID]: hasForeignKey });

return {
entity: parentEntity,
[ID]: hasForeignKey
};
}

function getAssociationDetails (entity) {
if (!entity) return {};
const assocName = entity['change-tracking-parentEntity']?.associationName;
const assoc = entity.elements[assocName];
const parentEntity = assoc?._target;
const foreignKey = assoc?.keys?.[0]?.$generatedFieldName;
const ID = assoc?.keys?.[0]?.ref[0] || 'ID';
if (!entity || typeof entity !== 'object') return {};

const { name } = entity;
if (!name || typeof name !== 'string') return {};

const definition = cds.model.definitions[name];
if (!definition) return {};

const assocName = entity[hasParent]?.associationName ?? definition[hasParent]?.associationName;
if (!assocName) return {};

const elements = entity.elements || {};
const assoc = elements[assocName];
if (!assoc) return {};

const parentEntity = assoc._target;
const foreignKey = assoc.keys?.[0]?.$generatedFieldName;
const ID = assoc.keys?.[0]?.ref?.[0] ?? 'ID';

return { ID, foreignKey, parentEntity };
}

function isRootEntity (entity) {
return entity[isRoot] || (cds.model.definitions[entity.name]?.[isRoot] || false);
}

function isEmpty(value) {
return value === null || value === undefined || value === "";
}
Expand Down Expand Up @@ -517,8 +540,9 @@ async function trackChangesForDiff(diff, req, that){
let target = req.target
let compContext = null;
let entityKey = diff.ID
let isTopLevel = isRootEntity(target);
const params = convertSubjectToParams(req.subject);
if (req.subject.ref.length === 1 && params.length === 1 && !target[isRoot]) {
if (req.subject.ref.length === 1 && params.length === 1 && !isTopLevel) {
compContext = await generatePathAndParams(req, entityKey);
}
let isComposition = _isCompositionContextPath(
Expand All @@ -527,7 +551,7 @@ async function trackChangesForDiff(diff, req, that){
);
if (
req.event === "DELETE" &&
target[isRoot] &&
isTopLevel &&
!cds.env.requires["change-tracking"]?.preserveDeletes
) {
await DELETE.from(`sap.changelog.ChangeLog`).where({ entityKey });
Expand Down