Your IP : 216.73.216.79


Current Path : /var/www/html/eform/frontend/controllers/
Upload File :
Current File : /var/www/html/eform/frontend/controllers/ApplicationInfoController.php

<?php

namespace frontend\controllers;

use Yii;
use yii\filters\AccessControl;
use yii\filters\VerbFilter;
use yii\web\Controller;
use yii\web\UploadedFile;
use backend\modules\refdynawebv2\models\Ref;
use common\components\Sanitize;
use Exception;
use frontend\models\StaffInfo;
use frontend\models\eform\FileConversion;
use frontend\queue\FileConversionJob;
use frontend\models\eform\EformApplicationInfo;
use frontend\models\eform\EformApplicationAttachments;
use frontend\models\eform\EformApplicationApprovers;
use frontend\models\eform\EformAppWorkflowApproval;
use frontend\models\eform\EformAppWorkflowUser;
use frontend\models\eform\EformAppWorkflowApprovalRouting;
use frontend\models\eform\EformAppWorkflowApprovalApprover;
use frontend\models\eform\EformAppWorkflowApprovalRoutingHistory;
use frontend\queue\NotificationEmailJob;

/**
 * Site controller
 */
class ApplicationInfoController extends Controller
{
    const SITEID = '{FA11B219-8CC4-4DF3-B3E3-00AEF89F4DDC}';

    const LISTID = '{4AE3B9F8-6B35-483A-94BD-16CCD6648AAC}';

    const UPLOAD_DIR = 'uploads/eform-edocument/';

    const WF_APPROVAL_APPTYPE = 28;

    const WF_APPROVAL_APPROVAL_TYPE = 'eForm.EPAPER.Library.EPAPERAppApproval';

    const WF_APPROVAL_APPROVAL_TYPE_FQN = 'eForm.EPAPER.Library.EPAPERAppApproval, eForm.EPAPER.Library, Version=1.0.0.0, Culture=neutral, PublicKeyToken=78c132e4260bf62e';

    /**
     * @inheritdoc
     */
    public function behaviors()
    {
        return [
            'access' => [
                'class' => AccessControl::className(),
                'only' => ['*'],
                'rules' => [
                    [
                        'actions' => ['save-application', 'delete', 'stub'],
                        'allow' => true,
                        'roles' => ['@'],
                    ],
                ],
            ],
            'verbs' => [
                'class' => VerbFilter::className(),
            ],
        ];
    }

