|
@@ -24,7 +24,13 @@ function render_jobs_table(string $audience, ?int $vendor_id = null): string {
|
|
|
CASE WHEN j.due_date IS NULL THEN ''
|
|
CASE WHEN j.due_date IS NULL THEN ''
|
|
|
ELSE CAST(CAST(strftime('%m', j.due_date) AS INTEGER) AS TEXT) || '-' ||
|
|
ELSE CAST(CAST(strftime('%m', j.due_date) AS INTEGER) AS TEXT) || '-' ||
|
|
|
CAST(CAST(strftime('%d', j.due_date) AS INTEGER) AS TEXT)
|
|
CAST(CAST(strftime('%d', j.due_date) AS INTEGER) AS TEXT)
|
|
|
- END AS due_short
|
|
|
|
|
|
|
+ END AS due_short,
|
|
|
|
|
+ (SELECT MAX(changed_at) FROM job_history
|
|
|
|
|
+ WHERE job_id = j.id AND field = 'status' AND new_value = 'Finished') AS finished_at,
|
|
|
|
|
+ (SELECT MAX(changed_at) FROM job_history
|
|
|
|
|
+ WHERE job_id = j.id AND field = 'status' AND new_value = 'Shipped') AS shipped_at,
|
|
|
|
|
+ (SELECT MAX(changed_at) FROM job_history
|
|
|
|
|
+ WHERE job_id = j.id AND field = 'status' AND new_value = 'Received') AS received_at
|
|
|
FROM jobs j
|
|
FROM jobs j
|
|
|
JOIN vendors v ON v.id = j.vendor_id
|
|
JOIN vendors v ON v.id = j.vendor_id
|
|
|
WHERE $where
|
|
WHERE $where
|
|
@@ -75,7 +81,7 @@ function render_jobs_table(string $audience, ?int $vendor_id = null): string {
|
|
|
<td class="center"><?= render_due($r, $editable) ?></td>
|
|
<td class="center"><?= render_due($r, $editable) ?></td>
|
|
|
<?php if ($audience === 'ICG'): ?><td><?= h($r['vendor_name']) ?></td><?php endif; ?>
|
|
<?php if ($audience === 'ICG'): ?><td><?= h($r['vendor_name']) ?></td><?php endif; ?>
|
|
|
<td class="center <?= h($ackClass) ?>"><?= $r['ack'] === 'new' ? 'NEW' : '' ?></td>
|
|
<td class="center <?= h($ackClass) ?>"><?= $r['ack'] === 'new' ? 'NEW' : '' ?></td>
|
|
|
- <td class="center"><?= h($r['status']) ?></td>
|
|
|
|
|
|
|
+ <td class="center"><?= render_status($r, $audience) ?></td>
|
|
|
<td class="center actions"><?= render_actions($r, $audience) ?></td>
|
|
<td class="center actions"><?= render_actions($r, $audience) ?></td>
|
|
|
</tr>
|
|
</tr>
|
|
|
<?php endforeach; ?>
|
|
<?php endforeach; ?>
|
|
@@ -102,6 +108,33 @@ function render_due(array $r, bool $editable): string {
|
|
|
. $display . '</span>';
|
|
. $display . '</span>';
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+function render_status(array $r, string $audience): string {
|
|
|
|
|
+ $out = h($r['status']);
|
|
|
|
|
+ $stamp = null;
|
|
|
|
|
+ if ($audience === 'ICG') {
|
|
|
|
|
+ if ($r['status'] === 'Finished') $stamp = $r['finished_at'] ?? null;
|
|
|
|
|
+ elseif ($r['status'] === 'Shipped') $stamp = $r['shipped_at'] ?? null;
|
|
|
|
|
+ } else { // vendor
|
|
|
|
|
+ if ($r['status'] === 'Received') $stamp = $r['received_at'] ?? null;
|
|
|
|
|
+ }
|
|
|
|
|
+ if ($stamp) {
|
|
|
|
|
+ $out .= '<div class="status-date">' . h(format_short_date($stamp)) . '</div>';
|
|
|
|
|
+ }
|
|
|
|
|
+ return $out;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+// Convert a UTC 'YYYY-MM-DD HH:MM:SS' from datetime('now') into 'M/D' in the
|
|
|
|
|
+// server's local timezone for display.
|
|
|
|
|
+function format_short_date(?string $ts): string {
|
|
|
|
|
+ if (!$ts) return '';
|
|
|
|
|
+ try {
|
|
|
|
|
+ $dt = new DateTimeImmutable($ts . ' UTC');
|
|
|
|
|
+ return $dt->setTimezone(new DateTimeZone(date_default_timezone_get()))->format('n/j');
|
|
|
|
|
+ } catch (Exception $e) {
|
|
|
|
|
+ return '';
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
function render_actions(array $r, string $audience): string {
|
|
function render_actions(array $r, string $audience): string {
|
|
|
$btns = [];
|
|
$btns = [];
|
|
|
if ($audience === 'vendor') {
|
|
if ($audience === 'vendor') {
|
|
@@ -113,6 +146,9 @@ function render_actions(array $r, string $audience): string {
|
|
|
} elseif ($r['status'] === 'Finished') {
|
|
} elseif ($r['status'] === 'Finished') {
|
|
|
$btns[] = '<button class="btn btn-ship" data-action="mark_shipped">Mark Shipped</button>';
|
|
$btns[] = '<button class="btn btn-ship" data-action="mark_shipped">Mark Shipped</button>';
|
|
|
}
|
|
}
|
|
|
|
|
+ if (in_array($r['status'], ['', 'Finished'], true) && (int) $r['qty'] > 1) {
|
|
|
|
|
+ $btns[] = '<button class="btn btn-partial" data-action="partial_ship" data-qty="' . (int) $r['qty'] . '">Partial Ship</button>';
|
|
|
|
|
+ }
|
|
|
} else { // ICG
|
|
} else { // ICG
|
|
|
if ($r['status'] === 'Shipped') {
|
|
if ($r['status'] === 'Shipped') {
|
|
|
$btns[] = '<button class="btn btn-receive" data-action="mark_received">Mark Received</button>';
|
|
$btns[] = '<button class="btn btn-receive" data-action="mark_received">Mark Received</button>';
|