on ‎2021 Apr 23 9:10 PM
Environment
Steps to reproduce:
I create simple CAP application with the following structure
schema.cds
using {
User
} from '@sap/cds/common';
namespace example;
entity Project {
key ID : UUID;
name : String;
owner : Composition of many ProjectOwner
on owner.project = $self;
}
entity ProjectOwner {
key user : User;
key project : Association to Project;
}
srv/service.cds
using {example as custom} from '../db/schema';
service Example {
entity Projects as projection on custom.Project;
entity ProjectOwners as projection on custom.ProjectOwner {
* , project
};
}
srv/service.js
const cds = require("@sap/cds");
module.exports = (srv) => {
srv.before(['UPDATE', 'DELETE', 'CREATE'], 'ProjectOwners', async (req) => {
var projectId = req.data.project_ID;
console.log(`Project id: ${projectId}`);
});
};
The task is the following: on create, update and delete we need to check amount of owners for project. If amount of owners is less than 2 - we need to throw error.
I adopted service in the following way
const cds = require("@sap/cds");
module.exports = (srv) => {
srv.before(['UPDATE', 'DELETE', 'CREATE'], 'ProjectOwners', async (req) => {
var projectId = req.data.project_ID;
console.log(`Project id: ${projectId}`);
if (projectId) {
const tx = cds.transaction(req);
const { ProjectOwner } = srv.entities("example");
const foundProjectOwners = await tx.run(
SELECT.from(ProjectOwner).where({ project_ID: projectId })
);
// depending on amount of project owners do validation
// ...
} else {
req.reject(400, 'No value found for project_ID!');
}
});
srv.before(['UPDATE', 'DELETE', 'CREATE'], "Projects", async (req) => {
const foundProjectOwners = req.data.owners;
// depending on amount of project owners do validation
// ...
});
};
--- --- --- --- ---
Questions:
Case 1:
Owners can be added in 2 ways:
1) POST http://localhost:4004/example/Projects
Body:
{
"name": "alice project",
"owner": [{
"user": "alice"
}]
}
2) POST http://localhost:4004/example/Projects({PROJECT_ID})/owner
Body:
{
"user": "alice"
}
In first case handler is srv.before(['UPDATE', 'DELETE', 'CREATE'], "Projects",
in second case srv.before(['UPDATE', 'DELETE', 'CREATE'], 'ProjectOwners'
So the logic
// depending on amount of project owners do validation
// ...
will be duplicated in both handlers.
Is there a way to avoid this ?
--- --- --- --- ---
Case 2:
When I delete owner through the following request
DELETE http://localhost:4004/example/Projects({PROJECT_ID})/owner/alice
projectId is equal to undefined.

Strange that projectId is recognized for CREATE and UPDATE, but not for DELETE.
What I do wrong here ? Or it is an issue in CAP itself ?
Thank for advance !
Request clarification before answering.
Hi,
Case 1:
Yes, there are multiple ways to create an entity, either directly or through the composition.
Therefore you need to run the logic for both handlers.
Case 2:
The DELETE request is sent to the `ProjectOwners` entity, therefore `req.data` doesn't contain the project ID. Can you look into `req.query.DELETE`? I expect the project ID to be present there.
Best regards,
David
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
| User | Count |
|---|---|
| 5 | |
| 5 | |
| 4 | |
| 4 | |
| 2 | |
| 2 | |
| 2 | |
| 2 | |
| 2 | |
| 2 |
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.