HEX
Server: Apache/2.2.15 (CentOS)
System: Linux ip-10-0-2-146.eu-west-1.compute.internal 2.6.32-754.35.1.el6.centos.plus.x86_64 #1 SMP Sat Nov 7 11:33:42 UTC 2020 x86_64
User: root (0)
PHP: 5.6.40
Disabled: NONE
Upload Files
File: /www/exchange2/cmws/scripts/root-receipts-discovery.php
<?php
// script for discovering and verifying the calculations for Root Grand Parent Receipts in Exchange 2.0

$timeStart = microtime(true);

if (PHP_SAPI !== "cli") {
    echo "The script should be run only from CLI.";
    exit;
}

$memoryLimit = '1512M';
if (ini_set('memory_limit', $memoryLimit) === false) {
    echo "Unable to set the required memory limit: " . $memoryLimit . ".\n";
    exit;
}

// required includes
require_once("../../exchange/Bin/constants.php");
require_once("../../exchange/Bin/init.php");
require_once(ROOT_FOLDER . "Bin/Security.php");
require_once(ROOT_FOLDER . "admin/classes/Model/base_actions.php");
require_once(ROOT_FOLDER . "admin/classes/Model/CMSync.php");

$cmSync = new CMSync(MYSQL_ENGINE_IMPROVED);

if ($cmSync->initLogFile(CM_SYNC_TRANSACTION_CHILD) === false
    || $cmSync->initLogFile(CM_SYNC_TRANSACTION_ROOT) === false
    || $cmSync->initLogFile(CM_SYNC_TRANSACTION_REMOVED) === false) {
    echo "Log File write error: Unable to create log file. Please check folder permissions.\n";
    exit;
}

$entitiesArgArr = $argv;
array_shift($entitiesArgArr);
array_walk($entitiesArgArr, function (&$value) { $value = ucfirst(strtolower($value)); });

if (in_array('debug', $entitiesArgArr, true) === true) {
    $cmSync->debugMode = true;
}

$cmSync->loadFxRates();
echo "Loaded Fx Rates for ", count($cmSync->fxRatesData), " days.\n";

$cmSync->loadAllTrailingBalances();
echo "Loaded ", count($cmSync->tbData), " Trailing Balance Transactions.\n";

$cmSync->loadAllTrailingBalances(true);
echo "Loaded ", count($cmSync->tbChildData), " unidirectionally linked Children Transactions.\n";

$cmSync->initDiscoveryData();
$allChildrenArr = $cmSync->getAllLatestChildrenReceipts();
$allChildrenArrCount = count($allChildrenArr);
echo "Loaded ", $allChildrenArrCount, " Latest Children Transactions.\n";

$processedLatestChildrenArr = array();
$brokenParentsArr = array();
$deletedTransArr = array();
$currentLatestChildId = 0;
$currentParentChild = 0;
$childrenProcessedCount = 0;
$sumCheck1MismatchCount = 0;
$sumCheck2MismatchCount = 0;
$sumCheck3MismatchCount = 0;
$sumCheck4MismatchCount = 0;

$commentsArr = array(
    '232972' => array(
        'error_type' => "Missing Amount",
        'comments' => "It appears the currency and amount of one of the split child transactions 232975 (OCPA) has been altered manually " .
            "(amount and currency changed from EUR 1,502,888.10 to USD 1,485,499.36 without any notes)."
        ),
    '109671' => array(
        'error_type' => "Missing Amount",
        'comments' => "It appears the amount of child transaction 110030 (OCPA) has been altered manually " .
            "(amount changed from EPR'ed Deposit of EUR 98,869.16 to OCPA EUR 178,430.59 without any notes)."
    ),
    '110031' => array(
        'error_type' => "Missing Amount",
        'comments' => "It appears the amount of parent transaction 110030 (OCPA) has been altered manually " .
            "(amount changed from EPR'ed Deposit of EUR 98,869.16 to OCPA EUR 178,430.59 without any notes)."
    )
);

