Your IP : 216.73.217.117


Current Path : /var/www/cesa.co.za/php/includes/
Upload File :
Current File : /var/www/cesa.co.za/php/includes/ADQFirms.php

<?php

/*
 * Contact otto@igotafrica.com for details
 */

include_once('BaseTableClass.php');

/**
 * Control the  ADQFirms table
 *
 * @author Otto Saayman
 */
class ADQFirms extends BaseTableClass
{

    public function findByMemberFirmIdQuestionnaireIdYear($memberFirmID, $questionnaireId, $auditYear)
    {
        return $this->sqlf->getRow("SELECT * FROM ADQFirms WHERE FirmID = $memberFirmID AND ADQID = $questionnaireId AND AuditYear = $auditYear");
    }

    public function checkCreate($memberFirmID, $questionnaireId, $auditYear)
    {

        $questionnaireFirm = $this->findByMemberFirmIdQuestionnaireIdYear($memberFirmID, $questionnaireId, $auditYear);

        if (!is_countable($questionnaireFirm) || count($questionnaireFirm) <= 0) {

            $nowDate = new DateTime();

            $questionnaireFirm = array(
                'ADQID' => $questionnaireId,
                'FirmID' => $memberFirmID,
                'DateStarted' => $nowDate->format('Y-m-d H:i:s'),
                'AuditYear' => $auditYear
            );

            $this->sqlf->autoExecute('ADQFirms', $questionnaireFirm, 'INSERT');

            $questionnaireFirm = $this->findByMemberFirmIdQuestionnaireIdYear($memberFirmID, $questionnaireId, $auditYear);
        }

        return $questionnaireFirm;
    }

    public function getAllFromQId($qid)
    {

        $sql = "SELECT * "
            . "FROM ADQFirms adqf "
            . "INNER JOIN tblMemberFirms tmf ON adqf.FirmID = tmf.FirmID "
            . "WHERE adqf.ADQID=" . $qid . " "
            . "AND tmf.FirmID <> 1312 "
            . "AND adqf.AuditYear > " . (date('Y') - 3) . " "
            . "ORDER BY tmf.FirmName";

        return $this->sqlf->getAll($sql);
    }

