Untitled

 avatar
unknown
javascript
4 years ago
16 kB
5
Indexable
import { Request, Response } from 'lambda-api';
import { ClientBase } from 'pg';
// import { Endpoint } from 'aws-sdk';
import { failure, success } from '../../../shared/libs/response';
import { getAuth, setAuth } from '../../../shared/libs/auth';
import code from '../../../shared/libs/code';
import { AuthModel } from '../../../shared/models/auth.model';
import lambda from '../../../shared/libs/lambda';
import config from '../../../shared/libs/config';
import { ApiModel } from '../../../shared/models/api.model';

async function queryGetPeriodsByAcademicYear(
  db: ClientBase,
  auth: AuthModel,
  academicYear: string
): Promise<any> {
  try {
    const queryResult = await db.query(
      `
      SELECT DISTINCT   period.period_id,
                        period.period_name
      FROM period
        JOIN academic_calendar
            ON academic_calendar.period_id = period.period_id
                AND academic_calendar.deleted_at IS NULL 
                AND academic_calendar.tenant_uuid = $1
      WHERE period.deleted_at IS NULL 
        AND period.tenant_uuid = $1
        AND academic_calendar.academic_year = $2
      ORDER BY period.period_id
    `,
      [auth.tenant_uuid, academicYear]
    );

    if (queryResult.rowCount === 0) {
      return null;
    }

    return queryResult.rows;
  } catch (e) {
    console.error('[ERROR-QUERY] - func: queryGetPeriodsByAcademicYear', e);
    throw Error(code.database_error);
  }
}

async function queryGetYearLevelsBySchoolLevel(
  db: ClientBase,
  auth: AuthModel,
  params: {
    school_level_id: number;
    school_location_id: number;
  }
): Promise<any> {
  try {
    const queryResult = await db.query(
      `
        SELECT DISTINCT year_level.year_level_id,
                        year_level.year_level_name
        FROM year_level
            JOIN school_level_relation
                ON school_level_relation.year_level_id = year_level.year_level_id
                    AND school_level_relation.deleted_at IS NULL
                    AND school_level_relation.tenant_uuid = $1
        WHERE year_level.deleted_at IS NULL
            AND year_level.tenant_uuid = $1
            AND school_level_relation.school_level_id = $2
            AND school_level_relation.school_location_id = $3
        ORDER BY year_level.year_level_name
    `,
      [auth.tenant_uuid, params.school_level_id, params.school_location_id]
    );

    if (queryResult.rowCount === 0) {
      return null;
    }

    return queryResult.rows;
  } catch (e) {
    console.error('[ERROR-QUERY] - func: queryGetYearLevelsBySchoolLevel', e);
    throw Error(code.database_error);
  }
}

async function queryGetClassMembers(db: ClientBase, auth: AuthModel, params: any): Promise<any> {
  try {
    let filterQueryIndex = 1;

    const filteredColumns = {
      academic_year: 'academic_calendar.academic_year',
      period_id: 'academic_calendar.period_id',
      school_level_id: 'school_level_relation.school_level_id',
      school_location_id: 'school_level_relation.school_location_id',
      year_level_id: 'school_level_relation.year_level_id',
    };

    const queryStrings = [];
    const queryValues = [];

    for (const key in filteredColumns) {
      if (Object.prototype.hasOwnProperty.call(filteredColumns, key)) {
        const value = filteredColumns[key];

        if (!params[key] || params[key] === 'null' || params[key] === 'undefined') {
          continue;
        }

        queryStrings.push(`AND ${value} = $${++filterQueryIndex}`);

        queryValues.push(params[key] || null);
      }
    }

    const queryResult = await db.query(
      `
        SELECT DISTINCT class_member.student_id,
                        class.class_name,
                        academic_calendar.academic_start_date,
                        academic_calendar.academic_end_date
        FROM  class_member
            JOIN class
                ON class.class_id = class_member.class_id
                    AND class.deleted_at IS NULL 
                    AND class.tenant_uuid = $1
            JOIN academic_calendar
                ON academic_calendar.academic_calendar_id = class.academic_calendar_id
                    AND academic_calendar.deleted_at IS NULL 
                    AND academic_calendar.tenant_uuid = $1
            JOIN school_level_relation
                ON school_level_relation.school_level_relation_id = academic_calendar.school_level_relation_id
                    AND school_level_relation.deleted_at IS NULL 
                    AND school_level_relation.tenant_uuid = $1
        WHERE class_member.deleted_at IS NULL 
            AND class_member.tenant_uuid = $1
            ${queryStrings.join(' ')}
        ORDER BY class_member.student_id ASC
    `,
      [auth.tenant_uuid, ...queryValues]
    );

    if (queryResult.rowCount === 0) {
      return null;
    }

    return queryResult.rows;
  } catch (e) {
    console.error('[ERROR-QUERY] - func: queryGetClassMembers', e);
    throw Error(code.database_error);
  }
}

async function getDetailStudents(req: Request, studentIds: Array<number>): Promise<any> {
  let students = [];

  try {
    // lambda.endpoint = new Endpoint('http://localhost:3012');

    const result = await lambda
      .invoke({
        FunctionName: `student-service-${config.stage}-api-v1`,
        InvocationType: 'RequestResponse',
        LogType: 'Tail',
        Payload: JSON.stringify({
          ...setAuth(req),
          httpMethod: 'POST',
          path: '/student/api/v1/student-by-student-ids',
          body: {
            student_ids: studentIds,
          },
        }),
      })
      .promise();

    const payload = JSON.parse(result.Payload as string);
    const body: ApiModel<any> = JSON.parse(payload.body);

    if (body.status) {
      students = body.data;
    } else {
      console.error(body.message);
      throw Error(body.message);
    }
  } catch (e) {
    console.error('[ERROR-INVOKE] - func: getDetailStudents', e);
    throw Error(e);
  }

  return students;
}

async function getReligions(req: Request): Promise<any> {
  let religions = [];

  try {
    // lambda.endpoint = new Endpoint('http://localhost:3014');

    const result = await lambda
      .invoke({
        FunctionName: `general-service-${config.stage}-api-v1`,
        InvocationType: 'RequestResponse',
        LogType: 'Tail',
        Payload: JSON.stringify({
          ...setAuth(req),
          httpMethod: 'GET',
          path: '/general/v1/religion-list',
        }),
      })
      .promise();

    const payload = JSON.parse(result.Payload as string);
    const body: ApiModel<any> = JSON.parse(payload.body);

    if (body.status) {
      religions = body.data;
    } else {
      console.error(body.message);
      throw Error(body.message);
    }
  } catch (e) {
    console.error(e);
    throw e;
  }

  return religions;
}

async function getStudentsByJoinDate(req: Request, year: string): Promise<any> {
  let students = [];

  try {
    // lambda.endpoint = new Endpoint('http://localhost:3012');

    const result = await lambda
      .invoke({
        FunctionName: `student-service-${config.stage}-api-v1`,
        InvocationType: 'RequestResponse',
        LogType: 'Tail',
        Payload: JSON.stringify({
          ...setAuth(req),
          httpMethod: 'GET',
          path: `/student/api/v1/students/join-date-school/${year}`,
        }),
      })
      .promise();

    const payload = JSON.parse(result.Payload as string);
    const body: ApiModel<any> = JSON.parse(payload.body);

    if (body.status) {
      students = body.data;
    } else {
      console.error(body.message);
      throw Error(body.message);
    }
  } catch (e) {
    console.error('[ERROR-INVOKE] - func: getStudentsByJoinDate', e);
    throw Error(e);
  }

  return students;
}

export default async function classGenerateStudents(req: Request, res: Response): Promise<any> {
  try {
    const auth = getAuth(req);
    const params = req.body;

    if (
      !params.academic_year ||
      !params.periods ||
      !params.school_level_id ||
      !params.school_location_id ||
      !params.year_level_id
    ) {
      throw Error(code.input_invalid);
    }

    const periods = params.periods;

    const previousSchoolLocationsIds = params.previous_school_location_ids;
    const otherSchoolLocationIds = params.other_school_location_ids;

    const schoolLocationsIds = previousSchoolLocationsIds.concat(otherSchoolLocationIds);
    schoolLocationsIds.push(+params.school_location_id);

    const isFirstYearLevel = params.is_first_year_level;

    const classMembers = [];

    // [START] logic class members from previous class
    const masterPeriods = await queryGetPeriodsByAcademicYear(
      req.namespace.db,
      auth,
      params.academic_year
    );
    if (!masterPeriods) {
      throw Error(code.data_not_found);
    }

    const oddPeriod = masterPeriods[0];
    const evenPeriod = masterPeriods[1];

    const yearLevelsParams = {
      school_level_id: +params.school_level_id,
      school_location_id: +params.school_location_id,
    };

    // check year level
    const yearLevels = await queryGetYearLevelsBySchoolLevel(
      req.namespace.db,
      auth,
      yearLevelsParams
    );
    if (!yearLevels) {
      throw Error(code.data_not_found);
    }

    const currentYearLevel = yearLevels.find((i) => +i.year_level_id === +params.year_level_id);
    if (!currentYearLevel) {
      throw Error(code.data_not_found);
    }

    for (const period of periods) {
      // odd period
      if (+period.period_id === +oddPeriod.period_id) {
        // check graduate_status, previous academic_year
        if (isFirstYearLevel) {
          // check graduate_status, previous academic_year
        } else {
          // check previous academic_year
          const currentYearLevelIndex = yearLevels.findIndex(
            (i) => +i.year_level_id === +currentYearLevel.year_level_id
          );
          const previousYearLevel = yearLevels.slice(0, currentYearLevelIndex + 1);

          const currentAcademicYear = params.academic_year;
          const previousAcademicYear = currentAcademicYear
            .split('-')
            .map((i) => +(i - 1))
            .join('-');

          const previousAcademicDataParams = {
            academic_year: previousAcademicYear,
            period_id: +period.period_id,
            school_level_id: +params.school_level_id,
            school_location_id: null,
            year_level_id: null,
          };

          if (schoolLocationsIds.length !== 0) {
            for (const schoolLocationId of schoolLocationsIds) {
              previousAcademicDataParams.school_location_id = +schoolLocationId;

              for (const yearLevel of previousYearLevel) {
                previousAcademicDataParams.year_level_id = +yearLevel.year_level_id;

                const previousClassMembers = await queryGetClassMembers(
                  req.namespace.db,
                  auth,
                  previousAcademicDataParams
                );
                if (previousClassMembers) {
                  for (const classMember of previousClassMembers) {
                    classMembers.push(classMember);
                  }
                }
              }
            }
          }
        }
      }

      // even period
      if (+period.period_id === +evenPeriod.period_id) {
        // get odd period data
        const previousPeriodParams = {
          academic_year: params.academic_year,
          period_id: +oddPeriod.period_id,
          school_level_id: +params.school_level_id,
          school_location_id: null,
          year_level_id: +params.year_level_id,
        };

        if (schoolLocationsIds.length !== 0) {
          for (const schoolLocationId of schoolLocationsIds) {
            previousPeriodParams.school_location_id = +schoolLocationId;
            const previousClassMembers = await queryGetClassMembers(
              req.namespace.db,
              auth,
              previousPeriodParams
            );

            if (previousClassMembers) {
              for (const classMember of previousClassMembers) {
                classMembers.push(classMember);
              }
            }
          }
        }
      }
    }
    // [END] logic class members from previous class

    // [START] check allocated students
    const masterClassMembers = [];

    for (const schoolLocationId of schoolLocationsIds) {
      const masterClassMembersParams = {
        academic_year: params.academic_year,
        period_id: +periods.period_id,
        school_level_id: +params.school_level_id,
        school_location_id: +schoolLocationId,
      };

      const classMemberData = await queryGetClassMembers(
        req.namespace.db,
        auth,
        masterClassMembersParams
      );

      if (classMemberData) {
        for (const classMember of classMemberData) {
          masterClassMembers.push(classMember);
        }
      }
    }

    for (const masterClassMember of masterClassMembers) {
      const index = classMembers.findIndex((i) => +i.student_id === +masterClassMember.student_id);
      if (index < 0) {
        continue;
      }
      classMembers.splice(index, 1);
    }

    const year = params.academic_year.slice(0, 4);

    const masterStudentList = await getStudentsByJoinDate(req, year);
    if (!masterStudentList) {
      throw Error(code.data_not_found);
    }

    for (const student of masterStudentList) {
      const index = masterClassMembers.findIndex((i) => +i.student_id === +student.student_id);
      if (index < 0) {
        classMembers.push({
          student_id: +student.student_id,
          student_name: student.student_name,
          nis: student.nis,
          religion_id: +student.religion_id,
        });
      }
    }
    // [END] check allocated students

    // [START] get students detail
    if (classMembers.length > 0) {
      // get students detail
      const studentsDetail = await getDetailStudents(
        req,
        classMembers.map((i) => +i.student_id)
      );
      if (!studentsDetail) {
        throw Error(code.data_not_found);
      }

      // get religions
      const religions = await getReligions(req);
      if (!religions) {
        throw Error(code.data_not_found);
      }

      for (const classMember of classMembers) {
        const index = studentsDetail.findIndex((i) => +i.student_id === +classMember.student_id);
        if (index < 0) {
          continue;
        }

        classMember.student_name = studentsDetail[index].student_name;
        classMember.nis = studentsDetail[index].nis;
        classMember.religion_id = +studentsDetail[index].religion_id;
      }

      for (const classMember of classMembers) {
        const index = religions.findIndex((i) => +i.religion_id === +classMember.religion_id);
        if (index < 0) {
          continue;
        }

        classMember.religion_name = religions[index].religion_name;
      }
    }
    // [END] get students detail

    success(res, {
      status: true,
      version: req.version,
      message: 'success',
      data: classMembers,
      meta: null,
    });
  } catch (e) {
    failure(res, e);
  }
}
Editor is loading...