'pdo_pgsql', 'host' => 'localhost', 'port' => 5432, 'dbname' => 'inventory', 'user' => 'ferme_user', 'password' => 'fermerecette', ]); echo "=== CUSTOM FIELDS HEALTH CHECK ===\n\n"; // 1. Orphaned CFs (should be 0) $orphanedCfs = $conn->fetchOne('SELECT COUNT(*) FROM custom_fields WHERE typecomposantid IS NULL AND typepieceid IS NULL AND typeproductid IS NULL'); echo sprintf("1. Orphaned CF definitions: %d %s\n", $orphanedCfs, 0 == $orphanedCfs ? '[OK]' : '[PROBLEM]'); // 2. Orphaned CFValues (pointing to orphaned CFs) $orphanedCfvs = $conn->fetchOne(' SELECT COUNT(*) FROM custom_field_values cfv JOIN custom_fields cf ON cf.id = cfv.customfieldid WHERE cf.typecomposantid IS NULL AND cf.typepieceid IS NULL AND cf.typeproductid IS NULL '); echo sprintf("2. Orphaned CF values: %d %s\n", $orphanedCfvs, 0 == $orphanedCfvs ? '[OK]' : '[PROBLEM]'); // 3. Duplicate CFValues (same entity + same field name) $duplicatePieces = $conn->fetchOne(" SELECT COUNT(*) FROM ( SELECT cfv.pieceid, cf.name, COUNT(*) as cnt FROM custom_field_values cfv JOIN custom_fields cf ON cf.id = cfv.customfieldid WHERE cfv.pieceid IS NOT NULL GROUP BY cfv.pieceid, cf.name HAVING COUNT(*) > 1 ) t "); $duplicateComposants = $conn->fetchOne(" SELECT COUNT(*) FROM ( SELECT cfv.composantid, cf.name, COUNT(*) as cnt FROM custom_field_values cfv JOIN custom_fields cf ON cf.id = cfv.customfieldid WHERE cfv.composantid IS NOT NULL GROUP BY cfv.composantid, cf.name HAVING COUNT(*) > 1 ) t "); $totalDuplicates = $duplicatePieces + $duplicateComposants; echo sprintf("3. Duplicate CF values: %d %s\n", $totalDuplicates, 0 == $totalDuplicates ? '[OK]' : '[PROBLEM]'); // 4. Spot check known pieces echo "\n--- Spot checks ---\n"; $checks = [ ['Arbre du palier pied E1', 'cl3d978dd4b071daff8fb185f7', 'pieceid', 'diamètre', '50'], ['Arbre du palier tête E1', 'cmkr0qjw5004s1eq6pen63x7j', 'pieceid', 'diamètre', '70'], ['Cage écureuil pied E1', 'clbe710810fd7ccd09811957b3', 'composantid', 'Diamètre', ''], ]; foreach ($checks as [$name, $id, $fk, $fieldName, $expectedValue]) { $row = $conn->fetchAssociative( "SELECT cfv.value FROM custom_field_values cfv JOIN custom_fields cf ON cf.id = cfv.customfieldid WHERE cfv.{$fk} = ? AND cf.name = ?", [$id, $fieldName] ); $value = $row ? $row['value'] : '(NOT FOUND)'; $ok = '' === $expectedValue ? ('' !== $value && null !== $value) : ($value === $expectedValue); echo sprintf(" %s → %s = '%s' %s\n", $name, $fieldName, $value, $ok ? '[OK]' : '[CHECK]'); } // 5. Summary of empty vs filled values echo "\n--- Value fill rates ---\n"; $stats = $conn->fetchAllAssociative(" SELECT CASE WHEN cfv.pieceid IS NOT NULL THEN 'piece' WHEN cfv.composantid IS NOT NULL THEN 'composant' WHEN cfv.productid IS NOT NULL THEN 'product' ELSE 'unknown' END as entity_type, COUNT(*) as total, COUNT(*) FILTER (WHERE cfv.value != '' AND cfv.value IS NOT NULL) as filled, COUNT(*) FILTER (WHERE cfv.value = '' OR cfv.value IS NULL) as empty FROM custom_field_values cfv GROUP BY entity_type ORDER BY entity_type "); foreach ($stats as $s) { $pct = $s['total'] > 0 ? round(100 * $s['filled'] / $s['total']) : 0; echo sprintf(" %s: %d/%d filled (%d%%)\n", $s['entity_type'], $s['filled'], $s['total'], $pct); } echo "\n=== DONE ===\n";