    public function getOverview($filters)
    {

        $sql = "SELECT ADQFirms.FirmID,
            MAX(CASE WHEN ADQFirms.ADQID = 1 THEN ADQFirms.ADQFirmID ELSE NULL END) AS ADQFirmIDFIMS,
            MAX(CASE WHEN ADQFirms.ADQID = 2 THEN ADQFirms.ADQFirmID ELSE NULL END) AS ADQFirmIDQMS,
            MAX(CASE WHEN ADQFirms.ADQID = 3 THEN ADQFirms.ADQFirmID ELSE NULL END) AS ADQFirmIDPSM,
            MAX(CASE WHEN ADQFirms.ADQID = 1 THEN ADQFirms.ScorePerc ELSE NULL END) AS ScorePercFIMS,
            MAX(CASE WHEN ADQFirms.ADQID = 2 THEN ADQFirms.ScorePerc ELSE NULL END) AS ScorePercQMS,
            MAX(CASE WHEN ADQFirms.ADQID = 3 THEN ADQFirms.ScorePerc ELSE NULL END) AS ScorePercPSM,
            MAX(CASE WHEN ADQFirms.ADQID = 1 THEN ADQFirms.AuditScorePerc ELSE NULL END) AS AuditScorePercFIMS,
            MAX(CASE WHEN ADQFirms.ADQID = 2 THEN ADQFirms.AuditScorePerc ELSE NULL END) AS AuditScorePercQMS,
            MAX(CASE WHEN ADQFirms.ADQID = 3 THEN ADQFirms.AuditScorePerc ELSE NULL END) AS AuditScorePercPSM,
            MAX(CASE WHEN ADQFirms.ADQID = 1 THEN ADQFirms.DateStarted ELSE NULL END) AS DateStartedFIMS,
            MAX(CASE WHEN ADQFirms.ADQID = 2 THEN ADQFirms.DateStarted ELSE NULL END) AS DateStartedQMS,
            MAX(CASE WHEN ADQFirms.ADQID = 3 THEN ADQFirms.DateStarted ELSE NULL END) AS DateStartedPSM,
            MAX(CASE WHEN ADQFirms.ADQID = 1 THEN ADQFirms.DateCompleted ELSE NULL END) AS DateCompletedFIMS,
            MAX(CASE WHEN ADQFirms.ADQID = 2 THEN ADQFirms.DateCompleted ELSE NULL END) AS DateCompletedQMS,
            MAX(CASE WHEN ADQFirms.ADQID = 3 THEN ADQFirms.DateCompleted ELSE NULL END) AS DateCompletedPSM,
            MAX(CASE WHEN ADQFirms.ADQID = 1 THEN ADQFirms.ADQFirmID ELSE NULL END) AS ADQFirmIDFIMS,
            MAX(CASE WHEN ADQFirms.ADQID = 2 THEN ADQFirms.ADQFirmID ELSE NULL END) AS ADQFirmIDQMS,
            MAX(CASE WHEN ADQFirms.ADQID = 3 THEN ADQFirms.ADQFirmID ELSE NULL END) AS ADQFirmIDPSM,
            MAX(CASE WHEN ADQFirms.ADQID = 1 THEN ADQFirms.CESAApproved ELSE NULL END) AS CESAApprovedFIMS,
            MAX(CASE WHEN ADQFirms.ADQID = 2 THEN ADQFirms.CESAApproved ELSE NULL END) AS CESAApprovedQMS,
            MAX(CASE WHEN ADQFirms.ADQID = 3 THEN ADQFirms.CESAApproved ELSE NULL END) AS CESAApprovedPSM,
            MAX(CASE WHEN ADQFirms.ADQID = 1 THEN ADQAudit.Verified ELSE NULL END) AS VerifiedFIMS,
            MAX(CASE WHEN ADQFirms.ADQID = 2 THEN ADQAudit.Verified ELSE NULL END) AS VerifiedQMS,
            MAX(CASE WHEN ADQFirms.ADQID = 3 THEN ADQAudit.Verified ELSE NULL END) AS VerifiedPSM,
            MAX(CASE WHEN ADQFirms.ADQID = 1 THEN (SELECT COUNT(*) AS AnswerCount 
                FROM `ADQAnswers` a 
                INNER JOIN ADQuestions q ON a.ADQuestionID = q.ADQuestionID 
                WHERE q.ADQID = 1 AND a.ADQFirmID = ADQFirms.ADQFirmID) ELSE NULL END) AS AnswerCountFIMS,
            MAX(CASE WHEN ADQFirms.ADQID = 2 THEN (SELECT COUNT(*) AS AnswerCount 
                FROM `ADQAnswers` a 
                INNER JOIN ADQuestions q ON a.ADQuestionID = q.ADQuestionID 
                WHERE q.ADQID = 2 AND a.ADQFirmID = ADQFirms.ADQFirmID) ELSE NULL END) AS AnswerCountQMS,
            MAX(CASE WHEN ADQFirms.ADQID = 3 THEN (SELECT COUNT(*) AS AnswerCount 
                FROM `ADQAnswers` a 
                INNER JOIN ADQuestions q ON a.ADQuestionID = q.ADQuestionID 
                WHERE q.ADQID = 3 AND a.ADQFirmID = ADQFirms.ADQFirmID) ELSE NULL END) AS AnswerCountPSM,
            tblMemberFirms.FirmName, tblMemberFirms.DateJoined, MAX(ADQAuditID) AS ADQAuditID, 
            MIN(ADQAudit.ADQAuditID) AS FirstADQAuditID, tblMemberFirms.DateJoined
        FROM ADQFirms JOIN tblMemberFirms USING (FirmID)
        LEFT JOIN ADQAudit USING (ADQFirmID)
        WHERE ADQFirms.FirmID<>1312 ";

        if (isset($filters["filteraudit"]) && !empty($filters["filteraudit"])) {
            if ($filters["filteraudit"] == "P") {
                $sql .= " AND ADQAudit.Verified=''";
            } else {
                $sql .= " AND ADQAudit.Verified='" . addslashes($filters["filteraudit"]) . "'";
            }
        }

        if (isset($filters["auditYear"]) && $filters["auditYear"] != 'all') {
            $sql .= " AND ADQFirms.AuditYear = " . $filters["auditYear"];
        }

        $sql .= "
GROUP BY ADQFirms.FirmID, tblMemberFirms.FirmName, tblMemberFirms.DateJoined
ORDER BY FirmName";

        // echo $sql . '<br />';

        return $this->sqlf->getAll($sql);
    }

