belongsToMany relation CRUD examples using OpWithRelation
functions
In Supista ERP, a belongsToMany
relation is used to define a many-to-many relationship between two components, where:
- One record in Table A can be linked to many records in Table B
- And one record in Table B can also be linked to many records in Table A
This is made possible using an automatically generated junction table (also called a relation or pivot table), which holds the IDs of both linked records.
Example Scenario: Members ↔ Projects
- A Member can work on multiple Projects
- A Project can have multiple Members
In this case:
- Members and Projects are the two main tables
- Supista ERP auto-generates a relation table (e.g.,
Projects - Members Relation
) with:- Member ID →
__d3__id
- Project ID →
__d3__parentId
- Member ID →
createOpWithRelation
Adds a new relation row in the junction table, linking Member ↔ Project.
Example Code
async function customizeERP(userData, apiOperations) {
const parentTableName = "members";
return new Promise(async (resolve, reject) => {
const payload = {
__d3__newData: { ...userData?.__d3__newData }
}
const createdData = await createOpWithRelation(
parentTableName,
payload,
userData?.__d3__parentId,
userData?.__d3__relationId
);
if (createdData[0]) {
resolve({ result: createdData[0] });
} else {
resolve({
result: {},
popupMsg: {
type: 'warning',
message: 'Could not read data! Please try again later',
}
});
}
})
}
Example Input
{
"__d3__newData": {
"__d3__id": [2]
},
"__d3__parentId": 2,
"__d3__relationId": "732f6s3717"
}
Example Output
{
"response": {
"__d3__result": {
"result": {
"projects Id": 2,
"members Id": 2,
"__d3__createdAt": "2025-06-18T11:53:37.614Z",
"__d3__updatedAt": "2025-06-18T11:53:37.614Z",
"__d3__deletedAt": null
}
},
"__d3__error": false,
"printConsole": []
}
}
readOpWithRelation
Fetches all related records for a parent entity (e.g., all Members in a Project).
Example Code
async function customizeERP(userData, apiOperations) {
const parentTableName = "members";
return new Promise(async (resolve, reject) => {
const payload = {
__d3__filterdata: { where: {} }
}
const rowsData = await readOpWithRelation(
parentTableName,
payload,
userData?.__d3__parentId,
userData?.__d3__relationId
);
if (rowsData?.count) {
resolve({ result: rowsData });
} else {
resolve({
result: {},
popupMsg: {
type: "error",
message: "Could Not read data! Please try again later"
}
});
}
})
}
Example Input
{
"__d3__filterdata": {
"where": {}
},
"__d3__parentId": 1,
"__d3__relationId": "732f6s3717"
}
Example Output
{
"response": {
"__d3__result": {
"result": {
"count": 2,
"rows": [
{
"id": 2,
"project title": "AI/ML",
"__d3__createdBy": 575,
"__d3__lastUpdatedBy": null,
"__d3__createdAt": "2025-06-17T08:59:23.289Z",
"__d3__updatedAt": "2025-06-17T08:59:23.289Z",
"__d3__deletedAt": null
},
{
"id": 1,
"project title": "Web3",
"__d3__createdBy": 575,
"__d3__lastUpdatedBy": null,
"__d3__createdAt": "2025-06-16T20:24:46.032Z",
"__d3__updatedAt": "2025-06-16T20:24:46.032Z",
"__d3__deletedAt": null
}
]
}
},
"__d3__error": false,
"printConsole": []
}
}
updateOpWithRelation
Updates metadata or related values in the junction row (if any exist).
Example Code
async function customizeERP(userData, apiOperations) {
const parentTableName = "members";
const { updateOp } = apiOperations;
return new Promise(async (resolve, reject) => {
const payload = {
__d3__id: userData?.__d3__id,
__d3__newData: { ...userData?.__d3__newData }
}
const updatedData = await updateOpWithRelation(
parentTableName,
payload,
userData?.__d3__parentId,
userData?.__d3__relationId
);
if (updatedData?.affectedCount?.[0]) {
resolve({ result: updatedData });
} else {
resolve({
result: {},
popupMsg: {
type: "error",
message: "Could Not update data! Please try again later"
}
});
}
})
}
Example Input
{
"__d3__newData": {
"id": 2,
"project title": "AI/ML/design",
"__d3__createdBy": 575,
"__d3__lastUpdatedBy": null,
"__d3__createdAt": "2025-06-17T08:59:23.289Z",
"__d3__updatedAt": "2025-06-17T08:59:23.289Z",
"__d3__deletedAt": null
},
"__d3__id": 2,
"__d3__parentId": 1,
"__d3__relationId": "732f6s3717"
}
Example Output
{
"response": {
"__d3__result": {
"result": {
"affectedCount": [1]
}
},
"__d3__error": false,
"printConsole": []
}
}
removeOpWithRelation
Removes the link between a Member and a Project.
Example Code
async function customizeERP(userData, apiOperations) {
const parentTableName = "members";
return new Promise(async (resolve, reject) => {
const payload = {
__d3__id: [userData?.__d3__id]
}
const deletedData = await removeOpWithRelation(
parentTableName,
payload,
userData?.__d3__parentId,
userData?.__d3__relationId
);
if (deletedData?.deletedObjNo) {
resolve({ result: deletedData });
} else {
resolve({
result: {},
popupMsg: {
type: "error",
message: "Could Not delete data! Please try again later"
}
});
}
})
}
Example Input
{
"__d3__parentId": 1,
"__d3__id": 2,
"__d3__relationId": "732f6s3717"
}
Example Output
{
"response": {
"__d3__result": {
"result": {
"deletedObjNo": 1
}
},
"__d3__error": false,
"printConsole": []
}
}