add all files

This commit is contained in:
Rucus
2026-02-17 09:29:34 -06:00
parent b8c8d67c67
commit 782d203799
21925 changed files with 2433086 additions and 0 deletions

View File

@@ -0,0 +1,546 @@
<?php // phpcs:ignoreFile
/**
* Mill Data Comparison - Compare categories across mills
*/
require __DIR__ . '/../session.php';
require __DIR__ . '/../userAccess.php';
require __DIR__ . '/../includes/millnames.php';
// ============================================================================
// Database Configuration
// ============================================================================
$config = [
'server' => '192.168.0.16',
'database' => 'lasucaai',
'username' => 'lasucaai',
'password' => 'is413#dfslw',
];
// ============================================================================
// Database Connection
// ============================================================================
function getCompareConnection($config) {
$connectionOptions = [
"Database" => $config['database'],
"Uid" => $config['username'],
"PWD" => $config['password'],
"TrustServerCertificate" => true,
"Encrypt" => false,
];
$conn = sqlsrv_connect($config['server'], $connectionOptions);
return $conn ?: null;
}
// ============================================================================
// Data Queries
// ============================================================================
function getCompareSourceFiles($conn) {
$sql = "SELECT DISTINCT SourceFileName,
MIN(BeginningDate) as BeginningDate,
MAX(EndingDate) as EndingDate,
MAX(ProcessedAt) as ProcessedAt
FROM dbo.MillDataReports
GROUP BY SourceFileName
ORDER BY MAX(ProcessedAt) DESC";
$stmt = sqlsrv_query($conn, $sql);
$files = [];
if ($stmt) {
while ($row = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC)) {
$files[] = $row;
}
}
return $files;
}
function getCompareCategories($conn, $sourceFileName = null) {
// Get all categories - simpler query that matches working pattern
$sql = "SELECT DISTINCT Category FROM dbo.MillDataMetrics WHERE Category IS NOT NULL ORDER BY Category";
$stmt = sqlsrv_query($conn, $sql);
$categories = [];
if ($stmt) {
while ($row = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC)) {
$categories[] = $row['Category'];
}
}
return $categories;
}
function getMillsForCompare($conn, $sourceFileName) {
$sql = "SELECT ReportId, MillName
FROM dbo.MillDataReports
WHERE SourceFileName = ?
ORDER BY MillName";
$stmt = sqlsrv_query($conn, $sql, [$sourceFileName]);
$mills = [];
if ($stmt) {
while ($row = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC)) {
$mills[] = $row;
}
}
return $mills;
}
function getComparisonData($conn, $sourceFileName, $category) {
// Get all metrics for this category across all mills in this file
$sql = "SELECT r.MillName, r.ReportId, m.ItemNumber, m.MetricName,
m.RunValue, m.RunValueNumeric, m.ToDateValue, m.ToDateValueNumeric
FROM dbo.MillDataMetrics m
JOIN dbo.MillDataReports r ON m.ReportId = r.ReportId
WHERE r.SourceFileName = ? AND m.Category = ?
ORDER BY m.ItemNumber, m.MetricName, r.MillName";
$stmt = sqlsrv_query($conn, $sql, [$sourceFileName, $category]);
$data = [];
if ($stmt) {
while ($row = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC)) {
$data[] = $row;
}
}
return $data;
}
function formatCompareDate($date) {
if ($date instanceof DateTime) {
return $date->format('m/d/Y');
}
return $date ?? '-';
}
// ============================================================================
// Main Logic
// ============================================================================
$conn = getCompareConnection($config);
$connectionError = $conn === null;
$sourceFiles = [];
$categories = [];
$mills = [];
$comparisonData = [];
$pivotedData = [];
$millNameLookup = [];
$selectedFile = isset($_GET['file']) ? trim($_GET['file']) : '';
$selectedCategory = isset($_GET['category']) ? trim($_GET['category']) : '';
if (!$connectionError) {
// Load mill name mappings
$millNameLookup = getMillNames($conn);
$sourceFiles = getCompareSourceFiles($conn);
$categories = getCompareCategories($conn);
// Default to first file
if (empty($selectedFile) && !empty($sourceFiles)) {
$selectedFile = $sourceFiles[0]['SourceFileName'];
}
if (!empty($selectedFile)) {
$mills = getMillsForCompare($conn, $selectedFile);
// Default to first category
if (empty($selectedCategory) && !empty($categories)) {
$selectedCategory = $categories[0];
}
if (!empty($selectedCategory)) {
$comparisonData = getComparisonData($conn, $selectedFile, $selectedCategory);
// Pivot data: group by metric, columns are mills
foreach ($comparisonData as $row) {
$metricKey = $row['ItemNumber'] . '|' . $row['MetricName'];
if (!isset($pivotedData[$metricKey])) {
$pivotedData[$metricKey] = [
'ItemNumber' => $row['ItemNumber'],
'MetricName' => $row['MetricName'],
'mills' => []
];
}
$pivotedData[$metricKey]['mills'][$row['MillName']] = [
'RunValue' => $row['RunValue'],
'RunValueNumeric' => $row['RunValueNumeric'],
'ToDateValue' => $row['ToDateValue'],
'ToDateValueNumeric' => $row['ToDateValueNumeric']
];
}
}
}
sqlsrv_close($conn);
}
// Get unique mill codes for column headers (raw codes used as data keys)
$millCodes = [];
foreach ($mills as $m) {
$millCodes[] = $m['MillName'];
}
// Build display names map for headers
$millDisplayNames = [];
foreach ($millCodes as $code) {
$millDisplayNames[$code] = getMillDisplayName($millNameLookup, $code);
}
// ============================================================================
// Page Layout
// ============================================================================
$pageTitle = 'Mill Comparison';
$pageSubtitle = 'Compare metrics across mills';
$pageDescription = 'Side-by-side comparison of mill production data.';
$layoutWithoutSidebar = true;
$layoutReturnUrl = 'milldata.php';
$layoutReturnLabel = 'Back to Mill Data';
$assetBasePath = '../';
require __DIR__ . '/../includes/layout/header.php';
?>
<style>
.compare-controls {
display: flex;
gap: 1rem;
margin-bottom: 1.5rem;
flex-wrap: wrap;
align-items: flex-end;
}
.compare-control {
display: flex;
flex-direction: column;
gap: 0.3rem;
}
.compare-control label {
font-size: 0.8rem;
color: var(--text-muted);
text-transform: uppercase;
letter-spacing: 0.5px;
}
.compare-control select {
padding: 0.6rem 1rem;
border: 1px solid var(--border);
border-radius: 6px;
font-size: 0.9rem;
background: var(--surface);
color: var(--text);
min-width: 200px;
}
.compare-table-container {
background: var(--surface);
border-radius: 8px;
border: 1px solid var(--border);
overflow-x: auto;
max-height: 600px;
overflow-y: auto;
}
.compare-table {
width: 100%;
border-collapse: separate;
border-spacing: 0;
font-size: 0.85rem;
}
.compare-table th,
.compare-table td {
padding: 0.5rem 0.6rem;
border-bottom: 1px solid var(--border);
}
.compare-table th {
background: var(--surface-alt);
text-align: left;
font-weight: 600;
color: var(--text-muted);
border-bottom: 2px solid var(--border);
position: sticky;
top: 0;
white-space: nowrap;
z-index: 20;
}
/* Sticky first two columns */
.compare-table th.sticky-col,
.compare-table td.sticky-col {
position: sticky;
background: var(--surface);
z-index: 10;
}
.compare-table th.sticky-col {
background: var(--surface-alt);
z-index: 30;
}
.compare-table .sticky-col-1 {
left: 0;
min-width: 60px;
max-width: 60px;
}
.compare-table .sticky-col-2 {
left: 60px;
min-width: 200px;
max-width: 250px;
border-right: 2px solid var(--border);
}
.compare-table th.mill-header {
text-align: center;
min-width: 120px;
}
.compare-table th.mill-header .mill-name {
font-weight: 600;
color: var(--accent);
}
/* Mill column shading - alternating backgrounds */
.compare-table .mill-col-0 { background-color: rgba(33, 150, 243, 0.08); }
.compare-table .mill-col-1 { background-color: rgba(76, 175, 80, 0.08); }
.compare-table .mill-col-2 { background-color: rgba(156, 39, 176, 0.08); }
.compare-table .mill-col-3 { background-color: rgba(255, 152, 0, 0.08); }
.compare-table .mill-col-4 { background-color: rgba(0, 188, 212, 0.08); }
.compare-table .mill-col-5 { background-color: rgba(233, 30, 99, 0.08); }
.compare-table .mill-col-6 { background-color: rgba(139, 195, 74, 0.08); }
.compare-table .mill-col-7 { background-color: rgba(121, 85, 72, 0.08); }
/* Header shading matches columns */
.compare-table th.mill-col-0 { background-color: rgba(33, 150, 243, 0.15); }
.compare-table th.mill-col-1 { background-color: rgba(76, 175, 80, 0.15); }
.compare-table th.mill-col-2 { background-color: rgba(156, 39, 176, 0.15); }
.compare-table th.mill-col-3 { background-color: rgba(255, 152, 0, 0.15); }
.compare-table th.mill-col-4 { background-color: rgba(0, 188, 212, 0.15); }
.compare-table th.mill-col-5 { background-color: rgba(233, 30, 99, 0.15); }
.compare-table th.mill-col-6 { background-color: rgba(139, 195, 74, 0.15); }
.compare-table th.mill-col-7 { background-color: rgba(121, 85, 72, 0.15); }
.compare-table th.sub-header {
font-size: 0.75rem;
font-weight: 500;
top: 35px;
}
.compare-table tr:hover td {
background: var(--hover);
}
.compare-table tr:hover td.sticky-col {
background: var(--hover);
}
.compare-table .item-num {
font-weight: 600;
color: var(--accent);
white-space: nowrap;
}
.compare-table .metric-name {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.compare-table .value-cell {
text-align: right;
font-family: 'Consolas', 'Monaco', monospace;
white-space: nowrap;
}
.compare-table .value-cell.negative {
color: #ef5350;
}
.compare-table .value-cell.best {
background: rgba(76, 175, 80, 0.15);
font-weight: 600;
}
.compare-table .value-cell.worst {
background: rgba(244, 67, 54, 0.1);
}
.no-data {
text-align: center;
padding: 3rem;
color: var(--text-muted);
background: var(--surface);
border-radius: 8px;
border: 1px solid var(--border);
}
.compare-summary {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
gap: 1rem;
margin-bottom: 1.5rem;
}
.compare-stat {
background: var(--surface);
padding: 1rem;
border-radius: 8px;
text-align: center;
border: 1px solid var(--border);
}
.compare-stat .value {
font-size: 1.5rem;
font-weight: 600;
color: var(--accent);
}
.compare-stat .label {
font-size: 0.8rem;
color: var(--text-muted);
}
.view-toggle {
display: flex;
gap: 0.5rem;
margin-left: auto;
}
.view-toggle button {
padding: 0.5rem 1rem;
border: 1px solid var(--border);
background: var(--surface);
color: var(--text);
border-radius: 6px;
cursor: pointer;
font-size: 0.85rem;
}
.view-toggle button.active {
background: var(--accent);
color: white;
border-color: var(--accent);
}
</style>
<div class="app-content">
<section class="data-panel">
<?php if ($connectionError): ?>
<div class="no-data">Unable to connect to the database.</div>
<?php else: ?>
<form class="compare-controls" method="get">
<div class="compare-control">
<label>Report File</label>
<select name="file" onchange="this.form.submit()">
<?php if (empty($sourceFiles)): ?>
<option value="">No reports available</option>
<?php else: ?>
<?php foreach ($sourceFiles as $file): ?>
<option value="<?= htmlspecialchars($file['SourceFileName']) ?>"
<?= $file['SourceFileName'] === $selectedFile ? 'selected' : '' ?>>
<?= htmlspecialchars($file['SourceFileName']) ?>
(<?= formatCompareDate($file['BeginningDate']) ?> - <?= formatCompareDate($file['EndingDate']) ?>)
</option>
<?php endforeach; ?>
<?php endif; ?>
</select>
</div>
<div class="compare-control">
<label>Category</label>
<select name="category" onchange="this.form.submit()">
<?php if (empty($categories)): ?>
<option value="">No categories available</option>
<?php else: ?>
<?php foreach ($categories as $cat): ?>
<option value="<?= htmlspecialchars($cat) ?>"
<?= $cat === $selectedCategory ? 'selected' : '' ?>>
<?= htmlspecialchars($cat) ?>
</option>
<?php endforeach; ?>
<?php endif; ?>
</select>
</div>
</form>
<div class="compare-summary">
<div class="compare-stat">
<div class="value"><?= count($millCodes) ?></div>
<div class="label">Mills</div>
</div>
<div class="compare-stat">
<div class="value"><?= count($pivotedData) ?></div>
<div class="label">Metrics</div>
</div>
<div class="compare-stat">
<div class="value"><?= htmlspecialchars($selectedCategory ?: '-') ?></div>
<div class="label">Category</div>
</div>
</div>
<?php if (!empty($pivotedData) && !empty($millCodes)): ?>
<div class="compare-table-container">
<table class="compare-table">
<thead>
<tr>
<th rowspan="2" class="sticky-col sticky-col-1">Item</th>
<th rowspan="2" class="sticky-col sticky-col-2">Metric</th>
<?php foreach ($millCodes as $idx => $millCode): ?>
<th colspan="2" class="mill-header mill-col-<?= $idx % 8 ?>">
<span class="mill-name"><?= htmlspecialchars($millDisplayNames[$millCode]) ?></span>
</th>
<?php endforeach; ?>
</tr>
<tr>
<?php foreach ($millCodes as $idx => $millCode): ?>
<th class="sub-header mill-col-<?= $idx % 8 ?>">RUN</th>
<th class="sub-header mill-col-<?= $idx % 8 ?>">TO DATE</th>
<?php endforeach; ?>
</tr>
</thead>
<tbody>
<?php foreach ($pivotedData as $metric): ?>
<tr>
<td class="item-num sticky-col sticky-col-1"><?= htmlspecialchars($metric['ItemNumber'] ?? '') ?></td>
<td class="metric-name sticky-col sticky-col-2"><?= htmlspecialchars($metric['MetricName'] ?? '') ?></td>
<?php foreach ($millCodes as $idx => $millCode): ?>
<?php
$millData = $metric['mills'][$millCode] ?? null;
$runValue = $millData['RunValue'] ?? '-';
$toDateValue = $millData['ToDateValue'] ?? '-';
$runNumeric = $millData['RunValueNumeric'] ?? null;
$toDateNumeric = $millData['ToDateValueNumeric'] ?? null;
$colClass = 'mill-col-' . ($idx % 8);
?>
<td class="value-cell <?= $colClass ?> <?= ($runNumeric ?? 0) < 0 ? 'negative' : '' ?>">
<?= htmlspecialchars($runValue) ?>
</td>
<td class="value-cell <?= $colClass ?> <?= ($toDateNumeric ?? 0) < 0 ? 'negative' : '' ?>">
<?= htmlspecialchars($toDateValue) ?>
</td>
<?php endforeach; ?>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
<?php else: ?>
<div class="no-data">
<p>No comparison data available. Select a file and category above.</p>
</div>
<?php endif; ?>
<?php endif; ?>
</section>
</div>
<?php require __DIR__ . '/../includes/layout/footer.php'; ?>