Merge pull request #28 from internship-humic/feat/assignable-interns

feat(project): menambahkan endpoint assignable interns untuk admin atau mentor
This commit is contained in:
Muhammad Zhafran Ilham
2026-07-01 21:06:16 +07:00
committed by GitHub
4 changed files with 172 additions and 0 deletions
@@ -247,6 +247,34 @@ class ProjectController {
}
}
async getAssignableInterns(req, res) {
try {
const actor = getActor(req);
const result = await projectService.getAssignableInterns(actor);
if (result.err) {
return response(res, "fail", result);
}
return response(
res,
"success",
result,
"Assignable interns retrieved successfully",
SUCCESS.OK
);
} catch (err) {
return response(
res,
"fail",
error(new InternalServerError(err.message)),
"Unexpected error occurred",
ERROR.INTERNAL_ERROR
);
}
}
async assignMember(req, res) {
try {
const actor = getActor(req);
@@ -404,6 +404,38 @@ class ProjectRepository {
});
}
async findAssignableInterns() {
return prisma.user.findMany({
where: {
role: "intern",
is_active: true,
project_members: {
none: {
status: "active",
project: {
status: "active",
},
},
},
},
orderBy: {
full_name: "asc",
},
include: {
lamaran_magang: {
include: {
lowongan_magang: {
select: {
posisi: true,
kelompok_peminatan: true,
},
},
},
},
},
});
}
async assignMember(id_project, id_user) {
return prisma.projectMember.create({
data: {
@@ -559,6 +559,42 @@ class ProjectService {
}
}
async getAssignableInterns(actor = {}) {
try {
if (!actor?.id) {
return error(new BadRequestError("Admin ID is required"));
}
if (actor.role !== "admin" && actor.role !== "mentor") {
return error(
new ForbiddenError("Access denied: only mentors/admins can view assignable interns")
);
}
const interns = await projectRepository.findAssignableInterns();
const mappedInterns = interns.map((intern) => {
const lowongan = intern.lamaran_magang?.lowongan_magang;
return {
id: intern.id,
full_name: intern.full_name,
email: intern.email,
professional_bio: intern.professional_bio || null,
position: lowongan?.posisi || intern.intern_position || null,
kelompok_peminatan:
lowongan?.kelompok_peminatan || intern.intern_interest_group || null,
is_active: intern.is_active,
is_assignable: true,
};
});
return data(mappedInterns);
} catch (err) {
return error(err);
}
}
async assignMember(payload, actor = {}) {
try {
if (!actor?.id) {
+76
View File
@@ -481,6 +481,52 @@ const router = express.Router();
* code:
* type: integer
* example: 417
* AssignableInternItem:
* type: object
* properties:
* id:
* type: integer
* example: 4
* full_name:
* type: string
* example: Dina Pratama
* email:
* type: string
* example: dina@student.com
* professional_bio:
* type: string
* nullable: true
* example: Backend developer intern
* position:
* type: string
* nullable: true
* example: Web Developer
* kelompok_peminatan:
* type: string
* nullable: true
* example: Software Engineering
* is_active:
* type: boolean
* example: true
* is_assignable:
* type: boolean
* example: true
* AssignableInternListResponse:
* type: object
* properties:
* status:
* type: boolean
* example: true
* data:
* type: array
* items:
* $ref: '#/components/schemas/AssignableInternItem'
* message:
* type: string
* example: Assignable interns retrieved successfully
* code:
* type: integer
* example: 200
*/
/**
@@ -818,6 +864,36 @@ router.get('/mentor-projects', verifyJWT, isMentorOrAdmin, projectController.get
*/
router.get('/interns', verifyJWT, isMentorOrAdmin, projectController.getInterns);
/**
* @swagger
* /project-api/assignable-interns:
* get:
* summary: Get assignable interns
* description: Retrieve active intern accounts that can be assigned to a project. Interns are assignable if they do not have an active membership in any active project. Accessible only by admin/mentor.
* tags: [Project]
* security:
* - bearerAuth: []
* responses:
* 200:
* description: Assignable interns retrieved successfully
* content:
* application/json:
* schema:
* $ref: '#/components/schemas/AssignableInternListResponse'
* 401:
* description: Unauthorized
* 403:
* description: Forbidden. Only admin/mentor can access this endpoint.
* 500:
* description: Internal server error
*/
router.get(
"/assignable-interns",
verifyJWT,
isMentorOrAdmin,
projectController.getAssignableInterns
);
/**
* @swagger
* /project-api/assign-member: