sfasdf

mail@pastecode.io avatar
unknown
typescript
2 years ago
30 kB
1
Indexable
Never
import {ClientBase} from 'pg';
import {Endpoint} from 'aws-sdk';
import { Request, Response } from 'lambda-api';
import {failure, success} from '../../../shared/libs/response';
import {getAuth, setAuth} from '../../../shared/libs/auth';
import code from '../../../shared/libs/code';
import lambda from '../../../shared/libs/lambda';
import config from '../../../shared/libs/config';
import {ApiModel} from '../../../shared/models/api.model';

async function querySurveyDetail(db: ClientBase, tenantUuid: string, surveyId: number): Promise<any> {
    try {

        const queryResult = await db.query(`
            SELECT survey_id, survey_start_date, survey_end_date, school_level_id, survey_title_first_language, survey_title_second_language,
                   survey_description_first_language, survey_description_second_language, school_location_id, survey_closing_first_language,
                   survey_closing_second_language, is_mandatory, sibling_group, survey_group
            FROM survey
            WHERE deleted_at IS NULL
              AND tenant_uuid = $1
              AND survey_id = $2
        `, [
            tenantUuid,
            surveyId
        ]);

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

        return queryResult.rows[0];

    } catch (e) {
        console.error('[ERROR-FUNC] - func: querySurveyDetail', e);
        throw Error(code.database_error);
    }
}

async function getAcademicYear(req: Request, params: any): Promise<any> {
    let year: any = [];

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

        const result = await lambda.invoke({
            FunctionName: `academic-service-${config.stage}-school-level-v1`,
            InvocationType: 'RequestResponse',
            LogType: 'Tail',
            Payload: JSON.stringify({
                    ...setAuth(req),
                    httpMethod: 'POST',
                    path: '/academic/school-level/v1/get-survey-academic-year',
                    body: params
                }
            )
        })
            .promise();

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

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

    return year;
}

async function querySurveyUserDetail(db: ClientBase, tenantUuid: string, surveyId: number): Promise<any> {
    try {

        const queryResult = await db.query(`
            SELECT role_id, user_id, user_uuid
            FROM survey_role_user_relation
            WHERE deleted_at IS NULL
              AND tenant_uuid = $1
              AND survey_id = $2
        `, [
            tenantUuid,
            surveyId
        ]);

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

        return queryResult.rows;

    } catch (e) {
        console.error('[ERROR-FUNC] - func: querySurveyRoleDetail', e);
        throw Error(code.database_error);
    }
}

async function queryGetFormDetail(db: ClientBase, tenantUuid: string, surveyId): Promise<any> {
    try {
        const queryResult = await db.query(`
            SELECT
                (SELECT COALESCE(
                                json_agg(
                                        jsonb_build_object(
                                                'survey_form_id', survey_form_transaction.survey_form_id,
                                                'survey_form_type_id', survey_form_transaction.survey_form_type_id,
                                                'form_type', CASE WHEN survey_form_transaction.survey_form_type_id = 1 THEN 'Linear Scale'
                                                                  WHEN survey_form_transaction.survey_form_type_id = 2 THEN 'Multiple Choice'
                                                                  WHEN survey_form_transaction.survey_form_type_id = 3 THEN 'Multiple Choice Grid'
                                                                  WHEN survey_form_transaction.survey_form_type_id = 4 THEN 'Checkbox Choice'
                                                                  WHEN survey_form_transaction.survey_form_type_id = 5 THEN 'Checkbox Choice Grid'
                                                                  WHEN survey_form_transaction.survey_form_type_id = 6 THEN 'Paragraph Answer Text'
                                                                  WHEN survey_form_transaction.survey_form_type_id = 7 THEN 'Checkbox and Short Answer Text'
                                                                  WHEN survey_form_transaction.survey_form_type_id = 8 THEN 'Rating Scale'
                                                    END,
                                                'survey_form_title_first_language', survey_form_transaction.survey_form_title_first_language,
                                                'survey_form_title_second_language', survey_form_transaction.survey_form_title_second_language,
                                                'survey_form_description_first_language', survey_form_transaction.survey_form_description_first_language,
                                                'survey_form_description_second_language', survey_form_transaction.survey_form_description_second_language,
                                                'max_question', CASE WHEN survey_form_transaction.survey_form_type_id = 7 THEN max_question
                                                                     ELSE NULL
                                                    END,
                                                'linear_scale_minimal', null,
                                                'linear_scale_minimal_description', null,
                                                'linear_scale_minimal_description_second', null,
                                                'linear_scale_maximal', null,
                                                'linear_scale_maximal_description', null,
                                                'linear_scale_maximal_description_second', null
                                            )), '[]'::json) AS detail
                 FROM survey_form_transaction
                 WHERE survey_form_transaction.deleted_at IS NULL
                   AND survey_form_transaction.tenant_uuid = $1
                   AND survey_form_transaction.survey_id = $2
                ) AS form_detail
            FROM survey_form_transaction
        `, [
            tenantUuid,
            surveyId
        ]);

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

        return queryResult.rows[0];

    } catch (e) {
        console.error('[ERROR-FUNC] - func: queryGetForm', e);
        throw Error(code.database_error);
    }
}