while (!empty($allChildrenArr)) {
    $childArr = array_shift($allChildrenArr);

    // init additional array elements
    if (isset($cmSync->discoveryData[$childArr['exchange_ref_id']]) === false) {
        $childArr['children'] = array();
        $childArr['children_array'] = array();
        $childArr['parents'] = array();
        $childArr['parents_array'] = array();
        $childArr['is_root'] = 0;
        $childArr['roots'] = array();
        $childArr['roots_array'] = array();
        $childArr['face_value_tb'] = 0.00;
        $childArr['face_value_used'] = 0.00;
        $childArr['log_message'] = null;
        $childArr['check_sum_4'] = $childArr['check_sum_3'] = $childArr['check_sum_2'] = null;
    }

    if ((int)$childArr['latest_child'] === 1) {
        echo "Processing Latest Child Transaction [" . $childArr['exchange_ref_id'] . "] ", ++$childrenProcessedCount,
        " out of ", $allChildrenArrCount, "\r";
    }

    if (isset($processedLatestChildrenArr[$childArr['exchange_ref_id']]) === true) {
        $childArr['latest_child'] = 1;
        $currentLatestChildId = $childArr['exchange_ref_id'];
    } elseif (isset($processedLatestChildrenArr[$childArr['exchange_ref_id']]) === false
        && (int)$childArr['latest_child'] === 1) {
        $processedLatestChildrenArr[$childArr['exchange_ref_id']] = true;
        $currentLatestChildId = $childArr['exchange_ref_id'];
    } else {
        $currentParentChild = $childArr['exchange_ref_id'];
    }

    $tbArr = $cmSync->getTrailingBalance($childArr);
    $parentArr = $cmSync->getParentReceiptList($childArr);

    if (count($parentArr) === 0) {
        if ((int)$childArr['latest_child'] === 1) {
            $errorText = "Unable to obtain Parent Receipt list for Latest Child Transaction: " .
                $childArr['exchange_ref_id'] . ".";
        } else {
            $errorText = "Unable to obtain Parent Receipt list for a Parent Transaction: " .
                $childArr['exchange_ref_id'] . ".";
        }
        $cmSync->updateArrayLogMessage($childArr, $errorText);

        if (isset($cmSync->discoveryData[$childArr['exchange_ref_id']]) === false) {
            $cmSync->discoveryData[$childArr['exchange_ref_id']] = $childArr;
        }
        unset($childArr);
        continue;
    }

    if ((int)$childArr['latest_child'] === 1) {
        $childArr['face_value_used'] = round($childArr['face_value'] + $childArr['face_value_tb'], 2);
    }

    while (!empty($parentArr)) {
        $errorText = '';
        $currentParentArr = array_shift($parentArr);
        $currentParentArr['is_root'] = 0;
        $currentParentArr['log_message'] = null;
        $currentParentArr['target_type'] = $childArr['source_type'];
        $currentParentArr['children'] = array($childArr['exchange_ref_id']);

        if (is_null($currentParentArr['ex20_id']) === true) {
            $errorText = "Transaction: " . $currentParentArr['exchange_ref_id'] . " not in Archive or Production.";
            $cmSync->updateArrayLogMessage($currentParentArr, $errorText);
            $errorText = "Parent " . $errorText;
        } elseif (isset($cmSync->discoveryData[$currentParentArr['exchange_ref_id']]) === true) {

            if (in_array($currentLatestChildId,
                    $cmSync->discoveryData[$currentParentArr['exchange_ref_id']]['latest_children'], false) === false) {
                $cmSync->discoveryData[$currentParentArr['exchange_ref_id']]['latest_children'][] = $currentLatestChildId;
            }

            if ((int)$cmSync->discoveryData[$currentParentArr['exchange_ref_id']]['latest_child'] !== 1) {
                $tmpSrcFV =
                    round($childArr['parents_array']['transactions'][$currentParentArr['exchange_ref_id']]['source_amount'],
                        2);
                $cmSync->addFaceValueUsedtoParent($cmSync->discoveryData[$currentParentArr['exchange_ref_id']],
                    $tmpSrcFV, $childArr);
            }

            if (in_array($childArr['exchange_ref_id'],
                    $cmSync->discoveryData[$currentParentArr['exchange_ref_id']]['children'], true) === false) {
                $cmSync->discoveryData[$currentParentArr['exchange_ref_id']]['children'][] = $childArr['exchange_ref_id'];
            }

        } elseif ($cmSync->isReceiptValidChild($currentParentArr)) {
            array_unshift($allChildrenArr, $currentParentArr);
        } elseif ($cmSync->isParentReceiptRoot($currentParentArr)) {
            $cmSync->addReceiptToRoots($childArr, $currentParentArr);
        } elseif ($cmSync->isReceiptParentForTrailingBalance($currentParentArr, $childArr)) {
            $currentParentArr['trailing_balance_id'] = $childArr['exchange_ref_id'];
            $currentParentArr['face_value_tb'] = $childArr['face_value'];
            if ($currentParentArr['source_table'] === 'production') {
                $cmSync->addReceiptToRoots($childArr, $currentParentArr);
            }
        } else {
            $errorText = "Transaction: " . $currentParentArr['exchange_ref_id'] . " is not a valid Child nor Root.";
            $cmSync->updateArrayLogMessage($currentParentArr, $errorText);
            $errorText = "Parent " . $errorText;
        }

        if ($errorText !== '') {
            $cmSync->updateArrayLogMessage($childArr, $errorText);

            if (isset($brokenParentsArr[$currentParentArr['exchange_ref_id']]) === false) {
                $brokenParentsArr[$currentParentArr['exchange_ref_id']] = true;
            }
        }

        if (isset($cmSync->discoveryData[$currentParentArr['exchange_ref_id']]) === false) {
            $tmpFVUsed = $childArr['parents_array']['transactions'][$currentParentArr['exchange_ref_id']]['source_amount'];
            if (!is_null($currentParentArr['trailing_balance_id'])) {
                $tmpFVUsed += $currentParentArr['face_value'];
            }

            $cmSync->addFaceValueUsedtoParent($currentParentArr, $tmpFVUsed, $childArr);

            $currentParentArr['latest_children'] = array($currentLatestChildId);
            $cmSync->discoveryData[$currentParentArr['exchange_ref_id']] = $currentParentArr;
        }

        $tmpCheckResult =
            (bool)$childArr['parents_array']['transactions'][$currentParentArr['exchange_ref_id']]['check_sum_1_flag'];

        if ($tmpCheckResult === false) {
            $sumCheck1MismatchCount++;
        }
        unset($currentParentArr, $tmpCheckResult);
    }

    if (isset($cmSync->discoveryData[$childArr['exchange_ref_id']]) === true) {
        $cmSync->discoveryData[$childArr['exchange_ref_id']]['parents_array'] = $childArr['parents_array'];
        $cmSync->discoveryData[$childArr['exchange_ref_id']]['parents'] = $childArr['parents'];
        $cmSync->discoveryData[$childArr['exchange_ref_id']]['roots'] = $childArr['roots'];
        $cmSync->discoveryData[$childArr['exchange_ref_id']]['log_message'] =  $childArr['log_message'];
        $cmSync->discoveryData[$childArr['exchange_ref_id']]['source_type'] =  $childArr['source_type'];
        if (is_null($cmSync->discoveryData[$childArr['exchange_ref_id']]['check_sum_2'])) {
            $cmSync->discoveryData[$childArr['exchange_ref_id']]['check_sum_2'] = $childArr['check_sum_2'];
            $cmSync->discoveryData[$childArr['exchange_ref_id']]['check_sum_2_flag'] = $childArr['check_sum_2_flag'];
        }
    } else {
        $cmSync->discoveryData[$childArr['exchange_ref_id']] = $childArr;
    }
    unset($parentArr, $childArr);
}

