refactor: odstraneni PSR-1 SideEffects warningu
- Handler funkce extrahovany z API souboru do api/admin/handlers/ - config.php rozdeleny na helpers.php (funkce) a constants.php (konstanty) - require_once odstranen z class souboru (AuditLog, JWTAuth, LeaveNotification) - vendor/autoload.php presunuto do config.php bootstrap - totp-handlers.php: pridany use deklarace pro TwoFactorAuth - phpstan.neon: bootstrapFiles, scanDirectories, dynamicConstantNames - Opraveny chybejici routing bloky v totp.php a session.php Vysledek: phpcs 0 errors 0 warnings, PHPStan 0 errors, ESLint 0 errors Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -15,6 +15,7 @@ declare(strict_types=1);
|
||||
require_once dirname(__DIR__) . '/config.php';
|
||||
require_once dirname(__DIR__) . '/includes/JWTAuth.php';
|
||||
require_once dirname(__DIR__) . '/includes/AuditLog.php';
|
||||
require_once __DIR__ . '/handlers/orders-handlers.php';
|
||||
|
||||
setCorsHeaders();
|
||||
setSecurityHeaders();
|
||||
@@ -88,528 +89,3 @@ try {
|
||||
// --- Valid status transitions ---
|
||||
|
||||
/** @return list<string> */
|
||||
function getValidTransitions(string $currentStatus): array
|
||||
{
|
||||
$map = [
|
||||
'prijata' => ['v_realizaci', 'stornovana'],
|
||||
'v_realizaci' => ['dokoncena', 'stornovana'],
|
||||
'dokoncena' => [],
|
||||
'stornovana' => [],
|
||||
];
|
||||
return $map[$currentStatus] ?? [];
|
||||
}
|
||||
|
||||
// --- Number generation ---
|
||||
|
||||
function generateOrderNumber(PDO $pdo): string
|
||||
{
|
||||
return generateSharedNumber($pdo);
|
||||
}
|
||||
|
||||
// --- Handlers ---
|
||||
|
||||
function handleGetList(PDO $pdo): void
|
||||
{
|
||||
$search = trim($_GET['search'] ?? '');
|
||||
$sort = $_GET['sort'] ?? 'created_at';
|
||||
$order = strtoupper($_GET['order'] ?? 'DESC') === 'ASC' ? 'ASC' : 'DESC';
|
||||
$page = max(1, (int) ($_GET['page'] ?? 1));
|
||||
$perPage = min(500, max(1, (int) ($_GET['per_page'] ?? 500)));
|
||||
|
||||
$sortMap = [
|
||||
'OrderNumber' => 'o.order_number',
|
||||
'order_number' => 'o.order_number',
|
||||
'CreatedAt' => 'o.created_at',
|
||||
'created_at' => 'o.created_at',
|
||||
'Status' => 'o.status',
|
||||
'status' => 'o.status',
|
||||
'Currency' => 'o.currency',
|
||||
'currency' => 'o.currency',
|
||||
];
|
||||
if (!isset($sortMap[$sort])) {
|
||||
errorResponse('Neplatný parametr řazení', 400);
|
||||
}
|
||||
$sortCol = $sortMap[$sort];
|
||||
|
||||
$where = 'WHERE 1=1';
|
||||
$params = [];
|
||||
|
||||
if ($search) {
|
||||
$search = mb_substr($search, 0, 100);
|
||||
$where .= ' AND (o.order_number LIKE ? OR q.quotation_number LIKE ? OR q.project_code LIKE ? OR c.name LIKE ?)';
|
||||
$searchParam = "%{$search}%";
|
||||
$params = [$searchParam, $searchParam, $searchParam, $searchParam];
|
||||
}
|
||||
|
||||
$countSql = "
|
||||
SELECT COUNT(*)
|
||||
FROM orders o
|
||||
LEFT JOIN quotations q ON o.quotation_id = q.id
|
||||
LEFT JOIN customers c ON o.customer_id = c.id
|
||||
$where
|
||||
";
|
||||
$stmt = $pdo->prepare($countSql);
|
||||
$stmt->execute($params);
|
||||
$total = (int) $stmt->fetchColumn();
|
||||
|
||||
$offset = ($page - 1) * $perPage;
|
||||
|
||||
$sql = "
|
||||
SELECT o.id, o.order_number, o.quotation_id, o.status, o.currency,
|
||||
o.created_at, o.apply_vat, o.vat_rate,
|
||||
q.quotation_number, q.project_code,
|
||||
c.name as customer_name,
|
||||
(SELECT COALESCE(SUM(CASE WHEN oi.is_included_in_total THEN oi.quantity * oi.unit_price ELSE 0 END), 0)
|
||||
FROM order_items oi WHERE oi.order_id = o.id) as total,
|
||||
(SELECT inv.id FROM invoices inv WHERE inv.order_id = o.id LIMIT 1) as invoice_id,
|
||||
(SELECT inv.invoice_number FROM invoices inv WHERE inv.order_id = o.id LIMIT 1) as invoice_number
|
||||
FROM orders o
|
||||
LEFT JOIN quotations q ON o.quotation_id = q.id
|
||||
LEFT JOIN customers c ON o.customer_id = c.id
|
||||
$where
|
||||
ORDER BY $sortCol $order
|
||||
LIMIT $perPage OFFSET $offset
|
||||
";
|
||||
|
||||
$stmt = $pdo->prepare($sql);
|
||||
$stmt->execute($params);
|
||||
$orders = $stmt->fetchAll();
|
||||
|
||||
successResponse([
|
||||
'orders' => $orders,
|
||||
'total' => $total,
|
||||
'page' => $page,
|
||||
'per_page' => $perPage,
|
||||
]);
|
||||
}
|
||||
|
||||
function handleGetDetail(PDO $pdo, int $id): void
|
||||
{
|
||||
// BLOB vynechany - stahuje se pres action=attachment
|
||||
$stmt = $pdo->prepare('
|
||||
SELECT o.id, o.order_number, o.customer_order_number, o.attachment_name,
|
||||
o.quotation_id, o.customer_id, o.status, o.currency, o.language,
|
||||
o.vat_rate, o.apply_vat, o.exchange_rate, o.scope_title, o.scope_description,
|
||||
o.notes, o.created_at, o.modified_at,
|
||||
q.quotation_number, q.project_code,
|
||||
c.name as customer_name
|
||||
FROM orders o
|
||||
LEFT JOIN quotations q ON o.quotation_id = q.id
|
||||
LEFT JOIN customers c ON o.customer_id = c.id
|
||||
WHERE o.id = ?
|
||||
');
|
||||
$stmt->execute([$id]);
|
||||
$order = $stmt->fetch();
|
||||
|
||||
if (!$order) {
|
||||
errorResponse('Objednávka nebyla nalezena', 404);
|
||||
}
|
||||
|
||||
// Get items
|
||||
$stmt = $pdo->prepare('SELECT * FROM order_items WHERE order_id = ? ORDER BY position');
|
||||
$stmt->execute([$id]);
|
||||
$order['items'] = $stmt->fetchAll();
|
||||
|
||||
// Get sections
|
||||
$stmt = $pdo->prepare('SELECT * FROM order_sections WHERE order_id = ? ORDER BY position');
|
||||
$stmt->execute([$id]);
|
||||
$order['sections'] = $stmt->fetchAll();
|
||||
|
||||
// Get customer
|
||||
if ($order['customer_id']) {
|
||||
$stmt = $pdo->prepare(
|
||||
'SELECT id, name, company_id, vat_id, street, city,
|
||||
postal_code, country, custom_fields
|
||||
FROM customers WHERE id = ?'
|
||||
);
|
||||
$stmt->execute([$order['customer_id']]);
|
||||
$order['customer'] = $stmt->fetch();
|
||||
}
|
||||
|
||||
// Get linked project
|
||||
$stmt = $pdo->prepare('SELECT id, project_number, name, status FROM projects WHERE order_id = ?');
|
||||
$stmt->execute([$id]);
|
||||
$order['project'] = $stmt->fetch() ?: null;
|
||||
|
||||
// Get linked invoice
|
||||
$stmt = $pdo->prepare('SELECT id, invoice_number, status FROM invoices WHERE order_id = ? LIMIT 1');
|
||||
$stmt->execute([$id]);
|
||||
$order['invoice'] = $stmt->fetch() ?: null;
|
||||
|
||||
// Valid transitions
|
||||
$order['valid_transitions'] = getValidTransitions($order['status']);
|
||||
|
||||
successResponse($order);
|
||||
}
|
||||
|
||||
function handleGetAttachment(PDO $pdo, int $id): void
|
||||
{
|
||||
$stmt = $pdo->prepare('SELECT attachment_data, attachment_name FROM orders WHERE id = ?');
|
||||
$stmt->execute([$id]);
|
||||
$row = $stmt->fetch();
|
||||
|
||||
if (!$row || !$row['attachment_data']) {
|
||||
errorResponse('Příloha nebyla nalezena', 404);
|
||||
}
|
||||
|
||||
$finfo = new finfo(FILEINFO_MIME_TYPE);
|
||||
$mime = $finfo->buffer($row['attachment_data']);
|
||||
if ($mime !== 'application/pdf') {
|
||||
errorResponse('Příloha není platný PDF soubor', 415);
|
||||
}
|
||||
|
||||
header_remove('Content-Type');
|
||||
header('Content-Type: application/pdf');
|
||||
$safeName = preg_replace('/[^a-zA-Z0-9._-]/', '_', basename($row['attachment_name'] ?: 'priloha.pdf'));
|
||||
header('Content-Disposition: attachment; filename="' . $safeName . '"');
|
||||
header('Content-Length: ' . strlen($row['attachment_data']));
|
||||
echo $row['attachment_data'];
|
||||
exit;
|
||||
}
|
||||
|
||||
function handleCreateOrder(PDO $pdo): void
|
||||
{
|
||||
// Podporuje JSON i FormData (kvuli nahravani prilohy)
|
||||
$contentType = $_SERVER['CONTENT_TYPE'] ?? '';
|
||||
if (str_contains($contentType, 'multipart/form-data')) {
|
||||
$quotationId = (int)($_POST['quotationId'] ?? 0);
|
||||
$customerOrderNumber = trim($_POST['customerOrderNumber'] ?? '');
|
||||
} else {
|
||||
$input = getJsonInput();
|
||||
$quotationId = (int)($input['quotationId'] ?? 0);
|
||||
$customerOrderNumber = trim($input['customerOrderNumber'] ?? '');
|
||||
}
|
||||
|
||||
if (!$quotationId) {
|
||||
errorResponse('ID nabídky je povinné');
|
||||
}
|
||||
|
||||
if ($customerOrderNumber === '') {
|
||||
errorResponse('Číslo objednávky zákazníka je povinné');
|
||||
}
|
||||
if (mb_strlen($customerOrderNumber) > 100) {
|
||||
errorResponse('Číslo objednávky zákazníka je příliš dlouhé (max 100 znaků)');
|
||||
}
|
||||
|
||||
// Validace prilohy
|
||||
$attachmentData = null;
|
||||
$attachmentName = null;
|
||||
if (!empty($_FILES['attachment']['tmp_name'])) {
|
||||
$file = $_FILES['attachment'];
|
||||
if ($file['error'] !== UPLOAD_ERR_OK) {
|
||||
errorResponse('Chyba při nahrávání souboru');
|
||||
}
|
||||
$finfo = new finfo(FILEINFO_MIME_TYPE);
|
||||
$mime = $finfo->file($file['tmp_name']);
|
||||
if ($mime !== 'application/pdf') {
|
||||
errorResponse('Příloha musí být ve formátu PDF');
|
||||
}
|
||||
if ($file['size'] > 10 * 1024 * 1024) {
|
||||
errorResponse('Příloha nesmí být větší než 10 MB');
|
||||
}
|
||||
$attachmentData = file_get_contents($file['tmp_name']);
|
||||
$attachmentName = preg_replace('/[^a-zA-Z0-9._-]/', '_', basename($file['name']));
|
||||
}
|
||||
|
||||
// Verify quotation exists and has no order yet
|
||||
$stmt = $pdo->prepare('SELECT * FROM quotations WHERE id = ?');
|
||||
$stmt->execute([$quotationId]);
|
||||
$quotation = $stmt->fetch();
|
||||
|
||||
if (!$quotation) {
|
||||
errorResponse('Nabídka nebyla nalezena', 404);
|
||||
}
|
||||
|
||||
if ($quotation['order_id']) {
|
||||
errorResponse('Tato nabídka již má objednávku');
|
||||
}
|
||||
|
||||
// Get quotation items and sections
|
||||
$stmt = $pdo->prepare('SELECT * FROM quotation_items WHERE quotation_id = ? ORDER BY position');
|
||||
$stmt->execute([$quotationId]);
|
||||
$quotationItems = $stmt->fetchAll();
|
||||
|
||||
$stmt = $pdo->prepare('SELECT * FROM scope_sections WHERE quotation_id = ? ORDER BY position');
|
||||
$stmt->execute([$quotationId]);
|
||||
$quotationSections = $stmt->fetchAll();
|
||||
|
||||
// Lock for concurrent number generation
|
||||
$locked = $pdo->query("SELECT GET_LOCK('boha_order_number', 5)")->fetchColumn();
|
||||
if (!$locked) {
|
||||
errorResponse('Nepodařilo se získat zámek pro číslo objednávky, zkuste to znovu', 503);
|
||||
}
|
||||
|
||||
$pdo->beginTransaction();
|
||||
try {
|
||||
$orderNumber = generateOrderNumber($pdo);
|
||||
|
||||
$stmt = $pdo->prepare("
|
||||
INSERT INTO orders (
|
||||
order_number, customer_order_number, attachment_data, attachment_name,
|
||||
quotation_id, customer_id, status,
|
||||
currency, language, vat_rate, apply_vat, exchange_rate,
|
||||
scope_title, scope_description, created_at, modified_at
|
||||
) VALUES (?, ?, ?, ?, ?, ?, 'prijata', ?, ?, ?, ?, ?, ?, ?, NOW(), NOW())
|
||||
");
|
||||
$stmt->execute([
|
||||
$orderNumber,
|
||||
$customerOrderNumber,
|
||||
$attachmentData,
|
||||
$attachmentName,
|
||||
$quotationId,
|
||||
$quotation['customer_id'],
|
||||
$quotation['currency'] ?? 'EUR',
|
||||
$quotation['language'] ?? 'EN',
|
||||
$quotation['vat_rate'] ?? 0,
|
||||
$quotation['apply_vat'] ?? 0,
|
||||
$quotation['exchange_rate'],
|
||||
$quotation['scope_title'] ?? '',
|
||||
$quotation['scope_description'] ?? '',
|
||||
]);
|
||||
$orderId = (int)$pdo->lastInsertId();
|
||||
|
||||
// Copy items
|
||||
if (!empty($quotationItems)) {
|
||||
$itemStmt = $pdo->prepare('
|
||||
INSERT INTO order_items (
|
||||
order_id, description, item_description, quantity, unit,
|
||||
unit_price, is_included_in_total, position, modified_at
|
||||
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, NOW())
|
||||
');
|
||||
foreach ($quotationItems as $item) {
|
||||
$itemStmt->execute([
|
||||
$orderId,
|
||||
$item['description'] ?? '',
|
||||
$item['item_description'] ?? '',
|
||||
$item['quantity'] ?? 1,
|
||||
$item['unit'] ?? '',
|
||||
$item['unit_price'] ?? 0,
|
||||
$item['is_included_in_total'] ?? 1,
|
||||
$item['position'] ?? 0,
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
// Copy sections
|
||||
if (!empty($quotationSections)) {
|
||||
$sectionStmt = $pdo->prepare('
|
||||
INSERT INTO order_sections (
|
||||
order_id, title, title_cz, content, position, modified_at
|
||||
) VALUES (?, ?, ?, ?, ?, NOW())
|
||||
');
|
||||
foreach ($quotationSections as $section) {
|
||||
$sectionStmt->execute([
|
||||
$orderId,
|
||||
$section['title'] ?? '',
|
||||
$section['title_cz'] ?? '',
|
||||
$section['content'] ?? '',
|
||||
$section['position'] ?? 0,
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
// Create project with same number
|
||||
$projectName = $quotation['project_code'] ?: ($quotation['customer_name'] ?? 'Projekt ' . $orderNumber);
|
||||
// Need customer name
|
||||
if (!$quotation['project_code'] && $quotation['customer_id']) {
|
||||
$custStmt = $pdo->prepare('SELECT name FROM customers WHERE id = ?');
|
||||
$custStmt->execute([$quotation['customer_id']]);
|
||||
$custName = $custStmt->fetchColumn();
|
||||
if ($custName) {
|
||||
$projectName = $custName;
|
||||
}
|
||||
}
|
||||
|
||||
$stmt = $pdo->prepare("
|
||||
INSERT INTO projects (
|
||||
project_number, name, customer_id, quotation_id, order_id,
|
||||
status, start_date, created_at, modified_at
|
||||
) VALUES (?, ?, ?, ?, ?, 'aktivni', CURDATE(), NOW(), NOW())
|
||||
");
|
||||
$stmt->execute([
|
||||
$orderNumber,
|
||||
$projectName,
|
||||
$quotation['customer_id'],
|
||||
$quotationId,
|
||||
$orderId,
|
||||
]);
|
||||
$projectId = (int)$pdo->lastInsertId();
|
||||
|
||||
// Update quotation with back-reference
|
||||
$stmt = $pdo->prepare('UPDATE quotations SET order_id = ?, modified_at = NOW() WHERE id = ?');
|
||||
$stmt->execute([$orderId, $quotationId]);
|
||||
|
||||
|
||||
$pdo->commit();
|
||||
$pdo->query("SELECT RELEASE_LOCK('boha_order_number')");
|
||||
|
||||
AuditLog::logCreate('orders_order', $orderId, [
|
||||
'order_number' => $orderNumber,
|
||||
'quotation_number' => $quotation['quotation_number'],
|
||||
'project_id' => $projectId,
|
||||
], "Vytvořena objednávka '$orderNumber' z nabídky '{$quotation['quotation_number']}'");
|
||||
|
||||
successResponse([
|
||||
'order_id' => $orderId,
|
||||
'order_number' => $orderNumber,
|
||||
'project_id' => $projectId,
|
||||
'project_number' => $orderNumber,
|
||||
], 'Objednávka byla vytvořena');
|
||||
} catch (PDOException $e) {
|
||||
$pdo->rollBack();
|
||||
$pdo->query("SELECT RELEASE_LOCK('boha_order_number')");
|
||||
throw $e;
|
||||
}
|
||||
}
|
||||
|
||||
function handleUpdateOrder(PDO $pdo, int $id): void
|
||||
{
|
||||
$stmt = $pdo->prepare('SELECT * FROM orders WHERE id = ?');
|
||||
$stmt->execute([$id]);
|
||||
$order = $stmt->fetch();
|
||||
|
||||
if (!$order) {
|
||||
errorResponse('Objednávka nebyla nalezena', 404);
|
||||
}
|
||||
|
||||
$input = getJsonInput();
|
||||
$newStatus = $input['status'] ?? null;
|
||||
$notes = $input['notes'] ?? null;
|
||||
$newOrderNumber = isset($input['order_number']) ? trim($input['order_number']) : null;
|
||||
|
||||
// Delkove limity
|
||||
if ($notes !== null && mb_strlen($notes) > 5000) {
|
||||
errorResponse('Poznámky jsou příliš dlouhé (max 5000 znaků)');
|
||||
}
|
||||
if ($newOrderNumber !== null && mb_strlen($newOrderNumber) > 50) {
|
||||
errorResponse('Číslo objednávky je příliš dlouhé (max 50 znaků)');
|
||||
}
|
||||
|
||||
// Validate status transition
|
||||
if ($newStatus && $newStatus !== $order['status']) {
|
||||
$valid = getValidTransitions($order['status']);
|
||||
if (!in_array($newStatus, $valid)) {
|
||||
errorResponse("Neplatný přechod stavu z '{$order['status']}' na '$newStatus'");
|
||||
}
|
||||
}
|
||||
|
||||
// Validate order number uniqueness
|
||||
if ($newOrderNumber !== null && $newOrderNumber !== $order['order_number']) {
|
||||
if (empty($newOrderNumber)) {
|
||||
errorResponse('Číslo objednávky nesmí být prázdné');
|
||||
}
|
||||
$stmt = $pdo->prepare('SELECT id FROM orders WHERE order_number = ? AND id != ?');
|
||||
$stmt->execute([$newOrderNumber, $id]);
|
||||
if ($stmt->fetch()) {
|
||||
errorResponse('Toto číslo objednávky již existuje');
|
||||
}
|
||||
}
|
||||
|
||||
$pdo->beginTransaction();
|
||||
try {
|
||||
$updates = [];
|
||||
$params = [];
|
||||
|
||||
if ($newOrderNumber !== null && $newOrderNumber !== $order['order_number']) {
|
||||
$updates[] = 'order_number = ?';
|
||||
$params[] = $newOrderNumber;
|
||||
|
||||
// Sync project number
|
||||
$stmt = $pdo->prepare('UPDATE projects SET project_number = ?, modified_at = NOW() WHERE order_id = ?');
|
||||
$stmt->execute([$newOrderNumber, $id]);
|
||||
}
|
||||
if ($newStatus !== null) {
|
||||
$updates[] = 'status = ?';
|
||||
$params[] = $newStatus;
|
||||
}
|
||||
if ($notes !== null) {
|
||||
$updates[] = 'notes = ?';
|
||||
$params[] = $notes;
|
||||
}
|
||||
|
||||
if (!empty($updates)) {
|
||||
$updates[] = 'modified_at = NOW()';
|
||||
$params[] = $id;
|
||||
$sql = 'UPDATE orders SET ' . implode(', ', $updates) . ' WHERE id = ?';
|
||||
$stmt = $pdo->prepare($sql);
|
||||
$stmt->execute($params);
|
||||
}
|
||||
|
||||
// Sync project status with order status
|
||||
if ($newStatus && $newStatus !== $order['status']) {
|
||||
$projectStatus = null;
|
||||
if ($newStatus === 'stornovana') {
|
||||
$projectStatus = 'zruseny';
|
||||
} elseif ($newStatus === 'dokoncena') {
|
||||
$projectStatus = 'dokonceny';
|
||||
} elseif ($newStatus === 'v_realizaci') {
|
||||
$projectStatus = 'aktivni';
|
||||
}
|
||||
|
||||
if ($projectStatus) {
|
||||
$stmt = $pdo->prepare('UPDATE projects SET status = ?, modified_at = NOW() WHERE order_id = ?');
|
||||
$stmt->execute([$projectStatus, $id]);
|
||||
}
|
||||
}
|
||||
|
||||
$pdo->commit();
|
||||
|
||||
AuditLog::logUpdate(
|
||||
'orders_order',
|
||||
$id,
|
||||
['status' => $order['status'], 'notes' => $order['notes']],
|
||||
['status' => $newStatus ?? $order['status'], 'notes' => $notes ?? $order['notes']],
|
||||
"Upravena objednávka '{$order['order_number']}'"
|
||||
);
|
||||
|
||||
successResponse(null, 'Objednávka byla aktualizována');
|
||||
} catch (PDOException $e) {
|
||||
$pdo->rollBack();
|
||||
throw $e;
|
||||
}
|
||||
}
|
||||
|
||||
function handleDeleteOrder(PDO $pdo, int $id): void
|
||||
{
|
||||
$stmt = $pdo->prepare('SELECT * FROM orders WHERE id = ?');
|
||||
$stmt->execute([$id]);
|
||||
$order = $stmt->fetch();
|
||||
|
||||
if (!$order) {
|
||||
errorResponse('Objednávka nebyla nalezena', 404);
|
||||
}
|
||||
|
||||
$pdo->beginTransaction();
|
||||
try {
|
||||
// Delete project linked to this order
|
||||
$stmt = $pdo->prepare('DELETE FROM projects WHERE order_id = ?');
|
||||
$stmt->execute([$id]);
|
||||
|
||||
// Delete order items and sections
|
||||
$stmt = $pdo->prepare('DELETE FROM order_items WHERE order_id = ?');
|
||||
$stmt->execute([$id]);
|
||||
|
||||
$stmt = $pdo->prepare('DELETE FROM order_sections WHERE order_id = ?');
|
||||
$stmt->execute([$id]);
|
||||
|
||||
// Delete order
|
||||
$stmt = $pdo->prepare('DELETE FROM orders WHERE id = ?');
|
||||
$stmt->execute([$id]);
|
||||
|
||||
// Remove back-reference from quotation
|
||||
$stmt = $pdo->prepare('UPDATE quotations SET order_id = NULL, modified_at = NOW() WHERE order_id = ?');
|
||||
$stmt->execute([$id]);
|
||||
|
||||
$pdo->commit();
|
||||
|
||||
AuditLog::logDelete('orders_order', $id, [
|
||||
'order_number' => $order['order_number'],
|
||||
'quotation_id' => $order['quotation_id'],
|
||||
], "Smazána objednávka '{$order['order_number']}'");
|
||||
|
||||
successResponse(null, 'Objednávka byla smazána');
|
||||
} catch (PDOException $e) {
|
||||
$pdo->rollBack();
|
||||
throw $e;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user