WAHBi-AI-V2 / utils /helpers.py
EGYADMIN's picture
Create utils/helpers.py
caffd57 verified
import os
import re
import json
import pandas as pd
from typing import Dict, List, Any, Union, Tuple, Optional
from datetime import datetime
def format_currency(amount: float, currency: str = "ريال") -> str:
"""
تنسيق المبالغ المالية
المعاملات:
----------
amount : float
المبلغ
currency : str, optional
العملة (افتراضي: "ريال")
المخرجات:
--------
str
المبلغ بالتنسيق المناسب
"""
if not amount and amount != 0:
return "غير محدد"
# تنسيق الأرقام بالفواصل الآلاف
formatted = f"{amount:,.2f}".replace(".00", "")
# ترتيب العملة حسب اللغة العربية (يمين)
return f"{formatted} {currency}"
def format_percentage(value: float) -> str:
"""
تنسيق النسب المئوية
المعاملات:
----------
value : float
القيمة
المخرجات:
--------
str
النسبة بالتنسيق المناسب
"""
if not value and value != 0:
return "غير محدد"
return f"{value:.2f}%".replace(".00", "")
def format_date(date_obj: Any) -> str:
"""
تنسيق التواريخ
المعاملات:
----------
date_obj : Any
كائن التاريخ
المخرجات:
--------
str
التاريخ بالتنسيق المناسب
"""
if not date_obj:
return "غير محدد"
# إذا كان التاريخ سلسلة نصية
if isinstance(date_obj, str):
try:
date_obj = datetime.strptime(date_obj, "%Y-%m-%d")
except ValueError:
try:
date_obj = datetime.strptime(date_obj, "%Y-%m-%d %H:%M:%S")
except ValueError:
return date_obj
# تنسيق التاريخ بالطريقة العربية
month_names = [
"يناير", "فبراير", "مارس", "إبريل", "مايو", "يونيو",
"يوليو", "أغسطس", "سبتمبر", "أكتوبر", "نوفمبر", "ديسمبر"
]
return f"{date_obj.day} {month_names[date_obj.month - 1]} {date_obj.year}"
def extract_keywords(text: str, keywords: List[str], context_size: int = 50) -> List[Dict[str, str]]:
"""
استخراج الكلمات المفتاحية من النص مع سياقها
المعاملات:
----------
text : str
النص المراد البحث فيه
keywords : List[str]
قائمة الكلمات المفتاحية
context_size : int, optional
حجم السياق بالأحرف قبل وبعد الكلمة (افتراضي: 50)
المخرجات:
--------
List[Dict[str, str]]
قائمة بالكلمات المفتاحية وسياقها
"""
results = []
for keyword in keywords:
# البحث عن الكلمة المفتاحية في النص
pattern = re.compile(r'\\b' + re.escape(keyword) + r'\\b', re.IGNORECASE | re.MULTILINE)
matches = pattern.finditer(text)
for match in matches:
start_idx = max(0, match.start() - context_size)
end_idx = min(len(text), match.end() + context_size)
# استخراج السياق
context = text[start_idx:end_idx]
# إضافة النتيجة
results.append({
"keyword": keyword,
"context": context,
"position": match.start()
})
# ترتيب النتائج حسب الموقع في النص
results = sorted(results, key=lambda x: x["position"])
return results
def calculate_progress(current: float, total: float) -> Dict[str, Any]:
"""
حساب نسبة الإنجاز
المعاملات:
----------
current : float
القيمة الحالية
total : float
القيمة الإجمالية
المخرجات:
--------
Dict[str, Any]
معلومات التقدم
"""
if total == 0:
return {
"percentage": 0,
"status": "لم يبدأ",
"color": "gray"
}
percentage = min(100, (current / total) * 100)
if percentage == 0:
status = "لم يبدأ"
color = "gray"
elif percentage < 25:
status = "بداية"
color = "red"
elif percentage < 50:
status = "قيد التنفيذ"
color = "orange"
elif percentage < 75:
status = "متقدم"
color = "blue"
elif percentage < 100:
status = "شبه مكتمل"
color = "teal"
else:
status = "مكتمل"
color = "green"
return {
"percentage": round(percentage, 1),
"status": status,
"color": color
}
def create_directory_structure(base_dir: str, structure: Dict[str, Any]) -> None:
"""
إنشاء هيكل المجلدات
المعاملات:
----------
base_dir : str
المجلد الأساسي
structure : Dict[str, Any]
هيكل المجلدات
"""
os.makedirs(base_dir, exist_ok=True)
for key, value in structure.items():
path = os.path.join(base_dir, key)
if isinstance(value, dict):
# إذا كانت القيمة قاموساً، استمر في إنشاء الهيكل الفرعي
create_directory_structure(path, value)
else:
# إنشاء المجلد
os.makedirs(path, exist_ok=True)
# إذا كانت القيمة قائمة، إنشاء ملفات فارغة
if isinstance(value, list):
for file_name in value:
file_path = os.path.join(path, file_name)
if not os.path.exists(file_path):
with open(file_path, 'w', encoding='utf-8') as f:
# يمكن كتابة محتوى افتراضي هنا
pass
def export_to_excel(data: List[Dict[str, Any]], file_path: str, sheet_name: str = "Sheet1") -> bool:
"""
تصدير البيانات إلى ملف Excel
المعاملات:
----------
data : List[Dict[str, Any]]
البيانات المراد تصديرها
file_path : str
مسار الملف
sheet_name : str, optional
اسم ورقة العمل (افتراضي: "Sheet1")
المخرجات:
--------
bool
نجاح أو فشل العملية
"""
try:
# تحويل البيانات إلى DataFrame
df = pd.DataFrame(data)
# تصدير إلى Excel
df.to_excel(file_path, sheet_name=sheet_name, index=False)
return True
except Exception as e:
print(f"Error exporting to Excel: {str(e)}")
return False
def export_to_json(data: Any, file_path: str) -> bool:
"""
تصدير البيانات إلى ملف JSON
المعاملات:
----------
data : Any
البيانات المراد تصديرها
file_path : str
مسار الملف
المخرجات:
--------
bool
نجاح أو فشل العملية
"""
try:
# إنشاء المجلد إذا لم يكن موجوداً
os.makedirs(os.path.dirname(file_path), exist_ok=True)
# تصدير إلى JSON
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"Error exporting to JSON: {str(e)}")
return False
def validate_input(input_data: Dict[str, Any], validation_rules: Dict[str, Dict[str, Any]]) -> Dict[str, List[str]]:
"""
التحقق من صحة البيانات المدخلة
المعاملات:
----------
input_data : Dict[str, Any]
البيانات المدخلة
validation_rules : Dict[str, Dict[str, Any]]
قواعد التحقق
المخرجات:
--------
Dict[str, List[str]]
قائمة بالأخطاء لكل حقل
"""
errors = {}
for field, rules in validation_rules.items():
field_errors = []
value = input_data.get(field)
# التحقق من الحقول المطلوبة
if rules.get("required", False) and (value is None or (isinstance(value, str) and value.strip() == "")):
field_errors.append("هذا الحقل مطلوب")
# التحقق من النوع
if value is not None and "type" in rules:
expected_type = rules["type"]
if expected_type == "number" and not (isinstance(value, (int, float)) or (isinstance(value, str) and value.strip().replace(".", "", 1).isdigit())):
field_errors.append("يجب أن يكون هذا الحقل رقماً")
elif expected_type == "email" and not re.match(r'^[\w\.-]+@[\w\.-]+\.\w+$', str(value)):
field_errors.append("يرجى إدخال بريد إلكتروني صحيح")
elif expected_type == "date" and not re.match(r'^\d{4}-\d{2}-\d{2}$', str(value)):
field_errors.append("يرجى إدخال تاريخ صحيح (YYYY-MM-DD)")
# التحقق من الحد الأدنى والأقصى
if value is not None and isinstance(value, (int, float)):
if "min" in rules and value < rules["min"]:
field_errors.append(f"يجب أن يكون هذا الحقل أكبر من أو يساوي {rules['min']}")
if "max" in rules and value > rules["max"]:
field_errors.append(f"يجب أن يكون هذا الحقل أصغر من أو يساوي {rules['max']}")
# التحقق من طول النص
if value is not None and isinstance(value, str):
if "min_length" in rules and len(value) < rules["min_length"]:
field_errors.append(f"يجب أن يحتوي هذا الحقل على {rules['min_length']} أحرف على الأقل")
if "max_length" in rules and len(value) > rules["max_length"]:
field_errors.append(f"يجب أن يحتوي هذا الحقل على {rules['max_length']} أحرف كحد أقصى")
# إضافة الأخطاء إذا وجدت
if field_errors:
errors[field] = field_errors
return errors