Skip to content
Merged
Show file tree
Hide file tree
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
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
const { ValidationError } = require('@strapi/utils').errors;

async function isLocked(contactInfoId) {
if (!contactInfoId) return false;

const relatedBds = await strapi.entityService.findMany('api::bd.bd', {
filters: {
bd_contact_information: contactInfoId,
},
fields: ['id', 'submitted_for_vote'],
});

return relatedBds.some(bd => !!bd.submitted_for_vote);
}

module.exports = {
async beforeUpdate(event) {
const { where } = event.params;
const isVotingLocked = await isLocked(where.id);
if (isVotingLocked) {
throw new ValidationError('Cannot update contact information because related proposal has already been submitted for voting.');
}
},

async beforeDelete(event) {
const { where } = event.params;
const isVotingLocked = await isLocked(where.id);
if (isVotingLocked) {
throw new ValidationError('Cannot delete contact information because related proposal has already been submitted for voting.');
}
},

async beforeCreate(event) {
const { data } = event.params;

if (!data) return;

const bdId = data.bd;

if (!bdId) return;

const relatedBd = await strapi.entityService.findOne('api::bd.bd', bdId, {
fields: ['submitted_for_vote'],
});

if (relatedBd?.submitted_for_vote) {
throw new ValidationError('Cannot create contact information because related proposal has already been submitted for voting.');
}
},
};
47 changes: 47 additions & 0 deletions backend/src/api/bd-costing/content-types/bd-costing/lifecycles.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
const { ValidationError } = require('@strapi/utils').errors;

async function isLocked(costingId) {
if (!costingId) return false;
const relatedBds = await strapi.entityService.findMany('api::bd.bd', {
filters: {
bd_costing: costingId,
},
fields: ['id', 'submitted_for_vote'],
});
return relatedBds.some(bd => !!bd.submitted_for_vote);
}