    /**
     * Save application, form - /web/edocument-form
     * @return void
     */
    public function actionSaveApplication($id = null)
    {

        /** extract and sanitize **/
        extract(
            Sanitize::cast_arr($_POST, [
                'action' => 'string',
            ])
        );

        /** models **/
        $model = new EformApplicationInfo();
        $model_attachments = new EformApplicationAttachments();
        $model_approver = new EformApplicationApprovers();

        if (!empty($id)) {
            $model = EformApplicationInfo::findOne($id);
            $model_attachments = new EformApplicationAttachments();
            $model_approver = new EformApplicationApprovers();
        }

        /** load all model **/
        if (
            $model->load(Yii::$app->request->post())
            && $model_attachments->load(Yii::$app->request->post())
            && $model_approver->load(Yii::$app->request->post())
        ) {
            /*** staff info ***/
            $staffinfo = StaffInfo::find()->where(StaffInfo::staffIdMapping())->one(); // the reference column might change in the future

            if (empty($model->ApplicantStaffID)) {

                $model->ApplicantStaffID = $staffinfo->StaffId;
                $model->ApplicantStaffNo = $staffinfo->StaffNo;
                $model->ApplicantStaffName = $staffinfo->StaffName;
                $model->ApplicantStaffPositionCode = $staffinfo->PositionCode;
                $model->ApplicantStaffPositionName = $staffinfo->positions->Name;
                $model->ApplicantStaffDepartmentCode = $staffinfo->DepartmentCode;
                $model->ApplicantStaffDepartmentName = $staffinfo->department->Name;
                $model->ApplicantStaffName = $staffinfo->StaffName;
                $model->CreatedDate = date('Y-m-d H:i:s');
                $model->CreatedByID = $staffinfo->StaffId;
                $model->Status = 0;
            }

            /** 
             * Application info assignment
             */
            $model->PendingAtApproverLevel = 0;
            $model->ModifiedDate = date('Y-m-d H:i:s');
            $model->ModifiedByID = $staffinfo->StaffId;

            Yii::$app->epaper->transaction(function () use ($model, $model_attachments, $model_approver, $staffinfo, $action) {

                /** 
                 * Paperwork upload
                 */
                $paperwork = UploadedFile::getInstance($model_attachments, 'FilePaperwork');

                if (!empty($paperwork)) {

                    /** remove old paperwork if the record is updated */
                    if (!empty($id)) {
                        $removePaperwork = EformApplicationAttachments::find()
                            ->where([
                                'AppGuid' => $model->ApplicationGuid,
                                'AttachmentType' => 1
                            ])
                            ->one();
                        $removePaperwork->delete();
                    }

                    $applicationPaperwork = new EformApplicationAttachments();

                    $time = time();
                    $filename = preg_replace("/\.[^.]+$/", "", $paperwork->name);
                    $eform_document_url = self::UPLOAD_DIR . $filename . '-' . $time . '.' . $paperwork->extension;

                    $applicationPaperwork->AppGuid = $model->ApplicationGuid;
                    $applicationPaperwork->ConvertedFromDocumentID = 0;
                    $applicationPaperwork->FileName = $filename . '-' . $time;
                    $applicationPaperwork->OriginalFileName = $paperwork->name;
                    $applicationPaperwork->FileHash = hash_file('sha256', $paperwork->tempName);
                    $applicationPaperwork->FileExtension = $paperwork->extension;
                    $applicationPaperwork->SiteID = self::SITEID; // we dont need this, but insert regardless because, this is not a sharepoint
                    $applicationPaperwork->ListID = self::LISTID; // This id randomly taken from the existing attachement data
                    $applicationPaperwork->ListItemID = 0;
                    $applicationPaperwork->CreatedDate  = $this->nowDate();
                    $applicationPaperwork->CreatedByID  = $staffinfo->StaffId;
                    $applicationPaperwork->ModifiedDate = $this->nowDate();
                    $applicationPaperwork->ModifiedByID = $staffinfo->StaffId;
                    $applicationPaperwork->AttachmentType = 1;

                    if ($paperwork->saveAs($eform_document_url)) {
                        $applicationPaperwork->FileUrl =  '/' . $eform_document_url;
                    }

                    /** save file attachment */
                    $applicationPaperwork->save();
                }


                /**
                 * Remove file, if user remove it in file attachment form
                 */

                /** create list of filename */
                // $attachment_list = json_decode($model_attachments->FileAttachmentsList);


                // /** create filename array for comparison*/
                // $attachment_list_arr = [];
                // foreach ($attachment_list as $attach_list) {

                //     if (property_exists($attach_list, 'FileName')) {
                //         $attachment_list_arr[] = $attach_list->FileName;
                //     }
                // }

                // /** check existing record */
                // $existing_attachment_list = EformApplicationAttachments::find()
                //     ->where([
                //         'AppGuid' => $model->ApplicationGuid,
                //         'AttachmentType' => 2
                //     ])
                //     ->all();

                // if (!empty($existing_attachment_list)) {

                //     for ($i = 0; $i < count($existing_attachment_list); $i++) {
                //         /** compare and delete file if not exist */
                //         if (!in_array($existing_attachment_list[$i]->FileName, $attachment_list_arr)) {
                //             $existing_attachment_list[$i]->delete();

                //             echo 'deleting  - ' . $existing_attachment_list[$i]->FileName;
                //         }
                //     }
                // }

                /** 
                 * Document attachment upload
                 */

                /** file upload attachment **/
                $files = UploadedFile::getInstances($model_attachments, 'FileAttachments');

                if (!empty($files)) {

                    /** convert into object from json string */

                    $i = 0;
                    foreach ($files as $file) {

                        $applicationAttachments = new EformApplicationAttachments();

                        $time = time();
                        $filename = preg_replace("/\.[^.]+$/", "", $file->name);
                        $eform_document_url = self::UPLOAD_DIR . $filename . '-' . $time . '.' . $file->extension;
                        $applicationAttachments->AppGuid = $model->ApplicationGuid;
                        $applicationAttachments->ConvertedFromDocumentID = 0;
                        $applicationAttachments->FileName = $filename . '-' . $time;
                        $applicationAttachments->OriginalFileName = $file->name;
                        $applicationAttachments->FileHash = hash_file('sha256', $file->tempName);
                        $applicationAttachments->FileExtension = $file->extension;
                        $applicationAttachments->SiteID = self::SITEID; // we dont need this, but insert regardless because, this is not a sharepoint
                        $applicationAttachments->ListID = self::LISTID; // This id randomly taken from the existing attachement data
                        $applicationAttachments->ListItemID = 0;
                        $applicationAttachments->CreatedDate  = $this->nowDate();
                        $applicationAttachments->CreatedByID  = $staffinfo->StaffId;
                        $applicationAttachments->ModifiedDate = $this->nowDate();
                        $applicationAttachments->ModifiedByID = $staffinfo->StaffId;
                        $applicationAttachments->AttachmentType = 2;

                        if ($file->saveAs($eform_document_url)) {
                            $applicationAttachments->FileUrl =  '/' . $eform_document_url;
                        }

                        /** save file attachment */
                        $applicationAttachments->save();
                        $i++;
                    }
                }

                /** 
                 * Application Approver
                 */
                if (!empty($model_approver->ApproverStaffID)) {

                    $approver_exists_arr = []; // hold all the user from th db
                    $form_existing_arr = []; // hold the form input hidden array
                    $approver_change_arr = []; //hold all approver that has been changed to another 
                    $approver_exist_staffid_arr = []; // hold all staffId instead of id
                    $approver_skip_approver_arr = []; // hold all staffId mark for the skip

                    /** create an array of existing record */
                    $approver_exists = EformApplicationApprovers::find()->where(['AppGuid' => $model->ApplicationGuid])->orderBy('ApproverLevel ASC')->all();

                    if (!empty($approver_exists)) {

                        for ($i = 0; $i < count($approver_exists); $i++) {
                            $approver_exists_arr[] = $approver_exists[$i]->ID;
                            $approver_exist_staffid_arr[$approver_exists[$i]->ID] = $approver_exists[$i]->ApproverStaffID;
                        }
                    }

                    /** create and array of staff based on hidden input of approver*/
                    $form_approver_list = json_decode($model_approver->ApproverList);

                    foreach ($form_approver_list as $form_existing_record) {
                        $form_existing_arr[] = $form_existing_record->id;
                    }

                    for ($i = 0; $i < count($model_approver->ApproverStaffID); $i++) {

                        if (in_array($form_existing_arr[$i], $approver_exists_arr)) {
                            continue; # skip existing user only allow new user pass trough insertion
                        }

                        if($model_approver->ApproverStaffID[$i] === "-1") {
                            
                            if(isset($approver_exists_arr[$i])) {
                                $form_existing_arr[$i] = $approver_exists_arr[$i]; // reinsert this approver, because it only a skip not a remove or changes of approval
                                $approver_skip_approver_arr[] = $approver_exist_staffid_arr[$approver_exists_arr[$i]];
                            }
                            continue; # skip for skip-approver
                        }

                        /** track the changes for wf-update*/
                        if (isset($approver_exists_arr[$i]) && !empty($approver_exists_arr[$i]) && $form_existing_arr[$i] != $approver_exists_arr[$i]) {
                            $approver_change_arr[$approver_exists_arr[$i]]['from'] = $approver_exist_staffid_arr[$approver_exists_arr[$i]];
                            $approver_change_arr[$approver_exists_arr[$i]]['to'] = $model_approver->ApproverStaffID[$i];
                        }

                        /** insert the array */
                        $applicationApprover = new EformApplicationApprovers();

                        $applicationApprover->AppGuid = $model->ApplicationGuid;
                        $applicationApprover->ApproverType = $model_approver->ApproverType[$i];
                        $applicationApprover->RolesWording = $model_approver->RolesWording[$i];
                        $applicationApprover->ApproverStaffID = $model_approver->ApproverStaffID[$i];
                        $applicationApprover->ApproverDueDay = $model_approver->ApproverDueDay[$i];
                        $applicationApprover->ApproverLevel = 0; # default level, we will update the sequence later

                        /** Approve staff detail **/
                        $approver = $this->grabStaffInfoByStaffId($applicationApprover->ApproverStaffID);

                        $applicationApprover->ApproverStaffNo = $approver->StaffNo;
                        $applicationApprover->ApproverStaffName = $approver->StaffName;
                        $applicationApprover->ApproverStaffPositionCode = $approver->PositionCode;
                        $applicationApprover->ApproverStaffPositionName = $approver->positions->Name;
                        $applicationApprover->ApproverStaffDepartmentCode = $approver->DepartmentCode;
                        $applicationApprover->ApproverStaffDepartmentName = $approver->department->Name;

                        $applicationApprover->ApproverPositiveActionName = $this->reference('APP_POSITIVE_ACTION_NAME', $model_approver->ApproverType[$i], 'descr');
                        $applicationApprover->ApproverNegativeActionName = $this->reference('APP_NEGATIVE_ACTION_NAME', $model_approver->ApproverType[$i], 'descr');
                        $applicationApprover->CreatedDate = $this->nowDate();
                        $applicationApprover->ModifiedDate = $this->nowDate();
                        $applicationApprover->CreatedByID = $staffinfo->StaffId;
                        $applicationApprover->ModifiedByID = $staffinfo->StaffId;

                        /** save the approver inside the loop */
                        if (!$applicationApprover->save()) {
                            throw new \Exception("Error Processing Request" . json_encode($applicationApprover->errors));
                        }
                    }

                    /*** 
                     * remove record / user replacement
                     ***/
                    foreach ($approver_exists_arr as $exist_approver) {

                        if (!in_array($exist_approver, $form_existing_arr)) {

                            $approver_delete = EformApplicationApprovers::find()
                                ->where([
                                    'AppGuid' => $model->ApplicationGuid,
                                    'ID' => $exist_approver
                                ])
                                ->one();

                            if (!empty($approver_delete)) {
                                $approver_delete->delete();
                            }
                        }
                    }

                    /** 
                     * update sequence *
                     **/
                    /**  reset old sequence from old record */
                    $approver_reset = EformApplicationApprovers::find()
                        ->where([
                            'AppGuid' => $model->ApplicationGuid,
                        ])
                        ->all();

                    foreach ($approver_reset as $reset_sequence) {
                        $reset_sequence->ApproverLevel = 0;
                        $reset_sequence->save();
                    }

                    $sequence = 1;
                    foreach ($form_approver_list as $form_list) {

                        $staffid = $form_list->staffId;

                        /** if user is selected to skip approver, restore it staffid and level */
                        if($form_list->staffId == '-1') {
                            if(!empty($form_existing_arr[$sequence - 1])) {
                                $staffid = $this->grabApproverById($model->ApplicationGuid, $form_existing_arr[$sequence - 1])->ApproverStaffID;
                            }
                        }

                        // debug 
                        // var_dump($staffid);

                        $approver_update = EformApplicationApprovers::find()
                            ->where([
                                'AppGuid' => $model->ApplicationGuid,
                                'ApproverStaffID' => $staffid,
                                'ApproverLevel' => 0 // prevent conflict if same staffid record selected, the record is updated one by one
                            ])
                            ->orderBy('ID ASC')
                            ->one();

                        /* update sequence */
                        if (!empty($approver_update)) {
                            $approver_update->ApproverLevel = $sequence;
                            $approver_update->save();
                            $sequence++;
                        }
                    }
                }

                /** 
                 * Application info save
                 */
                $model->save();

                /** 
                 * 
                 * Form submission workflow
                 * 
                 */

                /***
                 * WF-SUBMIT
                 **/
                if ($action === 'submit') {

                    /** model status update*/
                    $model_update = EformApplicationInfo::findOne($model->ApplicationId);
                    $model_update->Status = 1;
                    $model_update->PendingAtApproverLevel = 1;

                    if (!$model_update->save()) {
                        throw new \Exception("Error saving model in workflow submit");
                    }

                    /**
                     * workflow approval
                     */
                    $wf_approval = EformAppWorkflowApproval::find()->where(['AppGuid' => $model->ApplicationGuid])->one();

                    if (!$wf_approval) {
                        $wf_approval = new EformAppWorkflowApproval();
                        $wf_approval->Guid = $this->createGuid();
                        $wf_approval->AppGuid = $model->ApplicationGuid;
                        $wf_approval->AppType = self::WF_APPROVAL_APPTYPE; //doesn't know what this value do. But it exist on old db
                        $wf_approval->ApprovalType = self::WF_APPROVAL_APPROVAL_TYPE;
                        $wf_approval->ApprovalTypeFQN = self::WF_APPROVAL_APPROVAL_TYPE_FQN;
                        $wf_approval->OwnerGuid = $this->getOrCreateUserGuid(StaffInfo::staffIdMapping()['StaffId']);
                        $wf_approval->Status = 3; # 0 new, 1 cancel, 2 Initiated, 3 Waiting for Approval, 4 Approved, 5 Rejected
                        $wf_approval->CurrentWFInstanceGuid = $this->createGuid();
                        $wf_approval->WFInstanceStatus = 0; # 0 new, 1 pending, 2 completed
                        $wf_approval->DateSubmitted = $this->nowDate();
                        // $wf_approval->CurrentApprover = 0;

                        $wf_approval->save();
                    }


                    /**
                     * workflow approval routing
                     */
                    $sequence = 1;

                    //application approver object
                    $recipient = $this->grabRecipientByWorkflowUserOrCreate($model->ApplicationGuid, $sequence);

                    $recipient_guid = $recipient->appWorkflowUser->Guid;

                    $wf_approval_routing = EformAppWorkflowApprovalRouting::find()->where(['AppGuid' => $model->ApplicationGuid, 'Sequence' => $sequence])->one();

                    if (empty($wf_approval_routing)) {
                        $wf_approval_routing = new EformAppWorkflowApprovalRouting();
                        $wf_approval_routing->AppGuid = $model->ApplicationGuid;
                        $wf_approval_routing->AppType = self::WF_APPROVAL_APPTYPE;
                        $wf_approval_routing->WorkflowGuid = $wf_approval->Guid;
                        $wf_approval_routing->WFInstanceGuid = $wf_approval->CurrentWFInstanceGuid;
                        $wf_approval_routing->Sequence = $sequence; // new submission use 1 as sequence
                        $wf_approval_routing->SenderGuid = $wf_approval->OwnerGuid;
                        $wf_approval_routing->RecipientGuid = $recipient_guid;
                        $wf_approval_routing->OriginalRecipientGuid = $recipient_guid;
                        $wf_approval_routing->Subject = $this->subjectRemark($model->ApplicationId, $recipient->ApproverType);
                        $wf_approval_routing->Status = 0; //new  
                        $wf_approval_routing->ApprovalAction = 0;
                        $wf_approval_routing->DateReceived = $this->nowDate();
                        $wf_approval_routing->DueDate = $this->calculateDueDate($this->nowDate(), $recipient->ApproverDueDay . " days");
                        // $wf_approval_routing->RepliedBy = null;
                        // $wf_approval_routing->DateReplied = null;
                        // $wf_approval_routing->Remarks = null;

                        if (!$wf_approval_routing->save()) {
                            throw new \Exception("Error Processing Request" . json_encode($wf_approval_routing->errors));
                        }
                    }

                    /** @var send email to first approver  */
                    $approver_user = $this->grabWorkflowUserByStaffid($recipient->ApproverStaffID);

                    /** email notification */
                    if(empty($approver_user->Email)) {
                        throw new Exception('Email is empty when try to send full approve notification, for user ' . $model->ApplicantStaffID);
                    } 

                    $content = [
                        'subject' => 'Application Notification for id ' . $this->AppRefNo($model->ApplicationId),
                        'content' => 'Please check/review application to continue the approval process. <br> - id ' . $this->AppRefNo($model->ApplicationId),
                    ];

                    $this->sendEmail($model->ApplicationId, $model->ApplicationGuid, 
                        $content, 
                        $approver_user->Email,
                        [
                            'view' => 'basic',
                            'data' => [
                                'message' => $content['content']
                            ]
                        ]
                    );
                        

                    /**
                     * workflow approval approver
                     */
                    $wf_approval_approver = EformAppWorkflowApprovalApprover::find()->where(['WorkflowGuid' => $wf_approval->Guid]);

                    if (empty($wf_approval_approver)) {
                        $wf_approval_approver = new EformAppWorkflowApprovalApprover();

                        $wf_approval_approver->WorkflowGuid = $wf_approval->Guid;
                        $wf_approval_approver->Sequence = 1;
                        $wf_approval_approver->Approver = $recipient_guid;
                        $wf_approval_approver->ActionType = 0; // unless reject level 50
                        $wf_approval_approver->DueDays = $recipient->ApproverDueDay;
                        $wf_approval_approver->TaskNotification = 1; // no sure for what, leave it for later

                        $wf_approval_approver->save();

                        /** create workflow approval routing history */
                        $this->addWfRoutingHistory(
                            $wf_approval->Guid,
                            2,
                            'Task created for : ' . $recipient->ApproverStaffName,
                            1
                        );
                    }
                    
                    /** popup message and redirect */
                    Yii::$app->session->setFlash('success', 'Application Successfully Submitted');

                    return $this->redirect(['/web/edocument-list-submitted']);

                }
                /***
                 * END SUBMIT
                 **/


                /**
                 *  WF-UPDATE
                 **/
                if ($action === 'update') {

                    // debug changes
                    // for ($i = 0; $i < count($approver_exists_arr); $i++) {
                    //     echo $approver_exists_arr[$i]  . '=' . $form_existing_arr[$i] . '<br>';
                    // }
                    // 

                    /***
                     * Reassign
                     **/

                    $current_routing = $this->grabCurrentRouting($model->ApplicationGuid);

                    $wf_approval = EformAppWorkflowApproval::find()->where(['AppGuid' => $model->ApplicationGuid])->one();
                    
                    if (!empty($approver_change_arr)) {

                        foreach ($approver_change_arr as $approver_change) { // must be loop as index is not 0, index hold id from existing record

                            /**  insert the routing for new assingned staff  */
                            $current_approver_guid  = $this->getOrCreateUserGuid($approver_change['to']);
                            $previous_approver_guid  = $this->getOrCreateUserGuid($approver_change['from']);
                            $current_approver_level = $this->grabRecipientByLevel($model->ApplicationGuid, $current_routing->Sequence);
                            $current_recipient = $this->grabApproverByStaffId($model->ApplicationGuid, $approver_change['to']);
                            $previous_approver_staffinfo = $this->grabStaffInfoByStaffId($approver_change['from']);

                            if ($current_routing->Sequence == $current_recipient->ApproverLevel) { // only insert the routing if this record is the replaced sequence / level

                                /** update current routing */
                                $wf_approval_routing_current = EformAppWorkflowApprovalRouting::find()->where(['Guid' => $current_routing->Guid])->one();

                                $wf_approval_routing_current->Status = 2; //2 complete
                                $wf_approval_routing_current->ApprovalAction = 9; //9 reassign
                                $wf_approval_routing_current->Remarks = 'Reassign to '  . $approver_change['to'] . ' ; comment: ' . $model->Comments;
                                $wf_approval_routing_current->RepliedBy = Yii::$app->user->identity->grabWorkflowUserGuid();
                                $wf_approval_routing_current->DateReplied = $this->nowDate();

                                if (!$wf_approval_routing_current->save()) {
                                    throw new \Exception('Error update current routing in approval workflow');
                                }

                                $wf_approval_routing_current = new EformAppWorkflowApprovalRouting();
                                $wf_approval_routing_current->AppGuid = $model->ApplicationGuid;
                                $wf_approval_routing_current->AppType = self::WF_APPROVAL_APPTYPE;
                                $wf_approval_routing_current->WorkflowGuid = $wf_approval->Guid;
                                $wf_approval_routing_current->WFInstanceGuid = $this->createGuid();
                                $wf_approval_routing_current->Sequence = $current_routing->Sequence; // new submission use 1 as sequence
                                $wf_approval_routing_current->SenderGuid = Yii::$app->user->identity->grabWorkflowUserGuid();
                                $wf_approval_routing_current->RecipientGuid = $current_approver_guid;
                                $wf_approval_routing_current->OriginalRecipientGuid = $previous_approver_guid;
                                $wf_approval_routing_current->Subject = $this->subjectRemark($model->ApplicationId, $current_approver_level->ApproverType);
                                $wf_approval_routing_current->Status = 0; //new  
                                $wf_approval_routing_current->ApprovalAction = 0;
                                $wf_approval_routing_current->DateReceived = $this->nowDate();
                                $wf_approval_routing_current->DueDate = $this->calculateDueDate($this->nowDate(), $current_approver_level->ApproverDueDay . " days");

                                if (!$wf_approval_routing_current->save()) {
                                    throw new \Exception("Error Processing Request" . json_encode($wf_approval_routing_current->errors));
                                }
                                //todo email to recepient
                                //
                                
                            }
                        }

                        /** create workflow approval routing history */
                        $this->addWfRoutingHistory(
                            $wf_approval->Guid,
                            2,
                            'Task Reassign from ' . $previous_approver_staffinfo->StaffName . ' TO ' . $current_recipient->ApproverStaffName,
                            1
                        );

                    }

                    /** 
                     * skip approver
                     */
                    if(!empty($approver_skip_approver_arr)) {
                        
                        /** update current routing */
                        $wf_approval_routing_current = EformAppWorkflowApprovalRouting::find()->where(['Guid' => $current_routing->Guid])->one();

                        $wf_approval_routing_current->Status = 2; //2 complete
                        $wf_approval_routing_current->ApprovalAction = 5; // Skip approver / autoapprover
                        $wf_approval_routing_current->Remarks = '[Auto Approve for has been set by the owner] comment:'  . $model->Comments;
                        $wf_approval_routing_current->RepliedBy = Yii::$app->user->identity->grabWorkflowUserGuid();
                        $wf_approval_routing_current->DateReplied = $this->nowDate();

                        if (!$wf_approval_routing_current->save()) {
                            throw new \Exception('Error update current routing in approval workflow');
                        }

                        /** add the next routing / next sequence must be after wf updated*/
                        $next_sequence = $this->grabNextApproverLevel($model->ApplicationGuid);

                        /** if app reach an end */
                        if ($next_sequence == -1) {

                            /** update workflow info approve */
                            $model_update = EformApplicationInfo::findOne($model->ApplicationId);
                            $model_update->Status = 2; // approve

                            if (!$model_update->save()) {
                                throw new \Exception("Error saving model in workflow submit" . json_encode($model_update->errors));
                            }
                            return;
                        }

                        $next_recipient = $this->grabRecipientByWorkflowUserOrCreate($model->ApplicationGuid, $next_sequence);
                        $next_recipient_guid = $next_recipient->appWorkflowUser->Guid;

                        $wf_approval_routing_next = new EformAppWorkflowApprovalRouting();
                        $wf_approval_routing_next->AppGuid = $model->ApplicationGuid;
                        $wf_approval_routing_next->AppType = self::WF_APPROVAL_APPTYPE;
                        $wf_approval_routing_next->WorkflowGuid = $wf_approval->Guid;
                        $wf_approval_routing_next->WFInstanceGuid = $this->createGuid();
                        $wf_approval_routing_next->Sequence = $next_sequence; // new submission use 1 as sequence
                        $wf_approval_routing_next->SenderGuid = Yii::$app->user->identity->grabWorkflowUserGuid();
                        $wf_approval_routing_next->RecipientGuid = $next_recipient_guid;
                        $wf_approval_routing_next->OriginalRecipientGuid = $next_recipient_guid;
                        $wf_approval_routing_next->Subject = $this->subjectRemark($model->ApplicationId, $next_recipient->ApproverType);
                        $wf_approval_routing_next->Status = 0; //new  
                        $wf_approval_routing_next->ApprovalAction = 0;
                        $wf_approval_routing_next->DateReceived = $this->nowDate();
                        $wf_approval_routing_next->DueDate = $this->calculateDueDate($this->nowDate(), $next_recipient->ApproverDueDay . " days");

                        if (!$wf_approval_routing_next->save()) {
                            throw new \Exception("Error Processing Request" . json_encode($wf_approval_routing_next->errors));
                        }

                        /** insert next approver  */
                        $wf_approval_approver = new EformAppWorkflowApprovalApprover();

                        $wf_approval_approver->WorkflowGuid = $wf_approval->Guid;
                        $wf_approval_approver->Sequence = 50;
                        $wf_approval_approver->Approver = $wf_approval->OwnerGuid;
                        $wf_approval_approver->ActionType = 0; // unless reject level 50
                        $wf_approval_approver->DueDays = 3; // no futher information where this value came from
                        $wf_approval_approver->TaskNotification = 1; // no sure for what, leave it for later

                        if (!$wf_approval_approver->save()) {
                            throw new \Exception("Error saving aproval approver in approval workflow" . json_encode($wf_approval_approver->errors));
                        }
                    }

                    /** all ok redirect */
                    Yii::$app->session->setFlash('success', 'Application Successfully Saved');

                    return $this->redirect(['/web/edocument-list']);
                }
                /** 
                 * END WF-UPDATE
                 */


                /***
                 * WF-APPROVE
                 */
                if ($action === 'approve') {
                    /**
                     * workflow approval
                     */
                    $wf_approval = EformAppWorkflowApproval::find()->where(['AppGuid' => $model->ApplicationGuid])->one();

                    /** state  */
                    $current_routing = $this->grabCurrentRouting($model->ApplicationGuid);
                    $current_approver_level = $this->grabRecipientByLevel($model->ApplicationGuid, $current_routing->Sequence);

                    /** check if the approver is the current approver */
                    if ($current_approver_level->ApproverStaffID != Yii::$app->user->identity->staff_no) {
                        return;
                    }

                    /** update current routing */
                    $wf_approval_routing_current = EformAppWorkflowApprovalRouting::find()->where(['Guid' => $current_routing->Guid])->one();

                    $wf_approval_routing_current->Status = 2; //2 complete
                    $wf_approval_routing_current->ApprovalAction = 1; //1 Approve
                    $wf_approval_routing_current->Remarks = $model->Comments;
                    $wf_approval_routing_current->RepliedBy = Yii::$app->user->identity->grabWorkflowUserGuid();
                    $wf_approval_routing_current->DateReplied = $this->nowDate();


                    if (!$wf_approval_routing_current->save()) {
                        throw new \Exception('Error update current routing in approval workflow');
                    }

                    /** add the next routing / next sequence must be after wf updated*/
                    $next_sequence = $this->grabNextApproverLevel($model->ApplicationGuid);

                    /** update approver comment */
                    $this->updateApproverComment($model, 'APP_POSITIVE_ACTION_NAME');

                    /** update application info */
                    $update_model = EformApplicationInfo::findOne($model->ApplicationId);
                    $update_model->PendingAtApproverLevel = $next_sequence;
                    $update_model->save();

                    /** if app reach an end */
                    if ($next_sequence == -1) {

                        /** update application info full approval */
                        $model_update = EformApplicationInfo::findOne($model->ApplicationId);
                        $model_update->Status = 2; // approve

                        if (!$model_update->save()) {
                            throw new \Exception("Error saving model in workflow submit" . json_encode($model_update->errors));
                        }

                        /** send the application for conversion */
                        $app_guid   = $model->ApplicationGuid;
                        $attachment = EformApplicationAttachments::find()->where(['AttachmentType' => 1, 'AppGuid' => $app_guid])->one();
                        $approvers  = EformApplicationApprovers::find()->where(['AppGuid' => $app_guid])->orderBy('ApproverLevel')->all();

                        $approvers_list = [];

                        if(!empty($approvers)) {
                            
                            for ($i=0; $i < count($approvers); $i++) { 
                                $approvers_list[$i]['name'] = $approvers[$i]->ApproverStaffName;
                                $approvers_list[$i]['department'] = $approvers[$i]->ApproverStaffDepartmentName;
                                $approvers_list[$i]['position'] = $approvers[$i]->ApproverStaffPositionName;
                                $approvers_list[$i]['date'] = $approvers[$i]->ApproverActionDate;
                                $approvers_list[$i]['comment'] = $approvers[$i]->ApproverApproveKomen;
                                $approvers_list[$i]['role'] = $approvers[$i]->RolesWording;
                            }
                        }

                        if(!empty($attachment)) {
                            $data = [
                                'application' => [
                                    'name' => $model->ApplicantStaffName,
                                    'department' => $model->ApplicantStaffDepartmentName,
                                    'position' => $model->ApplicantStaffPositionName,
                                    'application_date' => $model->CreatedDate,
                                    'date_of_application' => $model->ModifiedDate,
                                    'type' => $model->ApplicationType,
                                    'reference_no' => $this->AppRefNo($model->ApplicationId),
                                    'title' => $model->ApplicantStaffPositionName,
                                    'file_path' => $attachment->FileUrl
                                ],
                                'approver' => $approvers_list
                            ];


                            /** send file for converstion */
                            $this->file_conversion($model->ApplicationGuid, $data);

                        } else {
                            throw new \Exception('Empty attachment to convert. Make sure file is uploaded.');
                        }

                        /** update main workflow approval  */
                        $wf_approval->Status = 4; # 0 new, 1 cancel, 2 Initiated, 3 Waiting for Approval, 4 Approved, 5 Rejected
                        $wf_approval->WFInstanceStatus = 2; # 0 new, 1 pending, 2 completed

                        if (!$wf_approval->save()) {
                            throw new \Exception("Error Saving Workflow approval status on workflow approval" . json_encode($wf_approval));
                        }

                        $grab_owner = $this->grabWorkflowUserByStaffid($model->ApplicantStaffID);

                        /** email notification */
                        if(empty($grab_owner->Email)) {
                            throw new Exception('Email is empty when try to send full approve notification, for user ' . $model->ApplicantStaffID);
                        } 

                        $content = [
                            'subject' => 'Application Notification for id ' . $this->AppRefNo($model->ApplicationId),
                            'content' => 'Application has finished the approval proces, you may download your file. <br> - id ' . $this->AppRefNo($model->ApplicationId),
                        ];

                        $this->sendEmail($model->ApplicationId, $model->ApplicationGuid, 
                            $content, 
                            $grab_owner->Email,
                            [
                                'view' => 'basic',
                                'data' => [
                                    'message' => $content['content']
                                ]
                            ]
                        );
                        
                        return;
                    }

                    $next_recipient = $this->grabRecipientByWorkflowUserOrCreate($model->ApplicationGuid, $next_sequence);
                    $next_recipient_guid = $next_recipient->appWorkflowUser->Guid;

                    $wf_approval_routing_next = new EformAppWorkflowApprovalRouting();
                    $wf_approval_routing_next->AppGuid = $model->ApplicationGuid;
                    $wf_approval_routing_next->AppType = self::WF_APPROVAL_APPTYPE;
                    $wf_approval_routing_next->WorkflowGuid = $wf_approval->Guid;
                    $wf_approval_routing_next->WFInstanceGuid = $this->createGuid();
                    $wf_approval_routing_next->Sequence = $next_sequence; // new submission use 1 as sequence
                    $wf_approval_routing_next->SenderGuid = Yii::$app->user->identity->grabWorkflowUserGuid();
                    $wf_approval_routing_next->RecipientGuid = $next_recipient_guid;
                    $wf_approval_routing_next->OriginalRecipientGuid = $next_recipient_guid;
                    $wf_approval_routing_next->Subject = $this->subjectRemark($model->ApplicationId, $next_recipient->ApproverType);
                    $wf_approval_routing_next->Status = 0; //new  
                    $wf_approval_routing_next->ApprovalAction = 0;
                    $wf_approval_routing_next->DateReceived = $this->nowDate();
                    $wf_approval_routing_next->DueDate = $this->calculateDueDate($this->nowDate(), $next_recipient->ApproverDueDay . " days");

                    if (!$wf_approval_routing_next->save()) {
                        throw new \Exception("Error Processing Request" . json_encode($wf_approval_routing_next->errors));
                    }

                    /** insert next approver  */
                    $wf_approval_approver = new EformAppWorkflowApprovalApprover();

                    $wf_approval_approver->WorkflowGuid = $wf_approval->Guid;
                    $wf_approval_approver->Sequence = $next_sequence;
                    $wf_approval_approver->Approver = $next_recipient_guid;
                    $wf_approval_approver->ActionType = 0; // unless reject level 50
                    $wf_approval_approver->DueDays = $next_recipient->ApproverDueDay;
                    $wf_approval_approver->TaskNotification = 1; // no sure for what, leave it for later

                    if (!$wf_approval_approver->save()) {
                        throw new \Exception("Error saving aproval approver in approval workflow :" . json_encode($wf_approval_approver->errors));
                    }

                    /** create workflow approval routing history */
                    $this->addWfRoutingHistory(
                        $wf_approval->Guid,
                        2,
                        'Task created for : ' . $next_recipient->ApproverStaffName,
                        $next_sequence
                    );

                    /** update main workflow approval  */
                    $wf_approval->Status = 3; # 0 new, 1 cancel, 2 Initiated, 3 Waiting for Approval, 4 Approved, 5 Rejected
                    $wf_approval->WFInstanceStatus = 2; # 0 new, 1 pending, 2 completed

                    if (!$wf_approval->save()) {
                        throw new \Exception("Error Saving Workflow approval status on workflow approval" . json_encode($wf_approval));
                    }

                    /** email notification */
                    $content = [
                        'subject' => 'Application Notification for id ' . $this->AppRefNo($model->ApplicationId),
                        'content' => 'Please check application to continue the approval process <br> - id ' . $this->AppRefNo($model->ApplicationId),
                    ];

                    $this->sendEmail($model->ApplicationId, $model->ApplicationGuid, 
                        $content, 
                        $next_recipient->appWorkflowUser->Email,
                        [
                            'view' => 'basic',
                            'data' => [
                                'message' => 'Please check id 403118'
                            ]
                        ]
                    );

                    /** popup message and redirect */
                    Yii::$app->session->setFlash('success', 'Application Successfully Approved');

                    return $this->redirect(['/web/edocument-list']);
                }
                /**
                 * END WF-APPROVE
                 **/


                /**
                 * WF-REJECT
                 */
                if ($action === 'reject') {

                    /** update workflow info approve */
                    $model_update = EformApplicationInfo::findOne($model->ApplicationId);
                    $model_update->Status = 3; // approve

                    if (!$model_update->save()) {
                        throw new \Exception("Error saving model in workflow submit");
                    }

                    /**
                     * workflow approval
                     */
                    $wf_approval = EformAppWorkflowApproval::find()->where(['AppGuid' => $model->ApplicationGuid])->one();

                    /** state  */
                    $current_routing = $this->grabCurrentRouting($model->ApplicationGuid);
                    $current_approver_level = $this->grabRecipientByLevel($model->ApplicationGuid, $current_routing->Sequence);

                    /** check if the approver is the current approver */
                    if ($current_approver_level->ApproverStaffID != Yii::$app->user->identity->staff_no) {
                        return;
                    }

                    /** update current routing */
                    $wf_approval_routing_current = EformAppWorkflowApprovalRouting::find()->where(['Guid' => $current_routing->Guid])->one();

                    $wf_approval_routing_current->Status = 2; //2 complete
                    $wf_approval_routing_current->ApprovalAction = 2; //2 Rejected
                    $wf_approval_routing_current->Remarks = $model->Comments;
                    $wf_approval_routing_current->RepliedBy = Yii::$app->user->identity->grabWorkflowUserGuid();
                    $wf_approval_routing_current->DateReplied = $this->nowDate();

                    if (!$wf_approval_routing_current->save()) {
                        throw new \Exception('Error update current routing in approval workflow');
                    }

                    /** update approver comment */
                    $this->updateApproverComment($model, 'APP_NEGATIVE_ACTION_NAME');

                    /** add the next routing / next sequence must be after wf updated*/
                    $next_sequence = $this->grabNextApproverLevel($model->ApplicationGuid);

                    $wf_approval_routing_next = new EformAppWorkflowApprovalRouting();
                    $wf_approval_routing_next->AppGuid = $model->ApplicationGuid;
                    $wf_approval_routing_next->AppType = self::WF_APPROVAL_APPTYPE;
                    $wf_approval_routing_next->WorkflowGuid = $wf_approval->Guid;
                    $wf_approval_routing_next->WFInstanceGuid = $this->createGuid();
                    $wf_approval_routing_next->Sequence = 50; // reject submission use 50 as sequence
                    $wf_approval_routing_next->SenderGuid = Yii::$app->user->identity->grabWorkflowUserGuid();
                    $wf_approval_routing_next->RecipientGuid = $wf_approval->OwnerGuid;
                    $wf_approval_routing_next->OriginalRecipientGuid = $wf_approval->OwnerGuid;
                    $wf_approval_routing_next->Subject = 'Please check this Application ' . $this->AppRefNo($model->ApplicationId);
                    $wf_approval_routing_next->Status = 0; //new  
                    $wf_approval_routing_next->ApprovalAction = 0;
                    $wf_approval_routing_next->DateReceived = $this->nowDate();
                    $wf_approval_routing_next->DueDate = $this->calculateDueDate($this->nowDate(), "3 days");

                    if (!$wf_approval_routing_next->save()) {
                        throw new \Exception("Error Processing Request" . json_encode($wf_approval_routing_next->errors));
                    }


                    /** insert next approver  */
                    $wf_approval_approver = EformAppWorkflowApprovalApprover::find()
                    ->where(['WorkflowGuid' => $wf_approval->Guid, 'Approver' => $wf_approval->OwnerGuid])
                    ->one();
                    
                    if(empty($wf_approval_approver)) {

                        /** insert next approver  */
                        $wf_approval_approver = new EformAppWorkflowApprovalApprover();
                        $wf_approval_approver->WorkflowGuid = $wf_approval->Guid;
                        $wf_approval_approver->Sequence = 50;
                        $wf_approval_approver->Approver = $wf_approval->OwnerGuid;
                        $wf_approval_approver->ActionType = 0; // unless reject level 50
                        $wf_approval_approver->DueDays = 3; // no futher information where this value came from
                        $wf_approval_approver->TaskNotification = 1; // no sure for what, leave it for later

                        if (!$wf_approval_approver->save()) {
                            throw new \Exception("Error saving aproval approver in approval workflow" . json_encode($wf_approval_approver->errors));
                        }
                    }

                    /** update application info */
                    $update_model = EformApplicationInfo::findOne($model->ApplicationId);
                    $update_model->PendingAtApproverLevel = 0;
                    $update_model->save();

                    /** create workflow approval routing history */


                    /** update main workflow approval  */
                    $wf_approval->Status = 5; # 0 new, 1 cancel, 2 Initiated, 3 Waiting for Approval, 4 Approved, 5 Rejected
                    $wf_approval->WFInstanceStatus = 2; # 0 new, 1 pending, 2 completed

                    if (!$wf_approval->save()) {
                        throw new \Exception("Error Saving Workflow approval status on workflow rejected" . json_encode($wf_approval));
                    }

                    /** email notification */
                    $grab_owner = $this->grabWorkflowUserByStaffid($model->ApplicantStaffID);

                    if(empty($grab_owner->Email)) {
                        throw new Exception('Email is empty when try to send reject notification, for user ' . $model->ApplicantStaffID);
                    } 
                    
                    $content = [
                        'subject' => 'Application Notification for id ' . $this->AppRefNo($model->ApplicationId),
                        'content' => 'Application has been rejected in approval proccess, you may resubmit your application. <br> - id ' . $this->AppRefNo($model->ApplicationId),
                    ];

                    $this->sendEmail($model->ApplicationId, $model->ApplicationGuid, 
                        $content, 
                        $grab_owner->Email,
                        [
                            'view' => 'basic',
                            'data' => [
                                'message' => $content['content']
                            ]
                        ]
                    );
                }

                /***
                 * WF-RESUBMIT
                 */
                if ($action === 'resubmit') {
                    /**
                     * workflow approval
                     */
                    $wf_approval = EformAppWorkflowApproval::find()->where(['AppGuid' => $model->ApplicationGuid])->one();

                    /** state  */
                    $current_routing = $this->grabCurrentRouting($model->ApplicationGuid);

                    /** update workflow info approve */
                    $model_update = EformApplicationInfo::findOne($model->ApplicationId);

                    /** check if the current application is rejected before proccedding */
                    if ($model_update->Status !== 3) {
                        return;
                    }

                    /** update current routing */
                    $wf_approval_routing_current = EformAppWorkflowApprovalRouting::find()->where(['Guid' => $current_routing->Guid])->one();

                    $wf_approval_routing_current->Status = 2; //2 complete
                    $wf_approval_routing_current->ApprovalAction = 99; //2 Resubmit
                    $wf_approval_routing_current->Remarks = $model->Comments;
                    $wf_approval_routing_current->RepliedBy = Yii::$app->user->identity->grabWorkflowUserGuid();
                    $wf_approval_routing_current->DateReplied = $this->nowDate();

                    if (!$wf_approval_routing_current->save()) {
                        throw new \Exception('Error update current routing in approval workflow');
                    }

                    /** add the next routing / next sequence must be after wf updated*/
                    $next_sequence = $this->grabNextApproverLevel($model->ApplicationGuid);
                    $next_recipient = $this->grabRecipientByWorkflowUserOrCreate($model->ApplicationGuid, $next_sequence);
                    $next_recipient_guid = $next_recipient->appWorkflowUser->Guid;

                    $wf_approval_routing_next = new EformAppWorkflowApprovalRouting();
                    $wf_approval_routing_next->AppGuid = $model->ApplicationGuid;
                    $wf_approval_routing_next->AppType = self::WF_APPROVAL_APPTYPE;
                    $wf_approval_routing_next->WorkflowGuid = $wf_approval->Guid;
                    $wf_approval_routing_next->WFInstanceGuid = $this->createGuid();
                    $wf_approval_routing_next->Sequence = $next_sequence; // new submission use 1 as sequence
                    $wf_approval_routing_next->SenderGuid = Yii::$app->user->identity->grabWorkflowUserGuid();
                    $wf_approval_routing_next->RecipientGuid = $next_recipient_guid;
                    $wf_approval_routing_next->OriginalRecipientGuid = $next_recipient_guid;
                    $wf_approval_routing_next->Subject = $this->subjectRemark($model->ApplicationId, $next_recipient->ApproverType);
                    $wf_approval_routing_next->Status = 0; //new  
                    $wf_approval_routing_next->ApprovalAction = 0;
                    $wf_approval_routing_next->DateReceived = $this->nowDate();
                    $wf_approval_routing_next->DueDate = $this->calculateDueDate($this->nowDate(), $next_recipient->ApproverDueDay . " days");

                    if (!$wf_approval_routing_next->save()) {
                        throw new \Exception("Error Processing Request" . json_encode($wf_approval_routing_next->errors));
                    }

                    /** insert next approver  */
                    $wf_approval_approver = EformAppWorkflowApprovalApprover::find()
                    ->where(['WorkflowGuid' => $wf_approval->Guid, 'Approver' => $next_recipient_guid])
                    ->one();

                    if(empty($wf_approval_approver)) {

                        $wf_approval_approver = new EformAppWorkflowApprovalApprover();
                        $wf_approval_approver->WorkflowGuid = $wf_approval->Guid;
                        $wf_approval_approver->Sequence = 50;
                        $wf_approval_approver->Approver = $next_recipient_guid;
                        $wf_approval_approver->ActionType = 0; // unless reject level 50
                        $wf_approval_approver->DueDays = 3; // no futher information where this value came from
                        $wf_approval_approver->TaskNotification = 1; // no sure for what, leave it for later

                        if (!$wf_approval_approver->save()) {
                            throw new \Exception("Error saving aproval approver in approval workflow" . json_encode($wf_approval_approver->errors));
                        }
                    }
                    /** update workflow info approve */
                    $model_update = EformApplicationInfo::findOne($model->ApplicationId);
                    $model_update->Status = 1; // in progress

                    if (!$model_update->save()) {
                        throw new \Exception("Error saving model in workflow submit");
                    }

                    /** email notification */
                }


                if (!empty($model->errors) && empty(!$model_attachments->errors)) {

                    Yii::$app->session->setFlash('error', json_encode(
                        [
                            'EformApplicationInfo' => json_encode($model->errors),
                            'EformApplicationAttachments' => json_encode($model_attachments->errors),
                        ]
                    ));

                    throw new \Exception("Error saving data");
                    // return $this->redirect(['/web/edocument-list']);
                }
            });

            /** all ok redirect */
            Yii::$app->session->setFlash('success', 'Application Successfully Saved');

            return $this->redirect(['/web/edocument-list']);
        }
    }

