File "StudentsImport.php"

Full Path: /home/trinadezambia/public_html/admin_panel/app/Imports/StudentsImport.php
File size: 10.83 KB
MIME-type: text/x-php
Charset: utf-8

<?php

namespace App\Imports;

use App\Jobs\SendBulkStudentEmail;
use App\Repositories\FormField\FormFieldsInterface;
use App\Repositories\SessionYear\SessionYearInterface;
use App\Repositories\Student\StudentInterface;
use App\Repositories\Subscription\SubscriptionInterface;
use App\Repositories\User\UserInterface;
use App\Rules\TrimmedEnum;
use App\Services\CachingService;
use App\Services\ResponseService;
use App\Services\SchoolDataService;
use App\Services\UserService;
use Carbon\Carbon;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Queue;
use Illuminate\Support\Facades\Validator;
use JsonException;
use Maatwebsite\Excel\Concerns\ToCollection;
use Maatwebsite\Excel\Concerns\WithHeadingRow;
use Maatwebsite\Excel\Concerns\WithMultipleSheets;
use Str;
use Throwable;
use TypeError;

class StudentsImport implements WithMultipleSheets
{
    private mixed $classSectionID;
    private mixed $sessionYearID;
    private mixed $is_send_notification;

    public function __construct($classSectionID, $sessionYearID, $is_send_notification)
    {
        $this->classSectionID = $classSectionID;
        $this->sessionYearID = $sessionYearID;
        $this->is_send_notification = $is_send_notification;
    }

    /**
     * @throws Throwable
     */
    public function sheets(): array
    {
        return [
            new FirstSheetImport($this->classSectionID, $this->sessionYearID, $this->is_send_notification)
        ];
    }
}

class FirstSheetImport implements ToCollection, WithHeadingRow
{
    private mixed $classSectionID;
    private mixed $sessionYearID;
    private mixed $is_send_notification;

    /**
     * @param $classSectionID
     * @param $sessionYearID
     * @param $is_send_notification
     */

    // Import the Class Section and Repositories
    public function __construct($classSectionID, $sessionYearID, $is_send_notification)
    {
        $this->classSectionID = $classSectionID;
        $this->sessionYearID = $sessionYearID;
        $this->is_send_notification = $is_send_notification;
    }

