Skip to content

Commit

Permalink
Merge pull request #26 from MentorsWithoutBorders/cp/48/returns-the-orgs
Browse files Browse the repository at this point in the history
issue #48 Part 1– Returns information about the centers of organizations
  • Loading branch information
paschalidi authored Sep 3, 2023
2 parents 9a0789f + a9e50a0 commit 2a8adcd
Show file tree
Hide file tree
Showing 3 changed files with 161 additions and 3 deletions.
23 changes: 20 additions & 3 deletions server.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
import express from 'express';
import express, { NextFunction, Request, Response } from 'express';
import cron from 'node-cron';
import dotenv from 'dotenv';
import cors from 'cors';
import { Request, Response, NextFunction } from 'express';
import { Auth } from './src/db_queries/auth';
import { ApprovedUsers } from './src/db_queries/approved_users';
import { Users } from './src/db_queries/users';
Expand Down Expand Up @@ -50,7 +49,10 @@ import { AdminAvailableStudents } from './src/db_queries/admin_available_student
import { AdminPartnersMentors } from './src/db_queries/admin_partners_mentors';
import { AdminPartnersMentorStats } from './src/db_queries/admin_partners_mentors_stats';
import { AdminPartnersProjects } from './src/db_queries/admin_partners_projects'
import {AdminPartnersStudents} from "./src/db_queries/admin_partners_students";
import { AdminPartnersStudents } from "./src/db_queries/admin_partners_students";
import {
AdminPartnersOrganizationCentres
} from "./src/db_queries/admin_partners_organization_centres";

dotenv.config();
const port = process.env.PORT;
Expand Down Expand Up @@ -103,6 +105,7 @@ const adminPartnersMentors = new AdminPartnersMentors();
const adminPartnersMentorStats = new AdminPartnersMentorStats();
const adminPartnersProjects = new AdminPartnersProjects();
const adminPartnersStudents = new AdminPartnersStudents();
const adminPartnersCentres = new AdminPartnersOrganizationCentres();