    /** Delete the application */
    public function actionDelete($id)
    {
        $model = EformApplicationInfo::findOne($id);

        if ($model->delete()) {
            Yii::$app->session->setFlash('warning', 'Application has been deleted');
        }

        return $this->redirect(['/web/edocument-list']);
    }

    /** fetch staff info using id */
    public function grabStaffInfoByStaffId($staffid)
    {
        return StaffInfo::find()->where(['StaffId' => $staffid])->one();
    }

    /** fetch staff info using id */
    public function reference($cat, $code, $field)
    {
        return Ref::getDesc($cat, $code, $field);
    }

    /**
     * Give current date time
     * @return string the date
     */
    private function nowDate()
    {
        return date('Y-m-d H:i:s');
    }

    /**
     * Create Guid
     * @return string the guid
     */
    private function createGuid(): string
    {
        return EformAppWorkflowApproval::createGuid();
    }

    /**
     * Get or create the user guid
     * @param  string $staffid Staffid
     * @return mixed
     */
    public function getOrCreateUserGuid($staffid)
    {

        return (new EformAppWorkflowUser)->getOrCreateUserGuid($staffid);
    }

    /**
     * Return the current level approver
     * @return int
     */
    public function grabCurrentApproverLevel($appguid)
    {
        return EformApplicationInfo::grabCurrentApproverLevel($appguid);
    }

