514 lines
16 KiB
PHP
514 lines
16 KiB
PHP
<?php
|
|
// phpcs:ignoreFile
|
|
|
|
if (!function_exists('sqlsrv_query')) {
|
|
define('FARMDATA_SQLSRV_STUB', true);
|
|
|
|
function sqlsrv_query($conn, $sql, $params = array(), $options = array())
|
|
{
|
|
return false;
|
|
}
|
|
|
|
function sqlsrv_fetch_array($stmt, $fetchType)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
function sqlsrv_free_stmt($stmt)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
function sqlsrv_connect($serverName, $connectionInfo)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
function sqlsrv_close($conn)
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
|
|
function farmdata_env($key, $fallback = null)
|
|
{
|
|
$value = getenv($key);
|
|
|
|
if ($value === false || $value === null || $value === '') {
|
|
return $fallback;
|
|
}
|
|
|
|
return $value;
|
|
}
|
|
|
|
function farmdata_fetch_column($conn, $sql, $params = array())
|
|
{
|
|
$results = array();
|
|
|
|
if (!function_exists('sqlsrv_query')) {
|
|
return $results;
|
|
}
|
|
|
|
$stmt = sqlsrv_query($conn, $sql, $params);
|
|
|
|
if ($stmt === false) {
|
|
return $results;
|
|
}
|
|
|
|
$fetchNumeric = defined('SQLSRV_FETCH_NUMERIC') ? constant('SQLSRV_FETCH_NUMERIC') : 2;
|
|
|
|
while ($row = sqlsrv_fetch_array($stmt, $fetchNumeric)) {
|
|
if (!isset($row[0])) {
|
|
continue;
|
|
}
|
|
|
|
$value = trim((string) $row[0]);
|
|
|
|
if ($value === '') {
|
|
continue;
|
|
}
|
|
|
|
$results[] = $value;
|
|
}
|
|
|
|
if (function_exists('sqlsrv_free_stmt')) {
|
|
sqlsrv_free_stmt($stmt);
|
|
}
|
|
|
|
return $results;
|
|
}
|
|
|
|
function farmdata_format_number($value, $decimals = 0)
|
|
{
|
|
if (!is_numeric($value)) {
|
|
return '—';
|
|
}
|
|
|
|
return number_format((float) $value, $decimals);
|
|
}
|
|
|
|
function farmdata_h($value)
|
|
{
|
|
return htmlspecialchars((string) $value, ENT_QUOTES, 'UTF-8');
|
|
}
|
|
|
|
$filters = array(
|
|
'grower' => isset($_GET['grower']) ? trim((string) $_GET['grower']) : '',
|
|
'cropday' => isset($_GET['cropday']) ? trim((string) $_GET['cropday']) : '',
|
|
'vehicle' => isset($_GET['vehicle']) ? trim((string) $_GET['vehicle']) : '',
|
|
'tract' => isset($_GET['tract']) ? trim((string) $_GET['tract']) : '',
|
|
'load' => isset($_GET['load']) ? trim((string) $_GET['load']) : '',
|
|
'overload' => isset($_GET['overload']) && $_GET['overload'] === '1',
|
|
);
|
|
|
|
$serverName = farmdata_env('SQLSRV_HOST', 'CBM2K12\\SQLEXPRESS');
|
|
$connectionInfo = array(
|
|
'UID' => farmdata_env('SQLSRV_USERNAME', 'cbmclient'),
|
|
'PWD' => farmdata_env('SQLSRV_PASSWORD', 'ascbm2k'),
|
|
'ReturnDatesAsStrings' => true,
|
|
'CharacterSet' => 'UTF-8',
|
|
'Database' => farmdata_env('SQLSRV_DATABASE', 'SugarCaneScale'),
|
|
);
|
|
|
|
$conn = null;
|
|
$connectionError = null;
|
|
$growerOptions = array();
|
|
$cropDayOptions = array();
|
|
$vehicleSuggestions = array();
|
|
$tractSuggestions = array();
|
|
$loadSuggestions = array();
|
|
$latestCropDay = null;
|
|
$latestCropDayTons = null;
|
|
$overallTons = null;
|
|
$rows = array();
|
|
$resultTotals = array(
|
|
'tons' => 0.0,
|
|
'gross' => 0.0,
|
|
'tare' => 0.0,
|
|
);
|
|
|
|
if (defined('FARMDATA_SQLSRV_STUB') || !function_exists('sqlsrv_connect')) {
|
|
$connectionError = 'The SQL Server driver is not available on this server.';
|
|
} else {
|
|
$conn = @sqlsrv_connect($serverName, $connectionInfo);
|
|
|
|
if ($conn === false) {
|
|
$connectionError = 'Unable to connect to the load data database at this time.';
|
|
} else {
|
|
$growerOptions = farmdata_fetch_column(
|
|
$conn,
|
|
"SELECT DISTINCT AccountName FROM Tract WHERE AccountName IS NOT NULL AND AccountName <> '' ORDER BY AccountName ASC"
|
|
);
|
|
|
|
$cropDayOptions = farmdata_fetch_column(
|
|
$conn,
|
|
"SELECT DISTINCT CropDay FROM LoadData WHERE CropDay IS NOT NULL ORDER BY CropDay DESC"
|
|
);
|
|
|
|
$vehicleSuggestions = farmdata_fetch_column(
|
|
$conn,
|
|
"SELECT DISTINCT TOP 75 VehicleId_Fk FROM LoadData WHERE VehicleId_Fk IS NOT NULL AND VehicleId_Fk <> '' ORDER BY VehicleId_Fk ASC"
|
|
);
|
|
|
|
$tractSuggestions = farmdata_fetch_column(
|
|
$conn,
|
|
"SELECT DISTINCT TOP 75 TractId_Fk FROM LoadData WHERE TractId_Fk IS NOT NULL AND TractId_Fk <> '' ORDER BY TractId_Fk ASC"
|
|
);
|
|
|
|
$loadSuggestions = farmdata_fetch_column(
|
|
$conn,
|
|
"SELECT DISTINCT TOP 50 LoadId_Pk FROM LoadData WHERE LoadId_Pk IS NOT NULL ORDER BY LoadId_Pk DESC"
|
|
);
|
|
|
|
$latestStmt = sqlsrv_query(
|
|
$conn,
|
|
'SELECT TOP 1 CropDay, SUM(Tons) AS total_tons FROM LoadData WHERE CropDay IS NOT NULL GROUP BY CropDay ORDER BY CropDay DESC'
|
|
);
|
|
|
|
if ($latestStmt !== false) {
|
|
$fetchAssoc = defined('SQLSRV_FETCH_ASSOC') ? constant('SQLSRV_FETCH_ASSOC') : 2;
|
|
$latestRow = sqlsrv_fetch_array($latestStmt, $fetchAssoc);
|
|
|
|
if ($latestRow) {
|
|
$latestCropDay = $latestRow['CropDay'];
|
|
$latestCropDayTons = isset($latestRow['total_tons']) ? (float) $latestRow['total_tons'] : null;
|
|
}
|
|
|
|
if (function_exists('sqlsrv_free_stmt')) {
|
|
sqlsrv_free_stmt($latestStmt);
|
|
}
|
|
}
|
|
|
|
$overallStmt = sqlsrv_query(
|
|
$conn,
|
|
'SELECT SUM(Tons) AS total_tons FROM LoadData'
|
|
);
|
|
|
|
if ($overallStmt !== false) {
|
|
$fetchAssoc = isset($fetchAssoc) ? $fetchAssoc : (defined('SQLSRV_FETCH_ASSOC') ? constant('SQLSRV_FETCH_ASSOC') : 2);
|
|
$overallRow = sqlsrv_fetch_array($overallStmt, $fetchAssoc);
|
|
|
|
if ($overallRow && isset($overallRow['total_tons'])) {
|
|
$overallTons = (float) $overallRow['total_tons'];
|
|
}
|
|
|
|
if (function_exists('sqlsrv_free_stmt')) {
|
|
sqlsrv_free_stmt($overallStmt);
|
|
}
|
|
}
|
|
|
|
$query = "SELECT TOP 500
|
|
ld.LoadId_Pk,
|
|
ld.CropDay,
|
|
ld.VehicleId_Fk,
|
|
ld.TractId_Fk,
|
|
ld.TareWt,
|
|
ld.GrossWt,
|
|
ld.Tons,
|
|
ld.FarmerId_Fk,
|
|
CONVERT(varchar(20), ld.DateOut, 100) AS TimeOutFormatted,
|
|
ld.Parked,
|
|
t.AccountName
|
|
FROM LoadData ld
|
|
LEFT JOIN (
|
|
SELECT AccountId_Pk, MAX(AccountName) AS AccountName
|
|
FROM Tract
|
|
WHERE AccountName IS NOT NULL AND AccountName <> ''
|
|
GROUP BY AccountId_Pk
|
|
) t ON ld.FarmerId_Fk = t.AccountId_Pk";
|
|
|
|
$conditions = array();
|
|
$params = array();
|
|
|
|
if ($filters['grower'] !== '') {
|
|
$conditions[] = 't.AccountName = ?';
|
|
$params[] = $filters['grower'];
|
|
}
|
|
|
|
if ($filters['cropday'] !== '') {
|
|
$conditions[] = 'ld.CropDay = ?';
|
|
$params[] = $filters['cropday'];
|
|
}
|
|
|
|
if ($filters['vehicle'] !== '') {
|
|
$conditions[] = 'ld.VehicleId_Fk LIKE ?';
|
|
$params[] = $filters['vehicle'] . '%';
|
|
}
|
|
|
|
if ($filters['tract'] !== '') {
|
|
$conditions[] = 'ld.TractId_Fk LIKE ?';
|
|
$params[] = $filters['tract'] . '%';
|
|
}
|
|
|
|
if ($filters['load'] !== '') {
|
|
$conditions[] = 'ld.LoadId_Pk = ?';
|
|
$params[] = (int) $filters['load'];
|
|
}
|
|
|
|
if ($filters['overload']) {
|
|
$conditions[] = 'ld.GrossWt >= ?';
|
|
$params[] = 100000;
|
|
}
|
|
|
|
if (!empty($conditions)) {
|
|
$query .= ' WHERE ' . implode(' AND ', $conditions);
|
|
}
|
|
|
|
$query .= ' ORDER BY ld.DateOut DESC, ld.LoadId_Pk DESC';
|
|
|
|
$cursorType = defined('SQLSRV_CURSOR_KEYSET') ? constant('SQLSRV_CURSOR_KEYSET') : 1;
|
|
$loadStmt = sqlsrv_query($conn, $query, $params, array('Scrollable' => $cursorType));
|
|
|
|
if ($loadStmt === false) {
|
|
$connectionError = 'Unable to retrieve load data right now.';
|
|
} else {
|
|
$fetchAssoc = defined('SQLSRV_FETCH_ASSOC') ? constant('SQLSRV_FETCH_ASSOC') : 2;
|
|
while ($row = sqlsrv_fetch_array($loadStmt, $fetchAssoc)) {
|
|
$tons = isset($row['Tons']) && is_numeric($row['Tons']) ? (float) $row['Tons'] : null;
|
|
$tare = isset($row['TareWt']) && is_numeric($row['TareWt']) ? (float) $row['TareWt'] : null;
|
|
$gross = isset($row['GrossWt']) && is_numeric($row['GrossWt']) ? (float) $row['GrossWt'] : null;
|
|
$parkedRaw = isset($row['Parked']) ? trim((string) $row['Parked']) : '';
|
|
$parked = in_array(strtoupper($parkedRaw), array('1', 'Y', 'YES', 'TRUE'), true);
|
|
|
|
if ($tons !== null) {
|
|
$resultTotals['tons'] += $tons;
|
|
}
|
|
|
|
if ($tare !== null) {
|
|
$resultTotals['tare'] += $tare;
|
|
}
|
|
|
|
if ($gross !== null) {
|
|
$resultTotals['gross'] += $gross;
|
|
}
|
|
|
|
$rows[] = array(
|
|
'load_id' => isset($row['LoadId_Pk']) ? (int) $row['LoadId_Pk'] : null,
|
|
'crop_day' => isset($row['CropDay']) ? $row['CropDay'] : '',
|
|
'vehicle' => isset($row['VehicleId_Fk']) ? trim((string) $row['VehicleId_Fk']) : '',
|
|
'tract' => isset($row['TractId_Fk']) ? trim((string) $row['TractId_Fk']) : '',
|
|
'grower' => isset($row['AccountName']) ? trim((string) $row['AccountName']) : '',
|
|
'tons' => $tons,
|
|
'tare' => $tare,
|
|
'gross' => $gross,
|
|
'time_out' => isset($row['TimeOutFormatted']) ? trim((string) $row['TimeOutFormatted']) : '',
|
|
'parked' => $parked,
|
|
);
|
|
}
|
|
|
|
if (function_exists('sqlsrv_free_stmt')) {
|
|
sqlsrv_free_stmt($loadStmt);
|
|
}
|
|
}
|
|
|
|
if (function_exists('sqlsrv_close')) {
|
|
sqlsrv_close($conn);
|
|
}
|
|
}
|
|
}
|
|
|
|
$resultCount = count($rows);
|
|
|
|
$pageTitle = 'Load Data Explorer';
|
|
$metaDescription = 'Search LASUCA load data by grower, crop day, vehicle, or tract.';
|
|
$activeNav = 'production';
|
|
$extraStyles = array('/new/css/farmdata.css');
|
|
$extraScripts = array('/new/js/scripts.js');
|
|
$rootDir = __DIR__;
|
|
require $rootDir . '/../inc/theme-header.php';
|
|
?>
|
|
|
|
<main>
|
|
<header class="hero hero-sub farmdata-hero">
|
|
<div class="container">
|
|
<span class="badge">Live load data</span>
|
|
<h1 class="mt-3">Search cane deliveries and scale tickets.</h1>
|
|
<p class="lead">
|
|
Filter the latest loads by grower, crop day, vehicle, or tract. Results update instantly and include live
|
|
tonnage, tare, and gross weight totals so you can track activity at a glance.
|
|
</p>
|
|
</div>
|
|
</header>
|
|
|
|
<section class="page-section py-5">
|
|
<div class="container">
|
|
<?php if ($connectionError !== null): ?>
|
|
<div class="alert alert-warning" role="alert">
|
|
<?php echo farmdata_h($connectionError); ?>
|
|
</div>
|
|
<?php endif; ?>
|
|
|
|
<div class="farmdata-search-card">
|
|
<form method="get" action="index.php" class="row g-4 align-items-end">
|
|
<div class="col-12 col-md-6 col-xl-3">
|
|
<label for="grower" class="form-label">Grower</label>
|
|
<select class="form-select" id="grower" name="grower">
|
|
<option value="">All growers</option>
|
|
<?php foreach ($growerOptions as $option): ?>
|
|
<option value="<?php echo farmdata_h($option); ?>"<?php echo $filters['grower'] === $option ? ' selected' : ''; ?>>
|
|
<?php echo farmdata_h($option); ?>
|
|
</option>
|
|
<?php endforeach; ?>
|
|
</select>
|
|
</div>
|
|
|
|
<div class="col-12 col-md-6 col-xl-3">
|
|
<label for="cropday" class="form-label">Crop day</label>
|
|
<select class="form-select" id="cropday" name="cropday">
|
|
<option value="">All crop days</option>
|
|
<?php foreach ($cropDayOptions as $option): ?>
|
|
<option value="<?php echo farmdata_h($option); ?>"<?php echo $filters['cropday'] === $option ? ' selected' : ''; ?>>
|
|
<?php echo farmdata_h($option); ?>
|
|
</option>
|
|
<?php endforeach; ?>
|
|
</select>
|
|
</div>
|
|
|
|
<div class="col-12 col-md-6 col-xl-3">
|
|
<label for="vehicle" class="form-label">Vehicle</label>
|
|
<input
|
|
type="text"
|
|
class="form-control"
|
|
id="vehicle"
|
|
name="vehicle"
|
|
list="vehicleOptions"
|
|
value="<?php echo farmdata_h($filters['vehicle']); ?>"
|
|
placeholder="e.g. V9901"
|
|
/>
|
|
<datalist id="vehicleOptions">
|
|
<?php foreach ($vehicleSuggestions as $option): ?>
|
|
<option value="<?php echo farmdata_h($option); ?>"></option>
|
|
<?php endforeach; ?>
|
|
</datalist>
|
|
</div>
|
|
|
|
<div class="col-12 col-md-6 col-xl-3">
|
|
<label for="tract" class="form-label">Tract</label>
|
|
<input
|
|
type="text"
|
|
class="form-control"
|
|
id="tract"
|
|
name="tract"
|
|
list="tractOptions"
|
|
value="<?php echo farmdata_h($filters['tract']); ?>"
|
|
placeholder="Tract ID"
|
|
/>
|
|
<datalist id="tractOptions">
|
|
<?php foreach ($tractSuggestions as $option): ?>
|
|
<option value="<?php echo farmdata_h($option); ?>"></option>
|
|
<?php endforeach; ?>
|
|
</datalist>
|
|
</div>
|
|
|
|
<div class="col-12 col-md-6 col-xl-3">
|
|
<label for="load" class="form-label">Load #</label>
|
|
<input
|
|
type="number"
|
|
class="form-control"
|
|
id="load"
|
|
name="load"
|
|
list="loadOptions"
|
|
value="<?php echo farmdata_h($filters['load']); ?>"
|
|
placeholder="Exact load number"
|
|
min="1"
|
|
/>
|
|
<datalist id="loadOptions">
|
|
<?php foreach ($loadSuggestions as $option): ?>
|
|
<option value="<?php echo farmdata_h($option); ?>"></option>
|
|
<?php endforeach; ?>
|
|
</datalist>
|
|
</div>
|
|
|
|
<div class="col-12 col-md-6 col-xl-3">
|
|
<div class="form-check">
|
|
<input class="form-check-input" type="checkbox" value="1" id="overload" name="overload"<?php echo $filters['overload'] ? ' checked' : ''; ?> />
|
|
<label class="form-check-label" for="overload">Show overloads (gross ≥ 100,000)</label>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="col-12 col-md-6 col-xl-3 ms-auto">
|
|
<button type="submit" class="btn btn-success w-100">Search loads</button>
|
|
</div>
|
|
|
|
<div class="col-12 col-md-6 col-xl-3">
|
|
<a class="btn btn-outline-secondary w-100" href="/farmdata/index.php">Reset filters</a>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
|
|
<div class="farmdata-metrics">
|
|
<div class="farmdata-metric">
|
|
<h4>Loads returned</h4>
|
|
<p><?php echo farmdata_h(number_format($resultCount)); ?> matching records</p>
|
|
</div>
|
|
<div class="farmdata-metric">
|
|
<h4>Result tons</h4>
|
|
<p><?php echo farmdata_h(farmdata_format_number($resultTotals['tons'], 2)); ?> total tons</p>
|
|
</div>
|
|
<div class="farmdata-metric">
|
|
<h4>Latest crop day</h4>
|
|
<p>
|
|
<?php if ($latestCropDay !== null): ?>
|
|
Day <?php echo farmdata_h($latestCropDay); ?> · <?php echo farmdata_h(farmdata_format_number($latestCropDayTons, 2)); ?> tons
|
|
<?php else: ?>
|
|
Not available
|
|
<?php endif; ?>
|
|
</p>
|
|
</div>
|
|
<div class="farmdata-metric">
|
|
<h4>All-time tons</h4>
|
|
<p><?php echo farmdata_h(farmdata_format_number($overallTons, 2)); ?> tons processed</p>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="farmdata-results-card">
|
|
<?php if ($resultCount === 0): ?>
|
|
<p class="mb-0 text-muted">No loads match the filters you selected. Try adjusting the search criteria.</p>
|
|
<?php else: ?>
|
|
<div class="farmdata-results-summary">
|
|
<span>Gross: <?php echo farmdata_h(farmdata_format_number($resultTotals['gross'], 0)); ?></span>
|
|
<span>Tare: <?php echo farmdata_h(farmdata_format_number($resultTotals['tare'], 0)); ?></span>
|
|
<span>Tons: <?php echo farmdata_h(farmdata_format_number($resultTotals['tons'], 2)); ?></span>
|
|
</div>
|
|
<div class="table-responsive">
|
|
<table class="table table-hover align-middle mb-0">
|
|
<thead>
|
|
<tr>
|
|
<th scope="col">Load #</th>
|
|
<th scope="col">Crop day</th>
|
|
<th scope="col">Grower</th>
|
|
<th scope="col">Tract</th>
|
|
<th scope="col">Vehicle</th>
|
|
<th scope="col">Gross</th>
|
|
<th scope="col">Tare</th>
|
|
<th scope="col">Tons</th>
|
|
<th scope="col">Time out</th>
|
|
<th scope="col">Parked</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<?php foreach ($rows as $row): ?>
|
|
<tr>
|
|
<td><?php echo farmdata_h($row['load_id']); ?></td>
|
|
<td><?php echo farmdata_h($row['crop_day']); ?></td>
|
|
<td><?php echo $row['grower'] !== '' ? farmdata_h($row['grower']) : '—'; ?></td>
|
|
<td><?php echo $row['tract'] !== '' ? farmdata_h($row['tract']) : '—'; ?></td>
|
|
<td><?php echo $row['vehicle'] !== '' ? farmdata_h($row['vehicle']) : '—'; ?></td>
|
|
<td><?php echo farmdata_h(farmdata_format_number($row['gross'], 0)); ?></td>
|
|
<td><?php echo farmdata_h(farmdata_format_number($row['tare'], 0)); ?></td>
|
|
<td><?php echo farmdata_h(farmdata_format_number($row['tons'], 2)); ?></td>
|
|
<td><?php echo $row['time_out'] !== '' ? farmdata_h($row['time_out']) : '—'; ?></td>
|
|
<td><?php echo $row['parked'] ? '<span class="badge bg-warning text-dark">Yes</span>' : '<span class="badge bg-success">No</span>'; ?></td>
|
|
</tr>
|
|
<?php endforeach; ?>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
<?php endif; ?>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
</main>
|
|
|
|
<?php require $rootDir . '/../inc/theme-footer.php'; ?>
|