diff --git a/api/pharmacy.php b/api/pharmacy.php index c30cb91..2cdd874 100644 --- a/api/pharmacy.php +++ b/api/pharmacy.php @@ -6,6 +6,10 @@ $action = $_GET['action'] ?? ''; $pdo = db(); try { + $page = isset($_GET['page']) ? (int)$_GET['page'] : 1; + $limit = isset($_GET['limit']) ? (int)$_GET['limit'] : 10; + $offset = ($page - 1) * $limit; + switch ($action) { case 'get_stock': // List all drugs with total stock quantity @@ -19,6 +23,116 @@ try { echo json_encode($stmt->fetchAll(PDO::FETCH_ASSOC)); break; + case 'get_low_stock': + // Count total for pagination + $countSql = "SELECT COUNT(*) FROM ( + SELECT d.id + FROM drugs d + LEFT JOIN pharmacy_batches b ON d.id = b.drug_id AND b.quantity > 0 AND b.expiry_date >= CURDATE() + GROUP BY d.id + HAVING COALESCE(SUM(b.quantity), 0) <= MAX(d.reorder_level) + ) as total"; + $total = $pdo->query($countSql)->fetchColumn(); + + // List drugs where total stock is <= reorder_level + $sql = "SELECT d.id, d.name_en, d.name_ar, d.min_stock_level, d.reorder_level, d.unit, + COALESCE(SUM(b.quantity), 0) as total_stock + FROM drugs d + LEFT JOIN pharmacy_batches b ON d.id = b.drug_id AND b.quantity > 0 AND b.expiry_date >= CURDATE() + GROUP BY d.id + HAVING total_stock <= MAX(d.reorder_level) + ORDER BY total_stock ASC + LIMIT :limit OFFSET :offset"; + + $stmt = $pdo->prepare($sql); + $stmt->bindValue(':limit', $limit, PDO::PARAM_INT); + $stmt->bindValue(':offset', $offset, PDO::PARAM_INT); + $stmt->execute(); + + echo json_encode([ + 'data' => $stmt->fetchAll(PDO::FETCH_ASSOC), + 'total' => $total, + 'page' => $page, + 'limit' => $limit + ]); + break; + + case 'get_expired': + // Count total + $countSql = "SELECT COUNT(*) + FROM pharmacy_batches b + JOIN drugs d ON b.drug_id = d.id + LEFT JOIN suppliers s ON b.supplier_id = s.id + WHERE b.expiry_date < CURDATE() AND b.quantity > 0"; + $total = $pdo->query($countSql)->fetchColumn(); + + // List batches that have expired and still have quantity + $sql = "SELECT b.id, b.batch_number, b.expiry_date, b.quantity, + d.name_en as drug_name, d.name_ar as drug_name_ar, + s.name_en as supplier_name + FROM pharmacy_batches b + JOIN drugs d ON b.drug_id = d.id + LEFT JOIN suppliers s ON b.supplier_id = s.id + WHERE b.expiry_date < CURDATE() AND b.quantity > 0 + ORDER BY b.expiry_date ASC + LIMIT :limit OFFSET :offset"; + + $stmt = $pdo->prepare($sql); + $stmt->bindValue(':limit', $limit, PDO::PARAM_INT); + $stmt->bindValue(':offset', $offset, PDO::PARAM_INT); + $stmt->execute(); + + echo json_encode([ + 'data' => $stmt->fetchAll(PDO::FETCH_ASSOC), + 'total' => $total, + 'page' => $page, + 'limit' => $limit + ]); + break; + + case 'get_near_expiry': + $days = $_GET['days'] ?? 90; + + // Count total + $countSql = "SELECT COUNT(*) + FROM pharmacy_batches b + JOIN drugs d ON b.drug_id = d.id + LEFT JOIN suppliers s ON b.supplier_id = s.id + WHERE b.expiry_date >= CURDATE() + AND b.expiry_date <= DATE_ADD(CURDATE(), INTERVAL ? DAY) + AND b.quantity > 0"; + $countStmt = $pdo->prepare($countSql); + $countStmt->execute([$days]); + $total = $countStmt->fetchColumn(); + + // List batches expiring in the next X days + $sql = "SELECT b.id, b.batch_number, b.expiry_date, b.quantity, + d.name_en as drug_name, d.name_ar as drug_name_ar, + s.name_en as supplier_name, + DATEDIFF(b.expiry_date, CURDATE()) as days_remaining + FROM pharmacy_batches b + JOIN drugs d ON b.drug_id = d.id + LEFT JOIN suppliers s ON b.supplier_id = s.id + WHERE b.expiry_date >= CURDATE() + AND b.expiry_date <= DATE_ADD(CURDATE(), INTERVAL :days DAY) + AND b.quantity > 0 + ORDER BY b.expiry_date ASC + LIMIT :limit OFFSET :offset"; + + $stmt = $pdo->prepare($sql); + $stmt->bindValue(':days', $days, PDO::PARAM_INT); + $stmt->bindValue(':limit', $limit, PDO::PARAM_INT); + $stmt->bindValue(':offset', $offset, PDO::PARAM_INT); + $stmt->execute(); + + echo json_encode([ + 'data' => $stmt->fetchAll(PDO::FETCH_ASSOC), + 'total' => $total, + 'page' => $page, + 'limit' => $limit + ]); + break; + case 'get_batches': $drug_id = $_GET['drug_id'] ?? 0; if (!$drug_id) throw new Exception("Drug ID required"); @@ -164,6 +278,188 @@ try { echo json_encode($sale); break; + case 'get_report': + $type = $_GET['type'] ?? 'inventory_valuation'; + $startDate = $_GET['start_date'] ?? date('Y-m-01'); + $endDate = $_GET['end_date'] ?? date('Y-m-d'); + + if ($type === 'inventory_valuation') { + // Count distinct drugs in stock for pagination + $countSql = "SELECT COUNT(DISTINCT d.id) + FROM drugs d + JOIN pharmacy_batches b ON d.id = b.drug_id + WHERE b.quantity > 0"; + $total = $pdo->query($countSql)->fetchColumn(); + + $sql = "SELECT d.name_en as drug_name, d.name_ar as drug_name_ar, + g.name_en as category_name, + SUM(b.quantity) as stock_quantity, + SUM(b.quantity * b.cost_price) / SUM(b.quantity) as avg_cost, + SUM(b.quantity * b.sale_price) / SUM(b.quantity) as selling_price, + SUM(b.quantity * b.cost_price) as total_cost_value, + SUM(b.quantity * b.sale_price) as total_sales_value + FROM drugs d + JOIN pharmacy_batches b ON d.id = b.drug_id + LEFT JOIN drugs_groups g ON d.group_id = g.id + WHERE b.quantity > 0 + GROUP BY d.id + ORDER BY d.name_en ASC + LIMIT :limit OFFSET :offset"; + + // Calculate Grand Totals (entire stock) + $grandTotalSql = "SELECT SUM(b.quantity * b.cost_price) as total_cost, + SUM(b.quantity * b.sale_price) as total_sales + FROM pharmacy_batches b + WHERE b.quantity > 0"; + $grandTotals = $pdo->query($grandTotalSql)->fetch(PDO::FETCH_ASSOC); + + $stmt = $pdo->prepare($sql); + $stmt->bindValue(':limit', $limit, PDO::PARAM_INT); + $stmt->bindValue(':offset', $offset, PDO::PARAM_INT); + $stmt->execute(); + + echo json_encode([ + 'data' => $stmt->fetchAll(PDO::FETCH_ASSOC), + 'total' => $total, + 'page' => $page, + 'limit' => $limit, + 'grand_total_cost' => $grandTotals['total_cost'] ?? 0, + 'grand_total_sales' => $grandTotals['total_sales'] ?? 0 + ]); + + } elseif ($type === 'sales') { + // Count + $countSql = "SELECT COUNT(*) FROM pharmacy_sales WHERE created_at BETWEEN ? AND ? + INTERVAL 1 DAY"; + $countStmt = $pdo->prepare($countSql); + $countStmt->execute([$startDate, $endDate]); + $total = $countStmt->fetchColumn(); + + $sql = "SELECT s.id, s.created_at, s.total_amount, s.payment_method, + p.name as patient_name, + (SELECT COUNT(*) FROM pharmacy_sale_items i WHERE i.sale_id = s.id) as item_count + FROM pharmacy_sales s + LEFT JOIN patients p ON s.patient_id = p.id + WHERE s.created_at BETWEEN :start AND :end + INTERVAL 1 DAY + ORDER BY s.created_at DESC + LIMIT :limit OFFSET :offset"; + + $grandTotalSql = "SELECT SUM(total_amount) as total FROM pharmacy_sales WHERE created_at BETWEEN ? AND ? + INTERVAL 1 DAY"; + $grandTotalStmt = $pdo->prepare($grandTotalSql); + $grandTotalStmt->execute([$startDate, $endDate]); + $grandTotal = $grandTotalStmt->fetchColumn(); + + $stmt = $pdo->prepare($sql); + $stmt->bindValue(':start', $startDate); + $stmt->bindValue(':end', $endDate); + $stmt->bindValue(':limit', $limit, PDO::PARAM_INT); + $stmt->bindValue(':offset', $offset, PDO::PARAM_INT); + $stmt->execute(); + + echo json_encode([ + 'data' => $stmt->fetchAll(PDO::FETCH_ASSOC), + 'total' => $total, + 'page' => $page, + 'limit' => $limit, + 'grand_total_sales' => $grandTotal ?? 0 + ]); + + } elseif ($type === 'expiry') { + $countSql = "SELECT COUNT(*) FROM pharmacy_batches WHERE expiry_date BETWEEN ? AND ? AND quantity > 0"; + $countStmt = $pdo->prepare($countSql); + $countStmt->execute([$startDate, $endDate]); + $total = $countStmt->fetchColumn(); + + $sql = "SELECT b.id, b.batch_number, b.expiry_date, b.quantity, + d.name_en as drug_name, d.name_ar as drug_name_ar, + s.name_en as supplier_name, + DATEDIFF(b.expiry_date, CURDATE()) as days_remaining + FROM pharmacy_batches b + JOIN drugs d ON b.drug_id = d.id + LEFT JOIN suppliers s ON b.supplier_id = s.id + WHERE b.expiry_date BETWEEN :start AND :end AND b.quantity > 0 + ORDER BY b.expiry_date ASC + LIMIT :limit OFFSET :offset"; + + $stmt = $pdo->prepare($sql); + $stmt->bindValue(':start', $startDate); + $stmt->bindValue(':end', $endDate); + $stmt->bindValue(':limit', $limit, PDO::PARAM_INT); + $stmt->bindValue(':offset', $offset, PDO::PARAM_INT); + $stmt->execute(); + + echo json_encode([ + 'data' => $stmt->fetchAll(PDO::FETCH_ASSOC), + 'total' => $total, + 'page' => $page, + 'limit' => $limit + ]); + + } elseif ($type === 'purchase_report') { + $countSql = "SELECT COUNT(*) FROM pharmacy_lpos WHERE lpo_date BETWEEN ? AND ?"; + $countStmt = $pdo->prepare($countSql); + $countStmt->execute([$startDate, $endDate]); + $total = $countStmt->fetchColumn(); + + $sql = "SELECT l.id, l.lpo_date, l.status, l.total_amount, s.name_en as supplier_name, s.name_ar as supplier_name_ar + FROM pharmacy_lpos l + LEFT JOIN suppliers s ON l.supplier_id = s.id + WHERE l.lpo_date BETWEEN :start AND :end + ORDER BY l.lpo_date DESC + LIMIT :limit OFFSET :offset"; + + $grandTotalSql = "SELECT SUM(total_amount) as total FROM pharmacy_lpos WHERE lpo_date BETWEEN ? AND ?"; + $grandTotalStmt = $pdo->prepare($grandTotalSql); + $grandTotalStmt->execute([$startDate, $endDate]); + $grandTotal = $grandTotalStmt->fetchColumn(); + + $stmt = $pdo->prepare($sql); + $stmt->bindValue(':start', $startDate); + $stmt->bindValue(':end', $endDate); + $stmt->bindValue(':limit', $limit, PDO::PARAM_INT); + $stmt->bindValue(':offset', $offset, PDO::PARAM_INT); + $stmt->execute(); + + echo json_encode([ + 'data' => $stmt->fetchAll(PDO::FETCH_ASSOC), + 'total' => $total, + 'page' => $page, + 'limit' => $limit, + 'grand_total_purchases' => $grandTotal ?? 0 + ]); + } elseif ($type === 'low_stock') { + // Reuse get_low_stock logic + $countSql = "SELECT COUNT(*) FROM ( + SELECT d.id + FROM drugs d + LEFT JOIN pharmacy_batches b ON d.id = b.drug_id AND b.quantity > 0 AND b.expiry_date >= CURDATE() + GROUP BY d.id + HAVING COALESCE(SUM(b.quantity), 0) <= MAX(d.reorder_level) + ) as total"; + $total = $pdo->query($countSql)->fetchColumn(); + + $sql = "SELECT d.id, d.name_en, d.name_ar, d.min_stock_level, d.reorder_level, d.unit, + COALESCE(SUM(b.quantity), 0) as total_stock + FROM drugs d + LEFT JOIN pharmacy_batches b ON d.id = b.drug_id AND b.quantity > 0 AND b.expiry_date >= CURDATE() + GROUP BY d.id + HAVING total_stock <= MAX(d.reorder_level) + ORDER BY total_stock ASC + LIMIT :limit OFFSET :offset"; + + $stmt = $pdo->prepare($sql); + $stmt->bindValue(':limit', $limit, PDO::PARAM_INT); + $stmt->bindValue(':offset', $offset, PDO::PARAM_INT); + $stmt->execute(); + + echo json_encode([ + 'data' => $stmt->fetchAll(PDO::FETCH_ASSOC), + 'total' => $total, + 'page' => $page, + 'limit' => $limit + ]); + } + break; + default: throw new Exception("Invalid action"); } diff --git a/api/pharmacy_lpo.php b/api/pharmacy_lpo.php index 8b2ef75..1818ff3 100644 --- a/api/pharmacy_lpo.php +++ b/api/pharmacy_lpo.php @@ -27,7 +27,7 @@ try { ]); $lpoId = $pdo->lastInsertId(); - $stmtItem = $pdo->prepare("INSERT INTO pharmacy_lpo_items (lpo_id, drug_id, quantity, cost_price, total_cost) VALUES (?, ?, ?, ?, ?)"); + $stmtItem = $pdo->prepare("INSERT INTO pharmacy_lpo_items (lpo_id, drug_id, quantity, cost_price, total_cost, batch_number, expiry_date) VALUES (?, ?, ?, ?, ?, ?, ?)"); foreach ($data['items'] as $item) { $stmtItem->execute([ @@ -35,23 +35,129 @@ try { $item['drug_id'], $item['quantity'], $item['cost_price'], - $item['total_cost'] + $item['total_cost'], + !empty($item['batch_number']) ? $item['batch_number'] : null, + !empty($item['expiry_date']) ? $item['expiry_date'] : null ]); } $pdo->commit(); - echo json_encode(['success' => true, 'message' => 'LPO created successfully']); + echo json_encode(['success' => true, 'message' => 'Purchase created successfully']); } elseif ($action === 'update_status') { $data = json_decode(file_get_contents('php://input'), true); if (empty($data['id']) || empty($data['status'])) { throw new Exception("ID and Status are required"); } + + $pdo->beginTransaction(); + + // Check if items update is requested (specifically for Received status or corrections) + if (!empty($data['items']) && is_array($data['items'])) { + $updateItemStmt = $pdo->prepare("UPDATE pharmacy_lpo_items SET batch_number = ?, expiry_date = ? WHERE id = ?"); + foreach ($data['items'] as $item) { + if (!empty($item['id'])) { + $updateItemStmt->execute([ + !empty($item['batch_number']) ? $item['batch_number'] : null, + !empty($item['expiry_date']) ? $item['expiry_date'] : null, + $item['id'] + ]); + } + } + } + + // If status is being changed to Received, we must update stock + if ($data['status'] === 'Received') { + // Fetch LPO items (re-fetch to get updated values) + $stmtItems = $pdo->prepare("SELECT * FROM pharmacy_lpo_items WHERE lpo_id = ?"); + $stmtItems->execute([$data['id']]); + $items = $stmtItems->fetchAll(PDO::FETCH_ASSOC); + + // Fetch LPO details for supplier + $stmtLPO = $pdo->prepare("SELECT supplier_id FROM pharmacy_lpos WHERE id = ?"); + $stmtLPO->execute([$data['id']]); + $lpo = $stmtLPO->fetch(PDO::FETCH_ASSOC); + + $batchStmt = $pdo->prepare("INSERT INTO pharmacy_batches (drug_id, batch_number, expiry_date, quantity, cost_price, sale_price, supplier_id, received_date) VALUES (?, ?, ?, ?, ?, ?, ?, CURDATE())"); + + // We need sale price for the batch. Ideally, LPO should have it or we fetch current from drugs table. + $drugPriceStmt = $pdo->prepare("SELECT price FROM drugs WHERE id = ?"); + + foreach ($items as $item) { + if (empty($item['batch_number']) || empty($item['expiry_date'])) { + // If still missing (should be caught by UI), generate defaults + $item['batch_number'] = $item['batch_number'] ?? 'BATCH-' . date('Ymd') . '-' . $item['id']; + $item['expiry_date'] = $item['expiry_date'] ?? date('Y-m-d', strtotime('+1 year')); + } + + $drugPriceStmt->execute([$item['drug_id']]); + $drug = $drugPriceStmt->fetch(PDO::FETCH_ASSOC); + $salePrice = $drug['price'] ?? ($item['cost_price'] * 1.5); // Fallback margin + + $batchStmt->execute([ + $item['drug_id'], + $item['batch_number'], + $item['expiry_date'], + $item['quantity'], + $item['cost_price'], + $salePrice, + $lpo['supplier_id'] + ]); + } + } $stmt = $pdo->prepare("UPDATE pharmacy_lpos SET status = ? WHERE id = ?"); $stmt->execute([$data['status'], $data['id']]); + $pdo->commit(); echo json_encode(['success' => true]); + + } elseif ($action === 'create_return') { + $data = json_decode(file_get_contents('php://input'), true); + + if (empty($data['supplier_id']) || empty($data['items'])) { + throw new Exception("Supplier and items are required."); + } + + $pdo->beginTransaction(); + + $stmt = $pdo->prepare("INSERT INTO pharmacy_purchase_returns (supplier_id, return_date, total_amount, reason) VALUES (?, ?, ?, ?)"); + $stmt->execute([ + $data['supplier_id'], + $data['return_date'] ?? date('Y-m-d'), + $data['total_amount'] ?? 0, + $data['reason'] ?? '' + ]); + $returnId = $pdo->lastInsertId(); + + $stmtItem = $pdo->prepare("INSERT INTO pharmacy_purchase_return_items (return_id, drug_id, batch_id, quantity, unit_price, total_price) VALUES (?, ?, ?, ?, ?, ?)"); + $updateBatch = $pdo->prepare("UPDATE pharmacy_batches SET quantity = quantity - ? WHERE id = ?"); + + foreach ($data['items'] as $item) { + // Check stock first + $checkBatch = $pdo->prepare("SELECT quantity FROM pharmacy_batches WHERE id = ?"); + $checkBatch->execute([$item['batch_id']]); + $currentStock = $checkBatch->fetchColumn(); + + if ($currentStock < $item['quantity']) { + throw new Exception("Insufficient stock in batch for drug ID " . $item['drug_id']); + } + + $stmtItem->execute([ + $returnId, + $item['drug_id'], + $item['batch_id'], + $item['quantity'], + $item['unit_price'], + $item['total_price'] + ]); + + // Deduct stock + $updateBatch->execute([$item['quantity'], $item['batch_id']]); + } + + $pdo->commit(); + echo json_encode(['success' => true, 'message' => 'Return created successfully']); } } elseif ($_SERVER['REQUEST_METHOD'] === 'GET') { if ($action === 'get_lpos') { @@ -100,6 +206,70 @@ try { } elseif ($action === 'get_drugs') { $stmt = $pdo->query("SELECT id, name_en, name_ar, sku, price FROM drugs ORDER BY name_en ASC"); echo json_encode($stmt->fetchAll(PDO::FETCH_ASSOC)); + + } elseif ($action === 'get_returns') { + $page = isset($_GET['page']) ? (int)$_GET['page'] : 1; + $limit = isset($_GET['limit']) ? (int)$_GET['limit'] : 20; + $offset = ($page - 1) * $limit; + + $countStmt = $pdo->query("SELECT COUNT(*) FROM pharmacy_purchase_returns"); + $total = $countStmt->fetchColumn(); + + $stmt = $pdo->prepare(" + SELECT r.*, s.name_en as supplier_name + FROM pharmacy_purchase_returns r + LEFT JOIN suppliers s ON r.supplier_id = s.id + ORDER BY r.return_date DESC + LIMIT :limit OFFSET :offset + "); + $stmt->bindValue(':limit', $limit, PDO::PARAM_INT); + $stmt->bindValue(':offset', $offset, PDO::PARAM_INT); + $stmt->execute(); + + echo json_encode([ + 'data' => $stmt->fetchAll(PDO::FETCH_ASSOC), + 'total' => $total, + 'page' => $page, + 'limit' => $limit, + 'pages' => ceil($total / $limit) + ]); + + } elseif ($action === 'get_return_details') { + $id = $_GET['id'] ?? 0; + $stmt = $pdo->prepare(" + SELECT i.*, d.name_en as drug_name, d.sku, b.batch_number + FROM pharmacy_purchase_return_items i + LEFT JOIN drugs d ON i.drug_id = d.id + LEFT JOIN pharmacy_batches b ON i.batch_id = b.id + WHERE i.return_id = ? + "); + $stmt->execute([$id]); + echo json_encode($stmt->fetchAll(PDO::FETCH_ASSOC)); + + } elseif ($action === 'get_supplier_batches') { + // Get batches for a specific supplier (or all if not specified, but usually filtered by drug) + // Ideally: We select a supplier for return, then we select items. + // Better: Select Drug -> Show Batches (maybe filter by supplier if we track supplier_id in batch) + $drug_id = $_GET['drug_id'] ?? 0; + $supplier_id = $_GET['supplier_id'] ?? 0; + + $sql = "SELECT b.id, b.batch_number, b.expiry_date, b.quantity, b.cost_price + FROM pharmacy_batches b + WHERE b.drug_id = ? AND b.quantity > 0"; + $params = [$drug_id]; + + if ($supplier_id) { + // If we want to strictly return only what we bought from this supplier: + // $sql .= " AND b.supplier_id = ?"; + // $params[] = $supplier_id; + // BUT, sometimes we might return to a supplier what we bought elsewhere if they accept it, + // or `supplier_id` in batches might be null for old data. + // Let's NOT strictly enforce supplier_id match for now, just show all batches. + } + + $stmt = $pdo->prepare($sql); + $stmt->execute($params); + echo json_encode($stmt->fetchAll(PDO::FETCH_ASSOC)); } } diff --git a/db/migrations/20260321_create_purchase_returns.sql b/db/migrations/20260321_create_purchase_returns.sql new file mode 100644 index 0000000..bacae25 --- /dev/null +++ b/db/migrations/20260321_create_purchase_returns.sql @@ -0,0 +1,29 @@ +-- Add batch and expiry to LPO items for receiving stock +ALTER TABLE pharmacy_lpo_items ADD COLUMN IF NOT EXISTS batch_number VARCHAR(50) NULL; +ALTER TABLE pharmacy_lpo_items ADD COLUMN IF NOT EXISTS expiry_date DATE NULL; + +-- Create Purchase Returns table +CREATE TABLE IF NOT EXISTS pharmacy_purchase_returns ( + id INT AUTO_INCREMENT PRIMARY KEY, + supplier_id INT NOT NULL, + return_date DATE NOT NULL, + total_amount DECIMAL(10, 2) DEFAULT 0.00, + reason TEXT NULL, + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + FOREIGN KEY (supplier_id) REFERENCES suppliers(id) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; + +-- Create Purchase Return Items table +CREATE TABLE IF NOT EXISTS pharmacy_purchase_return_items ( + id INT AUTO_INCREMENT PRIMARY KEY, + return_id INT NOT NULL, + drug_id INT NOT NULL, + batch_id INT NULL, -- Which batch we are returning from + quantity INT NOT NULL, + unit_price DECIMAL(10, 2) NOT NULL, -- Refund price + total_price DECIMAL(10, 2) NOT NULL, + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + FOREIGN KEY (return_id) REFERENCES pharmacy_purchase_returns(id) ON DELETE CASCADE, + FOREIGN KEY (drug_id) REFERENCES drugs(id), + FOREIGN KEY (batch_id) REFERENCES pharmacy_batches(id) ON DELETE SET NULL +); diff --git a/includes/layout/header.php b/includes/layout/header.php index 394df57..0f7e7af 100644 --- a/includes/layout/header.php +++ b/includes/layout/header.php @@ -131,16 +131,19 @@ $site_favicon = !empty($site_settings['company_favicon']) ? $site_settings['comp - + -