    /**
     * Return the current level approver
     * @return int
     */
    public function grabCurrentRouting($appguid)
    {
        return EformApplicationInfo::grabCurrentRouting($appguid);
    }

    /**
     * Return the current level approver
     * @return int
     */
    public function grabMaxApproverLevel($appguid)
    {
        /** if routing empty set the approver to 1*/
        $routing = EformApplicationApprovers::find()
            ->where(['AppGuid' => $appguid])
            ->orderBy('ApproverLevel DESC')
            ->one();

        if (empty($routing)) {
            return 0;
        }

        return $routing->ApproverLevel;
    }

    /**
     * Return the current level approver
     * @return int
     */
    public function grabNextApproverLevel($appguid)
    {
        /** if routing empty set the approver to 1*/
        $routing = EformAppWorkflowApprovalRouting::find()
            ->where(['AppGuid' => $appguid])
            ->andWhere(['Status' => 2])
            ->orderBy('Sequence DESC')
            ->one();

        if (empty($routing)) {
            return 1;
        }

        $max  = $this->grabMaxApproverLevel($appguid);
        $curr = $this->grabCurrentApproverLevel($appguid);

        if ($curr === 50) {
            return 1;
        }

        if ($routing->Sequence >= $max) {
            return -1;
        }

        if ($routing->Sequence + 1 == $curr) {
            return  0; #no insertion on routing will ocurr because this will no advance the flow
        }

        return $routing->Sequence + 1;
    }

