&rand= */ require_once __DIR__ . '/../../../config/database.php'; require_once __DIR__ . '/../../../lib/auth.php'; require_once __DIR__ . '/../../../lib/soil_calculations.php'; if (session_status() === PHP_SESSION_NONE) { session_start(); } requireLogin(); $pdo = getDBConnection(); $userId = getCurrentUserId(); $recordId = (int) ($_GET['rid'] ?? 0); $randId = trim( $_GET['rand'] ?? ''); $row = null; $spec = []; $savedComments = []; $today = date('jS F Y'); if ($recordId > 0 && $randId !== '') { $stmt = $pdo->prepare('SELECT * FROM soil_records WHERE id = ? AND rand = ? LIMIT 1'); $stmt->execute([$recordId, $randId]); $row = $stmt->fetch(PDO::FETCH_ASSOC); if ($row) { // Load spec ranges for this soil type if (!empty($row['soil_type'])) { $stmtSpec = $pdo->prepare('SELECT * FROM soil_specifications WHERE soil_type = ? LIMIT 1'); $stmtSpec->execute([$row['soil_type']]); $spec = $stmtSpec->fetch(PDO::FETCH_ASSOC) ?: []; } // Load saved report comments (JSON blob) $stmtRpt = $pdo->prepare( 'SELECT comment FROM reports WHERE record_id = ? AND modx_user_id = ? ORDER BY id DESC LIMIT 1' ); $stmtRpt->execute([$recordId, $userId]); $savedRow = $stmtRpt->fetchColumn(); if ($savedRow) { $decoded = json_decode($savedRow, true); if (is_array($decoded)) { $savedComments = $decoded; } } } } // ── Five-year plan ──────────────────────────────────────────────────────────── $planElements = [ ['Calcium', 'BS_ca_ppm', 'ca_ppm_min', 'ca_ppm_max', 'kg/ha'], ['Magnesium', 'BS_mg_ppm', 'mg_ppm_min', 'mg_ppm_max', 'kg/ha'], ['Potassium', 'BS_k_ppm', 'k_ppm_min', 'k_ppm_max', 'kg/ha'], ['Sodium', 'BS_na_ppm', 'na_ppm_min', 'na_ppm_max', 'kg/ha'], ['Phosphate', 'p_colwell', '', '', 'kg/ha'], ['Sulfur', 's_morgan', '', '', 'kg/ha'], ['Boron', 'b_cacl2', '', '', 'kg/ha'], ['Manganese', 'mn_dtpa', '', '', 'kg/ha'], ['Zinc', 'zn_dtpa', '', '', 'kg/ha'], ['Copper', 'cu_dtpa', '', '', 'kg/ha'], ]; $acHa = 2.4710559990832394739; function calcDeficitPdf(array $row, array $spec, string $col, string $minCol, string $maxCol): float { global $acHa; $value = (float)($row[$col] ?? 0); $maxVal = $maxCol !== '' ? (float)($row[$maxCol] ?? 0) : (float)($spec[$col] ?? 0); $deficit = ($maxVal - $value) * $acHa; return $deficit > 0 ? round($deficit, 2) : 0.0; } $h = fn($v) => htmlspecialchars((string)($v ?? ''), ENT_QUOTES, 'UTF-8'); // Format saved text: preserve newlines as paragraphs function formatReportText(string $text): string { if (trim($text) === '') return '

No content saved.

'; $paragraphs = preg_split('/\n{2,}/', trim($text)); $out = ''; foreach ($paragraphs as $para) { $para = trim($para); if ($para === '') continue; $out .= '

' . nl2br(htmlspecialchars($para, ENT_QUOTES, 'UTF-8')) . '

'; } return $out ?: '

No content saved.

'; } ?> Soil Analysis Report | Crop Monitor
Record not found or access denied.
Crop Monitor
Soil Analysis Report
CLIENT: SAMPLE ID:
ADDRESS: DATE SAMPLED:
LAB NUMBER:
CROP:
SOIL TYPE:
← Back to Report

Total kilograms per hectare of each element needed to balance soil
Ideal Soil Balancing Program — 5-Year Plan (kg/ha per year)
0 ? round($total / 5, 2) : 0; ?>
Element Total Deficit Year
0 ? $total . ' ' . $unit : '✓ Adequate' ?> 0 ? $perYear . ' ' . $unit : '—' ?>
Overview
AI Soil Interpretation
Microbial Program

Any recommendations provided by Crop Monitor are advice only. We are not paid consultants and accept no responsibility for any of our suggestions. No control can be exercised over storage, handling, mixing, application, or use, or over weather, plant or soil conditions before, during or after application — all of which may affect the performance of our program. No responsibility for, or liability for, any failure in performance, losses, damage or injuries consequential or otherwise arising from such storage, mixing, application or use will be accepted under any circumstances whatsoever. The buyer assumes all responsibility for the use of any of our products.