async function querySurveyGetScaleMaxNumber(db: ClientBase, tenantUuid: string, formId: number): Promise<any> {
    try {

        const queryResult = await db.query(`
            SELECT attribute_order, score_range_first_language, score_range_second_language
            FROM survey_form_attribute
            WHERE deleted_at IS NULL
              AND tenant_uuid = $1
              AND survey_form_id = $2
            ORDER BY attribute_order DESC
            LIMIT 1

        `, [
            tenantUuid,
            formId
        ]);

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

        return queryResult.rows[0];

    } catch (e) {
        console.error('[ERROR-FUNC] - func: querySurveyGetScaleMaxNumber', e);
        throw Error(code.database_error);
    }
}

async function querySurveyGetScaleMinNumber(db: ClientBase, tenantUuid: string, formId: number): Promise<any> {
    try {

        const queryResult = await db.query(`
            SELECT attribute_order, score_range_first_language, score_range_second_language
            FROM survey_form_attribute
            WHERE deleted_at IS NULL
              AND tenant_uuid = $1
              AND survey_form_id = $2
            ORDER BY attribute_order ASC
            LIMIT 1

        `, [
            tenantUuid,
            formId
        ]);

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

        return queryResult.rows[0];

    } catch (e) {
        console.error('[ERROR-FUNC] - func: querySurveyGetScaleMinNumber', e);
        throw Error(code.database_error);
    }
}

async function querySurveyQuestionDetail(db: ClientBase, tenantUuid: string, surveyFormId: number): Promise<any> {
    try {

        const queryResult = await db.query(`
            SELECT survey_question_id, question_first_language AS survey_form_question_first_language, question_second_language AS survey_form_question_second_language
            FROM survey_question_transaction
            WHERE deleted_at IS NULL
              AND tenant_uuid = $1
              AND survey_form_id = $2
        `, [
            tenantUuid,
            surveyFormId
        ]);

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

        return queryResult.rows;

    } catch (e) {
        console.error('[ERROR-FUNC] - func: querySurveyQuestionDetail', e);
        throw Error(code.database_error);
    }
}

async function queryAttributeDetailByQuestion(db: ClientBase, tenantUuid: string, questionId: number): Promise<any> {
    try {

        const queryResult = await db.query(`
            SELECT survey_form_attribute_id, survey_form_id, survey_question_id, attribute_order, score_range_first_language,
                   score_range_second_language, option_first_language AS survey_form_option_first_language, option_second_language AS survey_form_option_second_language, row_first_language,
                   row_second_language, column_first_language, column_second_language
            FROM survey_form_attribute
            WHERE deleted_at IS NULL
              AND tenant_uuid = $1
              AND survey_question_id = $2
        `, [
            tenantUuid,
            questionId
        ]);

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

        return queryResult.rows;

    } catch (e) {
        console.error('[ERROR-FUNC] - func: queryAttributeDetailByQuestion', e);
        throw Error(code.database_error);
    }
}

