hasMany relation CRUD examples using OpWithRelation functions
In Supista ERP, a hasMany relation defines a one-to-many relationship between two components (tables), where a single record in the parent table is associated with multiple records in the child table.
This is the inverse of a belongsTo relation — and in fact, they often exist together as complementary links between two modules.
Example Scenario: A Team has many Members
- Parent Table: Teams
- Child Table: Members
- Supista creates a column in Members:
Teams - Members ID - Multiple members can be assigned to a single team
createOpWithRelation
Creates a new Member and auto-assigns it to Team ID = 1.
Example Code
async function customizeERP(userData, apiOperations) {
const parentTableName = "teams";
const { createOp } = apiOperations;
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?.id) {
resolve({ result: createdData });
} else {
resolve({
result: {},
popupMsg: {
type: 'warning',
message: 'Could not create data! Please try again later',
}
});
}
})
}Example Input
{
"__d3__newData": {
"name": "john",
"email": "john@gmail.com",
"teams - members ID": 1
},
"__d3__parentId": 1,
"__d3__relationId": "5r1i4x3071"
}Example Output
{
"response": {
"__d3__result": {
"result": {
"id": 1,
"name": "john",
"email": "john@gmail.com",
"teams - members ID": 1,
"__d3__createdBy": 575,
"__d3__updatedAt": "2025-06-11T10:07:59.065Z",
"__d3__createdAt": "2025-06-11T10:07:59.065Z",
"__d3__lastUpdatedBy": null,
"__d3__deletedAt": null
}
},
"__d3__error": false,
"printConsole": []
}
}readOpWithRelation
Fetches all members under Team ID = 1.
Example Code
async function customizeERP(userData, apiOperations) {
const parentTableName = "teams";
const { readOpWithRelation } = apiOperations;
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": "5r1i4x3071"
}Example Output
{
"response": {
"__d3__result": {
"result": {
"count": 2,
"rows": [
{
"id": 1,
"name": "john",
"email": "john@gmail.com",
"teams - members ID": 1,
"__d3__createdBy": 575,
"__d3__lastUpdatedBy": null,
"__d3__createdAt": "2025-06-11T10:07:59.065Z",
"__d3__updatedAt": "2025-06-11T10:07:59.065Z",
"__d3__deletedAt": null
},
{
"id": 2,
"name": "james",
"email": "james@gmail.com",
"teams - members ID": 1,
"__d3__createdBy": 575,
"__d3__lastUpdatedBy": null,
"__d3__createdAt": "2025-06-10T13:23:48.594Z",
"__d3__updatedAt": "2025-06-10T13:23:48.594Z",
"__d3__deletedAt": null
}
]
}
},
"__d3__error": false,
"printConsole": []
}
}updateOpWithRelation
Updates Member ID = 1 under Team ID = 1.
Example Code
async function customizeERP(userData, apiOperations) {
const parentTableName = "teams";
const { updateOpWithRelation } = 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": {
"name": "john Doe",
"email": "john@gmail.com",
"teams - members ID": 1,
"__d3__createdBy": 575,
"__d3__lastUpdatedBy": null,
"__d3__createdAt": "2025-06-11T10:07:59.065Z",
"__d3__updatedAt": "2025-06-11T10:07:59.065Z",
"__d3__deletedAt": null
},
"__d3__id": 1,
"__d3__parentId": 1,
"__d3__relationId": "5r1i4x3071"
}Example Output
{
"response": {
"__d3__result": {
"result": {
"affectedCount": [1]
}
},
"__d3__error": false,
"printConsole": []
}
}removeOpWithRelation
Deletes Member ID = 1 only if it belongs to Team ID = 1.
Example Code
async function customizeERP(userData, apiOperations) {
const parentTableName = "teams";
const { removeOpWithRelation } = apiOperations;
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": "5r1i4x3071"
}Example Output
{
"response": {
"__d3__result": {
"result": {
"deletedObjNo": 1
}
},
"__d3__error": false,
"printConsole": []
}
}bulkCreateOpWithRelation
Creates multiple new Members and auto-assigns them to Team ID = 1.
Example Code
async function customizeERP(userData, apiOperations) {
const tableName = "teams";
const { bulkCreateOpWithRelation } = apiOperations;
return new Promise(async (resolve, reject) => {
const payload = {
__d3__bulkData: userData?.__d3__bulkData
}
const bulkData = await bulkCreateOpWithRelation(
tableName,
payload,
userData.__d3__parentId,
userData.__d3__relationId
);
if (bulkData) {
resolve({ result: bulkData });
} else {
resolve({
result: {},
popupMsg: {
type: "error",
message: "Could Not create data! Please try again later"
}
});
}
})
}Example Input
{
"__d3__bulkData": [
{
"name": "john",
"email": "john@gmail.com",
"teams - members ID": 1
},
{
"name": "james",
"email": "james@gmail.com",
"teams - members ID": 1
}
],
"__d3__parentId": 1,
"__d3__relationId": "5r1i4x3071"
}Example Output
{
"response": {
"__d3__result": {
"result": {
"bulkCreated": 2
}
},
"__d3__error": false,
"printConsole": []
}
}