    public function getStats($filters)
    {

        $sql = "SELECT COUNT(ADQFirms.FirmID) AS FirmCount,
        MAX(CASE WHEN ADQFirms.ADQID = 1 THEN ADQFirms.ADQFirmID ELSE NULL END) AS ADQFirmIDFIMS,
        MAX(CASE WHEN ADQFirms.ADQID = 2 THEN ADQFirms.ADQFirmID ELSE NULL END) AS ADQFirmIDQMS,
        MAX(CASE WHEN ADQFirms.ADQID = 3 THEN ADQFirms.ADQFirmID ELSE NULL END) AS ADQFirmIDPSM,
        MAX(CASE WHEN ADQFirms.ADQID = 1 THEN ADQFirms.ScorePerc ELSE NULL END) AS ScorePercFIMS,
        MAX(CASE WHEN ADQFirms.ADQID = 2 THEN ADQFirms.ScorePerc ELSE NULL END) AS ScorePercQMS,
        MAX(CASE WHEN ADQFirms.ADQID = 3 THEN ADQFirms.ScorePerc ELSE NULL END) AS ScorePercPSM,
        MAX(CASE WHEN ADQFirms.ADQID = 1 THEN ADQFirms.AuditScorePerc ELSE NULL END) AS AuditScorePercFIMS,
        MAX(CASE WHEN ADQFirms.ADQID = 2 THEN ADQFirms.AuditScorePerc ELSE NULL END) AS AuditScorePercQMS,
        MAX(CASE WHEN ADQFirms.ADQID = 3 THEN ADQFirms.AuditScorePerc ELSE NULL END) AS AuditScorePercPSM,
        MAX(CASE WHEN ADQFirms.ADQID = 1 THEN ADQFirms.DateStarted ELSE NULL END) AS DateStartedFIMS,
        MAX(CASE WHEN ADQFirms.ADQID = 2 THEN ADQFirms.DateStarted ELSE NULL END) AS DateStartedQMS,
        MAX(CASE WHEN ADQFirms.ADQID = 3 THEN ADQFirms.DateStarted ELSE NULL END) AS DateStartedPSM,
        MAX(CASE WHEN ADQFirms.ADQID = 1 THEN ADQFirms.DateCompleted ELSE NULL END) AS DateCompletedFIMS,
        MAX(CASE WHEN ADQFirms.ADQID = 2 THEN ADQFirms.DateCompleted ELSE NULL END) AS DateCompletedQMS,
        MAX(CASE WHEN ADQFirms.ADQID = 3 THEN ADQFirms.DateCompleted ELSE NULL END) AS DateCompletedPSM,
        SUM(CASE WHEN ADQFirms.ADQID = 1 AND ADQFirms.DateCompleted IS NOT NULL THEN 1 ELSE 0 END) AS DateCompletedFIMSCnt,
        SUM(CASE WHEN ADQFirms.ADQID = 2 AND ADQFirms.DateCompleted IS NOT NULL THEN 1 ELSE 0 END) AS DateCompletedQMSCnt,
        SUM(CASE WHEN ADQFirms.ADQID = 3 AND ADQFirms.DateCompleted IS NOT NULL THEN 1 ELSE 0 END) AS DateCompletedPSMCnt,
        MAX(CASE WHEN ADQFirms.ADQID = 1 THEN ADQFirms.ADQFirmID ELSE NULL END) AS ADQFirmIDFIMS,
        MAX(CASE WHEN ADQFirms.ADQID = 2 THEN ADQFirms.ADQFirmID ELSE NULL END) AS ADQFirmIDQMS,
        MAX(CASE WHEN ADQFirms.ADQID = 3 THEN ADQFirms.ADQFirmID ELSE NULL END) AS ADQFirmIDPSM,
        MAX(CASE WHEN ADQFirms.ADQID = 1 THEN ADQFirms.CESAApproved ELSE NULL END) AS CESAApprovedFIMS,
        MAX(CASE WHEN ADQFirms.ADQID = 2 THEN ADQFirms.CESAApproved ELSE NULL END) AS CESAApprovedQMS,
        MAX(CASE WHEN ADQFirms.ADQID = 3 THEN ADQFirms.CESAApproved ELSE NULL END) AS CESAApprovedPSM,
        MAX(ADQAuditID) AS ADQAuditID, MIN(ADQAudit.ADQAuditID) AS FirstADQAuditID
FROM ADQFirms JOIN tblMemberFirms USING (FirmID)
LEFT JOIN ADQAudit USING (ADQFirmID)
WHERE ADQFirms.FirmID<>1312 ";
        if (isset($filters["filteraudit"]) && !empty($filters["filteraudit"])) {
            if ($filters["filteraudit"] == "P") {
                $sql .= " AND ADQAudit.Verified=''";
            } else {
                $sql .= " AND ADQAudit.Verified='" . addslashes($filters["filteraudit"]) . "'";
            }
        }

        if (isset($filters["auditYear"]) && $filters["auditYear"] != 'all') {
            $sql .= " AND ADQFirms.AuditYear = " . $filters["auditYear"];
        }

        $stats = $this->sqlf->getAll($sql);

        return $stats[0];
    }

