Skip to content

Commit 91ff8d9

Browse files
authored
Merge pull request #77 from TaskTrial/enhancement/29/organization_apis
enhancement/organization-apis
2 parents b0cc61a + a51f62b commit 91ff8d9

6 files changed

Lines changed: 336 additions & 112 deletions

File tree

src/controllers/organization.controller.js

Lines changed: 69 additions & 86 deletions
Original file line numberDiff line numberDiff line change
@@ -184,7 +184,7 @@ export const verifyOrganization = async (req, res, next) => {
184184
*/
185185
export const getAllOrganizations = async (req, res, next) => {
186186
try {
187-
// Destructure and parse query params with defaults
187+
// Parse query parameters
188188
const {
189189
page = 1,
190190
limit = 10,
@@ -197,32 +197,27 @@ export const getAllOrganizations = async (req, res, next) => {
197197
const limitNum = parseInt(limit, 10);
198198
const skip = (pageNum - 1) * limitNum;
199199

200-
// Robust boolean conversion utility
201-
const parseBoolean = (value) => {
202-
if (value === 'true' || value === true || value === '1') {
203-
return true;
204-
}
205-
if (value === 'false' || value === false || value === '0') {
206-
return false;
200+
// Build filters
201+
const where = { deletedAt: null };
202+
203+
// Apply text search
204+
if (filters.name) {
205+
where.name = { contains: filters.name, mode: 'insensitive' };
206+
}
207+
208+
// Apply direct filters
209+
['industry', 'sizeRange', 'status'].forEach((field) => {
210+
if (filters[field]) {
211+
where[field] = filters[field];
207212
}
208-
return undefined; // or throw error if you prefer strict validation
209-
};
210-
211-
// Build base where clause
212-
const where = {
213-
deletedAt: null,
214-
...(filters.name && {
215-
name: { contains: filters.name, mode: 'insensitive' },
216-
}),
217-
...(filters.industry && { industry: filters.industry }),
218-
...(filters.sizeRange && { sizeRange: filters.sizeRange }),
219-
...(filters.status && { status: filters.status }),
220-
...(filters.isVerified !== undefined && {
221-
isVerified: parseBoolean(filters.isVerified),
222-
}),
223-
};
213+
});
224214

225-
// Rest of the function remains the same...
215+
// Handle boolean filter
216+
if (filters.isVerified !== undefined) {
217+
where.isVerified = ['true', '1', true].includes(filters.isVerified);
218+
}
219+
220+
// Add permission filters for non-admin users
226221
if (req.user.role !== 'ADMIN') {
227222
where.OR = [
228223
{ createdBy: req.user.id },
@@ -231,6 +226,7 @@ export const getAllOrganizations = async (req, res, next) => {
231226
];
232227
}
233228

229+
// Fetch data and count in parallel
234230
const [totalCount, organizations] = await Promise.all([
235231
prisma.organization.count({ where }),
236232
prisma.organization.findMany({
@@ -263,7 +259,8 @@ export const getAllOrganizations = async (req, res, next) => {
263259
}),
264260
]);
265261

266-
const response = {
262+
// Format response
263+
return res.status(200).json({
267264
success: true,
268265
message: 'Organizations retrieved successfully',
269266
data: {
@@ -289,9 +286,7 @@ export const getAllOrganizations = async (req, res, next) => {
289286
pages: Math.ceil(totalCount / limitNum),
290287
},
291288
},
292-
};
293-
294-
return res.status(200).json(response);
289+
});
295290
} catch (error) {
296291
next(error);
297292
}
@@ -314,7 +309,7 @@ export const getSpecificOrganization = async (req, res, next) => {
314309
});
315310
}
316311

317-
// Check if the organization exists and is not deleted
312+
// Find organization with all related data
318313
const organization = await prisma.organization.findFirst({
319314
where: {
320315
id: organizationId,
@@ -353,7 +348,7 @@ export const getSpecificOrganization = async (req, res, next) => {
353348
name: true,
354349
description: true,
355350
_count: {
356-
select: { members: true, projects: true }, // Changed from users to members
351+
select: { members: true, projects: true },
357352
},
358353
},
359354
take: 5,
@@ -379,6 +374,12 @@ export const getSpecificOrganization = async (req, res, next) => {
379374
templates: true,
380375
},
381376
},
377+
users: {
378+
where: {
379+
id: req.user.id,
380+
},
381+
take: 1,
382+
},
382383
},
383384
});
384385

@@ -389,73 +390,55 @@ export const getSpecificOrganization = async (req, res, next) => {
389390
});
390391
}
391392

392-
// Check if user has permission to view this organization
393+
// Check permissions for non-admin users
393394
if (req.user.role !== 'ADMIN') {
394-
const hasAccess = await prisma.user.findFirst({
395-
where: {
396-
id: req.user.id,
397-
OR: [
398-
{ createdOrganizations: { some: { id: organizationId } } },
399-
{ organizations: { some: { id: organizationId } } },
400-
{ ownedOrganizations: { some: { organizationId } } },
401-
],
402-
},
403-
});
395+
// Check if user is an owner
396+
const isOwner = organization.owners.some(
397+
(owner) => owner.user.id === req.user.id,
398+
);
399+
400+
// Check if user is a member
401+
const isMember = organization.users.length > 0;
404402

405-
if (!hasAccess) {
403+
if (!isOwner && !isMember) {
406404
return res.status(403).json({
407405
success: false,
408406
message: 'You do not have permission to view this organization',
409407
});
410408
}
411409
}
412410

413-
// Format response data
414-
const formattedResponse = {
415-
id: organization.id,
416-
name: organization.name,
417-
description: organization.description,
418-
industry: organization.industry,
419-
sizeRange: organization.sizeRange,
420-
website: organization.website,
421-
logoUrl: organization.logoUrl,
422-
status: organization.status,
423-
isVerified: organization.isVerified,
424-
contactEmail: organization.contactEmail,
425-
contactPhone: organization.contactPhone,
426-
address: organization.address,
427-
createdAt: organization.createdAt,
428-
updatedAt: organization.updatedAt,
429-
statistics: {
430-
usersCount: organization._count.users,
431-
departmentsCount: organization._count.departments,
432-
teamsCount: organization._count.teams,
433-
projectsCount: organization._count.projects,
434-
templatesCount: organization._count.templates,
435-
},
436-
owners: organization.owners.map((owner) => ({
437-
id: owner.user.id,
438-
name: `${owner.user.firstName} ${owner.user.lastName}`,
439-
email: owner.user.email,
440-
profileImage: owner.user.profilePic,
441-
})),
442-
departments: organization.departments,
443-
teams: organization.teams.map((team) => ({
444-
...team,
445-
usersCount: team._count.members, // Updated to use members count
446-
projectsCount: team._count.projects,
447-
_count: undefined, // Remove the original _count field
448-
})),
449-
projects: organization.projects,
450-
hasMoreDepartments: organization._count.departments > 5,
451-
hasMoreTeams: organization._count.teams > 5,
452-
hasMoreProjects: organization._count.projects > 5,
453-
};
454-
411+
// Format and return response
455412
return res.status(200).json({
456413
success: true,
457414
message: 'Organization retrieved successfully',
458-
data: formattedResponse,
415+
data: {
416+
...organization,
417+
statistics: {
418+
usersCount: organization._count.users,
419+
departmentsCount: organization._count.departments,
420+
teamsCount: organization._count.teams,
421+
projectsCount: organization._count.projects,
422+
templatesCount: organization._count.templates,
423+
},
424+
owners: organization.owners.map((owner) => ({
425+
id: owner.user.id,
426+
name: `${owner.user.firstName} ${owner.user.lastName}`,
427+
email: owner.user.email,
428+
profileImage: owner.user.profilePic,
429+
})),
430+
teams: organization.teams.map((team) => ({
431+
...team,
432+
usersCount: team._count.members,
433+
projectsCount: team._count.projects,
434+
_count: undefined,
435+
})),
436+
hasMoreDepartments: organization._count.departments > 5,
437+
hasMoreTeams: organization._count.teams > 5,
438+
hasMoreProjects: organization._count.projects > 5,
439+
_count: undefined,
440+
users: undefined,
441+
},
459442
});
460443
} catch (error) {
461444
next(error);

0 commit comments

Comments
 (0)