payfrit-api/api/ratings/submit.php
John Mizerek 1f81d98c52 Initial PHP API migration from CFML
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.
2026-03-14 14:26:59 -07:00

102 lines
4.3 KiB
PHP

<?php
require_once __DIR__ . '/../helpers.php';
runAuth();
try {
$data = readJsonBody();
$token = trim($data['token'] ?? ($_GET['token'] ?? ''));
if ($token === '') {
apiAbort(['OK' => false, 'ERROR' => 'missing_token', 'MESSAGE' => 'Rating token is required.']);
}
$qRating = queryOne("
SELECT r.*, t.Title,
u_for.FirstName AS ForFirstName, u_for.LastName AS ForLastName,
u_by.FirstName AS ByFirstName, u_by.LastName AS ByLastName
FROM TaskRatings r
JOIN Tasks t ON t.ID = r.TaskID
LEFT JOIN Users u_for ON u_for.ID = r.ForUserID
LEFT JOIN Users u_by ON u_by.ID = r.ByUserID
WHERE r.AccessToken = ? LIMIT 1
", [$token]);
if (!$qRating) {
apiAbort(['OK' => false, 'ERROR' => 'invalid_token', 'MESSAGE' => 'Rating not found or link is invalid.']);
}
if (strtotime($qRating['ExpiresOn']) < time()) {
apiAbort(['OK' => false, 'ERROR' => 'expired', 'MESSAGE' => 'This rating link has expired.']);
}
if (!empty($qRating['CompletedOn'])) {
apiAbort(['OK' => false, 'ERROR' => 'already_submitted', 'MESSAGE' => 'This rating has already been submitted.']);
}
// Check if this is a submission or info request
$isSubmission = isset($data['onTime']) || isset($data['completedScope'])
|| isset($data['requiredFollowup']) || isset($data['continueAllow'])
|| isset($data['prepared']) || isset($data['respectful'])
|| isset($data['wouldAutoAssign']);
if (!$isSubmission) {
$result = [
'OK' => true,
'RatingID' => (int) $qRating['ID'],
'Direction' => $qRating['Direction'],
'Title' => $qRating['Title'],
'ForUserName' => trim($qRating['ForFirstName'] . ' ' . $qRating['ForLastName']),
'ExpiresOn' => toISO8601($qRating['ExpiresOn']),
];
if ($qRating['Direction'] === 'customer_rates_worker' || $qRating['Direction'] === 'admin_rates_worker') {
$result['Questions'] = [
'onTime' => 'Was the worker on time?',
'completedScope' => 'Was the scope completed?',
'requiredFollowup' => 'Was follow-up required?',
'continueAllow' => 'Continue to allow these tasks?',
];
} elseif ($qRating['Direction'] === 'worker_rates_customer') {
$result['Questions'] = [
'prepared' => 'Was the customer prepared?',
'completedScope' => 'Was the scope clear?',
'respectful' => 'Was the customer respectful?',
'wouldAutoAssign' => 'Would you serve this customer again?',
];
}
jsonResponse($result);
}
// Process submission
$ratingId = (int) $qRating['ID'];
if ($qRating['Direction'] === 'customer_rates_worker' || $qRating['Direction'] === 'admin_rates_worker') {
queryTimed("
UPDATE TaskRatings SET OnTime = ?, CompletedScope = ?, RequiredFollowup = ?, ContinueAllow = ?, CompletedOn = NOW()
WHERE ID = ?
", [
isset($data['onTime']) ? ($data['onTime'] ? 1 : 0) : null,
isset($data['completedScope']) ? ($data['completedScope'] ? 1 : 0) : null,
isset($data['requiredFollowup']) ? ($data['requiredFollowup'] ? 1 : 0) : null,
isset($data['continueAllow']) ? ($data['continueAllow'] ? 1 : 0) : null,
$ratingId,
]);
} elseif ($qRating['Direction'] === 'worker_rates_customer') {
queryTimed("
UPDATE TaskRatings SET Prepared = ?, CompletedScope = ?, Respectful = ?, WouldAutoAssign = ?, CompletedOn = NOW()
WHERE ID = ?
", [
isset($data['prepared']) ? ($data['prepared'] ? 1 : 0) : null,
isset($data['completedScope']) ? ($data['completedScope'] ? 1 : 0) : null,
isset($data['respectful']) ? ($data['respectful'] ? 1 : 0) : null,
isset($data['wouldAutoAssign']) ? ($data['wouldAutoAssign'] ? 1 : 0) : null,
$ratingId,
]);
}
jsonResponse(['OK' => true, 'MESSAGE' => 'Rating submitted successfully. Thank you for your feedback!']);
} catch (Exception $e) {
jsonResponse(['OK' => false, 'ERROR' => 'server_error', 'MESSAGE' => 'Error submitting rating', 'DETAIL' => $e->getMessage()]);
}