payfrit-api/api/orders/getOrCreateCart.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

139 lines
5.5 KiB
PHP

<?php
require_once __DIR__ . '/../helpers.php';
require_once __DIR__ . '/_cartPayload.php';
require_once __DIR__ . '/../grants/_grantUtils.php';
runAuth();
/**
* Get or Create Cart
* POST: { BusinessID: int, UserID: int, ServicePointID?: int, OrderTypeID?: int }
* Always creates a fresh cart.
*/
$data = readJsonBody();
$BusinessID = (int) ($data['BusinessID'] ?? 0);
$ServicePointID = (int) ($data['ServicePointID'] ?? 0);
$OrderTypeID = (int) ($data['OrderTypeID'] ?? 0);
$UserID = (int) ($data['UserID'] ?? 0);
if ($BusinessID <= 0 || $UserID <= 0) {
apiAbort(['OK' => false, 'ERROR' => 'missing_params', 'MESSAGE' => 'BusinessID and UserID are required.']);
}
if ($OrderTypeID === 1 && $ServicePointID <= 0) {
apiAbort(['OK' => false, 'ERROR' => 'missing_service_point', 'MESSAGE' => 'ServicePointID is required for dine-in. Please scan a table beacon.']);
}
if ($OrderTypeID < 0 || $OrderTypeID > 3) {
apiAbort(['OK' => false, 'ERROR' => 'invalid_order_type', 'MESSAGE' => 'OrderTypeID must be 0-3 (0=undecided, 1=dine-in, 2=takeaway, 3=delivery).']);
}
try {
$qBiz = queryOne("SELECT DeliveryFlatFee FROM Businesses WHERE ID = ? LIMIT 1", [$BusinessID]);
if (!$qBiz) {
apiAbort(['OK' => false, 'ERROR' => 'bad_business', 'MESSAGE' => 'Business not found']);
}
// SP-SM: Resolve grant if ServicePoint doesn't belong to this business
$grantID = 0;
$grantOwnerBusinessID = 0;
$grantEconomicsType = '';
$grantEconomicsValue = 0;
if ($ServicePointID > 0) {
$qSPOwner = queryOne("SELECT BusinessID FROM ServicePoints WHERE ID = ? LIMIT 1", [$ServicePointID]);
if ($qSPOwner && (int) $qSPOwner['BusinessID'] !== $BusinessID) {
// SP belongs to another business
$qParent = queryOne("SELECT ParentBusinessID FROM Businesses WHERE ID = ? LIMIT 1", [$BusinessID]);
$isChildOfSPOwner = $qParent && (int) ($qParent['ParentBusinessID'] ?? 0) === (int) $qSPOwner['BusinessID'];
if (!$isChildOfSPOwner) {
// Check for active grant
$qGrant = queryOne(
"SELECT ID, OwnerBusinessID, EconomicsType, EconomicsValue, EligibilityScope, TimePolicyType, TimePolicyData
FROM ServicePointGrants
WHERE GuestBusinessID = ? AND ServicePointID = ? AND StatusID = 1
LIMIT 1",
[$BusinessID, $ServicePointID]
);
if (!$qGrant) {
apiAbort(['OK' => false, 'ERROR' => 'sp_not_accessible', 'MESSAGE' => 'Service point is not accessible to your business.']);
}
if (!isGrantTimeActive($qGrant['TimePolicyType'], $qGrant['TimePolicyData'])) {
apiAbort(['OK' => false, 'ERROR' => 'grant_time_inactive', 'MESSAGE' => 'Service point access is not available at this time.']);
}
if (!checkGrantEligibility($qGrant['EligibilityScope'], $UserID, (int) $qGrant['OwnerBusinessID'], $BusinessID)) {
apiAbort(['OK' => false, 'ERROR' => 'grant_eligibility_failed', 'MESSAGE' => 'You are not eligible to order at this service point.']);
}
$grantID = (int) $qGrant['ID'];
$grantOwnerBusinessID = (int) $qGrant['OwnerBusinessID'];
$grantEconomicsType = $qGrant['EconomicsType'];
$grantEconomicsValue = (float) $qGrant['EconomicsValue'];
}
}
}
// Check if user is on an active tab at this business
$tabID = 0;
$qUserTab = queryOne("
SELECT t.ID
FROM TabMembers tm
JOIN Tabs t ON t.ID = tm.TabID
WHERE tm.UserID = ? AND tm.StatusID = 1 AND t.BusinessID = ? AND t.StatusID = 1
LIMIT 1
", [$UserID, $BusinessID]);
if ($qUserTab) {
$tabID = (int) $qUserTab['ID'];
}
$nowISO = gmdate('Y-m-d H:i:s');
$newUUID = generateUUID();
$deliveryFee = ($OrderTypeID === 3) ? (float) $qBiz['DeliveryFlatFee'] : 0;
// Generate new OrderID (table is not auto-inc)
$qNext = queryOne("SELECT IFNULL(MAX(ID),0) + 1 AS NextID FROM Orders", []);
$NewOrderID = (int) $qNext['NextID'];
queryTimed("
INSERT INTO Orders (
ID, UUID, UserID, BusinessID, DeliveryMultiplier, OrderTypeID, DeliveryFee,
StatusID, AddressID, PaymentID, Remarks, AddedOn, LastEditedOn, SubmittedOn,
ServicePointID, GrantID, GrantOwnerBusinessID, GrantEconomicsType,
GrantEconomicsValue, TabID
) VALUES (
?, ?, ?, ?, 1.0, ?, ?,
0, NULL, NULL, NULL, ?, ?, NULL,
?, ?, ?, ?, ?, ?
)
", [
$NewOrderID,
$newUUID,
$UserID,
$BusinessID,
$OrderTypeID,
$deliveryFee,
$nowISO,
$nowISO,
$ServicePointID,
$grantID > 0 ? $grantID : null,
$grantOwnerBusinessID > 0 ? $grantOwnerBusinessID : null,
strlen($grantEconomicsType) > 0 ? $grantEconomicsType : null,
($grantEconomicsType !== '' && $grantEconomicsType !== 'none') ? $grantEconomicsValue : null,
$tabID > 0 ? $tabID : null,
]);
// Get the final ID
$qLatest = queryOne("SELECT MAX(ID) AS NextID FROM Orders", []);
$FinalOrderID = (int) $qLatest['NextID'];
$payload = loadCartPayload($FinalOrderID);
jsonResponse($payload);
} catch (Exception $e) {
jsonResponse([
'OK' => false,
'ERROR' => 'server_error: ' . $e->getMessage(),
'MESSAGE' => 'DB error creating cart',
'DETAIL' => $e->getMessage(),
]);
}