    /**
     * Grab Recipient 
     * @return 
     */
    public function grabRecipientByLevel($appguid, $level)
    {
        $wf_user = EformApplicationApprovers::find()->where(['AppGuid' => $appguid, 'ApproverLevel' => $level])->one();

        if (empty($wf_user)) {
            throw new \Exception('This Recipient does not exist on this app guid');
        }

        return $wf_user;
    }

    /**
     * Grab Approver by staffid 
     * @return 
     */
    public function grabApproverByStaffId($appguid, $staffid)
    {
        // $ap_user = EformApplicationApprovers::find()->where(['AppGuid' => $appguid, 'ApproverStaffID' => $staffid])->one();
        $ap_user = (new EformApplicationApprovers)->grabApproverByStaffId($appguid, $staffid);

        if (empty($ap_user)) {
            throw new \Exception('This Approver does not exist on this app guid');
        }

        return $ap_user;
    }

    /**
     * Grab Approver by ID 
     * @return 
     */
    public function grabApproverById($appguid, $id)
    {
        $ap_user = EformApplicationApprovers::find()->where(['AppGuid' => $appguid, 'ID' => $id])->one();

        if (empty($ap_user)) {
            throw new \Exception('This Approver does not exist on this app guid');
        }

        return $ap_user;
    }