module.exports = {
async beforeUpdate(event) {
const { where } = event.params;
const isVotingLocked = await isLocked(where.id);
if (isVotingLocked) {
throw new ValidationError('Cannot update costing because related proposal has already been submitted for voting.');
}
},

async beforeDelete(event) {
const { where } = event.params;
const isVotingLocked = await isLocked(where.id);
if (isVotingLocked) {
throw new ValidationError('Cannot delete costing because related proposal has already been submitted for voting.');
}
},

async beforeCreate(event) {
const { data } = event.params;
if (!data) return;

const bdId = data.bd;

if (!bdId) return;

const relatedBd = await strapi.entityService.findOne('api::bd.bd', bdId, {
fields: ['submitted_for_vote'],
});

if (relatedBd?.submitted_for_vote) {
throw new ValidationError('Cannot create costing because related proposal has already been submitted for voting.');
}
},
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
const { ValidationError } = require('@strapi/utils').errors;

async function isLocked(furtherInfoId) {
if (!furtherInfoId) return false;

const relatedBds = await strapi.entityService.findMany('api::bd.bd', {
filters: {
bd_further_information: furtherInfoId,
},
fields: ['id', 'submitted_for_vote'],
});

return relatedBds.some(bd => !!bd.submitted_for_vote);
}

module.exports = {
async beforeUpdate(event) {
const { where } = event.params;
const isVotingLocked = await isLocked(where.id);
if (isVotingLocked) {
throw new ValidationError('Cannot update further information because related proposal has already been submitted for voting.');
}
},

async beforeDelete(event) {
const { where } = event.params;
const isVotingLocked = await isLocked(where.id);
if (isVotingLocked) {
throw new ValidationError('Cannot delete further information because related proposal has already been submitted for voting.');
}
},
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
const { ValidationError } = require('@strapi/utils').errors;

async function isVotingLockedFromPoolId(bd_poll_id) {
if (!bd_poll_id) return false;

const pool = await strapi.entityService.findOne('api::bd-poll.bd-poll', bd_poll_id, {
fields: ['bd_proposal_id'],
});

const bdId = pool?.bd_proposal_id;
if (!bdId) return false;

const bd = await strapi.entityService.findOne('api::bd.bd', bdId, {
fields: ['submitted_for_vote'],
});

return !!bd?.submitted_for_vote;
}


module.exports = {
async beforeCreate(event) {
const { data } = event.params;
const isLocked = await isVotingLockedFromPoolId(data.bd_poll_id);
if (isLocked) {
throw new ValidationError('Creating poll votes is not allowed after the proposal has been submitted for voting.');
}
},

async beforeUpdate(event) {
const { where } = event.params;

const voteEntry = await strapi.entityService.findOne('api::bd-poll-vote.bd-poll-vote', where.id, {
fields: ['bd_poll_id'],
});

const isLocked = await isVotingLockedFromPoolId(voteEntry?.bd_poll_id);
if (isLocked) {
throw new ValidationError('Modifying poll votes is not allowed after the proposal has been submitted for voting.');
}
},

async beforeDelete(event) {
const { where } = event.params;

const voteEntry = await strapi.entityService.findOne('api::bd-poll-vote.bd-poll-vote', where.id, {
fields: ['bd_poll_id'],
});

const isLocked = await isVotingLockedFromPoolId(voteEntry?.bd_poll_id);
if (isLocked) {
throw new ValidationError('Deleting poll votes is not allowed after the proposal has been submitted for voting.');
}
},
};
44 changes: 44 additions & 0 deletions backend/src/api/bd-poll/content-types/bd-poll/lifecycles.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
const { ValidationError } = require('@strapi/utils').errors;

module.exports = {
async beforeUpdate(event) {
const { where } = event.params;

const existingPool = await strapi.entityService.findOne('api::bd-pool.bd-pool', where.id, {
fields: ['bd_proposal_id'],
});
const bdId = existingPool?.bd_proposal_id;
if (!bdId) return;
const relatedBd = await strapi.entityService.findOne('api::bd.bd', bdId, {
fields: ['submitted_for_vote'],
});
if (relatedBd?.submitted_for_vote) {
throw new ValidationError('Update is not allowed because the related BD entry has already been submitted for voting.');
}
},
async beforeDelete(event) {
const { where } = event.params;
const existingPool = await strapi.entityService.findOne('api::bd-pool.bd-pool', where.id, {
fields: ['bd_proposal_id'],
});
const bdId = existingPool?.bd_proposal_id;
if (!bdId) return;
const relatedBd = await strapi.entityService.findOne('api::bd.bd', bdId, {
fields: ['submitted_for_vote'],
});
if (relatedBd?.submitted_for_vote) {
throw new ValidationError('Deletion is not allowed because the related BD entry has already been submitted for voting.');
}
},
async beforeCreate(event) {
const { data } = event;
const bdId = data.bd_proposal_id;
if (!bdId) return;
const relatedBd = await strapi.entityService.findOne('api::bd.bd', bdId, {
fields: ['submitted_for_vote'],
});
if (relatedBd?.submitted_for_vote) {
throw new ValidationError('Creation is not allowed because the related BD entry has already been submitted for voting.');
}
},
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
const { ValidationError } = require('@strapi/utils').errors;

async function isLocked(detailId) {
if (!detailId) return false;

const relatedBds = await strapi.entityService.findMany('api::bd.bd', {
filters: {
bd_proposal_detail: detailId,
},
fields: ['id', 'submitted_for_vote'],
});

return relatedBds.some(bd => !!bd.submitted_for_vote);
}

module.exports = {
async beforeUpdate(event) {
const { where } = event.params;
const isVotingLocked = await isLocked(where.id);
if (isVotingLocked) {
throw new ValidationError('Cannot update proposal detail because related proposal has already been submitted for voting.');
}
},

async beforeDelete(event) {
const { where } = event.params;
const isVotingLocked = await isLocked(where.id);
if (isVotingLocked) {
throw new ValidationError('Cannot delete proposal detail because related proposal has already been submitted for voting.');
}
}
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
const { ValidationError } = require('@strapi/utils').errors;

async function isLocked(ownershipId) {
if (!ownershipId) return false;

const relatedBds = await strapi.entityService.findMany('api::bd.bd', {
filters: {
bd_proposal_ownership: ownershipId,
},
fields: ['id', 'submitted_for_vote'],
});

return relatedBds.some(bd => !!bd.submitted_for_vote);
}

module.exports = {
async beforeUpdate(event) {
const { where } = event.params;
const isVotingLocked = await isLocked(where.id);
if (isVotingLocked) {
throw new ValidationError('Cannot update proposal ownership because related proposal has already been submitted for voting.');
}
},

async beforeDelete(event) {
const { where } = event.params;
const isVotingLocked = await isLocked(where.id);
if (isVotingLocked) {
throw new ValidationError('Cannot delete proposal ownership because related proposal has already been submitted for voting.');
}
},
};
32 changes: 32 additions & 0 deletions backend/src/api/bd-psapb/content-types/bd-psapb/lifecycles.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
const { ValidationError } = require('@strapi/utils').errors;

async function isLocked(psapbId) {
if (!psapbId) return false;

const relatedBds = await strapi.entityService.findMany('api::bd.bd', {
filters: {
bd_psapb: psapbId,
},
fields: ['id', 'submitted_for_vote'],
});

return relatedBds.some(bd => !!bd.submitted_for_vote);
}

module.exports = {
async beforeUpdate(event) {
const { where } = event.params;
const isVotingLocked = await isLocked(where.id);
if (isVotingLocked) {
throw new ValidationError('Cannot update PSAPB section because related proposal has already been submitted for voting.');
}
},

async beforeDelete(event) {
const { where } = event.params;
const isVotingLocked = await isLocked(where.id);
if (isVotingLocked) {
throw new ValidationError('Cannot delete PSAPB section because related proposal has already been submitted for voting.');
}
},
};
63 changes: 63 additions & 0 deletions backend/src/api/bd/content-types/bd/lifecycles.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
const { ValidationError } = require('@strapi/utils').errors;
const _ = require('lodash');

const IGNORED_FIELDS = [
'updatedAt',
'updatedBy',
'creator',
'bd_costing',
'bd_proposal_detail',
'bd_contact_information',
'bd_further_information',
'bd_psapb',
'bd_proposal_ownership',
'old_ver',
];

module.exports = {
async beforeUpdate(event) {
const { where, data } = event.params;

const existingEntry = await strapi.entityService.findOne('api::bd.bd', where.id);

if (!existingEntry?.submitted_for_vote) return;

// Ukloni prop_comments_number i ignorisana polja
const fieldsToCheck = Object.keys(data).filter(
key => key !== 'prop_comments_number' && !IGNORED_FIELDS.includes(key)
);

const changedFields = [];

for (const key of fieldsToCheck) {
const newVal = data[key];
const oldVal = existingEntry[key];

if (!_.isEqual(newVal, oldVal)) {
changedFields.push({
field: key,
from: oldVal,
to: newVal
});
}
}

if (changedFields.length > 0) {
const fieldList = changedFields.map(f => `${f.field} (from: ${JSON.stringify(f.from)}, to: ${JSON.stringify(f.to)})`);
throw new ValidationError(
`Only "prop_comments_number" can be changed after submission for voting. Changed fields: ${fieldList.join('; ')}`
);
}
},
async beforeDelete(event) {
const { where } = event.params;

const existingEntry = await strapi.entityService.findOne('api::bd.bd', where.id, {
fields: ['submitted_for_vote'],
});

if (existingEntry?.submitted_for_vote) {
throw new ValidationError('Deletion is not allowed because this entry has already been submitted for voting.');
}
},
};
Loading