candidate-registration-external

mail@pastecode.io avatar
unknown
typescript
2 years ago
13 kB
3
Indexable
Never
import { Request, Response } from 'lambda-api';
import { ClientBase } from 'pg';
import { failure, success } from '../../../../shared/libs/response';
import { getAuth } from '../../../../shared/libs/auth';
import { getBatches, getBatchSteps, incrementAlphanumeric } from '../helper/get-data';
import { getStudentByStudentIds } from '../helper/post-data';
import { batchInsert } from '../../../../shared/functions/batch-process';
import code from '../../../../shared/libs/code';

const candidateColumns = [
  'created_at',
  'tenant_uuid',
  'batch_id',
  'candidate_name',
  'nisn',
  'form_number',
  'enroll_school_location_id',
  'enroll_school_level_id',
  'enroll_year_level_id',
  'enrollment_status',
  'origin_school',
  'gender',
  'religion_id',
  'place_of_birth',
  'date_of_birth',
  'birth_certificate_number',
  'nationality_id',
  'identification_number',
  'passport_number',
  'passport_expiry_date',
  'kitas_number',
  'kitas_expiry_date',
  'phone_number',
  'cellular_number',
  'email',
  'address',
  'neighbourhood_number',
  'hamlet_number',
  'urban_village',
  'sub_district',
  'postal_code',
  'living_with',
  'distance_to_school',
  'estimated_time_to_school',
  'transport_to_school',
  'child_status',
  'child_order',
  'number_of_child',
  'special_conditions',
  'kks_number',
  'kps_pkh_receiver',
  'kps_pkh_number',
  'kip_receiver',
  'kip_number',
  'kip_holder_name',
  'user_uuid',
  'candidate_sibling_group'
];

const returningCandidateColumns = [
  'candidate_id',
  'batch_id',
  'gender',
  'place_of_birth',
  'date_of_birth',
  'candidate_name',
  'religion_id',
  'enroll_school_level_id',
  'enroll_school_location_id',
];

const candidateStatusColumns = [
  'created_at',
  'tenant_uuid',
  'candidate_id',
  'current_status',
  'next_status',
]

const parentColumns = [
  'created_at',
  'tenant_uuid',
  'candidate_id',
  'parent_type',
  'parent_name',
  'gender',
  'religion_id',
  'place_of_birth',
  'date_of_birth',
  'nationality_id',
  'identification_number',
  'passport_number',
  'passport_expiry_date',
  'kitas_number',
  'kitas_expiry_date',
  'phone_number',
  'cellular_number',
  'email',
  'address',
  'neighbourhood_number',
  'hamlet_number',
  'urban_village',
  'sub_district',
  'postal_code',
  'education',
  'employment_company',
  'job_title',
  'salary_range',
  'user_uuid',
];

