| Current Path : /var/www/cesa.co.za/php/includes/ |
| 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
);
}
}