asd
This commit is contained in:
commit
3e4a056b14
67 files changed
+13926
No files matched your search
@@ -0,0 +1,70 @@
|
||||
<?php
|
||||
// Validates the server-side engine (includes/engine.php) against the values
|
||||
// recalculated by Microsoft Excel (tests/excel-fixtures.json), using the
|
||||
// parameters stored in MySQL. Same checks and tolerances as tests/validate.js.
|
||||
// php tests/validate_engine.php
|
||||
declare(strict_types=1);
|
||||
|
||||
if (PHP_SAPI !== 'cli') {
|
||||
http_response_code(404);
|
||||
exit;
|
||||
}
|
||||
require __DIR__ . '/../includes/params.php';
|
||||
require __DIR__ . '/../includes/engine.php';
|
||||
|
||||
$fixtures = json_decode(preg_replace('/^\xEF\xBB\xBF/', '', (string)file_get_contents(__DIR__ . '/excel-fixtures.json')), true);
|
||||
$params = load_params_db();
|
||||
|
||||
$rateFields = ['equiv', 'rateGiro', 'rateSimanja', 'rateSimpeda', 'rateDeposito', 'totalRateGiro', 'totalRateSimanja', 'totalRateSimpeda', 'shareNasabah', 'shareBank'];
|
||||
|
||||
function engine_view(array $r): array
|
||||
{
|
||||
$by = array_column($r['comparison'], null, 'key');
|
||||
$ok = $r['eligible'];
|
||||
$pr = $r['products'];
|
||||
return [
|
||||
'cashbackGross' => $ok ? $r['cashback']['gross'] : null, 'cashbackNet' => $ok ? $r['cashback']['net'] : null,
|
||||
'giroNet' => $pr['giro']['bungaNet'], 'simanjaNet' => $pr['simanja']['bungaNet'], 'simpedaNet' => $pr['simpeda']['bungaNet'],
|
||||
'depositoNet' => $r['deposito']['net'], 'depositoGross' => $r['deposito']['gross'], 'rateDeposito' => $r['deposito']['rate'],
|
||||
'totalGiro' => $ok ? $by['giro']['total'] : null, 'totalSimanja' => $ok ? $by['simanja']['total'] : null, 'totalSimpeda' => $ok ? $by['simpeda']['total'] : null,
|
||||
'totalDeposito' => $r['deposito']['net'],
|
||||
'rateGiro' => $pr['giro']['rate'], 'rateSimanja' => $pr['simanja']['rate'], 'rateSimpeda' => $pr['simpeda']['rate'],
|
||||
'equiv' => $ok ? $r['cashback']['equiv'] : null,
|
||||
'totalRateGiro' => $ok ? $by['giro']['totalRate'] : null, 'totalRateSimanja' => $ok ? $by['simanja']['totalRate'] : null, 'totalRateSimpeda' => $ok ? $by['simpeda']['totalRate'] : null,
|
||||
'penaltyRefund' => $ok ? $r['penalty']['refund'] : null, 'penaltyTax' => $ok ? $r['penalty']['tax'] : null,
|
||||
'penaltyFee' => $ok ? $r['penalty']['fee'] : null, 'penaltyTotal' => $ok ? $r['penalty']['total'] : null,
|
||||
'shareNasabah' => $ok ? $r['share'] : null, 'shareBank' => $ok ? $r['shareBank'] : null,
|
||||
'income' => $r['fund']['income'], 'puabIncome' => $r['fund']['puabIncome'], 'creditIncome' => $r['fund']['creditIncome'],
|
||||
'spreadSimanja' => $pr['simanja']['spread'], 'spreadSimpeda' => $pr['simpeda']['spread'], 'spreadGiro' => $pr['giro']['spread'],
|
||||
];
|
||||
}
|
||||
|
||||
$checks = 0;
|
||||
$failures = [];
|
||||
foreach ($fixtures['cases'] as $c) {
|
||||
$got = engine_view(engine_calculate($params, (float)$c['nominal'], (int)$c['tenor'], 'perorangan'));
|
||||
foreach ($c as $field => $expected) {
|
||||
if ($field === 'nominal' || $field === 'tenor' || !array_key_exists($field, $got)) {
|
||||
continue;
|
||||
}
|
||||
$checks++;
|
||||
$actual = $got[$field];
|
||||
if ($expected === null) {
|
||||
$pass = $actual === null;
|
||||
} elseif ($actual === null) {
|
||||
$pass = false;
|
||||
} elseif (in_array($field, $rateFields, true)) {
|
||||
$pass = abs($actual - $expected) < 1e-9;
|
||||
} else {
|
||||
$pass = round($actual) == round($expected) && abs($actual - $expected) < 0.01;
|
||||
}
|
||||
if (!$pass) {
|
||||
$failures[] = sprintf('%s / %d bln / %s: excel=%s app=%s', $c['nominal'], $c['tenor'], $field, var_export($expected, true), var_export($actual, true));
|
||||
}
|
||||
}
|
||||
}
|
||||
printf("PHP engine: %d/%d checks match Excel over %d cases\n", $checks - count($failures), $checks, count($fixtures['cases']));
|
||||
foreach (array_slice($failures, 0, 20) as $f) {
|
||||
echo " FAIL $f\n";
|
||||
}
|
||||
exit($failures ? 1 : 0);
|
||||
Reference in new issue
Block a user