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:
@@ -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) {
|
async assignMember(req, res) {
|
||||||
try {
|
try {
|
||||||
const actor = getActor(req);
|
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) {
|
async assignMember(id_project, id_user) {
|
||||||
return prisma.projectMember.create({
|
return prisma.projectMember.create({
|
||||||
data: {
|
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 = {}) {
|
async assignMember(payload, actor = {}) {
|
||||||
try {
|
try {
|
||||||
if (!actor?.id) {
|
if (!actor?.id) {
|
||||||
|
|||||||
@@ -481,6 +481,52 @@ const router = express.Router();
|
|||||||
* code:
|
* code:
|
||||||
* type: integer
|
* type: integer
|
||||||
* example: 417
|
* 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);
|
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
|
* @swagger
|
||||||
* /project-api/assign-member:
|
* /project-api/assign-member:
|
||||||
|
|||||||
Reference in New Issue
Block a user