async function queryAttributeDetailByForm(db: ClientBase, tenantUuid: string, formId: number): Promise<any> {
    try {

        const queryResult = await db.query(`
            SELECT survey_form_attribute_id, survey_form_id, survey_question_id, attribute_order, score_range_first_language,
                   score_range_second_language, option_first_language AS survey_form_option_first_language, option_second_language AS survey_form_option_second_language, row_first_language,
                   row_second_language, column_first_language, column_second_language
            FROM survey_form_attribute
            WHERE deleted_at IS NULL
              AND tenant_uuid = $1
              AND survey_form_id = $2
        `, [
            tenantUuid,
            formId
        ]);

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

        return queryResult.rows;

    } catch (e) {
        console.error('[ERROR-FUNC] - func: queryAttributeDetailByForm', e);
        throw Error(code.database_error);
    }
}

async function getSchoolName(req: Request, params): Promise<any> {
    let schoolName: any = [];

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

        const result = await lambda.invoke({
            FunctionName: `academic-service-${config.stage}-school-location-v1`,
            InvocationType: 'RequestResponse',
            LogType: 'Tail',
            Payload: JSON.stringify({
                    ...setAuth(req),
                    httpMethod: 'POST',
                    path: '/academic/school-location/v1/school-location-search',
                    body: params
                }
            )
        })
            .promise();

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

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

    return schoolName;
}

async function getData(req: Request, params: any): Promise<any> {
    let dataSurvey: any = [];

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

        const result = await lambda.invoke({
            FunctionName: `academic-service-${config.stage}-school-level-v1`,
            InvocationType: 'RequestResponse',
            LogType: 'Tail',
            Payload: JSON.stringify({
                    ...setAuth(req),
                    httpMethod: 'POST',
                    path: '/academic/school-level/v1/get-survey-data',
                    body: params
                }
            )
        })
            .promise();

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

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

    return dataSurvey;
}

// PARENT
async function getParentDetail(req: Request): Promise<any> {
    let parent: any = [];

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

        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/get-parent-survey-data',
                }
            )
        })
            .promise();

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

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

    return parent;
}

// STAFF
async function getStaffData(req: Request, staffs: any ): Promise<any> {
    let staff: any = [];

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

        const result = await lambda.invoke({
            FunctionName: `personnel-service-${config.stage}-personnel-v1`,
            InvocationType: 'RequestResponse',
            LogType: 'Tail',
            Payload: JSON.stringify({
                    ...setAuth(req),
                    httpMethod: 'POST',
                    path: '/personnel/v1/get-staff-survey-data/',
                    body: staffs,
                }
            )
        })
            .promise();

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

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

    return staff;
}

async function getStudent(req: Request, roleName: string, params: any ): Promise<any> {
    let role: any = [];
    try {
        lambda.endpoint = new Endpoint('http://localhost:3004')

        const result = await lambda.invoke({
            FunctionName: `auth-service-${config.stage}-api-v1`,
            InvocationType: 'RequestResponse',
            LogType: 'Tail',
            Payload: JSON.stringify({
                    ...setAuth(req),
                    httpMethod: 'POST',
                    path: '/auth/v1/get-user-role-survey',
                    body: {roleName, params},
                }
            )
        })
            .promise();

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

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

    return role;
}

async function getStudentData(req: Request, students: any): Promise<any> {
    let student: any = [];

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

        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/get-student-survey-data',
                    body: students,
                }
            )
        })
            .promise();

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

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

    return student;
}

async function getRoleId(req: Request, roleName: string): Promise<any> {
    let role: any = [];

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

        const result = await lambda.invoke({
            FunctionName: `auth-service-${config.stage}-api-v1`,
            InvocationType: 'RequestResponse',
            LogType: 'Tail',
            Payload: JSON.stringify({
                    ...setAuth(req),
                    httpMethod: 'POST',
                    path: '/auth/v1/get-user-role-survey',
                    body: roleName
                }
            )
        })
            .promise();

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

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

    return role;
}