app.use(express.urlencoded({ extended: true }));
app.use(express.json());
Expand Down Expand Up @@ -380,6 +383,20 @@ app.get(
// Partners
app.get('/api/v1/partners/dashboard/stats', partnersDashboardStats.getDashboardStats);
app.get('/api/v1/partners/:partner_id/dashboard/stats', partnersDashboardStats.getDashboardStatsByPartnerId);
// Returns the location of the org centres of _all_ the partners
// that have had at least one active student.
// Filtering by date is possible.
app.get(
'/api/v1/partners/dashboard/organization-centres',
adminPartnersCentres.getDashboardOrganizationCentres
);
// Returns the location of the org centres of _a specific_ partner
// that have had at least one active student.
// Filtering by date is possible.
app.get(
'/api/v1/partners/:partner_id/dashboard/organization-centres',
adminPartnersCentres.getDashboardOrganizationCentresByPartnerId
);

// Fields
app.get("/api/v1/fields", fields.getFields);
Expand Down
137 changes: 137 additions & 0 deletions src/db_queries/admin_partners_organization_centres.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
import { Request, Response } from "express";
import pg from "pg";
import "moment-timezone";
import { Conn } from "../db/conn";
import { Helpers } from "../utils/helpers";
import { PartnerCentersSearch } from "../models/partner_organization_centres.model";


const conn = new Conn();
const pool = conn.pool;
const helpers = new Helpers();

const deriveQuery = ({ fromDate, toDate }: PartnerCentersSearch, partnerId?: string) => {
let whereFromToDateCondition = "";
const andPartnerIdCondition = partnerId ? ` AND oc.organization_id = '${partnerId}'` : "";

if (fromDate || toDate) {
if (fromDate && toDate) {
whereFromToDateCondition = `(
(uc.start_date_time between '${fromDate}' AND ${toDate}')
OR (uc.start_date_time + (ct.duration * INTERVAL '1 month') between '${fromDate}' and '${toDate}')
)
`;
} else if (fromDate && !toDate) {
// If only from date is provided, we will take all courses that end after that date
whereFromToDateCondition = `(uc.start_date_time + (ct.duration * INTERVAL '1 month') > '${fromDate}')`;
} else if (!fromDate && toDate) {
// If only to date is provided, we will take all courses that begin before that date
whereFromToDateCondition = `(uc.start_date_time < '${toDate}')`;
}
whereFromToDateCondition = ` WHERE ${whereFromToDateCondition} `;
}
return `
WITH student_courses AS (
SELECT
ucs.student_id,
COUNT(*) AS courses_count
FROM users_courses_students ucs
INNER JOIN users_courses uc ON uc.id = ucs.course_id
INNER JOIN course_types ct ON uc.course_type_id = ct.id
INNER JOIN users u ON ucs.student_id = u.id
${whereFromToDateCondition}
GROUP BY
ucs.student_id
)
SELECT
oc.*,
json_agg(json_build_object('id', u.id, 'name', u.name)) AS students
FROM organizations_centres AS oc
JOIN users AS u ON oc.organization_id = u.organization_id
JOIN users_courses_students AS ucs ON ucs.student_id = u.id
LEFT JOIN student_courses AS sc ON sc.student_id = u.id
WHERE ucs.id IS NOT NULL
${andPartnerIdCondition}
GROUP BY oc.id
HAVING COUNT(sc.courses_count) >= 1;
`;

}

export class AdminPartnersOrganizationCentres {
constructor() {
helpers.autoBind(this);
}

async getDashboardOrganizationCentres(
request: Request,
response: Response
): Promise<void> {
const searchParameters: PartnerCentersSearch = request.query;

const client = await pool.connect();
try {
await client.query("BEGIN");
const students = await this.getDashboardOrganizationCentresFromDB(
searchParameters,
client
);
response.status(200).json(students);
await client.query("COMMIT");
} catch (error) {
console.log("getDashboardOrganizationCentresFromDB", error)
response.status(400).send(error);
await client.query("ROLLBACK");
} finally {
client.release();
}
}

async getDashboardOrganizationCentresByPartnerId(
request: Request,
response: Response
): Promise<void> {
const { partner_id: partnerId } = request.params;
const searchParameters: PartnerCentersSearch = request.body;
const client = await pool.connect();
try {
await client.query("BEGIN");
const students = await this.getDashboardOrganizationCentresByPartnerIdFromDB(
partnerId,
searchParameters,
client
);
response.status(200).json(students);
await client.query("COMMIT");
} catch (error) {
console.log("getDashboardOrganizationCentresByPartnerIdFromDB", error)
response.status(400).send(error);
await client.query("ROLLBACK");
} finally {
client.release();
}
}

private async getDashboardOrganizationCentresFromDB(
searchParameters: PartnerCentersSearch,
client: pg.PoolClient
) {
const { fromDate, toDate, } = searchParameters;
const getAllOrganizationCentersWithOneStudentQuery = deriveQuery({ fromDate, toDate });

const { rows }: pg.QueryResult = await client.query(getAllOrganizationCentersWithOneStudentQuery);
return rows;
}

private async getDashboardOrganizationCentresByPartnerIdFromDB(
partnerId: string,
searchParameters: PartnerCentersSearch,
client: pg.PoolClient
) {
const { fromDate, toDate } = searchParameters;
const getAllOrganizationCentersWithOneStudentQuery = deriveQuery({ fromDate, toDate }, partnerId);

const { rows }: pg.QueryResult = await client.query(getAllOrganizationCentersWithOneStudentQuery);
return rows;
}
}
4 changes: 4 additions & 0 deletions src/models/partner_organization_centres.model.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export interface PartnerCentersSearch {
fromDate?: string;
toDate?: string;
}

0 comments on commit 2a8adcd

Please sign in to comment.