    public function grabWorkflowUserByStaffid($staffid) {
        return EformAppWorkflowUser::find()->where(['StaffId' => $staffid])->one();
    }

    public function grabRecipientByWorkflowUserOrCreate($appguid, $sequence)
    {
        /** create the user guid if doest not exis on workflow user */
        $recipient = $this->grabRecipientByLevel($appguid, $sequence);

        if (empty($recipient->appWorkflowUser)) {
            $this->getOrCreateUserGuid($recipient->ApproverStaffID);

            /**  refetch the data */
            $recipient = $this->grabRecipientByLevel($appguid, $sequence);
        }

        return $recipient;
    }

    public function subjectRemark($application_id, $approverType)
    {
        if ($approverType === 'Approver') {
            return Yii::t('app', 'Please Approve Application') . ' ' . $this->AppRefNo($application_id);
        }

        if ($approverType === 'Checker') {
            return Yii::t('app', 'Please Check Application') . ' ' . $this->AppRefNo($application_id);
        }

        if ($approverType === 'Verifier') {
            return Yii::t('app', 'Please Verify Application') . ' ' . $this->AppRefNo($application_id);
        }

        if ($approverType === 'Reject') {
            return Yii::t('app', 'Please Check this Application') . ' ' . $this->AppRefNo($application_id);
        }
    }