    /**
     * @throws JsonException
     * @throws Throwable
     */
    public function collection(Collection $collection)
    {
        $student = app(StudentInterface::class);
        $formFields = app(FormFieldsInterface::class);
        $sessionYear = app(SessionYearInterface::class);

        $subscription = app(SubscriptionInterface::class);
        $user = app(UserInterface::class);
        $cache = app(CachingService::class);

        // $collection->toArray(); if getting null first_name then skip after that row
        $collection = $collection->filter(function ($row) {
            return $row['first_name'] != '';
        });

        $validator = Validator::make($collection->toArray(), [
            '*.first_name'     => 'required',
            '*.last_name'      => 'required',
            '*.mobile'         => 'nullable|regex:/^([0-9\s\-\+\(\)]*)$/',
            '*.gender'         => ['required', new TrimmedEnum(['male', 'female', 'Male', 'Female']), 'regex:/^(male|female)$/i'],
            '*.guardian_gender' => ['required', 'regex:/^(male|female)$/i'],
            '*.dob'            => 'required|date',
            '*.admission_date' => 'required|date',
            '*.current_address'      => 'required',
            '*.permanent_address'      => 'required',
            '*.guardian_email'      => 'required|email',
            '*.guardian_first_name' => 'required',
            '*.guardian_last_name'  => 'required',
            '*.guardian_mobile'     => 'required|regex:/^([0-9\s\-\+\(\)]*)$/',
        ], [
            '*.first_name.required' => 'Please enter the first name.',
            '*.last_name.required' => 'Please enter the last name.',
            '*.mobile.required' => 'Please enter the mobile number.',
            '*.gender.required' => 'Please select the gender.',
            '*.gender.regex' => 'Gender must be either Male or Female only.',
            '*.guardian_gender.required' => 'Please select the gender.',
            '*.guardian_gender.regex' => 'Guardian gender must be either Male or Female only.',
            '*.dob.date' => 'Please ensure that the dob date format you use is either DD-MM-YYYY or MM/DD/YYYY.',
            '*.admission_date.date' => 'Please ensure that the admission date format you use is either DD-MM-YYYY or MM/DD/YYYY.',
            '*.guardian_email.required' => 'Please enter the guardian email.',
            '*.guardian_email.email' => 'Please enter a valid email address.',
            '*.guardian_first_name.required' => 'Please enter the guardian first name.',
            '*.guardian_last_name.required' => 'Please enter the guardian last name.',
            '*.guardian_mobile.required' => 'Please enter the guardian mobile number.',

        ]);

        //             If Validation fails then this will throw the ValidationFail Exception
        $validator->validate();

        // Check free trial package
        $today_date = Carbon::now()->format('Y-m-d');
        $get_subscription = $subscription->builder()->doesntHave('subscription_bill')->whereDate('start_date', '<=', $today_date)->where('end_date', '>=', $today_date)->whereHas('package', function ($q) {
            $q->where('is_trial', 1);
        })->first();

        $userService = app(UserService::class);
        $sessionYear = $sessionYear->findById($this->sessionYearID);

        DB::beginTransaction();
        foreach ($collection as $row) {

            // Check free trial package

            if ($get_subscription) {
                $systemSettings = $cache->getSystemSettings();
                $count_student = $user->builder()->role('Student')->withTrashed()->count();
                if ($count_student >= $systemSettings['student_limit']) {
                    $message = "The free trial allows only " . $systemSettings['student_limit'] . " students.";
                    ResponseService::errorResponse($message);
                    break;
                }
            }
            $row = $row->toArray();
            // Find the index of the key after which to split the array
            $splitIndex = array_search('guardian_mobile', array_keys($row)) + 1;

            // Get The Extra Details of it
            $extraDetailsFields = array_slice($row, $splitIndex);


            $guardian = $userService->createOrUpdateParent($row['guardian_first_name'], $row['guardian_last_name'], $row['guardian_email'], $row['guardian_mobile'], $row['guardian_gender']);
            // $get_student = $student->builder()->select('user_id')->orderBy('id', 'desc')->first();
            // $admission_no = $sessionYear->name . '0' .  Auth::user()->school_id . '0' . ($get_student->user_id + 1);

            if (!$guardian) {
                ResponseService::errorResponse('Email address is already associated with another role. Please use a different email and try again.');
            }

            // Generate unique uuid
            $admission_no = null;
            do {
                $uuid = mt_rand(100000000, 999999999);
                $admission_no = $sessionYear->name . '' .  Auth::user()->school_id . '' . $uuid;
            } while ($student->builder()->where('admission_no', $admission_no)->exists()); // Check uniqueness;

            $extraDetails = array();
            // Check that Extra Details Exists
            if (!empty($extraDetailsFields)) {
                $extraFieldName = array_map(static function ($d) {
                    return str_replace("_", " ", $d);
                }, array_keys($extraDetailsFields));
                $formFieldsCollection = $formFields->builder()->whereIn('name', $extraFieldName)->get();
                $extraFieldValidationRules = [];
                foreach ($formFieldsCollection as $field) {
                    if ($field->is_required) {
                        $name = strtolower(str_replace(' ', '_', $field->name));
                        $extraFieldValidationRules[$name] = 'required';
                    }
                }
                $extraFieldValidator = Validator::make($row, $extraFieldValidationRules);
                $extraFieldValidator->validate();


                // Create Extra Details Array for Student's Extra Form Details
                foreach ($extraDetailsFields as $key => $value) {
                    $formField = $formFieldsCollection->first(function ($data) use ($key) {
                        return strtolower($data->name) === str_replace("_", " ", $key);
                    });

                    if (!empty($formField)) {

                        // if Form Field is checkbox then make data in json format
                        $data = $formField->type == 'checkbox' ? explode(',', $value) : $value;
                        $extraDetails[] = array(
                            'input_type'    => $formField->type,
                            'form_field_id' => $formField->id,
                            'data'          => (is_array($data)) ? json_encode($data, JSON_THROW_ON_ERROR) : $data
                        );
                    }
                }
                //                     Make File Input Array to Store the Null Values
                $getFileExtraField = $formFields->builder()->where('type', 'file')->get();
                foreach ($getFileExtraField as $value) {
                    $extraDetails[] = array(
                        'input_type'    => 'file',
                        'form_field_id' => $value->id,
                        'data'          => NULL,
                    );
                }
            }

            try {
                $studentUser = $userService->createStudentUser(
                    $row['first_name'],
                    $row['last_name'],
                    $admission_no,
                    $row['mobile'],
                    $row['dob'],
                    $row['gender'],
                    null,
                    $this->classSectionID,
                    $row['admission_date'],
                    $row['current_address'],
                    $row['permanent_address'],
                    $sessionYear->id,
                    $guardian->id,
                    $extraDetails,
                    0,
                    false
                );

                if ($this->is_send_notification) {
                    SendBulkStudentEmail::dispatch(Auth::user()->school_id, $studentUser->id);
                }
            } catch (Throwable $e) {
                // IF Exception is TypeError and message contains Mail keywords then email is not sent successfully
                if ($e instanceof TypeError && Str::contains($e->getMessage(), [
                    'Mail',
                    'Mailer',
                    'MailManager'
                ])) {
                    continue;
                }
                DB::rollBack();
                throw $e;
            }
        }
        DB::commit();
        return true;
    }
}