    public function getMSDStartDate($firmId, $qid, $auditYear)
    {
        $sql = "SELECT * FROM ADQFirms adqf "
            . "WHERE adqf.FirmID=" . $firmId . " AND adqf.ADQID=" . $qid . " AND adqf.AuditYear=" . $auditYear;

        $aDecQuestionnaire = $this->sqlf->getRow($sql);

        if (!is_array($aDecQuestionnaire) || count($aDecQuestionnaire) <= 0) {
            return '';
        }

        $MSDDate = new DateTime($aDecQuestionnaire['DateStarted']);

        return $MSDDate->format('Y-m-d');
    }

    public static function answerCountIndicator($answerCount) {
        if ($answerCount <= 0) {
            return '<span style="background-color:red; color:white; padding: 4px; border-radius: 2px;">0</span>';
        } elseif ($answerCount <= 10) {
            return '<span style="background-color:yellow; color:black; padding: 4px; border-radius: 2px;">' . $answerCount . '</span>';
        } elseif ($answerCount <= 20) {
            return '<span style="background-color:blue; color:white; padding: 4px; border-radius: 2px;">' . $answerCount . '</span>';
        } elseif ($answerCount <= 30) {
            return '<span style="background-color:green; color:white; padding: 4px; border-radius: 2px;">' . $answerCount . '</span>';
        } else {
            return '<span style="color:green; padding: 4px; border-radius: 2px;">' . $answerCount . '</span>';
        }
    }

    /**
     * Get all member firms with verified QMS in MSD system
     * 
     * Returns firms that have completed QMS questionnaires (ADQID=2) 
     * with verified status (Verified='Y' or 'C') in ADQAudit
     * 
     * @return array Array of firms with FirmID, FirmName, CurrentQMSISOCert, and VerifiedStatus
     */
    public function getFirmsWithVerifiedQMS()
    {
        $sql = "SELECT DISTINCT 
                    af.FirmID,
                    tmf.FirmName,
                    tmf.QMSISOCert AS CurrentQMSISOCert,
                    MAX(CASE WHEN adqa.Verified IN ('Y', 'C') THEN 'Y' ELSE 'N' END) AS VerifiedStatus
                FROM ADQFirms af
                INNER JOIN tblMemberFirms tmf ON af.FirmID = tmf.FirmID
                LEFT JOIN ADQAudit adqa ON af.ADQFirmID = adqa.ADQFirmID
                WHERE af.ADQID = 2  -- QMS questionnaire
                    AND af.DateCompleted IS NOT NULL  -- Only completed questionnaires
                    AND adqa.Verified IN ('Y', 'C')  -- Verified or Verified With Comments
                GROUP BY af.FirmID, tmf.FirmName, tmf.QMSISOCert";

        return $this->sqlf->getAll($sql);
    }

    /**
     * Get firms that should have QMSISOCert reset to 'N'
     * 
     * Returns firms that currently have QMSISOCert='Y' but no longer have
     * a verified QMS in the MSD system. This handles cases where verification
     * was removed or expired.
     * 
     * @return array Array of firms with FirmID, FirmName, and QMSISOCert
     */
    public function getFirmsWithoutVerifiedQMS()
    {
        $sql = "SELECT DISTINCT 
                    tmf.FirmID,
                    tmf.FirmName,
                    tmf.QMSISOCert
                  FROM tblMemberFirms tmf
                  WHERE tmf.QMSISOCert = 'Y'
                    AND tmf.FirmID NOT IN (
                        SELECT DISTINCT af.FirmID
                        FROM ADQFirms af
                        LEFT JOIN ADQAudit adqa ON af.ADQFirmID = adqa.ADQFirmID
                        WHERE af.ADQID = 2
                          AND af.DateCompleted IS NOT NULL
                          AND adqa.Verified IN ('Y', 'C')
                    )";

        return $this->sqlf->getAll($sql);
    }

    /**
     * Update QMSISOCert status for a specific firm
     * 
     * @param int $firmID The FirmID to update
     * @param string $status The status to set ('Y' or 'N')
     * @return bool True on success, false on failure
     */
    public function updateQMSISOCertStatus($firmID, $status)
    {
        $firmID = intval($firmID);
        $status = $this->sqlf->qstr($status);

        $updateSql = "UPDATE tblMemberFirms 
                     SET QMSISOCert = {$status} 
                     WHERE FirmID = {$firmID}";

        return $this->sqlf->execute($updateSql);
    }