$discoveryCount = count($cmSync->discoveryData);
$discoveryProcessedCount = 0;
$timeEnd = microtime(true);
$stage1Time = round(($timeEnd - $timeStart) / 60, 2);
$timeStart2 = microtime(true);
echo "\nStage 1 of discovery completed in ", $stage1Time, " minutes.\n";

foreach ($cmSync->discoveryData as $key => $transArr) {
    echo "Processing Stage 2 discovery for Transaction [" . $transArr['exchange_ref_id'] . "] ", ++$discoveryProcessedCount,
    " out of ", $discoveryCount, "\r";

    if ((int)$transArr['is_root'] !== 1
        && (bool)$transArr['parents_array']['check_sum_2_flag'] === false) {
        $sumCheck2MismatchCount++;
    }
    $tmpDiff = round($transArr['face_value_used'] - ($transArr['face_value'] + $transArr['face_value_tb']),3);
    $cmSync->discoveryData[$key]['check_sum_3'] = $tmpDiff;
    if (abs($tmpDiff) > CM_SYNC_MINIMUM_SUMDIFF) {

        $childrenArr = $cmSync->getChildrenReceiptList($cmSync->discoveryData[$key]);

        foreach($childrenArr as $childArr) {
            if (is_null($childArr['ex20_id'])) {
                $errorText = "Child Transaction: " . $childArr['exchange_ref_id'] . " not in Production or Archive.";
                $cmSync->updateArrayLogMessage($cmSync->discoveryData[$key], $errorText);
                continue;
            }

            if (in_array($childArr['exchange_ref_id'], $cmSync->discoveryData[$key]['children'], true) === false) {
                $cmSync->discoveryData[$key]['children'][] = $childArr['exchange_ref_id'];
                $tmpSourceAmount =
                    $cmSync->discoveryData[$key]['children_array']['transactions'][$childArr['exchange_ref_id']]['source_amount'];
                $tmpDiff += $tmpSourceAmount;

                $cmSync->addFaceValueUsedtoParent($cmSync->discoveryData[$key], $tmpSourceAmount, $childArr);

                $childArr['source_type'] = $cmSync->discoveryData[$key]['target_type'];
                $childArr['is_root'] = 0;
                $childArr['log_message'] = null;
                $childArr['parents'] = array($key);
                $childArr['parents_array'] = array(
                    'type' => $cmSync->getTargetOperationType($cmSync->discoveryData[$key]['target_type'])
                );
                $tmpParentArr = array($key => $cmSync->discoveryData[$key]);
                $cmSync->processChecksForParentTransactions($tmpParentArr, $childArr);
                $cmSync->discoveryData[$childArr['exchange_ref_id']] = $childArr;

                if ($childArr['source_table'] === 'archive'
                    && ($cmSync->isParentReceiptRoot($childArr) === false
                        || $childArr['delete_notes'] === '')) {
                    $errorText = "Transaction: " . $childArr['exchange_ref_id'] . " was manually deleted.";
                    if (isset($deletedTransArr[$childArr['exchange_ref_id']]) === false) {
                        $deletedTransArr[$childArr['exchange_ref_id']] = $childArr;
                    }
                    $cmSync->updateArrayLogMessage($cmSync->discoveryData[$key], "Child " . $errorText);
                    $cmSync->updateArrayLogMessage($cmSync->discoveryData[$childArr['exchange_ref_id']], $errorText);
                    $cmSync->discoveryData[$childArr['exchange_ref_id']]['error_type'] = 'Deleted Data';
                }
            }
        }

        $tmpDiff = round($tmpDiff, 3);
        $cmSync->discoveryData[$key]['check_sum_3'] = $tmpDiff;
        if (abs($tmpDiff) > CM_SYNC_MINIMUM_SUMDIFF) {
            $sumCheck3MismatchCount++;
            $errorText = "Failed Sum Check #3 by: " . round($tmpDiff, 2) . ".";
            $cmSync->updateArrayLogMessage($cmSync->discoveryData[$key], $errorText);
        }

        if (!empty($cmSync->discoveryData[$key]['children_array'])
            && (bool)$cmSync->discoveryData[$key]['children_array']['check_sum_4_flag'] === false) {
            $sumCheck4MismatchCount++;
        }
    }

    if (!empty($cmSync->discoveryData[$key]['children'])) {
        array_walk($cmSync->discoveryData[$key]['children'], function(&$val) { $val = (int)$val; });
    }

    if (!empty($cmSync->discoveryData[$key]['latest_children'])) {
        array_walk($cmSync->discoveryData[$key]['latest_children'], function(&$val) { $val = (int)$val; });
    }

    if (!empty($cmSync->discoveryData[$key]['parents'])) {
        array_walk($cmSync->discoveryData[$key]['parents'], function(&$val) { $val = (int)$val; });
    }

    if (!empty($cmSync->discoveryData[$key]['roots'])) {
        array_walk($cmSync->discoveryData[$key]['roots'], function(&$val) { $val = (int)$val; });
    }

    $cmSync->discoveryData[$key]['error_type'] = null;
    $cmSync->discoveryData[$key]['comments'] = null;

    if (!empty($cmSync->discoveryData[$key]['log_message'])) {

        $tmpCheckSum3 = round($cmSync->discoveryData[$key]['check_sum_3'], 2);
        $tmpCheckSum4 = round($cmSync->discoveryData[$key]['check_sum_4'], 2);
        if ($tmpCheckSum3 !== 0.0
            && $tmpCheckSum4 !== 0.0) {
            $cmSync->discoveryData[$key]['error_type'] = "Missing Amount";
        } else {
            $cmSync->discoveryData[$key]['error_type'] = "Other";
        }

        if (stripos($cmSync->discoveryData[$key]['log_message'], 'Fx Rates') !== false) {
            $cmSync->discoveryData[$key]['error_type'] = "Wrong Fx Rates";
        } elseif (stripos($cmSync->discoveryData[$key]['log_message'], 'not in Archive or Production') !== false) {
            $cmSync->discoveryData[$key]['error_type'] = "Missing Data";
            $cmSync->discoveryData[$key]['check_sum_3'] = null;
        } elseif (stripos($cmSync->discoveryData[$key]['log_message'], 'manually deleted') !== false) {
            $cmSync->discoveryData[$key]['error_type'] = "Deleted Data";
        }
    }

    if (array_key_exists($key, $commentsArr) === true) {
        $cmSync->discoveryData[$key]['error_type'] = $commentsArr[$key]['error_type'];
        $cmSync->discoveryData[$key]['comments'] = $commentsArr[$key]['comments'];
    }
}
echo "\n";
$timeEnd = microtime(true);
$stage2Time = round(($timeEnd - $timeStart2) / 60, 2);
echo "Stage 2 of discovery completed in ", $stage2Time, " minutes.\n";
echo "Saving log data to file with all Children and all Parent Transactions...\t";
$cmSync->addLogFileEntry(CM_SYNC_TRANSACTION_CHILD, $cmSync->discoveryData);
echo "Completed\n";
echo $cmSync->showMemoryUsage();
echo "Saving log data to file with all Root Grand Parent Transactions...\t";
$cmSync->addLogFileEntry(CM_SYNC_TRANSACTION_ROOT, $cmSync->allRootsData);
echo "Completed\n";
echo $cmSync->showMemoryUsage();
echo "Saving log data to file with all manually deleted Transactions...\t";
$cmSync->addLogFileEntry(CM_SYNC_TRANSACTION_REMOVED, $deletedTransArr);
echo "Completed\n";
echo $cmSync->showMemoryUsage();
if ($cmSync->debugMode === true) {
    $cmSync->arrayToLogFile('db', $cmSync->discoveryData);
    exit();
}
echo "Saving discovery data to database...\t";
$cmSync->cleanStoredRootsDiscovery();
$cmSync->storeReceiptRootsDiscovery($cmSync->discoveryData);
echo "Completed\n";
echo $cmSync->showMemoryUsage();
echo "Root Grand Parent Receipts Discovery process completed successfully.\n";
echo "Latest Children Receipts in Production use: ", $allChildrenArrCount, "\n";
echo "Total Receipts discovered: ", count($cmSync->discoveryData), "\n";
echo "Root Grand Parent Receipts discovered: ", count($cmSync->allRootsData), "\n";
echo "Broken Receipts: ", count($brokenParentsArr), "\n";
echo "Manually deleted Receipts: ", count($deletedTransArr), "\n";
echo "Failed Amount Sum Check #1 results: ", $sumCheck1MismatchCount, "\n";
echo "Failed Amount Sum Check #2 results: ", $sumCheck2MismatchCount, "\n";
echo "Failed Amount Sum Check #3 results: ", $sumCheck3MismatchCount, "\n";
echo "Failed Amount Sum Check #4 results: ", $sumCheck4MismatchCount, "\n";
$timeEnd = microtime(true);
echo "Execution time: [Stage 1 in ", $stage1Time, "] [Step 2 in ", $stage2Time, "] Total: ",
    round(($timeEnd - $timeStart) / 60, 2), " minutes.\n";