""" دوال مساعدة عامة للنظام """ import re import os import json import pandas as pd import numpy as np from datetime import datetime, timedelta import uuid import config def generate_unique_id(prefix=""): """ توليد معرف فريد المعلمات: prefix: بادئة للمعرف (اختياري) الإرجاع: معرف فريد """ unique_id = str(uuid.uuid4()).replace("-", "")[:12] return f"{prefix}{unique_id}" if prefix else unique_id def format_number(number, decimal_places=2): """ تنسيق الأرقام مع إضافة فواصل الآلاف المعلمات: number: الرقم المراد تنسيقه decimal_places: عدد المنازل العشرية (افتراضي: 2) الإرجاع: الرقم المنسق كنص """ if number is None: return "" try: return "{:,.{precision}f}".format(number, precision=decimal_places) except (ValueError, TypeError): return str(number) def format_currency(amount, currency="SAR", decimal_places=2): """ تنسيق المبالغ المالية مع إضافة رمز العملة المعلمات: amount: المبلغ المراد تنسيقه currency: رمز العملة (افتراضي: SAR) decimal_places: عدد المنازل العشرية (افتراضي: 2) الإرجاع: المبلغ المنسق كنص """ if amount is None: return "" try: formatted_amount = "{:,.{precision}f}".format(amount, precision=decimal_places) # تخصيص العرض حسب نوع العملة if currency.upper() in ["SAR", "ريال"]: return f"{formatted_amount} ريال" elif currency.upper() == "USD": return f"${formatted_amount}" elif currency.upper() == "EUR": return f"€{formatted_amount}" else: return f"{formatted_amount} {currency}" except (ValueError, TypeError): return str(amount) def format_date(date_obj, format_str="%Y-%m-%d"): """ تنسيق التاريخ المعلمات: date_obj: كائن التاريخ format_str: صيغة التاريخ (افتراضي: %Y-%m-%d) الإرجاع: التاريخ المنسق كنص """ if date_obj is None: return "" try: if isinstance(date_obj, str): # محاولة تحويل النص إلى تاريخ date_obj = datetime.strptime(date_obj, "%Y-%m-%d") return date_obj.strftime(format_str) except Exception: return str(date_obj) def extract_numbers_from_text(text): """ استخراج الأرقام من النص المعلمات: text: النص المراد استخراج الأرقام منه الإرجاع: قائمة بالأرقام المستخرجة """ if not text: return [] # نمط للبحث عن الأرقام (يدعم الأرقام العشرية والأرقام مع فواصل) number_pattern = r'\d+(?:,\d+)*(?:\.\d+)?' numbers = re.findall(number_pattern, str(text)) # تحويل الأرقام إلى قيم عددية return [float(num.replace(',', '')) for num in numbers] def extract_units_from_text(text): """ استخراج وحدات القياس من النص المعلمات: text: النص المراد استخراج وحدات القياس منه الإرجاع: قائمة بوحدات القياس المستخرجة """ if not text: return [] # قائمة بوحدات القياس الشائعة common_units = [ 'م2', 'م3', 'م.ط', 'متر مربع', 'متر مكعب', 'متر طولي', 'كجم', 'طن', 'جم', 'كيلوجرام', 'لتر', 'مل', 'قطعة', 'عدد', 'وحدة', 'مجموعة', 'زوج', 'يوم', 'ساعة', 'شهر', 'سنة', 'نقطة', 'مخرج' ] # إنشاء نمط بحث للوحدات pattern = r'\b(' + '|'.join(common_units) + r')\b' units = re.findall(pattern, str(text)) return units def safe_convert_to_float(value, default=0.0): """ تحويل آمن للقيمة إلى عدد عشري المعلمات: value: القيمة المراد تحويلها default: القيمة الافتراضية في حالة فشل التحويل (افتراضي: 0.0) الإرجاع: القيمة بعد التحويل """ try: if isinstance(value, str): # إزالة أي فواصل آلاف value = value.replace(',', '') return float(value) except (ValueError, TypeError): return default def safe_convert_to_int(value, default=0): """ تحويل آمن للقيمة إلى عدد صحيح المعلمات: value: القيمة المراد تحويلها default: القيمة الافتراضية في حالة فشل التحويل (افتراضي: 0) الإرجاع: القيمة بعد التحويل """ try: if isinstance(value, str): # إزالة أي فواصل آلاف value = value.replace(',', '') return int(float(value)) except (ValueError, TypeError): return default def save_to_json(data, file_path): """ حفظ البيانات في ملف JSON المعلمات: data: البيانات المراد حفظها file_path: مسار الملف الإرجاع: True في حالة النجاح، False في حالة الفشل """ try: # التأكد من وجود المجلد os.makedirs(os.path.dirname(file_path), exist_ok=True) with open(file_path, 'w', encoding='utf-8') as f: json.dump(data, f, ensure_ascii=False, indent=4) return True except Exception as e: print(f"خطأ في حفظ البيانات إلى JSON: {str(e)}") return False def load_from_json(file_path, default=None): """ تحميل البيانات من ملف JSON المعلمات: file_path: مسار الملف default: القيمة الافتراضية في حالة فشل التحميل (افتراضي: None) الإرجاع: البيانات المحملة """ if not os.path.exists(file_path): return default try: with open(file_path, 'r', encoding='utf-8') as f: return json.load(f) except Exception as e: print(f"خطأ في تحميل البيانات من JSON: {str(e)}") return default def export_to_excel(df, file_path, sheet_name="Sheet1"): """ تصدير DataFrame إلى ملف Excel المعلمات: df: DataFrame المراد تصديره file_path: مسار ملف Excel sheet_name: اسم الصفحة (افتراضي: Sheet1) الإرجاع: True في حالة النجاح، False في حالة الفشل """ try: # التأكد من وجود المجلد os.makedirs(os.path.dirname(file_path), exist_ok=True) # تصدير DataFrame إلى Excel df.to_excel(file_path, sheet_name=sheet_name, index=False) return True except Exception as e: print(f"خطأ في تصدير البيانات إلى Excel: {str(e)}") return False def create_directory_if_not_exists(directory_path): """ إنشاء المجلد إذا لم يكن موجوداً المعلمات: directory_path: مسار المجلد الإرجاع: True في حالة النجاح، False في حالة الفشل """ try: if not os.path.exists(directory_path): os.makedirs(directory_path) return True except Exception as e: print(f"خطأ في إنشاء المجلد: {str(e)}") return False def get_file_extension(file_name): """ الحصول على امتداد الملف المعلمات: file_name: اسم الملف الإرجاع: امتداد الملف """ return os.path.splitext(file_name)[1].lower() def is_file_type_supported(file_name): """ التحقق مما إذا كان نوع الملف مدعوماً المعلمات: file_name: اسم الملف الإرجاع: True إذا كان نوع الملف مدعوماً، False خلاف ذلك """ ext = get_file_extension(file_name) return ext[1:] in config.SUPPORTED_DOCUMENT_TYPES # إزالة النقطة من الامتداد def calculate_percentage_difference(value1, value2): """ حساب نسبة الفرق بين قيمتين المعلمات: value1: القيمة الأولى value2: القيمة الثانية الإرجاع: نسبة الفرق """ if value1 == 0 and value2 == 0: return 0 if value2 == 0: return float('inf') if value1 > 0 else float('-inf') return ((value1 - value2) / abs(value2)) * 100 from openai import OpenAI def get_openai_response(prompt, api_key, model_name="gpt-4"): """ إرسال استعلام إلى OpenAI واسترجاع الرد من النموذج المحدد. """ try: client = OpenAI(api_key=api_key) response = client.chat.completions.create( model=model_name, messages=[ {"role": "user", "content": prompt} ] ) return response.choices[0].message.content.strip() except Exception as e: return f"❌ حدث خطأ أثناء الاتصال بـ OpenAI: {str(e)}"