splitting db
This commit is contained in:
parent
c6cb25129c
commit
c5ac8e3c6e
@ -3,6 +3,10 @@ document.addEventListener('DOMContentLoaded', () => {
|
|||||||
const chatInput = document.getElementById('chat-input');
|
const chatInput = document.getElementById('chat-input');
|
||||||
const chatMessages = document.getElementById('chat-messages');
|
const chatMessages = document.getElementById('chat-messages');
|
||||||
|
|
||||||
|
if (!chatForm || !chatInput || !chatMessages) {
|
||||||
|
return; // Not on the chat page
|
||||||
|
}
|
||||||
|
|
||||||
const appendMessage = (text, sender) => {
|
const appendMessage = (text, sender) => {
|
||||||
const msgDiv = document.createElement('div');
|
const msgDiv = document.createElement('div');
|
||||||
msgDiv.classList.add('message', sender);
|
msgDiv.classList.add('message', sender);
|
||||||
|
|||||||
@ -158,9 +158,9 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['delete_status'])) {
|
|||||||
$_SESSION['error'] = 'عذراً، ليس لديك الصلاحية لحذف الإعدادات';
|
$_SESSION['error'] = 'عذراً، ليس لديك الصلاحية لحذف الإعدادات';
|
||||||
} else {
|
} else {
|
||||||
$id = $_POST['status_id'];
|
$id = $_POST['status_id'];
|
||||||
$count = db()->prepare("SELECT COUNT(*) FROM mailbox WHERE status_id = ?");
|
$count = 0; foreach(['inbound_mail', 'outbound_mail', 'internal_mail'] as $t) { $stmt = db()->prepare("SELECT COUNT(*) FROM $t WHERE status_id = ?"); $stmt->execute([$id]); $count += $stmt->fetchColumn(); }
|
||||||
$count->execute([$id]);
|
|
||||||
if ($count->fetchColumn() > 0) {
|
if ($count > 0) {
|
||||||
$_SESSION['error'] = 'لا يمكن حذف هذه الحالة لأنها مستخدمة في بعض السجلات';
|
$_SESSION['error'] = 'لا يمكن حذف هذه الحالة لأنها مستخدمة في بعض السجلات';
|
||||||
} else {
|
} else {
|
||||||
db()->prepare("DELETE FROM mailbox_statuses WHERE id = ?")->execute([$id]);
|
db()->prepare("DELETE FROM mailbox_statuses WHERE id = ?")->execute([$id]);
|
||||||
|
|||||||
@ -22,14 +22,21 @@ function db() {
|
|||||||
*/
|
*/
|
||||||
function generateRefNo($type) {
|
function generateRefNo($type) {
|
||||||
$prefix = 'IN';
|
$prefix = 'IN';
|
||||||
if ($type === 'outbound') $prefix = 'OUT';
|
$table = 'inbound_mail';
|
||||||
if ($type === 'internal') $prefix = 'INT';
|
if ($type === 'outbound') {
|
||||||
|
$prefix = 'OUT';
|
||||||
|
$table = 'outbound_mail';
|
||||||
|
} elseif ($type === 'internal') {
|
||||||
|
$prefix = 'INT';
|
||||||
|
$table = 'internal_mail';
|
||||||
|
}
|
||||||
|
|
||||||
$year = date('Y');
|
$year = date('Y');
|
||||||
$pattern = $prefix . '-' . $year . '-%';
|
$pattern = $prefix . '-' . $year . '-%';
|
||||||
|
|
||||||
$stmt = db()->prepare("SELECT ref_no FROM mailbox WHERE type = ? AND ref_no LIKE ? ORDER BY id DESC LIMIT 1");
|
// Query the specific table for the type
|
||||||
$stmt->execute([$type, $pattern]);
|
$stmt = db()->prepare("SELECT ref_no FROM $table WHERE ref_no LIKE ? ORDER BY id DESC LIMIT 1");
|
||||||
|
$stmt->execute([$pattern]);
|
||||||
$last_ref = $stmt->fetchColumn();
|
$last_ref = $stmt->fetchColumn();
|
||||||
|
|
||||||
$serial = 1;
|
$serial = 1;
|
||||||
|
|||||||
176
db/migrations/015_split_mailbox_tables.sql
Normal file
176
db/migrations/015_split_mailbox_tables.sql
Normal file
@ -0,0 +1,176 @@
|
|||||||
|
-- Migration: Split mailbox into separate tables for each module
|
||||||
|
-- This addresses the architectural concern of having all modules in a single table
|
||||||
|
|
||||||
|
-- 1. Create INBOUND tables
|
||||||
|
CREATE TABLE IF NOT EXISTS inbound_mail (
|
||||||
|
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||||
|
ref_no VARCHAR(50) NOT NULL UNIQUE,
|
||||||
|
date_registered DATE NOT NULL,
|
||||||
|
due_date DATE NULL,
|
||||||
|
sender VARCHAR(255),
|
||||||
|
recipient VARCHAR(255),
|
||||||
|
subject VARCHAR(255) NOT NULL,
|
||||||
|
description TEXT,
|
||||||
|
status_id INT,
|
||||||
|
assigned_to INT,
|
||||||
|
created_by INT,
|
||||||
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||||
|
FOREIGN KEY (assigned_to) REFERENCES users(id) ON DELETE SET NULL,
|
||||||
|
FOREIGN KEY (created_by) REFERENCES users(id) ON DELETE SET NULL
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS inbound_attachments (
|
||||||
|
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||||
|
mail_id INT NOT NULL,
|
||||||
|
display_name VARCHAR(255),
|
||||||
|
file_path VARCHAR(255) NOT NULL,
|
||||||
|
file_name VARCHAR(255) NOT NULL,
|
||||||
|
file_size INT,
|
||||||
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
FOREIGN KEY (mail_id) REFERENCES inbound_mail(id) ON DELETE CASCADE
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS inbound_comments (
|
||||||
|
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||||
|
mail_id INT NOT NULL,
|
||||||
|
user_id INT,
|
||||||
|
comment TEXT NOT NULL,
|
||||||
|
referred_user_id INT DEFAULT NULL,
|
||||||
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
FOREIGN KEY (mail_id) REFERENCES inbound_mail(id) ON DELETE CASCADE,
|
||||||
|
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE SET NULL,
|
||||||
|
FOREIGN KEY (referred_user_id) REFERENCES users(id) ON DELETE SET NULL
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||||
|
|
||||||
|
-- 2. Create OUTBOUND tables
|
||||||
|
CREATE TABLE IF NOT EXISTS outbound_mail (
|
||||||
|
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||||
|
ref_no VARCHAR(50) NOT NULL UNIQUE,
|
||||||
|
date_registered DATE NOT NULL,
|
||||||
|
due_date DATE NULL,
|
||||||
|
sender VARCHAR(255),
|
||||||
|
recipient VARCHAR(255),
|
||||||
|
subject VARCHAR(255) NOT NULL,
|
||||||
|
description TEXT,
|
||||||
|
status_id INT,
|
||||||
|
assigned_to INT,
|
||||||
|
created_by INT,
|
||||||
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||||
|
FOREIGN KEY (assigned_to) REFERENCES users(id) ON DELETE SET NULL,
|
||||||
|
FOREIGN KEY (created_by) REFERENCES users(id) ON DELETE SET NULL
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS outbound_attachments (
|
||||||
|
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||||
|
mail_id INT NOT NULL,
|
||||||
|
display_name VARCHAR(255),
|
||||||
|
file_path VARCHAR(255) NOT NULL,
|
||||||
|
file_name VARCHAR(255) NOT NULL,
|
||||||
|
file_size INT,
|
||||||
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
FOREIGN KEY (mail_id) REFERENCES outbound_mail(id) ON DELETE CASCADE
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS outbound_comments (
|
||||||
|
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||||
|
mail_id INT NOT NULL,
|
||||||
|
user_id INT,
|
||||||
|
comment TEXT NOT NULL,
|
||||||
|
referred_user_id INT DEFAULT NULL,
|
||||||
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
FOREIGN KEY (mail_id) REFERENCES outbound_mail(id) ON DELETE CASCADE,
|
||||||
|
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE SET NULL,
|
||||||
|
FOREIGN KEY (referred_user_id) REFERENCES users(id) ON DELETE SET NULL
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||||
|
|
||||||
|
-- 3. Create INTERNAL tables
|
||||||
|
CREATE TABLE IF NOT EXISTS internal_mail (
|
||||||
|
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||||
|
ref_no VARCHAR(50) NOT NULL UNIQUE,
|
||||||
|
date_registered DATE NOT NULL,
|
||||||
|
due_date DATE NULL,
|
||||||
|
sender VARCHAR(255),
|
||||||
|
recipient VARCHAR(255),
|
||||||
|
subject VARCHAR(255) NOT NULL,
|
||||||
|
description TEXT,
|
||||||
|
status_id INT,
|
||||||
|
assigned_to INT,
|
||||||
|
created_by INT,
|
||||||
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||||
|
FOREIGN KEY (assigned_to) REFERENCES users(id) ON DELETE SET NULL,
|
||||||
|
FOREIGN KEY (created_by) REFERENCES users(id) ON DELETE SET NULL
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS internal_attachments (
|
||||||
|
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||||
|
mail_id INT NOT NULL,
|
||||||
|
display_name VARCHAR(255),
|
||||||
|
file_path VARCHAR(255) NOT NULL,
|
||||||
|
file_name VARCHAR(255) NOT NULL,
|
||||||
|
file_size INT,
|
||||||
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
FOREIGN KEY (mail_id) REFERENCES internal_mail(id) ON DELETE CASCADE
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS internal_comments (
|
||||||
|
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||||
|
mail_id INT NOT NULL,
|
||||||
|
user_id INT,
|
||||||
|
comment TEXT NOT NULL,
|
||||||
|
referred_user_id INT DEFAULT NULL,
|
||||||
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
FOREIGN KEY (mail_id) REFERENCES internal_mail(id) ON DELETE CASCADE,
|
||||||
|
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE SET NULL,
|
||||||
|
FOREIGN KEY (referred_user_id) REFERENCES users(id) ON DELETE SET NULL
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||||
|
|
||||||
|
-- 4. Migrate data from old mailbox table
|
||||||
|
-- We'll use a temporary mapping for IDs if we were strict, but since we are splitting, we can just insert.
|
||||||
|
-- Note: Original IDs will change, which means attachments and comments must be migrated carefully.
|
||||||
|
|
||||||
|
-- Migrate Inbound
|
||||||
|
INSERT INTO inbound_mail (id, ref_no, date_registered, due_date, sender, recipient, subject, description, status_id, assigned_to, created_by, created_at, updated_at)
|
||||||
|
SELECT id, ref_no, date_registered, due_date, sender, recipient, subject, description, status_id, assigned_to, created_by, created_at, updated_at
|
||||||
|
FROM mailbox WHERE type = 'inbound';
|
||||||
|
|
||||||
|
INSERT INTO inbound_attachments (id, mail_id, display_name, file_path, file_name, file_size, created_at)
|
||||||
|
SELECT a.id, a.mail_id, a.display_name, a.file_path, a.file_name, a.file_size, a.created_at
|
||||||
|
FROM attachments a JOIN mailbox m ON a.mail_id = m.id WHERE m.type = 'inbound';
|
||||||
|
|
||||||
|
INSERT INTO inbound_comments (id, mail_id, user_id, comment, referred_user_id, created_at)
|
||||||
|
SELECT c.id, c.mail_id, c.user_id, c.comment, c.referred_user_id, c.created_at
|
||||||
|
FROM comments c JOIN mailbox m ON c.mail_id = m.id WHERE m.type = 'inbound';
|
||||||
|
|
||||||
|
-- Migrate Outbound
|
||||||
|
INSERT INTO outbound_mail (id, ref_no, date_registered, due_date, sender, recipient, subject, description, status_id, assigned_to, created_by, created_at, updated_at)
|
||||||
|
SELECT id, ref_no, date_registered, due_date, sender, recipient, subject, description, status_id, assigned_to, created_by, created_at, updated_at
|
||||||
|
FROM mailbox WHERE type = 'outbound';
|
||||||
|
|
||||||
|
INSERT INTO outbound_attachments (id, mail_id, display_name, file_path, file_name, file_size, created_at)
|
||||||
|
SELECT a.id, a.mail_id, a.display_name, a.file_path, a.file_name, a.file_size, a.created_at
|
||||||
|
FROM attachments a JOIN mailbox m ON a.mail_id = m.id WHERE m.type = 'outbound';
|
||||||
|
|
||||||
|
INSERT INTO outbound_comments (id, mail_id, user_id, comment, referred_user_id, created_at)
|
||||||
|
SELECT c.id, c.mail_id, c.user_id, c.comment, c.referred_user_id, c.created_at
|
||||||
|
FROM comments c JOIN mailbox m ON c.mail_id = m.id WHERE m.type = 'outbound';
|
||||||
|
|
||||||
|
-- Migrate Internal
|
||||||
|
INSERT INTO internal_mail (id, ref_no, date_registered, due_date, sender, recipient, subject, description, status_id, assigned_to, created_by, created_at, updated_at)
|
||||||
|
SELECT id, ref_no, date_registered, due_date, sender, recipient, subject, description, status_id, assigned_to, created_by, created_at, updated_at
|
||||||
|
FROM mailbox WHERE type = 'internal';
|
||||||
|
|
||||||
|
INSERT INTO internal_attachments (id, mail_id, display_name, file_path, file_name, file_size, created_at)
|
||||||
|
SELECT a.id, a.mail_id, a.display_name, a.file_path, a.file_name, a.file_size, a.created_at
|
||||||
|
FROM attachments a JOIN mailbox m ON a.mail_id = m.id WHERE m.type = 'internal';
|
||||||
|
|
||||||
|
INSERT INTO internal_comments (id, mail_id, user_id, comment, referred_user_id, created_at)
|
||||||
|
SELECT c.id, c.mail_id, c.user_id, c.comment, c.referred_user_id, c.created_at
|
||||||
|
FROM comments c JOIN mailbox m ON c.mail_id = m.id WHERE m.type = 'internal';
|
||||||
|
|
||||||
|
-- 5. Rename old tables instead of dropping for safety
|
||||||
|
RENAME TABLE mailbox TO mailbox_old;
|
||||||
|
RENAME TABLE attachments TO attachments_old;
|
||||||
|
RENAME TABLE comments TO comments_old;
|
||||||
20
inbound.php
20
inbound.php
@ -74,8 +74,8 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
|||||||
try {
|
try {
|
||||||
db()->beginTransaction();
|
db()->beginTransaction();
|
||||||
if ($action === 'add') {
|
if ($action === 'add') {
|
||||||
$stmt = db()->prepare("INSERT INTO mailbox (type, ref_no, date_registered, due_date, sender, recipient, subject, description, status_id, assigned_to, created_by) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)");
|
$stmt = db()->prepare("INSERT INTO inbound_mail (ref_no, date_registered, due_date, sender, recipient, subject, description, status_id, assigned_to, created_by) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)");
|
||||||
$stmt->execute([$type, $ref_no, $date_registered, $due_date, $sender, $recipient, $subject, $description, $status_id, $assigned_to, $user_id]);
|
$stmt->execute([$ref_no, $date_registered, $due_date, $sender, $recipient, $subject, $description, $status_id, $assigned_to, $user_id]);
|
||||||
$mail_id = db()->lastInsertId();
|
$mail_id = db()->lastInsertId();
|
||||||
|
|
||||||
if ($assigned_to) {
|
if ($assigned_to) {
|
||||||
@ -86,11 +86,11 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
|||||||
} elseif ($action === 'edit') {
|
} elseif ($action === 'edit') {
|
||||||
$mail_id = $id;
|
$mail_id = $id;
|
||||||
// Get previous assigned_to to check if it changed
|
// Get previous assigned_to to check if it changed
|
||||||
$stmt_old = db()->prepare("SELECT assigned_to FROM mailbox WHERE id = ?");
|
$stmt_old = db()->prepare("SELECT assigned_to FROM inbound_mail WHERE id = ?");
|
||||||
$stmt_old->execute([$id]);
|
$stmt_old->execute([$id]);
|
||||||
$old_assigned_to = $stmt_old->fetchColumn();
|
$old_assigned_to = $stmt_old->fetchColumn();
|
||||||
|
|
||||||
$stmt = db()->prepare("UPDATE mailbox SET ref_no = ?, date_registered = ?, due_date = ?, sender = ?, recipient = ?, subject = ?, description = ?, status_id = ?, assigned_to = ? WHERE id = ? AND type = 'inbound'");
|
$stmt = db()->prepare("UPDATE inbound_mail SET ref_no = ?, date_registered = ?, due_date = ?, sender = ?, recipient = ?, subject = ?, description = ?, status_id = ?, assigned_to = ? WHERE id = ? ");
|
||||||
$stmt->execute([$ref_no, $date_registered, $due_date, $sender, $recipient, $subject, $description, $status_id, $assigned_to, $id]);
|
$stmt->execute([$ref_no, $date_registered, $due_date, $sender, $recipient, $subject, $description, $status_id, $assigned_to, $id]);
|
||||||
|
|
||||||
if ($assigned_to && $assigned_to != $old_assigned_to) {
|
if ($assigned_to && $assigned_to != $old_assigned_to) {
|
||||||
@ -110,7 +110,7 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
|||||||
$file_name = time() . '_' . basename($name);
|
$file_name = time() . '_' . basename($name);
|
||||||
$target_path = $upload_dir . $file_name;
|
$target_path = $upload_dir . $file_name;
|
||||||
if (move_uploaded_file($_FILES['attachments']['tmp_name'][$key], $target_path)) {
|
if (move_uploaded_file($_FILES['attachments']['tmp_name'][$key], $target_path)) {
|
||||||
$stmt = db()->prepare("INSERT INTO attachments (mail_id, display_name, file_path, file_name, file_size) VALUES (?, ?, ?, ?, ?)");
|
$stmt = db()->prepare("INSERT INTO inbound_attachments (mail_id, display_name, file_path, file_name, file_size) VALUES (?, ?, ?, ?, ?)");
|
||||||
$stmt->execute([$mail_id, $name, $target_path, $name, $_FILES['attachments']['size'][$key]]);
|
$stmt->execute([$mail_id, $name, $target_path, $name, $_FILES['attachments']['size'][$key]]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -145,7 +145,7 @@ if (isset($_GET['action']) && $_GET['action'] === 'delete' && isset($_GET['id'])
|
|||||||
$error = 'عذراً، ليس لديك الصلاحية لحذف السجلات';
|
$error = 'عذراً، ليس لديك الصلاحية لحذف السجلات';
|
||||||
} else {
|
} else {
|
||||||
$id = $_GET['id'];
|
$id = $_GET['id'];
|
||||||
$stmt = db()->prepare("DELETE FROM mailbox WHERE id = ? AND type = 'inbound'");
|
$stmt = db()->prepare("DELETE FROM inbound_mail WHERE id = ? ");
|
||||||
$stmt->execute([$id]);
|
$stmt->execute([$id]);
|
||||||
$_SESSION['success'] = 'تم حذف البريد بنجاح';
|
$_SESSION['success'] = 'تم حذف البريد بنجاح';
|
||||||
redirect('inbound.php');
|
redirect('inbound.php');
|
||||||
@ -189,7 +189,7 @@ if ($my_tasks) {
|
|||||||
$where_sql = implode(" AND ", $where_clauses);
|
$where_sql = implode(" AND ", $where_clauses);
|
||||||
|
|
||||||
// Get total records for pagination
|
// Get total records for pagination
|
||||||
$count_query = "SELECT COUNT(*) FROM mailbox m WHERE $where_sql";
|
$count_query = "SELECT COUNT(*) FROM inbound_mail m WHERE $where_sql";
|
||||||
$stmt_count = db()->prepare($count_query);
|
$stmt_count = db()->prepare($count_query);
|
||||||
$stmt_count->execute($params);
|
$stmt_count->execute($params);
|
||||||
$total_records = $stmt_count->fetchColumn();
|
$total_records = $stmt_count->fetchColumn();
|
||||||
@ -197,7 +197,7 @@ $total_pages = ceil($total_records / $limit);
|
|||||||
|
|
||||||
// Fetch paginated results
|
// Fetch paginated results
|
||||||
$query = "SELECT m.*, s.name as status_name, s.color as status_color, u.full_name as assigned_to_name
|
$query = "SELECT m.*, s.name as status_name, s.color as status_color, u.full_name as assigned_to_name
|
||||||
FROM mailbox m
|
FROM inbound_mail m
|
||||||
LEFT JOIN mailbox_statuses s ON m.status_id = s.id
|
LEFT JOIN mailbox_statuses s ON m.status_id = s.id
|
||||||
LEFT JOIN users u ON m.assigned_to = u.id
|
LEFT JOIN users u ON m.assigned_to = u.id
|
||||||
WHERE $where_sql
|
WHERE $where_sql
|
||||||
@ -214,7 +214,7 @@ $users_list = db()->query("SELECT id, full_name FROM users ORDER BY full_name")-
|
|||||||
$deepLinkData = null;
|
$deepLinkData = null;
|
||||||
if (isset($_GET['action']) && $_GET['action'] === 'edit' && isset($_GET['id'])) {
|
if (isset($_GET['action']) && $_GET['action'] === 'edit' && isset($_GET['id'])) {
|
||||||
if (canEdit('inbound')) {
|
if (canEdit('inbound')) {
|
||||||
$stmt = db()->prepare("SELECT * FROM mailbox WHERE id = ? AND type = 'inbound'");
|
$stmt = db()->prepare("SELECT * FROM inbound_mail WHERE id = ? ");
|
||||||
$stmt->execute([$_GET['id']]);
|
$stmt->execute([$_GET['id']]);
|
||||||
$deepLinkData = $stmt->fetch();
|
$deepLinkData = $stmt->fetch();
|
||||||
}
|
}
|
||||||
@ -415,7 +415,7 @@ function getStatusBadgeInList($mail) {
|
|||||||
</div>
|
</div>
|
||||||
<div class="col-12">
|
<div class="col-12">
|
||||||
<label class="form-label fw-bold">المرفقات</label>
|
<label class="form-label fw-bold">المرفقات</label>
|
||||||
<input type="file" name="attachments[]" class="form-control" multiple>
|
<input type="file" name="inbound_attachments[]" class="form-control" multiple>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-md-6">
|
<div class="col-md-6">
|
||||||
<label class="form-label fw-bold">الحالة</label>
|
<label class="form-label fw-bold">الحالة</label>
|
||||||
|
|||||||
112
index.php
112
index.php
@ -9,14 +9,13 @@ if (!isAdmin()) {
|
|||||||
$user_id = $_SESSION['user_id'];
|
$user_id = $_SESSION['user_id'];
|
||||||
$is_admin = isAdmin();
|
$is_admin = isAdmin();
|
||||||
|
|
||||||
// Stats
|
// Stats - Total counts from separate tables
|
||||||
$total_inbound = canView('inbound') ? db()->query("SELECT COUNT(*) FROM mailbox WHERE type = 'inbound'")->fetchColumn() : 0;
|
$total_inbound = canView('inbound') ? db()->query("SELECT COUNT(*) FROM inbound_mail")->fetchColumn() : 0;
|
||||||
$total_outbound = canView('outbound') ? db()->query("SELECT COUNT(*) FROM mailbox WHERE type = 'outbound'")->fetchColumn() : 0;
|
$total_outbound = canView('outbound') ? db()->query("SELECT COUNT(*) FROM outbound_mail")->fetchColumn() : 0;
|
||||||
|
|
||||||
// Fetch statuses for badge and count
|
// Fetch statuses for badge and count
|
||||||
$statuses_data = db()->query("SELECT * FROM mailbox_statuses")->fetchAll(PDO::FETCH_UNIQUE);
|
$statuses_data = db()->query("SELECT * FROM mailbox_statuses")->fetchAll(PDO::FETCH_UNIQUE);
|
||||||
|
|
||||||
// For the "In Progress" stat card, we might need a specific status or just a sum of non-closed statuses.
|
|
||||||
$in_progress_id = null;
|
$in_progress_id = null;
|
||||||
foreach ($statuses_data as $id => $s) {
|
foreach ($statuses_data as $id => $s) {
|
||||||
if ($s['name'] == 'in_progress') {
|
if ($s['name'] == 'in_progress') {
|
||||||
@ -24,68 +23,83 @@ foreach ($statuses_data as $id => $s) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$in_progress_count = 0;
|
$in_progress_count = 0;
|
||||||
if ($in_progress_id) {
|
if ($in_progress_id) {
|
||||||
$where_types = [];
|
if (canView('inbound')) {
|
||||||
if (canView('inbound')) $where_types[] = "'inbound'";
|
$in_progress_count += db()->prepare("SELECT COUNT(*) FROM inbound_mail WHERE status_id = ?")->execute([$in_progress_id]) ? db()->prepare("SELECT COUNT(*) FROM inbound_mail WHERE status_id = ?")->execute([$in_progress_id]) : 0;
|
||||||
if (canView('outbound')) $where_types[] = "'outbound'";
|
// Wait, execute returns bool.
|
||||||
|
$stmt = db()->prepare("SELECT COUNT(*) FROM inbound_mail WHERE status_id = ?");
|
||||||
if (!empty($where_types)) {
|
|
||||||
$types_sql = implode(',', $where_types);
|
|
||||||
$stmt = db()->prepare("SELECT COUNT(*) FROM mailbox WHERE status_id = ? AND type IN ($types_sql)");
|
|
||||||
$stmt->execute([$in_progress_id]);
|
$stmt->execute([$in_progress_id]);
|
||||||
$in_progress_count = $stmt->fetchColumn();
|
$in_progress_count += $stmt->fetchColumn();
|
||||||
|
}
|
||||||
|
if (canView('outbound')) {
|
||||||
|
$stmt = db()->prepare("SELECT COUNT(*) FROM outbound_mail WHERE status_id = ?");
|
||||||
|
$stmt->execute([$in_progress_id]);
|
||||||
|
$in_progress_count += $stmt->fetchColumn();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// My Assignments
|
// My Assignments - Combine from all tables
|
||||||
$my_assignments = [];
|
$my_assignments = [];
|
||||||
$assignment_types = [];
|
$queries = [];
|
||||||
if (canView('inbound')) $assignment_types[] = "'inbound'";
|
if (canView('inbound')) {
|
||||||
if (canView('outbound')) $assignment_types[] = "'outbound'";
|
$queries[] = "SELECT id, 'inbound' as type, ref_no, subject, due_date, status_id, created_at FROM inbound_mail WHERE assigned_to = $user_id";
|
||||||
if (canView('internal')) $assignment_types[] = "'internal'";
|
}
|
||||||
|
if (canView('outbound')) {
|
||||||
|
$queries[] = "SELECT id, 'outbound' as type, ref_no, subject, due_date, status_id, created_at FROM outbound_mail WHERE assigned_to = $user_id";
|
||||||
|
}
|
||||||
|
if (canView('internal')) {
|
||||||
|
$queries[] = "SELECT id, 'internal' as type, ref_no, subject, due_date, status_id, created_at FROM internal_mail WHERE assigned_to = $user_id";
|
||||||
|
}
|
||||||
|
|
||||||
if (!empty($assignment_types)) {
|
if (!empty($queries)) {
|
||||||
$types_sql = implode(',', $assignment_types);
|
$full_query = "(" . implode(") UNION ALL (", $queries) . ") ORDER BY created_at DESC LIMIT 5";
|
||||||
$my_assignments = db()->prepare("SELECT m.*, s.name as status_name, s.color as status_color
|
$stmt = db()->query($full_query);
|
||||||
FROM mailbox m
|
$my_assignments = $stmt->fetchAll();
|
||||||
LEFT JOIN mailbox_statuses s ON m.status_id = s.id
|
|
||||||
WHERE m.assigned_to = ? AND m.type IN ($types_sql)
|
// Add status info to assignments
|
||||||
ORDER BY m.created_at DESC LIMIT 5");
|
foreach ($my_assignments as &$m) {
|
||||||
$my_assignments->execute([$user_id]);
|
$m['status_name'] = $statuses_data[$m['status_id']]['name'] ?? 'unknown';
|
||||||
$my_assignments = $my_assignments->fetchAll();
|
$m['status_color'] = $statuses_data[$m['status_id']]['color'] ?? '#6c757d';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Recent Mail (Global for Admin/Clerk, otherwise limited)
|
// Recent Mail (Global for Admin/Clerk, otherwise limited)
|
||||||
$recent_mail = [];
|
$recent_mail = [];
|
||||||
$recent_types = [];
|
$recent_queries = [];
|
||||||
if (canView('inbound')) $recent_types[] = "'inbound'";
|
if (canView('inbound')) {
|
||||||
if (canView('outbound')) $recent_types[] = "'outbound'";
|
$recent_queries[] = "SELECT m.id, 'inbound' as type, m.ref_no, m.subject, m.due_date, m.sender, m.recipient, m.status_id, m.assigned_to, m.created_by, m.date_registered, m.created_at, u.full_name as assigned_to_name
|
||||||
|
FROM inbound_mail m LEFT JOIN users u ON m.assigned_to = u.id";
|
||||||
|
}
|
||||||
|
if (canView('outbound')) {
|
||||||
|
$recent_queries[] = "SELECT m.id, 'outbound' as type, m.ref_no, m.subject, m.due_date, m.sender, m.recipient, m.status_id, m.assigned_to, m.created_by, m.date_registered, m.created_at, u.full_name as assigned_to_name
|
||||||
|
FROM outbound_mail m LEFT JOIN users u ON m.assigned_to = u.id";
|
||||||
|
}
|
||||||
|
|
||||||
if (!empty($recent_types)) {
|
if (!empty($recent_queries)) {
|
||||||
$types_sql = implode(',', $recent_types);
|
$full_recent_query = "(" . implode(") UNION ALL (", $recent_queries) . ")";
|
||||||
$recent_mail_query = "SELECT m.*, s.name as status_name, s.color as status_color, u.full_name as assigned_to_name
|
|
||||||
FROM mailbox m
|
|
||||||
LEFT JOIN mailbox_statuses s ON m.status_id = s.id
|
|
||||||
LEFT JOIN users u ON m.assigned_to = u.id
|
|
||||||
WHERE m.type IN ($types_sql)";
|
|
||||||
|
|
||||||
if (!$is_admin && ($_SESSION['user_role'] ?? '') !== 'clerk') {
|
if (!$is_admin && ($_SESSION['user_role'] ?? '') !== 'clerk') {
|
||||||
$recent_mail_query .= " AND (m.assigned_to = ? OR m.created_by = ?)";
|
$full_recent_query = "SELECT * FROM ($full_recent_query) AS combined WHERE assigned_to = $user_id OR created_by = $user_id ORDER BY created_at DESC LIMIT 10";
|
||||||
$recent_stmt = db()->prepare($recent_mail_query . " ORDER BY m.created_at DESC LIMIT 10");
|
|
||||||
$recent_stmt->execute([$user_id, $user_id]);
|
|
||||||
} else {
|
} else {
|
||||||
$recent_stmt = db()->prepare($recent_mail_query . " ORDER BY m.created_at DESC LIMIT 10");
|
$full_recent_query = "SELECT * FROM ($full_recent_query) AS combined ORDER BY created_at DESC LIMIT 10";
|
||||||
$recent_stmt->execute();
|
}
|
||||||
|
|
||||||
|
$stmt = db()->query($full_recent_query);
|
||||||
|
$recent_mail = $stmt->fetchAll();
|
||||||
|
|
||||||
|
// Add status info
|
||||||
|
foreach ($recent_mail as &$m) {
|
||||||
|
$m['status_name'] = $statuses_data[$m['status_id']]['name'] ?? 'unknown';
|
||||||
|
$m['status_color'] = $statuses_data[$m['status_id']]['color'] ?? '#6c757d';
|
||||||
}
|
}
|
||||||
$recent_mail = $recent_stmt->fetchAll();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function getStatusBadge($mail) {
|
function getStatusBadge($mail) {
|
||||||
$status_name = $mail['status_name'] ?? 'غير معروف';
|
$status_name = $mail['status_name'] ?? 'غير معروف';
|
||||||
$status_color = $mail['status_color'] ?? '#6c757d';
|
$status_color = $mail['status_color'] ?? '#6c757d';
|
||||||
|
|
||||||
// Translation for default statuses
|
|
||||||
$display_name = $status_name;
|
$display_name = $status_name;
|
||||||
if ($status_name == 'received') $display_name = 'تم الاستلام';
|
if ($status_name == 'received') $display_name = 'تم الاستلام';
|
||||||
if ($status_name == 'in_progress') $display_name = 'قيد المعالجة';
|
if ($status_name == 'in_progress') $display_name = 'قيد المعالجة';
|
||||||
@ -106,7 +120,7 @@ function getStatusBadge($mail) {
|
|||||||
<a href="inbound.php?action=add" class="btn btn-sm btn-outline-primary">إضافة بريد وارد</a>
|
<a href="inbound.php?action=add" class="btn btn-sm btn-outline-primary">إضافة بريد وارد</a>
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
<?php if (canAdd('outbound')): ?>
|
<?php if (canAdd('outbound')): ?>
|
||||||
<a href="outbound.php" class="btn btn-sm btn-outline-secondary">إضافة بريد صادر</a>
|
<a href="outbound.php?action=add" class="btn btn-sm btn-outline-secondary">إضافة بريد صادر</a>
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -115,7 +129,11 @@ function getStatusBadge($mail) {
|
|||||||
<!-- Overdue Alert -->
|
<!-- Overdue Alert -->
|
||||||
<?php
|
<?php
|
||||||
if (canView('reports')):
|
if (canView('reports')):
|
||||||
$overdue_count = db()->query("SELECT COUNT(*) FROM mailbox WHERE due_date < CURDATE() AND status_id IN (SELECT id FROM mailbox_statuses WHERE name != 'closed') AND type != 'internal'")->fetchColumn();
|
// Combine overdue counts from inbound and outbound
|
||||||
|
$overdue_count = 0;
|
||||||
|
$overdue_count += db()->query("SELECT COUNT(*) FROM inbound_mail WHERE due_date < CURDATE() AND status_id IN (SELECT id FROM mailbox_statuses WHERE name != 'closed')")->fetchColumn();
|
||||||
|
$overdue_count += db()->query("SELECT COUNT(*) FROM outbound_mail WHERE due_date < CURDATE() AND status_id IN (SELECT id FROM mailbox_statuses WHERE name != 'closed')")->fetchColumn();
|
||||||
|
|
||||||
if ($overdue_count > 0):
|
if ($overdue_count > 0):
|
||||||
?>
|
?>
|
||||||
<div class="row mb-4">
|
<div class="row mb-4">
|
||||||
@ -215,7 +233,7 @@ endif;
|
|||||||
<table class="table table-hover align-middle mb-0">
|
<table class="table table-hover align-middle mb-0">
|
||||||
<tbody>
|
<tbody>
|
||||||
<?php foreach ($my_assignments as $mail): ?>
|
<?php foreach ($my_assignments as $mail): ?>
|
||||||
<tr style="cursor: pointer;" onclick="window.location='view_mail.php?id=<?= $mail['id'] ?>'">
|
<tr style="cursor: pointer;" onclick="window.location='view_mail.php?id=<?= $mail['id'] ?>&type=<?= $mail['type'] ?>'">
|
||||||
<td class="ps-4" width="120">
|
<td class="ps-4" width="120">
|
||||||
<small class="text-muted d-block">رقم القيد</small>
|
<small class="text-muted d-block">رقم القيد</small>
|
||||||
<span class="fw-bold text-primary"><?= $mail['ref_no'] ?></span>
|
<span class="fw-bold text-primary"><?= $mail['ref_no'] ?></span>
|
||||||
@ -276,7 +294,7 @@ endif;
|
|||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
<?php foreach ($recent_mail as $mail): ?>
|
<?php foreach ($recent_mail as $mail): ?>
|
||||||
<tr style="cursor: pointer;" onclick="window.location='view_mail.php?id=<?= $mail['id'] ?>'">
|
<tr style="cursor: pointer;" onclick="window.location='view_mail.php?id=<?= $mail['id'] ?>&type=<?= $mail['type'] ?>'">
|
||||||
<td class="ps-4 fw-bold text-primary"><?= $mail['ref_no'] ?></td>
|
<td class="ps-4 fw-bold text-primary"><?= $mail['ref_no'] ?></td>
|
||||||
<td>
|
<td>
|
||||||
<?php if ($mail['type'] == 'inbound'): ?>
|
<?php if ($mail['type'] == 'inbound'): ?>
|
||||||
|
|||||||
@ -27,14 +27,14 @@ if ($search) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Get total for pagination
|
// Get total for pagination
|
||||||
$count_stmt = db()->prepare("SELECT COUNT(*) FROM mailbox m LEFT JOIN users u_sender ON m.created_by = u_sender.id WHERE $where");
|
$count_stmt = db()->prepare("SELECT COUNT(*) FROM internal_mail m LEFT JOIN users u_sender ON m.created_by = u_sender.id WHERE $where");
|
||||||
$count_stmt->execute($params);
|
$count_stmt->execute($params);
|
||||||
$total_records = $count_stmt->fetchColumn();
|
$total_records = $count_stmt->fetchColumn();
|
||||||
$total_pages = ceil($total_records / $limit);
|
$total_pages = ceil($total_records / $limit);
|
||||||
|
|
||||||
// Fetch messages
|
// Fetch messages
|
||||||
$query = "SELECT m.*, u_sender.full_name as sender_name, u_sender.profile_image as sender_image, s.name as status_name, s.color as status_color
|
$query = "SELECT m.*, u_sender.full_name as sender_name, u_sender.profile_image as sender_image, s.name as status_name, s.color as status_color
|
||||||
FROM mailbox m
|
FROM internal_mail m
|
||||||
LEFT JOIN users u_sender ON m.created_by = u_sender.id
|
LEFT JOIN users u_sender ON m.created_by = u_sender.id
|
||||||
LEFT JOIN mailbox_statuses s ON m.status_id = s.id
|
LEFT JOIN mailbox_statuses s ON m.status_id = s.id
|
||||||
WHERE $where
|
WHERE $where
|
||||||
|
|||||||
@ -28,8 +28,8 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['action']) && $_POST['
|
|||||||
$recipient_email = '';
|
$recipient_email = '';
|
||||||
try {
|
try {
|
||||||
db()->beginTransaction();
|
db()->beginTransaction();
|
||||||
$stmt = db()->prepare("INSERT INTO mailbox (type, ref_no, date_registered, subject, description, status_id, assigned_to, created_by) VALUES (?, ?, ?, ?, ?, ?, ?, ?)");
|
$stmt = db()->prepare("INSERT INTO internal_mail (ref_no, date_registered, subject, description, status_id, assigned_to, created_by) VALUES (?, ?, ?, ?, ?, ?, ?)");
|
||||||
$stmt->execute([$type, $ref_no, $date_registered, $subject, $description, $default_status_id, $recipient_id, $user_id]);
|
$stmt->execute([$ref_no, $date_registered, $subject, $description, $default_status_id, $recipient_id, $user_id]);
|
||||||
$mail_id = db()->lastInsertId();
|
$mail_id = db()->lastInsertId();
|
||||||
|
|
||||||
// Handle Attachments
|
// Handle Attachments
|
||||||
@ -42,7 +42,7 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['action']) && $_POST['
|
|||||||
$file_name = time() . '_' . basename($name);
|
$file_name = time() . '_' . basename($name);
|
||||||
$target_path = $upload_dir . $file_name;
|
$target_path = $upload_dir . $file_name;
|
||||||
if (move_uploaded_file($_FILES['attachments']['tmp_name'][$key], $target_path)) {
|
if (move_uploaded_file($_FILES['attachments']['tmp_name'][$key], $target_path)) {
|
||||||
$stmt = db()->prepare("INSERT INTO attachments (mail_id, display_name, file_path, file_name, file_size) VALUES (?, ?, ?, ?, ?)");
|
$stmt = db()->prepare("INSERT INTO internal_attachments (mail_id, display_name, file_path, file_name, file_size) VALUES (?, ?, ?, ?, ?)");
|
||||||
$stmt->execute([$mail_id, $name, $target_path, $name, $_FILES['attachments']['size'][$key]]);
|
$stmt->execute([$mail_id, $name, $target_path, $name, $_FILES['attachments']['size'][$key]]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -117,14 +117,14 @@ if ($search) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Get total for pagination
|
// Get total for pagination
|
||||||
$count_stmt = db()->prepare("SELECT COUNT(*) FROM mailbox m LEFT JOIN users u_recp ON m.assigned_to = u_recp.id WHERE $where");
|
$count_stmt = db()->prepare("SELECT COUNT(*) FROM internal_mail m LEFT JOIN users u_recp ON m.assigned_to = u_recp.id WHERE $where");
|
||||||
$count_stmt->execute($params);
|
$count_stmt->execute($params);
|
||||||
$total_records = $count_stmt->fetchColumn();
|
$total_records = $count_stmt->fetchColumn();
|
||||||
$total_pages = ceil($total_records / $limit);
|
$total_pages = ceil($total_records / $limit);
|
||||||
|
|
||||||
// Fetch messages
|
// Fetch messages
|
||||||
$query = "SELECT m.*, u_recp.full_name as recipient_name, u_recp.profile_image as recipient_image, s.name as status_name, s.color as status_color
|
$query = "SELECT m.*, u_recp.full_name as recipient_name, u_recp.profile_image as recipient_image, s.name as status_name, s.color as status_color
|
||||||
FROM mailbox m
|
FROM internal_mail m
|
||||||
LEFT JOIN users u_recp ON m.assigned_to = u_recp.id
|
LEFT JOIN users u_recp ON m.assigned_to = u_recp.id
|
||||||
LEFT JOIN mailbox_statuses s ON m.status_id = s.id
|
LEFT JOIN mailbox_statuses s ON m.status_id = s.id
|
||||||
WHERE $where
|
WHERE $where
|
||||||
@ -296,7 +296,7 @@ function getStatusBadgeInternal($mail) {
|
|||||||
</div>
|
</div>
|
||||||
<div class="col-md-12">
|
<div class="col-md-12">
|
||||||
<label class="form-label fw-bold">المرفقات</label>
|
<label class="form-label fw-bold">المرفقات</label>
|
||||||
<input type="file" name="attachments[]" class="form-control border-2" multiple>
|
<input type="file" name="internal_attachments[]" class="form-control border-2" multiple>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
20
outbound.php
20
outbound.php
@ -86,8 +86,8 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
|||||||
try {
|
try {
|
||||||
db()->beginTransaction();
|
db()->beginTransaction();
|
||||||
if ($action === 'add') {
|
if ($action === 'add') {
|
||||||
$stmt = db()->prepare("INSERT INTO mailbox (type, ref_no, date_registered, due_date, sender, recipient, subject, description, status_id, assigned_to, created_by) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)");
|
$stmt = db()->prepare("INSERT INTO outbound_mail (ref_no, date_registered, due_date, sender, recipient, subject, description, status_id, assigned_to, created_by) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)");
|
||||||
$stmt->execute([$type, $ref_no, $date_registered, $due_date, $sender, $recipient, $subject, $description, $status_id, $assigned_to, $user_id]);
|
$stmt->execute([$$ref_no, $date_registered, $due_date, $sender, $recipient, $subject, $description, $status_id, $assigned_to, $user_id]);
|
||||||
$mail_id = db()->lastInsertId();
|
$mail_id = db()->lastInsertId();
|
||||||
|
|
||||||
if ($assigned_to) {
|
if ($assigned_to) {
|
||||||
@ -99,11 +99,11 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
|||||||
$mail_id = $id;
|
$mail_id = $id;
|
||||||
|
|
||||||
// Get previous assigned_to to check if it changed
|
// Get previous assigned_to to check if it changed
|
||||||
$stmt_old = db()->prepare("SELECT assigned_to FROM mailbox WHERE id = ?");
|
$stmt_old = db()->prepare("SELECT assigned_to FROM outbound_mail WHERE id = ?");
|
||||||
$stmt_old->execute([$id]);
|
$stmt_old->execute([$id]);
|
||||||
$old_assigned_to = $stmt_old->fetchColumn();
|
$old_assigned_to = $stmt_old->fetchColumn();
|
||||||
|
|
||||||
$stmt = db()->prepare("UPDATE mailbox SET ref_no = ?, date_registered = ?, due_date = ?, sender = ?, recipient = ?, subject = ?, description = ?, status_id = ?, assigned_to = ? WHERE id = ? AND type = 'outbound'");
|
$stmt = db()->prepare("UPDATE outbound_mail SET ref_no = ?, date_registered = ?, due_date = ?, sender = ?, recipient = ?, subject = ?, description = ?, status_id = ?, assigned_to = ? WHERE id = ? ");
|
||||||
$stmt->execute([$ref_no, $date_registered, $due_date, $sender, $recipient, $subject, $description, $status_id, $assigned_to, $mail_id]);
|
$stmt->execute([$ref_no, $date_registered, $due_date, $sender, $recipient, $subject, $description, $status_id, $assigned_to, $mail_id]);
|
||||||
|
|
||||||
if ($assigned_to && $assigned_to != $old_assigned_to) {
|
if ($assigned_to && $assigned_to != $old_assigned_to) {
|
||||||
@ -123,7 +123,7 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
|||||||
$file_name = time() . '_' . basename($name);
|
$file_name = time() . '_' . basename($name);
|
||||||
$target_path = $upload_dir . $file_name;
|
$target_path = $upload_dir . $file_name;
|
||||||
if (move_uploaded_file($_FILES['attachments']['tmp_name'][$key], $target_path)) {
|
if (move_uploaded_file($_FILES['attachments']['tmp_name'][$key], $target_path)) {
|
||||||
$stmt = db()->prepare("INSERT INTO attachments (mail_id, display_name, file_path, file_name, file_size) VALUES (?, ?, ?, ?, ?)");
|
$stmt = db()->prepare("INSERT INTO outbound_attachments (mail_id, display_name, file_path, file_name, file_size) VALUES (?, ?, ?, ?, ?)");
|
||||||
$stmt->execute([$mail_id, $name, $target_path, $name, $_FILES['attachments']['size'][$key]]);
|
$stmt->execute([$mail_id, $name, $target_path, $name, $_FILES['attachments']['size'][$key]]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -158,7 +158,7 @@ if (isset($_GET['action']) && $_GET['action'] === 'delete' && isset($_GET['id'])
|
|||||||
$error = 'عذراً، ليس لديك الصلاحية لحذف السجلات';
|
$error = 'عذراً، ليس لديك الصلاحية لحذف السجلات';
|
||||||
} else {
|
} else {
|
||||||
$id = $_GET['id'];
|
$id = $_GET['id'];
|
||||||
$stmt = db()->prepare("DELETE FROM mailbox WHERE id = ? AND type = 'outbound'");
|
$stmt = db()->prepare("DELETE FROM outbound_mail WHERE id = ? ");
|
||||||
$stmt->execute([$id]);
|
$stmt->execute([$id]);
|
||||||
$_SESSION['success'] = 'تم حذف البريد بنجاح';
|
$_SESSION['success'] = 'تم حذف البريد بنجاح';
|
||||||
redirect('outbound.php');
|
redirect('outbound.php');
|
||||||
@ -202,7 +202,7 @@ if ($my_tasks) {
|
|||||||
$where_sql = implode(" AND ", $where_clauses);
|
$where_sql = implode(" AND ", $where_clauses);
|
||||||
|
|
||||||
// Get total records for pagination
|
// Get total records for pagination
|
||||||
$count_query = "SELECT COUNT(*) FROM mailbox m WHERE $where_sql";
|
$count_query = "SELECT COUNT(*) FROM outbound_mail m WHERE $where_sql";
|
||||||
$stmt_count = db()->prepare($count_query);
|
$stmt_count = db()->prepare($count_query);
|
||||||
$stmt_count->execute($params);
|
$stmt_count->execute($params);
|
||||||
$total_records = $stmt_count->fetchColumn();
|
$total_records = $stmt_count->fetchColumn();
|
||||||
@ -210,7 +210,7 @@ $total_pages = ceil($total_records / $limit);
|
|||||||
|
|
||||||
// Fetch paginated results
|
// Fetch paginated results
|
||||||
$query = "SELECT m.*, s.name as status_name, s.color as status_color, u.full_name as assigned_to_name
|
$query = "SELECT m.*, s.name as status_name, s.color as status_color, u.full_name as assigned_to_name
|
||||||
FROM mailbox m
|
FROM outbound_mail m
|
||||||
LEFT JOIN mailbox_statuses s ON m.status_id = s.id
|
LEFT JOIN mailbox_statuses s ON m.status_id = s.id
|
||||||
LEFT JOIN users u ON m.assigned_to = u.id
|
LEFT JOIN users u ON m.assigned_to = u.id
|
||||||
WHERE $where_sql
|
WHERE $where_sql
|
||||||
@ -227,7 +227,7 @@ $users_list = db()->query("SELECT id, full_name FROM users ORDER BY full_name")-
|
|||||||
$deepLinkData = null;
|
$deepLinkData = null;
|
||||||
if (isset($_GET['action']) && $_GET['action'] === 'edit' && isset($_GET['id'])) {
|
if (isset($_GET['action']) && $_GET['action'] === 'edit' && isset($_GET['id'])) {
|
||||||
if (canEdit('outbound')) {
|
if (canEdit('outbound')) {
|
||||||
$stmt = db()->prepare("SELECT * FROM mailbox WHERE id = ? AND type = 'outbound'");
|
$stmt = db()->prepare("SELECT * FROM outbound_mail WHERE id = ? ");
|
||||||
$stmt->execute([$_GET['id']]);
|
$stmt->execute([$_GET['id']]);
|
||||||
$deepLinkData = $stmt->fetch();
|
$deepLinkData = $stmt->fetch();
|
||||||
}
|
}
|
||||||
@ -428,7 +428,7 @@ function getStatusBadgeInList($mail) {
|
|||||||
</div>
|
</div>
|
||||||
<div class="col-12">
|
<div class="col-12">
|
||||||
<label class="form-label fw-bold">المرفقات</label>
|
<label class="form-label fw-bold">المرفقات</label>
|
||||||
<input type="file" name="attachments[]" class="form-control" multiple>
|
<input type="file" name="outbound_attachments[]" class="form-control" multiple>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-md-6">
|
<div class="col-md-6">
|
||||||
<label class="form-label fw-bold">الحالة</label>
|
<label class="form-label fw-bold">الحالة</label>
|
||||||
|
|||||||
@ -8,30 +8,49 @@ if (!canView('reports')) {
|
|||||||
$type_filter = $_GET['type'] ?? '';
|
$type_filter = $_GET['type'] ?? '';
|
||||||
$user_filter = $_GET['user_id'] ?? '';
|
$user_filter = $_GET['user_id'] ?? '';
|
||||||
|
|
||||||
$params = [];
|
$overdue_items = [];
|
||||||
$where = ["m.due_date < CURDATE()", "s.name != 'closed'", "m.type != 'internal'"];
|
$queries = [];
|
||||||
|
|
||||||
if ($type_filter) {
|
if (!$type_filter || $type_filter === 'inbound') {
|
||||||
$where[] = "m.type = ?";
|
$where = ["m.due_date < CURDATE()", "s.name != 'closed'"];
|
||||||
$params[] = $type_filter;
|
$params = [];
|
||||||
|
if ($user_filter) {
|
||||||
|
$where[] = "m.assigned_to = ?";
|
||||||
|
$params[] = $user_filter;
|
||||||
|
}
|
||||||
|
$where_clause = implode(" AND ", $where);
|
||||||
|
$sql = "SELECT m.*, 'inbound' as type, u.full_name as assigned_name, s.name as status_name, s.color as status_color
|
||||||
|
FROM inbound_mail m
|
||||||
|
LEFT JOIN users u ON m.assigned_to = u.id
|
||||||
|
LEFT JOIN mailbox_statuses s ON m.status_id = s.id
|
||||||
|
WHERE $where_clause";
|
||||||
|
$stmt = db()->prepare($sql);
|
||||||
|
$stmt->execute($params);
|
||||||
|
$overdue_items = array_merge($overdue_items, $stmt->fetchAll());
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($user_filter) {
|
if (!$type_filter || $type_filter === 'outbound') {
|
||||||
$where[] = "m.assigned_to = ?";
|
$where = ["m.due_date < CURDATE()", "s.name != 'closed'"];
|
||||||
$params[] = $user_filter;
|
$params = [];
|
||||||
|
if ($user_filter) {
|
||||||
|
$where[] = "m.assigned_to = ?";
|
||||||
|
$params[] = $user_filter;
|
||||||
|
}
|
||||||
|
$where_clause = implode(" AND ", $where);
|
||||||
|
$sql = "SELECT m.*, 'outbound' as type, u.full_name as assigned_name, s.name as status_name, s.color as status_color
|
||||||
|
FROM outbound_mail m
|
||||||
|
LEFT JOIN users u ON m.assigned_to = u.id
|
||||||
|
LEFT JOIN mailbox_statuses s ON m.status_id = s.id
|
||||||
|
WHERE $where_clause";
|
||||||
|
$stmt = db()->prepare($sql);
|
||||||
|
$stmt->execute($params);
|
||||||
|
$overdue_items = array_merge($overdue_items, $stmt->fetchAll());
|
||||||
}
|
}
|
||||||
|
|
||||||
$where_clause = implode(" AND ", $where);
|
// Sort by due date
|
||||||
$sql = "SELECT m.*, u.full_name as assigned_name, s.name as status_name, s.color as status_color
|
usort($overdue_items, function($a, $b) {
|
||||||
FROM mailbox m
|
return strtotime($a['due_date']) - strtotime($b['due_date']);
|
||||||
LEFT JOIN users u ON m.assigned_to = u.id
|
});
|
||||||
LEFT JOIN mailbox_statuses s ON m.status_id = s.id
|
|
||||||
WHERE $where_clause
|
|
||||||
ORDER BY m.due_date ASC";
|
|
||||||
|
|
||||||
$stmt = db()->prepare($sql);
|
|
||||||
$stmt->execute($params);
|
|
||||||
$overdue_items = $stmt->fetchAll();
|
|
||||||
|
|
||||||
// Fetch all users for filter
|
// Fetch all users for filter
|
||||||
$users = db()->query("SELECT id, full_name FROM users ORDER BY full_name")->fetchAll();
|
$users = db()->query("SELECT id, full_name FROM users ORDER BY full_name")->fetchAll();
|
||||||
@ -40,7 +59,6 @@ function getStatusBadgeForReport($item) {
|
|||||||
$status_name = $item['status_name'] ?? 'غير معروف';
|
$status_name = $item['status_name'] ?? 'غير معروف';
|
||||||
$status_color = $item['status_color'] ?? '#6c757d';
|
$status_color = $item['status_color'] ?? '#6c757d';
|
||||||
|
|
||||||
// Translation for default statuses
|
|
||||||
$display_name = $status_name;
|
$display_name = $status_name;
|
||||||
if ($status_name == 'received') $display_name = 'تم الاستلام';
|
if ($status_name == 'received') $display_name = 'تم الاستلام';
|
||||||
if ($status_name == 'in_progress') $display_name = 'قيد المعالجة';
|
if ($status_name == 'in_progress') $display_name = 'قيد المعالجة';
|
||||||
@ -126,7 +144,7 @@ function getStatusBadgeForReport($item) {
|
|||||||
<td class="text-danger fw-bold"><?= $item['due_date'] ?></td>
|
<td class="text-danger fw-bold"><?= $item['due_date'] ?></td>
|
||||||
<td class="text-danger fw-bold"><?= $diff ?> يوم</td>
|
<td class="text-danger fw-bold"><?= $diff ?> يوم</td>
|
||||||
<td>
|
<td>
|
||||||
<a href="view_mail.php?id=<?= $item['id'] ?>" class="btn btn-sm btn-outline-primary">
|
<a href="view_mail.php?id=<?= $item['id'] ?>&type=<?= $item['type'] ?>" class="btn btn-sm btn-outline-primary">
|
||||||
<i class="fas fa-eye"></i> عرض
|
<i class="fas fa-eye"></i> عرض
|
||||||
</a>
|
</a>
|
||||||
</td>
|
</td>
|
||||||
|
|||||||
@ -7,73 +7,78 @@ require_once __DIR__ . '/../mail/MailService.php';
|
|||||||
|
|
||||||
echo "[" . date('Y-m-d H:i:s') . "] Starting reminder process..." . PHP_EOL;
|
echo "[" . date('Y-m-d H:i:s') . "] Starting reminder process..." . PHP_EOL;
|
||||||
|
|
||||||
// 1. Tasks due in 24 hours (exactly 1 day away)
|
$tables = ['inbound_mail', 'outbound_mail']; // internal mail usually doesn't have due dates or reminders the same way
|
||||||
$due_tomorrow = db()->query("
|
|
||||||
SELECT m.*, u.email, u.full_name
|
|
||||||
FROM mailbox m
|
|
||||||
JOIN users u ON m.assigned_to = u.id
|
|
||||||
JOIN mailbox_statuses s ON m.status_id = s.id
|
|
||||||
WHERE m.due_date = DATE_ADD(CURDATE(), INTERVAL 1 DAY)
|
|
||||||
AND s.name != 'closed'
|
|
||||||
")->fetchAll();
|
|
||||||
|
|
||||||
foreach ($due_tomorrow as $task) {
|
foreach ($tables as $table) {
|
||||||
if (!empty($task['email'])) {
|
echo "Processing $table..." . PHP_EOL;
|
||||||
$subject = "تذكير: موعد نهائي لمهمة غداً - " . $task['ref_no'];
|
|
||||||
$html = "
|
// 1. Tasks due in 24 hours
|
||||||
<div dir='rtl' style='font-family: Arial, sans-serif;'>
|
$stmt = db()->prepare("
|
||||||
<h3>تذكير بموعد نهائي</h3>
|
SELECT m.*, u.email, u.full_name
|
||||||
<p>عزيزي <b>" . htmlspecialchars($task['full_name']) . "</b>،</p>
|
FROM $table m
|
||||||
<p>هذا تذكير بأن المهمة التالية مستحقة غداً:</p>
|
JOIN users u ON m.assigned_to = u.id
|
||||||
<ul>
|
JOIN mailbox_statuses s ON m.status_id = s.id
|
||||||
<li><b>رقم المرجع:</b> " . htmlspecialchars($task['ref_no']) . "</li>
|
WHERE m.due_date = DATE_ADD(CURDATE(), INTERVAL 1 DAY)
|
||||||
<li><b>الموضوع:</b> " . htmlspecialchars($task['subject']) . "</li>
|
AND s.name != 'closed'
|
||||||
<li><b>تاريخ الاستحقاق:</b> " . $task['due_date'] . "</li>
|
");
|
||||||
</ul>
|
$stmt->execute();
|
||||||
<p>يرجى متابعة المهمة وإغلاقها في الوقت المحدد.</p>
|
$due_tomorrow = $stmt->fetchAll();
|
||||||
</div>
|
|
||||||
";
|
foreach ($due_tomorrow as $task) {
|
||||||
$res = MailService::sendMail($task['email'], $subject, $html);
|
if (!empty($task['email'])) {
|
||||||
if ($res['success']) {
|
$subject = "تذكير: موعد نهائي لمهمة غداً - " . $task['ref_no'];
|
||||||
echo "Sent 24h reminder to " . $task['email'] . " for task " . $task['ref_no'] . PHP_EOL;
|
$html = "
|
||||||
} else {
|
<div dir='rtl' style='font-family: Arial, sans-serif;'>
|
||||||
echo "Failed to send 24h reminder to " . $task['email'] . ": " . ($res['error'] ?? 'Unknown error') . PHP_EOL;
|
<h3>تذكير بموعد نهائي</h3>
|
||||||
|
<p>عزيزي <b>" . htmlspecialchars($task['full_name']) . "</b>،</p>
|
||||||
|
<p>هذا تذكير بأن المهمة التالية مستحقة غداً:</p>
|
||||||
|
<ul>
|
||||||
|
<li><b>رقم المرجع:</b> " . htmlspecialchars($task['ref_no']) . "</li>
|
||||||
|
<li><b>الموضوع:</b> " . htmlspecialchars($task['subject']) . "</li>
|
||||||
|
<li><b>تاريخ الاستحقاق:</b> " . $task['due_date'] . "</li>
|
||||||
|
</ul>
|
||||||
|
<p>يرجى متابعة المهمة وإغلاقها في الوقت المحدد.</p>
|
||||||
|
</div>
|
||||||
|
";
|
||||||
|
$res = MailService::sendMail($task['email'], $subject, $html);
|
||||||
|
if ($res['success']) {
|
||||||
|
echo "Sent 24h reminder to " . $task['email'] . " for task " . $task['ref_no'] . PHP_EOL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// 2. Overdue tasks (due date passed and still not closed) - Only send once a week or daily?
|
// 2. Overdue tasks
|
||||||
// For now, let's send daily for overdue tasks to ensure they are handled.
|
$stmt = db()->prepare("
|
||||||
$overdue = db()->query("
|
SELECT m.*, u.email, u.full_name
|
||||||
SELECT m.*, u.email, u.full_name
|
FROM $table m
|
||||||
FROM mailbox m
|
JOIN users u ON m.assigned_to = u.id
|
||||||
JOIN users u ON m.assigned_to = u.id
|
JOIN mailbox_statuses s ON m.status_id = s.id
|
||||||
JOIN mailbox_statuses s ON m.status_id = s.id
|
WHERE m.due_date < CURDATE()
|
||||||
WHERE m.due_date < CURDATE()
|
AND s.name != 'closed'
|
||||||
AND s.name != 'closed'
|
");
|
||||||
")->fetchAll();
|
$stmt->execute();
|
||||||
|
$overdue = $stmt->fetchAll();
|
||||||
|
|
||||||
foreach ($overdue as $task) {
|
foreach ($overdue as $task) {
|
||||||
if (!empty($task['email'])) {
|
if (!empty($task['email'])) {
|
||||||
$subject = "تنبيه: مهمة متأخرة! - " . $task['ref_no'];
|
$subject = "تنبيه: مهمة متأخرة! - " . $task['ref_no'];
|
||||||
$html = "
|
$html = "
|
||||||
<div dir='rtl' style='font-family: Arial, sans-serif;'>
|
<div dir='rtl' style='font-family: Arial, sans-serif;'>
|
||||||
<h3 style='color: red;'>تنبيه: مهمة متأخرة</h3>
|
<h3 style='color: red;'>تنبيه: مهمة متأخرة</h3>
|
||||||
<p>عزيزي <b>" . htmlspecialchars($task['full_name']) . "</b>،</p>
|
<p>عزيزي <b>" . htmlspecialchars($task['full_name']) . "</b>،</p>
|
||||||
<p>هذه المهمة قد تجاوزت الموعد النهائي المحدد:</p>
|
<p>هذه المهمة قد تجاوزت الموعد النهائي المحدد:</p>
|
||||||
<ul>
|
<ul>
|
||||||
<li><b>رقم المرجع:</b> " . htmlspecialchars($task['ref_no']) . "</li>
|
<li><b>رقم المرجع:</b> " . htmlspecialchars($task['ref_no']) . "</li>
|
||||||
<li><b>الموضوع:</b> " . htmlspecialchars($task['subject']) . "</li>
|
<li><b>الموضوع:</b> " . htmlspecialchars($task['subject']) . "</li>
|
||||||
<li><b>تاريخ الاستحقاق:</b> <span style='color: red;'>" . $task['due_date'] . "</span></li>
|
<li><b>تاريخ الاستحقاق:</b> <span style='color: red;'>" . $task['due_date'] . "</span></li>
|
||||||
</ul>
|
</ul>
|
||||||
<p>يرجى معالجة هذه المهمة في أقرب وقت ممكن.</p>
|
<p>يرجى معالجة هذه المهمة في أقرب وقت ممكن.</p>
|
||||||
</div>
|
</div>
|
||||||
";
|
";
|
||||||
$res = MailService::sendMail($task['email'], $subject, $html);
|
$res = MailService::sendMail($task['email'], $subject, $html);
|
||||||
if ($res['success']) {
|
if ($res['success']) {
|
||||||
echo "Sent overdue reminder to " . $task['email'] . " for task " . $task['ref_no'] . PHP_EOL;
|
echo "Sent overdue reminder to " . $task['email'] . " for task " . $task['ref_no'] . PHP_EOL;
|
||||||
} else {
|
}
|
||||||
echo "Failed to send overdue reminder to " . $task['email'] . ": " . ($res['error'] ?? 'Unknown error') . PHP_EOL;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -11,65 +11,69 @@ $user_role = $_SESSION['user_role'];
|
|||||||
$is_admin = isAdmin();
|
$is_admin = isAdmin();
|
||||||
$is_clerk = ($user_role === 'clerk');
|
$is_clerk = ($user_role === 'clerk');
|
||||||
|
|
||||||
// Stats for this specific user
|
// Stats for this specific user - Combine from all tables
|
||||||
$stmt = db()->prepare("SELECT COUNT(*) FROM mailbox WHERE assigned_to = ?");
|
$my_total_assignments = 0;
|
||||||
$stmt->execute([$user_id]);
|
$my_pending_tasks = 0;
|
||||||
$my_total_assignments = $stmt->fetchColumn();
|
|
||||||
|
|
||||||
$stmt = db()->prepare("SELECT COUNT(*) FROM mailbox WHERE assigned_to = ? AND status_id IN (SELECT id FROM mailbox_statuses WHERE name != 'closed')");
|
foreach (['inbound', 'outbound', 'internal'] as $t) {
|
||||||
$stmt->execute([$user_id]);
|
if (canView($t)) {
|
||||||
$my_pending_tasks = $stmt->fetchColumn();
|
$table = $t . '_mail';
|
||||||
|
$stmt = db()->prepare("SELECT COUNT(*) FROM $table WHERE assigned_to = ?");
|
||||||
|
$stmt->execute([$user_id]);
|
||||||
|
$my_total_assignments += $stmt->fetchColumn();
|
||||||
|
|
||||||
// Global Stats (for Clerks or if we want to show them)
|
$stmt = db()->prepare("SELECT COUNT(*) FROM $table WHERE assigned_to = ? AND status_id IN (SELECT id FROM mailbox_statuses WHERE name != 'closed')");
|
||||||
$total_inbound = canView('inbound') ? db()->query("SELECT COUNT(*) FROM mailbox WHERE type = 'inbound'")->fetchColumn() : 0;
|
$stmt->execute([$user_id]);
|
||||||
$total_outbound = canView('outbound') ? db()->query("SELECT COUNT(*) FROM mailbox WHERE type = 'outbound'")->fetchColumn() : 0;
|
$my_pending_tasks += $stmt->fetchColumn();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Global Stats
|
||||||
|
$total_inbound = canView('inbound') ? db()->query("SELECT COUNT(*) FROM inbound_mail")->fetchColumn() : 0;
|
||||||
|
$total_outbound = canView('outbound') ? db()->query("SELECT COUNT(*) FROM outbound_mail")->fetchColumn() : 0;
|
||||||
|
|
||||||
// Fetch statuses for badge and count
|
// Fetch statuses for badge and count
|
||||||
$statuses_data = db()->query("SELECT * FROM mailbox_statuses")->fetchAll(PDO::FETCH_UNIQUE);
|
$statuses_data = db()->query("SELECT * FROM mailbox_statuses")->fetchAll(PDO::FETCH_UNIQUE);
|
||||||
|
|
||||||
// My Assignments
|
// My Assignments
|
||||||
$my_assignments = [];
|
$my_assignments = [];
|
||||||
$assignment_types = [];
|
$assignment_queries = [];
|
||||||
if (canView('inbound')) $assignment_types[] = "'inbound'";
|
if (canView('inbound')) $assignment_queries[] = "SELECT id, 'inbound' as type, ref_no, subject, due_date, status_id, created_at FROM inbound_mail WHERE assigned_to = $user_id";
|
||||||
if (canView('outbound')) $assignment_types[] = "'outbound'";
|
if (canView('outbound')) $assignment_queries[] = "SELECT id, 'outbound' as type, ref_no, subject, due_date, status_id, created_at FROM outbound_mail WHERE assigned_to = $user_id";
|
||||||
if (canView('internal')) $assignment_types[] = "'internal'";
|
if (canView('internal')) $assignment_queries[] = "SELECT id, 'internal' as type, ref_no, subject, due_date, status_id, created_at FROM internal_mail WHERE assigned_to = $user_id";
|
||||||
|
|
||||||
if (!empty($assignment_types)) {
|
if (!empty($assignment_queries)) {
|
||||||
$types_sql = implode(',', $assignment_types);
|
$full_assignment_query = "(" . implode(") UNION ALL (", $assignment_queries) . ") ORDER BY created_at DESC LIMIT 10";
|
||||||
$my_assignments = db()->prepare("SELECT m.*, s.name as status_name, s.color as status_color
|
$stmt = db()->query($full_assignment_query);
|
||||||
FROM mailbox m
|
$my_assignments = $stmt->fetchAll();
|
||||||
LEFT JOIN mailbox_statuses s ON m.status_id = s.id
|
foreach ($my_assignments as &$m) {
|
||||||
WHERE m.assigned_to = ? AND m.type IN ($types_sql)
|
$m['status_name'] = $statuses_data[$m['status_id']]['name'] ?? 'unknown';
|
||||||
ORDER BY m.created_at DESC LIMIT 10");
|
$m['status_color'] = $statuses_data[$m['status_id']]['color'] ?? '#6c757d';
|
||||||
$my_assignments->execute([$user_id]);
|
}
|
||||||
$my_assignments = $my_assignments->fetchAll();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Recent Activity
|
// Recent Activity
|
||||||
$recent_activity = [];
|
$recent_activity = [];
|
||||||
$recent_types = [];
|
$recent_queries = [];
|
||||||
if (canView('inbound')) $recent_types[] = "'inbound'";
|
if (canView('inbound')) $recent_queries[] = "SELECT id, 'inbound' as type, ref_no, subject, status_id, created_by, assigned_to, updated_at FROM inbound_mail";
|
||||||
if (canView('outbound')) $recent_types[] = "'outbound'";
|
if (canView('outbound')) $recent_queries[] = "SELECT id, 'outbound' as type, ref_no, subject, status_id, created_by, assigned_to, updated_at FROM outbound_mail";
|
||||||
if (canView('internal')) $recent_types[] = "'internal'";
|
if (canView('internal')) $recent_queries[] = "SELECT id, 'internal' as type, ref_no, subject, status_id, created_by, assigned_to, updated_at FROM internal_mail";
|
||||||
|
|
||||||
if (!empty($recent_types)) {
|
if (!empty($recent_queries)) {
|
||||||
$types_sql = implode(',', $recent_types);
|
$full_recent_query = "(" . implode(") UNION ALL (", $recent_queries) . ")";
|
||||||
$recent_query = "SELECT m.*, s.name as status_name, s.color as status_color, u.full_name as assigned_to_name
|
|
||||||
FROM mailbox m
|
|
||||||
LEFT JOIN mailbox_statuses s ON m.status_id = s.id
|
|
||||||
LEFT JOIN users u ON m.assigned_to = u.id
|
|
||||||
WHERE m.type IN ($types_sql)";
|
|
||||||
|
|
||||||
if ($is_admin || $is_clerk) {
|
if ($is_admin || $is_clerk) {
|
||||||
// Admins and Clerks see all recent activity EXCEPT internal mail they are not part of
|
$full_recent_query = "SELECT * FROM ($full_recent_query) AS combined WHERE (type != 'internal' OR assigned_to = $user_id OR created_by = $user_id) ORDER BY updated_at DESC LIMIT 10";
|
||||||
$recent_stmt = db()->prepare($recent_query . " AND (m.type != 'internal' OR m.assigned_to = ? OR m.created_by = ?) ORDER BY m.updated_at DESC LIMIT 10");
|
|
||||||
$recent_stmt->execute([$user_id, $user_id]);
|
|
||||||
} else {
|
} else {
|
||||||
// Staff see only theirs
|
$full_recent_query = "SELECT * FROM ($full_recent_query) AS combined WHERE (assigned_to = $user_id OR created_by = $user_id) ORDER BY updated_at DESC LIMIT 10";
|
||||||
$recent_stmt = db()->prepare($recent_query . " AND (m.assigned_to = ? OR m.created_by = ?) ORDER BY m.updated_at DESC LIMIT 10");
|
}
|
||||||
$recent_stmt->execute([$user_id, $user_id]);
|
|
||||||
|
$stmt = db()->query($full_recent_query);
|
||||||
|
$recent_activity = $stmt->fetchAll();
|
||||||
|
foreach ($recent_activity as &$a) {
|
||||||
|
$a['status_name'] = $statuses_data[$a['status_id']]['name'] ?? 'unknown';
|
||||||
|
$a['status_color'] = $statuses_data[$a['status_id']]['color'] ?? '#6c757d';
|
||||||
}
|
}
|
||||||
$recent_activity = $recent_stmt->fetchAll();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function getStatusBadge($mail) {
|
function getStatusBadge($mail) {
|
||||||
@ -124,7 +128,6 @@ function getStatusBadge($mail) {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="row g-4 mb-4">
|
<div class="row g-4 mb-4">
|
||||||
<!-- Stats for everyone -->
|
|
||||||
<div class="col-md-3">
|
<div class="col-md-3">
|
||||||
<div class="card h-100 p-3 shadow-sm border-0 border-start border-primary border-4">
|
<div class="card h-100 p-3 shadow-sm border-0 border-start border-primary border-4">
|
||||||
<div class="d-flex align-items-center">
|
<div class="d-flex align-items-center">
|
||||||
@ -153,7 +156,6 @@ function getStatusBadge($mail) {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<?php if ($is_admin || $is_clerk): ?>
|
<?php if ($is_admin || $is_clerk): ?>
|
||||||
<!-- Admin/Clerk specific stats -->
|
|
||||||
<?php if (canView('inbound')): ?>
|
<?php if (canView('inbound')): ?>
|
||||||
<div class="col-md-3">
|
<div class="col-md-3">
|
||||||
<div class="card h-100 p-3 shadow-sm border-0 border-start border-info border-4">
|
<div class="card h-100 p-3 shadow-sm border-0 border-start border-info border-4">
|
||||||
@ -185,7 +187,6 @@ function getStatusBadge($mail) {
|
|||||||
</div>
|
</div>
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
<?php else: ?>
|
<?php else: ?>
|
||||||
<!-- Staff specific stats -->
|
|
||||||
<div class="col-md-3">
|
<div class="col-md-3">
|
||||||
<div class="card h-100 p-3 shadow-sm border-0 border-start border-info border-4">
|
<div class="card h-100 p-3 shadow-sm border-0 border-start border-info border-4">
|
||||||
<div class="d-flex align-items-center">
|
<div class="d-flex align-items-center">
|
||||||
@ -195,9 +196,9 @@ function getStatusBadge($mail) {
|
|||||||
<div>
|
<div>
|
||||||
<h6 class="text-muted mb-1">وارد من قبلي</h6>
|
<h6 class="text-muted mb-1">وارد من قبلي</h6>
|
||||||
<?php
|
<?php
|
||||||
$stmt = db()->prepare("SELECT COUNT(*) FROM mailbox WHERE created_by = ? AND type = 'inbound'");
|
$my_in_count = db()->prepare("SELECT COUNT(*) FROM inbound_mail WHERE created_by = ?");
|
||||||
$stmt->execute([$user_id]);
|
$my_in_count->execute([$user_id]);
|
||||||
$my_in_count = $stmt->fetchColumn();
|
$my_in_count = $my_in_count->fetchColumn();
|
||||||
?>
|
?>
|
||||||
<h3 class="fw-bold mb-0"><?= $my_in_count ?></h3>
|
<h3 class="fw-bold mb-0"><?= $my_in_count ?></h3>
|
||||||
</div>
|
</div>
|
||||||
@ -213,9 +214,9 @@ function getStatusBadge($mail) {
|
|||||||
<div>
|
<div>
|
||||||
<h6 class="text-muted mb-1">صادر من قبلي</h6>
|
<h6 class="text-muted mb-1">صادر من قبلي</h6>
|
||||||
<?php
|
<?php
|
||||||
$stmt = db()->prepare("SELECT COUNT(*) FROM mailbox WHERE created_by = ? AND type = 'outbound'");
|
$my_out_count = db()->prepare("SELECT COUNT(*) FROM outbound_mail WHERE created_by = ?");
|
||||||
$stmt->execute([$user_id]);
|
$my_out_count->execute([$user_id]);
|
||||||
$my_out_count = $stmt->fetchColumn();
|
$my_out_count = $my_out_count->fetchColumn();
|
||||||
?>
|
?>
|
||||||
<h3 class="fw-bold mb-0"><?= $my_out_count ?></h3>
|
<h3 class="fw-bold mb-0"><?= $my_out_count ?></h3>
|
||||||
</div>
|
</div>
|
||||||
@ -226,7 +227,6 @@ function getStatusBadge($mail) {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<!-- Assignments Table -->
|
|
||||||
<div class="col-lg-8">
|
<div class="col-lg-8">
|
||||||
<div class="card shadow-sm border-0 mb-4 h-100">
|
<div class="card shadow-sm border-0 mb-4 h-100">
|
||||||
<div class="card-header bg-white py-3 border-bottom d-flex justify-content-between align-items-center">
|
<div class="card-header bg-white py-3 border-bottom d-flex justify-content-between align-items-center">
|
||||||
@ -236,7 +236,7 @@ function getStatusBadge($mail) {
|
|||||||
<a href="inbound.php?action=add" class="btn btn-sm btn-outline-primary">إضافة وارد</a>
|
<a href="inbound.php?action=add" class="btn btn-sm btn-outline-primary">إضافة وارد</a>
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
<?php if (canAdd('outbound')): ?>
|
<?php if (canAdd('outbound')): ?>
|
||||||
<a href="outbound.php" class="btn btn-sm btn-outline-success">إضافة صادر</a>
|
<a href="outbound.php?action=add" class="btn btn-sm btn-outline-success">إضافة صادر</a>
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -255,7 +255,7 @@ function getStatusBadge($mail) {
|
|||||||
<tbody>
|
<tbody>
|
||||||
<?php if (!empty($my_assignments)): ?>
|
<?php if (!empty($my_assignments)): ?>
|
||||||
<?php foreach ($my_assignments as $mail): ?>
|
<?php foreach ($my_assignments as $mail): ?>
|
||||||
<tr style="cursor: pointer;" onclick="window.location='view_mail.php?id=<?= $mail['id'] ?>'">
|
<tr style="cursor: pointer;" onclick="window.location='view_mail.php?id=<?= $mail['id'] ?>&type=<?= $mail['type'] ?>'">
|
||||||
<td class="ps-4 fw-bold text-primary"><?= $mail['ref_no'] ?></td>
|
<td class="ps-4 fw-bold text-primary"><?= $mail['ref_no'] ?></td>
|
||||||
<td><?= htmlspecialchars($mail['subject']) ?></td>
|
<td><?= htmlspecialchars($mail['subject']) ?></td>
|
||||||
<td>
|
<td>
|
||||||
@ -269,14 +269,13 @@ function getStatusBadge($mail) {
|
|||||||
</td>
|
</td>
|
||||||
<td><?= getStatusBadge($mail) ?></td>
|
<td><?= getStatusBadge($mail) ?></td>
|
||||||
<td class="pe-4 text-center">
|
<td class="pe-4 text-center">
|
||||||
<a href="view_mail.php?id=<?= $mail['id'] ?>" class="btn btn-sm btn-light rounded-pill px-3">عرض</a>
|
<a href="view_mail.php?id=<?= $mail['id'] ?>&type=<?= $mail['type'] ?>" class="btn btn-sm btn-light rounded-pill px-3">عرض</a>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<?php endforeach; ?>
|
<?php endforeach; ?>
|
||||||
<?php else: ?>
|
<?php else: ?>
|
||||||
<tr>
|
<tr>
|
||||||
<td colspan="5" class="text-center py-5 text-muted">
|
<td colspan="5" class="text-center py-5 text-muted">
|
||||||
<i class="fas fa-check-double fa-3x mb-3 d-block text-success opacity-25"></i>
|
|
||||||
أنت على اطلاع بكافة مهامك! لا توجد مهام معلقة.
|
أنت على اطلاع بكافة مهامك! لا توجد مهام معلقة.
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
@ -288,7 +287,6 @@ function getStatusBadge($mail) {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Recent Activity Sidebar -->
|
|
||||||
<div class="col-lg-4">
|
<div class="col-lg-4">
|
||||||
<div class="card shadow-sm border-0 mb-4 h-100">
|
<div class="card shadow-sm border-0 mb-4 h-100">
|
||||||
<div class="card-header bg-white py-3 border-bottom">
|
<div class="card-header bg-white py-3 border-bottom">
|
||||||
@ -298,7 +296,7 @@ function getStatusBadge($mail) {
|
|||||||
<div class="list-group list-group-flush">
|
<div class="list-group list-group-flush">
|
||||||
<?php if (!empty($recent_activity)): ?>
|
<?php if (!empty($recent_activity)): ?>
|
||||||
<?php foreach ($recent_activity as $act): ?>
|
<?php foreach ($recent_activity as $act): ?>
|
||||||
<a href="view_mail.php?id=<?= $act['id'] ?>" class="list-group-item list-group-item-action p-3 border-0 border-bottom">
|
<a href="view_mail.php?id=<?= $act['id'] ?>&type=<?= $act['type'] ?>" class="list-group-item list-group-item-action p-3 border-0 border-bottom">
|
||||||
<div class="d-flex w-100 justify-content-between mb-1">
|
<div class="d-flex w-100 justify-content-between mb-1">
|
||||||
<h6 class="mb-1 fw-bold text-truncate" title="<?= htmlspecialchars($act['subject']) ?>"><?= htmlspecialchars($act['subject']) ?></h6>
|
<h6 class="mb-1 fw-bold text-truncate" title="<?= htmlspecialchars($act['subject']) ?>"><?= htmlspecialchars($act['subject']) ?></h6>
|
||||||
<small class="text-muted"><?= date('m-d', strtotime($act['updated_at'])) ?></small>
|
<small class="text-muted"><?= date('m-d', strtotime($act['updated_at'])) ?></small>
|
||||||
@ -319,11 +317,6 @@ function getStatusBadge($mail) {
|
|||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="card-footer bg-light text-center py-2">
|
|
||||||
<?php if (canView('inbound')): ?>
|
|
||||||
<a href="inbound.php" class="small text-decoration-none">عرض كافة المراسلات <i class="fas fa-chevron-left ms-1"></i></a>
|
|
||||||
<?php endif; ?>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
145
view_mail.php
145
view_mail.php
@ -3,11 +3,32 @@ require_once __DIR__ . '/includes/header.php';
|
|||||||
require_once __DIR__ . '/mail/MailService.php';
|
require_once __DIR__ . '/mail/MailService.php';
|
||||||
|
|
||||||
$id = $_GET['id'] ?? 0;
|
$id = $_GET['id'] ?? 0;
|
||||||
|
$type = $_GET['type'] ?? '';
|
||||||
|
|
||||||
if (!$id) redirect('index.php');
|
if (!$id) redirect('index.php');
|
||||||
|
|
||||||
|
// If type is not provided, try to find it in any of the tables (for backward compatibility if any links were missed)
|
||||||
|
if (!$type) {
|
||||||
|
foreach (['inbound', 'outbound', 'internal'] as $t) {
|
||||||
|
$table = $t . '_mail';
|
||||||
|
$check = db()->prepare("SELECT id FROM $table WHERE id = ?");
|
||||||
|
$check->execute([$id]);
|
||||||
|
if ($check->fetch()) {
|
||||||
|
$type = $t;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!$type) redirect('index.php');
|
||||||
|
|
||||||
|
$table_mail = $type . '_mail';
|
||||||
|
$table_attachments = $type . '_attachments';
|
||||||
|
$table_comments = $type . '_comments';
|
||||||
|
|
||||||
$stmt = db()->prepare("SELECT m.*, u1.full_name as assigned_name, u2.full_name as creator_name,
|
$stmt = db()->prepare("SELECT m.*, u1.full_name as assigned_name, u2.full_name as creator_name,
|
||||||
s.name as status_name, s.color as status_color
|
s.name as status_name, s.color as status_color
|
||||||
FROM mailbox m
|
FROM $table_mail m
|
||||||
LEFT JOIN users u1 ON m.assigned_to = u1.id
|
LEFT JOIN users u1 ON m.assigned_to = u1.id
|
||||||
LEFT JOIN users u2 ON m.created_by = u2.id
|
LEFT JOIN users u2 ON m.created_by = u2.id
|
||||||
LEFT JOIN mailbox_statuses s ON m.status_id = s.id
|
LEFT JOIN mailbox_statuses s ON m.status_id = s.id
|
||||||
@ -17,14 +38,16 @@ $mail = $stmt->fetch();
|
|||||||
|
|
||||||
if (!$mail) redirect('index.php');
|
if (!$mail) redirect('index.php');
|
||||||
|
|
||||||
|
// Add back the type for logic below
|
||||||
|
$mail['type'] = $type;
|
||||||
|
|
||||||
// Check if user has view permission for this mail type
|
// Check if user has view permission for this mail type
|
||||||
if (!canView($mail['type'])) {
|
if (!canView($type)) {
|
||||||
redirect('index.php');
|
redirect('index.php');
|
||||||
}
|
}
|
||||||
|
|
||||||
// Security check for internal mail: only sender or recipient can view
|
// Security check for internal mail: only sender or recipient can view
|
||||||
// Even admins should only see their own internal mail for privacy
|
if ($type === 'internal') {
|
||||||
if ($mail['type'] === 'internal') {
|
|
||||||
if ($mail['created_by'] != $_SESSION['user_id'] && $mail['assigned_to'] != $_SESSION['user_id']) {
|
if ($mail['created_by'] != $_SESSION['user_id'] && $mail['assigned_to'] != $_SESSION['user_id']) {
|
||||||
redirect('internal_inbox.php');
|
redirect('internal_inbox.php');
|
||||||
}
|
}
|
||||||
@ -35,15 +58,14 @@ $error = '';
|
|||||||
|
|
||||||
// Handle Comment submission
|
// Handle Comment submission
|
||||||
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['add_comment'])) {
|
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['add_comment'])) {
|
||||||
// For internal mail, users can always comment if involved. For others, check edit permission.
|
if ($type !== 'internal' && !canEdit($type)) {
|
||||||
if ($mail['type'] !== 'internal' && !canEdit($mail['type'])) {
|
|
||||||
$error = 'عذراً، ليس لديك الصلاحية لإضافة تعليقات';
|
$error = 'عذراً، ليس لديك الصلاحية لإضافة تعليقات';
|
||||||
} else {
|
} else {
|
||||||
$comment = $_POST['comment'] ?? '';
|
$comment = $_POST['comment'] ?? '';
|
||||||
$referred_user_id = $_POST['referred_user_id'] ?: null;
|
$referred_user_id = $_POST['referred_user_id'] ?: null;
|
||||||
|
|
||||||
if ($comment) {
|
if ($comment) {
|
||||||
$stmt = db()->prepare("INSERT INTO comments (mail_id, user_id, comment, referred_user_id) VALUES (?, ?, ?, ?)");
|
$stmt = db()->prepare("INSERT INTO $table_comments (mail_id, user_id, comment, referred_user_id) VALUES (?, ?, ?, ?)");
|
||||||
$stmt->execute([$id, $_SESSION['user_id'], $comment, $referred_user_id]);
|
$stmt->execute([$id, $_SESSION['user_id'], $comment, $referred_user_id]);
|
||||||
|
|
||||||
// Send email notification if referred
|
// Send email notification if referred
|
||||||
@ -55,7 +77,7 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['add_comment'])) {
|
|||||||
if ($referred_user && !empty($referred_user['email'])) {
|
if ($referred_user && !empty($referred_user['email'])) {
|
||||||
$sender_name = $_SESSION['name'] ?? 'زميلك';
|
$sender_name = $_SESSION['name'] ?? 'زميلك';
|
||||||
$mail_subject = "إحالة بريد: " . $mail['subject'];
|
$mail_subject = "إحالة بريد: " . $mail['subject'];
|
||||||
$mail_link = (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on' ? "https" : "http") . "://$_SERVER[HTTP_HOST]" . dirname($_SERVER['PHP_SELF']) . "/view_mail.php?id=" . $id;
|
$mail_link = (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on' ? "https" : "http") . "://$_SERVER[HTTP_HOST]" . dirname($_SERVER['PHP_SELF']) . "/view_mail.php?id=" . $id . "&type=" . $type;
|
||||||
|
|
||||||
$html = "
|
$html = "
|
||||||
<div dir='rtl'>
|
<div dir='rtl'>
|
||||||
@ -80,14 +102,14 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['add_comment'])) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
$_SESSION['success'] = 'تم إضافة التعليق بنجاح';
|
$_SESSION['success'] = 'تم إضافة التعليق بنجاح';
|
||||||
redirect("view_mail.php?id=$id");
|
redirect("view_mail.php?id=$id&type=$type");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handle Attachment upload
|
// Handle Attachment upload
|
||||||
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_FILES['attachment'])) {
|
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_FILES['attachment'])) {
|
||||||
if ($mail['type'] !== 'internal' && !canEdit($mail['type'])) {
|
if ($type !== 'internal' && !canEdit($type)) {
|
||||||
$error = 'عذراً، ليس لديك الصلاحية لرفع مرفقات';
|
$error = 'عذراً، ليس لديك الصلاحية لرفع مرفقات';
|
||||||
} else {
|
} else {
|
||||||
$file = $_FILES['attachment'];
|
$file = $_FILES['attachment'];
|
||||||
@ -100,10 +122,10 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_FILES['attachment'])) {
|
|||||||
$target_path = $upload_dir . $file_name;
|
$target_path = $upload_dir . $file_name;
|
||||||
|
|
||||||
if (move_uploaded_file($file['tmp_name'], $target_path)) {
|
if (move_uploaded_file($file['tmp_name'], $target_path)) {
|
||||||
$stmt = db()->prepare("INSERT INTO attachments (mail_id, display_name, file_path, file_name, file_size) VALUES (?, ?, ?, ?, ?)");
|
$stmt = db()->prepare("INSERT INTO $table_attachments (mail_id, display_name, file_path, file_name, file_size) VALUES (?, ?, ?, ?, ?)");
|
||||||
$stmt->execute([$id, $display_name, $target_path, $file['name'], $file['size']]);
|
$stmt->execute([$id, $display_name, $target_path, $file['name'], $file['size']]);
|
||||||
$_SESSION['success'] = 'تم رفع الملف بنجاح';
|
$_SESSION['success'] = 'تم رفع الملف بنجاح';
|
||||||
redirect("view_mail.php?id=$id");
|
redirect("view_mail.php?id=$id&type=$type");
|
||||||
} else {
|
} else {
|
||||||
$error = 'فشل في رفع الملف';
|
$error = 'فشل في رفع الملف';
|
||||||
}
|
}
|
||||||
@ -113,26 +135,23 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_FILES['attachment'])) {
|
|||||||
|
|
||||||
// Handle Attachment deletion
|
// Handle Attachment deletion
|
||||||
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['delete_attachment'])) {
|
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['delete_attachment'])) {
|
||||||
if ($mail['type'] !== 'internal' && !canDelete($mail['type'])) {
|
if ($type !== 'internal' && !canDelete($type)) {
|
||||||
$error = 'عذراً، ليس لديك الصلاحية لحذف المرفقات';
|
$error = 'عذراً، ليس لديك الصلاحية لحذف المرفقات';
|
||||||
} else {
|
} else {
|
||||||
$attachment_id = $_POST['attachment_id'] ?? 0;
|
$attachment_id = $_POST['attachment_id'] ?? 0;
|
||||||
if ($attachment_id) {
|
if ($attachment_id) {
|
||||||
$stmt = db()->prepare("SELECT * FROM attachments WHERE id = ?");
|
$stmt = db()->prepare("SELECT * FROM $table_attachments WHERE id = ?");
|
||||||
$stmt->execute([$attachment_id]);
|
$stmt->execute([$attachment_id]);
|
||||||
$attachment = $stmt->fetch();
|
$attachment = $stmt->fetch();
|
||||||
|
|
||||||
if ($attachment) {
|
if ($attachment) {
|
||||||
// Delete file from disk
|
|
||||||
if (file_exists($attachment['file_path'])) {
|
if (file_exists($attachment['file_path'])) {
|
||||||
unlink($attachment['file_path']);
|
unlink($attachment['file_path']);
|
||||||
}
|
}
|
||||||
|
$stmt = db()->prepare("DELETE FROM $table_attachments WHERE id = ?");
|
||||||
// Delete record from DB
|
|
||||||
$stmt = db()->prepare("DELETE FROM attachments WHERE id = ?");
|
|
||||||
$stmt->execute([$attachment_id]);
|
$stmt->execute([$attachment_id]);
|
||||||
$_SESSION['success'] = 'تم حذف المرفق بنجاح';
|
$_SESSION['success'] = 'تم حذف المرفق بنجاح';
|
||||||
redirect("view_mail.php?id=$id");
|
redirect("view_mail.php?id=$id&type=$type");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -148,35 +167,34 @@ if (isset($_SESSION['error'])) {
|
|||||||
unset($_SESSION['error']);
|
unset($_SESSION['error']);
|
||||||
}
|
}
|
||||||
|
|
||||||
$comments = db()->prepare("SELECT c.*, u.full_name, ru.full_name as referred_name
|
$comments_stmt = db()->prepare("SELECT c.*, u.full_name, ru.full_name as referred_name
|
||||||
FROM comments c
|
FROM $table_comments c
|
||||||
LEFT JOIN users u ON c.user_id = u.id
|
LEFT JOIN users u ON c.user_id = u.id
|
||||||
LEFT JOIN users ru ON c.referred_user_id = ru.id
|
LEFT JOIN users ru ON c.referred_user_id = ru.id
|
||||||
WHERE c.mail_id = ? ORDER BY c.created_at DESC");
|
WHERE c.mail_id = ? ORDER BY c.created_at DESC");
|
||||||
$comments->execute([$id]);
|
$comments_stmt->execute([$id]);
|
||||||
$mail_comments = $comments->fetchAll();
|
$mail_comments = $comments_stmt->fetchAll();
|
||||||
|
|
||||||
$attachments = db()->prepare("SELECT * FROM attachments WHERE mail_id = ? ORDER BY created_at DESC");
|
$attachments_stmt = db()->prepare("SELECT * FROM $table_attachments WHERE mail_id = ? ORDER BY created_at DESC");
|
||||||
$attachments->execute([$id]);
|
$attachments_stmt->execute([$id]);
|
||||||
$mail_attachments = $attachments->fetchAll();
|
$mail_attachments = $attachments_stmt->fetchAll();
|
||||||
|
|
||||||
// Fetch all users for referral dropdown (excluding current user)
|
// Fetch all users for referral dropdown
|
||||||
$stmt_users = db()->prepare("SELECT id, full_name, role FROM users WHERE id != ? ORDER BY full_name ASC");
|
$stmt_users = db()->prepare("SELECT id, full_name, role FROM users WHERE id != ? ORDER BY full_name ASC");
|
||||||
$stmt_users->execute([$_SESSION['user_id']]);
|
$stmt_users->execute([$_SESSION['user_id']]);
|
||||||
$all_users = $stmt_users->fetchAll();
|
$all_users = $stmt_users->fetchAll();
|
||||||
|
|
||||||
// Helper to check previewable files
|
|
||||||
function isPreviewable($fileName) {
|
function isPreviewable($fileName) {
|
||||||
$ext = strtolower(pathinfo($fileName, PATHINFO_EXTENSION));
|
$ext = strtolower(pathinfo($fileName, PATHINFO_EXTENSION));
|
||||||
return in_array($ext, ['pdf', 'png', 'jpg', 'jpeg', 'gif', 'webp']);
|
return in_array($ext, ['pdf', 'png', 'jpg', 'jpeg', 'gif', 'webp']);
|
||||||
}
|
}
|
||||||
|
|
||||||
$type_label = 'بريد وارد';
|
$type_label = 'بريد وارد';
|
||||||
if ($mail['type'] == 'outbound') $type_label = 'بريد صادر';
|
if ($type == 'outbound') $type_label = 'بريد صادر';
|
||||||
if ($mail['type'] == 'internal') $type_label = 'رسالة داخلية';
|
if ($type == 'internal') $type_label = 'رسالة داخلية';
|
||||||
|
|
||||||
$back_link = $mail['type'] . '.php';
|
$back_link = $type . '.php';
|
||||||
if ($mail['type'] == 'internal') {
|
if ($type == 'internal') {
|
||||||
$back_link = ($mail['created_by'] == $_SESSION['user_id']) ? 'internal_outbox.php' : 'internal_inbox.php';
|
$back_link = ($mail['created_by'] == $_SESSION['user_id']) ? 'internal_outbox.php' : 'internal_inbox.php';
|
||||||
}
|
}
|
||||||
?>
|
?>
|
||||||
@ -185,8 +203,8 @@ if ($mail['type'] == 'internal') {
|
|||||||
<h1 class="h2">تفاصيل <?= $type_label ?></h1>
|
<h1 class="h2">تفاصيل <?= $type_label ?></h1>
|
||||||
<div class="btn-group">
|
<div class="btn-group">
|
||||||
<a href="<?= $back_link ?>" class="btn btn-outline-secondary">عودة للقائمة</a>
|
<a href="<?= $back_link ?>" class="btn btn-outline-secondary">عودة للقائمة</a>
|
||||||
<?php if ($mail['type'] !== 'internal' && canEdit($mail['type'])): ?>
|
<?php if ($type !== 'internal' && canEdit($type)): ?>
|
||||||
<a href="<?= $mail['type'] ?>.php?action=edit&id=<?= $mail['id'] ?>" class="btn btn-outline-primary">تعديل البيانات</a>
|
<a href="<?= $type ?>.php?action=edit&id=<?= $mail['id'] ?>" class="btn btn-outline-primary">تعديل البيانات</a>
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -244,9 +262,9 @@ if ($mail['type'] == 'internal') {
|
|||||||
$s_name = $mail['status_name'] ?? 'received';
|
$s_name = $mail['status_name'] ?? 'received';
|
||||||
$s_color = $mail['status_color'] ?? '#6c757d';
|
$s_color = $mail['status_color'] ?? '#6c757d';
|
||||||
$d_name = $s_name;
|
$d_name = $s_name;
|
||||||
if ($s_name == 'received') $d_name = ($mail['type'] == 'internal' ? 'جديد / مرسل' : 'تم الاستلام');
|
if ($s_name == 'received') $d_name = ($type == 'internal' ? 'جديد / مرسل' : 'تم الاستلام');
|
||||||
if ($s_name == 'in_progress') $d_name = 'قيد المعالجة';
|
if ($s_name == 'in_progress') $d_name = 'قيد المعالجة';
|
||||||
if ($s_name == 'closed') $d_name = ($mail['type'] == 'internal' ? 'مؤرشف' : 'مكتمل');
|
if ($s_name == 'closed') $d_name = ($type == 'internal' ? 'مؤرشف' : 'مكتمل');
|
||||||
?>
|
?>
|
||||||
<span class="badge" style="background-color: <?= $s_color ?>;"><?= htmlspecialchars($d_name) ?></span>
|
<span class="badge" style="background-color: <?= $s_color ?>;"><?= htmlspecialchars($d_name) ?></span>
|
||||||
</p>
|
</p>
|
||||||
@ -255,7 +273,7 @@ if ($mail['type'] == 'internal') {
|
|||||||
<label class="text-muted small">الموضوع</label>
|
<label class="text-muted small">الموضوع</label>
|
||||||
<div class="fw-bold">
|
<div class="fw-bold">
|
||||||
<?php
|
<?php
|
||||||
if ($mail['type'] == 'outbound' || $mail['type'] == 'internal') {
|
if ($type == 'outbound' || $type == 'internal') {
|
||||||
echo $mail['subject'];
|
echo $mail['subject'];
|
||||||
} else {
|
} else {
|
||||||
echo htmlspecialchars($mail['subject']);
|
echo htmlspecialchars($mail['subject']);
|
||||||
@ -264,7 +282,7 @@ if ($mail['type'] == 'internal') {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<?php if ($mail['type'] == 'internal'): ?>
|
<?php if ($type == 'internal'): ?>
|
||||||
<div class="col-md-6">
|
<div class="col-md-6">
|
||||||
<label class="text-muted small">المرسل</label>
|
<label class="text-muted small">المرسل</label>
|
||||||
<p class="fw-bold text-primary"><?= htmlspecialchars($mail['creator_name']) ?></p>
|
<p class="fw-bold text-primary"><?= htmlspecialchars($mail['creator_name']) ?></p>
|
||||||
@ -275,11 +293,11 @@ if ($mail['type'] == 'internal') {
|
|||||||
</div>
|
</div>
|
||||||
<?php else: ?>
|
<?php else: ?>
|
||||||
<div class="col-md-6">
|
<div class="col-md-6">
|
||||||
<label class="text-muted small"><?= $mail['type'] == 'inbound' ? 'المرسل' : 'المرسل الداخلي' ?></label>
|
<label class="text-muted small"><?= $type == 'inbound' ? 'المرسل' : 'المرسل الداخلي' ?></label>
|
||||||
<p><?= htmlspecialchars($mail['sender'] ?: 'غير محدد') ?></p>
|
<p><?= htmlspecialchars($mail['sender'] ?: 'غير محدد') ?></p>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-md-6">
|
<div class="col-md-6">
|
||||||
<label class="text-muted small"><?= $mail['type'] == 'inbound' ? 'المستلم الداخلي' : 'الجهة المستلمة' ?></label>
|
<label class="text-muted small"><?= $type == 'inbound' ? 'المستلم الداخلي' : 'الجهة المستلمة' ?></label>
|
||||||
<p><?= htmlspecialchars($mail['recipient'] ?: 'غير محدد') ?></p>
|
<p><?= htmlspecialchars($mail['recipient'] ?: 'غير محدد') ?></p>
|
||||||
</div>
|
</div>
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
@ -288,7 +306,7 @@ if ($mail['type'] == 'internal') {
|
|||||||
<label class="text-muted small">الرسالة / الوصف</label>
|
<label class="text-muted small">الرسالة / الوصف</label>
|
||||||
<div class="bg-light p-3 rounded border">
|
<div class="bg-light p-3 rounded border">
|
||||||
<?php
|
<?php
|
||||||
if ($mail['type'] == 'outbound' || $mail['type'] == 'internal') {
|
if ($type == 'outbound' || $type == 'internal') {
|
||||||
echo $mail['description'] ?: '<span class="text-muted">لا يوجد محتوى إضافي</span>';
|
echo $mail['description'] ?: '<span class="text-muted">لا يوجد محتوى إضافي</span>';
|
||||||
} else {
|
} else {
|
||||||
echo nl2br(htmlspecialchars($mail['description'] ?: 'لا يوجد محتوى إضافي'));
|
echo nl2br(htmlspecialchars($mail['description'] ?: 'لا يوجد محتوى إضافي'));
|
||||||
@ -297,14 +315,14 @@ if ($mail['type'] == 'internal') {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<?php if ($mail['type'] != 'internal'): ?>
|
<?php if ($type != 'internal'): ?>
|
||||||
<div class="col-md-6">
|
<div class="col-md-6">
|
||||||
<label class="text-muted small">الموظف المسؤول</label>
|
<label class="text-muted small">الموظف المسؤول</label>
|
||||||
<p><?= htmlspecialchars($mail['assigned_name'] ?: 'غير معين') ?></p>
|
<p><?= htmlspecialchars($mail['assigned_name'] ?: 'غير معين') ?></p>
|
||||||
</div>
|
</div>
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
|
|
||||||
<div class="col-md-6 <?= $mail['type'] == 'internal' ? 'col-md-12' : '' ?> text-end">
|
<div class="col-md-6 <?= $type == 'internal' ? 'col-md-12' : '' ?> text-end">
|
||||||
<label class="text-muted small">تاريخ الإنشاء</label>
|
<label class="text-muted small">تاريخ الإنشاء</label>
|
||||||
<p class="text-muted small"><?= $mail['created_at'] ?></p>
|
<p class="text-muted small"><?= $mail['created_at'] ?></p>
|
||||||
</div>
|
</div>
|
||||||
@ -318,13 +336,13 @@ if ($mail['type'] == 'internal') {
|
|||||||
<h5 class="mb-0 fw-bold">الردود والمتابعة</h5>
|
<h5 class="mb-0 fw-bold">الردود والمتابعة</h5>
|
||||||
</div>
|
</div>
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<?php if ($mail['type'] === 'internal' || canEdit($mail['type'])): ?>
|
<?php if ($type === 'internal' || canEdit($type)): ?>
|
||||||
<form method="POST" class="mb-4 bg-light p-3 rounded border">
|
<form method="POST" class="mb-4 bg-light p-3 rounded border">
|
||||||
<div class="mb-2">
|
<div class="mb-2">
|
||||||
<label class="form-label small fw-bold">إضافة <?= $mail['type'] == 'internal' ? 'رد' : 'تعليق' ?></label>
|
<label class="form-label small fw-bold">إضافة <?= $type == 'internal' ? 'رد' : 'تعليق' ?></label>
|
||||||
<textarea name="comment" class="form-control" rows="2" placeholder="اكتب ردك هنا..." required></textarea>
|
<textarea name="comment" class="form-control" rows="2" placeholder="اكتب ردك هنا..." required></textarea>
|
||||||
</div>
|
</div>
|
||||||
<?php if ($mail['type'] != 'internal'): ?>
|
<?php if ($type != 'internal'): ?>
|
||||||
<div class="mb-3">
|
<div class="mb-3">
|
||||||
<label class="form-label small fw-bold">إحالة إلى موظف (اختياري)</label>
|
<label class="form-label small fw-bold">إحالة إلى موظف (اختياري)</label>
|
||||||
<select name="referred_user_id" class="form-select form-select-sm">
|
<select name="referred_user_id" class="form-select form-select-sm">
|
||||||
@ -333,10 +351,9 @@ if ($mail['type'] == 'internal') {
|
|||||||
<option value="<?= $u['id'] ?>"><?= htmlspecialchars($u['full_name']) ?> (<?= ucfirst($u['role']) ?>)</option>
|
<option value="<?= $u['id'] ?>"><?= htmlspecialchars($u['full_name']) ?> (<?= ucfirst($u['role']) ?>)</option>
|
||||||
<?php endforeach; ?>
|
<?php endforeach; ?>
|
||||||
</select>
|
</select>
|
||||||
<div class="form-text small">سيتم إرسال تنبيه عبر البريد الإلكتروني للموظف المحال إليه.</div>
|
|
||||||
</div>
|
</div>
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
<button type="submit" name="add_comment" class="btn btn-sm btn-primary">إرسال <?= $mail['type'] == 'internal' ? 'الرد' : 'التعليق' ?></button>
|
<button type="submit" name="add_comment" class="btn btn-sm btn-primary">إرسال <?= $type == 'internal' ? 'الرد' : 'التعليق' ?></button>
|
||||||
</form>
|
</form>
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
|
|
||||||
@ -371,7 +388,7 @@ if ($mail['type'] == 'internal') {
|
|||||||
<h5 class="mb-0 fw-bold">المرفقات</h5>
|
<h5 class="mb-0 fw-bold">المرفقات</h5>
|
||||||
</div>
|
</div>
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<?php if ($mail['type'] === 'internal' || canEdit($mail['type'])): ?>
|
<?php if ($type === 'internal' || canEdit($type)): ?>
|
||||||
<form method="POST" enctype="multipart/form-data" class="mb-4">
|
<form method="POST" enctype="multipart/form-data" class="mb-4">
|
||||||
<div class="mb-2">
|
<div class="mb-2">
|
||||||
<label class="form-label small mb-1">اسم المرفق (يظهر في القائمة)</label>
|
<label class="form-label small mb-1">اسم المرفق (يظهر في القائمة)</label>
|
||||||
@ -404,7 +421,7 @@ if ($mail['type'] == 'internal') {
|
|||||||
</button>
|
</button>
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
|
|
||||||
<?php if ($mail['type'] == 'internal' || canDelete($mail['type'])): ?>
|
<?php if ($type == 'internal' || canDelete($type)): ?>
|
||||||
<form method="POST" class="d-inline delete-attachment-form">
|
<form method="POST" class="d-inline delete-attachment-form">
|
||||||
<input type="hidden" name="attachment_id" value="<?= $a['id'] ?>">
|
<input type="hidden" name="attachment_id" value="<?= $a['id'] ?>">
|
||||||
<input type="hidden" name="delete_attachment" value="1">
|
<input type="hidden" name="delete_attachment" value="1">
|
||||||
@ -434,13 +451,11 @@ if ($mail['type'] == 'internal') {
|
|||||||
<button type="button" class="btn-close ms-0 me-auto" data-bs-dismiss="modal" aria-label="Close"></button>
|
<button type="button" class="btn-close ms-0 me-auto" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-body p-0 bg-dark d-flex align-items-center justify-content-center" style="min-height: 80vh;">
|
<div class="modal-body p-0 bg-dark d-flex align-items-center justify-content-center" style="min-height: 80vh;">
|
||||||
<div id="previewContainer" class="w-100 h-100 text-center">
|
<div id="previewContainer" class="w-100 h-100 text-center"></div>
|
||||||
<!-- Preview content will be loaded here -->
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-footer">
|
<div class="modal-footer">
|
||||||
<a id="downloadBtn" href="#" class="btn btn-primary" download>تحميل الملف</a>
|
<a id="downloadBtn" href="#" class="btn btn-primary" download>تحميل الملف</a>
|
||||||
<button type="button" class="btn btn-secondary" data-bs-modal="modal">إغلاق</button>
|
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">إغلاق</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -482,29 +497,11 @@ if ($mail['type'] == 'internal') {
|
|||||||
previewContainer.innerHTML = '';
|
previewContainer.innerHTML = '';
|
||||||
});
|
});
|
||||||
|
|
||||||
// Handle Delete Confirmation
|
|
||||||
document.querySelectorAll('.delete-btn').forEach(btn => {
|
document.querySelectorAll('.delete-btn').forEach(btn => {
|
||||||
btn.addEventListener('click', function() {
|
btn.addEventListener('click', function() {
|
||||||
const form = this.closest('form');
|
const form = this.closest('form');
|
||||||
if (typeof Swal !== 'undefined') {
|
if (confirm('هل أنت متأكد من الحذف؟')) {
|
||||||
Swal.fire({
|
form.submit();
|
||||||
title: 'هل أنت متأكد؟',
|
|
||||||
text: "سيتم حذف المرفق نهائياً!",
|
|
||||||
icon: 'warning',
|
|
||||||
showCancelButton: true,
|
|
||||||
confirmButtonColor: '#d33',
|
|
||||||
cancelButtonColor: '#3085d6',
|
|
||||||
confirmButtonText: 'نعم، احذف',
|
|
||||||
cancelButtonText: 'إلغاء'
|
|
||||||
}).then((result) => {
|
|
||||||
if (result.isConfirmed) {
|
|
||||||
form.submit();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
if (confirm('هل أنت متأكد من الحذف؟')) {
|
|
||||||
form.submit();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user