async function getStaff(req: Request, roleName: string, params: any ): Promise<any> {
    let role: any = [];

    try {
        lambda.endpoint = new Endpoint('http://localhost:3004')
        const result = await lambda.invoke({
            FunctionName: `auth-service-${config.stage}-api-v1`,
            InvocationType: 'RequestResponse',
            LogType: 'Tail',
            Payload: JSON.stringify({
                    ...setAuth(req),
                    httpMethod: 'POST',
                    path: '/auth/v1/get-user-role-survey',
                    body: {roleName, params},
                }
            )
        })
            .promise();

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

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

    return role;
}

async function processData (db, tenantUuid, data: Array<any>): Promise<any> {
    try {

        for (const form of data) {
            // LINEAR SCALE
            if (form.survey_form_type_id === 1) {
                // MAXIMUM SCALE
                const maximum = await querySurveyGetScaleMaxNumber(db, tenantUuid, form.survey_form_id)
                form.linear_scale_maximal = maximum.attribute_order
                form.linear_scale_maximal_description = maximum.score_range_first_language
                form.linear_scale_maximal_description_second = maximum.score_range_second_language

                // MINIMUM SCALE
                const minimum = await querySurveyGetScaleMinNumber(db, tenantUuid, form.survey_form_id)
                form.linear_scale_minimal = minimum.attribute_order
                form.linear_scale_minimal_description = minimum.score_range_first_language
                form.linear_scale_minimal_description_second = minimum.score_range_second_language

                // QUESTION
                const question = await querySurveyQuestionDetail(db, tenantUuid, form.survey_form_id)
                form.form_question = question
            }

            // MULTIPLE CHOICE
            if (form.survey_form_type_id === 2) {
                const question = await querySurveyQuestionDetail(db, tenantUuid, form.survey_form_id)
                for (const q of question) {
                    const option = await queryAttributeDetailByQuestion(db, tenantUuid, q.survey_question_id)
                    q.form_option = option
                }
                form.form_question = question
            }

            // MULTIPLE CHOICE GRID
            if (form.survey_form_type_id === 3) {
                const question = await querySurveyQuestionDetail(db, tenantUuid, form.survey_form_id)
                form.form_question = question

                const option = await queryAttributeDetailByForm(db, tenantUuid, form.survey_form_id)
                form.form_option = option
            }

            // CHECKBOX CHOICE
            if (form.survey_form_type_id === 4) {
                const question = await querySurveyQuestionDetail(db, tenantUuid, form.survey_form_id)
                for (const q of question) {
                    const option = await queryAttributeDetailByQuestion(db, tenantUuid, q.survey_question_id)
                    q.form_option = option
                }
                form.form_question = question
            }

            // CHECKBOX CHOICE GRID
            if (form.survey_form_type_id === 5) {
                const question = await querySurveyQuestionDetail(db, tenantUuid, form.survey_form_id)
                form.form_question = question

                const option = await queryAttributeDetailByForm(db, tenantUuid, form.survey_form_id)
                form.form_option = option
            }

            // PARAGRAPH ANSWER TEXT
            if (form.survey_form_type_id === 6) {
                const question = await querySurveyQuestionDetail(db, tenantUuid, form.survey_form_id)
                form.form_question = question
            }

            // CHECKBOX AND SHORT ANSWER TEXT
            if (form.survey_form_type_id === 7) {
                const question = await querySurveyQuestionDetail(db, tenantUuid, form.survey_form_id)
                form.form_question = question
            }

            // RATING SCALE
            if (form.survey_form_type_id === 8) {
                const question = await querySurveyQuestionDetail(db, tenantUuid, form.survey_form_id)
                form.form_question = question
            }
        }

        return data;

    } catch (e) {
        console.error('[ERROR-FUNC]: processData', e)
        throw Error (code.database_error);
    }
}

export default async function surveyDetail (req: Request, res: Response): Promise<any> {
    try {

        const auth = getAuth(req)
        const surveyId = +req.params.survey_id

        if (!surveyId) {
            throw Error(code.input_invalid);
        }

        const result = {
            survey: {},
            user: {
                student: [],
                parent: [],
                staff: [],
            },
            form: {},
            role: {
                student: null,
                parent: null,
                staff: null
            },
        }

        const surveyData = await querySurveyDetail(req.namespace.db, auth.tenant_uuid, surveyId);

        if (!surveyData) {
            throw Error(code.data_not_found);
        }

        surveyData.start_date = surveyData.survey_start_date;
        surveyData.end_date = surveyData.survey_end_date


        const academicYear = await getAcademicYear(req, surveyData)

        if (!academicYear) {
            throw Error(code.data_not_found)
        } else if (academicYear) {
            surveyData.academic_year = academicYear.academic_year;
        }

        const schoolName = await getSchoolName(req, surveyData.school_location_id) || []

        if (!schoolName) {
            throw Error(code.data_not_found)
        } else if (schoolName) {
            surveyData.school_short_name = schoolName.school_short_name;
        }

        result.survey = surveyData

        const studentUsers = await getStudent(req, 'STUDENT', surveyData);

        const studentTemp = studentUsers.users

        const studentData = await getStudentData(req, studentTemp);

        const dataStudent = await getData(req, surveyData) || [];

        const parentUsers = await getRoleId(req, 'PARENT');

        const staffUsers = await getStaff(req, 'STAFF', surveyData);

        const staffTemp = staffUsers.users

        const staffData = await getStaffData(req, staffTemp);

        const users = await querySurveyUserDetail(req.namespace.db, auth.tenant_uuid, surveyId);

        if (!users) {
            throw Error(code.data_not_found);
        }

        const newStudent = [];
        const newParent = [];
        const newStaff = [];

        for (let user of users) {
            if (+user.role_id === studentUsers.roleId) {
                for (const student of studentData) {
                    if (!student) {
                        continue;
                    }
                    if (user.user_uuid === student.user_uuid) {
                        result.role.student = 'Student'
                        user.student_id = student.student_id;
                        user.student_name = student.student_name;
                        user.nis = student.nis;

                        const index  = dataStudent.findIndex(j => +j.student_id === +user.student_id);
                        if (index !== -1) {
                            user.year_level_name = dataStudent[index].year_level_name;
                            user.class_name = dataStudent[index].class_name;
                            user.school_short_name = dataStudent[index].school_short_name;
                        }

                        newStudent.push(user);
                        break;
                    }
                }
            } else if (+user.role_id === +parentUsers.roleId) {
                result.role.parent = 'Parent'

                const parents = await getParentDetail(req) || [];

                if (!parents) {
                    throw Error (code.data_not_found);
                }

                if (parents.length > 0) {
                    for (const parent of dataStudent) {
                        const index  = parents.findIndex(i => +i.student_id === +parent.student_id);

                        if (index === -1) {
                            continue;
                        }

                        parent.student_name = parents[index].student_name;
                        parent.parent_name = parents[index].parent_name;
                        parent.user_uuid = parents[index].user_uuid;
                    }
                }

                for (const parent of dataStudent) {
                    if (user.user_uuid === parent.user_uuid) {
                        parent.user_id = user.user_id;
                        user = parent;
                        newParent.push(user);
                        break;
                    }
                }
            } else {
                for (const staff of staffData) {
                    if (!staff) {
                        continue;
                    }
                    
                    if (user.user_uuid === staff.user_uuid) {
                        result.role.staff = 'Staff'
                        staff.user_id = user.user_id;
                        user = staff;
                        newStaff.push(user);
                        break;
                    }
                }
            }
        }

        result.user.student = newStudent
        result.user.parent = newParent
        result.user.staff = newStaff

        const formDetail = await queryGetFormDetail(req.namespace.db, auth.tenant_uuid, surveyId)

        if (!formDetail) {
            throw Error(code.data_not_found)
        }

        const detail = await processData(req.namespace.db, auth.tenant_uuid, formDetail.form_detail)

        if (!detail) {
            throw Error(code.data_not_found)
        }

        result.form = detail

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