    /**
     * Get list of firms that would be updated (dry-run mode)
     * 
     * Returns an array of firms that would be updated without actually
     * performing the database updates. Useful for testing and preview.
     * 
     * @return array Array with 'toUpdate' (firms to set to 'Y'), 'toReset' (firms to set to 'N'), and 'skipped' counts
     */
    public function getFirmsToUpdate()
    {
        $toUpdate = array();
        $toReset = array();
        $skipped = 0;

        // Get firms with verified QMS
        $firms = $this->getFirmsWithVerifiedQMS();

        foreach ($firms as $firm) {
            $firmID = $firm['FirmID'];
            $firmName = $firm['FirmName'];
            $currentStatus = $firm['CurrentQMSISOCert'];
            $verifiedStatus = $firm['VerifiedStatus'];

            // Only include if status has changed
            if ($currentStatus != $verifiedStatus) {
                $toUpdate[] = array(
                    'FirmID' => $firmID,
                    'FirmName' => $firmName,
                    'CurrentStatus' => $currentStatus,
                    'NewStatus' => $verifiedStatus
                );
            } else {
                $skipped++;
            }
        }

        // Get firms that should have QMSISOCert reset to 'N'
        $firmsNoVerified = $this->getFirmsWithoutVerifiedQMS();

        foreach ($firmsNoVerified as $firm) {
            $firmID = $firm['FirmID'];
            $firmName = $firm['FirmName'];

            $toReset[] = array(
                'FirmID' => $firmID,
                'FirmName' => $firmName,
                'CurrentStatus' => $firm['QMSISOCert'],
                'NewStatus' => 'N'
            );
        }

        return array(
            'toUpdate' => $toUpdate,
            'toReset' => $toReset,
            'skipped' => $skipped
        );
    }

    /**
     * Sync QMSISOCert status in tblMemberFirms based on MSD verifications
     * 
     * This method:
     * 1. Finds all firms with verified QMS and updates their QMSISOCert to 'Y'
     * 2. Finds firms that should have QMSISOCert reset to 'N' (no longer verified)
     * 
     * @param bool $dryRun If true, only returns what would be updated without making changes
     * @return array Statistics array with 'updated', 'skipped', and 'errors' counts, or dry-run data if $dryRun is true
     */
    public function syncQMSISOCertStatus($dryRun = false)
    {
        include_once($_SERVER['DOCUMENT_ROOT'] . '/php/includes/ErrorLog.php');

        // If dry run, return what would be updated
        if ($dryRun) {
            return $this->getFirmsToUpdate();
        }

        $updated = 0;
        $skipped = 0;
        $errors = 0;

        // Get firms with verified QMS
        $firms = $this->getFirmsWithVerifiedQMS();

        foreach ($firms as $firm) {
            $firmID = $firm['FirmID'];
            $firmName = $firm['FirmName'];
            $currentStatus = $firm['CurrentQMSISOCert'];
            $verifiedStatus = $firm['VerifiedStatus'];

            // Only update if status has changed
            if ($currentStatus != $verifiedStatus) {
                try {
                    $result = $this->updateQMSISOCertStatus($firmID, $verifiedStatus);

                    if ($result) {
                        $updated++;
                        ErrorLog::logInfo("Updated QMSISOCert for FirmID {$firmID} ({$firmName}) from '{$currentStatus}' to '{$verifiedStatus}'");
                    } else {
                        $errors++;
                        ErrorLog::logError("Failed to update QMSISOCert for FirmID {$firmID} ({$firmName})");
                    }
                } catch (Exception $e) {
                    $errors++;
                    ErrorLog::logError("Error updating QMSISOCert for FirmID {$firmID} ({$firmName}): " . $e->getMessage());
                }
            } else {
                $skipped++;
            }
        }

        // Get firms that should have QMSISOCert reset to 'N'
        $firmsNoVerified = $this->getFirmsWithoutVerifiedQMS();

        foreach ($firmsNoVerified as $firm) {
            $firmID = $firm['FirmID'];
            $firmName = $firm['FirmName'];

            try {
                $result = $this->updateQMSISOCertStatus($firmID, 'N');

                if ($result) {
                    $updated++;
                    ErrorLog::logInfo("Reset QMSISOCert to 'N' for FirmID {$firmID} ({$firmName}) - no verified QMS found");
                } else {
                    $errors++;
                    ErrorLog::logError("Failed to reset QMSISOCert for FirmID {$firmID} ({$firmName})");
                }
            } catch (Exception $e) {
                $errors++;
                ErrorLog::logError("Error resetting QMSISOCert for FirmID {$firmID} ({$firmName}): " . $e->getMessage());
            }
        }

        return array(
            'updated' => $updated,
            'skipped' => $skipped,
            'errors' => $errors
        );
    }
}