feat: Invite intern ke project ketika creare project hanya bisa jika intern tidak sedang memiliki active project lain

This commit is contained in:
Muhammad Zhafran Ilham
2026-06-09 20:45:03 +07:00
parent 1eaa791081
commit e14ee25ef3
3 changed files with 50 additions and 3 deletions
@@ -390,6 +390,32 @@ class ProjectRepository {
data: { status }, data: { status },
}); });
} }
async findActiveMembershipsByUserIds(userIds) {
return prisma.projectMember.findMany({
where: {
id_user: {
in: userIds.map((id) => parseInt(id)),
},
status: "active",
},
include: {
user: {
select: {
id: true,
full_name: true,
email: true,
},
},
project: {
select: {
id: true,
project_name: true,
},
},
},
});
}
} }
module.exports = new ProjectRepository(); module.exports = new ProjectRepository();
@@ -58,6 +58,27 @@ class ProjectService {
} }
} }
const userIds = users.map((user) => user.id);
if (userIds.length > 0) {
const activeMemberships = await projectRepository.findActiveMembershipsByUserIds(userIds);
if (activeMemberships.length > 0) {
const assignedInterns = activeMemberships.map((membership) => {
const email = membership.user?.email || "unknown email";
const projectName = membership.project?.project_name || "Unknown Project";
return `${email} already assigned to ${projectName}`;
});
return error(
new ConflictError(
`One or more interns already have an active project: ${assignedInterns.join(", ")}`
)
);
}
}
const newProjectData = { const newProjectData = {
id_admin: parseInt(actor.id), id_admin: parseInt(actor.id),
project_icon: projectData.project_icon, project_icon: projectData.project_icon,
@@ -69,7 +90,6 @@ class ProjectService {
status: "active", status: "active",
}; };
const userIds = users.map((user) => user.id);
const project = await projectRepository.createWithMembers( const project = await projectRepository.createWithMembers(
newProjectData, newProjectData,
userIds, userIds,
+2 -1
View File
@@ -74,6 +74,7 @@ const router = express.Router();
* example: 2026-08-10 * example: 2026-08-10
* member_emails: * member_emails:
* type: array * type: array
* description: Optional intern emails to invite. Each intern must already have an active user account and must not be assigned to another active project.
* items: * items:
* type: string * type: string
* format: email * format: email
@@ -459,7 +460,7 @@ const router = express.Router();
* /project-api/add: * /project-api/add:
* post: * post:
* summary: Create a new project * summary: Create a new project
* description: Create a new Internify LMS project. Admin can optionally invite interns by email. * description: Create a new Internify LMS project. Admin can optionally invite interns by email. Invited interns must not be active members of another project.
* tags: [Project] * tags: [Project]
* security: * security:
* - bearerAuth: [] * - bearerAuth: []