    // Function to calculate the due date based on the start date and duration
    public function calculateDueDate($startDate, $duration)
    {
        // Create a DateTime object from the start date
        $startDateTime = new \DateTime($startDate);

        // Create a DateInterval object from the duration string
        $interval = \DateInterval::createFromDateString($duration);

        // Add the interval to the start date to get the due date
        $dueDateTime = $startDateTime->add($interval);

        // Return the due date as a string in the desired format
        return $dueDateTime->format('Y-m-d H:i:s'); // Example format: YYYY-MM-DD
    }

    public function addWfRoutingHistory($guid, $event_type, $description, $sequence)
    {
        $wf_approval_routing_history = new EformAppWorkflowApprovalRoutingHistory();
        $wf_approval_routing_history->WorkflowGuid = $guid;
        $wf_approval_routing_history->EventType = $event_type;
        $wf_approval_routing_history->DateCreated = $this->nowDate();
        $wf_approval_routing_history->Description = $description;
        $wf_approval_routing_history->Sequence = $sequence;

        if(!$wf_approval_routing_history->save()) {
            throw new \Exception('Error Saving Wf history ' . json_encode($wf_approval_routing_history->errors) );
        }
    }

    public function actionStub($id, $level = null)
    {
        try {
            $max_level =  $this->grabMaxApproverLevel($id);

            // test 1 = id BA586AFF-D0AA-41B1-86E2-D147A0173707
            if ($max_level != 4) {
                // throw new \Exception('Max level Failed assertion ' . $max_level);
            }

            $curr_level = $this->grabCurrentApproverLevel($id);

            if ($curr_level != 4) {
                // throw new \Exception('curr level Failed assertion ' . $curr_level);
            }

            $next_level = $this->grabNextApproverLevel($id);

            if ($next_level != -1) {
                // throw new \Exception('next level Failed assertion ' . $next_level);
            }
            $guidByLevel = '';
            // $guidByLevel = $this->grabRecipientByLevel($id, $level)->appWorkflowUser->Guid;

            $dueday = $this->calculateDueDate(date('Y-m-d H:i:s'), "3 days");

            // var_dump($max_level, $curr_level, $next_level, $guidByLevel, $dueday);
             
            /*
                // send file to api
             $this->file_conversion('DCD229B9-5817-43A8-8491-97231A36ACA9', [
                'application' => [
                    'name' => 'Nur Ain Shahri',
                    'department' => 'INFORMATION TECHNOLOGY',
                    'position' => 'DEVELOPER',
                    'application_date' => '2024-10-10',
                    'date_of_application' => '2024-10-10',
                    'type' => 'Cadangan',
                    'reference_no' => '00001992',
                    'title' => 'FILE UPLOAD TESTING',
                    'file_path' => '/uploads/eform-edocument/eDoc-screen-1734416717.docx'
                ],
                'approver' => [
                    [
                        'name' => 'SITI NADIYAH BINTI AWALUDIN (1999104)',
                        'department' => 'INFORMATION TECHNOLOGY SYSTEM',
                        'position' => 'PMO',
                        'date' => '25/09/2024 03:22 PM',
                        'comment' => 'comment 1',
                        'role' => 'Disediakan Oleh',
                    ],
                    [
                        'name' => 'NORAZLINA BINTI MOHD ZAHARIN (2008036)',
                        'department' => 'LEGAL (PRODUCTS & SERVICES)',
                        'position' => 'KERANI TINGKATAN BIASA',
                        'date' => '25/09/2024 03:51 PM',
                        'comment' => 'comment 2',
                        'role' => 'Disemak Oleh',
                    ]
                ]
            ]);
        */
       
        /* 
        $this->sendEmail(403118, '{C7D27FE0-C674-46CE-981D-05234BBE3C4B}', [
            'subject' => 'Please check id 403118',
            'content' => 'Please check id 403118',
        ], 
        'allif.ahmad92@gmail.com',
        [
            'view' => 'basic',
            'data' => [
                'message' => 'Please check id 403118'
            ]
        ]
        );
        */
        
        } catch (\Throwable $t) {
            echo $t->getMessage();
        }
    }