const siblingColumns = [
  'created_at',
  'tenant_uuid',
  'candidate_id',
  'sibling_name',
  'year_level_id',
  'gender',
  'religion_id',
  'place_of_birth',
  'date_of_birth',
  'sibling_same_school',
  'sibling_same_enrolling',
  'sibling_candidate_id',
  'sibling_nis'
];

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

    const queryResult = await db.query(`
      select max(candidate_sibling_group) as max
      from candidate
      where tenant_uuid = $1
    `, [tenantUuid]);


    return ++queryResult.rows[0].max;

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

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

    const auth = getAuth(req);

    const result = {
      candidates: [],
      candidates_status: [],
      parents: [],
      siblings: [],
    };

    const parentProfiles = req.body.parent_profile;
    const candidateProfiles = req.body.student_profile;
    const siblingProfiles = req.body.sibling_profile;

    const batchIds = candidateProfiles.students.map(student => +student.batch_id).filter(student => student.batch_id !== null);

    const batches = await getBatches(req.namespace.db, auth.tenant_uuid, batchIds);

    if (!batches) {
      throw Error('Batch not found!');
    }

    const students = candidateProfiles.students;

    let candidateSiblingGroup = null;

    if (students.length > 1) {
      candidateSiblingGroup = await getMaxCandidateSiblingGroup(req.namespace.db, auth.tenant_uuid);
    }

    for (const batch of batches) {

      const candidatePerBatch = students.filter(student => +student.batch_id === +batch.batch_id);

      let formNumber = batch.form_code;

      if (formNumber) {
        candidatePerBatch.forEach(candidate => {

          candidate.user_uuid = auth.user_uuid;
          candidate.form_number = incrementAlphanumeric(formNumber);
          candidate.candidate_sibling_group = candidateSiblingGroup;

          // reassign form_number to the last form_number
          formNumber = candidate.form_number;
        });
      }

    }

    await req.namespace.db.query('BEGIN');

    const candidates = await batchInsert(
      req.namespace.db,
      auth.tenant_uuid,
      'candidate',
      students,
      candidateColumns,
      returningCandidateColumns,
    );

    if (!candidates) {
      throw Error('Failed to create candidate!');
    }

    const batchSteps = await getBatchSteps(req.namespace.db, auth.tenant_uuid, batchIds);

    if (!batchSteps) {
      throw Error('Failed to get batch steps!');
    }

    candidates.forEach(candidate => {

      const steps = batchSteps.filter(batch => +batch.batch_id === +candidate.batch_id);

      candidate.current_status = steps.length > 0 ? batchSteps[0].step_codes[0] : null;
      candidate.next_status = steps.length > 0 ? batchSteps[0].step_codes[1] : null;

      delete candidate.batch_id;

    });

    const candidateStatuses = await batchInsert(
      req.namespace.db,
      auth.tenant_uuid,
      'candidate_status',
      candidates,
      candidateStatusColumns,
    );

    if (!candidateStatuses) {
      throw Error('Failed to create candidate status!');
    }

    const parents = [];

    for (const candidate of candidates) {

      if (
        parentProfiles.father.parent_name
        && parentProfiles.father.parent_type === 'Father'
      ) {
        parentProfiles.father.candidate_id = +candidate.candidate_id;
        parentProfiles.father.user_uuid = auth.user_uuid;
        // parentProfiles.father.passport_expiry_date = new Date(parentProfiles.father.passport_expiry_date) || new Date();
        // parentProfiles.father.date_of_birth = new Date(parentProfiles.father.date_of_birth) || new Date();
        parents.push(parentProfiles.father);
      }

      if (
        parentProfiles.mother.parent_name
        && parentProfiles.mother.parent_type === 'Mother'
      ) {
        parentProfiles.mother.candidate_id = +candidate.candidate_id;
        parentProfiles.mother.user_uuid = auth.user_uuid;
        // parentProfiles.mother.passport_expiry_date = new Date(parentProfiles.mother.passport_expiry_date) || new Date();
        // parentProfiles.mother.date_of_birth = new Date(parentProfiles.mother.date_of_birth) || new Date();
        parents.push(parentProfiles.mother);
      }

      if (
        parentProfiles.guardian.parent_name
      ) {
        parentProfiles.guardian.candidate_id = +candidate.candidate_id;
        parentProfiles.guardian.user_uuid = auth.user_uuid;
        // parentProfiles.guardian.passport_expiry_date = new Date(parentProfiles.guardian.passport_expiry_date) || new Date();
        // parentProfiles.guardian.date_of_birth = new Date(parentProfiles.guardian.date_of_birth) || new Date();
        parents.push(parentProfiles.guardian);
      }

    }

    const candidateParents = await batchInsert(
      req.namespace.db,
      auth.tenant_uuid,
      'parents',
      parents,
      parentColumns,
    );

    if (!candidateParents) {
      throw Error('Failed to create parent!');
    }

    const siblings = {
      students: siblingProfiles.siblings
        .filter(sibling => sibling.student_id !== null)
        .map(sibling => {
          return {
            candidate_id: null,
            student_id: sibling.student_id,
            sibling_candidate_id: null,
            sibling_nis: null,
            gender: sibling.gender,
            place_of_birth: sibling.place_of_birth,
            date_of_birth: sibling.date_of_birth ? new Date(sibling.date_of_birth) : null,
            sibling_name: sibling.sibling_name,
            religion_id: sibling.religion_id,
            sibling_same_school: null,
            sibling_same_enrolling: false,
          }
        }),
      candidates: [],
      externals: siblingProfiles.siblings
        .filter(sibling => sibling.student_id === null)
        .map(sibling => {
          return {
            candidate_id: null,
            sibling_candidate_id: null,
            sibling_nis: null,
            gender: sibling.gender,
            place_of_birth: sibling.place_of_birth,
            date_of_birth: sibling.date_of_birth ? new Date(sibling.date_of_birth) : null,
            sibling_name: sibling.sibling_name,
            religion_id: sibling.religion_id,
            sibling_same_school: false,
            sibling_same_enrolling: false,
          }
        }),
    };

    if (siblings.students.length > 0) {

      const studentSiblings = await getStudentByStudentIds(req, siblings.students.map(sibling => +sibling.student_id));

      for (const sibling of siblings.students) {

        const index = studentSiblings.findIndex(student => +student.student_id === +sibling.student_id);

        sibling.sibling_nis = index !== -1 ? studentSiblings[index].nis : null;

      }

      siblings.students = [];
      siblings.students.push(...siblings.students.filter(sibling => sibling.sibling_nis !== null));

      const externalSiblings = siblings.students.filter(sibling => sibling.sibling_nis === null);

      if (externalSiblings.length > 0) {

        externalSiblings.forEach(sibling => {

          sibling.sibling_same_school = false;

          delete sibling.student_id;

          siblings.externals.push(sibling);
        });
      }

    }

    if (candidates.length > 1) {

      for (const candidate of candidates) {

        const candidateSiblings = candidates.filter(sibling => +sibling.candidate_id !== +candidate.candidate_id);

        if (candidateSiblings.length > 0) {
          siblings.candidates.push(...candidateSiblings.map(i => {
            return {
              candidate_id: candidate.candidate_id,
              sibling_candidate_id: i.candidate_id,
              gender: i.gender,
              place_of_birth: i.place_of_birth,
              date_of_birth: new Date(i.date_of_birth),
              sibling_name: i.candidate_name,
              religion_id: i.religion_id,
              sibling_same_school: (
                +candidate.enroll_school_level_id === +i.enroll_school_level_id
                && +candidate.enroll_school_location_id === +i.enroll_school_location_id
              ),
              sibling_same_enrolling: true,
              sibling_nis: null,
            }
          }))
        }

        if (siblings.externals.length > 0) {
          siblings.externals = siblings.externals.forEach(i => {
            i.candidate_id = candidate.candidate_id;
          });
        }

        if (siblings.students.length > 0) {
          siblings.students = siblings.students.forEach(i => {
            i.sibling_same_school = (
              +candidate.enroll_school_level_id === +i.enroll_school_level_id
              && +candidate.enroll_school_location_id === +i.enroll_school_location_id
            );
            i.candidate_id = candidate.candidate_id;
          });
        }

      }

    } else {

      if (siblings.externals.length > 0) {
        siblings.externals.forEach(i => {
          i.candidate_id = candidates[0].candidate_id;
        });
      }

      if (siblings.students.length > 0) {
        siblings.students.forEach(i => {
          i.candidate_id = candidates[0].candidate_id;
          i.sibling_same_school = (
            +i.enroll_school_level_id === +candidates[0].enroll_school_level_id
            && +i.enroll_school_location_id === +candidates[0].enroll_school_location_id
          );
        });
      }

    }



    const masterSiblings = [
      ...siblings.externals,
      ...siblings.students,
      ...siblings.candidates,
    ].filter(i => i !== undefined);

    result.siblings = await batchInsert(
      req.namespace.db,
      auth.tenant_uuid,
      'sibling',
      masterSiblings,
      siblingColumns,
    );

    result.candidates = candidates;
    result.candidates_status = candidateStatuses;
    result.parents = candidateParents;

    await req.namespace.db.query('COMMIT');

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