Complete port of all 163 API endpoints from Lucee/CFML to PHP 8.3. Shared helpers in api/helpers.php (DB, auth, request/response, security). PDO prepared statements throughout. Same JSON response shapes as CFML.
106 lines
3.9 KiB
PHP
106 lines
3.9 KiB
PHP
<?php
|
|
require_once __DIR__ . '/../helpers.php';
|
|
runAuth();
|
|
|
|
/**
|
|
* Create or update a task type for a business
|
|
* POST: { BusinessID, TaskTypeName, TaskTypeDescription?, TaskTypeIcon?, TaskTypeColor?,
|
|
* RequiresServicePoint?, TaskTypeCategoryID?/CategoryID?, TaskTypeID? (for update) }
|
|
*/
|
|
|
|
$data = readJsonBody();
|
|
$businessID = (int) ($data['BusinessID'] ?? 0);
|
|
|
|
if ($businessID <= 0) {
|
|
apiAbort(['OK' => false, 'ERROR' => 'missing_params', 'MESSAGE' => 'BusinessID is required']);
|
|
}
|
|
|
|
try {
|
|
$taskTypeName = trim($data['TaskTypeName'] ?? '');
|
|
if (empty($taskTypeName)) {
|
|
apiAbort(['OK' => false, 'ERROR' => 'missing_params', 'MESSAGE' => 'TaskTypeName is required']);
|
|
}
|
|
if (strlen($taskTypeName) > 45) {
|
|
apiAbort(['OK' => false, 'ERROR' => 'invalid_params', 'MESSAGE' => 'TaskTypeName must be 45 characters or less']);
|
|
}
|
|
|
|
$taskTypeDescription = trim($data['TaskTypeDescription'] ?? '');
|
|
if (strlen($taskTypeDescription) > 100) {
|
|
apiAbort(['OK' => false, 'ERROR' => 'invalid_params', 'MESSAGE' => 'TaskTypeDescription must be 100 characters or less']);
|
|
}
|
|
|
|
$taskTypeIcon = trim($data['TaskTypeIcon'] ?? '') ?: 'notifications';
|
|
if (strlen($taskTypeIcon) > 30) {
|
|
apiAbort(['OK' => false, 'ERROR' => 'invalid_params', 'MESSAGE' => 'TaskTypeIcon must be 30 characters or less']);
|
|
}
|
|
|
|
$taskTypeColor = trim($data['TaskTypeColor'] ?? '') ?: '#9C27B0';
|
|
if ($taskTypeColor[0] !== '#') {
|
|
$taskTypeColor = '#' . $taskTypeColor;
|
|
}
|
|
if (strlen($taskTypeColor) > 7) {
|
|
apiAbort(['OK' => false, 'ERROR' => 'invalid_params', 'MESSAGE' => 'TaskTypeColor must be a valid hex color']);
|
|
}
|
|
|
|
$requiresServicePoint = 1;
|
|
if (isset($data['RequiresServicePoint'])) {
|
|
$requiresServicePoint = $data['RequiresServicePoint'] ? 1 : 0;
|
|
}
|
|
|
|
$categoryID = null;
|
|
if (isset($data['TaskTypeCategoryID']) && is_numeric($data['TaskTypeCategoryID']) && (int) $data['TaskTypeCategoryID'] > 0) {
|
|
$categoryID = (int) $data['TaskTypeCategoryID'];
|
|
} elseif (isset($data['CategoryID']) && is_numeric($data['CategoryID']) && (int) $data['CategoryID'] > 0) {
|
|
$categoryID = (int) $data['CategoryID'];
|
|
}
|
|
|
|
$taskTypeID = (int) ($data['TaskTypeID'] ?? 0);
|
|
|
|
if ($taskTypeID > 0) {
|
|
// UPDATE
|
|
$qCheck = queryOne("
|
|
SELECT ID FROM tt_TaskTypes WHERE ID = ? AND BusinessID = ?
|
|
", [$taskTypeID, $businessID]);
|
|
|
|
if (!$qCheck) {
|
|
apiAbort(['OK' => false, 'ERROR' => 'not_found', 'MESSAGE' => 'Task type not found or does not belong to this business']);
|
|
}
|
|
|
|
queryTimed("
|
|
UPDATE tt_TaskTypes
|
|
SET Name = ?, Description = ?, Icon = ?, Color = ?,
|
|
RequiresServicePoint = ?, TaskCategoryID = ?
|
|
WHERE ID = ?
|
|
", [
|
|
$taskTypeName,
|
|
!empty($taskTypeDescription) ? $taskTypeDescription : null,
|
|
$taskTypeIcon,
|
|
$taskTypeColor,
|
|
$requiresServicePoint,
|
|
$categoryID,
|
|
$taskTypeID,
|
|
]);
|
|
|
|
jsonResponse(['OK' => true, 'TASK_TYPE_ID' => $taskTypeID, 'MESSAGE' => 'Task type updated']);
|
|
} else {
|
|
// INSERT
|
|
queryTimed("
|
|
INSERT INTO tt_TaskTypes (Name, Description, Icon, Color, RequiresServicePoint, BusinessID, TaskCategoryID)
|
|
VALUES (?, ?, ?, ?, ?, ?, ?)
|
|
", [
|
|
$taskTypeName,
|
|
!empty($taskTypeDescription) ? $taskTypeDescription : null,
|
|
$taskTypeIcon,
|
|
$taskTypeColor,
|
|
$requiresServicePoint,
|
|
$businessID,
|
|
$categoryID,
|
|
]);
|
|
|
|
$newID = (int) lastInsertId();
|
|
jsonResponse(['OK' => true, 'TASK_TYPE_ID' => $newID, 'MESSAGE' => 'Task type created']);
|
|
}
|
|
|
|
} catch (Exception $e) {
|
|
jsonResponse(['OK' => false, 'ERROR' => 'server_error', 'MESSAGE' => $e->getMessage()]);
|
|
}
|