    public function file_conversion($appguid, $data) {
        // insert file path
        $conversion = new FileConversion();
        $conversion->app_guid = $appguid;
        $conversion->file_path = $data['application']['file_path'];
        $conversion->data = json_encode($data);
        $conversion->status = 0;
        $conversion->created_at = date('Y-m-d H:i:s');

        if(!$conversion->save()) {
            throw new \Exception('Failed to save conversion data');
        }
        // insert app guid
        
        Yii::$app->queue->push(new FileConversionJob([
            'conversion_id' => $conversion->conversion_id,
        ]));
         
        //insert into queue
    }

    /**
     * Make a ref no
     * @param string $application_id Application id
     */
    private function AppRefNo($application_id): string {
        return EformApplicationInfo::AppRefNo($application_id);
    }

    /**
     * Update approver comment
     * @param  EformApplicationInfo $model  Model from application info
     * @param  String $action APP_POSITIVE_ACTION_NAME / APP_NEGATIVE_ACTION_NAME
     * @return void
     */
    private function updateApproverComment($model, $action) {
        //update app approver comment
        $wf_application_approver = EformApplicationApprovers::find()->where(['AppGuid' => $model->ApplicationGuid, 'ApproverStaffID' => Yii::$app->user->identity->staff_no])->one();
        

        if(empty($wf_application_approver)) {
            throw new Exception('Empty workflow approver in update approver comment : staff id' . Yii::$app->user->identity->staff_no);
        }

        if($action == 'APP_POSITIVE_ACTION_NAME') {
            $wf_application_approver->ApproverApproveKomen = $model->Comments;
        }
        if($action == 'APP_NEGATIVE_ACTION_NAME') {
            $wf_application_approver->ApproverApproveKomen = $model->Comments;
        }
        
        $wf_application_approver->ApproverActionName = $this->reference($action, $wf_application_approver->ApproverType, 'descr');
        $wf_application_approver->ApproverActionDate = $this->nowDate();
        $wf_application_approver->ModifiedDate = $this->nowDate();
        $wf_application_approver->ModifiedByID = Yii::$app->user->identity->staff_no;

        if(!$wf_application_approver->save()) {
            throw new \Exception('Cannot update application approver comments, on workflow approve');
        }
    }

    private function sendEmail($app_id, $app_guid, array $message, $recepient, array $template = null) {

        Yii::$app->queue->push(new NotificationEmailJob([
            'ref_id' => $app_id,
            'ref_code' => $app_guid,
            'body' => $message,
            'recipient' => $recepient,
            'view' => $template['view'] ?? null,
            'data' => $template['data'] ?? null,
        ]));
    }

     /*
    public function ActionName($role, $type)
    {

        $action =  [
            'Approver' => [
                'positive' => 'Lulus',
                'negative' => 'Tidak Lulus'
            ],
            'Checker' => [
                'positive' => 'Sokong',
                'negative' => 'Tidak Sokong'
            ],
            'Verifier' => [
                'positive' => 'Sokong',
                'negative' => 'Tidak Sokong'
            ],
        ];

        return $action[$role][$type];
    }
    */
}