Add comprehensive workflow management system for ticket status transitions: - Created WorkflowModel.php for managing status transition rules - Updated TicketController.php to load allowed transitions for each ticket - Modified TicketView.php to display dynamic status dropdown with only allowed transitions - Enhanced api/update_ticket.php with server-side workflow validation - Added updateTicketStatus() JavaScript function for client-side status changes - Included CSS styling for status select dropdown with color-coded states - Transitions can require comments or admin privileges - Status changes are validated against status_transitions table This feature enforces proper ticket workflows and prevents invalid status changes. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
118 lines
3.4 KiB
PHP
118 lines
3.4 KiB
PHP
<?php
|
|
/**
|
|
* WorkflowModel - Handles status transition workflows and validation
|
|
*/
|
|
class WorkflowModel {
|
|
private $conn;
|
|
|
|
public function __construct($conn) {
|
|
$this->conn = $conn;
|
|
}
|
|
|
|
/**
|
|
* Get allowed status transitions for a given status
|
|
*
|
|
* @param string $currentStatus Current ticket status
|
|
* @return array Array of allowed transitions with requirements
|
|
*/
|
|
public function getAllowedTransitions($currentStatus) {
|
|
$sql = "SELECT to_status, requires_comment, requires_admin
|
|
FROM status_transitions
|
|
WHERE from_status = ? AND is_active = TRUE";
|
|
$stmt = $this->conn->prepare($sql);
|
|
$stmt->bind_param("s", $currentStatus);
|
|
$stmt->execute();
|
|
$result = $stmt->get_result();
|
|
|
|
$transitions = [];
|
|
while ($row = $result->fetch_assoc()) {
|
|
$transitions[] = $row;
|
|
}
|
|
|
|
$stmt->close();
|
|
return $transitions;
|
|
}
|
|
|
|
/**
|
|
* Check if a status transition is allowed
|
|
*
|
|
* @param string $fromStatus Current status
|
|
* @param string $toStatus Desired status
|
|
* @param bool $isAdmin Whether user is admin
|
|
* @return bool True if transition is allowed
|
|
*/
|
|
public function isTransitionAllowed($fromStatus, $toStatus, $isAdmin = false) {
|
|
// Allow same status (no change)
|
|
if ($fromStatus === $toStatus) {
|
|
return true;
|
|
}
|
|
|
|
$sql = "SELECT requires_admin FROM status_transitions
|
|
WHERE from_status = ? AND to_status = ? AND is_active = TRUE";
|
|
$stmt = $this->conn->prepare($sql);
|
|
$stmt->bind_param("ss", $fromStatus, $toStatus);
|
|
$stmt->execute();
|
|
$result = $stmt->get_result();
|
|
|
|
if ($result->num_rows === 0) {
|
|
$stmt->close();
|
|
return false; // Transition not defined
|
|
}
|
|
|
|
$row = $result->fetch_assoc();
|
|
$stmt->close();
|
|
|
|
if ($row['requires_admin'] && !$isAdmin) {
|
|
return false; // Admin required
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Get all possible statuses from transitions table
|
|
*
|
|
* @return array Array of unique status values
|
|
*/
|
|
public function getAllStatuses() {
|
|
$sql = "SELECT DISTINCT from_status as status FROM status_transitions
|
|
UNION
|
|
SELECT DISTINCT to_status as status FROM status_transitions
|
|
ORDER BY status";
|
|
$result = $this->conn->query($sql);
|
|
|
|
$statuses = [];
|
|
while ($row = $result->fetch_assoc()) {
|
|
$statuses[] = $row['status'];
|
|
}
|
|
|
|
return $statuses;
|
|
}
|
|
|
|
/**
|
|
* Get transition requirements
|
|
*
|
|
* @param string $fromStatus Current status
|
|
* @param string $toStatus Desired status
|
|
* @return array|null Transition requirements or null if not found
|
|
*/
|
|
public function getTransitionRequirements($fromStatus, $toStatus) {
|
|
$sql = "SELECT requires_comment, requires_admin
|
|
FROM status_transitions
|
|
WHERE from_status = ? AND to_status = ? AND is_active = TRUE";
|
|
$stmt = $this->conn->prepare($sql);
|
|
$stmt->bind_param("ss", $fromStatus, $toStatus);
|
|
$stmt->execute();
|
|
$result = $stmt->get_result();
|
|
|
|
if ($result->num_rows === 0) {
|
|
$stmt->close();
|
|
return null;
|
|
}
|
|
|
|
$row = $result->fetch_assoc();
|
|
$stmt->close();
|
|
return $row;
|
|
}
|
|
}
|