From 79333a4beeec992a5def1f4b2f8c0ad26a3f0120 Mon Sep 17 00:00:00 2001 From: Hamza-Ayed Date: Mon, 3 Aug 2026 13:22:27 +0300 Subject: [PATCH] Update: 2026-08-03 13:22:27 --- .../Admin/marketing/get_social_reports.php | 60 +++++++++++++++++++ ...6_08_03_create_marketing_engine_tables.sql | 50 ++++++++++++++++ siro_admin/lib/constant/links.dart | 5 ++ .../driver_details_not_active_page.dart | 1 - .../views/admin/captain/register_captain.dart | 1 - .../lib/views/admin/dashboard_widget.dart | 1 - .../marketing/social_intelligence_screen.dart | 35 +++++++---- .../admin/static/advanced_analytics_page.dart | 1 - .../lib/views/invoice/add_invoice_page.dart | 1 - siro_admin/lib/views/widgets/snackbar.dart | 1 - 10 files changed, 140 insertions(+), 16 deletions(-) create mode 100644 backend/Admin/marketing/get_social_reports.php create mode 100644 backend/migrations/2026_08_03_create_marketing_engine_tables.sql diff --git a/backend/Admin/marketing/get_social_reports.php b/backend/Admin/marketing/get_social_reports.php new file mode 100644 index 00000000..64d3f444 --- /dev/null +++ b/backend/Admin/marketing/get_social_reports.php @@ -0,0 +1,60 @@ +prepare(" + SELECT id, platform, report_html, is_weekly, created_at + FROM marketing_reports + $where + ORDER BY created_at DESC + LIMIT $limit + "); + $stmt->execute($params); + $reports = $stmt->fetchAll(PDO::FETCH_ASSOC); + + foreach ($reports as &$r) { + $r['id'] = (int) $r['id']; + $r['is_weekly'] = (int) $r['is_weekly'] === 1; + } + unset($r); + + jsonSuccess($reports); + +} catch (Throwable $e) { + // الجدول قد يكون غير موجود على نشر لم يُطبَّق عليه الترحيل + // 2026_08_03_create_marketing_engine_tables.sql — نُبلغ بوضوح بدل + // إرجاع خطأ عام يُقرأ كـ "لا بيانات". + error_log('[get_social_reports] ' . $e->getMessage()); + jsonError('تعذّر جلب تقارير الذكاء الاجتماعي. راجع سجل الخادم.', 500); +} diff --git a/backend/migrations/2026_08_03_create_marketing_engine_tables.sql b/backend/migrations/2026_08_03_create_marketing_engine_tables.sql new file mode 100644 index 00000000..bdb3f042 --- /dev/null +++ b/backend/migrations/2026_08_03_create_marketing_engine_tables.sql @@ -0,0 +1,50 @@ +-- ============================================================ +-- marketing_tasks + marketing_reports — جدولا محرّك التسويق والبوت الاجتماعي +-- ============================================================ +-- كلا الجدولين مستعمل في الكود ولا وجود لهما في schema_primary.sql — نفس +-- حالة admin_audit_log بالضبط. الأثر: +-- +-- • marketing_tasks هو طابور مهام البوت الاجتماعي: +-- يكتب فيه cron_insert_task.php (كل 4 ساعات) و insert_autonomous_task.php +-- ويقرأ منه marketing_engine/index.php ليخدم socialBot. +-- بغيابه لا يستلم البوت مهمة واحدة أبداً، ويفشل الكرون بصمت. +-- +-- • marketing_reports هو مصدر شاشة "الذكاء الاجتماعي": +-- يكتب فيه telegram_scraper.php (كل 3 ساعات) و cron_weekly_report.php +-- و index.php (evaluate_posts). +-- بغيابه تظهر الشاشة فارغة دائماً — وهو ما لوحظ. +-- +-- الأعمدة مستخرجة من مواضع الاستعمال الفعلية في: +-- marketing_engine/index.php, cron_insert_task.php, cron_weekly_report.php, +-- insert_autonomous_task.php, telegram_scraper.php, insert_test_task.php +-- ============================================================ + +CREATE TABLE IF NOT EXISTS `marketing_tasks` ( + `id` BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY, + `platform` VARCHAR(50) NOT NULL DEFAULT 'facebook', + `type` VARCHAR(100) NOT NULL, + -- 'pending' هي الحالة التي يبحث عنها get_task؛ أي قيمة أخرى تعني + -- أن المهمة قيد التنفيذ أو انتهت. + `status` VARCHAR(30) NOT NULL DEFAULT 'pending', + `target_url` TEXT DEFAULT NULL, + `content_text` TEXT DEFAULT NULL, + `media_url` TEXT DEFAULT NULL, + `error_message` TEXT DEFAULT NULL, + `completed_at` TIMESTAMP NULL DEFAULT NULL, + `created_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, + -- get_task يرشّح بـ status + platform ويرتّب بـ id + KEY `idx_status_platform` (`status`, `platform`), + KEY `idx_created_at` (`created_at`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + +CREATE TABLE IF NOT EXISTS `marketing_reports` ( + `id` BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY, + `platform` VARCHAR(50) NOT NULL DEFAULT 'all', + `report_html` LONGTEXT NOT NULL, + -- cron_weekly_report.php يكتب 1؛ التقارير اللحظية تترك 0 + `is_weekly` TINYINT(1) NOT NULL DEFAULT 0, + `created_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, + -- get_reports يرتّب بـ created_at تنازلياً + KEY `idx_created_at` (`created_at`), + KEY `idx_is_weekly` (`is_weekly`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; diff --git a/siro_admin/lib/constant/links.dart b/siro_admin/lib/constant/links.dart index f093052f..e037ae07 100644 --- a/siro_admin/lib/constant/links.dart +++ b/siro_admin/lib/constant/links.dart @@ -413,6 +413,11 @@ class AppLink { static String withdrawalRequests = "$paymentServerV2/ride/driverPayment/withdrawal_requests.php"; + // تقارير الذكاء الاجتماعي — نقطة إدارية بديلة عن + // marketing_engine/index.php (نقطة البوت المحميّة بـ X-Bot-Token) + static String get socialReports => + "$server/Admin/marketing/get_social_reports.php"; + // وحدة الطعام — الباك إند جاهز في backend/food/admin/ ولا واجهة له static String get foodMerchants => "$server/food/admin/merchants.php"; static String get foodMerchantApprove => diff --git a/siro_admin/lib/views/admin/captain/driver_details_not_active_page.dart b/siro_admin/lib/views/admin/captain/driver_details_not_active_page.dart index d5abfbbf..9ca0f4e6 100644 --- a/siro_admin/lib/views/admin/captain/driver_details_not_active_page.dart +++ b/siro_admin/lib/views/admin/captain/driver_details_not_active_page.dart @@ -17,7 +17,6 @@ class DriverDetailsPage extends StatelessWidget { @override Widget build(BuildContext context) { - final cs = Theme.of(context).colorScheme; controller.getDriverDetails(driverId); return Scaffold( diff --git a/siro_admin/lib/views/admin/captain/register_captain.dart b/siro_admin/lib/views/admin/captain/register_captain.dart index 080a229e..6361e6ce 100644 --- a/siro_admin/lib/views/admin/captain/register_captain.dart +++ b/siro_admin/lib/views/admin/captain/register_captain.dart @@ -14,7 +14,6 @@ class RegisterCaptain extends StatelessWidget { @override Widget build(BuildContext context) { - final cs = Theme.of(context).colorScheme; final controller = Get.put(RegisterCaptainController()); // String text = ''; controller.driveInit(); diff --git a/siro_admin/lib/views/admin/dashboard_widget.dart b/siro_admin/lib/views/admin/dashboard_widget.dart index 5f668551..e6d7b00f 100644 --- a/siro_admin/lib/views/admin/dashboard_widget.dart +++ b/siro_admin/lib/views/admin/dashboard_widget.dart @@ -1,4 +1,3 @@ -import 'package:siro_admin/constant/theme.dart'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; // For Get.width if needed, and .tr import 'package:siro_admin/constant/colors.dart'; // Assuming AppColor is here diff --git a/siro_admin/lib/views/admin/marketing/social_intelligence_screen.dart b/siro_admin/lib/views/admin/marketing/social_intelligence_screen.dart index 3fadb576..7e1d6a81 100644 --- a/siro_admin/lib/views/admin/marketing/social_intelligence_screen.dart +++ b/siro_admin/lib/views/admin/marketing/social_intelligence_screen.dart @@ -1,9 +1,10 @@ import 'dart:convert'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; -import 'package:http/http.dart' as http; import 'package:flutter_widget_from_html_core/flutter_widget_from_html_core.dart'; import '../../../constant/links.dart'; +import '../../../controller/functions/crud.dart'; +import '../../widgets/snackbar.dart'; class SocialIntelligenceController extends GetxController { var isLoading = true.obs; @@ -18,18 +19,32 @@ class SocialIntelligenceController extends GetxController { Future fetchReports() async { try { isLoading(true); - final url = Uri.parse( - '${AppLink.server}/marketing_engine/index.php?action=get_reports'); - final response = await http.get(url); - if (response.statusCode == 200) { - final data = json.decode(response.body); - if (data['status'] == 'success') { - reports.value = data['data'] ?? []; - } + // كانت تستدعي marketing_engine/index.php?action=get_reports بـ + // http.get الخام: نقطة بوت محميّة بـ X-Bot-Token، بلا JWT ولا + // X-Device-FP، فترجع 401 بعد تفعيل مصادقة البوت. النقطة الإدارية + // البديلة تمرّ عبر CRUD فتحمل التوكن وبصمة الجهاز. + final res = + await CRUD().get(link: AppLink.socialReports, payload: {}); + + if (res == 'failure' || res == null) { + mySnackbarError('تعذّر الاتصال بخادم التقارير'); + reports.value = []; + return; + } + + final data = res is String ? json.decode(res) : res; + if (data['status'] == 'success') { + // jsonSuccess يغلّف الحمولة في message لا data + final payload = data['message'] ?? data['data']; + reports.value = payload is List ? payload : []; + } else { + mySnackbarError('${data['message'] ?? 'تعذّر جلب التقارير'}'); + reports.value = []; } } catch (e) { - print('Error fetching reports: $e'); + mySnackbarError('$e'); + reports.value = []; } finally { isLoading(false); } diff --git a/siro_admin/lib/views/admin/static/advanced_analytics_page.dart b/siro_admin/lib/views/admin/static/advanced_analytics_page.dart index 56d0fa1f..2b31143e 100644 --- a/siro_admin/lib/views/admin/static/advanced_analytics_page.dart +++ b/siro_admin/lib/views/admin/static/advanced_analytics_page.dart @@ -651,7 +651,6 @@ class _LegendDot extends StatelessWidget { @override Widget build(BuildContext context) { - final cs = Theme.of(context).colorScheme; return Row( mainAxisSize: MainAxisSize.min, children: [ diff --git a/siro_admin/lib/views/invoice/add_invoice_page.dart b/siro_admin/lib/views/invoice/add_invoice_page.dart index 3ac4c9c0..c60dd330 100644 --- a/siro_admin/lib/views/invoice/add_invoice_page.dart +++ b/siro_admin/lib/views/invoice/add_invoice_page.dart @@ -1,4 +1,3 @@ -import 'package:siro_admin/constant/theme.dart'; import 'dart:convert'; import 'dart:io'; import 'package:flutter/material.dart'; diff --git a/siro_admin/lib/views/widgets/snackbar.dart b/siro_admin/lib/views/widgets/snackbar.dart index 47f70a0e..f35978c0 100644 --- a/siro_admin/lib/views/widgets/snackbar.dart +++ b/siro_admin/lib/views/widgets/snackbar.dart @@ -1,4 +1,3 @@ -import 'package:siro_admin/constant/theme.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:get/get.dart';