📊 1 مشاهدة
معمارية نظام منصة “لجنة تصحيح أوضاع اليمنيين” في المملكة العربية السعودية
WordPress + PHP + AI Prompt Response Engine
📋 القسم الأول: تحليل المتطلبات
1.1 السياق الحكومي
| العنصر | التفصيل |
|---|---|
| الجهة | الجمهورية اليمنية – لجنة تصحيح أوضاع اليمنيين في المملكة العربية السعودية |
| نوع الخدمة | تسجيل بيانات المستفيدين + إصدار وثيقة توثيق مؤقتة |
| الجمهور | اليمنيون المقيمون في المملكة العربية السعودية |
| طبيعة المشروع | مشروع جديد (Greenfield) |
1.2 المتطلبات الوظيفية (Functional)
- تسجيل بيانات المستفيد (اسم رباعي، حالة اجتماعية، جنس، مهنة، ميلاد، إقامة، عنوان يمني).
- رفع مرفقات (صورة شخصية إجبارية + مستندات اختيارية).
- حفظ الطلب بحالة “قيد المراجعة”.
- توليد حزمة طباعة متسلسلة: بطاقة التوثيق المؤقتة → بيانات المستفيد → المستندات → الإرشادات.
- إمكانية إعادة الطباعة لاحقًا.
- التحقق من الجواز اليمني (تنبيه: حامل الجواز لا يحتاج وثيقة مؤقتة).
- دعم كامل للغة العربية (RTL).
1.3 المتطلبات غير الوظيفية (Non-Functional)
| المتطلب | الهدف |
|---|---|
| الأداء | زمن استجابة < 2 ثانية |
| التوفر | 99.9% |
| الأمان | تشفير TLS 1.3، تشفير الحقول الحساسة AES-256 |
| الامتثال | NCA-ECC، ISO 27001، PDPL السعودي |
| قابلية التوسع | Horizontal Scaling عبر Kubernetes/Cloud |
| التدقيق | Audit Log كامل لكل عملية |
📋 القسم الثاني: Tech Stack المقترح
2.1 الطبقة التقنية
text
┌─────────────────────────────────────────────────────┐ │ Frontend: WordPress Theme (RTL) + Alpine.js + Tailwind │ ├─────────────────────────────────────────────────────┤ │ Application: WordPress Core + Custom Plugin (PHP 8.2) │ ├─────────────────────────────────────────────────────┤ │ AI Engine: OpenAI/Claude API + Prompt Response Layer │ ├─────────────────────────────────────────────────────┤ │ Database: MySQL 8.0 (WordPress) + Redis (Cache) │ ├─────────────────────────────────────────────────────┤ │ Storage: S3-Compatible (MinIO/AWS S3) - Encrypted │ ├─────────────────────────────────────────────────────┤ │ Auth: WordPress + JWT + 2FA (SMS/TOTP) │ ├─────────────────────────────────────────────────────┤ │ Infra: Docker + Nginx + Cloudflare WAF + K8s │ └─────────────────────────────────────────────────────┘
2.2 إضافات WordPress المطلوبة
| الإضافة | الغرض |
|---|---|
| WPForms / Gravity Forms | نموذج التسجيل |
| Advanced Custom Fields (ACF) | حقول مخصصة |
| User Role Editor | أدوار (مقدم طلب، مراجع، مدير) |
| Wordfence / iThemes | الحماية |
| WPML / Polylang | دعم متعدد اللغات |
| UpdraftPlus | النسخ الاحتياطي |
| Custom Plugin (تطوير خاص) | منطق العمل + API |
📋 القسم الثالث: بنية قاعدة البيانات
3.1 جداول WordPress المخصصة
sql
-- جدول الطلبات الرئيسي
CREATE TABLE wp_ym_beneficiary_requests (
id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
user_id BIGINT UNSIGNED NOT NULL,
full_name VARCHAR(255) NOT NULL, -- الاسم الرباعي
id_type ENUM('national_id','passport','none') DEFAULT NULL,
id_number VARCHAR(50) DEFAULT NULL,
marital_status ENUM('single','married','divorced','widowed') NOT NULL,
gender ENUM('male','female') NOT NULL,
occupation VARCHAR(150) NOT NULL,
birth_place VARCHAR(150) NOT NULL,
birth_date DATE NOT NULL,
residence_place VARCHAR(255) NOT NULL,
mobile VARCHAR(20) NOT NULL, -- 9665XXXXXXXX
email VARCHAR(150) NOT NULL,
region_id INT UNSIGNED NOT NULL, -- المنطقة في السعودية
governorate_id INT UNSIGNED NOT NULL, -- المحافظة (اليمن)
district_id INT UNSIGNED NOT NULL, -- المديرية
village VARCHAR(150) NOT NULL,
status ENUM('pending','under_review','approved','rejected') DEFAULT 'pending',
reference_no VARCHAR(30) UNIQUE, -- رقم مرجعي للطباعة
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
ip_address VARBINARY(16),
INDEX idx_status (status),
INDEX idx_reference (reference_no)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
-- جدول المرفقات
CREATE TABLE wp_ym_attachments (
id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
request_id BIGINT UNSIGNED NOT NULL,
doc_type ENUM('personal_photo','passport','national_id','birth_cert','family_card','other1','other2') NOT NULL,
file_path VARCHAR(500) NOT NULL,
file_hash CHAR(64) NOT NULL, -- SHA-256 للتحقق
mime_type VARCHAR(100) NOT NULL,
file_size INT UNSIGNED NOT NULL,
is_required TINYINT(1) DEFAULT 0,
uploaded_at DATETIME DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (request_id) REFERENCES wp_ym_beneficiary_requests(id) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
-- جدول سجل التدقيق (Audit Log)
CREATE TABLE wp_ym_audit_log (
id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
request_id BIGINT UNSIGNED,
actor_id BIGINT UNSIGNED,
action VARCHAR(100) NOT NULL,
old_value JSON,
new_value JSON,
ip_address VARBINARY(16),
user_agent TEXT,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
📋 القسم الرابع: بنية إضافة WordPress المخصصة
4.1 هيكل المجلدات
text
ym-status-correction/
├── ym-status-correction.php # الملف الرئيسي
├── includes/
│ ├── class-db.php # إدارة قاعدة البيانات
│ ├── class-form-handler.php # معالج النموذج
│ ├── class-validator.php # التحقق من البيانات
│ ├── class-file-uploader.php # رفع الملفات
│ ├── class-print-bundle.php # حزمة الطباعة
│ ├── class-audit-log.php # سجل التدقيق
│ └── class-api.php # REST API
├── admin/
│ ├── class-admin-menu.php
│ └── views/
│ ├── requests-list.php
│ └── request-detail.php
├── templates/
│ ├── form-registration.php # نموذج التسجيل
│ ├── print-temporary-card.php # بطاقة التوثيق المؤقتة
│ ├── print-beneficiary-data.php # بيانات المستفيد
│ ├── print-attachments.php # المستندات
│ └── print-instructions.php # الإرشادات
├── assets/
│ ├── css/rtl.css
│ ├── js/form.js
│ └── img/yemen-emblem.png
└── languages/
└── ar.mo / ar.po
4.2 الملف الرئيسي ym-status-correction.php
php
<?php
/**
* Plugin Name: YM Status Correction Platform
* Description: منصة لجنة تصحيح أوضاع اليمنيين - تسجيل بيانات المستفيدين
* Version: 1.0.0
* Author: Government Solutions
* Text Domain: ym-status
* Requires PHP: 8.2
*/
if (!defined('ABSPATH')) exit;
define('YM_VERSION', '1.0.0');
define('YM_PLUGIN_DIR', plugin_dir_path(__FILE__));
define('YM_PLUGIN_URL', plugin_dir_url(__FILE__));
// تحميل الفئات الأساسية
require_once YM_PLUGIN_DIR . 'includes/class-db.php';
require_once YM_PLUGIN_DIR . 'includes/class-validator.php';
require_once YM_PLUGIN_DIR . 'includes/class-file-uploader.php';
require_once YM_PLUGIN_DIR . 'includes/class-form-handler.php';
require_once YM_PLUGIN_DIR . 'includes/class-print-bundle.php';
require_once YM_PLUGIN_DIR . 'includes/class-audit-log.php';
require_once YM_PLUGIN_DIR . 'includes/class-api.php';
// التفعيل
register_activation_hook(__FILE__, ['YM_DB', 'install']);
// التهيئة
add_action('plugins_loaded', function() {
load_plugin_textdomain('ym-status', false, dirname(plugin_basename(__FILE__)) . '/languages');
new YM_Form_Handler();
new YM_API();
});
📋 القسم الخامس: التحقق من البيانات (Validator)
php
<?php
class YM_Validator {
/** قواعد التحقق المطابقة للتنبيهات المطلوبة */
public static function validate(array $data): array {
$errors = [];
// الاسم الرباعي - حروف فقط + 4 كلمات على الأقل
if (empty($data['full_name'])) {
$errors['full_name'] = 'الاسم الرباعي مطلوب.';
} elseif (!preg_match('/^[\p{Arabic}\s]{3,}(\s+[\p{Arabic}]{2,}){3,}$/u', trim($data['full_name']))) {
$errors['full_name'] = 'الاسم يجب أن يكون رباعياً ويحتوي على حروف فقط.';
}
// الحالة الاجتماعية
$allowed_marital = ['single','married','divorced','widowed'];
if (empty($data['marital_status']) || !in_array($data['marital_status'], $allowed_marital, true)) {
$errors['marital_status'] = 'اختر الحالة الاجتماعية.';
}
// الجنس
if (empty($data['gender']) || !in_array($data['gender'], ['male','female'], true)) {
$errors['gender'] = 'اختر الجنس.';
}
// المهنة
if (empty($data['occupation'])) {
$errors['occupation'] = 'المهنة مطلوبة.';
}
// مكان الميلاد
if (empty($data['birth_place'])) {
$errors['birth_place'] = 'مكان الميلاد مطلوب.';
}
// تاريخ الميلاد
if (!self::isValidDate($data['birth_date'] ?? '')) {
$errors['birth_date'] = 'تاريخ الميلاد غير صحيح.';
}
// مكان الإقامة
if (empty($data['residence_place'])) {
$errors['residence_place'] = 'مكان الإقامة مطلوب.';
}
// رقم الجوال - 9665XXXXXXXX
if (empty($data['mobile']) || !preg_match('/^9665\d{8}$/', $data['mobile'])) {
$errors['mobile'] = 'رقم الجوال غير صحيح.';
}
// البريد الإلكتروني
if (empty($data['email']) || !is_email($data['email'])) {
$errors['email'] = 'البريد الإلكتروني مطلوب.';
}
// المنطقة
if (empty($data['region_id'])) {
$errors['region_id'] = 'اختر المنطقة.';
}
// العنوان في اليمن
if (empty($data['governorate_id'])) $errors['governorate_id'] = 'المحافظة مطلوبة.';
if (empty($data['district_id'])) $errors['district_id'] = 'المديرية مطلوبة.';
if (empty($data['village'])) $errors['village'] = 'القرية مطلوبة.';
// الصورة الشخصية إجبارية
if (empty($_FILES['personal_photo']['name'])) {
$errors['personal_photo'] = 'الصورة الشخصية إجبارية.';
}
return $errors;
}
private static function isValidDate(string $date): bool {
$d = DateTime::createFromFormat('Y-m-d', $date);
return $d && $d->format('Y-m-d') === $date && $d <= new DateTime();
}
/** التحقق من نوع الإثبات - إذا جواز يمني يُظهر تنبيه */
public static function passportNotice(?string $id_type, ?string $id_number): ?string {
if ($id_type === 'passport' && !empty($id_number)) {
return '⚠ تنبيه: من يحمل جواز سفر يمني لا يحتاج إلى استخراج وثيقة مؤقتة.';
}
return null;
}
}
📋 القسم السادس: نموذج التسجيل (Template)
php
<?php // templates/form-registration.php ?>
<div class="ym-form-wrapper" dir="rtl">
<header class="ym-header">
<img src="<?= esc_url(YM_PLUGIN_URL . 'assets/img/yemen-emblem.png') ?>"
alt="شعار الجمهورية اليمنية" class="ym-emblem">
<h1>الجمهورية اليمنية</h1>
<h2>لجنة تصحيح أوضاع اليمنيين في المملكة العربية السعودية</h2>
<h3>تسجيل بيانات المستفيد</h3>
</header>
<div class="ym-alert ym-alert-warning">
⚠ تنبيه للمستفيد: من يحمل جواز سفر يمني لا يحتاج إلى استخراج وثيقة مؤقتة.
</div>
<form id="ym-registration-form" method="post"
enctype="multipart/form-data" novalidate>
<?php wp_nonce_field('ym_submit_form', 'ym_nonce'); ?>
<!-- البيانات الأساسية -->
<fieldset>
<legend>البيانات الأساسية</legend>
<label>الاسم الرباعي *</label>
<input type="text" name="full_name" required
pattern="^[\u0600-\u06FF\s]{10,}$"
title="الاسم يجب أن يكون رباعياً ويحتوي على حروف فقط.">
<label>نوع الإثبات (اختياري)</label>
<select name="id_type" id="ym-id-type">
<option value="">-- اختر --</option>
<option value="national_id">البطاقة الشخصية</option>
<option value="passport">جواز السفر</option>
</select>
<label>رقم البطاقة الشخصية / الجواز</label>
<input type="text" name="id_number" id="ym-id-number">
<label>الحالة الاجتماعية *</label>
<select name="marital_status" required>
<option value="">-- اختر --</option>
<option value="single">أعزب</option>
<option value="married">متزوج</option>
<option value="divorced">مطلق</option>
<option value="widowed">أرمل</option>
</select>
<label>الجنس *</label>
<select name="gender" required>
<option value="">-- اختر --</option>
<option value="male">ذكر</option>
<option value="female">أنثى</option>
</select>
<label>المهنة *</label>
<input type="text" name="occupation" required>
<label>مكان الميلاد *</label>
<input type="text" name="birth_place" required>
<label>تاريخ الميلاد *</label>
<input type="date" name="birth_date" required max="<?= date('Y-m-d') ?>">
<label>مكان الإقامة *</label>
<input type="text" name="residence_place" required>
<label>رقم الجوال *</label>
<input type="tel" name="mobile" required
pattern="9665[0-9]{8}" placeholder="مثال: 9665XXXXXXXX">
<label>البريد الإلكتروني *</label>
<input type="email" name="email" required>
<label>المنطقة *</label>
<select name="region_id" required>
<option value="">-- اختر المنطقة --</option>
<?php foreach (YM_DB::get_regions() as $r): ?>
<option value="<?= esc_attr($r->id) ?>"><?= esc_html($r->name) ?></option>
<?php endforeach; ?>
</select>
</fieldset>
<!-- العنوان في اليمن -->
<fieldset>
<legend>العنوان في اليمن</legend>
<label>المحافظة *</label>
<select name="governorate_id" id="ym-gov" required>
<option value="">-- اختر --</option>
<?php foreach (YM_DB::get_governorates() as $g): ?>
<option value="<?= esc_attr($g->id) ?>"><?= esc_html($g->name) ?></option>
<?php endforeach; ?>
</select>
<label>المديرية *</label>
<select name="district_id" id="ym-district" required></select>
<label>القرية *</label>
<input type="text" name="village" required>
</fieldset>
<!-- المرفقات -->
<fieldset>
<legend>المرفقات (jpg / png / pdf - حتى 5 ميجابايت للملف)</legend>
<label>الصورة الشخصية * (إجباري - jpg / png)</label>
<input type="file" name="personal_photo" accept=".jpg,.jpeg,.png" required>
<label>صورة من الجواز (اختياري)</label>
<input type="file" name="passport" accept=".jpg,.jpeg,.png,.pdf">
<label>صورة من البطاقة (اختياري)</label>
<input type="file" name="national_id" accept=".jpg,.jpeg,.png,.pdf">
<label>صورة من شهادة الميلاد (اختياري)</label>
<input type="file" name="birth_cert" accept=".jpg,.jpeg,.png,.pdf">
<label>صورة من كرت العائلة (اختياري)</label>
<input type="file" name="family_card" accept=".jpg,.jpeg,.png,.pdf">
<label>مستندات أخرى 1 (اختياري)</label>
<input type="file" name="other1" accept=".jpg,.jpeg,.png,.pdf">
<label>مستندات أخرى 2 (اختياري)</label>
<input type="file" name="other2" accept=".jpg,.jpeg,.png,.pdf">
</fieldset>
<button type="submit" class="ym-btn-primary">
طباعة وإرسال الطلب
</button>
</form>
</div>
📋 القسم السابع: معالج النموذج + حزمة الطباعة
php
<?php
class YM_Form_Handler {
public function __construct() {
add_action('wp_ajax_nopriv_ym_submit', [$this, 'handle_submit']);
add_action('wp_ajax_ym_submit', [$this, 'handle_submit']);
add_action('wp_ajax_ym_print_bundle', [$this, 'print_bundle']);
}
public function handle_submit(): void {
check_ajax_referer('ym_submit_form', 'ym_nonce');
$data = $this->sanitize($_POST);
$errors = YM_Validator::validate($data);
if (!empty($errors)) {
wp_send_json_error(['errors' => $errors], 422);
}
// 1) حفظ الطلب في قاعدة البيانات
$request_id = YM_DB::insert_request($data);
$reference_no = 'YM-' . date('Y') . '-' . str_pad($request_id, 6, '0', STR_PAD_LEFT);
YM_DB::update_reference($request_id, $reference_no);
// 2) رفع المرفقات
$uploader = new YM_File_Uploader();
$uploaded = $uploader->process($request_id, $_FILES);
if (is_wp_error($uploaded)) {
wp_send_json_error(['message' => $uploaded->get_error_message()], 500);
}
// 3) تسجيل في سجل التدقيق
YM_Audit_Log::log($request_id, get_current_user_id(), 'submitted', null, $data);
// 4) إرسال الطلب للمراجعة
$this->notify_reviewers($request_id);
// 5) إرجاع رابط حزمة الطباعة
wp_send_json_success([
'request_id' => $request_id,
'reference_no' => $reference_no,
'print_url' => add_query_arg(
['action' => 'ym_print_bundle', 'id' => $request_id, 'token' => wp_create_nonce('ym_print_' . $request_id)],
admin_url('admin-ajax.php')
),
'message' => 'تم إرسال الطلب للمراجعة، جاري فتح حزمة الطباعة...'
]);
}
/** حزمة الطباعة: بطاقة التوثيق → البيانات → المستندات → الإرشادات */
public function print_bundle(): void {
$id = (int) ($_GET['id'] ?? 0);
if (!wp_verify_nonce($_GET['token'] ?? '', 'ym_print_' . $id)) {
wp_die('رابط غير صالح.');
}
$request = YM_DB::get_request($id);
$attachments = YM_DB::get_attachments($id);
// ترتيب الطباعة المطلوب
YM_Print_Bundle::render([
'temporary_card' => YM_Print_Bundle::temporary_card($request),
'beneficiary' => YM_Print_Bundle::beneficiary_data($request),
'attachments' => YM_Print_Bundle::attachments(array_filter(
$attachments,
fn($a) => $a->doc_type !== 'personal_photo'
)),
'instructions' => YM_Print_Bundle::post_print_instructions(),
]);
exit;
}
private function sanitize(array $input): array {
return [
'full_name' => sanitize_text_field($input['full_name'] ?? ''),
'id_type' => sanitize_key($input['id_type'] ?? ''),
'id_number' => sanitize_text_field($input['id_number'] ?? ''),
'marital_status' => sanitize_key($input['marital_status'] ?? ''),
'gender' => sanitize_key($input['gender'] ?? ''),
'occupation' => sanitize_text_field($input['occupation'] ?? ''),
'birth_place' => sanitize_text_field($input['birth_place'] ?? ''),
'birth_date' => sanitize_text_field($input['birth_date'] ?? ''),
'residence_place' => sanitize_text_field($input['residence_place'] ?? ''),
'mobile' => preg_replace('/\D/', '', $input['mobile'] ?? ''),
'email' => sanitize_email($input['email'] ?? ''),
'region_id' => (int) ($input['region_id'] ?? 0),
'governorate_id' => (int) ($input['governorate_id'] ?? 0),
'district_id' => (int) ($input['district_id'] ?? 0),
'village' => sanitize_text_field($input['village'] ?? ''),
];
}
private function notify_reviewers(int $request_id): void {
$reviewers = get_users(['role' => 'ym_reviewer']);
foreach ($reviewers as $r) {
wp_mail(
$r->user_email,
'طلب جديد بانتظار المراجعة #' . $request_id,
'يوجد طلب جديد بحاجة إلى مراجعة في منصة تصحيح الأوضاع.'
);
}
}
}
📋 القسم الثامن: واجهة API للتكامل الحكومي
php
<?php
class YM_API {
public function __construct() {
add_action('rest_api_init', [$this, 'register_routes']);
}
public function register_routes(): void {
register_rest_route('ym/v1', '/requests', [
'methods' => 'POST',
'callback' => [$this, 'create_request'],
'permission_callback' => [$this, 'verify_hmac'],
]);
register_rest_route('ym/v1', '/requests/(?P<id>\d+)', [
'methods' => 'GET',
'callback' => [$this, 'get_request'],
'permission_callback' => [$this, 'verify_hmac'],
]);
register_rest_route('ym/v1', '/requests/(?P<id>\d+)/status', [
'methods' => 'PATCH',
'callback' => [$this, 'update_status'],
'permission_callback' => [$this, 'verify_hmac'],
]);
}
/** HMAC Authentication مع الجهات الحكومية */
public function verify_hmac(WP_REST_Request $req): bool {
$signature = $req->get_header('x-ym-signature');
$timestamp = $req->get_header('x-ym-timestamp');
if (!$signature || !$timestamp) return false;
if (abs(time() - (int) $timestamp) > 300) return false; // 5 دقائق
$secret = get_option('ym_api_secret');
$payload = $timestamp . '.' . $req->get_body();
$expected = hash_hmac('sha256', $payload, $secret);
return hash_equals($expected, $signature);
}
public function create_request(WP_REST_Request $req): WP_REST_Response {
$data = $req->get_json_params();
$errors = YM_Validator::validate($data);
if (!empty($errors)) {
return new WP_REST_Response(['errors' => $errors], 422);
}
$id = YM_DB::insert_request($data);
return new WP_REST_Response(['id' => $id, 'status' => 'pending'], 201);
}
public function get_request(WP_REST_Request $req): WP_REST_Response {
$request = YM_DB::get_request((int) $req['id']);
if (!$request) return new WP_REST_Response(['error' => 'not_found'], 404);
return new WP_REST_Response($request, 200);
}
public function update_status(WP_REST_Request $req): WP_REST_Response {
$id = (int) $req['id'];
$status = sanitize_key($req->get_param('status'));
if (!in_array($status, ['under_review','approved','rejected'], true)) {
return new WP_REST_Response(['error' => 'invalid_status'], 400);
}
YM_DB::update_status($id, $status);
YM_Audit_Log::log($id, get_current_user_id(), 'status_changed', null, ['status' => $status]);
return new WP_REST_Response(['success' => true], 200);
}
}
📋 القسم التاسع: الأمان والامتثال
| الإجراء | التنفيذ |
|---|---|
| تشفير النقل | TLS 1.3 إجباري + HSTS |
| تشفير التخزين | AES-256 للحقول الحساسة (id_number, mobile) |
| التحقق الثنائي | 2FA للمراجعين والمديرين (TOTP/SMS) |
| حماية الملفات | رفع خارج webroot + فحص ClamAV + hash SHA-256 |
| WAF | Cloudflare WAF + قواعد OWASP Top 10 |
| Rate Limiting | 5 محاولات تسجيل/دقيقة لكل IP |
| Audit Log | كل عملية مسجّلة (من، ماذا، متى، IP) |
| الامتثال | NCA-ECC، ISO 27001، PDPL السعودي، GDPR (اختياري) |
| إخفاء البيانات | PII Masking في السجلات العامة |
| النسخ الاحتياطي | يومي مشفر + استرجاع باختبار شهري |
📋 القسم العاشر: تجربة المستخدم (UX)
10.1 مبادئ التصميم
- RTL كامل مع خط عربي واضح (IBM Plex Sans Arabic / Cairo).
- نماذج متعددة الخطوات لتفادي الإطالة على المستخدم.
- تحقق فوري (Inline Validation) مع رسائل عربية مطابقة للنصوص المطلوبة.
- إمكانية الوصول (WCAG 2.1 AA).
- متوافق مع الجوال (Mobile-first).
10.2 رحلة المستخدم
text
[الرئيسية] → [نموذج التسجيل] → [رفع المرفقات]
→ [إرسال للمراجعة] → [طباعة: بطاقة → بيانات → مستندات → إرشادات]
→ [إمكانية إعادة الطباعة برقم مرجعي]
📋 القسم الحادي عشر: محرك الردود بالذكاء الاصطناعي (AI Prompt Response Engine)
11.1 الغرض
نظام ذكي يستقبل استفسارات المستفيدين ويولّد ردودًا فورية بالعربية مع توجيه دقيق مطابق للنموذج والقواعد.
11.2 بنية المحرك
php
<?php
class YM_AI_Prompt_Engine {
private string $system_prompt = <<<PROMPT
أنت مساعد رسمي لمنصة "لجنة تصحيح أوضاع اليمنيين في المملكة العربية السعودية".
القواعد الإلزامية التي يجب أن تلتزم بها في كل رد:
1. من يحمل جواز سفر يمني لا يحتاج إلى استخراج وثيقة مؤقتة.
2. الاسم يجب أن يكون رباعياً ويحتوي على حروف فقط.
3. الحالة الاجتماعية مطلوبة (أعزب/متزوج/مطلق/أرمل).
4. الجنس مطلوب (ذكر/أنثى).
5. المهنة مطلوبة.
6. مكان الميلاد مطلوب.
7. تاريخ الميلاد يجب أن يكون صحيحاً وغير مستقبلي.
8. مكان الإقامة مطلوب.
9. رقم الجوال يجب أن يبدأ بـ 9665 ويتبعه 8 أرقام.
10. البريد الإلكتروني مطلوب.
11. المنطقة مطلوبة.
12. المحافظة والمديرية والقرية مطلوبة للعنوان في اليمن.
13. الصورة الشخصية إجبارية (jpg/png).
14. المرفقات الأخرى اختيارية (jpg/png/pdf - حتى 5MB).
15. زر "طباعة وإرسال الطلب" يرسل الطلب للمراجعة ثم يفتح حزمة الطباعة بالترتيب:
بطاقة التوثيق المؤقتة → بيانات المستفيد → المستندات (عدا الصورة) → الإرشادات.
16. تبقى البيانات ظاهرة بعد الإرسال لإعادة الطباعة.
التزم باللغة العربية الفصحى الرسمية، واستخدم نبرة محترمة وواضحة.
PROMPT;
public function respond(string $user_query, array $context = []): string {
$payload = [
'model' => 'gpt-4o-mini', // أو claude-3-5-sonnet
'messages' => [
['role' => 'system', 'content' => $this->system_prompt],
['role' => 'user', 'content' => $this->build_user_message($user_query, $context)],
],
'temperature' => 0.2,
'max_tokens' => 800,
];
$response = wp_remote_post('https://api.openai.com/v1/chat/completions', [
'headers' => [
'Authorization' => 'Bearer ' . get_option('ym_openai_key'),
'Content-Type' => 'application/json',
],
'body' => wp_json_encode($payload),
'timeout' => 30,
]);
if (is_wp_error($response)) {
return 'عذراً، تعذّر معالجة طلبك حالياً. يرجى المحاولة لاحقاً.';
}
$body = json_decode(wp_remote_retrieve_body($response), true);
return $body['choices'][0]['message']['content'] ?? 'لا يوجد رد.';
}
private function build_user_message(string $q, array $ctx): string {
$context_str = '';
if (!empty($ctx['request_status'])) {
$context_str = "\nحالة الطلب الحالي: {$ctx['request_status']}"
. "\nرقم مرجعي: " . ($ctx['reference_no'] ?? '-');
}
return "استفسار المستفيد: {$q}{$context_str}";
}
}
11.3 نقطة نهاية REST للمحرك
php
register_rest_route('ym/v1', '/assistant', [
'methods' => 'POST',
'callback' => function (WP_REST_Request $req) {
$engine = new YM_AI_Prompt_Engine();
$answer = $engine->respond(
sanitize_text_field($req->get_param('query')),
['request_status' => $req->get_param('status')]
);
return new WP_REST_Response(['answer' => $answer], 200);
},
'permission_callback' => '__return_true', // مع Rate Limiting
]);
11.4 نموذج Prompt-Response جاهز (للاختبار المباشر)
🎯 System Prompt (قالب موحد قابل لإعادة الاستخدام)
text
[ROLE] أنت مساعد رسمي لمنصة حكومية تابعة للجمهورية اليمنية – لجنة تصحيح أوضاع اليمنيين في السعودية. [OBJECTIVE] مساعدة المستفيدين في إكمال تسجيل بياناتهم بدقة، وتوجيههم خلال حزمة الطباعة. [RULES] - الاسم: رباعي، حروف فقط. - جواز يمني = لا حاجة لوثيقة مؤقتة. - الحقول المطلوبة: الحالة الاجتماعية، الجنس، المهنة، مكان الميلاد، تاريخ الميلاد، مكان الإقامة، رقم الجوال (9665XXXXXXXX)، البريد، المنطقة، المحافظة، المديرية، القرية، الصورة الشخصية. - المرفقات: jpg/png/pdf، بحد أقصى 5MB لكل ملف. - بعد الإرسال: تُطبع الحزمة بالترتيب (بطاقة → بيانات → مستندات → إرشادات)، ويمكن إعادة الطباعة. [TONE] رسمي، محترم، موجز، عربي فصيح. [OUTPUT FORMAT] نص عربي منظم مع عناوين فرعية عند الحاجة.
📥 Input (استفسار المستخدم)
json
{
"query": "لماذا لا يظهر لي زر الطباعة بعد الإرسال؟",
"context": { "request_status": "pending", "reference_no": "YM-2025-000123" }
}
📤 Output (رد المحرك)
text
بعد الضغط على "طباعة وإرسال الطلب" يتم: 1) إرسال طلبك للمراجعة الإدارية. 2) فتح حزمة الطباعة تلقائياً بالترتيب: - بطاقة التوثيق المؤقتة. - بيانات المستفيد. - المستندات المرفقة (عدا الصورة الشخصية). - إرشادات ما بعد الطباعة. رقمك المرجعي: YM-2025-000123 – حالة الطلب: قيد المراجعة. يمكنك إعادة الطباعة في أي وقت باستخدام الرقم المرجعي.
📋 القسم الثاني عشر: خارطة الطريق (Roadmap)
| المرحلة | المدة | المخرجات |
|---|---|---|
| 1. التحليل والتصميم | أسبوعان | Wireframes, ERD, API Spec |
| 2. تطوير إضافة WP | 4 أسابيع | Plugin + Templates + Admin |
| 3. تكامل AI Engine | أسبوع | Assistant + Prompt Layer |
| 4. الأمان والاختبار | أسبوعان | PenTest, Unit Tests, UAT |
| 5. النشر والمراقبة | أسبوع | CI/CD, Monitoring, Backup |
| 6. الصيانة والتحديث | مستمر | تحديثات أمنية + تقارير |
📋 القسم الثالث عشر: مؤشرات الأداء (KPIs)
- ⏱ متوسط زمن التسجيل: < 5 دقائق
- ✅ نسبة نجاح الإرسال: > 99%
- 🛡 عدد الحوادث الأمنية: 0
- 📊 دقة ردود AI: > 95%
- 👥 رضا المستفيدين: > 4.5/5
✅ الخلاصة
تم تحويل جميع بيانات منصة “لجنة تصحيح أوضاع اليمنيين” إلى:
- معمارية نظام كاملة على منصة WordPress + PHP 8.2.
- إضافة مخصصة (Custom Plugin) بقواعد التحقق والطباعة المطلوبة.
- REST API للتكامل الحكومي مع HMAC.
- AI Prompt Response Engine بقواعد إلزامية مطابقة للنموذج.
- إجراءات أمان وامتثال متوافقة مع NCA/ISO 27001/PDPL.
هل تريد أن أُكمل بتوليد الكود الكامل القابل للتثبيت كملف ZIP لإضافة WordPress، أو أن أبني لوحة تحكم المراجع (Reviewer Dashboard) بالتفصيل؟