From 250e0aa7bbb74ba5a62d44cf4dae4388ba679b8c Mon Sep 17 00:00:00 2001 From: Marwan Alwali Date: Mon, 26 May 2025 15:17:10 +0300 Subject: [PATCH] update --- api/migrations/0001_initial.py | 2 +- car_inventory/urls.py | 2 +- haikalbot.zip | Bin 0 -> 61166 bytes ...c Language Support in Django AI Analyst.md | 204 + haikalbot/README.md | 163 + haikalbot/admin.py | 15 +- haikalbot/analysis_utils.py | 231 + haikalbot/chatbot_logic.py | 13 - haikalbot/haikalbot_01.png | Bin 0 -> 7807 bytes .../langchain_ollama_integration_guide.md | 312 ++ haikalbot/migrations/0001_initial.py | 2 +- haikalbot/migrations/0002_initial.py | 2 +- haikalbot/migrations/0003_analysiscache.py | 33 + ..._options_alter_chatlog_options_and_more.py | 36 + haikalbot/models.py | 66 +- haikalbot/ollama_model_recommendations.md | 76 + haikalbot/services/analysis_service.py | 319 ++ haikalbot/services/cache_service.py | 101 + haikalbot/services/llm_service.py | 99 + haikalbot/temp.txt | 80 + haikalbot/training_prompt.md | 161 + haikalbot/training_prompt_arabic.md | 161 + haikalbot/urls.py | 3 +- haikalbot/utils/response_formatter.py | 119 + haikalbot/views.py | 257 +- install_marwan.sh | 8 + inventory/migrations/0001_initial.py | 62 +- ..._is_sold.py => 0002_carfinance_is_sold.py} | 2 +- inventory/migrations/0002_vendor_active.py | 18 - .../0003_alter_opportunity_customer.py | 19 - inventory/migrations/0004_opportunity_slug.py | 18 - inventory/migrations/0005_notes_dealer.py | 20 - .../migrations/0006_organization_slug.py | 18 - .../0007_staff_active_staff_slug.py | 23 - inventory/migrations/0008_lead_salary.py | 18 - inventory/migrations/0009_car_item_model.py | 20 - .../migrations/0010_alter_car_item_model.py | 20 - .../migrations/0011_alter_car_item_model.py | 20 - inventory/urls.py | 1 + inventory/views.py | 4 + load_initial_data_marwan.sh | 46 + locale/ar/LC_MESSAGES/django.mo | Bin 234591 -> 252362 bytes locale/ar/LC_MESSAGES/django.po | 4125 +++++++++-------- plan.json | 50 + planpricing.json | 86 + planquota.json | 68 + pricing.json | 24 + quota.json | 32 + requirements.txt | 99 +- static/images/favicons/haikalbot_v1.png | Bin 0 -> 34443 bytes static/images/favicons/haikalbot_v2.png | Bin 0 -> 66777 bytes templates/account/signup-wizard.html | 1 + templates/crm/leads/lead_tracking.html | 29 +- templates/crm/leads/lead_view.html | 2 +- templates/haikalbot/chatbot.html | 506 +- templates/header.html | 2 + templates/terms_and_privacy.html | 271 ++ test.txt | 33 + test_ollama.py | 194 + 59 files changed, 6032 insertions(+), 2264 deletions(-) create mode 100644 haikalbot.zip create mode 100644 haikalbot/Optimizing Qwen3-8B for Arabic Language Support in Django AI Analyst.md create mode 100644 haikalbot/README.md create mode 100644 haikalbot/analysis_utils.py create mode 100644 haikalbot/haikalbot_01.png create mode 100644 haikalbot/langchain_ollama_integration_guide.md create mode 100644 haikalbot/migrations/0003_analysiscache.py create mode 100644 haikalbot/migrations/0004_alter_analysiscache_options_alter_chatlog_options_and_more.py create mode 100644 haikalbot/ollama_model_recommendations.md create mode 100644 haikalbot/services/analysis_service.py create mode 100644 haikalbot/services/cache_service.py create mode 100644 haikalbot/services/llm_service.py create mode 100644 haikalbot/temp.txt create mode 100644 haikalbot/training_prompt.md create mode 100644 haikalbot/training_prompt_arabic.md create mode 100644 haikalbot/utils/response_formatter.py create mode 100755 install_marwan.sh rename inventory/migrations/{0012_carfinance_is_sold.py => 0002_carfinance_is_sold.py} (86%) delete mode 100644 inventory/migrations/0002_vendor_active.py delete mode 100644 inventory/migrations/0003_alter_opportunity_customer.py delete mode 100644 inventory/migrations/0004_opportunity_slug.py delete mode 100644 inventory/migrations/0005_notes_dealer.py delete mode 100644 inventory/migrations/0006_organization_slug.py delete mode 100644 inventory/migrations/0007_staff_active_staff_slug.py delete mode 100644 inventory/migrations/0008_lead_salary.py delete mode 100644 inventory/migrations/0009_car_item_model.py delete mode 100644 inventory/migrations/0010_alter_car_item_model.py delete mode 100644 inventory/migrations/0011_alter_car_item_model.py create mode 100755 load_initial_data_marwan.sh create mode 100644 plan.json create mode 100644 planpricing.json create mode 100644 planquota.json create mode 100644 pricing.json create mode 100644 quota.json create mode 100644 static/images/favicons/haikalbot_v1.png create mode 100644 static/images/favicons/haikalbot_v2.png create mode 100644 templates/terms_and_privacy.html create mode 100644 test_ollama.py diff --git a/api/migrations/0001_initial.py b/api/migrations/0001_initial.py index e24aeb44..7441cd65 100644 --- a/api/migrations/0001_initial.py +++ b/api/migrations/0001_initial.py @@ -1,4 +1,4 @@ -# Generated by Django 5.1.7 on 2025-05-04 16:07 +# Generated by Django 5.2.1 on 2025-05-25 23:01 from django.db import migrations, models diff --git a/car_inventory/urls.py b/car_inventory/urls.py index cb957b7a..400f33c0 100644 --- a/car_inventory/urls.py +++ b/car_inventory/urls.py @@ -24,7 +24,7 @@ urlpatterns += i18n_patterns( # path('prometheus/', include('django_prometheus.urls')), path('', include('inventory.urls')), path('ledger/', include('django_ledger.urls', namespace='django_ledger')), - # path("haikalbot/", include("haikalbot.urls")), + path("haikalbot/", include("haikalbot.urls")), path('appointment/', include('appointment.urls')), path('plans/', include('plans.urls')), path("schema/", Schema.as_view()), diff --git a/haikalbot.zip b/haikalbot.zip new file mode 100644 index 0000000000000000000000000000000000000000..ffb7f4627ab9b38d1b192e9f20c9cab4a3c074da GIT binary patch literal 61166 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 NUI$T>)=l`=e*gy|X@md( literal 0 HcmV?d00001 diff --git a/haikalbot/Optimizing Qwen3-8B for Arabic Language Support in Django AI Analyst.md b/haikalbot/Optimizing Qwen3-8B for Arabic Language Support in Django AI Analyst.md new file mode 100644 index 00000000..863c221f --- /dev/null +++ b/haikalbot/Optimizing Qwen3-8B for Arabic Language Support in Django AI Analyst.md @@ -0,0 +1,204 @@ +# Optimizing Qwen3-8B for Arabic Language Support in Django AI Analyst + +This guide provides specific recommendations for using Qwen3-8B with your Django AI Analyst application for Arabic language support. + +## Qwen3-8B Overview + +Qwen3-8B is a powerful multilingual large language model developed by Alibaba Cloud. It offers several advantages for Arabic language processing: + +- **Strong multilingual capabilities**: Trained on diverse multilingual data including Arabic +- **Efficient performance**: 8B parameter size balances capability and resource requirements +- **Instruction following**: Excellent at following structured instructions in multiple languages +- **Context understanding**: Good comprehension of Arabic context and nuances +- **JSON formatting**: Reliable at generating structured JSON outputs + +## Configuration Settings for Qwen3-8B + +Update your Django settings to use Qwen3-8B: + +```python +# In settings.py +OLLAMA_BASE_URL = "http://localhost:11434" +OLLAMA_MODEL = "qwen3:8b" +OLLAMA_TIMEOUT = 120 # Seconds +``` + +## Optimized Parameters for Arabic + +When initializing the Ollama LLM with Qwen3-8B for Arabic, use these optimized parameters: + +```python +def get_ollama_llm(): + """ + Initialize and return an Ollama LLM instance configured for Arabic support with Qwen3-8B. + """ + try: + # Get settings from Django settings or use defaults + base_url = getattr(settings, 'OLLAMA_BASE_URL', 'http://localhost:11434') + model = getattr(settings, 'OLLAMA_MODEL', 'qwen3:8b') + timeout = getattr(settings, 'OLLAMA_TIMEOUT', 120) + + # Configure Ollama with parameters optimized for Qwen3-8B with Arabic + return Ollama( + base_url=base_url, + model=model, + timeout=timeout, + # Parameters optimized for Qwen3-8B with Arabic + parameters={ + "temperature": 0.2, # Lower temperature for more deterministic outputs + "top_p": 0.8, # Slightly reduced for more focused responses + "top_k": 40, # Standard value works well with Qwen3 + "num_ctx": 4096, # Qwen3 supports larger context windows + "num_predict": 2048, # Maximum tokens to generate + "stop": ["```", ""], # Stop sequences for JSON generation + "repeat_penalty": 1.1 # Slight penalty to avoid repetition + } + ) + except Exception as e: + logger.error(f"Error initializing Ollama LLM: {str(e)}") + return None +``` + +## Prompt Template Optimization for Qwen3-8B + +Qwen3-8B responds well to clear, structured prompts. For Arabic analysis, use this optimized template: + +```python +def create_prompt_analyzer_chain(language='ar'): + """ + Create a LangChain for analyzing prompts in Arabic with Qwen3-8B. + """ + llm = get_ollama_llm() + if not llm: + return None + + # Define the prompt template optimized for Qwen3-8B + if language == 'ar': + template = """ + أنت مساعد ذكي متخصص في تحليل نماذج Django. مهمتك هي تحليل الاستعلام التالي وتحديد: + 1. نوع التحليل المطلوب + 2. نماذج البيانات المستهدفة + 3. أي معلمات استعلام + + الاستعلام: {prompt} + + قم بتقديم إجابتك بتنسيق JSON فقط، بدون أي نص إضافي، كما يلي: + ```json + {{ + "analysis_type": "count" أو "relationship" أو "performance" أو "statistics" أو "general", + "target_models": ["ModelName1", "ModelName2"], + "query_params": {{"field1": "value1", "field2": "value2"}} + }} + ``` + """ + else: + template = """ + You are an intelligent assistant specialized in analyzing Django models. Your task is to analyze the following prompt and determine: + 1. The type of analysis required + 2. Target data models + 3. Any query parameters + + Prompt: {prompt} + + Provide your answer in JSON format only, without any additional text, as follows: + ```json + { + "analysis_type": "count" or "relationship" or "performance" or "statistics" or "general", + "target_models": ["ModelName1", "ModelName2"], + "query_params": {"field1": "value1", "field2": "value2"} + } + ``` + """ + + # Create the prompt template + prompt_template = PromptTemplate( + input_variables=["prompt"], + template=template + ) + + # Create and return the LLM chain + return LLMChain(llm=llm, prompt=prompt_template) +``` + +## Improved JSON Parsing for Qwen3-8B Responses + +Qwen3-8B sometimes includes markdown formatting in its JSON responses. Use this improved parsing function: + +```python +def _parse_llm_json_response(result): + """ + Parse JSON from Qwen3-8B response, handling markdown formatting. + """ + try: + # First try to extract JSON from markdown code blocks + json_match = re.search(r'```(?:json)?\s*([\s\S]*?)\s*```', result) + if json_match: + json_str = json_match.group(1).strip() + return json.loads(json_str) + + # If no markdown blocks, try to find JSON object directly + json_match = re.search(r'({[\s\S]*})', result) + if json_match: + json_str = json_match.group(1).strip() + return json.loads(json_str) + + # If still no match, try to parse the entire response as JSON + return json.loads(result.strip()) + except Exception as e: + logger.warning(f"Failed to parse JSON from LLM response: {str(e)}") + return None +``` + +## Performance Considerations for Qwen3-8B + +- **Memory Usage**: Qwen3-8B typically requires 8-16GB of RAM when running on Ollama +- **First Request Latency**: The first request may take 5-10 seconds as the model loads +- **Subsequent Requests**: Typically respond within 1-3 seconds +- **Batch Processing**: Consider batching multiple analyses for efficiency + +## Handling Arabic-Specific Challenges with Qwen3-8B + +1. **Diacritics**: Qwen3-8B handles Arabic diacritics well, but for consistency, consider normalizing input by removing diacritics + +2. **Text Direction**: When displaying results in frontend, ensure proper RTL (right-to-left) support + +3. **Dialectal Variations**: Qwen3-8B performs best with Modern Standard Arabic (MSA), but has reasonable support for major dialects + +4. **Technical Terms**: For Django-specific technical terms, consider providing a glossary in both English and Arabic + +## Example Arabic Prompts Optimized for Qwen3-8B + +``` +# Count query +كم عدد السيارات المتوفرة في النظام؟ + +# Relationship analysis +ما هي العلاقة بين نموذج المستخدم ونموذج الطلب؟ + +# Performance analysis +حدد مشاكل الأداء المحتملة في نموذج المنتج + +# Statistical analysis +ما هو متوسط سعر السيارات المتوفرة؟ +``` + +## Troubleshooting Qwen3-8B Specific Issues + +1. **Incomplete JSON**: If Qwen3-8B returns incomplete JSON, try: + - Reducing the complexity of your prompt + - Lowering the temperature parameter to 0.1 + - Adding explicit JSON formatting instructions + +2. **Arabic Character Encoding**: If you see garbled Arabic text, ensure: + - Your database uses UTF-8 encoding + - All HTTP responses include proper content-type headers + - Frontend properly handles Arabic character rendering + +3. **Slow Response Times**: If responses are slow: + - Consider using the quantized version: `qwen3:8b-q4_0` + - Reduce context window size if full 4096 context isn't needed + - Implement more aggressive caching + +## Conclusion + +Qwen3-8B is an excellent choice for Arabic language support in your Django AI Analyst application. With these optimized settings and techniques, you'll get reliable performance for analyzing Django models through Arabic natural language prompts. diff --git a/haikalbot/README.md b/haikalbot/README.md new file mode 100644 index 00000000..c670987d --- /dev/null +++ b/haikalbot/README.md @@ -0,0 +1,163 @@ +# Django AI Analyst - README + +This package provides a Django application that enables AI-powered analysis of Django models through natural language prompts. The AI agent can analyze model structures, relationships, and data to provide insights in JSON format. + +## Features + +- Natural language prompt processing for model analysis +- Support for various types of insights: + - Count queries (e.g., "How many cars do we have?") + - Relationship analysis between models + - Performance optimization suggestions + - Statistical analysis of model fields + - General model structure analysis +- Dealer-specific data access controls +- Caching mechanism for improved performance +- Visualization data generation for frontend display +- Comprehensive test suite + +## Installation + +1. Add 'ai_analyst' to your INSTALLED_APPS setting: + +```python +INSTALLED_APPS = [ + ... + 'ai_analyst', +] +``` + +2. Include the ai_analyst URLconf in your project urls.py: + +```python +path('api/ai/', include('ai_analyst.urls')), +``` + +3. Run migrations to create the AnalysisCache model: + +```bash +python manage.py makemigrations ai_analyst +python manage.py migrate +``` + +## Usage + +Send POST requests to the `/api/ai/analyze/` endpoint with a JSON body containing: + +```json +{ + "prompt": "How many cars do we have?", + "dealer_id": 1 // Optional, for dealer-specific queries +} +``` + +The response will be a JSON object with insights based on the prompt: + +```json +{ + "status": "success", + "request_id": "a1b2c3d4", + "timestamp": "2025-05-25T23:21:56Z", + "prompt": "How many cars do we have?", + "insights": [ + { + "type": "count_analysis", + "results": [ + { + "model": "Car", + "count": 42, + "filters_applied": {} + } + ], + "visualization_data": { + "chart_type": "bar", + "labels": ["Car"], + "data": [42] + } + } + ] +} +``` + +## Customization + +### Cache Duration + +You can customize the cache duration by setting the `CACHE_DURATION` class variable in the `ModelAnalystView` class: + +```python +# In your settings.py +AI_ANALYST_CACHE_DURATION = 7200 # 2 hours in seconds + +# Then in views.py +class ModelAnalystView(View): + CACHE_DURATION = getattr(settings, 'AI_ANALYST_CACHE_DURATION', 3600) + # ... +``` + +### Permission Logic + +The `_check_permissions` method in `ModelAnalystView` can be customized to match your application's permission model: + +```python +def _check_permissions(self, user, dealer_id): + # Your custom permission logic here + return user.has_perm('ai_analyst.can_analyze_models') +``` + +## Example Prompts + +- "How many cars do we have?" +- "Show relationship between User and Order" +- "What is the average price of products?" +- "Count active users" +- "Identify performance issues in the Order model" +- "Show maximum age of customers" + +## Frontend Integration + +The JSON responses include visualization_data that can be used with charting libraries like Chart.js: + +```javascript +// Example with Chart.js +fetch('/api/ai/analyze/', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ + prompt: 'How many cars do we have?', + dealer_id: 1 + }), +}) +.then(response => response.json()) +.then(data => { + if (data.status === 'success' && data.insights.length > 0) { + const insight = data.insights[0]; + const vizData = insight.visualization_data; + + const ctx = document.getElementById('insightChart').getContext('2d'); + new Chart(ctx, { + type: vizData.chart_type, + data: { + labels: vizData.labels, + datasets: [{ + label: insight.type, + data: vizData.data, + backgroundColor: [ + 'rgba(255, 99, 132, 0.2)', + 'rgba(54, 162, 235, 0.2)', + 'rgba(255, 206, 86, 0.2)' + ], + borderColor: [ + 'rgba(255, 99, 132, 1)', + 'rgba(54, 162, 235, 1)', + 'rgba(255, 206, 86, 1)' + ], + borderWidth: 1 + }] + } + }); + } +}); +``` diff --git a/haikalbot/admin.py b/haikalbot/admin.py index b97a94f6..5acba54b 100644 --- a/haikalbot/admin.py +++ b/haikalbot/admin.py @@ -1,2 +1,15 @@ +from django.contrib import admin +from .models import AnalysisCache -# Register your models here. + +@admin.register(AnalysisCache) +class AnalysisCacheAdmin(admin.ModelAdmin): + list_display = ('prompt_hash', 'dealer_id', 'created_at', 'expires_at', 'is_expired') + list_filter = ('dealer_id', 'created_at') + search_fields = ('prompt_hash',) + readonly_fields = ('prompt_hash', 'created_at', 'updated_at') + + def is_expired(self, obj): + return obj.is_expired() + + is_expired.boolean = True diff --git a/haikalbot/analysis_utils.py b/haikalbot/analysis_utils.py new file mode 100644 index 00000000..b3a0a8d4 --- /dev/null +++ b/haikalbot/analysis_utils.py @@ -0,0 +1,231 @@ +from django.db.models import Avg, Sum, Max, Min, ForeignKey, OneToOneField +import inspect +from django.db import models +from django.utils.translation import gettext_lazy as _ + + +def _localized_keys(language): + if language == 'ar': + return { + 'type': 'نوع', 'model': 'النموذج', 'count': 'العدد', 'filters': 'الفلاتر_المطبقة', + 'error': 'خطأ', 'chart_type': 'نوع_الرسم_البياني', 'labels': 'التسميات', 'data': 'البيانات', + 'visualization_data': 'بيانات_الرسم_البياني', 'field': 'الحقل', 'value': 'القيمة', + 'statistic_type': 'نوع_الإحصاء', 'results': 'النتائج', 'title': 'العنوان' + } + else: + return { + 'type': 'type', 'model': 'model', 'count': 'count', 'filters': 'filters_applied', + 'error': 'error', 'chart_type': 'chart_type', 'labels': 'labels', 'data': 'data', + 'visualization_data': 'visualization_data', 'field': 'field', 'value': 'value', + 'statistic_type': 'statistic_type', 'results': 'results', 'title': 'title' + } + + +def generate_count_insight(models, query_params, dealer_id=None, language='ar'): + keys = _localized_keys(language) + results = [] + + for model in models: + try: + queryset = model.objects.all() + + if dealer_id: + if hasattr(model, 'dealer_id'): + queryset = queryset.filter(dealer_id=dealer_id) + elif hasattr(model, 'dealer'): + queryset = queryset.filter(dealer=dealer_id) + + filters = {} + for key, value in query_params.items(): + if key not in ['field', 'operation'] and hasattr(model, key): + try: + field = model._meta.get_field(key) + if isinstance(field, models.IntegerField): + value = int(value) + elif isinstance(field, models.BooleanField): + value = value.lower() in ('true', '1', 'yes') + except Exception: + pass + filters[key] = value + + if filters: + queryset = queryset.filter(**filters) + + results.append({ + keys['model']: model.__name__, + keys['count']: queryset.count(), + keys['filters']: filters + }) + + except Exception as e: + results.append({ + keys['model']: model.__name__, + keys['error']: str(e) + }) + + return { + 'type': keys['type'] + '_analysis', + keys['results']: results, + keys['visualization_data']: { + keys['chart_type']: 'bar', + keys['labels']: [r[keys['model']] for r in results if keys['count'] in r], + keys['data']: [r[keys['count']] for r in results if keys['count'] in r] + } + } + + +def generate_statistics_insight(models, query_params, dealer_id=None, language='ar'): + keys = _localized_keys(language) + results = [] + field = query_params.get('field') + operation = query_params.get('operation', 'average') + + for model in models: + try: + if not field or not hasattr(model, field): + continue + + queryset = model.objects.all() + if dealer_id: + if hasattr(model, 'dealer_id'): + queryset = queryset.filter(dealer_id=dealer_id) + elif hasattr(model, 'dealer'): + queryset = queryset.filter(dealer=dealer_id) + + filters = {} + for k, v in query_params.items(): + if k not in ['field', 'operation'] and hasattr(model, k): + filters[k] = v + + if filters: + queryset = queryset.filter(**filters) + + stat_map = { + 'average': Avg, + 'sum': Sum, + 'max': Max, + 'min': Min + } + + if operation in stat_map: + agg = queryset.aggregate(val=stat_map[operation](field))['val'] + value = agg + else: + value = queryset.count() + + results.append({ + keys['model']: model.__name__, + keys['field']: field, + keys['statistic_type']: operation, + keys['value']: value, + keys['filters']: filters + }) + + except Exception as e: + results.append({keys['model']: model.__name__, keys['error']: str(e)}) + + return { + 'type': keys['type'] + '_analysis', + keys['results']: results, + keys['visualization_data']: { + keys['chart_type']: 'bar', + keys['labels']: [f"{r[keys['model']]}.{r[keys['field']]}" for r in results if keys['value'] in r], + keys['data']: [r[keys['value']] for r in results if keys['value'] in r], + keys['title']: f"{operation} of {field}" if language != 'ar' else f"{field} ({operation})" + } + } + + +def generate_recommendations(model_classes, analysis_type, language='ar'): + recs = [] + for model in model_classes: + for field in model._meta.fields: + if isinstance(field, ForeignKey) and not field.db_index: + msg = f"أضف db_index=True إلى {model.__name__}.{field.name}" if language == 'ar' else f"Add db_index=True to {model.__name__}.{field.name}" + recs.append(msg) + if isinstance(field, models.CharField) and not field.db_index and field.name in ['name', 'title', 'description', 'text']: + msg = f"فكر في فهرسة الحقل النصي {model.__name__}.{field.name}" if language == 'ar' else f"Consider indexing the text field {model.__name__}.{field.name}" + recs.append(msg) + return recs[:5] + + +def generate_model_insight(model, dealer_id=None, language='ar'): + keys = _localized_keys(language) + fields_info = [ + { + 'name': f.name, + 'type': f.__class__.__name__, + 'null': f.null, + 'blank': f.blank, + 'unique': f.unique, + 'pk': f.primary_key + } for f in model._meta.fields + ] + + try: + qs = model.objects.all() + if dealer_id: + if hasattr(model, 'dealer_id'): + qs = qs.filter(dealer_id=dealer_id) + elif hasattr(model, 'dealer'): + qs = qs.filter(dealer=dealer_id) + count = qs.count() + except Exception: + count = "error" + + return { + 'type': keys['type'] + '_analysis', + keys['model']: model.__name__, + 'fields': fields_info, + 'count': count + } + + +def generate_relationship_insight(models, query_params=None, dealer_id=None, language='ar'): + from_ = "من" if language == 'ar' else "from" + to_ = "إلى" if language == 'ar' else "to" + rel_type = "نوع" if language == 'ar' else "type" + relationships = [] + + for model in models: + for field in model._meta.fields: + if isinstance(field, (ForeignKey, OneToOneField)): + relationships.append({ + from_: model.__name__, + to_: field.related_model.__name__, + rel_type: field.__class__.__name__ + }) + for field in model._meta.many_to_many: + relationships.append({ + from_: model.__name__, + to_: field.related_model.__name__, + rel_type: 'ManyToManyField' + }) + + return { + 'type': 'تحليل_العلاقات' if language == 'ar' else 'relationship_analysis', + 'relationships': relationships + } + + +def generate_performance_insight(models, query_params=None, dealer_id=None, language='ar'): + issues = [] + for model in models: + for field in model._meta.fields: + if isinstance(field, ForeignKey) and not field.db_index: + issues.append({ + 'model': model.__name__, + 'field': field.name, + 'issue': 'Missing index on ForeignKey' + }) + if isinstance(field, models.CharField) and not field.db_index and field.name in ['name', 'title']: + issues.append({ + 'model': model.__name__, + 'field': field.name, + 'issue': 'Unindexed CharField used in filtering' + }) + + return { + 'type': 'تحليل_الأداء' if language == 'ar' else 'performance_analysis', + 'issues': issues + } diff --git a/haikalbot/chatbot_logic.py b/haikalbot/chatbot_logic.py index 15390ce0..f493274f 100644 --- a/haikalbot/chatbot_logic.py +++ b/haikalbot/chatbot_logic.py @@ -3,20 +3,7 @@ from inventory import models from car_inventory import settings def fetch_data(dealer): - """ - Fetches the total number of cars in the inventory for the specified dealer. If no cars are - found, returns a message indicating that fact. If an error occurs during the operation, - it returns an error message with details. - :param dealer: The dealer object for which the inventory information is required. - The dealer object must be an instance of a model that includes a - `get_local_name` method for formatting localized dealer names. - :type dealer: Dealer - :return: A string indicating either the total number of cars in the dealer's inventory, - that no cars exist in the inventory, or an error message detailing what went - wrong during the operation. - :rtype: str - """ try: # Annotate total cars by make, model, and trim cars = models.Car.objects.filter(dealer=dealer).count() diff --git a/haikalbot/haikalbot_01.png b/haikalbot/haikalbot_01.png new file mode 100644 index 0000000000000000000000000000000000000000..7b921365252c953d28e7065ce92813e9c93a272c GIT binary patch literal 7807 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 literal 0 HcmV?d00001 diff --git a/haikalbot/langchain_ollama_integration_guide.md b/haikalbot/langchain_ollama_integration_guide.md new file mode 100644 index 00000000..c60020f9 --- /dev/null +++ b/haikalbot/langchain_ollama_integration_guide.md @@ -0,0 +1,312 @@ +# Integrating Ollama with LangChain for Django AI Analyst + +This guide provides step-by-step instructions for integrating Ollama with LangChain in your Django AI Analyst application, with specific focus on Arabic language support. + +## Prerequisites + +1. Ollama installed on your system +2. An Ollama model with Arabic support (preferably Jais-13B as recommended) +3. Django project with the AI Analyst application + +## Installation Steps + +### 1. Install Required Python Packages + +```bash +pip install langchain langchain-community +``` + +### 2. Configure Django Settings + +Add the following to your Django settings.py file: + +```python +# Ollama and LangChain settings +OLLAMA_BASE_URL = "http://localhost:11434" # Default Ollama API URL +OLLAMA_MODEL = "jais:13b" # Or your preferred model +OLLAMA_TIMEOUT = 120 # Seconds +``` + +### 3. Create a LangChain Utility Module + +Create a new file `ai_analyst/langchain_utils.py`: + +```python +from langchain.llms import Ollama +from langchain.chains import LLMChain +from langchain.prompts import PromptTemplate +from django.conf import settings +import logging + +logger = logging.getLogger(__name__) + +def get_ollama_llm(): + """ + Initialize and return an Ollama LLM instance configured for Arabic support. + """ + try: + # Get settings from Django settings or use defaults + base_url = getattr(settings, 'OLLAMA_BASE_URL', 'http://localhost:11434') + model = getattr(settings, 'OLLAMA_MODEL', 'jais:13b') + timeout = getattr(settings, 'OLLAMA_TIMEOUT', 120) + + # Configure Ollama with appropriate parameters for Arabic + return Ollama( + base_url=base_url, + model=model, + timeout=timeout, + # Parameters to improve Arabic language generation + parameters={ + "temperature": 0.7, + "top_p": 0.9, + "top_k": 40, + "num_ctx": 2048, # Context window size + } + ) + except Exception as e: + logger.error(f"Error initializing Ollama LLM: {str(e)}") + return None + +def create_prompt_analyzer_chain(language='ar'): + """ + Create a LangChain for analyzing prompts in Arabic or English. + """ + llm = get_ollama_llm() + if not llm: + return None + + # Define the prompt template based on language + if language == 'ar': + template = """ + قم بتحليل الاستعلام التالي وتحديد نوع التحليل المطلوب ونماذج البيانات المستهدفة وأي معلمات استعلام. + + الاستعلام: {prompt} + + قم بتقديم إجابتك بتنسيق JSON كما يلي: + {{ + "analysis_type": "count" أو "relationship" أو "performance" أو "statistics" أو "general", + "target_models": ["ModelName1", "ModelName2"], + "query_params": {{"field1": "value1", "field2": "value2"}} + }} + """ + else: + template = """ + Analyze the following prompt and determine the type of analysis required, target data models, and any query parameters. + + Prompt: {prompt} + + Provide your answer in JSON format as follows: + { + "analysis_type": "count" or "relationship" or "performance" or "statistics" or "general", + "target_models": ["ModelName1", "ModelName2"], + "query_params": {"field1": "value1", "field2": "value2"} + } + """ + + # Create the prompt template + prompt_template = PromptTemplate( + input_variables=["prompt"], + template=template + ) + + # Create and return the LLM chain + return LLMChain(llm=llm, prompt=prompt_template) +``` + +### 4. Update Your View to Use LangChain + +Modify your `ModelAnalystView` class to use the LangChain utilities: + +```python +from .langchain_utils import create_prompt_analyzer_chain +import json +import re + +class ModelAnalystView(View): + # ... existing code ... + + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + # We'll initialize chains on demand to avoid startup issues + self.prompt_analyzer_chains = {} + + def _get_prompt_analyzer_chain(self, language='ar'): + """ + Get or create a prompt analyzer chain for the specified language. + """ + if language not in self.prompt_analyzer_chains: + self.prompt_analyzer_chains[language] = create_prompt_analyzer_chain(language) + return self.prompt_analyzer_chains[language] + + def _analyze_prompt_with_llm(self, prompt, language='ar'): + """ + Use LangChain and Ollama to analyze the prompt. + """ + try: + # Get the appropriate chain for the language + chain = self._get_prompt_analyzer_chain(language) + if not chain: + # Fallback to rule-based analysis if chain creation failed + return self._analyze_prompt_rule_based(prompt, language) + + # Run the chain + result = chain.run(prompt=prompt) + + # Parse the JSON result + # Find JSON content within the response (in case the LLM adds extra text) + json_match = re.search(r'({.*})', result.replace('\n', ' '), re.DOTALL) + if json_match: + json_str = json_match.group(1) + return json.loads(json_str) + else: + # Fallback to rule-based analysis + return self._analyze_prompt_rule_based(prompt, language) + + except Exception as e: + logger.error(f"Error in LLM prompt analysis: {str(e)}") + # Fallback to rule-based analysis + return self._analyze_prompt_rule_based(prompt, language) + + def _analyze_prompt_rule_based(self, prompt, language='ar'): + """ + Rule-based fallback for prompt analysis. + """ + analysis_type, target_models, query_params = self._analyze_prompt(prompt, language) + return { + "analysis_type": analysis_type, + "target_models": target_models, + "query_params": query_params + } + + def _process_prompt(self, prompt, user, dealer_id, language='ar'): + """ + Process the natural language prompt and generate insights. + """ + # ... existing code ... + + # Use LLM for prompt analysis + analysis_result = self._analyze_prompt_with_llm(prompt, language) + analysis_type = analysis_result.get('analysis_type', 'general') + target_models = analysis_result.get('target_models', []) + query_params = analysis_result.get('query_params', {}) + + # ... rest of the method ... +``` + +## Testing the Integration + +Create a test script to verify the Ollama and LangChain integration: + +```python +# test_ollama.py +import os +import sys +import django + +# Set up Django environment +os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'your_project.settings') +django.setup() + +from ai_analyst.langchain_utils import get_ollama_llm, create_prompt_analyzer_chain + +def test_ollama_connection(): + """Test basic Ollama connection and response.""" + llm = get_ollama_llm() + if not llm: + print("Failed to initialize Ollama LLM") + return + + # Test with Arabic prompt + arabic_prompt = "مرحبا، كيف حالك؟" + print(f"Testing Arabic prompt: {arabic_prompt}") + try: + response = llm.invoke(arabic_prompt) + print(f"Response: {response}") + print("Ollama connection successful!") + except Exception as e: + print(f"Error: {str(e)}") + +def test_prompt_analysis(): + """Test the prompt analyzer chain.""" + chain = create_prompt_analyzer_chain('ar') + if not chain: + print("Failed to create prompt analyzer chain") + return + + # Test with an Arabic analysis prompt + analysis_prompt = "كم عدد السيارات التي لدينا؟" + print(f"Testing analysis prompt: {analysis_prompt}") + try: + result = chain.run(prompt=analysis_prompt) + print(f"Analysis result: {result}") + except Exception as e: + print(f"Error: {str(e)}") + +if __name__ == "__main__": + print("Testing Ollama and LangChain integration...") + test_ollama_connection() + print("\n---\n") + test_prompt_analysis() +``` + +Run the test script: + +```bash +python test_ollama.py +``` + +## Troubleshooting + +### Common Issues and Solutions + +1. **Ollama Connection Error** + - Ensure Ollama is running: `ollama serve` + - Check if the model is downloaded: `ollama list` + - Verify the base URL in settings + +2. **Model Not Found** + - Download the model: `ollama pull jais:13b` + - Check model name spelling in settings + +3. **Timeout Errors** + - Increase the timeout setting for complex queries + - Consider using a smaller model if your hardware is limited + +4. **Poor Arabic Analysis** + - Ensure you're using an Arabic-capable model like Jais-13B + - Check that your prompts are properly formatted in Arabic + - Adjust temperature and other parameters for better results + +5. **JSON Parsing Errors** + - Improve the prompt template to emphasize strict JSON formatting + - Implement more robust JSON extraction from LLM responses + +## Performance Optimization + +For production use, consider these optimizations: + +1. **Caching LLM Responses** + - Implement Redis or another caching system for LLM responses + - Cache common analysis patterns to reduce API calls + +2. **Batch Processing** + - For bulk analysis, use batch processing to reduce overhead + +3. **Model Quantization** + - If performance is slow, consider using a quantized version of the model + - Example: `ollama pull jais:13b-q4_0` for a 4-bit quantized version + +4. **Asynchronous Processing** + - For long-running analyses, implement asynchronous processing with Celery + +## Advanced Usage: Fine-tuning for Domain-Specific Analysis + +For improved performance on your specific domain: + +1. Create a dataset of example prompts and expected analyses +2. Use Ollama's fine-tuning capabilities to adapt the model +3. Update your application to use the fine-tuned model + +## Conclusion + +This integration enables your Django AI Analyst to leverage Ollama's powerful language models through LangChain, with specific optimizations for Arabic language support. The fallback to rule-based analysis ensures robustness, while the LLM-based approach provides more natural language understanding capabilities. diff --git a/haikalbot/migrations/0001_initial.py b/haikalbot/migrations/0001_initial.py index a801e7ea..61850a1a 100644 --- a/haikalbot/migrations/0001_initial.py +++ b/haikalbot/migrations/0001_initial.py @@ -1,4 +1,4 @@ -# Generated by Django 5.1.7 on 2025-05-04 16:07 +# Generated by Django 5.2.1 on 2025-05-25 23:01 from django.db import migrations, models diff --git a/haikalbot/migrations/0002_initial.py b/haikalbot/migrations/0002_initial.py index 67dffe26..d8b26a8e 100644 --- a/haikalbot/migrations/0002_initial.py +++ b/haikalbot/migrations/0002_initial.py @@ -1,4 +1,4 @@ -# Generated by Django 5.1.7 on 2025-05-04 16:07 +# Generated by Django 5.2.1 on 2025-05-25 23:01 import django.db.models.deletion from django.db import migrations, models diff --git a/haikalbot/migrations/0003_analysiscache.py b/haikalbot/migrations/0003_analysiscache.py new file mode 100644 index 00000000..5d94804a --- /dev/null +++ b/haikalbot/migrations/0003_analysiscache.py @@ -0,0 +1,33 @@ +# Generated by Django 5.2.1 on 2025-05-26 00:28 + +import django.db.models.deletion +import django.utils.timezone +from django.conf import settings +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('haikalbot', '0002_initial'), + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ] + + operations = [ + migrations.CreateModel( + name='AnalysisCache', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('prompt_hash', models.CharField(db_index=True, max_length=64)), + ('dealer_id', models.IntegerField(blank=True, db_index=True, null=True)), + ('created_at', models.DateTimeField(default=django.utils.timezone.now)), + ('updated_at', models.DateTimeField(auto_now=True)), + ('expires_at', models.DateTimeField()), + ('result', models.JSONField()), + ('user', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)), + ], + options={ + 'indexes': [models.Index(fields=['prompt_hash', 'dealer_id'], name='haikalbot_a_prompt__b98e1e_idx'), models.Index(fields=['expires_at'], name='haikalbot_a_expires_e790cd_idx')], + }, + ), + ] diff --git a/haikalbot/migrations/0004_alter_analysiscache_options_alter_chatlog_options_and_more.py b/haikalbot/migrations/0004_alter_analysiscache_options_alter_chatlog_options_and_more.py new file mode 100644 index 00000000..c61771dd --- /dev/null +++ b/haikalbot/migrations/0004_alter_analysiscache_options_alter_chatlog_options_and_more.py @@ -0,0 +1,36 @@ +# Generated by Django 5.2.1 on 2025-05-26 08:17 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('haikalbot', '0003_analysiscache'), + ('inventory', '0001_initial'), + ] + + operations = [ + migrations.AlterModelOptions( + name='analysiscache', + options={'verbose_name_plural': 'Analysis caches'}, + ), + migrations.AlterModelOptions( + name='chatlog', + options={'ordering': ['-timestamp']}, + ), + migrations.AlterField( + model_name='analysiscache', + name='expires_at', + field=models.DateTimeField(db_index=True), + ), + migrations.AlterField( + model_name='chatlog', + name='timestamp', + field=models.DateTimeField(auto_now_add=True, db_index=True), + ), + migrations.AddIndex( + model_name='chatlog', + index=models.Index(fields=['dealer', 'timestamp'], name='haikalbot_c_dealer__6f8d63_idx'), + ), + ] diff --git a/haikalbot/models.py b/haikalbot/models.py index 1853a4be..fed58f8e 100644 --- a/haikalbot/models.py +++ b/haikalbot/models.py @@ -1,5 +1,8 @@ from django.db import models from inventory.models import Dealer +from django.contrib.auth.models import User +from django.conf import settings +from django.utils import timezone class ChatLog(models.Model): @@ -21,10 +24,67 @@ class ChatLog(models.Model): :ivar timestamp: The date and time when the chat log entry was created. :type timestamp: datetime """ - dealer = models.ForeignKey(Dealer, on_delete=models.CASCADE, related_name='chatlogs') + dealer = models.ForeignKey(Dealer, on_delete=models.CASCADE, related_name='chatlogs', db_index=True) user_message = models.TextField() chatbot_response = models.TextField() - timestamp = models.DateTimeField(auto_now_add=True) + timestamp = models.DateTimeField(auto_now_add=True, db_index=True) + + class Meta: + ordering = ['-timestamp'] + indexes = [ + models.Index(fields=['dealer', 'timestamp']), + ] def __str__(self): - return self.user_message \ No newline at end of file + return f"{self.dealer.name}: {self.user_message[:50]}..." + + +class AnalysisCache(models.Model): + """ + Model to cache analysis results for performance optimization. + + This model stores cached results of model analysis operations to improve + performance for repeated queries. It includes a hash of the prompt, user + information, dealer ID, timestamps, and the cached result in JSON format. + + :ivar prompt_hash: MD5 hash of the prompt + dealer_id + language + :type prompt_hash: str + :ivar user: The user who made the request (optional) + :type user: User + :ivar dealer_id: ID of the dealer associated with this cache entry + :type dealer_id: int + :ivar created_at: When the cache entry was created + :type created_at: datetime + :ivar updated_at: When the cache entry was last updated + :type updated_at: datetime + :ivar expires_at: When the cache entry expires + :type expires_at: datetime + :ivar result: The cached analysis result + :type result: dict + """ + prompt_hash = models.CharField(max_length=64, db_index=True) + user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, null=True, blank=True) + dealer_id = models.IntegerField(null=True, blank=True, db_index=True) + created_at = models.DateTimeField(default=timezone.now) + updated_at = models.DateTimeField(auto_now=True) + expires_at = models.DateTimeField(db_index=True) + result = models.JSONField() + + class Meta: + indexes = [ + models.Index(fields=['prompt_hash', 'dealer_id']), + models.Index(fields=['expires_at']), + ] + verbose_name_plural = "Analysis caches" + + def is_expired(self): + """ + Check if the cache entry has expired. + + :return: True if the cache entry has expired, False otherwise + :rtype: bool + """ + return timezone.now() > self.expires_at + + def __str__(self): + return f"Cache: {self.prompt_hash[:10]}... (Dealer: {self.dealer_id})" diff --git a/haikalbot/ollama_model_recommendations.md b/haikalbot/ollama_model_recommendations.md new file mode 100644 index 00000000..070451dc --- /dev/null +++ b/haikalbot/ollama_model_recommendations.md @@ -0,0 +1,76 @@ +# Recommended Ollama Models for Arabic Language Support + +## Top Recommendations + +1. **Jais-13B** (Recommended) + - **Size**: 13 billion parameters + - **Strengths**: Specifically trained on Arabic content, excellent understanding of Arabic context and nuances + - **Command**: `ollama pull jais:13b` + - **Best for**: Production-quality Arabic language understanding and generation + +2. **BLOOM-7B** + - **Size**: 7 billion parameters + - **Strengths**: Trained on 46 languages including Arabic, good multilingual capabilities + - **Command**: `ollama pull bloom:7b` + - **Best for**: Multilingual applications where Arabic is one of several languages + +3. **Mistral-7B-Instruct** + - **Size**: 7 billion parameters + - **Strengths**: Strong general performance, good instruction following, reasonable Arabic support + - **Command**: `ollama pull mistral:7b-instruct` + - **Best for**: General purpose applications with moderate Arabic requirements + +4. **Qwen2-7B** + - **Size**: 7 billion parameters + - **Strengths**: Good multilingual capabilities including Arabic + - **Command**: `ollama pull qwen2:7b` + - **Best for**: Applications requiring both Chinese and Arabic support + +## Comparison Table + +| Model | Size | Arabic Support | Instruction Following | Resource Requirements | Command | +|-------|------|---------------|----------------------|----------------------|---------| +| Jais-13B | 13B | Excellent | Very Good | High (16GB+ RAM) | `ollama pull jais:13b` | +| BLOOM-7B | 7B | Good | Good | Medium (8GB+ RAM) | `ollama pull bloom:7b` | +| Mistral-7B-Instruct | 7B | Moderate | Excellent | Medium (8GB+ RAM) | `ollama pull mistral:7b-instruct` | +| Qwen2-7B | 7B | Good | Very Good | Medium (8GB+ RAM) | `ollama pull qwen2:7b` | + +## Justification for Jais-13B Recommendation + +Jais-13B is specifically recommended for your Django AI Analyst application because: + +1. **Arabic-First Design**: Unlike most models that treat Arabic as one of many languages, Jais was specifically designed for Arabic language understanding and generation. + +2. **Cultural Context**: The model has better understanding of Arabic cultural contexts and nuances, which is important for analyzing domain-specific queries about your data models. + +3. **Technical Terminology**: Better handling of technical terms in Arabic, which is crucial for a model analyzing Django models and database structures. + +4. **Instruction Following**: Good ability to follow complex instructions in Arabic, which is essential for your prompt-based analysis system. + +5. **Performance on Analytical Tasks**: Superior performance on analytical and reasoning tasks in Arabic compared to general multilingual models. + +If your system has limited resources (less than 12GB RAM), Mistral-7B-Instruct would be the next best alternative, offering a good balance between performance and resource requirements. + +## Installation Instructions + +To install the recommended Jais-13B model: + +```bash +ollama pull jais:13b +``` + +For systems with limited resources, install Mistral-7B-Instruct instead: + +```bash +ollama pull mistral:7b-instruct +``` + +After installation, update the `OLLAMA_MODEL` setting in your Django view: + +```python +# For Jais-13B +OLLAMA_MODEL = 'jais:13b' + +# OR for Mistral-7B-Instruct if resources are limited +# OLLAMA_MODEL = 'mistral:7b-instruct' +``` diff --git a/haikalbot/services/analysis_service.py b/haikalbot/services/analysis_service.py new file mode 100644 index 00000000..8e0d3e8b --- /dev/null +++ b/haikalbot/services/analysis_service.py @@ -0,0 +1,319 @@ +from django.db.models import Avg, Sum, Max, Min, ForeignKey, OneToOneField +import inspect +from django.db import models +from django.utils.translation import gettext_lazy as _ + + +def _localized_keys(language): + """ + Get localized key names based on language. + + :param language: Language code ('en' or 'ar') + :type language: str + :return: Dictionary of localized keys + :rtype: dict + """ + if language == 'ar': + return { + 'type': 'نوع', 'model': 'النموذج', 'count': 'العدد', 'filters': 'الفلاتر_المطبقة', + 'error': 'خطأ', 'chart_type': 'نوع_الرسم_البياني', 'labels': 'التسميات', 'data': 'البيانات', + 'visualization_data': 'بيانات_الرسم_البياني', 'field': 'الحقل', 'value': 'القيمة', + 'statistic_type': 'نوع_الإحصاء', 'results': 'النتائج', 'title': 'العنوان' + } + else: + return { + 'type': 'type', 'model': 'model', 'count': 'count', 'filters': 'filters_applied', + 'error': 'error', 'chart_type': 'chart_type', 'labels': 'labels', 'data': 'data', + 'visualization_data': 'visualization_data', 'field': 'field', 'value': 'value', + 'statistic_type': 'statistic_type', 'results': 'results', 'title': 'title' + } + + +def generate_count_insight(models, query_params, dealer_id=None, language='en'): + """ + Generate count insights for the specified models. + + :param models: List of models to analyze + :type models: list + :param query_params: Query parameters for filtering + :type query_params: dict + :param dealer_id: Dealer ID for filtering + :type dealer_id: int + :param language: Language code ('en' or 'ar') + :type language: str + :return: Count insights + :rtype: dict + """ + keys = _localized_keys(language) + results = [] + + for model in models: + try: + queryset = model.objects.all() + + if dealer_id: + if hasattr(model, 'dealer_id'): + queryset = queryset.filter(dealer_id=dealer_id) + elif hasattr(model, 'dealer'): + queryset = queryset.filter(dealer=dealer_id) + + filters = {} + for key, value in query_params.items(): + if key not in ['field', 'operation'] and hasattr(model, key): + try: + field = model._meta.get_field(key) + if isinstance(field, models.IntegerField): + value = int(value) + elif isinstance(field, models.BooleanField): + value = value.lower() in ('true', '1', 'yes') + except Exception: + pass + filters[key] = value + + if filters: + queryset = queryset.filter(**filters) + + results.append({ + keys['model']: model.__name__, + keys['count']: queryset.count(), + keys['filters']: filters + }) + + except Exception as e: + results.append({ + keys['model']: model.__name__, + keys['error']: str(e) + }) + + return { + keys['type']: keys['type'] + '_analysis', + keys['results']: results, + keys['visualization_data']: { + keys['chart_type']: 'bar', + keys['labels']: [r[keys['model']] for r in results if keys['count'] in r], + keys['data']: [r[keys['count']] for r in results if keys['count'] in r] + } + } + + +def generate_statistics_insight(models, query_params, dealer_id=None, language='en'): + """ + Generate statistical insights for the specified models. + + :param models: List of models to analyze + :type models: list + :param query_params: Query parameters for filtering + :type query_params: dict + :param dealer_id: Dealer ID for filtering + :type dealer_id: int + :param language: Language code ('en' or 'ar') + :type language: str + :return: Statistical insights + :rtype: dict + """ + keys = _localized_keys(language) + results = [] + field = query_params.get('field') + operation = query_params.get('operation', 'average') + + for model in models: + try: + if not field or not hasattr(model, field): + continue + + queryset = model.objects.all() + if dealer_id: + if hasattr(model, 'dealer_id'): + queryset = queryset.filter(dealer_id=dealer_id) + elif hasattr(model, 'dealer'): + queryset = queryset.filter(dealer=dealer_id) + + filters = {} + for k, v in query_params.items(): + if k not in ['field', 'operation'] and hasattr(model, k): + filters[k] = v + + if filters: + queryset = queryset.filter(**filters) + + stat_map = { + 'average': Avg, + 'sum': Sum, + 'max': Max, + 'min': Min + } + + if operation in stat_map: + agg = queryset.aggregate(val=stat_map[operation](field))['val'] + value = agg + else: + value = queryset.count() + + results.append({ + keys['model']: model.__name__, + keys['field']: field, + keys['statistic_type']: operation, + keys['value']: value, + keys['filters']: filters + }) + + except Exception as e: + results.append({keys['model']: model.__name__, keys['error']: str(e)}) + + return { + keys['type']: keys['type'] + '_analysis', + keys['results']: results, + keys['visualization_data']: { + keys['chart_type']: 'bar', + keys['labels']: [f"{r[keys['model']]}.{r[keys['field']]}" for r in results if keys['value'] in r], + keys['data']: [r[keys['value']] for r in results if keys['value'] in r], + keys['title']: f"{operation} of {field}" if language != 'ar' else f"{field} ({operation})" + } + } + + +def generate_recommendations(model_classes, analysis_type, language='en'): + """ + Generate recommendations based on model analysis. + + :param model_classes: List of models to analyze + :type model_classes: list + :param analysis_type: Type of analysis + :type analysis_type: str + :param language: Language code ('en' or 'ar') + :type language: str + :return: List of recommendations + :rtype: list + """ + recs = [] + for model in model_classes: + for field in model._meta.fields: + if isinstance(field, ForeignKey) and not field.db_index: + msg = f"أضف db_index=True إلى {model.__name__}.{field.name}" if language == 'ar' else f"Add db_index=True to {model.__name__}.{field.name}" + recs.append(msg) + if isinstance(field, models.CharField) and not field.db_index and field.name in ['name', 'title', 'description', 'text']: + msg = f"فكر في فهرسة الحقل النصي {model.__name__}.{field.name}" if language == 'ar' else f"Consider indexing the text field {model.__name__}.{field.name}" + recs.append(msg) + return recs[:5] + + +def generate_model_insight(model, dealer_id=None, language='en'): + """ + Generate insights for a specific model. + + :param model: Model to analyze + :type model: Model class + :param dealer_id: Dealer ID for filtering + :type dealer_id: int + :param language: Language code ('en' or 'ar') + :type language: str + :return: Model insights + :rtype: dict + """ + keys = _localized_keys(language) + fields_info = [ + { + 'name': f.name, + 'type': f.__class__.__name__, + 'null': f.null, + 'blank': f.blank, + 'unique': f.unique, + 'pk': f.primary_key + } for f in model._meta.fields + ] + + try: + qs = model.objects.all() + if dealer_id: + if hasattr(model, 'dealer_id'): + qs = qs.filter(dealer_id=dealer_id) + elif hasattr(model, 'dealer'): + qs = qs.filter(dealer=dealer_id) + count = qs.count() + except Exception: + count = "error" + + return { + keys['type']: keys['type'] + '_analysis', + keys['model']: model.__name__, + 'fields': fields_info, + 'count': count + } + + +def generate_relationship_insight(models, query_params=None, dealer_id=None, language='en'): + """ + Generate relationship insights between models. + + :param models: List of models to analyze + :type models: list + :param query_params: Query parameters (unused) + :type query_params: dict + :param dealer_id: Dealer ID (unused) + :type dealer_id: int + :param language: Language code ('en' or 'ar') + :type language: str + :return: Relationship insights + :rtype: dict + """ + from_ = "من" if language == 'ar' else "from" + to_ = "إلى" if language == 'ar' else "to" + rel_type = "نوع" if language == 'ar' else "type" + relationships = [] + + for model in models: + for field in model._meta.fields: + if isinstance(field, (ForeignKey, OneToOneField)): + relationships.append({ + from_: model.__name__, + to_: field.related_model.__name__, + rel_type: field.__class__.__name__ + }) + for field in model._meta.many_to_many: + relationships.append({ + from_: model.__name__, + to_: field.related_model.__name__, + rel_type: 'ManyToManyField' + }) + + return { + 'type': 'تحليل_العلاقات' if language == 'ar' else 'relationship_analysis', + 'relationships': relationships + } + + +def generate_performance_insight(models, query_params=None, dealer_id=None, language='en'): + """ + Generate performance insights for models. + + :param models: List of models to analyze + :type models: list + :param query_params: Query parameters (unused) + :type query_params: dict + :param dealer_id: Dealer ID (unused) + :type dealer_id: int + :param language: Language code ('en' or 'ar') + :type language: str + :return: Performance insights + :rtype: dict + """ + issues = [] + for model in models: + for field in model._meta.fields: + if isinstance(field, ForeignKey) and not field.db_index: + issues.append({ + 'model': model.__name__, + 'field': field.name, + 'issue': 'Missing index on ForeignKey' + }) + if isinstance(field, models.CharField) and not field.db_index and field.name in ['name', 'title']: + issues.append({ + 'model': model.__name__, + 'field': field.name, + 'issue': 'Unindexed CharField used in filtering' + }) + + return { + 'type': 'تحليل_الأداء' if language == 'ar' else 'performance_analysis', + 'issues': issues + } diff --git a/haikalbot/services/cache_service.py b/haikalbot/services/cache_service.py new file mode 100644 index 00000000..ba1a63ba --- /dev/null +++ b/haikalbot/services/cache_service.py @@ -0,0 +1,101 @@ +from django.utils import timezone +from django.db import models +from ..models import AnalysisCache +import hashlib +import logging + +logger = logging.getLogger(__name__) + +class CacheService: + """ + Service for handling analysis result caching operations. + + This service provides methods for generating cache keys, retrieving + cached results, and storing new results in the cache. + """ + + def generate_hash(self, prompt, dealer_id, language): + """ + Generate a unique hash for the prompt, dealer, and language combination. + + :param prompt: The user's prompt text + :type prompt: str + :param dealer_id: The dealer's ID + :type dealer_id: int + :param language: The language code + :type language: str + :return: MD5 hash string + :rtype: str + """ + cache_key = f"{prompt}:{dealer_id or 'all'}:{language}" + return hashlib.md5(cache_key.encode()).hexdigest() + + def get_cached_result(self, prompt_hash, user, dealer_id): + """ + Retrieve a cached result if available and not expired. + + :param prompt_hash: The hash key for the cache entry + :type prompt_hash: str + :param user: The user making the request + :type user: User + :param dealer_id: The dealer's ID + :type dealer_id: int + :return: Cached result or None if not found + :rtype: dict or None + """ + try: + cache_entry = AnalysisCache.objects.filter( + prompt_hash=prompt_hash, + dealer_id=dealer_id, + expires_at__gt=timezone.now() + ).first() + + # If user is authenticated, also check user-specific cache + if user and user.is_authenticated: + user_cache = AnalysisCache.objects.filter( + prompt_hash=prompt_hash, + user=user, + expires_at__gt=timezone.now() + ).first() + + # User-specific cache takes precedence + if user_cache: + return user_cache.result + + return cache_entry.result if cache_entry else None + except Exception as e: + logger.warning(f"Error retrieving cache: {str(e)}") + return None + + def cache_result(self, prompt_hash, result, user, dealer_id, duration=3600): + """ + Store a result in the cache. + + :param prompt_hash: The hash key for the cache entry + :type prompt_hash: str + :param result: The result to cache + :type result: dict + :param user: The user making the request + :type user: User + :param dealer_id: The dealer's ID + :type dealer_id: int + :param duration: Cache duration in seconds + :type duration: int + :return: None + """ + try: + # Calculate expiration time + expires_at = timezone.now() + timezone.timedelta(seconds=duration) + + # Create or update cache entry + AnalysisCache.objects.update_or_create( + prompt_hash=prompt_hash, + user=user if user and user.is_authenticated else None, + dealer_id=dealer_id, + defaults={ + 'result': result, + 'expires_at': expires_at + } + ) + except Exception as e: + logger.warning(f"Error caching result: {str(e)}") diff --git a/haikalbot/services/llm_service.py b/haikalbot/services/llm_service.py new file mode 100644 index 00000000..9eb511b7 --- /dev/null +++ b/haikalbot/services/llm_service.py @@ -0,0 +1,99 @@ +from langchain_ollama import OllamaLLM +from langchain.chains import LLMChain +from langchain.prompts import PromptTemplate +from django.conf import settings +import logging + +logger = logging.getLogger(__name__) + + +def get_llm_instance(): + """ + Initialize and return an Ollama LLM instance configured for Arabic support. + + This function creates a new LLM instance with optimized parameters for + both Arabic and English language processing. It reads configuration from + Django settings or uses sensible defaults. + + :return: Configured OllamaLLM instance or None if initialization fails + :rtype: OllamaLLM or None + """ + try: + # Get settings from Django settings or use defaults + base_url = getattr(settings, 'OLLAMA_BASE_URL', 'http://localhost:11434') + model = getattr(settings, 'OLLAMA_MODEL', 'qwen3:8b') + temperature = getattr(settings, 'OLLAMA_TEMPERATURE', 0.2) + top_p = getattr(settings, 'OLLAMA_TOP_P', 0.8) + top_k = getattr(settings, 'OLLAMA_TOP_K', 40) + num_ctx = getattr(settings, 'OLLAMA_NUM_CTX', 4096) + num_predict = getattr(settings, 'OLLAMA_NUM_PREDICT', 2048) + + return OllamaLLM( + base_url=base_url, + model=model, + temperature=temperature, + top_p=top_p, + top_k=top_k, + num_ctx=num_ctx, + num_predict=num_predict, + stop=["```", ""], + repeat_penalty=1.1, + ) + except Exception as e: + logger.error(f"Error initializing Ollama LLM: {str(e)}") + return None + + +def get_llm_chain(language='en'): + """ + Create a LangChain for analyzing prompts in Arabic or English. + + This function creates a chain that processes user prompts and extracts + structured information about the analysis request. It supports both + Arabic and English languages. + + :param language: Language code ('en' or 'ar') + :type language: str + :return: LangChain for prompt analysis or None if initialization fails + :rtype: LLMChain or None + """ + llm = get_llm_instance() + if not llm: + return None + + # Define the prompt template based on language + if language == 'ar': + template = """ + قم بتحليل الاستعلام التالي وتحديد نوع التحليل المطلوب ونماذج البيانات المستهدفة وأي معلمات استعلام. + + الاستعلام: {prompt} + + قم بتقديم إجابتك بتنسيق JSON كما يلي: + {{ + "analysis_type": "count" أو "relationship" أو "performance" أو "statistics" أو "general", + "target_models": ["ModelName1", "ModelName2"], + "query_params": {{"field1": "value1", "field2": "value2"}} + }} + """ + else: + template = """ + Analyze the following prompt and determine the type of analysis required, target data models, and any query parameters. + + Prompt: {prompt} + + Provide your answer in JSON format as follows: + { + "analysis_type": "count" or "relationship" or "performance" or "statistics" or "general", + "target_models": ["ModelName1", "ModelName2"], + "query_params": {"field1": "value1", "field2": "value2"} + } + """ + + # Create the prompt template + prompt_template = PromptTemplate( + input_variables=["prompt"], + template=template + ) + + # Create and return the LLM chain + return prompt_template | llm diff --git a/haikalbot/temp.txt b/haikalbot/temp.txt new file mode 100644 index 00000000..ba64182e --- /dev/null +++ b/haikalbot/temp.txt @@ -0,0 +1,80 @@ +from langchain_ollama import OllamaLLM + +from langchain.chains import LLMChain +from langchain.prompts import PromptTemplate +from django.conf import settings +import logging + +logger = logging.getLogger(__name__) + + +def get_ollama_llm(): + """ + Initialize and return an Ollama LLM instance configured for Arabic support. + """ + try: + # Get settings from Django settings or use defaults + base_url = getattr(settings, 'OLLAMA_BASE_URL', 'http://localhost:11434') + model = getattr(settings, 'OLLAMA_MODEL', 'qwen3:8b') + # timeout = getattr(settings, 'OLLAMA_TIMEOUT', 120) + + return OllamaLLM( + base_url=base_url, + model=model, + temperature= 0.2, + top_p= 0.8, + top_k= 40, + num_ctx= 4096, + num_predict= 2048, + stop= ["```", ""], + repeat_penalty= 1.1, + ) + except Exception as e: + logger.error(f"Error initializing Ollama LLM: {str(e)}") + return None + + +def create_prompt_analyzer_chain(language='ar'): + """ + Create a LangChain for analyzing prompts in Arabic or English. + """ + llm = get_ollama_llm() + if not llm: + return None + + # Define the prompt template based on language + if language == 'ar': + template = """ + قم بتحليل الاستعلام التالي وتحديد نوع التحليل المطلوب ونماذج البيانات المستهدفة وأي معلمات استعلام. + + الاستعلام: {prompt} + + قم بتقديم إجابتك بتنسيق JSON كما يلي: + {{ + "analysis_type": "count" أو "relationship" أو "performance" أو "statistics" أو "general", + "target_models": ["ModelName1", "ModelName2"], + "query_params": {{"field1": "value1", "field2": "value2"}} + }} + """ + else: + template = """ + Analyze the following prompt and determine the type of analysis required, target data models, and any query parameters. + + Prompt: {prompt} + + Provide your answer in JSON format as follows: + { + "analysis_type": "count" or "relationship" or "performance" or "statistics" or "general", + "target_models": ["ModelName1", "ModelName2"], + "query_params": {"field1": "value1", "field2": "value2"} + } + """ + + # Create the prompt template + prompt_template = PromptTemplate( + input_variables=["prompt"], + template=template + ) + + # Create and return the LLM chain + return prompt_template | llm \ No newline at end of file diff --git a/haikalbot/training_prompt.md b/haikalbot/training_prompt.md new file mode 100644 index 00000000..ee381661 --- /dev/null +++ b/haikalbot/training_prompt.md @@ -0,0 +1,161 @@ +# Training Prompt for Django Model Analyst AI Agent + +## Agent Purpose +You are a specialized AI agent designed to analyze Django models and provide insightful information to users. Your primary function is to interpret Django model structures, relationships, and metadata to generate meaningful insights that help developers and stakeholders understand their data models better. + +## Core Capabilities +1. Parse and understand Django model definitions +2. Identify relationships between models (ForeignKey, ManyToMany, OneToOne) +3. Analyze model fields, types, constraints, and metadata +4. Generate statistics and insights about model usage and structure +5. Provide recommendations for model optimization +6. Respond to natural language queries about models +7. Format responses as structured JSON for integration with frontend applications + +## Input Processing +You will receive inputs in the following format: +1. Django model code or references to model files +2. A natural language prompt specifying the type of analysis or insights requested +3. Optional context about the project or specific concerns + +## Output Requirements +Your responses must: +1. Be formatted as valid JSON +2. Include a "status" field indicating success or failure +3. Provide an "insights" array containing the requested analysis +4. Include metadata about the analysis performed +5. Be structured in a way that's easy to parse and display in a frontend + +## Analysis Types +You should be able to perform the following types of analysis: + +### Structural Analysis +- Model count and complexity metrics +- Field type distribution +- Relationship mapping and visualization data +- Inheritance patterns +- Abstract models usage + +### Performance Analysis +- Potential query bottlenecks +- Missing index recommendations +- Relationship optimization suggestions +- N+1 query vulnerability detection + +### Security Analysis +- Sensitive field detection +- Permission model recommendations +- Data exposure risk assessment + +### Data Integrity Analysis +- Constraint analysis +- Validation rule assessment +- Data consistency recommendations + +## Example Interactions + +### Example 1: Basic Model Analysis +**Input Prompt:** +"Analyze the User and Profile models and show me their relationship structure." + +**Expected Response:** +```json +{ + "status": "success", + "request_id": "a1b2c3d4", + "timestamp": "2025-05-25T23:21:56Z", + "insights": [ + { + "type": "relationship_analysis", + "models": ["User", "Profile"], + "relationships": [ + { + "from": "Profile", + "to": "User", + "type": "OneToOne", + "field": "user", + "related_name": "profile", + "on_delete": "CASCADE" + } + ], + "visualization_data": { + "nodes": [...], + "edges": [...] + } + } + ], + "recommendations": [ + "Consider adding an index to Profile.user for faster lookups" + ] +} +``` + +### Example 2: Query Performance Analysis +**Input Prompt:** +"Identify potential performance issues in the Order and OrderItem models." + +**Expected Response:** +```json +{ + "status": "success", + "request_id": "e5f6g7h8", + "timestamp": "2025-05-25T23:22:30Z", + "insights": [ + { + "type": "performance_analysis", + "models": ["Order", "OrderItem"], + "issues": [ + { + "severity": "high", + "model": "OrderItem", + "field": "order", + "issue": "Missing database index on ForeignKey", + "impact": "Slow queries when filtering OrderItems by Order", + "solution": "Add db_index=True to order field" + }, + { + "severity": "medium", + "model": "Order", + "issue": "No select_related in common queries", + "impact": "Potential N+1 query problems", + "solution": "Use select_related when querying Orders with OrderItems" + } + ] + } + ], + "code_suggestions": [ + { + "model": "OrderItem", + "current": "order = models.ForeignKey(Order, on_delete=models.CASCADE)", + "suggested": "order = models.ForeignKey(Order, on_delete=models.CASCADE, db_index=True)" + } + ] +} +``` + +## Limitations and Boundaries +1. You should not modify or execute code unless explicitly requested +2. You should indicate when you need additional information to provide accurate insights +3. You should acknowledge when a requested analysis is beyond your capabilities +4. You should not make assumptions about implementation details not present in the provided models +5. You should clearly distinguish between factual observations and recommendations + +## Learning and Improvement +You should continuously improve your analysis capabilities by: +1. Learning from user feedback +2. Staying updated on Django best practices +3. Expanding your understanding of common model patterns +4. Refining your insight generation to be more relevant and actionable + +## Ethical Considerations +1. Respect data privacy by not suggesting exposing sensitive information +2. Provide balanced recommendations that consider security, performance, and usability +3. Be transparent about the limitations of your analysis +4. Avoid making judgments about the quality of code beyond objective metrics + +## Technical Integration +You will be integrated into a Django application as a service that: +1. Receives requests through a REST API +2. Has access to model definitions through Django's introspection capabilities +3. Returns JSON responses that can be directly used by frontend components +4. Maintains context across multiple related queries when session information is provided diff --git a/haikalbot/training_prompt_arabic.md b/haikalbot/training_prompt_arabic.md new file mode 100644 index 00000000..2d32829b --- /dev/null +++ b/haikalbot/training_prompt_arabic.md @@ -0,0 +1,161 @@ +# تدريب وكيل محلل نماذج Django بالعربية + +## هدف الوكيل +أنت وكيل ذكاء اصطناعي متخصص مصمم لتحليل نماذج Django وتقديم معلومات مفيدة للمستخدمين. وظيفتك الأساسية هي تفسير هياكل نماذج Django والعلاقات والبيانات الوصفية لتوليد رؤى ذات معنى تساعد المطورين وأصحاب المصلحة على فهم نماذج البيانات الخاصة بهم بشكل أفضل. + +## القدرات الأساسية +1. تحليل وفهم تعريفات نماذج Django +2. تحديد العلاقات بين النماذج (ForeignKey, ManyToMany, OneToOne) +3. تحليل حقول النموذج وأنواعها والقيود والبيانات الوصفية +4. توليد إحصائيات ورؤى حول استخدام النموذج وهيكله +5. تقديم توصيات لتحسين النموذج +6. الاستجابة للاستعلامات باللغة الطبيعية حول النماذج +7. تنسيق الردود كـ JSON منظم للتكامل مع تطبيقات الواجهة الأمامية + +## معالجة المدخلات +ستتلقى المدخلات بالتنسيق التالي: +1. كود نموذج Django أو مراجع لملفات النموذج +2. استعلام باللغة الطبيعية يحدد نوع التحليل أو الرؤى المطلوبة +3. سياق اختياري حول المشروع أو مخاوف محددة + +## متطلبات المخرجات +يجب أن تكون ردودك: +1. منسقة كـ JSON صالح +2. تتضمن حقل "status" يشير إلى النجاح أو الفشل +3. توفر مصفوفة "insights" تحتوي على التحليل المطلوب +4. تتضمن بيانات وصفية حول التحليل الذي تم إجراؤه +5. منظمة بطريقة يسهل تحليلها وعرضها في واجهة أمامية + +## أنواع التحليل +يجب أن تكون قادرًا على إجراء الأنواع التالية من التحليل: + +### التحليل الهيكلي +- عدد النماذج ومقاييس التعقيد +- توزيع أنواع الحقول +- رسم خرائط العلاقات وبيانات التصور +- أنماط الوراثة +- استخدام النماذج المجردة + +### تحليل الأداء +- اختناقات الاستعلام المحتملة +- توصيات الفهرس المفقود +- اقتراحات تحسين العلاقة +- كشف ضعف استعلام N+1 + +### تحليل الأمان +- كشف الحقول الحساسة +- توصيات نموذج الإذن +- تقييم مخاطر التعرض للبيانات + +### تحليل سلامة البيانات +- تحليل القيود +- تقييم قواعد التحقق +- توصيات اتساق البيانات + +## أمثلة على التفاعلات + +### مثال 1: تحليل النموذج الأساسي +**استعلام المدخلات:** +"قم بتحليل نماذج المستخدم والملف الشخصي وأظهر لي هيكل العلاقة بينهما." + +**الرد المتوقع:** +```json +{ + "status": "نجاح", + "request_id": "a1b2c3d4", + "timestamp": "2025-05-25T23:21:56Z", + "insights": [ + { + "type": "تحليل_العلاقات", + "models": ["User", "Profile"], + "relationships": [ + { + "from": "Profile", + "to": "User", + "type": "OneToOne", + "field": "user", + "related_name": "profile", + "on_delete": "CASCADE" + } + ], + "visualization_data": { + "nodes": [...], + "edges": [...] + } + } + ], + "recommendations": [ + "فكر في إضافة فهرس إلى Profile.user للبحث الأسرع" + ] +} +``` + +### مثال 2: تحليل أداء الاستعلام +**استعلام المدخلات:** +"حدد مشاكل الأداء المحتملة في نماذج الطلب وعناصر الطلب." + +**الرد المتوقع:** +```json +{ + "status": "نجاح", + "request_id": "e5f6g7h8", + "timestamp": "2025-05-25T23:22:30Z", + "insights": [ + { + "type": "تحليل_الأداء", + "models": ["Order", "OrderItem"], + "issues": [ + { + "severity": "عالية", + "model": "OrderItem", + "field": "order", + "issue": "فهرس قاعدة بيانات مفقود على ForeignKey", + "impact": "استعلامات بطيئة عند تصفية OrderItems حسب Order", + "solution": "أضف db_index=True إلى حقل order" + }, + { + "severity": "متوسطة", + "model": "Order", + "issue": "لا يوجد select_related في الاستعلامات الشائعة", + "impact": "مشاكل استعلام N+1 محتملة", + "solution": "استخدم select_related عند الاستعلام عن Orders مع OrderItems" + } + ] + } + ], + "code_suggestions": [ + { + "model": "OrderItem", + "current": "order = models.ForeignKey(Order, on_delete=models.CASCADE)", + "suggested": "order = models.ForeignKey(Order, on_delete=models.CASCADE, db_index=True)" + } + ] +} +``` + +## القيود والحدود +1. لا يجب عليك تعديل أو تنفيذ التعليمات البرمجية ما لم يُطلب منك ذلك صراحةً +2. يجب أن تشير عندما تحتاج إلى معلومات إضافية لتقديم رؤى دقيقة +3. يجب أن تعترف عندما يكون التحليل المطلوب خارج قدراتك +4. لا يجب أن تفترض تفاصيل التنفيذ غير الموجودة في النماذج المقدمة +5. يجب أن تميز بوضوح بين الملاحظات الواقعية والتوصيات + +## التعلم والتحسين +يجب أن تحسن باستمرار قدرات التحليل الخاصة بك من خلال: +1. التعلم من تعليقات المستخدم +2. البقاء على اطلاع بأفضل ممارسات Django +3. توسيع فهمك لأنماط النموذج الشائعة +4. تحسين توليد الرؤى لتكون أكثر صلة وقابلية للتنفيذ + +## الاعتبارات الأخلاقية +1. احترام خصوصية البيانات من خلال عدم اقتراح كشف المعلومات الحساسة +2. تقديم توصيات متوازنة تراعي الأمان والأداء وسهولة الاستخدام +3. الشفافية بشأن حدود تحليلك +4. تجنب إصدار أحكام حول جودة الكود بما يتجاوز المقاييس الموضوعية + +## التكامل التقني +سيتم دمجك في تطبيق Django كخدمة: +1. تتلقى الطلبات من خلال واجهة برمجة تطبيقات REST +2. لديها إمكانية الوصول إلى تعريفات النموذج من خلال قدرات التفتيش الذاتي لـ Django +3. تعيد استجابات JSON التي يمكن استخدامها مباشرة بواسطة مكونات الواجهة الأمامية +4. تحافظ على السياق عبر استعلامات متعددة ذات صلة عند توفير معلومات الجلسة diff --git a/haikalbot/urls.py b/haikalbot/urls.py index 71915fe7..ddd4713a 100644 --- a/haikalbot/urls.py +++ b/haikalbot/urls.py @@ -1,7 +1,8 @@ from django.urls import path from . import views +app_name = "haikalbot" urlpatterns = [ - path("", views.ChatbotView.as_view(), name="chatbot"), + path("analyze/", views.ModelAnalystView.as_view(), name="haikalbot"), ] diff --git a/haikalbot/utils/response_formatter.py b/haikalbot/utils/response_formatter.py new file mode 100644 index 00000000..ea9e6ea1 --- /dev/null +++ b/haikalbot/utils/response_formatter.py @@ -0,0 +1,119 @@ +def format_response(prompt, language, request_id, timestamp): + """ + Format a standardized response structure based on language. + + This utility creates a consistent response structure with the appropriate + keys based on the specified language. + + :param prompt: The original user prompt + :type prompt: str + :param language: Language code ('en' or 'ar') + :type language: str + :param request_id: Unique identifier for the request + :type request_id: str + :param timestamp: ISO-formatted timestamp + :type timestamp: str + :return: Formatted response structure + :rtype: dict + """ + if language == 'ar': + return { + 'حالة': "نجاح", + 'معرف_الطلب': request_id, + 'الطابع_الزمني': timestamp, + 'الاستعلام': prompt, + 'التحليلات': [] + } + else: + return { + 'status': "success", + 'request_id': request_id, + 'timestamp': timestamp, + 'prompt': prompt, + 'insights': [] + } + + +def format_error_response(message, status_code, language='en'): + """ + Format a standardized error response. + + :param message: Error message + :type message: str + :param status_code: HTTP status code + :type status_code: int + :param language: Language code ('en' or 'ar') + :type language: str + :return: Formatted error response + :rtype: dict + """ + if language == 'ar': + return { + 'حالة': "خطأ", + 'رسالة': message, + 'رمز_الحالة': status_code + } + else: + return { + 'status': "error", + 'message': message, + 'status_code': status_code + } + + +def format_insights_for_display(insights, language='en'): + """ + Format insights for human-readable display. + + :param insights: Raw insights data + :type insights: dict + :param language: Language code ('en' or 'ar') + :type language: str + :return: Human-readable formatted insights + :rtype: str + """ + formatted_text = "" + + # Determine keys based on language + insights_key = 'التحليلات' if language == 'ar' else 'insights' + recs_key = 'التوصيات' if language == 'ar' else 'recommendations' + + # Format insights + if insights_key in insights and insights[insights_key]: + header = "## نتائج التحليل\n\n" if language == 'ar' else "## Analysis Results\n\n" + formatted_text += header + + for insight in insights[insights_key]: + if isinstance(insight, dict): + # Add insight type as header + if 'type' in insight or 'نوع' in insight: + type_key = 'نوع' if language == 'ar' else 'type' + insight_type = insight.get(type_key, insight.get('type', insight.get('نوع', ''))) + formatted_text += f"### {insight_type}\n\n" + + # Format results if present + results_key = 'النتائج' if language == 'ar' else 'results' + if results_key in insight: + for result in insight[results_key]: + model_key = 'النموذج' if language == 'ar' else 'model' + error_key = 'خطأ' if language == 'ar' else 'error' + count_key = 'العدد' if language == 'ar' else 'count' + + model_name = result.get(model_key, result.get('model', '')) + + if error_key in result: + formatted_text += f"- **{model_name}**: {result[error_key]}\n" + elif count_key in result: + formatted_text += f"- **{model_name}**: {result[count_key]}\n" + + formatted_text += "\n" + + # Format recommendations + if recs_key in insights and insights[recs_key]: + header = "## التوصيات\n\n" if language == 'ar' else "## Recommendations\n\n" + formatted_text += header + + for rec in insights[recs_key]: + formatted_text += f"- {rec}\n" + + return formatted_text diff --git a/haikalbot/views.py b/haikalbot/views.py index 9420f4a2..b685bbf8 100644 --- a/haikalbot/views.py +++ b/haikalbot/views.py @@ -1,38 +1,253 @@ from django.contrib.auth.mixins import LoginRequiredMixin -from django.views import View from django.shortcuts import render +from django.views.decorators.csrf import csrf_exempt +from django.utils.decorators import method_decorator +from django.views import View from django.http import JsonResponse -from .chatbot_logic import get_gpt4_response +from django.apps import apps +from django.db import models +from django.conf import settings +from django.utils import timezone +from datetime import timedelta import json +import hashlib +import logging +import uuid +import re -class ChatbotView(LoginRequiredMixin, View): +from inventory import models as inventory_models +from inventory.utils import get_user_type +from .models import AnalysisCache +from .services.llm_service import get_llm_chain +from .services.analysis_service import ( + generate_model_insight, + generate_count_insight, + generate_relationship_insight, + generate_performance_insight, + generate_statistics_insight, + generate_recommendations +) +from .services.cache_service import CacheService +from .utils.response_formatter import format_response + +logger = logging.getLogger(__name__) + + +@method_decorator(csrf_exempt, name='dispatch') +class ModelAnalystView(View): """ - Represents a view for handling chatbot interactions. + View for handling model analysis requests and rendering the chatbot interface. - This class handles GET and POST requests for a chatbot interface. It leverages - `LoginRequiredMixin` to ensure that only authenticated users can access it. On GET - requests, it renders the chatbot interface, while on POST requests, it interacts - with a chatbot backend to process user messages and return responses. + This view provides both GET and POST methods: + - GET: Renders the chatbot interface + - POST: Processes analysis requests and returns JSON responses - :ivar request: The HTTP request object, providing metadata about the - current session and user. - :type request: HttpRequest + The view includes caching, permission checking, and multilingual support. """ - def get(self, request): - return render(request, "haikalbot/chatbot.html") + # Configuration settings (can be moved to Django settings) + CACHE_DURATION = getattr(settings, 'ANALYSIS_CACHE_DURATION', 3600) + DEFAULT_LANGUAGE = getattr(settings, 'DEFAULT_LANGUAGE', 'en') - def post(self, request): - dealer = request.user.dealer + def get(self, request, *args, **kwargs): + """ + Render the chatbot interface. + :param request: The HTTP request + :return: Rendered chatbot.html template + """ + context = { + 'dark_mode': request.session.get('dark_mode', False) + } + return render(request, "haikalbot/chatbot.html", context) + + def post(self, request, *args, **kwargs): + """ + Process analysis requests and return JSON responses. + + :param request: The HTTP request containing the prompt + :return: JsonResponse with analysis results + """ try: + # Parse request data data = json.loads(request.body) - user_message = data.get("message", "").strip() + prompt = data.get('prompt') + language = data.get('language', self.DEFAULT_LANGUAGE) + dealer = get_user_type(request) - if not user_message: - return JsonResponse({"error": "Message cannot be empty."}, status=400) + # Validate request + if not prompt: + error_msg = "الاستعلام مطلوب" if language == 'ar' else "Prompt is required" + return self._error_response(error_msg, 400) - chatbot_response = get_gpt4_response(user_message, dealer) + if not self._check_permissions(dealer.id): + error_msg = "تم رفض الإذن" if language == 'ar' else "Permission denied" + return self._error_response(error_msg, 403) + + # Check cache + cache_service = CacheService() + prompt_hash = cache_service.generate_hash(prompt, dealer.id, language) + cached_result = cache_service.get_cached_result(prompt_hash, request.user, dealer.id) + + if cached_result: + return JsonResponse(cached_result) + + # Process prompt and generate insights + insights = self._process_prompt(prompt, dealer, language) + + # Cache results + cache_service.cache_result( + prompt_hash, + insights, + request.user, + dealer.id, + self.CACHE_DURATION + ) + + return JsonResponse(insights) - return JsonResponse({"response": chatbot_response}, status=200) except json.JSONDecodeError: - return JsonResponse({"error": "Invalid JSON format."}, status=400) \ No newline at end of file + error_msg = "بيانات JSON غير صالحة في نص الطلب" if language == 'ar' else "Invalid JSON in request body" + return self._error_response(error_msg, 400) + except Exception as e: + logger.exception("Error processing model analysis request") + error_msg = f"حدث خطأ: {str(e)}" if language == 'ar' else f"An error occurred: {str(e)}" + return self._error_response(error_msg, 500) + + def _error_response(self, message, status): + """ + Create a standardized error response. + + :param message: Error message + :param status: HTTP status code + :return: JsonResponse with error details + """ + return JsonResponse({"status": "error", "message": message}, status=status) + + def _check_permissions(self, dealer_id): + """ + Check if the dealer has permissions to access the analysis. + + :param dealer_id: ID of the dealer + :return: True if dealer has permissions, False otherwise + """ + try: + return inventory_models.Dealer.objects.filter(id=dealer_id).exists() + except Exception: + logger.exception("Error checking permissions") + return False + + def _process_prompt(self, prompt, dealer, language): + """ + Process the prompt and generate insights. + + :param prompt: User's prompt text + :param dealer: Dealer object + :param language: Language code (e.g., 'en', 'ar') + :return: Dictionary with analysis results + """ + # Initialize response structure + response = format_response( + prompt=prompt, + language=language, + request_id=str(uuid.uuid4()), + timestamp=timezone.now().isoformat() + ) + + # Get LLM chain for prompt analysis + chain = get_llm_chain(language=language) + + # Parse prompt using LLM + if chain: + try: + result = chain.invoke({"prompt": prompt}) + json_match = re.search(r'({.*})', result.replace('\n', ' '), re.DOTALL) + result = json.loads(json_match.group(1)) if json_match else {} + except Exception as e: + logger.error(f"LLM error fallback: {e}") + result = {} + else: + result = {} + + # Extract analysis parameters + analysis_type = result.get('analysis_type', 'general') + target_models = result.get('target_models', []) + query_params = result.get('query_params', {}) + + # Get models to analyze + all_models = list(apps.get_models()) + models_to_analyze = self._filter_models(all_models, target_models) + if dealer: + models_to_analyze = self._filter_by_dealer(models_to_analyze, dealer.id) + + # Select analysis method based on type + analysis_method = { + 'count': generate_count_insight, + 'relationship': generate_relationship_insight, + 'performance': generate_performance_insight, + 'statistics': generate_statistics_insight + }.get(analysis_type, self._generate_model_insight_all) + + # Generate insights + insights = analysis_method(models_to_analyze, query_params, dealer.id if dealer else None, language) + + # Add insights to response + insights_key = "التحليلات" if language == 'ar' else "insights" + if isinstance(insights, list): + response[insights_key].extend(insights) + else: + response[insights_key].append(insights) + + # Generate recommendations + recommendations = generate_recommendations(models_to_analyze, analysis_type, language) + if recommendations: + recs_key = "التوصيات" if language == 'ar' else "recommendations" + response[recs_key] = recommendations + + # Add plain text summary for response + summary_lines = [] + for insight in response[insights_key]: + if isinstance(insight, dict): + summary_lines.append(insight.get('type', 'Insight')) + else: + summary_lines.append(str(insight)) + + response['response'] = "\n".join(summary_lines) + + return response + + def _filter_models(self, all_models, target_models): + """ + Filter models based on target model names. + + :param all_models: List of all available models + :param target_models: List of target model names + :return: Filtered list of models + """ + if not target_models: + return all_models + return [m for m in all_models if m.__name__ in target_models or + m.__name__.lower() in [t.lower() for t in target_models]] + + def _filter_by_dealer(self, models, dealer_id): + """ + Filter models that are relevant to the dealer. + + :param models: List of models + :param dealer_id: ID of the dealer + :return: Filtered list of models + """ + dealer_models = [m for m in models if any(f.name in ('dealer', 'dealer_id') + for f in m._meta.fields)] + return dealer_models if dealer_models else models + + def _generate_model_insight_all(self, models, query_params, dealer_id, language): + """ + Generate insights for all models. + + :param models: List of models + :param query_params: Query parameters + :param dealer_id: ID of the dealer + :param language: Language code + :return: List of insights + """ + return [generate_model_insight(m, dealer_id, language) for m in models] diff --git a/install_marwan.sh b/install_marwan.sh new file mode 100755 index 00000000..6c2ae0be --- /dev/null +++ b/install_marwan.sh @@ -0,0 +1,8 @@ +#!/bin/bash + + +#sudo brew update && sudo brew install libgl1 libglib2.0-dev libzbar0 cmake build-essential xmlsec1 libxmlsec1-dev pkg-config libxml2-dev libxmlsec1-dev libxmlsec1-openssl libssl-dev -y +pip install --upgrade pip +pip install -r requirements.txt +./apply_initial_migrations.sh +./load_initial_data_marwan.sh \ No newline at end of file diff --git a/inventory/migrations/0001_initial.py b/inventory/migrations/0001_initial.py index a19bf46f..cf6476e4 100644 --- a/inventory/migrations/0001_initial.py +++ b/inventory/migrations/0001_initial.py @@ -1,4 +1,4 @@ -# Generated by Django 5.1.7 on 2025-05-19 11:40 +# Generated by Django 5.2.1 on 2025-05-25 23:01 import datetime import django.core.validators @@ -21,32 +21,11 @@ class Migration(migrations.Migration): ('appointment', '0001_initial'), ('auth', '0012_alter_user_first_name_max_length'), ('contenttypes', '0002_remove_content_type_name'), - ('django_ledger', '0021_alter_bankaccountmodel_account_model_and_more'), + ('django_ledger', '0001_initial'), migrations.swappable_dependency(settings.AUTH_USER_MODEL), ] operations = [ - migrations.CreateModel( - name='Car', - fields=[ - ('id', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False, unique=True, verbose_name='Primary Key')), - ('slug', models.SlugField(blank=True, help_text='Slug for the object. If not provided, it will be generated automatically.', null=True, unique=True, verbose_name='Slug')), - ('created_at', models.DateTimeField(auto_now_add=True, verbose_name='Created At')), - ('updated_at', models.DateTimeField(auto_now=True, verbose_name='Updated At')), - ('vin', models.CharField(max_length=17, unique=True, verbose_name='VIN')), - ('year', models.IntegerField(verbose_name='Year')), - ('status', models.CharField(choices=[('available', 'Available'), ('sold', 'Sold'), ('hold', 'Hold'), ('damaged', 'Damaged'), ('reserved', 'Reserved'), ('transfer', 'Transfer')], default='available', max_length=10, verbose_name='Status')), - ('stock_type', models.CharField(choices=[('new', 'New'), ('used', 'Used')], default='new', max_length=10, verbose_name='Stock Type')), - ('remarks', models.TextField(blank=True, null=True, verbose_name='Remarks')), - ('mileage', models.IntegerField(blank=True, null=True, verbose_name='Mileage')), - ('receiving_date', models.DateTimeField(verbose_name='Receiving Date')), - ('hash', models.CharField(blank=True, max_length=64, null=True, verbose_name='Hash')), - ], - options={ - 'verbose_name': 'Car', - 'verbose_name_plural': 'Cars', - }, - ), migrations.CreateModel( name='CarEquipment', fields=[ @@ -146,6 +125,29 @@ class Migration(migrations.Migration): }, bases=(models.Model, inventory.mixins.LocalizedNameMixin), ), + migrations.CreateModel( + name='Car', + fields=[ + ('id', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False, unique=True, verbose_name='Primary Key')), + ('slug', models.SlugField(blank=True, help_text='Slug for the object. If not provided, it will be generated automatically.', null=True, unique=True, verbose_name='Slug')), + ('created_at', models.DateTimeField(auto_now_add=True, verbose_name='Created At')), + ('updated_at', models.DateTimeField(auto_now=True, verbose_name='Updated At')), + ('vin', models.CharField(max_length=17, unique=True, verbose_name='VIN')), + ('year', models.IntegerField(verbose_name='Year')), + ('status', models.CharField(choices=[('available', 'Available'), ('sold', 'Sold'), ('hold', 'Hold'), ('damaged', 'Damaged'), ('reserved', 'Reserved'), ('transfer', 'Transfer')], default='available', max_length=10, verbose_name='Status')), + ('stock_type', models.CharField(choices=[('new', 'New'), ('used', 'Used')], default='new', max_length=10, verbose_name='Stock Type')), + ('remarks', models.TextField(blank=True, null=True, verbose_name='Remarks')), + ('mileage', models.IntegerField(blank=True, null=True, verbose_name='Mileage')), + ('receiving_date', models.DateTimeField(verbose_name='Receiving Date')), + ('hash', models.CharField(blank=True, max_length=64, null=True, verbose_name='Hash')), + ('item_model', models.OneToOneField(blank=True, null=True, on_delete=django.db.models.deletion.DO_NOTHING, to='django_ledger.itemmodel', verbose_name='Item Model')), + ('id_car_make', models.ForeignKey(blank=True, db_column='id_car_make', null=True, on_delete=django.db.models.deletion.DO_NOTHING, to='inventory.carmake', verbose_name='Make')), + ], + options={ + 'verbose_name': 'Car', + 'verbose_name_plural': 'Cars', + }, + ), migrations.CreateModel( name='CarFinance', fields=[ @@ -161,11 +163,6 @@ class Migration(migrations.Migration): 'verbose_name_plural': 'Car Financial Details', }, ), - migrations.AddField( - model_name='car', - name='id_car_make', - field=models.ForeignKey(blank=True, db_column='id_car_make', null=True, on_delete=django.db.models.deletion.DO_NOTHING, to='inventory.carmake', verbose_name='Make'), - ), migrations.CreateModel( name='CarModel', fields=[ @@ -488,6 +485,7 @@ class Migration(migrations.Migration): ('updated', models.DateTimeField(auto_now=True, verbose_name='Updated')), ('content_type', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='contenttypes.contenttype')), ('created_by', models.ForeignKey(on_delete=django.db.models.deletion.DO_NOTHING, related_name='notes_created', to=settings.AUTH_USER_MODEL)), + ('dealer', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='notes', to='inventory.dealer')), ], options={ 'verbose_name': 'Note', @@ -524,6 +522,7 @@ class Migration(migrations.Migration): ('active', models.BooleanField(default=True, verbose_name='Active')), ('created', models.DateTimeField(auto_now_add=True, verbose_name='Created')), ('updated', models.DateTimeField(auto_now=True, verbose_name='Updated')), + ('slug', models.SlugField(blank=True, editable=False, max_length=255, null=True, unique=True)), ('customer_model', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to='django_ledger.customermodel')), ('dealer', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='organizations', to='inventory.dealer')), ('user', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, related_name='organization_profile', to=settings.AUTH_USER_MODEL)), @@ -555,6 +554,7 @@ class Migration(migrations.Migration): ('next_action_date', models.DateTimeField(blank=True, null=True, verbose_name='Next Action Date')), ('is_converted', models.BooleanField(default=False)), ('converted_at', models.DateTimeField(blank=True, null=True)), + ('salary', models.PositiveIntegerField(blank=True, null=True, verbose_name='Salary')), ('created', models.DateTimeField(auto_now_add=True, db_index=True, verbose_name='Created')), ('updated', models.DateTimeField(auto_now=True, verbose_name='Updated')), ('slug', models.SlugField(blank=True, null=True, unique=True)), @@ -645,8 +645,10 @@ class Migration(migrations.Migration): ('arabic_name', models.CharField(max_length=255, verbose_name='Arabic Name')), ('phone_number', phonenumber_field.modelfields.PhoneNumberField(max_length=128, region='SA', verbose_name='Phone Number')), ('staff_type', models.CharField(choices=[('inventory', 'Inventory'), ('accountant', 'Accountant'), ('sales', 'Sales')], max_length=255, verbose_name='Staff Type')), + ('active', models.BooleanField(default=True, verbose_name='Active')), ('created', models.DateTimeField(auto_now_add=True, verbose_name='Created')), ('updated', models.DateTimeField(auto_now=True, verbose_name='Updated')), + ('slug', models.SlugField(blank=True, editable=False, max_length=255, null=True, unique=True)), ('dealer', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='staff', to='inventory.dealer')), ('staff_member', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, related_name='staff', to='appointment.staffmember')), ], @@ -670,8 +672,9 @@ class Migration(migrations.Migration): ('closing_date', models.DateField(blank=True, null=True, verbose_name='Closing Date')), ('created', models.DateTimeField(auto_now_add=True, verbose_name='Created')), ('updated', models.DateTimeField(auto_now=True, verbose_name='Updated')), + ('slug', models.SlugField(blank=True, help_text='Unique slug for the opportunity.', null=True, unique=True, verbose_name='Slug')), ('car', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='inventory.car', verbose_name='Car')), - ('customer', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='opportunities', to='django_ledger.customermodel')), + ('customer', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='opportunities', to='inventory.customer')), ('dealer', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='opportunities', to='inventory.dealer')), ('estimate', models.OneToOneField(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='opportunity', to='django_ledger.estimatemodel')), ('lead', models.OneToOneField(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='opportunity', to='inventory.lead')), @@ -750,6 +753,7 @@ class Migration(migrations.Migration): ('email', models.EmailField(max_length=255, verbose_name='Email Address')), ('address', models.CharField(max_length=200, verbose_name='Address')), ('logo', models.ImageField(blank=True, null=True, upload_to='logos/vendors', verbose_name='Logo')), + ('active', models.BooleanField(default=True, verbose_name='Active')), ('created_at', models.DateTimeField(auto_now_add=True, verbose_name='Created At')), ('slug', models.SlugField(blank=True, max_length=255, null=True, unique=True, verbose_name='Slug')), ('dealer', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='vendors', to='inventory.dealer')), diff --git a/inventory/migrations/0012_carfinance_is_sold.py b/inventory/migrations/0002_carfinance_is_sold.py similarity index 86% rename from inventory/migrations/0012_carfinance_is_sold.py rename to inventory/migrations/0002_carfinance_is_sold.py index 24d73328..63ced651 100644 --- a/inventory/migrations/0012_carfinance_is_sold.py +++ b/inventory/migrations/0002_carfinance_is_sold.py @@ -6,7 +6,7 @@ from django.db import migrations, models class Migration(migrations.Migration): dependencies = [ - ('inventory', '0011_alter_car_item_model'), + ('inventory', '0001_initial'), ] operations = [ diff --git a/inventory/migrations/0002_vendor_active.py b/inventory/migrations/0002_vendor_active.py deleted file mode 100644 index 2118e3e2..00000000 --- a/inventory/migrations/0002_vendor_active.py +++ /dev/null @@ -1,18 +0,0 @@ -# Generated by Django 5.1.7 on 2025-05-20 12:00 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('inventory', '0001_initial'), - ] - - operations = [ - migrations.AddField( - model_name='vendor', - name='active', - field=models.BooleanField(default=True, verbose_name='Active'), - ), - ] diff --git a/inventory/migrations/0003_alter_opportunity_customer.py b/inventory/migrations/0003_alter_opportunity_customer.py deleted file mode 100644 index 0e399ba7..00000000 --- a/inventory/migrations/0003_alter_opportunity_customer.py +++ /dev/null @@ -1,19 +0,0 @@ -# Generated by Django 5.1.7 on 2025-05-20 12:45 - -import django.db.models.deletion -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('inventory', '0002_vendor_active'), - ] - - operations = [ - migrations.AlterField( - model_name='opportunity', - name='customer', - field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='opportunities', to='inventory.customer'), - ), - ] diff --git a/inventory/migrations/0004_opportunity_slug.py b/inventory/migrations/0004_opportunity_slug.py deleted file mode 100644 index 69b4d398..00000000 --- a/inventory/migrations/0004_opportunity_slug.py +++ /dev/null @@ -1,18 +0,0 @@ -# Generated by Django 5.1.7 on 2025-05-20 12:49 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('inventory', '0003_alter_opportunity_customer'), - ] - - operations = [ - migrations.AddField( - model_name='opportunity', - name='slug', - field=models.SlugField(blank=True, help_text='Unique slug for the opportunity.', null=True, unique=True, verbose_name='Slug'), - ), - ] diff --git a/inventory/migrations/0005_notes_dealer.py b/inventory/migrations/0005_notes_dealer.py deleted file mode 100644 index 63b30675..00000000 --- a/inventory/migrations/0005_notes_dealer.py +++ /dev/null @@ -1,20 +0,0 @@ -# Generated by Django 5.1.7 on 2025-05-20 13:45 - -import django.db.models.deletion -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('inventory', '0004_opportunity_slug'), - ] - - operations = [ - migrations.AddField( - model_name='notes', - name='dealer', - field=models.ForeignKey(default=1, on_delete=django.db.models.deletion.CASCADE, related_name='notes', to='inventory.dealer'), - preserve_default=False, - ), - ] diff --git a/inventory/migrations/0006_organization_slug.py b/inventory/migrations/0006_organization_slug.py deleted file mode 100644 index 91b349cf..00000000 --- a/inventory/migrations/0006_organization_slug.py +++ /dev/null @@ -1,18 +0,0 @@ -# Generated by Django 5.1.7 on 2025-05-21 10:54 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('inventory', '0005_notes_dealer'), - ] - - operations = [ - migrations.AddField( - model_name='organization', - name='slug', - field=models.SlugField(blank=True, editable=False, max_length=255, null=True, unique=True), - ), - ] diff --git a/inventory/migrations/0007_staff_active_staff_slug.py b/inventory/migrations/0007_staff_active_staff_slug.py deleted file mode 100644 index 704dddbf..00000000 --- a/inventory/migrations/0007_staff_active_staff_slug.py +++ /dev/null @@ -1,23 +0,0 @@ -# Generated by Django 5.1.7 on 2025-05-21 13:32 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('inventory', '0006_organization_slug'), - ] - - operations = [ - migrations.AddField( - model_name='staff', - name='active', - field=models.BooleanField(default=True, verbose_name='Active'), - ), - migrations.AddField( - model_name='staff', - name='slug', - field=models.SlugField(blank=True, editable=False, max_length=255, null=True, unique=True), - ), - ] diff --git a/inventory/migrations/0008_lead_salary.py b/inventory/migrations/0008_lead_salary.py deleted file mode 100644 index ea22048f..00000000 --- a/inventory/migrations/0008_lead_salary.py +++ /dev/null @@ -1,18 +0,0 @@ -# Generated by Django 5.1.7 on 2025-05-21 15:26 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('inventory', '0007_staff_active_staff_slug'), - ] - - operations = [ - migrations.AddField( - model_name='lead', - name='salary', - field=models.PositiveIntegerField(blank=True, null=True, verbose_name='Salary'), - ), - ] diff --git a/inventory/migrations/0009_car_item_model.py b/inventory/migrations/0009_car_item_model.py deleted file mode 100644 index 58d54a1f..00000000 --- a/inventory/migrations/0009_car_item_model.py +++ /dev/null @@ -1,20 +0,0 @@ -# Generated by Django 5.1.7 on 2025-05-25 11:41 - -import django.db.models.deletion -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('django_ledger', '0021_alter_bankaccountmodel_account_model_and_more'), - ('inventory', '0008_lead_salary'), - ] - - operations = [ - migrations.AddField( - model_name='car', - name='item_model', - field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.DO_NOTHING, related_name='cars', to='django_ledger.itemmodel', verbose_name='Item Model'), - ), - ] diff --git a/inventory/migrations/0010_alter_car_item_model.py b/inventory/migrations/0010_alter_car_item_model.py deleted file mode 100644 index af7fbfd8..00000000 --- a/inventory/migrations/0010_alter_car_item_model.py +++ /dev/null @@ -1,20 +0,0 @@ -# Generated by Django 5.1.7 on 2025-05-25 11:43 - -import django.db.models.deletion -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('django_ledger', '0021_alter_bankaccountmodel_account_model_and_more'), - ('inventory', '0009_car_item_model'), - ] - - operations = [ - migrations.AlterField( - model_name='car', - name='item_model', - field=models.OneToOneField(blank=True, null=True, on_delete=django.db.models.deletion.DO_NOTHING, related_name='cars', to='django_ledger.itemmodel', verbose_name='Item Model'), - ), - ] diff --git a/inventory/migrations/0011_alter_car_item_model.py b/inventory/migrations/0011_alter_car_item_model.py deleted file mode 100644 index 6a077ec0..00000000 --- a/inventory/migrations/0011_alter_car_item_model.py +++ /dev/null @@ -1,20 +0,0 @@ -# Generated by Django 5.1.7 on 2025-05-25 11:44 - -import django.db.models.deletion -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('django_ledger', '0021_alter_bankaccountmodel_account_model_and_more'), - ('inventory', '0010_alter_car_item_model'), - ] - - operations = [ - migrations.AlterField( - model_name='car', - name='item_model', - field=models.OneToOneField(blank=True, null=True, on_delete=django.db.models.deletion.DO_NOTHING, to='django_ledger.itemmodel', verbose_name='Item Model'), - ), - ] diff --git a/inventory/urls.py b/inventory/urls.py index 9824c840..0adbc6c5 100644 --- a/inventory/urls.py +++ b/inventory/urls.py @@ -45,6 +45,7 @@ urlpatterns = [ # Tasks path('tasks/', views.task_list, name='task_list'), + path('legal/', views.terms_and_privacy, name='terms_and_privacy'), # path('tasks//detail/', views.task_detail, name='task_detail'), # Dashboards # path("user//settings/", views.UserSettingsView.as_view(), name="user_settings"), diff --git a/inventory/views.py b/inventory/views.py index f49ab999..b43129e3 100644 --- a/inventory/views.py +++ b/inventory/views.py @@ -510,6 +510,10 @@ class SalesDashboard(LoginRequiredMixin, TemplateView): return context +def terms_and_privacy(request): + return render(request, 'terms_and_privacy.html') + + class WelcomeView(TemplateView): """ Handles the rendering and context data for the Welcome view. diff --git a/load_initial_data_marwan.sh b/load_initial_data_marwan.sh new file mode 100755 index 00000000..d1d35bcd --- /dev/null +++ b/load_initial_data_marwan.sh @@ -0,0 +1,46 @@ +#!/bin/bash +echo "Loading initial data" + +echo "Loading carmake" +python manage.py loaddata carmake_with_slugs.json + +echo "Loading carmodel" +python manage.py loaddata carmodel_with_slugs.json + +echo "Loading carserie" +python manage.py loaddata carserie_with_slugs.json + +echo "Loading cartrim" +python manage.py loaddata cartrim_with_slugs.json + +echo "Loading carequipment" +python manage.py loaddata carequipment_with_slugs.json + +echo "Loading carspecification" +python manage.py loaddata carspecification.json + +echo "Loading carspecificationvalue" +python manage.py loaddata carspecificationvalue.json + +echo "Loading caroption" +python manage.py loaddata caroption_with_slugs.json + +echo "Loading caroptionvalue" +python manage.py loaddata caroptionvalue.json + + +echo "Populating colors" +python manage.py populate_colors + +echo "Populating Plans" +python manage.py loaddata plan.json +python manage.py loaddata pricing.json +python manage.py loaddata planpricing.json +python manage.py loaddata quota.json +python manage.py loaddata planquota.json + +python manage.py set_vat + +python manage.py initial_services_offered + +echo "Done" \ No newline at end of file diff --git a/locale/ar/LC_MESSAGES/django.mo b/locale/ar/LC_MESSAGES/django.mo index adfbd03a7c17505f63ce8fccb4959ed3497de331..94e5f24db232c13c017cce1b31c55489be2a12bb 100644 GIT binary patch delta 74901 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 delta 58946 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 nwk~%9In~#iOAm1dW(Skwd$NRre^$q&MV?5 diff --git a/locale/ar/LC_MESSAGES/django.po b/locale/ar/LC_MESSAGES/django.po index e5f314c8..831427ef 100644 --- a/locale/ar/LC_MESSAGES/django.po +++ b/locale/ar/LC_MESSAGES/django.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2025-05-07 15:44+0300\n" +"POT-Creation-Date: 2025-05-26 14:44+0300\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -19,14 +19,14 @@ msgstr "" "Plural-Forms: nplurals=6; plural=n==0 ? 0 : n==1 ? 1 : n==2 ? 2 : n%100>=3 " "&& n%100<=10 ? 3 : n%100>=11 && n%100<=99 ? 4 : 5;\n" -#: api/models.py:6 inventory/models.py:373 inventory/tables.py:51 -#: templates/inventory/car_detail.html:59 templates/inventory/car_form.html:42 -#: ⁨templates/inventory/car_form_qabl alfalsafa.html⁩:31 -#: templates/inventory/car_inventory.html:53 -#: templates/inventory/car_list.html:67 templates/inventory/car_list.html:69 -#: templates/inventory/car_list_view.html:108 -#: templates/inventory/cars_list_api.html:31 -#: templates/inventory/transfer_details.html:69 +#: api/models.py:6 inventory/models.py:468 inventory/tables.py:51 +#: templates/inventory/car_detail.html:76 templates/inventory/car_form.html:48 +#: ⁨templates/inventory/car_form_qabl alfalsafa.html⁩:30 +#: templates/inventory/car_inventory.html:65 +#: templates/inventory/car_list.html:71 templates/inventory/car_list.html:77 +#: templates/inventory/car_list_view.html:162 +#: templates/inventory/cars_list_api.html:32 +#: templates/inventory/transfer_details.html:87 #: templates/sales/estimates/estimate_detail.html:194 #: templates/sales/estimates/sale_order_form.html:122 #: templates/sales/estimates/sale_order_preview.html:178 @@ -35,7 +35,15 @@ msgstr "" msgid "VIN" msgstr "رقم الهيكل" -#: car_inventory/settings.py:169 car_inventory/settings.py:334 +#: api/views.py:146 inventory/views.py:654 +msgid "Invalid VIN number provided" +msgstr "تم تقديم رقم تعريف مركبة (VIN) غير صالح" + +#: api/views.py:154 +msgid "VIN not found in any source" +msgstr "لم يتم العثور على رقم الهيكل (VIN) في أي مصدر" + +#: car_inventory/settings.py:170 car_inventory/settings.py:334 msgid "SAR" msgstr "ريال" @@ -48,25 +56,32 @@ msgstr "الإنجليزية" msgid "Arabic" msgstr "العربية" -#: car_inventory/settings.py:356 templates/header.html:342 +#: car_inventory/settings.py:356 templates/header.html:358 #: templates/welcome-temp.html:57 templates/welcome_header.html:7 msgid "Haikal" msgstr "هيكل" -#: inventory/forms.py:110 inventory/forms.py:1596 inventory/models.py:975 -#: inventory/models.py:1005 inventory/models.py:1058 inventory/models.py:1158 -#: inventory/models.py:1260 inventory/models.py:1408 inventory/models.py:1543 +#: inventory/forms.py:105 inventory/forms.py:1631 inventory/models.py:1099 +#: inventory/models.py:1128 inventory/models.py:1189 inventory/models.py:1315 +#: inventory/models.py:1444 inventory/models.py:1637 inventory/models.py:1800 #: templates/account/login.html:29 templates/account/login.html:31 +#: templates/admin_management/user_management.html:21 +#: templates/admin_management/user_management.html:85 +#: templates/admin_management/user_management.html:149 +#: templates/admin_management/user_management.html:213 #: templates/administration/display_appointment.html:49 #: templates/administration/manage_staff_personal_info.html:29 #: templates/administration/staff_list.html:35 #: templates/administration/user_profile.html:25 #: templates/appointment/appointment_client_information.html:45 -#: templates/crm/leads/lead_detail.html:82 -#: templates/crm/opportunities/opportunity_detail.html:200 -#: templates/customers/view_customer.html:74 -#: templates/dealers/dealer_detail.html:78 -#: templates/groups/group_detail.html:61 templates/pricing_page.html:187 +#: templates/components/activity_modal.html:18 +#: templates/crm/leads/lead_detail.html:72 +#: templates/crm/leads/lead_detail.html:163 +#: templates/crm/leads/lead_list.html:39 +#: templates/crm/opportunities/opportunity_detail.html:202 +#: templates/customers/view_customer.html:78 +#: templates/dealers/dealer_detail.html:84 +#: templates/groups/group_detail.html:61 templates/pricing_page.html:186 #: templates/sales/estimates/estimate_detail.html:158 #: templates/sales/estimates/sale_order_form.html:56 #: templates/sales/estimates/sale_order_preview.html:168 @@ -79,112 +94,115 @@ msgstr "هيكل" msgid "Email" msgstr "البريد الإلكتروني" -#: inventory/forms.py:115 +#: inventory/forms.py:110 msgid "Services Offered" msgstr "الخدمات المقدمة" -#: inventory/forms.py:123 inventory/forms.py:126 inventory/forms.py:158 -#: inventory/forms.py:173 inventory/forms.py:261 inventory/forms.py:509 -#: inventory/forms.py:596 inventory/forms.py:816 inventory/forms.py:1013 -#: inventory/forms.py:1602 inventory/models.py:822 inventory/models.py:909 -#: inventory/models.py:1063 inventory/models.py:1159 inventory/models.py:1241 -#: inventory/models.py:1261 inventory/models.py:1604 +#: inventory/forms.py:118 inventory/forms.py:121 inventory/forms.py:153 +#: inventory/forms.py:168 inventory/forms.py:267 inventory/forms.py:515 +#: inventory/forms.py:602 inventory/forms.py:822 inventory/forms.py:1019 +#: inventory/forms.py:1637 inventory/models.py:919 inventory/models.py:1006 +#: inventory/models.py:1194 inventory/models.py:1316 inventory/models.py:1425 +#: inventory/models.py:1445 inventory/models.py:1869 #: templates/administration/staff_index.html:123 -#: templates/crm/leads/lead_list.html:47 -#: templates/crm/opportunities/opportunity_detail.html:190 +#: templates/crm/leads/lead_list.html:103 +#: templates/crm/opportunities/opportunity_detail.html:192 #: templates/customers/customer_list.html:41 -#: templates/customers/view_customer.html:76 templates/pricing_page.html:114 -#: templates/pricing_page.html:117 templates/users/user_detail.html:51 +#: templates/customers/view_customer.html:80 templates/pricing_page.html:113 +#: templates/pricing_page.html:116 templates/users/user_detail.html:20 #: templates/vendors/view_vendor.html:20 #: venv/lib/python3.11/site-packages/appointment/templates/administration/staff_index.html:369 #: venv/lib/python3.11/site-packages/django_ledger/models/mixins.py:114 msgid "Phone Number" msgstr "رقم الهاتف" -#: inventory/forms.py:460 inventory/models.py:728 -#: templates/inventory/car_detail.html:122 +#: inventory/forms.py:466 inventory/models.py:825 +#: templates/inventory/car_detail.html:143 msgid "Custom Date" msgstr "تاريخ البطاقة الجمركية" -#: inventory/forms.py:510 inventory/models.py:1603 +#: inventory/forms.py:516 inventory/models.py:1868 #: templates/vendors/view_vendor.html:17 msgid "Contact Person" msgstr "الشخص المسؤول" -#: inventory/forms.py:575 +#: inventory/forms.py:581 msgid "Both exterior and interior colors must be selected." msgstr "يجب اختيار اللونين الخارجي والداخلي." -#: inventory/forms.py:671 inventory/forms.py:1599 inventory/models.py:1242 -#: inventory/models.py:1605 templates/account/email_change.html:5 -#: templates/account/email_change.html:9 templates/pricing_page.html:107 +#: inventory/forms.py:677 inventory/forms.py:1634 inventory/models.py:1426 +#: inventory/models.py:1870 templates/account/email_change.html:5 +#: templates/account/email_change.html:9 templates/pricing_page.html:106 msgid "Email Address" msgstr "عنوان البريد الإلكتروني" -#: inventory/forms.py:675 +#: inventory/forms.py:681 #: venv/lib/python3.11/site-packages/appointment/views.py:424 -#: venv/lib/python3.11/site-packages/django/db/models/fields/__init__.py:1915 +#: venv/lib/python3.11/site-packages/django/db/models/fields/__init__.py:1920 msgid "Email address" msgstr "عنوان البريد الإلكتروني" -#: inventory/forms.py:676 templates/crm/leads/lead_list.html:41 -#: templates/customers/customer_list.html:36 templates/users/user_list.html:26 -#: templates/vendors/vendors_list.html:49 +#: inventory/forms.py:682 templates/crm/leads/lead_list.html:97 +#: templates/customers/customer_list.html:36 templates/users/user_list.html:33 +#: templates/vendors/vendors_list.html:35 msgid "email" msgstr "البريد الإلكتروني" -#: inventory/forms.py:682 +#: inventory/forms.py:688 msgid "You must add an email." msgstr "يجب إضافة بريد إلكتروني." -#: inventory/forms.py:687 inventory/forms.py:691 +#: inventory/forms.py:693 inventory/forms.py:697 #: templates/account/login.html:36 templates/account/login.html:38 #: venv/lib/python3.11/site-packages/django_ledger/forms/auth.py:15 msgid "Password" msgstr "كلمة المرور" -#: inventory/forms.py:698 inventory/forms.py:715 inventory/forms.py:851 -#: inventory/forms.py:869 inventory/forms.py:884 +#: inventory/forms.py:704 inventory/forms.py:721 inventory/forms.py:857 +#: inventory/forms.py:875 inventory/forms.py:890 #: venv/lib/python3.11/site-packages/django/forms/fields.py:95 msgid "This field is required." msgstr "هذا الحقل مطلوب." -#: inventory/forms.py:704 inventory/forms.py:708 +#: inventory/forms.py:710 inventory/forms.py:714 msgid "Confirm Password" msgstr "تأكيد كلمة المرور" -#: inventory/forms.py:721 +#: inventory/forms.py:727 msgid "I accept the Terms and Privacy Policy" msgstr "أوافق على الشروط وسياسة الخصوصية" -#: inventory/forms.py:730 +#: inventory/forms.py:736 msgid "You must accept the terms and privacy policy." msgstr "يجب أن تقبل الشروط وسياسة الخصوصية." -#: inventory/forms.py:740 +#: inventory/forms.py:746 msgid "An account with this email already exists." msgstr "يوجد بالفعل حساب بهذا البريد الإلكتروني." -#: inventory/forms.py:748 +#: inventory/forms.py:754 msgid "Passwords do not match." msgstr "كلمات المرور غير متطابقة." -#: inventory/forms.py:775 inventory/models.py:328 inventory/models.py:677 -#: inventory/models.py:690 inventory/models.py:907 inventory/models.py:1152 -#: inventory/models.py:1236 templates/administration/manage_service.html:22 +#: inventory/forms.py:781 inventory/models.py:416 inventory/models.py:774 +#: inventory/models.py:787 inventory/models.py:1004 inventory/models.py:1309 +#: inventory/models.py:1420 templates/admin_management/user_management.html:83 +#: templates/admin_management/user_management.html:147 +#: templates/admin_management/user_management.html:211 +#: templates/administration/manage_service.html:22 #: templates/administration/service_list.html:23 #: templates/administration/staff_list.html:34 #: templates/administration/user_profile.html:242 #: templates/customers/customer_list.html:33 #: templates/groups/group_detail.html:47 templates/groups/group_detail.html:60 -#: templates/items/expenses/expenses_list.html:20 +#: templates/items/expenses/expenses_list.html:21 #: templates/items/service/service_list.html:20 -#: templates/ledger/bank_accounts/bank_account_list.html:18 +#: templates/ledger/bank_accounts/bank_account_list.html:19 #: templates/organizations/organization_list.html:45 -#: templates/plans/order_detail_table.html:8 templates/plans/order_list.html:21 -#: templates/pricing_page.html:186 +#: templates/plans/order_detail_table.html:8 templates/plans/order_list.html:19 +#: templates/pricing_page.html:185 #: templates/representatives/representative_list.html:17 -#: templates/users/user_detail.html:47 templates/vendors/vendors_list.html:46 +#: templates/users/user_detail.html:16 templates/vendors/vendors_list.html:26 #: templates/vendors/view_vendor.html:14 #: venv/lib/python3.11/site-packages/appointment/templates/administration/service_list.html:28 #: venv/lib/python3.11/site-packages/appointment/templates/administration/staff_list.html:38 @@ -194,71 +212,74 @@ msgstr "كلمات المرور غير متطابقة." msgid "Name" msgstr "الاسم" -#: inventory/forms.py:779 inventory/models.py:821 inventory/models.py:1602 +#: inventory/forms.py:785 inventory/models.py:918 inventory/models.py:1867 msgid "English Name" msgstr "الاسم بالإنجليزية" -#: inventory/forms.py:784 +#: inventory/forms.py:790 msgid "Please enter an English Name." msgstr "يرجى إدخال اسم باللغة الإنجليزية." -#: inventory/forms.py:789 inventory/forms.py:793 inventory/models.py:329 -#: inventory/models.py:678 inventory/models.py:691 inventory/models.py:820 -#: inventory/models.py:908 inventory/models.py:1153 inventory/models.py:1237 -#: inventory/models.py:1601 templates/users/user_detail.html:48 +#: inventory/forms.py:795 inventory/forms.py:799 inventory/models.py:417 +#: inventory/models.py:775 inventory/models.py:788 inventory/models.py:917 +#: inventory/models.py:1005 inventory/models.py:1310 inventory/models.py:1421 +#: inventory/models.py:1866 templates/admin_management/user_management.html:84 +#: templates/admin_management/user_management.html:148 +#: templates/admin_management/user_management.html:212 +#: templates/users/user_detail.html:17 msgid "Arabic Name" msgstr "الاسم بالعربية" -#: inventory/forms.py:798 +#: inventory/forms.py:804 msgid "Please enter an Arabic name." msgstr "يرجى إدخال اسم باللغة العربية." -#: inventory/forms.py:840 templates/organizations/organization_detail.html:8 +#: inventory/forms.py:846 templates/organizations/organization_detail.html:8 #: templates/organizations/organization_list.html:50 msgid "CRN" msgstr "رقم السجل التجاري" -#: inventory/forms.py:844 inventory/models.py:813 inventory/models.py:1155 -#: inventory/models.py:1296 inventory/models.py:1593 +#: inventory/forms.py:850 inventory/models.py:910 inventory/models.py:1312 +#: inventory/models.py:1481 inventory/models.py:1858 msgid "Commercial Registration Number" msgstr "رقم السجل التجاري" -#: inventory/forms.py:852 +#: inventory/forms.py:858 msgid "Commercial Registration Number must be 10 characters" msgstr "رقم السجل التجاري يجب أن يتكون من 10 أرقام" -#: inventory/forms.py:858 templates/organizations/organization_detail.html:9 +#: inventory/forms.py:864 templates/organizations/organization_detail.html:9 #: templates/organizations/organization_list.html:57 msgid "VRN" msgstr "الرقم الضريبي" -#: inventory/forms.py:862 inventory/models.py:818 inventory/models.py:1157 -#: inventory/models.py:1299 inventory/models.py:1596 +#: inventory/forms.py:868 inventory/models.py:915 inventory/models.py:1314 +#: inventory/models.py:1484 inventory/models.py:1861 msgid "VAT Registration Number" msgstr "رقم التسجيل في ضريبة القيمة المضافة" -#: inventory/forms.py:870 +#: inventory/forms.py:876 msgid "VAT Registration Number must be 15 characters." msgstr "يجب أن يكون رقم التسجيل الضريبي مكونًا من 15 حرفًا." -#: inventory/forms.py:875 inventory/models.py:824 inventory/models.py:1066 -#: inventory/models.py:1161 inventory/models.py:1244 inventory/models.py:1607 -#: templates/crm/leads/lead_detail.html:118 +#: inventory/forms.py:881 inventory/models.py:921 inventory/models.py:1197 +#: inventory/models.py:1318 inventory/models.py:1428 inventory/models.py:1872 +#: templates/crm/leads/lead_detail.html:199 #: templates/customers/customer_list.html:51 -#: templates/customers/view_customer.html:71 -#: templates/dealers/dealer_detail.html:68 +#: templates/customers/view_customer.html:75 +#: templates/dealers/dealer_detail.html:74 #: templates/organizations/organization_detail.html:11 #: templates/organizations/organization_list.html:71 #: templates/representatives/representative_detail.html:10 #: templates/sales/estimates/sale_order_form.html:70 -#: templates/vendors/vendors_list.html:64 templates/vendors/view_vendor.html:26 +#: templates/vendors/vendors_list.html:69 templates/vendors/view_vendor.html:26 #: venv/lib/python3.11/site-packages/django_ledger/templates/django_ledger/customer/tags/customer_table.html:10 #: venv/lib/python3.11/site-packages/django_ledger/templates/django_ledger/vendor/tags/vendor_table.html:11 msgid "Address" msgstr "العنوان" -#: inventory/forms.py:905 inventory/models.py:346 -#: templates/inventory/transfer_preview.html:229 +#: inventory/forms.py:911 inventory/models.py:434 +#: templates/inventory/transfer_preview.html:285 #: templates/ledger/bills/bill_detail.html:213 #: templates/ledger/ledger/ledger_detail.html:81 #: venv/lib/python3.11/site-packages/django_ledger/templates/django_ledger/bills/bill_detail.html:94 @@ -277,8 +298,8 @@ msgstr "العنوان" msgid "Item" msgstr "العنصر" -#: inventory/forms.py:909 inventory/models.py:540 -#: templates/inventory/transfer_preview.html:230 +#: inventory/forms.py:915 inventory/models.py:637 +#: templates/inventory/transfer_preview.html:286 #: templates/ledger/bills/bill_detail.html:214 #: templates/ledger/ledger/ledger_detail.html:83 #: templates/plans/invoices/layout.html:104 @@ -297,90 +318,90 @@ msgstr "العنصر" msgid "Quantity" msgstr "الكمية" -#: inventory/forms.py:934 inventory/models.py:1743 -#: templates/customers/view_customer.html:150 +#: inventory/forms.py:940 inventory/models.py:2026 +#: templates/customers/view_customer.html:154 #: templates/ledger/journal_entry/includes/card_invoice.html:10 #: templates/plans/create_order.html:29 templates/plans/invoices/layout.html:11 #: templates/sales/invoices/invoice_create.html:5 #: templates/sales/invoices/invoice_detail.html:69 #: templates/sales/payments/payment_list.html:21 #: templates/sales/sales_list.html:118 -#: venv/lib/python3.11/site-packages/django_ledger/models/entity.py:3159 +#: venv/lib/python3.11/site-packages/django_ledger/models/entity.py:3172 #: venv/lib/python3.11/site-packages/django_ledger/models/invoice.py:361 #: venv/lib/python3.11/site-packages/django_ledger/templates/django_ledger/invoice/includes/card_invoice.html:10 msgid "Invoice" msgstr "فاتورة" -#: inventory/forms.py:938 templates/ledger/bills/bill_detail.html:61 +#: inventory/forms.py:944 templates/ledger/bills/bill_detail.html:61 #: templates/ledger/bills/bill_update_form.html:4 #: templates/ledger/bills/bill_update_form.html:7 #: venv/lib/python3.11/site-packages/django_ledger/models/bill.py:392 -#: venv/lib/python3.11/site-packages/django_ledger/models/entity.py:3158 +#: venv/lib/python3.11/site-packages/django_ledger/models/entity.py:3171 #: venv/lib/python3.11/site-packages/django_ledger/templates/django_ledger/bills/includes/card_bill.html:11 #: venv/lib/python3.11/site-packages/django_ledger/templates/django_ledger/bills/includes/card_bill.html:61 msgid "Bill" msgstr "الفاتورة" -#: inventory/forms.py:940 +#: inventory/forms.py:946 #: templates/ledger/bank_accounts/bank_account_detail.html:50 -#: venv/lib/python3.11/site-packages/django_ledger/models/transactions.py:447 +#: venv/lib/python3.11/site-packages/django_ledger/models/transactions.py:471 #: venv/lib/python3.11/site-packages/django_ledger/templates/django_ledger/purchase_order/includes/po_item_formset.html:22 #: venv/lib/python3.11/site-packages/django_ledger/templates/django_ledger/purchase_order/tags/po_item_table.html:11 msgid "Amount" msgstr "المبلغ" -#: inventory/forms.py:943 inventory/models.py:1674 +#: inventory/forms.py:949 inventory/models.py:1957 msgid "cash" msgstr "نقداً" -#: inventory/forms.py:944 inventory/models.py:1675 +#: inventory/forms.py:950 inventory/models.py:1958 msgid "credit" msgstr "دائن" -#: inventory/forms.py:945 inventory/models.py:1676 -#: templates/inventory/car_detail.html:164 -#: templates/inventory/transfer_car.html:23 +#: inventory/forms.py:951 inventory/models.py:1959 +#: templates/inventory/car_detail.html:191 +#: templates/inventory/transfer_car.html:18 msgid "transfer" msgstr "نقل" -#: inventory/forms.py:946 inventory/models.py:1677 +#: inventory/forms.py:952 inventory/models.py:1960 msgid "debit" msgstr "مدين" -#: inventory/forms.py:947 inventory/models.py:1678 inventory/models.py:1753 +#: inventory/forms.py:953 inventory/models.py:1961 inventory/models.py:2036 msgid "SADAD" msgstr "سداد" -#: inventory/forms.py:949 templates/sales/estimates/sale_order_form.html:177 +#: inventory/forms.py:955 templates/sales/estimates/sale_order_form.html:177 msgid "Payment Method" msgstr "طريقة الدفع" -#: inventory/forms.py:953 +#: inventory/forms.py:959 msgid "Payment Date" msgstr "تاريخ الدفع" -#: inventory/forms.py:962 inventory/forms.py:968 +#: inventory/forms.py:968 inventory/forms.py:974 msgid "Payment amount is greater than amount due" msgstr "مبلغ الدفع أكبر من المبلغ المستحق" -#: inventory/forms.py:964 +#: inventory/forms.py:970 msgid "Payment amount must be greater than 0" msgstr "يجب أن يكون مبلغ الدفع أكبر من 0" -#: inventory/forms.py:966 +#: inventory/forms.py:972 msgid "Invoice is already paid" msgstr "تم دفع الفاتورة بالفعل" -#: inventory/forms.py:994 templates/inventory/transfer_details.html:61 -#: templates/inventory/transfer_preview.html:221 +#: inventory/forms.py:1000 templates/inventory/transfer_details.html:79 +#: templates/inventory/transfer_preview.html:277 msgid "To" msgstr "إلى" -#: inventory/forms.py:1016 inventory/models.py:174 inventory/models.py:390 -#: inventory/models.py:1277 inventory/tables.py:52 -#: templates/inventory/car_list_view.html:64 -#: templates/inventory/car_list_view.html:109 -#: templates/inventory/cars_list_api.html:32 +#: inventory/forms.py:1022 inventory/models.py:203 inventory/models.py:485 +#: inventory/models.py:1462 inventory/tables.py:52 +#: templates/inventory/car_list_view.html:103 +#: templates/inventory/car_list_view.html:163 +#: templates/inventory/cars_list_api.html:33 #: templates/sales/estimates/estimate_detail.html:191 #: templates/sales/estimates/sale_order_form.html:124 #: templates/sales/estimates/sale_order_preview.html:179 @@ -389,11 +410,11 @@ msgstr "إلى" msgid "Make" msgstr "الصانع" -#: inventory/forms.py:1033 inventory/models.py:187 inventory/models.py:398 -#: inventory/models.py:1284 inventory/tables.py:53 -#: templates/inventory/car_list_view.html:73 -#: templates/inventory/car_list_view.html:110 -#: templates/inventory/cars_list_api.html:33 +#: inventory/forms.py:1039 inventory/models.py:226 inventory/models.py:493 +#: inventory/models.py:1469 inventory/tables.py:53 +#: templates/inventory/car_list_view.html:117 +#: templates/inventory/car_list_view.html:164 +#: templates/inventory/cars_list_api.html:34 #: templates/sales/estimates/estimate_detail.html:192 #: templates/sales/estimates/sale_order_form.html:126 #: templates/sales/estimates/sale_order_preview.html:180 @@ -402,17 +423,28 @@ msgstr "الصانع" msgid "Model" msgstr "الموديل" -#: inventory/forms.py:1312 inventory/models.py:421 inventory/models.py:1319 -#: inventory/models.py:1484 inventory/models.py:1535 inventory/tables.py:62 -#: templates/crm/leads/lead_detail.html:51 -#: templates/crm/opportunities/opportunity_detail.html:88 -#: templates/inventory/car_detail.html:83 -#: templates/inventory/car_detail.html:368 -#: templates/inventory/car_inventory.html:58 -#: templates/inventory/car_list.html:163 -#: templates/inventory/car_list_view.html:115 -#: templates/inventory/cars_list_api.html:18 -#: templates/inventory/cars_list_api.html:34 templates/plans/current.html:24 +#: inventory/forms.py:1153 +msgid "Expected Closing Date" +msgstr "تاريخ الإغلاق المتوقع" + +#: inventory/forms.py:1158 +msgid "Probability (%)" +msgstr "الاحتمالية (%)" + +#: inventory/forms.py:1347 inventory/models.py:516 inventory/models.py:1504 +#: inventory/models.py:1792 inventory/tables.py:62 +#: templates/admin_management/user_management.html:22 +#: templates/admin_management/user_management.html:86 +#: templates/admin_management/user_management.html:150 +#: templates/admin_management/user_management.html:214 +#: templates/crm/leads/lead_detail.html:130 +#: templates/inventory/car_detail.html:100 +#: templates/inventory/car_detail.html:399 +#: templates/inventory/car_inventory.html:78 +#: templates/inventory/car_list.html:172 +#: templates/inventory/car_list_view.html:169 +#: templates/inventory/cars_list_api.html:19 +#: templates/inventory/cars_list_api.html:35 templates/plans/current.html:24 #: templates/sales/estimates/estimate_list.html:16 #: templates/sales/invoices/invoice_list.html:17 #: templates/sales/journals/journal_list.html:17 @@ -426,178 +458,195 @@ msgstr "الموديل" msgid "Status" msgstr "الحالة" -#: inventory/forms.py:1328 inventory/models.py:1479 -#: templates/crm/leads/lead_list.html:77 -#: templates/crm/opportunities/opportunity_detail.html:95 -#: templates/crm/opportunities/opportunity_form.html:48 +#: inventory/forms.py:1363 inventory/models.py:1708 msgid "Stage" msgstr "المرحلة" -#: inventory/forms.py:1457 +#: inventory/forms.py:1492 msgid "Select Car Makes" msgstr "اختر ماركات السيارات" -#: inventory/forms.py:1517 +#: inventory/forms.py:1552 msgid "Please enter a valid credit card number" msgstr "يرجى إدخال رقم بطاقة ائتمان صالح" -#: inventory/forms.py:1547 +#: inventory/forms.py:1582 msgid "Please enter a valid month (01-12)" msgstr "يرجى إدخال شهر صالح (01-12)" -#: inventory/forms.py:1554 +#: inventory/forms.py:1589 msgid "This card appears to be expired" msgstr "يبدو أن هذه البطاقة منتهية الصلاحية" -#: inventory/forms.py:1557 +#: inventory/forms.py:1592 msgid "Please enter a valid expiry date in MM/YY format" msgstr "يرجى إدخال تاريخ انتهاء صلاحية صحيح بصيغة MM/YY" -#: inventory/forms.py:1566 +#: inventory/forms.py:1601 msgid "CVV must contain only digits" msgstr "يجب أن يحتوي رمز التحقق (CVV) على أرقام فقط" -#: inventory/forms.py:1568 +#: inventory/forms.py:1603 msgid "CVV must be 3 or 4 digits" msgstr "يجب أن يكون رمز التحقق (CVV) مكونًا من 3 أو 4 أرقام" -#: inventory/forms.py:1577 inventory/forms.py:1580 inventory/models.py:1047 -#: inventory/models.py:1258 +#: inventory/forms.py:1612 inventory/forms.py:1615 inventory/models.py:1178 +#: inventory/models.py:1442 templates/admin_management/user_management.html:19 #: templates/administration/manage_staff_personal_info.html:18 -#: templates/pricing_page.html:93 templates/pricing_page.html:96 +#: templates/pricing_page.html:92 templates/pricing_page.html:95 msgid "First Name" msgstr "الاسم الأول" -#: inventory/forms.py:1587 inventory/forms.py:1590 inventory/models.py:1051 -#: inventory/models.py:1259 +#: inventory/forms.py:1622 inventory/forms.py:1625 inventory/models.py:1182 +#: inventory/models.py:1443 templates/admin_management/user_management.html:20 #: templates/administration/manage_staff_personal_info.html:24 -#: templates/pricing_page.html:100 templates/pricing_page.html:103 +#: templates/pricing_page.html:99 templates/pricing_page.html:102 msgid "Last Name" msgstr "اسم العائلة" -#: inventory/forms.py:1613 templates/pricing_page.html:143 -#: templates/pricing_page.html:146 templates/pricing_page.html:193 +#: inventory/forms.py:1648 templates/pricing_page.html:142 +#: templates/pricing_page.html:145 templates/pricing_page.html:192 msgid "Card Number" msgstr "رقم البطاقة" -#: inventory/forms.py:1624 +#: inventory/forms.py:1659 msgid "Expiration Date" msgstr "تاريخ الانتهاء" -#: inventory/forms.py:1635 +#: inventory/forms.py:1670 msgid "Security Code (CVV)" msgstr "رمز الأمان (CVV)" -#: inventory/forms.py:1647 +#: inventory/forms.py:1682 msgid "Name on Card" msgstr "الاسم على البطاقة" -#: inventory/forms.py:1657 +#: inventory/forms.py:1692 msgid "I agree to the Terms and Conditions" msgstr "أوافق على الشروط وسياسة الخصوصية" -#: inventory/forms.py:1659 +#: inventory/forms.py:1694 msgid "You must accept the terms and conditions" msgstr "يجب أن تقبل الشروط وسياسة الخصوصية." -#: inventory/models.py:147 inventory/models.py:440 inventory/models.py:523 -#: inventory/models.py:568 inventory/models.py:725 inventory/models.py:740 -#: inventory/models.py:784 inventory/models.py:1476 -#: templates/crm/leads/lead_list.html:35 -#: templates/crm/opportunities/opportunity_form.html:35 -#: templates/dashboards/manager.html:52 -#: templates/inventory/transfer_details.html:70 +#: inventory/models.py:36 +msgid "Primary Key" +msgstr "المفتاح الأساسي" + +#: inventory/models.py:37 inventory/models.py:1726 inventory/models.py:1879 +msgid "Slug" +msgstr "المُعرّف الفريد (Slug)" + +#: inventory/models.py:38 +msgid "" +"Slug for the object. If not provided, it will be generated automatically." +msgstr "المُعرّف الفريد للكائن. إذا لم يتم توفيره، فسيتم إنشاؤه تلقائيًا." + +#: inventory/models.py:39 inventory/models.py:646 inventory/models.py:859 +#: inventory/models.py:1878 +msgid "Created At" +msgstr "تاريخ الإنشاء" + +#: inventory/models.py:40 inventory/models.py:647 inventory/models.py:930 +msgid "Updated At" +msgstr "تم التحديث" + +#: inventory/models.py:165 inventory/models.py:536 inventory/models.py:620 +#: inventory/models.py:665 inventory/models.py:822 inventory/models.py:837 +#: inventory/models.py:881 inventory/models.py:1705 +#: templates/crm/leads/lead_list.html:91 templates/dashboards/manager.html:52 +#: templates/inventory/transfer_details.html:88 msgid "Car" msgstr "سيارة" -#: inventory/models.py:148 +#: inventory/models.py:166 msgid "Light Commercial" msgstr "مركبات تجارية خفيفة" -#: inventory/models.py:149 +#: inventory/models.py:167 msgid "Heavy-Duty Tractors" msgstr "جرارات ثقيلة" -#: inventory/models.py:150 +#: inventory/models.py:168 msgid "Trailers" msgstr "مقطورات" -#: inventory/models.py:151 +#: inventory/models.py:169 msgid "Medium Trucks" msgstr "شاحنات متوسطة" -#: inventory/models.py:152 +#: inventory/models.py:170 msgid "Buses" msgstr "حافلات" -#: inventory/models.py:153 +#: inventory/models.py:171 msgid "Motorcycles" msgstr "دراجات نارية" -#: inventory/models.py:154 +#: inventory/models.py:172 msgid "Buggy" msgstr "باجي" -#: inventory/models.py:155 +#: inventory/models.py:173 msgid "Moto ATV" msgstr "موتو ATV" -#: inventory/models.py:156 +#: inventory/models.py:174 msgid "Scooters" msgstr "دراجات سكوتر" -#: inventory/models.py:157 +#: inventory/models.py:175 msgid "Karting" msgstr "كارتينج" -#: inventory/models.py:158 +#: inventory/models.py:176 msgid "ATV" msgstr "مركبات ATV" -#: inventory/models.py:159 +#: inventory/models.py:177 msgid "Snowmobiles" msgstr "دراجات الثلج" -#: inventory/models.py:166 +#: inventory/models.py:185 msgid "logo" msgstr "الشعار" -#: inventory/models.py:205 inventory/models.py:407 inventory/tables.py:55 -#: templates/inventory/car_form.html:75 -#: ⁨templates/inventory/car_form_qabl alfalsafa.html⁩:121 +#: inventory/models.py:255 inventory/models.py:502 inventory/tables.py:55 +#: templates/inventory/car_form.html:82 +#: ⁨templates/inventory/car_form_qabl alfalsafa.html⁩:100 msgid "Series" msgstr "السلسلة" -#: inventory/models.py:222 inventory/models.py:415 inventory/tables.py:56 -#: templates/inventory/car_list_view.html:112 +#: inventory/models.py:283 inventory/models.py:510 inventory/tables.py:56 +#: templates/inventory/car_list_view.html:166 #: templates/sales/sales_list.html:115 msgid "Trim" msgstr "الفئة" -#: inventory/models.py:236 +#: inventory/models.py:302 #: venv/lib/python3.11/site-packages/django_ledger/io/roles.py:455 #: venv/lib/python3.11/site-packages/django_ledger/io/roles.py:541 #: venv/lib/python3.11/site-packages/django_ledger/models/items.py:509 msgid "Equipment" msgstr "المعدات" -#: inventory/models.py:251 +#: inventory/models.py:328 msgid "Specification" msgstr "المواصفة" -#: inventory/models.py:267 +#: inventory/models.py:344 msgid "Specification Value" msgstr "قيمة المواصفة" -#: inventory/models.py:282 +#: inventory/models.py:370 msgid "Option" msgstr "الخيار" -#: inventory/models.py:301 +#: inventory/models.py:389 msgid "Option Value" msgstr "قيمة الخيار" -#: inventory/models.py:305 templates/ledger/bills/bill_detail.html:191 +#: inventory/models.py:393 templates/ledger/bills/bill_detail.html:191 #: templates/sales/estimates/estimate_detail.html:82 #: templates/sales/estimates/estimate_detail.html:169 #: templates/sales/estimates/estimate_list.html:29 @@ -611,7 +660,7 @@ msgstr "قيمة الخيار" msgid "Draft" msgstr "مسودة" -#: inventory/models.py:306 templates/ledger/bills/bill_detail.html:195 +#: inventory/models.py:394 templates/ledger/bills/bill_detail.html:195 #: templates/sales/estimates/estimate_detail.html:86 #: templates/sales/estimates/estimate_detail.html:173 #: templates/sales/estimates/estimate_list.html:33 @@ -626,107 +675,105 @@ msgstr "مسودة" msgid "Approved" msgstr "تمت الموافقة" -#: inventory/models.py:307 inventory/models.py:981 -#: templates/crm/leads/lead_detail.html:55 -#: templates/crm/leads/lead_list.html:123 test.txt:46 +#: inventory/models.py:395 templates/crm/leads/lead_list.html:167 test.txt:46 msgid "Pending" msgstr "قيد الانتظار" -#: inventory/models.py:308 +#: inventory/models.py:396 msgid "Accepted" msgstr "تم القبول" -#: inventory/models.py:309 templates/administration/staff_index.html:83 +#: inventory/models.py:397 templates/administration/staff_index.html:83 #: venv/lib/python3.11/site-packages/appointment/templates/administration/staff_index.html:329 msgid "Success" msgstr "ناجحة" -#: inventory/models.py:310 +#: inventory/models.py:398 msgid "Reject" msgstr "رفض" -#: inventory/models.py:311 +#: inventory/models.py:399 msgid "Cancelled" msgstr "ملغى" -#: inventory/models.py:315 templates/dashboards/manager.html:103 +#: inventory/models.py:403 templates/dashboards/manager.html:103 #: templates/dashboards/manager.html:235 templates/dashboards/sales.html:20 #: templates/dashboards/sales.html:332 -#: templates/inventory/car_inventory.html:99 -#: templates/inventory/car_list_view.html:38 -#: templates/inventory/car_list_view.html:86 -#: templates/inventory/car_list_view.html:154 -#: templates/inventory/cars_list_api.html:19 +#: templates/inventory/car_inventory.html:131 +#: templates/inventory/car_list_view.html:45 +#: templates/inventory/car_list_view.html:130 +#: templates/inventory/car_list_view.html:210 +#: templates/inventory/cars_list_api.html:20 #: venv/lib/python3.11/site-packages/django_ledger/templates/django_ledger/invoice/tags/invoice_item_formset.html:21 msgid "Available" msgstr "متاح" -#: inventory/models.py:316 templates/dashboards/manager.html:109 +#: inventory/models.py:404 templates/dashboards/manager.html:109 #: templates/dashboards/manager.html:236 templates/dashboards/sales.html:26 #: templates/dashboards/sales.html:333 -#: templates/inventory/car_inventory.html:101 -#: templates/inventory/car_list_view.html:41 -#: templates/inventory/car_list_view.html:88 -#: templates/inventory/car_list_view.html:158 -#: templates/inventory/cars_list_api.html:21 +#: templates/inventory/car_inventory.html:133 +#: templates/inventory/car_list_view.html:56 +#: templates/inventory/car_list_view.html:132 +#: templates/inventory/car_list_view.html:214 +#: templates/inventory/cars_list_api.html:22 msgid "Sold" msgstr "تم البيع" -#: inventory/models.py:317 templates/dashboards/manager.html:127 +#: inventory/models.py:405 templates/dashboards/manager.html:127 #: templates/dashboards/manager.html:239 templates/dashboards/sales.html:44 #: templates/dashboards/sales.html:336 -#: templates/inventory/car_inventory.html:103 +#: templates/inventory/car_inventory.html:135 msgid "Hold" msgstr "في الانتظار" -#: inventory/models.py:318 templates/dashboards/manager.html:133 +#: inventory/models.py:406 templates/dashboards/manager.html:133 #: templates/dashboards/manager.html:240 templates/dashboards/sales.html:50 #: templates/dashboards/sales.html:337 -#: templates/inventory/car_inventory.html:107 -#: templates/inventory/cars_list_api.html:23 +#: templates/inventory/car_inventory.html:142 +#: templates/inventory/cars_list_api.html:24 msgid "Damaged" msgstr "تالف" -#: inventory/models.py:319 templates/dashboards/manager.html:115 +#: inventory/models.py:407 templates/dashboards/manager.html:115 #: templates/dashboards/manager.html:237 templates/dashboards/sales.html:32 #: templates/dashboards/sales.html:334 -#: templates/inventory/car_inventory.html:105 -#: templates/inventory/car_list_view.html:39 -#: templates/inventory/car_list_view.html:87 -#: templates/inventory/car_list_view.html:156 -#: templates/inventory/cars_list_api.html:20 +#: templates/inventory/car_inventory.html:140 +#: templates/inventory/car_list_view.html:49 +#: templates/inventory/car_list_view.html:131 +#: templates/inventory/car_list_view.html:212 +#: templates/inventory/cars_list_api.html:21 msgid "Reserved" msgstr "محجوزة" -#: inventory/models.py:320 templates/dashboards/manager.html:121 -#: templates/dashboards/manager.html:238 templates/dashboards/sales.html:38 -#: templates/dashboards/sales.html:335 -#: templates/inventory/car_list_view.html:40 -#: templates/inventory/car_list_view.html:89 -#: templates/inventory/car_list_view.html:160 -#: templates/inventory/cars_list_api.html:22 -#: templates/inventory/transfer_preview.html:213 +#: inventory/models.py:408 inventory/models.py:1138 +#: templates/dashboards/manager.html:121 templates/dashboards/manager.html:238 +#: templates/dashboards/sales.html:38 templates/dashboards/sales.html:335 +#: templates/inventory/car_list_view.html:53 +#: templates/inventory/car_list_view.html:133 +#: templates/inventory/car_list_view.html:216 +#: templates/inventory/cars_list_api.html:23 +#: templates/inventory/transfer_preview.html:264 msgid "Transfer" msgstr "نقل" -#: inventory/models.py:323 inventory/models.py:980 -#: templates/crm/leads/lead_detail.html:53 -#: templates/crm/leads/lead_list.html:121 -#: templates/inventory/car_inventory.html:68 test.txt:33 +#: inventory/models.py:411 inventory/models.py:1104 +#: templates/crm/leads/lead_detail.html:132 +#: templates/crm/leads/lead_list.html:165 +#: templates/inventory/car_inventory.html:90 test.txt:33 msgid "New" msgstr "جديد" -#: inventory/models.py:324 templates/inventory/car_inventory.html:70 +#: inventory/models.py:412 templates/inventory/car_inventory.html:92 msgid "Used" msgstr "مستعمل" -#: inventory/models.py:330 inventory/models.py:759 +#: inventory/models.py:418 inventory/models.py:856 inventory/models.py:1765 #: templates/administration/manage_day_off.html:63 #: templates/administration/manage_service.html:33 #: templates/administration/user_profile.html:93 #: templates/administration/user_profile.html:243 -#: templates/ledger/coa_accounts/account_detail.html:67 -#: templates/ledger/journal_entry/journal_entry_list.html:65 +#: templates/ledger/coa_accounts/account_detail.html:70 +#: templates/ledger/journal_entry/journal_entry_list.html:51 #: templates/ledger/journal_entry/journal_entry_transactions.html:23 #: templates/ledger/reports/tags/income_statement.html:9 #: templates/plans/invoices/layout.html:102 @@ -749,41 +796,46 @@ msgstr "مستعمل" msgid "Description" msgstr "الوصف" -#: inventory/models.py:332 inventory/tables.py:58 +#: inventory/models.py:420 inventory/tables.py:58 #: templates/administration/manage_service.html:55 #: templates/administration/service_list.html:25 #: templates/administration/user_profile.html:245 -#: templates/inventory/transfer_details.html:72 templates/pricing_page.html:180 +#: templates/inventory/transfer_details.html:89 templates/pricing_page.html:179 #: templates/sales/sales_list.html:116 #: venv/lib/python3.11/site-packages/appointment/templates/administration/service_list.html:30 #: venv/lib/python3.11/site-packages/appointment/templates/administration/user_profile.html:237 msgid "Price" msgstr "السعر" -#: inventory/models.py:334 +#: inventory/models.py:422 msgid "taxable" msgstr "خاضع للضريبة" -#: inventory/models.py:338 +#: inventory/models.py:426 msgid "Unit of Measurement" msgstr "وحدة القياس" -#: inventory/models.py:341 inventory/models.py:375 inventory/models.py:884 +#: inventory/models.py:429 inventory/models.py:470 inventory/models.py:981 msgid "Dealer" msgstr "المعرض" -#: inventory/models.py:365 inventory/models.py:366 +#: inventory/models.py:453 inventory/models.py:454 #: templates/sales/estimates/estimate_detail.html:227 #: templates/sales/estimates/sale_order_preview.html:206 #: templates/sales/invoices/invoice_detail.html:273 msgid "Additional Services" msgstr "الخدمات الإضافية" -#: inventory/models.py:382 inventory/models.py:1615 -#: templates/inventory/car_detail.html:100 -#: templates/inventory/car_form.html:144 -#: ⁨templates/inventory/car_form_qabl alfalsafa.html⁩:166 -#: templates/ledger/bills/bill_list.html:51 +#: inventory/models.py:464 +#: venv/lib/python3.11/site-packages/django_ledger/models/items.py:1053 +msgid "Item Model" +msgstr "نموذج العنصر" + +#: inventory/models.py:477 inventory/models.py:1892 +#: templates/inventory/car_detail.html:117 +#: templates/inventory/car_form.html:147 +#: ⁨templates/inventory/car_form_qabl alfalsafa.html⁩:136 +#: templates/ledger/bills/bill_list.html:52 #: venv/lib/python3.11/site-packages/django_ledger/models/bill.py:364 #: venv/lib/python3.11/site-packages/django_ledger/models/vendor.py:191 #: venv/lib/python3.11/site-packages/django_ledger/templates/django_ledger/bills/tags/bill_table.html:12 @@ -791,12 +843,12 @@ msgstr "الخدمات الإضافية" msgid "Vendor" msgstr "المورد" -#: inventory/models.py:400 inventory/models.py:1287 inventory/tables.py:54 -#: templates/inventory/car_form.html:65 -#: ⁨templates/inventory/car_form_qabl alfalsafa.html⁩:61 -#: templates/inventory/car_inventory.html:54 -#: templates/inventory/car_list_view.html:79 -#: templates/inventory/car_list_view.html:111 +#: inventory/models.py:495 inventory/models.py:1472 inventory/tables.py:54 +#: templates/inventory/car_form.html:72 +#: ⁨templates/inventory/car_form_qabl alfalsafa.html⁩:55 +#: templates/inventory/car_inventory.html:67 +#: templates/inventory/car_list_view.html:123 +#: templates/inventory/car_list_view.html:165 #: templates/ledger/reports/components/period_navigator.html:21 #: templates/sales/estimates/estimate_detail.html:193 #: templates/sales/estimates/sale_order_form.html:128 @@ -805,214 +857,205 @@ msgstr "المورد" msgid "Year" msgstr "السنة" -#: inventory/models.py:427 inventory/tables.py:50 -#: templates/inventory/car_detail.html:87 templates/inventory/car_form.html:157 -#: ⁨templates/inventory/car_form_qabl alfalsafa.html⁩:183 -#: templates/inventory/car_list.html:177 +#: inventory/models.py:522 inventory/tables.py:50 +#: templates/inventory/car_detail.html:104 +#: templates/inventory/car_form.html:158 +#: ⁨templates/inventory/car_form_qabl alfalsafa.html⁩:147 +#: templates/inventory/car_list.html:184 msgid "Stock Type" msgstr "نوع المخزون" -#: inventory/models.py:429 inventory/models.py:541 -#: templates/inventory/car_detail.html:105 -#: templates/inventory/car_form.html:195 -#: ⁨templates/inventory/car_form_qabl alfalsafa.html⁩:232 -#: templates/inventory/car_list.html:200 +#: inventory/models.py:524 inventory/models.py:638 +#: templates/inventory/car_detail.html:122 +#: templates/inventory/car_form.html:191 +#: ⁨templates/inventory/car_form_qabl alfalsafa.html⁩:181 +#: templates/inventory/car_list.html:210 msgid "Remarks" msgstr "ملاحظات" -#: inventory/models.py:430 inventory/tables.py:57 -#: templates/inventory/car_detail.html:91 templates/inventory/car_form.html:169 -#: ⁨templates/inventory/car_form_qabl alfalsafa.html⁩:198 -#: templates/inventory/car_list.html:191 templates/inventory/car_list.html:192 +#: inventory/models.py:525 inventory/tables.py:57 +#: templates/inventory/car_detail.html:108 +#: templates/inventory/car_form.html:169 +#: ⁨templates/inventory/car_form_qabl alfalsafa.html⁩:157 +#: templates/inventory/car_list.html:196 templates/inventory/car_list.html:202 msgid "Mileage" msgstr "عدد الكيلومترات" -#: inventory/models.py:431 templates/inventory/car_detail.html:95 -#: templates/inventory/car_form.html:182 -#: ⁨templates/inventory/car_form_qabl alfalsafa.html⁩:215 +#: inventory/models.py:526 templates/inventory/car_detail.html:112 +#: templates/inventory/car_form.html:180 +#: ⁨templates/inventory/car_form_qabl alfalsafa.html⁩:168 msgid "Receiving Date" msgstr "تاريخ الاستلام" -#: inventory/models.py:432 +#: inventory/models.py:527 msgid "Hash" msgstr "رمز" -#: inventory/models.py:441 templates/header.html:36 +#: inventory/models.py:537 templates/header.html:36 #: templates/sales/estimates/estimate_form.html:38 msgid "Cars" msgstr "السيارات" -#: inventory/models.py:488 -msgid "Car Sold" -msgstr "تم بيع السيارة" - -#: inventory/models.py:529 +#: inventory/models.py:626 msgid "From Dealer" msgstr "من معرض" -#: inventory/models.py:535 +#: inventory/models.py:632 msgid "To Dealer" msgstr "الى معرض" -#: inventory/models.py:538 +#: inventory/models.py:635 msgid "Transfer Date" msgstr "تاريخ النقل" -#: inventory/models.py:549 inventory/models.py:762 inventory/models.py:1612 -msgid "Created At" -msgstr "تاريخ الإنشاء" - -#: inventory/models.py:550 inventory/models.py:833 -msgid "Updated At" -msgstr "تم التحديث" - -#: inventory/models.py:556 +#: inventory/models.py:653 msgid "Car Transfer Log" msgstr "سجل نقل السيارة" -#: inventory/models.py:557 +#: inventory/models.py:654 msgid "Car Transfer Logs" msgstr "سجلات نقل السيارات" -#: inventory/models.py:574 templates/inventory/car_detail.html:311 +#: inventory/models.py:671 templates/inventory/car_detail.html:334 msgid "Reserved By" msgstr "محجوز بواسطة" -#: inventory/models.py:582 +#: inventory/models.py:679 msgid "Reserved At" msgstr "تاريخ الحجز" -#: inventory/models.py:583 +#: inventory/models.py:680 msgid "Reserved Until" msgstr "محجوز حتى" -#: inventory/models.py:593 templates/inventory/car_detail.html:451 +#: inventory/models.py:690 templates/inventory/car_detail.html:499 msgid "Car Reservation" msgstr "حجز السيارة" -#: inventory/models.py:594 +#: inventory/models.py:691 msgid "Car Reservations" msgstr "حجوزات السيارات" -#: inventory/models.py:604 templates/inventory/car_detail.html:201 +#: inventory/models.py:701 templates/inventory/car_detail.html:229 msgid "Cost Price" msgstr "سعر التكلفة" -#: inventory/models.py:607 templates/inventory/car_detail.html:206 +#: inventory/models.py:704 templates/inventory/car_detail.html:234 msgid "Selling Price" msgstr "سعر البيع" -#: inventory/models.py:612 templates/inventory/car_detail.html:210 +#: inventory/models.py:709 templates/inventory/car_detail.html:238 #: templates/sales/estimates/estimate_detail.html:221 #: templates/sales/invoices/invoice_detail.html:261 msgid "Discount Amount" msgstr "مبلغ الخصم" -#: inventory/models.py:672 inventory/models.py:673 +#: inventory/models.py:769 inventory/models.py:770 msgid "Car Financial Details" msgstr "تفاصيل المالية للسيارة" -#: inventory/models.py:679 inventory/models.py:692 +#: inventory/models.py:776 inventory/models.py:789 msgid "RGB" msgstr "آر جي بي" -#: inventory/models.py:682 inventory/models.py:683 +#: inventory/models.py:779 inventory/models.py:780 #: templates/inventory/add_colors.html:13 msgid "Exterior Colors" msgstr "الألوان الخارجية" -#: inventory/models.py:695 inventory/models.py:696 +#: inventory/models.py:792 inventory/models.py:793 #: templates/inventory/add_colors.html:33 msgid "Interior Colors" msgstr "الألوان الداخلية" -#: inventory/models.py:712 templates/inventory/car_list_view.html:113 +#: inventory/models.py:809 templates/inventory/car_list_view.html:167 msgid "Color" msgstr "اللون" -#: inventory/models.py:713 +#: inventory/models.py:810 msgid "Colors" msgstr "الألوان" -#: inventory/models.py:727 templates/inventory/car_detail.html:118 +#: inventory/models.py:824 templates/inventory/car_detail.html:139 msgid "Custom Number" msgstr "رقم البطاقة الجمركية" -#: inventory/models.py:731 templates/inventory/car_detail.html:127 -#: templates/inventory/car_detail.html:421 +#: inventory/models.py:828 templates/inventory/car_detail.html:148 +#: templates/inventory/car_detail.html:457 msgid "Custom Card" msgstr "البطاقة الجمركية" -#: inventory/models.py:732 +#: inventory/models.py:829 msgid "Custom Cards" msgstr "البطاقات الجمركية" -#: inventory/models.py:746 inventory/models.py:1492 +#: inventory/models.py:843 inventory/models.py:1715 msgid "Owner" msgstr "المالك" -#: inventory/models.py:747 +#: inventory/models.py:844 msgid "Dealer who owns the car." msgstr "التاجر الذي يمتلك السيارة." -#: inventory/models.py:753 inventory/models.py:960 +#: inventory/models.py:850 inventory/models.py:1084 msgid "Showroom" msgstr "صالة العرض" -#: inventory/models.py:754 +#: inventory/models.py:851 msgid "Dealer where the car is displayed (can be the owner)." msgstr "التاجر الذي تُعرض السيارة في صالته (يمكن أن يكون المالك)." -#: inventory/models.py:760 +#: inventory/models.py:857 msgid "Optional description about the showroom placement." msgstr "وصف اختياري حول وضع السيارة في صالة العرض." -#: inventory/models.py:763 +#: inventory/models.py:860 msgid "Last Updated" msgstr "آخر تحديث" -#: inventory/models.py:766 +#: inventory/models.py:863 msgid "Car Location" msgstr "موقع السيارة" -#: inventory/models.py:767 +#: inventory/models.py:864 msgid "Car Locations" msgstr "مواقف السيارات" -#: inventory/models.py:786 +#: inventory/models.py:883 msgid "Plate Number" msgstr "رقم اللوحة" -#: inventory/models.py:787 +#: inventory/models.py:884 msgid "Text 1" msgstr "النص 1" -#: inventory/models.py:788 +#: inventory/models.py:885 msgid "Text 2" msgstr "النص 2" -#: inventory/models.py:789 +#: inventory/models.py:886 msgid "Text 3" msgstr "النص 3" -#: inventory/models.py:790 templates/inventory/car_detail.html:143 +#: inventory/models.py:887 templates/inventory/car_detail.html:165 msgid "Registration Date" msgstr "تاريخ التسجيل" -#: inventory/models.py:793 templates/inventory/car_detail.html:137 -#: templates/inventory/car_detail.html:149 -#: templates/inventory/car_detail.html:436 +#: inventory/models.py:890 templates/inventory/car_detail.html:159 +#: templates/inventory/car_detail.html:170 +#: templates/inventory/car_detail.html:478 msgid "Registration" msgstr "التسجيل" -#: inventory/models.py:794 +#: inventory/models.py:891 msgid "Registrations" msgstr "تسجيل السيارات" -#: inventory/models.py:802 inventory/models.py:911 inventory/models.py:1072 -#: inventory/models.py:1167 inventory/models.py:1324 inventory/models.py:1497 -#: inventory/models.py:1517 inventory/models.py:1539 inventory/models.py:1562 -#: inventory/models.py:1579 templates/crm/leads/lead_detail.html:100 +#: inventory/models.py:899 inventory/models.py:1009 inventory/models.py:1203 +#: inventory/models.py:1324 inventory/models.py:1523 inventory/models.py:1723 +#: inventory/models.py:1749 inventory/models.py:1774 inventory/models.py:1796 +#: inventory/models.py:1819 inventory/models.py:1836 +#: templates/crm/leads/lead_detail.html:181 #: templates/sales/estimates/estimate_list.html:18 #: templates/sales/invoices/invoice_list.html:19 #: templates/sales/journals/journal_list.html:19 @@ -1022,26 +1065,27 @@ msgstr "تسجيل السيارات" msgid "Created" msgstr "تاريخ الإنشاء" -#: inventory/models.py:803 inventory/models.py:912 inventory/models.py:1073 -#: inventory/models.py:1168 inventory/models.py:1326 inventory/models.py:1498 -#: inventory/models.py:1518 inventory/models.py:1540 inventory/models.py:1563 +#: inventory/models.py:900 inventory/models.py:1010 inventory/models.py:1204 +#: inventory/models.py:1325 inventory/models.py:1525 inventory/models.py:1724 +#: inventory/models.py:1750 inventory/models.py:1775 inventory/models.py:1797 +#: inventory/models.py:1820 #: venv/lib/python3.11/site-packages/django_ledger/templates/django_ledger/chart_of_accounts/includes/coa_card.html:41 msgid "Updated" msgstr "تم التحديث" -#: inventory/models.py:827 inventory/models.py:1164 inventory/models.py:1610 +#: inventory/models.py:924 inventory/models.py:1321 inventory/models.py:1875 msgid "Logo" msgstr "الشعار" -#: inventory/models.py:832 +#: inventory/models.py:929 msgid "Joined At" msgstr "انضم في" -#: inventory/models.py:885 +#: inventory/models.py:982 msgid "Dealers" msgstr "المعارض" -#: inventory/models.py:896 inventory/tasks.py:63 templates/header.html:17 +#: inventory/models.py:993 inventory/tasks.py:62 templates/header.html:17 #: templates/header.html:22 templates/welcome.html:27 #: venv/lib/python3.11/site-packages/django_ledger/io/roles.py:440 #: venv/lib/python3.11/site-packages/django_ledger/io/roles.py:526 @@ -1050,281 +1094,27 @@ msgstr "المعارض" msgid "Inventory" msgstr "المخزن" -#: inventory/models.py:897 +#: inventory/models.py:994 msgid "Accountant" msgstr "محاسب" -#: inventory/models.py:898 templates/header.html:110 +#: inventory/models.py:995 templates/header.html:110 msgid "Sales" msgstr "المبيعات" -#: inventory/models.py:910 +#: inventory/models.py:1007 msgid "Staff Type" msgstr "نوع الموظف" -#: inventory/models.py:949 inventory/models.py:950 -#: templates/crm/opportunities/opportunity_detail.html:231 -#: templates/crm/opportunities/opportunity_form.html:70 -#: templates/dashboards/manager.html:16 templates/users/user_form.html:4 -#: templates/users/user_list.html:5 -msgid "Staff" -msgstr "الموظفون" - -#: inventory/models.py:958 -msgid "Referrals" -msgstr "إحالات" - -#: inventory/models.py:959 inventory/models.py:1006 -msgid "WhatsApp" -msgstr "واتساب" - -#: inventory/models.py:961 -msgid "TikTok" -msgstr "تيك توك" - -#: inventory/models.py:962 -msgid "Instagram" -msgstr "إنستغرام" - -#: inventory/models.py:963 -msgid "X" -msgstr "إكس" - -#: inventory/models.py:964 -msgid "Facebook" -msgstr "فيسبوك" - -#: inventory/models.py:965 -msgid "Motory" -msgstr "موتري" - -#: inventory/models.py:966 -msgid "Influencers" -msgstr "المؤثرون" - -#: inventory/models.py:967 -msgid "Youtube" -msgstr "يوتيوب" - -#: inventory/models.py:968 -msgid "Campaign" -msgstr "حملة" - -#: inventory/models.py:972 -msgid "Walk In" -msgstr "زيارة مباشرة" - -#: inventory/models.py:973 -msgid "Toll Free" -msgstr "رقم مجاني" - -#: inventory/models.py:974 -#: venv/lib/python3.11/site-packages/django_ledger/models/mixins.py:113 -msgid "Website" -msgstr "الموقع الإلكتروني" - -#: inventory/models.py:976 -msgid "Form" -msgstr "نموذج" - -#: inventory/models.py:982 templates/crm/leads/lead_detail.html:57 -#: templates/crm/leads/lead_list.html:125 -msgid "In Progress" -msgstr "قيد التنفيذ" - -#: inventory/models.py:983 templates/crm/leads/lead_detail.html:59 -#: templates/crm/leads/lead_list.html:127 -msgid "Qualified" -msgstr "مؤهل" - -#: inventory/models.py:984 templates/crm/leads/lead_list.html:129 -msgid "Contacted" -msgstr "تم الاتصال" - -#: inventory/models.py:985 -msgid "Converted" -msgstr "تم التحويل" - -#: inventory/models.py:986 inventory/models.py:1413 -#: templates/crm/leads/lead_detail.html:61 -#: templates/crm/leads/lead_list.html:131 -#: templates/sales/estimates/estimate_detail.html:90 -#: templates/sales/estimates/estimate_detail.html:177 -#: templates/sales/estimates/estimate_list.html:37 -#: templates/sales/invoices/invoice_list.html:34 test.txt:59 -#: venv/lib/python3.11/site-packages/django_ledger/models/bill.py:347 -#: venv/lib/python3.11/site-packages/django_ledger/models/estimate.py:228 -#: venv/lib/python3.11/site-packages/django_ledger/models/invoice.py:305 -#: venv/lib/python3.11/site-packages/django_ledger/models/items.py:1042 -#: venv/lib/python3.11/site-packages/django_ledger/models/purchase_order.py:196 -msgid "Canceled" -msgstr "ملغى" - -#: inventory/models.py:990 -msgid "Mr" -msgstr "السيد" - -#: inventory/models.py:991 -msgid "Mrs" -msgstr "السيدة" - -#: inventory/models.py:992 -msgid "Ms" -msgstr "الآنسة" - -#: inventory/models.py:993 -msgid "Miss" -msgstr "الآنسة" - -#: inventory/models.py:994 -msgid "Dr" -msgstr "الدكتور" - -#: inventory/models.py:995 -msgid "Prof" -msgstr "الأستاذ" - -#: inventory/models.py:996 -msgid "Prince" -msgstr "الأمير" - -#: inventory/models.py:997 -msgid "Princess" -msgstr "الأميرة" - -#: inventory/models.py:998 templates/pricing_page.html:121 -#: templates/pricing_page.html:124 templates/pricing_page.html:188 -msgid "Company" -msgstr "الشركة" - -#: inventory/models.py:999 -msgid "N/A" -msgstr "غير متوفر" - -#: inventory/models.py:1003 inventory/models.py:1406 -msgid "Call" -msgstr "مكالمة" - -#: inventory/models.py:1004 -msgid "SMS" -msgstr "رسالة نصية" - -#: inventory/models.py:1007 -msgid "Visit" -msgstr "زيارة" - -#: inventory/models.py:1008 templates/inventory/car_form.html:33 -msgid "Add Car" -msgstr "إضافة سيارة" - -#: inventory/models.py:1009 -msgid "Sale Car" -msgstr "بيع سيارة" - -#: inventory/models.py:1010 templates/inventory/reserve_car.html:6 -#: templates/inventory/reserve_car.html:9 -msgid "Reserve Car" -msgstr "حجز السيارة" - -#: inventory/models.py:1011 templates/inventory/transfer_car.html:4 -msgid "Transfer Car" -msgstr "نقل السيارة" - -#: inventory/models.py:1012 -msgid "Remove Car" -msgstr "إزالة السيارة" - -#: inventory/models.py:1013 -#: templates/crm/opportunities/opportunity_detail.html:18 -#: templates/sales/estimates/estimate_form.html:5 -#: templates/sales/estimates/estimate_form.html:32 -msgid "Create Quotation" -msgstr "إنشاء عرض" - -#: inventory/models.py:1014 -msgid "Cancel Quotation" -msgstr "إلغاء العرض" - -#: inventory/models.py:1015 -msgid "Create Order" -msgstr "إنشاء طلب" - -#: inventory/models.py:1016 -msgid "Cancel Order" -msgstr "إلغاء الطلب" - -#: inventory/models.py:1017 templates/sales/estimates/estimate_detail.html:108 -#: venv/lib/python3.11/site-packages/django_ledger/templates/django_ledger/invoice/invoice_create.html:24 -#: venv/lib/python3.11/site-packages/django_ledger/views/invoice.py:68 -msgid "Create Invoice" -msgstr "إنشاء فاتورة" - -#: inventory/models.py:1018 -msgid "Cancel Invoice" -msgstr "إلغاء الفاتورة" - -#: inventory/models.py:1022 -msgid "Prospect" -msgstr "العميل المحتمل" - -#: inventory/models.py:1023 -msgid "Proposal" -msgstr "عرض" - -#: inventory/models.py:1024 -msgid "Negotiation" -msgstr "مفاوضات" - -#: inventory/models.py:1025 -msgid "Closed Won" -msgstr "مغلقة - ناجحة" - -#: inventory/models.py:1026 -msgid "Closed Lost" -msgstr "مغلقة - خسارة" - -#: inventory/models.py:1030 -msgid "Low" -msgstr "منخفض" - -#: inventory/models.py:1031 -msgid "Medium" -msgstr "متوسط" - -#: inventory/models.py:1032 -msgid "High" -msgstr "مرتفع" - -#: inventory/models.py:1045 -#: venv/lib/python3.11/site-packages/django_ledger/templates/django_ledger/estimate/includes/estimate_table.html:11 -msgid "Title" -msgstr "العنوان" - -#: inventory/models.py:1053 -msgid "Male" -msgstr "ذكر" - -#: inventory/models.py:1053 -msgid "Female" -msgstr "أنثى" - -#: inventory/models.py:1055 -msgid "Gender" -msgstr "الجنس" - -#: inventory/models.py:1057 -msgid "Date of Birth" -msgstr "تاريخ الميلاد" - -#: inventory/models.py:1060 templates/customers/customer_list.html:46 -msgid "National ID" -msgstr "رقم الهوية الوطنية" - -#: inventory/models.py:1068 inventory/models.py:1166 +#: inventory/models.py:1008 inventory/models.py:1199 inventory/models.py:1323 +#: inventory/models.py:1877 templates/admin_management/user_management.html:35 +#: templates/admin_management/user_management.html:99 +#: templates/admin_management/user_management.html:163 +#: templates/admin_management/user_management.html:227 #: templates/customers/customer_list.html:56 -#: templates/dealers/dealer_detail.html:105 +#: templates/dealers/dealer_detail.html:111 #: templates/ledger/coa_accounts/account_detail.html:55 -#: templates/ledger/coa_accounts/account_list.html:52 +#: templates/ledger/coa_accounts/account_list.html:28 #: templates/plans/current.html:26 #: venv/lib/python3.11/site-packages/django_ledger/models/accounts.py:433 #: venv/lib/python3.11/site-packages/django_ledger/templates/django_ledger/account/tags/accounts_table.html:27 @@ -1334,13 +1124,283 @@ msgstr "رقم الهوية الوطنية" msgid "Active" msgstr "نشط" -#: inventory/models.py:1070 templates/administration/manage_service.html:76 +#: inventory/models.py:1073 inventory/models.py:1074 +#: templates/admin_management/user_management.html:206 +#: templates/crm/opportunities/opportunity_detail.html:233 +#: templates/dashboards/manager.html:16 templates/users/user_form.html:4 +#: templates/users/user_list.html:5 +msgid "Staff" +msgstr "الموظفون" + +#: inventory/models.py:1082 +msgid "Referrals" +msgstr "إحالات" + +#: inventory/models.py:1083 inventory/models.py:1130 +msgid "WhatsApp" +msgstr "واتساب" + +#: inventory/models.py:1085 +msgid "TikTok" +msgstr "تيك توك" + +#: inventory/models.py:1086 +msgid "Instagram" +msgstr "إنستغرام" + +#: inventory/models.py:1087 +msgid "X" +msgstr "إكس" + +#: inventory/models.py:1088 +msgid "Facebook" +msgstr "فيسبوك" + +#: inventory/models.py:1089 +msgid "Motory" +msgstr "موتري" + +#: inventory/models.py:1090 +msgid "Influencers" +msgstr "المؤثرون" + +#: inventory/models.py:1091 +msgid "Youtube" +msgstr "يوتيوب" + +#: inventory/models.py:1092 +msgid "Campaign" +msgstr "حملة" + +#: inventory/models.py:1096 +msgid "Walk In" +msgstr "زيارة مباشرة" + +#: inventory/models.py:1097 +msgid "Toll Free" +msgstr "رقم مجاني" + +#: inventory/models.py:1098 +#: venv/lib/python3.11/site-packages/django_ledger/models/mixins.py:113 +msgid "Website" +msgstr "الموقع الإلكتروني" + +#: inventory/models.py:1100 +msgid "Form" +msgstr "نموذج" + +#: inventory/models.py:1105 +msgid "Follow-up" +msgstr "متابعة" + +#: inventory/models.py:1106 inventory/models.py:1132 inventory/models.py:1155 +#: templates/crm/leads/lead_detail.html:58 +#: templates/crm/leads/lead_detail.html:136 +#: templates/crm/leads/lead_list.html:28 +#: templates/crm/leads/lead_tracking.html:104 +msgid "Negotiation" +msgstr "مفاوضات" + +#: inventory/models.py:1107 inventory/models.py:1134 +#: templates/crm/leads/lead_detail.html:59 +#: templates/crm/leads/lead_detail.html:138 +#: templates/crm/leads/lead_tracking.html:120 +msgid "Won" +msgstr "تم الفوز" + +msgid "Lost" +msgstr "تم الفقد" + +#: inventory/models.py:1109 inventory/models.py:1136 +#: templates/crm/leads/lead_detail.html:61 +#: templates/crm/leads/lead_detail.html:142 +#: templates/crm/leads/lead_list.html:29 +msgid "Closed" +msgstr "مغلقة" + +#: inventory/models.py:1113 +msgid "Mr" +msgstr "السيد" + +#: inventory/models.py:1114 +msgid "Mrs" +msgstr "السيدة" + +#: inventory/models.py:1115 +msgid "Ms" +msgstr "الآنسة" + +#: inventory/models.py:1116 +msgid "Miss" +msgstr "الآنسة" + +#: inventory/models.py:1117 +msgid "Dr" +msgstr "الدكتور" + +#: inventory/models.py:1118 +msgid "Prof" +msgstr "الأستاذ" + +#: inventory/models.py:1119 +msgid "Prince" +msgstr "الأمير" + +#: inventory/models.py:1120 +msgid "Princess" +msgstr "الأميرة" + +#: inventory/models.py:1121 templates/pricing_page.html:120 +#: templates/pricing_page.html:123 templates/pricing_page.html:187 +msgid "Company" +msgstr "الشركة" + +#: inventory/models.py:1122 +msgid "N/A" +msgstr "غير متوفر" + +#: inventory/models.py:1126 inventory/models.py:1635 +#: templates/components/activity_modal.html:17 +#: templates/crm/leads/lead_detail.html:70 +#: templates/crm/leads/lead_list.html:37 +msgid "Call" +msgstr "مكالمة" + +#: inventory/models.py:1127 +msgid "SMS" +msgstr "رسالة نصية" + +#: inventory/models.py:1129 inventory/models.py:1636 +#: templates/components/activity_modal.html:19 +#: templates/crm/leads/lead_detail.html:71 +#: templates/crm/leads/lead_list.html:38 +msgid "Meeting" +msgstr "اجتماع" + +#: inventory/models.py:1131 +msgid "Visit" +msgstr "زيارة" + +#: inventory/models.py:1133 templates/crm/leads/lead_detail.html:57 +#: templates/crm/leads/lead_detail.html:134 +#: templates/crm/leads/lead_list.html:26 templates/crm/leads/lead_list.html:41 +msgid "Follow Up" +msgstr "متابعة" + +#: inventory/models.py:1137 +msgid "Converted" +msgstr "تم التحويل" + +#: inventory/models.py:1139 templates/inventory/car_form.html:37 +#: templates/sales/estimates/estimate_form.html:20 +msgid "Add Car" +msgstr "إضافة سيارة" + +#: inventory/models.py:1140 +msgid "Sale Car" +msgstr "بيع سيارة" + +#: inventory/models.py:1141 templates/inventory/reserve_car.html:5 +#: templates/inventory/reserve_car.html:8 +msgid "Reserve Car" +msgstr "حجز السيارة" + +#: inventory/models.py:1142 templates/inventory/transfer_car.html:4 +msgid "Transfer Car" +msgstr "نقل السيارة" + +#: inventory/models.py:1143 +msgid "Remove Car" +msgstr "إزالة السيارة" + +#: inventory/models.py:1144 +#: templates/crm/opportunities/opportunity_detail.html:18 +#: templates/sales/estimates/estimate_form.html:5 +#: templates/sales/estimates/estimate_form.html:32 +msgid "Create Quotation" +msgstr "إنشاء عرض" + +#: inventory/models.py:1145 +msgid "Cancel Quotation" +msgstr "إلغاء العرض" + +#: inventory/models.py:1146 +msgid "Create Order" +msgstr "إنشاء طلب" + +#: inventory/models.py:1147 +msgid "Cancel Order" +msgstr "إلغاء الطلب" + +#: inventory/models.py:1148 templates/sales/estimates/estimate_detail.html:108 +#: venv/lib/python3.11/site-packages/django_ledger/templates/django_ledger/invoice/invoice_create.html:24 +#: venv/lib/python3.11/site-packages/django_ledger/views/invoice.py:68 +msgid "Create Invoice" +msgstr "إنشاء فاتورة" + +#: inventory/models.py:1149 +msgid "Cancel Invoice" +msgstr "إلغاء الفاتورة" + +#: inventory/models.py:1153 +msgid "Discovery" +msgstr "الاكتشاف" + +#: inventory/models.py:1154 +msgid "Proposal" +msgstr "عرض" + +#: inventory/models.py:1156 +msgid "Closed Won" +msgstr "مغلقة - ناجحة" + +#: inventory/models.py:1157 +msgid "Closed Lost" +msgstr "مغلقة - خسارة" + +#: inventory/models.py:1161 +msgid "Low" +msgstr "منخفض" + +#: inventory/models.py:1162 +msgid "Medium" +msgstr "متوسط" + +#: inventory/models.py:1163 +msgid "High" +msgstr "مرتفع" + +#: inventory/models.py:1176 inventory/models.py:1764 +#: venv/lib/python3.11/site-packages/django_ledger/templates/django_ledger/estimate/includes/estimate_table.html:11 +msgid "Title" +msgstr "العنوان" + +#: inventory/models.py:1184 +msgid "Male" +msgstr "ذكر" + +#: inventory/models.py:1184 +msgid "Female" +msgstr "أنثى" + +#: inventory/models.py:1186 +msgid "Gender" +msgstr "الجنس" + +#: inventory/models.py:1188 +msgid "Date of Birth" +msgstr "تاريخ الميلاد" + +#: inventory/models.py:1191 templates/customers/customer_list.html:46 +msgid "National ID" +msgstr "رقم الهوية الوطنية" + +#: inventory/models.py:1201 templates/administration/manage_service.html:76 #: venv/lib/python3.11/site-packages/django/db/models/fields/files.py:420 msgid "Image" msgstr "الصورة" -#: inventory/models.py:1076 inventory/models.py:1263 -#: templates/crm/opportunities/opportunity_form.html:22 +#: inventory/models.py:1219 inventory/models.py:1447 #: templates/sales/estimates/estimate_detail.html:154 #: templates/sales/estimates/estimate_list.html:15 #: templates/sales/estimates/sale_order_preview.html:167 @@ -1355,7 +1415,8 @@ msgstr "الصورة" msgid "Customer" msgstr "العميل" -#: inventory/models.py:1077 templates/customers/customer_form.html:4 +#: inventory/models.py:1220 templates/admin_management/user_management.html:14 +#: templates/customers/customer_form.html:4 #: templates/customers/customer_list.html:4 #: templates/customers/customer_list.html:5 #: templates/customers/customer_list.html:9 @@ -1363,203 +1424,258 @@ msgstr "العميل" msgid "Customers" msgstr "العملاء" -#: inventory/models.py:1171 inventory/models.py:1263 +#: inventory/models.py:1340 inventory/models.py:1447 msgid "Organization" msgstr "شركة" -#: inventory/models.py:1172 templates/header.html:151 -#: templates/organizations/organization_list.html:5 +#: inventory/models.py:1341 templates/admin_management/user_management.html:78 +#: templates/header.html:165 templates/organizations/organization_list.html:5 #: templates/organizations/organization_list.html:8 #: templates/organizations/organization_list.html:14 msgid "Organizations" msgstr "الشركات" -#: inventory/models.py:1239 +#: inventory/models.py:1423 #: templates/representatives/representative_detail.html:8 #: templates/representatives/representative_list.html:18 msgid "ID Number" msgstr "رقم الهوية" -#: inventory/models.py:1249 +#: inventory/models.py:1433 msgid "Representative" msgstr "ممثل شركة" -#: inventory/models.py:1250 +#: inventory/models.py:1434 #: templates/representatives/representative_list.html:3 #: templates/representatives/representative_list.html:6 msgid "Representatives" msgstr "ممثلي الشركات" -#: inventory/models.py:1263 +#: inventory/models.py:1447 msgid "Lead Type" msgstr "نوع العميل المتوقع" -#: inventory/models.py:1290 templates/crm/leads/lead_list.html:65 +#: inventory/models.py:1475 msgid "Source" msgstr "المصدر" -#: inventory/models.py:1293 templates/crm/leads/lead_list.html:71 +#: inventory/models.py:1478 msgid "Channel" msgstr "القناة" -#: inventory/models.py:1301 +#: inventory/models.py:1486 msgid "address" msgstr "العنوان" -#: inventory/models.py:1308 +#: inventory/models.py:1493 msgid "Assigned" msgstr "مُعين" -#: inventory/models.py:1314 +#: inventory/models.py:1499 msgid "Priority" msgstr "الأولوية" -#: inventory/models.py:1329 +#: inventory/models.py:1510 templates/crm/leads/lead_detail.html:66 +#: templates/crm/leads/lead_detail.html:218 +#: templates/crm/leads/lead_list.html:34 +msgid "Next Action" +msgstr "الإجراء التالي" + +msgid "Next Action Date" +msgstr "تاريخ الإجراء التالي" + +#: inventory/models.py:1521 templates/crm/leads/lead_detail.html:175 +msgid "Salary" +msgstr "الراتب" + +#: inventory/models.py:1529 msgid "Lead" msgstr "فرصة" -#: inventory/models.py:1330 templates/crm/leads/lead_list.html:3 +#: inventory/models.py:1530 templates/crm/leads/lead_list.html:3 #: templates/crm/leads/lead_list.html:7 templates/crm/leads/lead_send.html:5 +#: templates/crm/leads/lead_tracking.html:3 #: templates/dashboards/manager.html:21 test.txt:21 msgid "Leads" msgstr "الفرص" -#: inventory/models.py:1398 +#: inventory/models.py:1627 msgid "Product Demo" msgstr "عرض توضيحي للمنتج" -#: inventory/models.py:1399 +#: inventory/models.py:1628 msgid "Follow-Up Call" msgstr "مكالمة متابعة" -#: inventory/models.py:1400 +#: inventory/models.py:1629 msgid "Contract Discussion" msgstr "مناقشة العقد" -#: inventory/models.py:1401 +#: inventory/models.py:1630 msgid "Sales Meeting" msgstr "اجتماع مبيعات" -#: inventory/models.py:1402 +#: inventory/models.py:1631 msgid "Support Call" msgstr "مكالمة دعم" -#: inventory/models.py:1403 +#: inventory/models.py:1632 #: venv/lib/python3.11/site-packages/django_ledger/models/estimate.py:240 #: venv/lib/python3.11/site-packages/django_ledger/models/items.py:511 msgid "Other" msgstr "أخرى" -#: inventory/models.py:1407 -msgid "Meeting" -msgstr "اجتماع" - -#: inventory/models.py:1411 +#: inventory/models.py:1640 msgid "Scheduled" msgstr "مجدول" -#: inventory/models.py:1412 templates/sales/estimates/estimate_detail.html:88 +#: inventory/models.py:1641 inventory/models.py:1767 +#: templates/sales/estimates/estimate_detail.html:88 #: templates/sales/estimates/estimate_detail.html:175 #: templates/sales/estimates/estimate_list.html:39 #: venv/lib/python3.11/site-packages/django_ledger/models/estimate.py:226 msgid "Completed" msgstr "مكتمل" -#: inventory/models.py:1445 +#: inventory/models.py:1642 templates/crm/leads/lead_list.html:175 +#: templates/sales/estimates/estimate_detail.html:90 +#: templates/sales/estimates/estimate_detail.html:177 +#: templates/sales/estimates/estimate_list.html:37 +#: templates/sales/invoices/invoice_list.html:34 test.txt:59 +#: venv/lib/python3.11/site-packages/django_ledger/models/bill.py:347 +#: venv/lib/python3.11/site-packages/django_ledger/models/estimate.py:228 +#: venv/lib/python3.11/site-packages/django_ledger/models/invoice.py:305 +#: venv/lib/python3.11/site-packages/django_ledger/models/items.py:1042 +#: venv/lib/python3.11/site-packages/django_ledger/models/purchase_order.py:196 +msgid "Canceled" +msgstr "ملغى" + +#: inventory/models.py:1674 msgid "Old Status" msgstr "الحالة القديمة" -#: inventory/models.py:1448 +#: inventory/models.py:1677 msgid "New Status" msgstr "الحالة الجديدة" -#: inventory/models.py:1453 +#: inventory/models.py:1682 msgid "Changed At" msgstr "تم التغيير في" -#: inventory/models.py:1456 +#: inventory/models.py:1685 msgid "Lead Status History" msgstr "تاريخ حالة العميل المحتمل" -#: inventory/models.py:1457 +#: inventory/models.py:1686 msgid "Lead Status Histories" msgstr "تواريخ حالات العملاء المحتملين" -#: inventory/models.py:1465 +#: inventory/models.py:1694 msgid "Probability must be between 0 and 100." msgstr "يجب أن تكون الاحتمالية بين 0 و 100." -#: inventory/models.py:1496 -#: templates/crm/opportunities/opportunity_detail.html:264 -#: templates/crm/opportunities/opportunity_form.html:79 +#: inventory/models.py:1720 +#: ⁨templates/crm/opportunities/opportunity_list copy.html⁩:78 +#: templates/crm/opportunities/partials/opportunity_grid.html:60 +msgid "Expected Revenue" +msgstr "الإيرادات المتوقعة" + +#: inventory/models.py:1722 +#: templates/crm/opportunities/opportunity_detail.html:266 #: ⁨templates/crm/opportunities/opportunity_list copy.html⁩:100 -#: templates/crm/opportunities/opportunity_list.html:94 -#: venv/lib/python3.11/site-packages/django_ledger/models/closing_entry.py:71 +#: templates/crm/opportunities/partials/opportunity_grid.html:72 +#: venv/lib/python3.11/site-packages/django_ledger/models/closing_entry.py:75 msgid "Closing Date" msgstr "تاريخ الإغلاق" -#: inventory/models.py:1499 -msgid "Closed" -msgstr "مغلقة" +#: inventory/models.py:1727 +msgid "Unique slug for the opportunity." +msgstr "المُعرّف الفريد للفرصة (slug)." -#: inventory/models.py:1502 +#: inventory/models.py:1733 templates/crm/leads/lead_list.html:128 +#: templates/header.html:148 msgid "Opportunity" msgstr "فرصة" -#: inventory/models.py:1503 +#: inventory/models.py:1734 #: ⁨templates/crm/opportunities/opportunity_list copy.html⁩:8 #: templates/crm/opportunities/opportunity_list.html:8 msgid "Opportunities" msgstr "الفرص" -#: inventory/models.py:1513 inventory/models.py:1521 +#: inventory/models.py:1745 inventory/models.py:1753 #: templates/account/snippets/already_logged_in.html:8 -#: templates/crm/leads/lead_detail.html:226 -#: templates/customers/view_customer.html:91 +#: templates/crm/leads/lead_detail.html:314 +#: templates/crm/leads/lead_detail.html:592 +#: templates/customers/view_customer.html:95 msgid "Note" msgstr "ملاحظة" -#: inventory/models.py:1522 inventory/models.py:1558 -#: templates/crm/leads/lead_detail.html:137 -#: templates/crm/leads/lead_detail.html:213 -#: templates/crm/leads/lead_detail.html:387 -#: templates/customers/view_customer.html:188 +#: inventory/models.py:1754 inventory/models.py:1815 +#: templates/crm/leads/lead_detail.html:82 +#: templates/crm/leads/lead_detail.html:222 +#: templates/crm/leads/lead_detail.html:305 +#: templates/crm/leads/lead_list.html:51 +#: templates/customers/view_customer.html:192 #: templates/plans/invoices/layout.html:175 #: venv/lib/python3.11/site-packages/django_ledger/forms/bill.py:154 #: venv/lib/python3.11/site-packages/django_ledger/templates/django_ledger/includes/card_markdown.html:9 msgid "Notes" msgstr "ملاحظات" -#: inventory/models.py:1531 +#: inventory/models.py:1766 +#: templates/ledger/journal_entry/includes/card_invoice.html:52 +#: templates/ledger/journal_entry/includes/card_invoice.html:63 +#: templates/ledger/journal_entry/includes/card_invoice.html:77 +#: templates/plans/invoices/layout.html:161 +#: venv/lib/python3.11/site-packages/django_ledger/models/mixins.py:976 +#: venv/lib/python3.11/site-packages/django_ledger/templates/django_ledger/bills/includes/card_bill.html:72 +#: venv/lib/python3.11/site-packages/django_ledger/templates/django_ledger/bills/includes/card_bill.html:89 +#: venv/lib/python3.11/site-packages/django_ledger/templates/django_ledger/bills/includes/card_bill.html:110 +#: venv/lib/python3.11/site-packages/django_ledger/templates/django_ledger/invoice/includes/card_invoice.html:63 +#: venv/lib/python3.11/site-packages/django_ledger/templates/django_ledger/invoice/includes/card_invoice.html:80 +#: venv/lib/python3.11/site-packages/django_ledger/templates/django_ledger/invoice/includes/card_invoice.html:101 +msgid "Due Date" +msgstr "تاريخ الاستحقاق" + +#: inventory/models.py:1778 templates/crm/leads/lead_detail.html:572 +msgid "Task" +msgstr "مهمة" + +msgid "Tasks" +msgstr "مهام" + +#: inventory/models.py:1788 msgid "From Email" msgstr "من البريد الإلكتروني" -#: inventory/models.py:1532 +#: inventory/models.py:1789 msgid "To Email" msgstr "إلى البريد الإلكتروني" -#: inventory/models.py:1533 +#: inventory/models.py:1790 msgid "Subject" msgstr "الموضوع" -#: inventory/models.py:1534 inventory/models.py:1577 +#: inventory/models.py:1791 inventory/models.py:1834 msgid "Message" msgstr "رسالة" -#: inventory/models.py:1544 templates/crm/leads/lead_detail.html:138 -#: templates/crm/leads/lead_detail.html:265 +#: inventory/models.py:1801 templates/crm/leads/lead_detail.html:223 +#: templates/crm/leads/lead_detail.html:362 msgid "Emails" msgstr "رسائل البريد الإلكتروني" -#: inventory/models.py:1556 +#: inventory/models.py:1813 msgid "Activity Type" msgstr "نوع النشاط" -#: inventory/models.py:1566 templates/crm/leads/lead_detail.html:136 +#: inventory/models.py:1823 templates/components/activity_modal.html:7 +#: templates/crm/leads/lead_detail.html:221 #: templates/dealers/activity_log.html:11 #: templates/ledger/journal_entry/includes/card_journal_entry.html:32 -#: templates/ledger/journal_entry/journal_entry_list.html:64 -#: venv/lib/python3.11/site-packages/django_ledger/models/closing_entry.py:384 +#: templates/ledger/journal_entry/journal_entry_list.html:50 +#: venv/lib/python3.11/site-packages/django_ledger/models/closing_entry.py:396 #: venv/lib/python3.11/site-packages/django_ledger/models/journal_entry.py:388 #: venv/lib/python3.11/site-packages/django_ledger/templates/django_ledger/closing_entry/tags/closing_entry_txs_table.html:10 #: venv/lib/python3.11/site-packages/django_ledger/templates/django_ledger/journal_entry/includes/card_journal_entry.html:33 @@ -1567,376 +1683,375 @@ msgstr "نوع النشاط" msgid "Activity" msgstr "النشاط" -#: inventory/models.py:1567 templates/crm/leads/lead_detail.html:166 -#: templates/header.html:418 +#: inventory/models.py:1824 templates/crm/leads/lead_detail.html:257 +#: templates/header.html:434 msgid "Activities" msgstr "الأنشطة" -#: inventory/models.py:1578 +#: inventory/models.py:1835 msgid "Is Read" msgstr "تمت قراءته" -#: inventory/models.py:1582 +#: inventory/models.py:1839 msgid "Notification" msgstr "إشعار" -#: inventory/models.py:1583 templates/crm/notifications_history.html:6 -#: templates/notifications.html:13 +#: inventory/models.py:1840 templates/crm/notifications_history.html:6 +#: templates/notifications-copy.html:13 templates/notifications.html:23 msgid "Notifications" msgstr "الإشعارات" -#: inventory/models.py:1599 +#: inventory/models.py:1864 msgid "Vendor Model" msgstr "نموذج المورد" -#: inventory/models.py:1616 templates/vendors/vendor_form.html:4 -#: templates/vendors/vendors_list.html:4 templates/vendors/vendors_list.html:5 -#: templates/vendors/vendors_list.html:12 +#: inventory/models.py:1893 templates/admin_management/user_management.html:142 +#: templates/vendors/vendor_form.html:4 templates/vendors/vendors_list.html:5 +#: templates/vendors/vendors_list.html:7 templates/vendors/vendors_list.html:12 msgid "Vendors" msgstr "الموردين" -#: inventory/models.py:1682 inventory/models.py:1706 +#: inventory/models.py:1965 inventory/models.py:1989 msgid "amount" msgstr "المبلغ" -#: inventory/models.py:1685 +#: inventory/models.py:1968 msgid "method" msgstr "طريقة" -#: inventory/models.py:1688 +#: inventory/models.py:1971 msgid "reference number" msgstr "رقم المرجع" -#: inventory/models.py:1690 +#: inventory/models.py:1973 msgid "date" msgstr "التاريخ" -#: inventory/models.py:1694 +#: inventory/models.py:1977 msgid "payment" msgstr "الدفعة" -#: inventory/models.py:1695 templates/header.html:102 +#: inventory/models.py:1978 templates/header.html:102 msgid "payments" msgstr "المدفوعات" -#: inventory/models.py:1708 +#: inventory/models.py:1991 msgid "reason" msgstr "السبب" -#: inventory/models.py:1709 +#: inventory/models.py:1992 msgid "refund date" msgstr "تاريخ الاسترداد" -#: inventory/models.py:1712 +#: inventory/models.py:1995 msgid "refund" msgstr "استرداد" -#: inventory/models.py:1713 +#: inventory/models.py:1996 msgid "refunds" msgstr "استردادات" -#: inventory/models.py:1725 +#: inventory/models.py:2008 msgid "User Activity Log" msgstr "سجل نشاط المستخدم" -#: inventory/models.py:1726 +#: inventory/models.py:2009 msgid "User Activity Logs" msgstr "سجلات نشاط المستخدم" -#: inventory/models.py:1737 -#: venv/lib/python3.11/site-packages/django_ledger/models/entity.py:3160 +#: inventory/models.py:2020 +#: venv/lib/python3.11/site-packages/django_ledger/models/entity.py:3173 #: venv/lib/python3.11/site-packages/django_ledger/templates/django_ledger/estimate/includes/card_estimate.html:9 #: venv/lib/python3.11/site-packages/django_ledger/templates/django_ledger/estimate/includes/estimate_table.html:9 msgid "Estimate" msgstr "تقدير" -#: inventory/models.py:1748 inventory/tasks.py:39 +#: inventory/models.py:2031 inventory/tasks.py:38 #: templates/ledger/reports/dashboard.html:32 #: venv/lib/python3.11/site-packages/django_ledger/templates/django_ledger/includes/widget_bs.html:14 msgid "Cash" msgstr "نقداً" -#: inventory/models.py:1749 +#: inventory/models.py:2032 msgid "Finance" msgstr "تمويل" -#: inventory/models.py:1750 +#: inventory/models.py:2033 msgid "Lease" msgstr "تأجير" -#: inventory/models.py:1751 +#: inventory/models.py:2034 #: venv/lib/python3.11/site-packages/django_ledger/models/mixins.py:1139 msgid "Credit Card" msgstr "بطاقة ائتمان" -#: inventory/models.py:1752 +#: inventory/models.py:2035 msgid "Bank Transfer" msgstr "تحويل بنكي" -#: inventory/models.py:1796 templates/groups/group_form.html:4 +#: inventory/models.py:2079 templates/groups/group_form.html:4 #: templates/groups/group_list.html:5 templates/users/user_group_form.html:4 msgid "Group" msgstr "مجموعة" -#: inventory/models.py:1963 +#: inventory/models.py:2246 msgid "Payment History" msgstr "سجل الدفع" -#: inventory/models.py:1964 +#: inventory/models.py:2247 msgid "Payment Histories" msgstr "سجلات الدفع" -#: inventory/tables.py:59 templates/inventory/car_inventory.html:55 +#: inventory/tables.py:59 templates/inventory/car_inventory.html:70 msgid "Exterior Color" msgstr "اللون الخارجي" -#: inventory/tables.py:60 templates/inventory/car_inventory.html:56 +#: inventory/tables.py:60 templates/inventory/car_inventory.html:73 msgid "Interior Color" msgstr "اللون الداخلي" -#: inventory/tables.py:61 templates/inventory/car_inventory.html:59 -#: templates/inventory/car_list_view.html:114 +#: inventory/tables.py:61 templates/inventory/car_inventory.html:81 msgid "Age" msgstr "العمر" -#: inventory/tasks.py:51 templates/ledger/ledger/ledger_detail.html:38 +#: inventory/tasks.py:50 templates/ledger/ledger/ledger_detail.html:38 #: venv/lib/python3.11/site-packages/django_ledger/templates/django_ledger/invoice/invoice_detail.html:41 msgid "Accounts Receivable" msgstr "الحسابات المدينة" -#: inventory/tasks.py:76 +#: inventory/tasks.py:75 msgid "Prepaid Expenses" msgstr "المصروفات المدفوعة مقدمًا" -#: inventory/tasks.py:88 +#: inventory/tasks.py:87 msgid "Employee Advance" msgstr "سلفة الموظف" -#: inventory/tasks.py:99 +#: inventory/tasks.py:98 msgid "VAT Receivable" msgstr "ضريبة القيمة المضافة المستحقة" -#: inventory/tasks.py:109 +#: inventory/tasks.py:108 #: venv/lib/python3.11/site-packages/django_ledger/io/roles.py:452 #: venv/lib/python3.11/site-packages/django_ledger/io/roles.py:538 msgid "Buildings - Accum. Depreciation" msgstr "المباني - الإهلاك المتراكم" -#: inventory/tasks.py:121 +#: inventory/tasks.py:120 #: venv/lib/python3.11/site-packages/django_ledger/io/roles.py:459 #: venv/lib/python3.11/site-packages/django_ledger/io/roles.py:545 msgid "Intangible Assets" msgstr "الأصول غير الملموسة" -#: inventory/tasks.py:133 +#: inventory/tasks.py:132 msgid "Investments" msgstr "الاستثمارات" -#: inventory/tasks.py:170 +#: inventory/tasks.py:169 #: venv/lib/python3.11/site-packages/django_ledger/io/roles.py:451 #: venv/lib/python3.11/site-packages/django_ledger/io/roles.py:537 msgid "Buildings" msgstr "المباني" -#: inventory/tasks.py:184 +#: inventory/tasks.py:183 #: venv/lib/python3.11/site-packages/django_ledger/io/roles.py:466 #: venv/lib/python3.11/site-packages/django_ledger/io/roles.py:552 #: venv/lib/python3.11/site-packages/django_ledger/templates/django_ledger/bills/bill_detail.html:52 msgid "Accounts Payable" msgstr "الحسابات الدائنة" -#: inventory/tasks.py:196 templates/ledger/ledger/ledger_detail.html:46 +#: inventory/tasks.py:195 templates/ledger/ledger/ledger_detail.html:46 #: venv/lib/python3.11/site-packages/django_ledger/io/roles.py:472 #: venv/lib/python3.11/site-packages/django_ledger/io/roles.py:558 #: venv/lib/python3.11/site-packages/django_ledger/templates/django_ledger/invoice/invoice_detail.html:51 msgid "Deferred Revenue" msgstr "الإيرادات المؤجلة" -#: inventory/tasks.py:208 +#: inventory/tasks.py:207 #: venv/lib/python3.11/site-packages/django_ledger/io/roles.py:467 #: venv/lib/python3.11/site-packages/django_ledger/io/roles.py:553 msgid "Wages Payable" msgstr "الأجور المستحقة الدفع" -#: inventory/tasks.py:220 +#: inventory/tasks.py:219 msgid "Long-Term Notes Payable" msgstr "أوراق الدفع طويلة الأجل" -#: inventory/tasks.py:232 +#: inventory/tasks.py:231 msgid "VAT Payable" msgstr "ضريبة القيمة المضافة المستحقة الدفع" -#: inventory/tasks.py:242 +#: inventory/tasks.py:241 #: venv/lib/python3.11/site-packages/django_ledger/io/roles.py:469 #: venv/lib/python3.11/site-packages/django_ledger/io/roles.py:555 msgid "Taxes Payable" msgstr "الضرائب المستحقة الدفع" -#: inventory/tasks.py:252 +#: inventory/tasks.py:251 msgid "Social Insurance Payable" msgstr "التأمينات الاجتماعية المستحقة الدفع" -#: inventory/tasks.py:258 +#: inventory/tasks.py:257 msgid "End of Service Benefits" msgstr "مكافأة نهاية الخدمة" -#: inventory/tasks.py:265 +#: inventory/tasks.py:264 #: venv/lib/python3.11/site-packages/django_ledger/io/roles.py:478 #: venv/lib/python3.11/site-packages/django_ledger/io/roles.py:564 msgid "Mortgage Payable" msgstr "الرهن المستحق الدفع" -#: inventory/tasks.py:273 +#: inventory/tasks.py:272 msgid "Registered Capital" msgstr "رأس المال المسجل" -#: inventory/tasks.py:276 +#: inventory/tasks.py:275 msgid "Additional Paid-In Capital" msgstr "رأس المال المدفوع الإضافي" -#: inventory/tasks.py:279 +#: inventory/tasks.py:278 msgid "Opening Balances" msgstr "الأرصدة الافتتاحية" -#: inventory/tasks.py:284 +#: inventory/tasks.py:283 msgid "Statutory Reserve" msgstr "الاحتياطي النظامي" -#: inventory/tasks.py:287 +#: inventory/tasks.py:286 msgid "Foreign Currency Translation Reserve" msgstr "احتياطي تحويل العملات الأجنبية" -#: inventory/tasks.py:294 +#: inventory/tasks.py:293 msgid "Operating Profits and Losses" msgstr "الأرباح والخسائر التشغيلية" -#: inventory/tasks.py:305 +#: inventory/tasks.py:304 msgid "Retained Earnings (or Losses)" msgstr "الأرباح المحتجزة (أو الخسائر)" -#: inventory/tasks.py:315 +#: inventory/tasks.py:314 msgid "Sales Revenue" msgstr "إيرادات المبيعات" -#: inventory/tasks.py:327 +#: inventory/tasks.py:326 #: venv/lib/python3.11/site-packages/django_ledger/io/roles.py:492 #: venv/lib/python3.11/site-packages/django_ledger/io/roles.py:580 msgid "Interest Income" msgstr "دخل الفائدة" -#: inventory/tasks.py:339 +#: inventory/tasks.py:338 msgid "Unearned Income" msgstr "الدخل غير المكتسب" -#: inventory/tasks.py:345 +#: inventory/tasks.py:344 msgid "Sales/Service Revenue" msgstr "إيرادات المبيعات/الخدمات" -#: inventory/tasks.py:348 +#: inventory/tasks.py:347 msgid "Non-Operating Revenues" msgstr "الإيرادات غير التشغيلية" -#: inventory/tasks.py:356 inventory/tasks.py:537 +#: inventory/tasks.py:355 inventory/tasks.py:536 #: venv/lib/python3.11/site-packages/django_ledger/io/roles.py:497 #: venv/lib/python3.11/site-packages/django_ledger/io/roles.py:587 msgid "Cost of Goods Sold" msgstr "تكلفة البضائع المباعة" -#: inventory/tasks.py:369 +#: inventory/tasks.py:368 msgid "Accrued Expenses" msgstr "المصروفات المستحقة" -#: inventory/tasks.py:379 +#: inventory/tasks.py:378 msgid "Accrued Salaries" msgstr "الرواتب المستحقة" -#: inventory/tasks.py:389 +#: inventory/tasks.py:388 msgid "Rent Expense" msgstr "مصروف الإيجار" -#: inventory/tasks.py:401 +#: inventory/tasks.py:400 msgid "Salaries and Administrative Fees" msgstr "الرواتب والرسوم الإدارية" -#: inventory/tasks.py:411 +#: inventory/tasks.py:410 msgid "Medical Insurance" msgstr "التأمين الطبي" -#: inventory/tasks.py:421 +#: inventory/tasks.py:420 msgid "Marketing and Advertising Expenses" msgstr "مصروفات التسويق والإعلان" -#: inventory/tasks.py:431 +#: inventory/tasks.py:430 msgid "Commissions and Incentives" msgstr "العمولات والحوافز" -#: inventory/tasks.py:441 +#: inventory/tasks.py:440 msgid "Travel Tickets" msgstr "تذاكر السفر" -#: inventory/tasks.py:451 +#: inventory/tasks.py:450 msgid "Social Insurance" msgstr "التأمينات الاجتماعية" -#: inventory/tasks.py:461 +#: inventory/tasks.py:460 msgid "Government Fees" msgstr "الرسوم الحكومية" -#: inventory/tasks.py:471 +#: inventory/tasks.py:470 msgid "Fees and Subscriptions" msgstr "الرسوم والاشتراكات" -#: inventory/tasks.py:481 +#: inventory/tasks.py:480 msgid "Office Services Expenses" msgstr "مصروفات خدمات المكتب" -#: inventory/tasks.py:491 +#: inventory/tasks.py:490 msgid "Office Supplies and Printing" msgstr "اللوازم المكتبية والطباعة" -#: inventory/tasks.py:501 +#: inventory/tasks.py:500 msgid "Hospitality Expenses" msgstr "مصروفات الضيافة" -#: inventory/tasks.py:511 +#: inventory/tasks.py:510 msgid "Bank Commissions" msgstr "عمولات البنوك" -#: inventory/tasks.py:521 +#: inventory/tasks.py:520 #: templates/ledger/reports/tags/income_statement.html:223 #: venv/lib/python3.11/site-packages/django_ledger/templates/django_ledger/financial_statements/tags/income_statement.html:291 msgid "Other Expenses" msgstr "مصروفات أخرى" -#: inventory/tasks.py:531 +#: inventory/tasks.py:530 msgid "Transportation Expenses" msgstr "مصروفات النقل" -#: inventory/tasks.py:538 +#: inventory/tasks.py:537 msgid "Salaries and Wages" msgstr "الرواتب والأجور" -#: inventory/tasks.py:539 +#: inventory/tasks.py:538 msgid "Sales Commissions" msgstr "عمولات المبيعات" -#: inventory/tasks.py:540 +#: inventory/tasks.py:539 msgid "Shipping and Customs Clearance" msgstr "الشحن والتخليص الجمركي" -#: inventory/tasks.py:543 +#: inventory/tasks.py:542 msgid "Zakat" msgstr "الزكاة" -#: inventory/tasks.py:544 +#: inventory/tasks.py:543 msgid "Taxes" msgstr "الضرائب" -#: inventory/tasks.py:545 +#: inventory/tasks.py:544 msgid "Foreign Currency Translation" msgstr "تحويل العملات الأجنبية" -#: inventory/tasks.py:546 +#: inventory/tasks.py:545 msgid "Interest Expenses" msgstr "مصروفات الفائدة" @@ -1944,8 +2059,8 @@ msgstr "مصروفات الفائدة" msgid "success" msgstr "ناجحة" -#: inventory/utils.py:75 templates/inventory/car_form.html:383 -#: ⁨templates/inventory/car_form_qabl alfalsafa.html⁩:427 +#: inventory/utils.py:75 templates/inventory/car_form.html:386 +#: ⁨templates/inventory/car_form_qabl alfalsafa.html⁩:381 msgid "error" msgstr "خطأ" @@ -1962,93 +2077,89 @@ msgstr "تم حجز السيارة بنجاح." msgid "Enter a valid Saudi phone number (05XXXXXXXX or +9665XXXXXXXX)" msgstr "أدخل رقم جوال سعودي صحيح 05XXXXXXXX" -#: inventory/views.py:293 +#: inventory/views.py:270 msgid "Passwords do not match" msgstr "كلمات المرور غير متطابقة." -#: inventory/views.py:297 inventory/views.py:2596 +#: inventory/views.py:275 inventory/views.py:2641 msgid "User created successfully" msgstr "تم إنشاء المستخدم بنجاح." -#: inventory/views.py:595 +#: inventory/views.py:578 msgid "Car saved successfully" msgstr "تم حفظ السيارة بنجاح" -#: inventory/views.py:665 +#: inventory/views.py:650 msgid "VIN number exists" msgstr "رقم الهيكل موجود مسبقاً" -#: inventory/views.py:669 -msgid "Invalid VIN number provided" -msgstr "تم تقديم رقم تعريف مركبة (VIN) غير صالح" - -#: inventory/views.py:678 +#: inventory/views.py:664 msgid "VIN not found in all sources" msgstr "لم يتم العثور على رقم التعريف (VIN) في جميع المصادر" -#: inventory/views.py:691 +#: inventory/views.py:680 msgid "Manufacturer not found in the database" msgstr "لم يتم العثور على الشركة المصنعة في قاعدة البيانات" -#: inventory/views.py:731 +#: inventory/views.py:721 msgid "Server error occurred" msgstr "حدث خطأ في الخادم" -#: inventory/views.py:841 +#: inventory/views.py:819 msgid "No image provided" msgstr "لم يتم تقديم صورة" -#: inventory/views.py:853 +#: inventory/views.py:832 msgid "No QR/Barcode detected" msgstr "لم يتم اكتشاف رمز QR أو الباركود" -#: inventory/views.py:895 templates/dashboards/manager.html:48 -#: templates/dashboards/sales.html:112 templates/inventory/car_inventory.html:5 -#: templates/inventory/inventory_stats.html:5 +#: inventory/views.py:878 templates/dashboards/manager.html:48 +#: templates/dashboards/sales.html:112 templates/inventory/car_inventory.html:4 +#: templates/inventory/inventory_stats.html:4 msgid "inventory" msgstr "المخزون" -#: inventory/views.py:1224 +#: inventory/views.py:1214 msgid "Car finance details saved successfully" msgstr "تم حفظ تفاصيل المالية للسيارة بنجاح." -#: inventory/views.py:1270 +#: inventory/views.py:1261 msgid "Car finance details updated successfully" msgstr "تم تحديث تفاصيل المالية للسيارة بنجاح." -#: inventory/views.py:1322 +#: inventory/views.py:1314 msgid "Car updated successfully" msgstr "تم تحديث السيارة بنجاح" -#: inventory/views.py:1360 +#: inventory/views.py:1354 msgid "Car deleted successfully" msgstr "تم حذف السيارة بنجاح." -#: inventory/views.py:1396 +#: inventory/views.py:1391 msgid "Location saved successfully" msgstr "تم حفظ يوم الإجازة بنجاح." -#: inventory/views.py:1434 +#: inventory/views.py:1430 msgid "Location updated successfully" msgstr "تم تحديث البريد الإلكتروني بنجاح!" -#: inventory/views.py:1539 +#: inventory/views.py:1537 msgid "Car transfer canceled successfully" msgstr "تم إلغاء نقل السيارة بنجاح." -#: inventory/views.py:1556 +#: inventory/views.py:1554 msgid "Car transfer approved successfully" msgstr "تمت الموافقة على نقل السيارة بنجاح." -#: inventory/views.py:1581 +#: inventory/views.py:1579 msgid "Car transfer rejected successfully" msgstr "تم رفض نقل السيارة بنجاح." -#: inventory/views.py:1593 +#: inventory/views.py:1591 msgid "Car Transfer Completed successfully." msgstr "تم إكمال نقل السيارة بنجاح." -#: inventory/views.py:1662 +#: inventory/views.py:1661 msgid "Custom Card added successfully" msgstr "تم إضافة البطاقة الجمركية بنجاح." @@ -2076,310 +2187,350 @@ msgstr "إجراء غير صالح." msgid "Invalid request method" msgstr "طريقة الطلب غير صالحة" -#: inventory/views.py:1855 +#: inventory/views.py:1857 msgid "Dealer updated successfully" msgstr "تم تحديث المعرض بنجاح." -#: inventory/views.py:1888 templates/header.html:143 +#: inventory/views.py:1891 templates/header.html:157 msgid "customers" msgstr "العملاء" -#: inventory/views.py:2105 +msgid "Customer Account with this email is Deactivated,Please Contact Admin" +msgstr "تم تعطيل حساب العميل المرتبط بهذا البريد الإلكتروني، يرجى التواصل مع المسؤول" + +msgid "Customer with this email already exists" +msgstr "يوجد عميل مسجل مسبقًا بهذا البريد الإلكتروني" + msgid "Customer deactivated successfully" -msgstr "تم إلغاء تفعيل العميل بنجاح" +msgstr "تم تعطيل حساب العميل بنجاح" -#: inventory/views.py:2197 msgid "Vendor created successfully" -msgstr "تم إنشاء المورد بنجاح." +msgstr "تم إنشاء المورد بنجاح" -#: inventory/views.py:2235 +msgid "Vendor Account with this email is Deactivated,Please Contact Admin" +msgstr "تم تعطيل حساب المورد المرتبط بهذا البريد الإلكتروني، يرجى التواصل مع المسؤول" + +msgid "Vendor with this email already exists" +msgstr "يوجد مورد مسجل مسبقًا بهذا البريد الإلكتروني" + +#: inventory/views.py:2273 msgid "Vendor updated successfully" msgstr "تم تحديث المورد بنجاح" -#: inventory/views.py:2278 +#: inventory/views.py:2316 msgid "Vendor deleted successfully" msgstr "تم حذف المورد بنجاح." -#: inventory/views.py:2363 +#: inventory/views.py:2404 msgid "Group created successfully" msgstr "تم إنشاء المجموعة بنجاح." -#: inventory/views.py:2405 +#: inventory/views.py:2447 msgid "Group updated successfully" msgstr "تم تحديث المجموعة بنجاح." -#: inventory/views.py:2432 +#: inventory/views.py:2474 msgid "Group deleted successfully" msgstr "تم حذف المجموعة بنجاح." -#: inventory/views.py:2466 +#: inventory/views.py:2508 msgid "Permission added successfully" msgstr "تمت إضافة الإذن بنجاح." -#: inventory/views.py:2502 +#: inventory/views.py:2544 msgid "Group added successfully" msgstr "تمت إضافة المجموعة بنجاح." -#: inventory/views.py:2608 +#: inventory/views.py:2656 msgid "" "You have reached the maximum number of staff users allowed for your plan" msgstr "لقد وصلت إلى الحد الأقصى لعدد أعضاء الفريق المسموح به في خطتك." -#: inventory/views.py:2662 +#: inventory/views.py:2713 msgid "User updated successfully" msgstr "تم تحديث المستخدم بنجاح" -#: inventory/views.py:2714 +#: inventory/views.py:2764 msgid "User deleted successfully" msgstr "تم حذف المستخدم بنجاح." -#: inventory/views.py:2851 +#: inventory/views.py:2856 +msgid "Organization Account with this email is Deactivated,Please Contact Admin" +msgstr "تم تعطيل حساب المؤسسة المرتبط بهذا البريد الإلكتروني، يرجى التواصل مع المسؤول" + +msgid "Organization with this email already exists" +msgstr "يوجد مؤسسة مسجلة مسبقًا بهذا البريد الإلكتروني" + +#: inventory/views.py:2922 msgid "Organization Deactivated successfully" msgstr "تم إلغاء تفعيل المؤسسة بنجاح" -#: inventory/views.py:2933 +#: inventory/views.py:3007 msgid "Representative created successfully" msgstr "تم إنشاء الخدمة بنجاح." -#: inventory/views.py:2975 +#: inventory/views.py:3050 msgid "Representative updated successfully" msgstr "تم تحديث الخدمة بنجاح." -#: inventory/views.py:2999 +#: inventory/views.py:3075 msgid "Representative deleted successfully" msgstr "تم حذف الخدمة بنجاح!" -#: inventory/views.py:3070 +#: inventory/views.py:3148 msgid "Bank account created successfully" msgstr "تم إنشاء المنظمة بنجاح." -#: inventory/views.py:3141 +#: inventory/views.py:3221 msgid "Bank account updated successfully" msgstr "تم تحديث المجموعة بنجاح." -#: inventory/views.py:3177 +#: inventory/views.py:3257 msgid "Bank account deleted successfully" msgstr "تم حذف الملاحظة بنجاح." -#: inventory/views.py:3263 +#: inventory/views.py:3345 msgid "Account created successfully" msgstr "تم إنشاء المجموعة بنجاح." -#: inventory/views.py:3378 +#: inventory/views.py:3459 msgid "Account updated successfully" msgstr "تم تحديث المجموعة بنجاح." -#: inventory/views.py:3406 +#: inventory/views.py:3487 msgid "Account deleted successfully" msgstr "تم حذف الملاحظة بنجاح." -#: inventory/views.py:3519 inventory/views.py:5886 +#: inventory/views.py:3601 inventory/views.py:6148 msgid "Items and Quantities are required" msgstr "المنتجات والكميات مطلوبة" -#: inventory/views.py:3526 inventory/views.py:3531 inventory/views.py:5892 -#: inventory/views.py:5897 +#: inventory/views.py:3610 inventory/views.py:3618 inventory/views.py:6156 +#: inventory/views.py:6164 msgid "Quantity must be greater than zero" msgstr "يجب أن تكون مدة الفاصل الزمني أكبر من 0." -#: inventory/views.py:3540 inventory/views.py:3548 +#: inventory/views.py:3631 inventory/views.py:3644 msgid "Quantity must be less than or equal to the number of cars in stock" msgstr "يجب أن تكون الكمية أقل من أو تساوي عدد السيارات المتوفرة في المخزون" -#: inventory/views.py:3640 +#: inventory/views.py:3740 msgid "Quotation created successfully" msgstr "تم إنشاء عرض السعر بنجاح" -#: inventory/views.py:3891 +#: inventory/views.py:4017 msgid "Quotation is not ready for review" msgstr "العرض غير جاهز للمراجعة." -#: inventory/views.py:3897 +#: inventory/views.py:4023 msgid "Quotation is not ready for approval" msgstr "العرض غير جاهز للموافقة." -#: inventory/views.py:3900 +#: inventory/views.py:4026 msgid "Quotation approved successfully" msgstr "تمت الموافقة على العرض بنجاح." -#: inventory/views.py:3903 +#: inventory/views.py:4029 msgid "Quotation is not ready for rejection" msgstr "العرض غير جاهز للرفض." -#: inventory/views.py:3906 inventory/views.py:3924 +#: inventory/views.py:4032 inventory/views.py:4050 msgid "Quotation canceled successfully" msgstr "تم إلغاء الحجز بنجاح." -#: inventory/views.py:3909 +#: inventory/views.py:4035 msgid "Quotation is not ready for completion" msgstr "العرض غير جاهز للإكمال." -#: inventory/views.py:3913 +#: inventory/views.py:4039 msgid "Quotation is not ready for cancellation" msgstr "العرض غير جاهز للإلغاء." -#: inventory/views.py:3926 +#: inventory/views.py:4052 msgid "Quotation marked as " msgstr "تم وضع علامة على عرض السعر كـ" -#: inventory/views.py:4340 +#: inventory/views.py:4472 msgid "fully paid" msgstr "مدفوع بالكامل" -#: inventory/views.py:4343 +#: inventory/views.py:4475 msgid "Amount exceeds due amount" msgstr "المبلغ يتجاوز المبلغ المستحق" -#: inventory/views.py:4351 inventory/views.py:4461 +#: inventory/views.py:4483 inventory/views.py:4601 msgid "Payment created successfully" msgstr "تم إنشاء الدفعة بنجاح" -#: inventory/views.py:4465 +#: inventory/views.py:4605 msgid "Invoice is not fully paid, Payment cannot be marked as paid" msgstr "لم يتم دفع الفاتورة بالكامل، لا يمكن وضع علامة مدفوعة على الدفعة" -#: inventory/views.py:4663 +#: inventory/views.py:4810 msgid "Lead created successfully" msgstr "تم إنشاء العميل المتوقع بنجاح" -#: inventory/views.py:4728 +#: inventory/views.py:4965 msgid "Lead deleted successfully" msgstr "تم حذف العميل المتوقع بنجاح" -#: inventory/views.py:4757 inventory/views.py:4786 +#: inventory/views.py:4994 inventory/views.py:5025 inventory/views.py:8056 msgid "Note added successfully" msgstr "تمت إضافة الملاحظة بنجاح" -#: inventory/views.py:4783 +#: inventory/views.py:5020 msgid "Notes field is required" msgstr "حقل الملاحظات مطلوب" -#: inventory/views.py:4819 -msgid "Note updated successfully" -msgstr "تم تحديث الملاحظة بنجاح" - -#: inventory/views.py:4845 +#: inventory/views.py:5048 msgid "Note deleted successfully." msgstr "تم حذف الملاحظة بنجاح." -#: inventory/views.py:4871 +#: inventory/views.py:5074 msgid "Lead is already converted to customer" msgstr "تم تحويل العميل المتوقع بالفعل إلى عميل" -#: inventory/views.py:4875 +#: inventory/views.py:5085 msgid "Lead converted to customer successfully" msgstr "تم تحويل العميل المتوقع إلى عميل بنجاح" -#: inventory/views.py:4900 +#: inventory/views.py:5111 msgid "You do not have permission to schedule lead" msgstr "ليست لديك صلاحية جدولة هذا العميل المتوقع" -#: inventory/views.py:4941 +#: inventory/views.py:5155 msgid "Lead scheduled and appointment created successfully" msgstr "تمت جدولة العميل المتوقع وإنشاء الموعد بنجاح" -#: inventory/views.py:4971 +#: inventory/views.py:5186 msgid "Lead transferred successfully" msgstr "تم نقل العميل المتوقع بنجاح" -#: inventory/views.py:5004 +#: inventory/views.py:5233 msgid "Email Draft successfully" msgstr "تم إنشاء مسودة البريد الإلكتروني بنجاح" -#: inventory/views.py:5037 inventory/views.py:6098 +#: inventory/views.py:5268 inventory/views.py:6368 msgid "Email sent successfully" msgstr "تم إرسال البريد الإلكتروني بنجاح!" -#: inventory/views.py:5266 +#: inventory/views.py:5517 msgid "Opportunity deleted successfully" msgstr "تم حذف الفرصة بنجاح." -#: inventory/views.py:5304 +#: inventory/views.py:5555 msgid "Opportunity status updated successfully" msgstr "تم تحديث حالة الفرصة بنجاح" -#: inventory/views.py:5361 -msgid "Notification marked as read" -msgstr "تم تعليم الإشعار كمقروء" - -#: inventory/views.py:5418 +#: inventory/views.py:5671 msgid "Service created successfully" msgstr "تم إنشاء الخدمة بنجاح" -#: inventory/views.py:5462 +#: inventory/views.py:5716 msgid "Service updated successfully" msgstr "تم تحديث الخدمة بنجاح" -#: inventory/views.py:5718 inventory/views.py:5770 +#: inventory/views.py:5979 inventory/views.py:6032 msgid "Bill updated successfully" msgstr "تم تحديث الفاتورة بنجاح." -#: inventory/views.py:5811 +#: inventory/views.py:6073 msgid "Bill is already approved" msgstr "تمت الموافقة على الفاتورة مسبقًا." -#: inventory/views.py:5815 +#: inventory/views.py:6077 msgid "Bill marked as approved successfully" msgstr "تم تحديد الفاتورة كموافقة بنجاح." -#: inventory/views.py:5842 +#: inventory/views.py:6104 msgid "Bill is already paid" msgstr "تم دفع الفاتورة مسبقًا." -#: inventory/views.py:5851 +#: inventory/views.py:6113 msgid "Bill marked as paid successfully" msgstr "تم تحديد الفاتورة كمدفوعة بنجاح." -#: inventory/views.py:5853 +#: inventory/views.py:6115 msgid "Amount paid is not equal to amount due" msgstr "المبلغ المدفوع لا يساوي المبلغ المستحق." -#: inventory/views.py:5958 +#: inventory/views.py:6226 msgid "Bill created successfully" msgstr "تم تحديث الفاتورة بنجاح." -#: inventory/views.py:6059 +#: inventory/views.py:6329 msgid "Quotation has no items" msgstr "عرض السعر لا يحتوي على أي عناصر" -#: inventory/views.py:6607 +#: inventory/views.py:6885 #: venv/lib/python3.11/site-packages/django_ledger/templates/django_ledger/unit/unit_detail.html:23 #: venv/lib/python3.11/site-packages/django_ledger/views/entity.py:210 msgid "Dashboard" msgstr "لوحة القيادة" -#: inventory/views.py:6762 inventory/views.py:6796 inventory/views.py:6856 +#: inventory/views.py:7040 inventory/views.py:7073 inventory/views.py:7132 msgid "Unauthorized" msgstr "غير مصرح" -#: inventory/views.py:6982 +#: inventory/views.py:7258 msgid "Settings updated" msgstr "تم تحديث الإعدادات" -#: inventory/views.py:7308 +#: inventory/views.py:7598 msgid "Journal Entry created" msgstr "تم إنشاء قيد اليومية" -#: inventory/views.py:7349 +#: inventory/views.py:7639 msgid "Journal Entry cannot be deleted" msgstr "لا يمكن حذف قيد اليومية" -#: inventory/views.py:7422 +#: inventory/views.py:7713 msgid "Ledger is already locked" msgstr "دفتر الأستاذ مقفل بالفعل" -#: inventory/views.py:7449 +#: inventory/views.py:7740 msgid "Ledger is already Unlocked" msgstr "دفتر الأستاذ غير مقفل بالفعل" -#: inventory/views.py:7478 +#: inventory/views.py:7769 msgid "Ledger is already posted" msgstr "دفتر الأستاذ تم ترحيله بالفعل" -#: inventory/views.py:7508 +#: inventory/views.py:7799 msgid "Ledger is already Unposted" msgstr "دفتر الأستاذ لم يتم ترحيله بعد" +#: inventory/views.py:7991 +msgid "Activity added successfully" +msgstr "تمت إضافة النشاط بنجاح" + +msgid "Activity form is not valid" +msgstr "نموذج النشاط غير صالح" + +msgid "Task added successfully" +msgstr "تمت إضافة المهمة بنجاح" + +msgid "Task form is not valid" +msgstr "نموذج المهمة غير صالح" + +msgid "Task updated successfully" +msgstr "تم تحديث المهمة بنجاح" + +msgid "Note form is not valid" +msgstr "نموذج الملاحظة غير صالح" + +msgid "Note updated successfully" +msgstr "تم تحديث الملاحظة بنجاح" + +msgid "Account activated successfully" +msgstr "تم تفعيل الحساب بنجاح" + +msgid "Account Deleted successfully" +msgstr "تم حذف الحساب بنجاح" + +msgid "You cannot delete this account,it is related to another account" +msgstr "لا يمكنك حذف هذا الحساب، لأنه مرتبط بحساب آخر" + #: templates/account/account_inactive.html:5 #: templates/account/account_inactive.html:9 msgid "Account Inactive" @@ -2412,11 +2563,11 @@ msgstr "" #: templates/account/confirm_email_verification_code.html:27 #: templates/account/email_confirm.html:35 #: templates/account/reauthenticate.html:18 -#: templates/inventory/transfer_details.html:27 +#: templates/inventory/transfer_details.html:34 #: templates/ledger/bills/bill_detail.html:11 #: templates/ledger/bills/bill_detail.html:36 #: templates/ledger/journal_entry/journal_entry_list.html:13 -#: templates/plans/billing_info_delete.html:13 templates/pricing_page.html:202 +#: templates/plans/billing_info_delete.html:13 templates/pricing_page.html:201 #: templates/sales/estimates/estimate_detail.html:52 #: templates/sales/invoices/invoice_detail.html:19 #: templates/sales/invoices/invoice_detail.html:43 @@ -2427,40 +2578,41 @@ msgstr "تأكيد" #: templates/account/confirm_email_verification_code.html:31 #: templates/account/confirm_email_verification_code.html:35 #: templates/account/confirm_login_code..html:38 -#: templates/crm/leads/lead_form.html:16 +#: templates/crm/leads/lead_form.html:32 #: templates/crm/leads/schedule_lead.html:18 -#: templates/crm/opportunities/opportunity_detail.html:58 -#: templates/crm/opportunities/opportunity_form.html:89 +#: templates/crm/opportunities/opportunity_detail.html:59 #: templates/customers/customer_form.html:33 -#: templates/dealers/dealer_form.html:22 templates/groups/group_form.html:35 +#: templates/dealers/dealer_form.html:21 templates/groups/group_form.html:35 #: templates/groups/group_permission_form.html:35 -#: templates/inventory/add_colors.html:57 -#: templates/inventory/add_custom_card.html:12 -#: templates/inventory/car_confirm_delete.html:14 -#: templates/inventory/car_detail.html:330 -#: templates/inventory/car_finance_form.html:41 -#: templates/inventory/car_registration_form.html:13 -#: templates/inventory/color_palette.html:107 -#: templates/inventory/reserve_car.html:30 -#: templates/inventory/transfer_preview.html:181 -#: templates/inventory/transfer_preview.html:200 -#: templates/ledger/bank_accounts/bank_account_form.html:33 -#: templates/ledger/bills/bill_form.html:42 +#: templates/inventory/add_colors.html:74 +#: templates/inventory/add_custom_card.html:13 +#: templates/inventory/car_confirm_delete.html:11 +#: templates/inventory/car_detail.html:359 +#: templates/inventory/car_finance_form.html:46 +#: templates/inventory/car_registration_form.html:14 +#: templates/inventory/color_palette.html:108 +#: templates/inventory/reserve_car.html:23 +#: templates/inventory/transfer_preview.html:222 +#: templates/inventory/transfer_preview.html:246 +#: templates/items/expenses/expense_create.html:22 +#: templates/items/service/service_create.html:24 +#: templates/ledger/bank_accounts/bank_account_form.html:34 +#: templates/ledger/bills/bill_form.html:43 #: templates/ledger/bills/bill_update_form.html:18 -#: templates/ledger/coa_accounts/account_form.html:32 +#: templates/ledger/coa_accounts/account_form.html:35 #: templates/ledger/journal_entry/includes/card_invoice.html:134 #: templates/ledger/journal_entry/journal_entry_form.html:17 -#: templates/ledger/ledger/ledger_form.html:17 +#: templates/ledger/ledger/ledger_form.html:23 #: templates/modal/event_details_modal.html:24 -#: templates/organizations/organization_form.html:20 +#: templates/organizations/organization_form.html:16 #: templates/representatives/representative_form.html:12 #: templates/sales/estimates/estimate_detail.html:120 -#: templates/sales/estimates/estimate_form.html:66 +#: templates/sales/estimates/estimate_form.html:77 #: templates/sales/estimates/estimate_send.html:26 #: templates/sales/journals/journal_form.html:19 #: templates/two_factor/_wizard_actions.html:5 -#: templates/users/user_form.html:41 templates/users/user_group_form.html:28 -#: templates/vendors/vendor_form.html:38 +#: templates/users/user_form.html:41 templates/users/user_group_form.html:24 +#: templates/vendors/vendor_form.html:42 #: venv/lib/python3.11/site-packages/appointment/templates/modal/event_details_modal.html:22 #: venv/lib/python3.11/site-packages/django_ledger/templates/django_ledger/bills/bill_create.html:37 #: venv/lib/python3.11/site-packages/django_ledger/templates/django_ledger/bills/includes/card_bill.html:205 @@ -2476,7 +2628,7 @@ msgstr "إلغاء" #: templates/account/confirm_login_code..html:35 templates/account/login.html:6 #: templates/account/login.html:22 templates/account/login.html:46 #: templates/account/request_login_code.html:5 templates/account/signup.html:80 -#: templates/header.html:447 templates/welcome-temp.html:77 +#: templates/header.html:468 templates/welcome-temp.html:77 msgid "Sign In" msgstr "تسجيل الدخول" @@ -2506,6 +2658,7 @@ msgstr "تسجيل الدخول" #: templates/account/verification_sent.html:14 #: templates/account/verified_email_required.html:13 #: templates/account/verified_email_required.html:14 +#: templates/haikalbot/chatbot.html:58 templates/haikalbot/chatbot.html:59 #: templates/otp/verify_otp.html:11 templates/otp/verify_otp.html:12 msgid "home" msgstr "الرئيسية" @@ -2544,7 +2697,7 @@ msgstr "إعادة إرسال التحقق" #: templates/account/email.html:51 templates/administration/staff_list.html:48 #: templates/sales/estimates/estimate_form.html:53 -#: templates/sales/estimates/estimate_form.html:103 +#: templates/sales/estimates/estimate_form.html:117 #: templates/sales/sales_list.html:208 #: venv/lib/python3.11/site-packages/appointment/templates/administration/staff_list.html:52 msgid "Remove" @@ -2833,7 +2986,7 @@ msgstr "إذا لم تقم بإنشاء حساب بعد، يرجى التسجي #: templates/account/login.html:56 templates/account/signup-wizard.html:18 #: templates/account/signup.html:5 templates/account/signup.html:79 -#: templates/header.html:450 templates/welcome-temp.html:78 +#: templates/header.html:471 templates/welcome-temp.html:78 #: templates/welcome_header.html:36 msgid "Sign Up" msgstr "إنشاء حساب" @@ -2847,7 +3000,7 @@ msgid "Mail me a sign-in code" msgstr "أرسل لي رمز تسجيل الدخول عبر البريد الإلكتروني" #: templates/account/logout.html:3 templates/account/logout.html:11 -#: templates/account/logout.html:20 templates/header.html:440 +#: templates/account/logout.html:20 templates/header.html:461 msgid "Sign Out" msgstr "تسجيل الخروج" @@ -2932,7 +3085,7 @@ msgstr "لم تستلم الرمز؟" #: templates/account/password_reset_from_key.html:40 #: templates/account/password_reset_from_key_done.html:5 #: templates/account/password_reset_from_key_done.html:20 -#: templates/dealers/dealer_detail.html:10 +#: templates/dealers/dealer_detail.html:16 msgid "Change Password" msgstr "تغيير كلمة المرور" @@ -3013,7 +3166,7 @@ msgstr "الوصول" #: templates/account/signup-wizard.html:29 #: templates/items/service/service_list.html:23 templates/plans/current.html:17 #: venv/lib/python3.11/site-packages/django_ledger/models/accounts.py:443 -#: venv/lib/python3.11/site-packages/django_ledger/models/transactions.py:439 +#: venv/lib/python3.11/site-packages/django_ledger/models/transactions.py:463 #: venv/lib/python3.11/site-packages/django_ledger/templates/django_ledger/bank_account/bank_account_update.html:13 #: venv/lib/python3.11/site-packages/django_ledger/templates/django_ledger/closing_entry/tags/closing_entry_txs_table.html:8 #: venv/lib/python3.11/site-packages/django_ledger/templates/django_ledger/journal_entry/tags/je_txs_table.html:9 @@ -3033,23 +3186,27 @@ msgstr "إضافي" msgid "Done" msgstr "تم" -#: templates/account/signup-wizard.html:63 +#: templates/account/signup-wizard.html:44 +msgid "Read Terms of Service and Privacy Policy" +msgstr "اقرأ شروط الخدمة وسياسة الخصوصية" + +#: templates/account/signup-wizard.html:64 msgid "You are all set!" msgstr "كل شيء جاهز!" -#: templates/account/signup-wizard.html:64 +#: templates/account/signup-wizard.html:65 msgid "Now you can access your account" msgstr "الآن يمكنك الوصول إلى حسابك" -#: templates/account/signup-wizard.html:64 +#: templates/account/signup-wizard.html:65 msgid "anytime" msgstr "في أي وقت" -#: templates/account/signup-wizard.html:64 +#: templates/account/signup-wizard.html:65 msgid "anywhere" msgstr "في أي مكان" -#: templates/account/signup-wizard.html:64 +#: templates/account/signup-wizard.html:65 #: templates/administration/email_change_verification_code.html:25 #: templates/administration/manage_day_off.html:69 #: templates/appointment/enter_verification_code.html:24 @@ -3061,37 +3218,37 @@ msgstr "في أي مكان" msgid "Submit" msgstr "إرسال" -#: templates/account/signup-wizard.html:73 templates/pricing_page.html:200 +#: templates/account/signup-wizard.html:74 templates/pricing_page.html:199 #: venv/lib/python3.11/site-packages/alabaster/relations.html:9 msgid "Previous" msgstr "السابق" -#: templates/account/signup-wizard.html:75 -#: templates/appointment/appointments.html:86 templates/pricing_page.html:201 +#: templates/account/signup-wizard.html:76 +#: templates/appointment/appointments.html:86 templates/pricing_page.html:200 #: templates/two_factor/_wizard_actions.html:14 #: venv/lib/python3.11/site-packages/alabaster/relations.html:13 #: venv/lib/python3.11/site-packages/appointment/templates/appointment/appointments.html:85 msgid "Next" msgstr "التالي" -#: templates/account/signup-wizard.html:107 -#: templates/account/signup-wizard.html:112 +#: templates/account/signup-wizard.html:108 +#: templates/account/signup-wizard.html:113 msgid "Please enter a valid phone number" msgstr "يرجى إدخال رقم هاتف صالح" -#: templates/account/signup-wizard.html:143 +#: templates/account/signup-wizard.html:144 msgid "Password does not match" msgstr "كلمة المرور غير متطابقة" -#: templates/account/signup-wizard.html:251 -#: templates/inventory/car_form.html:614 -#: ⁨templates/inventory/car_form_qabl alfalsafa.html⁩:654 +#: templates/account/signup-wizard.html:252 +#: templates/inventory/car_form.html:617 +#: ⁨templates/inventory/car_form_qabl alfalsafa.html⁩:608 msgid "Please Wait" msgstr "الرجاء الإنتظار" -#: templates/account/signup-wizard.html:252 -#: templates/inventory/car_form.html:615 -#: ⁨templates/inventory/car_form_qabl alfalsafa.html⁩:655 +#: templates/account/signup-wizard.html:253 +#: templates/inventory/car_form.html:618 +#: ⁨templates/inventory/car_form_qabl alfalsafa.html⁩:609 msgid "Loading" msgstr "تحميل" @@ -3151,24 +3308,24 @@ msgstr "" #: templates/account/verified_email_required.html:23 msgid "" "This part of the site requires us to verify that\n" -"you are who you claim to be. For this purpose, we require that you\n" -"verify ownership of your email address. " +" you are who you claim to be. For this purpose, we " +"require that you\n" +" verify ownership of your email address. " msgstr "" -"يتطلب هذا الجزء من الموقع التحقق من أنك الشخص الذي تدّعي أنه أنت. لهذا السبب، " -"نطلب منك تأكيد ملكية عنوان بريدك الإلكتروني." +"يتطلب هذا الجزء من الموقع التحقق من أنك الشخص الذي تدّعي أنك هو. ولهذا الغرض، نطلب منك التحقق من ملكيتك لعنوان بريدك الإلكتروني." + #: templates/account/verified_email_required.html:28 msgid "" "We have sent an email to you for\n" -"verification. Please click on the link inside that email. If you do not see " -"the verification email in your main inbox, check your spam folder. " -"Otherwise\n" -"contact us if you do not receive it within a few minutes." +" verification. Please click on the link inside that " +"email. If you do not see the verification email in your main inbox, check " +"your spam folder. Otherwise\n" +" contact us if you do not receive it within a few " +"minutes." msgstr "" -"لقد أرسلنا لك بريدًا إلكترونيًا للتحقق. يرجى النقر على الرابط الموجود داخل " -"البريد الإلكتروني. إذا لم تجد البريد الإلكتروني للتحقق في صندوق الوارد " -"الرئيسي، تحقق من مجلد البريد العشوائي. بخلاف ذلك، اتصل بنا إذا لم تستلمه " -"خلال بضع دقائق." +"لقد أرسلنا إليك رسالة بريد إلكتروني للتحقق. يرجى النقر على الرابط الموجود داخل الرسالة. إذا لم تجد رسالة التحقق في صندوق الوارد الرئيسي، يرجى التحقق من مجلد الرسائل غير المرغوب فيها. وإذا لم تستلمها خلال بضع دقائق، يرجى التواصل معنا." + #: templates/account/verified_email_required.html:33 #, python-format @@ -3179,16 +3336,93 @@ msgstr "" "ملاحظة: لا يزال بإمكانك تغيير " "عنوان بريدك الإلكتروني." +#: templates/admin_management/user_management.html:5 +#: templates/admin_management/user_management.html:11 +msgid "User Management" +msgstr "إدارة المستخدمين" + +#: templates/admin_management/user_management.html:23 +msgid "Created date" +msgstr "تاريخ الإنشاء" + +#: templates/admin_management/user_management.html:24 +#: templates/admin_management/user_management.html:88 +#: templates/admin_management/user_management.html:152 +#: templates/admin_management/user_management.html:216 +#: templates/inventory/car_detail.html:336 +#: templates/ledger/coa_accounts/account_detail.html:71 +#: templates/representatives/representative_list.html:20 +#: templates/sales/estimates/estimate_list.html:19 +#: templates/sales/invoices/invoice_list.html:20 +#: templates/sales/journals/journal_list.html:20 +#: templates/sales/payments/payment_list.html:24 +#: venv/lib/python3.11/site-packages/django_ledger/templates/django_ledger/account/tags/account_txs_table.html:29 +#: venv/lib/python3.11/site-packages/django_ledger/templates/django_ledger/account/tags/accounts_table.html:30 +#: venv/lib/python3.11/site-packages/django_ledger/templates/django_ledger/account/tags/accounts_table.html:89 +#: venv/lib/python3.11/site-packages/django_ledger/templates/django_ledger/bank_account/tags/bank_accounts_table.html:39 +#: venv/lib/python3.11/site-packages/django_ledger/templates/django_ledger/bills/tags/bill_table.html:16 +#: venv/lib/python3.11/site-packages/django_ledger/templates/django_ledger/closing_entry/tags/closing_entry_table.html:13 +#: venv/lib/python3.11/site-packages/django_ledger/templates/django_ledger/closing_entry/tags/closing_entry_table.html:36 +#: venv/lib/python3.11/site-packages/django_ledger/templates/django_ledger/customer/tags/customer_table.html:13 +#: venv/lib/python3.11/site-packages/django_ledger/templates/django_ledger/data_import/tags/data_import_job_list_table.html:38 +#: venv/lib/python3.11/site-packages/django_ledger/templates/django_ledger/estimate/includes/estimate_table.html:16 +#: venv/lib/python3.11/site-packages/django_ledger/templates/django_ledger/estimate/includes/estimate_table.html:38 +#: venv/lib/python3.11/site-packages/django_ledger/templates/django_ledger/expense/tags/expense_item_table.html:13 +#: venv/lib/python3.11/site-packages/django_ledger/templates/django_ledger/financial_statements/tags/balance_sheet_statement.html:27 +#: venv/lib/python3.11/site-packages/django_ledger/templates/django_ledger/financial_statements/tags/balance_sheet_statement.html:57 +#: venv/lib/python3.11/site-packages/django_ledger/templates/django_ledger/financial_statements/tags/income_statement.html:15 +#: venv/lib/python3.11/site-packages/django_ledger/templates/django_ledger/financial_statements/tags/income_statement.html:51 +#: venv/lib/python3.11/site-packages/django_ledger/templates/django_ledger/financial_statements/tags/income_statement.html:112 +#: venv/lib/python3.11/site-packages/django_ledger/templates/django_ledger/financial_statements/tags/income_statement.html:186 +#: venv/lib/python3.11/site-packages/django_ledger/templates/django_ledger/financial_statements/tags/income_statement.html:260 +#: venv/lib/python3.11/site-packages/django_ledger/templates/django_ledger/financial_statements/tags/income_statement.html:321 +#: venv/lib/python3.11/site-packages/django_ledger/templates/django_ledger/invoice/tags/invoice_table.html:39 +#: venv/lib/python3.11/site-packages/django_ledger/templates/django_ledger/journal_entry/tags/je_table.html:16 +#: venv/lib/python3.11/site-packages/django_ledger/templates/django_ledger/ledger/tags/ledgers_table.html:16 +#: venv/lib/python3.11/site-packages/django_ledger/templates/django_ledger/ledger/tags/ledgers_table.html:95 +#: venv/lib/python3.11/site-packages/django_ledger/templates/django_ledger/product/tags/product_table.html:15 +#: venv/lib/python3.11/site-packages/django_ledger/templates/django_ledger/service/tags/services_table.html:15 +#: venv/lib/python3.11/site-packages/django_ledger/templates/django_ledger/uom/tags/uom_table.html:11 +#: venv/lib/python3.11/site-packages/django_ledger/templates/django_ledger/uom/tags/uom_table.html:33 +#: venv/lib/python3.11/site-packages/django_ledger/templates/django_ledger/vendor/tags/vendor_table.html:14 +msgid "Actions" +msgstr "الإجراءات" + +#: templates/admin_management/user_management.html:37 +#: templates/admin_management/user_management.html:101 +#: templates/admin_management/user_management.html:165 +#: templates/admin_management/user_management.html:229 +msgid "Inactive" +msgstr "غير نشط" + +msgid "Activate" +msgstr "تفعيل" + +msgid "Permenantly Delete" +msgstr "حذف نهائي" + +msgid "No data available in table" +msgstr "لا توجد بيانات في الجدول" + +#: templates/admin_management/user_management.html:87 +#: templates/admin_management/user_management.html:151 +#: templates/admin_management/user_management.html:215 +#: templates/customers/customer_list.html:60 +#: templates/organizations/organization_list.html:74 +#: templates/vendors/vendors_list.html:75 +msgid "Create date" +msgstr "تاريخ الإنشاء" + #: templates/administration/display_appointment.html:19 -#: templates/customers/view_customer.html:92 -#: templates/customers/view_customer.html:119 +#: templates/customers/view_customer.html:96 +#: templates/customers/view_customer.html:123 #: templates/email_sender/reminder_email.html:80 #: templates/email_sender/reschedule_email.html:64 #: templates/email_sender/reschedule_email.html:69 -#: templates/inventory/car_detail.html:371 -#: templates/inventory/transfer_details.html:59 -#: templates/inventory/transfer_preview.html:219 -#: templates/ledger/coa_accounts/account_detail.html:64 +#: templates/inventory/car_detail.html:402 +#: templates/inventory/transfer_details.html:73 +#: templates/inventory/transfer_preview.html:271 +#: templates/ledger/coa_accounts/account_detail.html:67 #: templates/ledger/journal_entry/includes/card_journal_entry.html:15 #: templates/sales/estimates/sale_order_preview.html:166 #: venv/lib/python3.11/site-packages/appointment/templates/administration/display_appointment.html:25 @@ -3240,14 +3474,14 @@ msgstr "العميل" #: templates/administration/display_appointment.html:55 #: templates/appointment/appointment_client_information.html:57 -#: templates/crm/leads/lead_detail.html:88 -#: templates/dealers/dealer_detail.html:84 +#: templates/crm/leads/lead_detail.html:169 +#: templates/dealers/dealer_detail.html:90 #: templates/organizations/organization_detail.html:10 #: templates/organizations/organization_list.html:64 -#: templates/pricing_page.html:189 +#: templates/pricing_page.html:188 #: templates/representatives/representative_detail.html:9 #: templates/representatives/representative_list.html:19 -#: templates/vendors/vendors_list.html:54 +#: templates/vendors/vendors_list.html:47 #: venv/lib/python3.11/site-packages/appointment/templates/administration/display_appointment.html:49 #: venv/lib/python3.11/site-packages/appointment/templates/appointment/appointment_client_information.html:64 msgid "Phone" @@ -3310,7 +3544,7 @@ msgstr "لقد أرسلنا رمز التحقق إلى بريدك الإلكتر #: templates/administration/email_change_verification_code.html:22 #: templates/appointment/enter_verification_code.html:21 -#: templates/ledger/coa_accounts/account_list.html:50 +#: templates/ledger/coa_accounts/account_list.html:26 #: venv/lib/python3.11/site-packages/appointment/templates/administration/email_change_verification_code.html:22 #: venv/lib/python3.11/site-packages/appointment/templates/appointment/enter_verification_code.html:21 msgid "Code" @@ -3358,25 +3592,26 @@ msgstr "تأكيد الحذف" #: templates/administration/service_list.html:13 #: templates/administration/staff_index.html:79 #: templates/administration/user_profile.html:18 -#: templates/crm/leads/lead_list.html:99 templates/crm/leads/lead_list.html:232 +#: templates/crm/leads/lead_list.html:142 +#: templates/crm/leads/lead_list.html:279 #: ⁨templates/crm/opportunities/opportunity_list copy.html⁩:28 #: templates/customers/view_customer.html:23 #: templates/groups/group_detail.html:109 #: templates/ledger/bank_accounts/bank_account_detail.html:63 -#: templates/ledger/coa_accounts/account_detail.html:118 -#: templates/ledger/coa_accounts/account_list.html:119 +#: templates/ledger/coa_accounts/account_detail.html:144 +#: templates/ledger/coa_accounts/account_list.html:100 #: templates/ledger/journal_entry/journal_entry_delete.html:19 -#: templates/ledger/journal_entry/journal_entry_list.html:116 +#: templates/ledger/journal_entry/journal_entry_list.html:102 #: templates/ledger/ledger/ledger_delete.html:19 -#: templates/ledger/ledger/ledger_list.html:108 +#: templates/ledger/ledger/ledger_list.html:110 #: templates/modal/delete_modal.html:12 templates/modal/delete_modal.html:26 #: templates/modal/event_details_modal.html:33 #: templates/organizations/organization_detail.html:19 -#: templates/organizations/organization_list.html:126 +#: templates/organizations/organization_list.html:123 #: templates/plans/billing_info_create_or_update.html:14 #: templates/representatives/representative_detail.html:16 #: templates/sales/estimates/estimate_detail.html:29 -#: templates/users/user_detail.html:90 templates/vendors/vendors_list.html:112 +#: templates/users/user_detail.html:60 templates/vendors/vendors_list.html:131 #: templates/vendors/view_vendor.html:39 #: venv/lib/python3.11/site-packages/appointment/templates/administration/staff_index.html:325 #: venv/lib/python3.11/site-packages/appointment/templates/administration/user_profile.html:33 @@ -3418,7 +3653,7 @@ msgstr "حذف" #: venv/lib/python3.11/site-packages/appointment/templates/administration/user_profile.html:236 #: venv/lib/python3.11/site-packages/appointment/templates/appointment/default_thank_you.html:23 #: venv/lib/python3.11/site-packages/appointment/views.py:421 -#: venv/lib/python3.11/site-packages/django/db/models/fields/__init__.py:1863 +#: venv/lib/python3.11/site-packages/django/db/models/fields/__init__.py:1868 msgid "Duration" msgstr "المدة" @@ -3461,35 +3696,38 @@ msgstr "" "خيار." #: templates/administration/manage_staff_member.html:70 -#: templates/crm/leads/lead_form.html:13 +#: templates/components/activity_modal.html:25 +#: templates/crm/leads/lead_detail.html:581 +#: templates/crm/leads/lead_detail.html:601 +#: templates/crm/leads/lead_form.html:30 #: templates/crm/leads/schedule_lead.html:15 -#: templates/crm/opportunities/opportunity_detail.html:59 -#: templates/crm/opportunities/opportunity_form.html:88 -#: templates/customers/customer_form.html:30 -#: templates/dealers/assign_car_makes.html:23 +#: templates/crm/opportunities/opportunity_detail.html:60 +#: templates/customers/customer_form.html:31 +#: templates/dealers/assign_car_makes.html:88 #: templates/dealers/dealer_form.html:19 templates/groups/group_form.html:38 #: templates/groups/group_permission_form.html:38 -#: templates/inventory/add_colors.html:56 -#: templates/inventory/add_custom_card.html:17 -#: templates/inventory/car_edit.html:12 -#: templates/inventory/car_finance_form.html:40 -#: templates/inventory/car_location_form.html:13 -#: templates/inventory/car_registration_form.html:18 +#: templates/inventory/add_colors.html:72 +#: templates/inventory/add_custom_card.html:18 +#: templates/inventory/car_edit.html:18 +#: templates/inventory/car_finance_form.html:44 +#: templates/inventory/car_location_form.html:14 +#: templates/inventory/car_registration_form.html:19 #: templates/inventory/color_palette.html:106 #: templates/items/expenses/expense_create.html:16 +#: templates/items/expenses/expense_create.html:21 #: templates/items/expenses/expense_update.html:16 -#: templates/items/service/service_create.html:22 -#: templates/ledger/bank_accounts/bank_account_form.html:31 -#: templates/ledger/bills/bill_form.html:41 +#: templates/items/service/service_create.html:23 +#: templates/ledger/bank_accounts/bank_account_form.html:32 +#: templates/ledger/bills/bill_form.html:42 #: templates/ledger/bills/bill_update_form.html:15 -#: templates/ledger/coa_accounts/account_form.html:30 +#: templates/ledger/coa_accounts/account_form.html:32 #: templates/ledger/journal_entry/journal_entry_form.html:16 #: templates/ledger/journal_entry/journal_entry_txs.html:62 -#: templates/ledger/ledger/ledger_form.html:16 -#: templates/organizations/organization_form.html:17 +#: templates/ledger/ledger/ledger_form.html:22 +#: templates/organizations/organization_form.html:15 #: templates/plans/billing_info_create_or_update.html:17 #: templates/representatives/representative_form.html:11 -#: templates/sales/estimates/estimate_form.html:65 +#: templates/sales/estimates/estimate_form.html:74 #: templates/sales/estimates/sale_order_form.html:194 #: templates/sales/invoices/approved_invoice_update.html:16 #: templates/sales/invoices/draft_invoice_update.html:16 @@ -3497,8 +3735,8 @@ msgstr "" #: templates/sales/invoices/paid_invoice_update.html:16 #: templates/sales/journals/journal_form.html:18 #: templates/sales/payments/payment_create.html:16 -#: templates/users/user_form.html:44 templates/users/user_group_form.html:31 -#: templates/vendors/vendor_form.html:41 +#: templates/users/user_form.html:44 templates/users/user_group_form.html:27 +#: templates/vendors/vendor_form.html:40 #: venv/lib/python3.11/site-packages/appointment/templates/administration/manage_staff_member.html:70 #: venv/lib/python3.11/site-packages/appointment/views_admin.py:464 #: venv/lib/python3.11/site-packages/django_ledger/templates/django_ledger/bills/tags/bill_item_formset.html:81 @@ -3539,12 +3777,14 @@ msgstr "قائمة الخدمات" #: templates/administration/service_list.html:26 #: templates/administration/user_profile.html:94 #: templates/administration/user_profile.html:162 -#: templates/groups/group_detail.html:83 -#: templates/inventory/car_detail.html:367 -#: templates/items/expenses/expenses_list.html:22 +#: templates/crm/leads/lead_list.html:115 +#: templates/crm/leads/lead_list.html:132 templates/groups/group_detail.html:83 +#: templates/inventory/car_detail.html:398 +#: templates/items/expenses/expenses_list.html:23 #: templates/items/service/service_list.html:24 -#: templates/ledger/bank_accounts/bank_account_list.html:21 -#: templates/ledger/journal_entry/journal_entry_list.html:69 +#: templates/ledger/bank_accounts/bank_account_list.html:22 +#: templates/ledger/bills/bill_list.html:53 +#: templates/ledger/journal_entry/journal_entry_list.html:55 #: templates/ledger/ledger/ledger_list.html:25 #: templates/modal/confirm_modal.html:21 #: venv/lib/python3.11/site-packages/appointment/templates/administration/service_list.html:31 @@ -3655,22 +3895,20 @@ msgstr "قائمة جميع أعضاء الفريق" msgid "Staff Members" msgstr "أعضاء الفريق" -#: templates/administration/staff_list.html:25 -#: templates/crm/leads/lead_detail.html:216 templates/crm/note_form.html:15 +#: templates/administration/staff_list.html:25 templates/crm/note_form.html:15 #: templates/customers/note_form.html:6 -#: templates/customers/view_customer.html:84 -#: templates/inventory/car_detail.html:130 -#: templates/inventory/car_detail.html:152 -#: templates/inventory/car_detail.html:168 -#: templates/inventory/car_detail.html:246 -#: templates/inventory/car_detail.html:292 +#: templates/customers/view_customer.html:88 +#: templates/inventory/car_detail.html:153 +#: templates/inventory/car_detail.html:175 +#: templates/inventory/car_detail.html:196 +#: templates/inventory/car_detail.html:273 +#: templates/inventory/car_detail.html:316 #: venv/lib/python3.11/site-packages/appointment/services.py:170 msgid "Add" msgstr "إضافة" #: templates/administration/staff_list.html:36 #: ⁨templates/crm/opportunities/opportunity_list copy.html⁩:71 -#: templates/crm/opportunities/opportunity_list.html:65 #: templates/inventory/car_form.html:228 #: templates/inventory/inventory_stats.html:63 #: venv/lib/python3.11/site-packages/appointment/templates/administration/staff_list.html:40 @@ -3934,20 +4172,20 @@ msgid "Payment Details" msgstr "تفاصيل الدفع" #: templates/appointment/appointment_client_information.html:96 -#: templates/customers/view_customer.html:117 -#: templates/inventory/car_detail.html:230 -#: templates/inventory/inventory_stats.html:72 -#: templates/inventory/transfer_details.html:74 -#: templates/inventory/transfer_preview.html:232 +#: templates/customers/view_customer.html:121 +#: templates/inventory/car_detail.html:258 +#: templates/inventory/inventory_stats.html:70 +#: templates/inventory/transfer_details.html:91 +#: templates/inventory/transfer_preview.html:288 #: templates/ledger/bills/bill_detail.html:216 -#: templates/ledger/coa_accounts/account_detail.html:100 +#: templates/ledger/coa_accounts/account_detail.html:114 #: templates/ledger/ledger/ledger_detail.html:84 #: templates/ledger/ledger/ledger_detail.html:100 #: templates/ledger/reports/tags/balance_sheet_statement.html:55 #: templates/ledger/reports/tags/cash_flow_statement.html:11 #: templates/plans/invoices/layout.html:112 #: templates/plans/invoices/layout.html:133 -#: templates/plans/order_detail_table.html:12 templates/pricing_page.html:183 +#: templates/plans/order_detail_table.html:12 templates/pricing_page.html:182 #: templates/sales/estimates/estimate_detail.html:197 #: templates/sales/estimates/sale_order_preview.html:184 #: templates/sales/invoices/invoice_detail.html:244 @@ -4122,71 +4360,101 @@ msgstr "هيكل" msgid "Select Date" msgstr "اختر التاريخ" -#: templates/crm/leads/lead_detail.html:18 -#: templates/crm/leads/lead_detail.html:35 +#: templates/crm/leads/lead_detail.html:45 +#: templates/crm/leads/lead_list.html:13 +msgid "Update Lead Actions" +msgstr "تحديث إجراءات العميل المحتمل" + +msgid "Current Action" +msgstr "الإجراء الحالي" + +msgid "Select Action" +msgstr "اختر إجراء" + +msgid "Select Next Action" +msgstr "اختر الإجراء التالي" + +msgid "No Action" +msgstr "لا يوجد إجراء" + +msgid "Close" +msgstr "إغلاق" + +msgid "Save Changes" +msgstr "حفظ التغييرات" + +#: templates/crm/leads/lead_detail.html:97 +#: templates/crm/leads/lead_detail.html:114 msgid "Lead Details" msgstr "تفاصيل العميل المحتمل" -#: templates/crm/leads/lead_detail.html:44 +#: templates/crm/leads/lead_detail.html:123 msgid "Assigned to" msgstr "مُعين إلى" -#: templates/crm/leads/lead_detail.html:46 +#: templates/crm/leads/lead_detail.html:125 msgid "Not Assigned" msgstr "غير معين" -#: templates/crm/leads/lead_detail.html:72 +#: templates/crm/leads/lead_detail.html:153 msgid "Car Requested" msgstr "السيارة المطلوبة" -#: templates/crm/leads/lead_detail.html:94 -msgid "Salary" -msgstr "الراتب" - -#: templates/crm/leads/lead_detail.html:106 +#: templates/crm/leads/lead_detail.html:187 msgid "Lead Source" msgstr "مصدر العميل المحتمل" -#: templates/crm/leads/lead_detail.html:112 +#: templates/crm/leads/lead_detail.html:193 msgid "Lead Channel" msgstr "قناة العميل المحتمل" -#: templates/crm/leads/lead_detail.html:124 +#: templates/crm/leads/lead_detail.html:205 #: venv/lib/python3.11/site-packages/django_ledger/forms/entity.py:82 #: venv/lib/python3.11/site-packages/django_ledger/forms/entity.py:159 #: venv/lib/python3.11/site-packages/django_ledger/models/mixins.py:108 msgid "City" msgstr "المدينة" -#: templates/crm/leads/lead_detail.html:201 -msgid "by" -msgstr "بواسطة" +msgid "Current Stage" +msgstr "المرحلة الحالية" -#: templates/crm/leads/lead_detail.html:218 -#: templates/customers/view_customer.html:86 +msgid "Update Actions" +msgstr "تحديث الإجراءات" + +msgid "Add Activity" +msgstr "إضافة نشاط" + +msgid "created by" +msgstr "تم الإنشاء بواسطة" + +#: templates/crm/leads/lead_detail.html:306 +#: templates/customers/view_customer.html:90 msgid "Add Note" msgstr "إضافة ملاحظة" -#: templates/crm/leads/lead_detail.html:227 +#: templates/crm/leads/lead_detail.html:315 msgid "Created By" msgstr "تم الإنشاء بواسطة" -#: templates/crm/leads/lead_detail.html:228 +#: templates/crm/leads/lead_detail.html:316 msgid "Created On" msgstr "تم الإنشاء في" -#: templates/crm/leads/lead_detail.html:245 -#: templates/crm/leads/lead_form.html:6 +#: templates/crm/leads/lead_detail.html:342 +#: templates/crm/leads/lead_detail.html:343 +#: templates/crm/leads/lead_form.html:20 #: templates/crm/leads/schedule_lead.html:5 templates/crm/note_form.html:13 +#: templates/crm/opportunities/opportunity_form.html:142 +#: templates/crm/opportunities/partials/opportunity_grid.html:103 #: templates/customers/view_customer.html:30 -#: templates/items/expenses/expenses_list.html:34 -#: templates/items/service/service_list.html:44 -#: templates/ledger/bank_accounts/bank_account_list.html:33 +#: templates/items/expenses/expenses_list.html:44 +#: templates/items/service/service_list.html:55 +#: templates/ledger/bank_accounts/bank_account_list.html:41 #: templates/ledger/journal_entry/includes/card_invoice.html:34 #: venv/lib/python3.11/site-packages/appointment/services.py:170 #: venv/lib/python3.11/site-packages/appointment/views_admin.py:374 #: venv/lib/python3.11/site-packages/appointment/views_admin.py:471 -#: venv/lib/python3.11/site-packages/django_ledger/templates/django_ledger/account/tags/accounts_table.html:102 +#: venv/lib/python3.11/site-packages/django_ledger/templates/django_ledger/account/tags/accounts_table.html:98 #: venv/lib/python3.11/site-packages/django_ledger/templates/django_ledger/bank_account/bank_account_update.html:23 #: venv/lib/python3.11/site-packages/django_ledger/templates/django_ledger/bank_account/tags/bank_accounts_table.html:49 #: venv/lib/python3.11/site-packages/django_ledger/templates/django_ledger/bills/includes/card_bill.html:46 @@ -4223,14 +4491,18 @@ msgstr "تم الإنشاء في" msgid "Update" msgstr "تحديث" -#: templates/crm/leads/lead_detail.html:417 -#: templates/customers/view_customer.html:219 -#: templates/inventory/car_detail.html:536 -msgid "Error loading form. Please try again later" -msgstr "حدث خطأ أثناء تحميل النموذج. يرجى المحاولة مرة أخرى لاحقًا." +#: templates/crm/leads/lead_detail.html:366 +#: templates/crm/leads/lead_list.html:272 +msgid "Send Email" +msgstr "إرسال البريد الإلكتروني" -#: templates/crm/leads/lead_form.html:6 +#: templates/crm/leads/lead_detail.html:486 +msgid "Add Task" +msgstr "إضافة مهمة" + +#: templates/crm/leads/lead_form.html:20 #: templates/crm/leads/schedule_lead.html:5 +#: templates/crm/opportunities/opportunity_form.html:144 #: venv/lib/python3.11/site-packages/appointment/views_admin.py:429 #: venv/lib/python3.11/site-packages/django_ledger/templates/django_ledger/bank_account/bank_account_create.html:22 #: venv/lib/python3.11/site-packages/django_ledger/templates/django_ledger/bills/bill_create.html:33 @@ -4246,48 +4518,48 @@ msgstr "حدث خطأ أثناء تحميل النموذج. يرجى المحا msgid "Create" msgstr "إنشاء" -#: templates/crm/leads/lead_list.html:13 +#: templates/crm/leads/lead_list.html:25 templates/crm/leads/lead_list.html:173 +msgid "Contacted" +msgstr "تم الاتصال" + +#: templates/crm/leads/lead_list.html:27 +msgid "Proposal Sent" +msgstr "تم إرسال العرض" + +msgid "Send Proposal" +msgstr "إرسال العرض" + +#: templates/crm/leads/lead_list.html:69 msgid "Add Lead" msgstr "إضافة عميل محتمل" -#: templates/crm/leads/lead_list.html:31 +#: templates/crm/leads/lead_list.html:87 msgid "Lead Name" msgstr "اسم العميل المحتمل" -#: templates/crm/leads/lead_list.html:53 +#: templates/crm/leads/lead_list.html:109 msgid "Schedule" msgstr "الجدولة" -#: templates/crm/leads/lead_list.html:59 +#: templates/crm/leads/lead_list.html:121 msgid "Assigned To" msgstr "مُعين إلى" -#: templates/crm/leads/lead_list.html:83 -msgid "Is Opportunity" -msgstr "هل هي فرصة" - -#: templates/crm/leads/lead_list.html:87 -#: templates/customers/customer_list.html:60 -#: templates/organizations/organization_list.html:74 -#: templates/vendors/vendors_list.html:68 -msgid "Create date" -msgstr "تاريخ الإنشاء" - -#: templates/crm/leads/lead_list.html:103 +#: templates/crm/leads/lead_list.html:146 msgid "Are you sure you want to delete this lead?" msgstr "هل أنت متأكد أنك تريد حذف هذا العميل المحتمل؟" -#: templates/crm/leads/lead_list.html:107 +#: templates/crm/leads/lead_list.html:150 #: ⁨templates/crm/opportunities/opportunity_list copy.html⁩:158 #: templates/groups/group_detail.html:32 -#: templates/inventory/car_detail.html:472 -#: templates/inventory/transfer_details.html:47 +#: templates/inventory/car_detail.html:519 +#: templates/inventory/transfer_details.html:62 #: templates/ledger/bank_accounts/bank_account_detail.html:31 #: templates/ledger/bills/bill_detail.html:24 #: templates/ledger/bills/bill_detail.html:49 #: templates/ledger/bills/bill_detail.html:121 #: templates/ledger/coa_accounts/account_detail.html:22 -#: templates/ledger/coa_accounts/account_list.html:86 +#: templates/ledger/coa_accounts/account_list.html:60 #: templates/ledger/journal_entry/journal_entry_list.html:25 #: templates/organizations/organization_list.html:96 #: templates/sales/estimates/estimate_detail.html:37 @@ -4295,50 +4567,32 @@ msgstr "هل أنت متأكد أنك تريد حذف هذا العميل الم #: templates/sales/invoices/invoice_detail.html:31 #: templates/sales/invoices/invoice_detail.html:56 #: templates/sales/invoices/invoice_detail.html:142 -#: templates/users/user_detail.html:32 #: venv/lib/python3.11/site-packages/appointment/models.py:530 -#: venv/lib/python3.11/site-packages/django/forms/widgets.py:801 +#: venv/lib/python3.11/site-packages/django/forms/widgets.py:867 msgid "Yes" msgstr "نعم" -#: templates/crm/leads/lead_list.html:205 -#: ⁨templates/crm/opportunities/opportunity_list copy.html⁩:155 -#: templates/groups/group_detail.html:27 -#: templates/inventory/car_detail.html:467 -#: templates/inventory/transfer_details.html:24 -#: templates/inventory/transfer_details.html:46 -#: templates/ledger/bank_accounts/bank_account_detail.html:26 -#: templates/ledger/bills/bill_detail.html:20 -#: templates/ledger/bills/bill_detail.html:45 -#: templates/ledger/bills/bill_detail.html:123 -#: templates/ledger/coa_accounts/account_detail.html:18 -#: templates/ledger/coa_accounts/account_list.html:83 -#: templates/ledger/journal_entry/journal_entry_list.html:24 -#: templates/organizations/organization_list.html:95 -#: templates/sales/estimates/estimate_detail.html:63 -#: templates/sales/invoices/invoice_detail.html:27 -#: templates/sales/invoices/invoice_detail.html:52 -#: templates/sales/invoices/invoice_detail.html:144 -#: templates/users/user_detail.html:27 -#: venv/lib/python3.11/site-packages/appointment/models.py:530 -#: venv/lib/python3.11/site-packages/appointment/tests/models/test_appointment.py:62 -#: venv/lib/python3.11/site-packages/django/forms/widgets.py:802 -msgid "No" -msgstr "لا" +#: templates/crm/leads/lead_list.html:169 +msgid "In Progress" +msgstr "قيد التنفيذ" -#: templates/crm/leads/lead_list.html:223 +#: templates/crm/leads/lead_list.html:171 +msgid "Qualified" +msgstr "مؤهل" + +#: templates/crm/leads/lead_list.html:267 #: ⁨templates/crm/opportunities/opportunity_list copy.html⁩:27 -#: templates/dealers/dealer_detail.html:13 +#: templates/dealers/dealer_detail.html:19 #: templates/groups/group_detail.html:103 -#: templates/inventory/car_detail.html:179 -#: templates/inventory/car_detail.html:237 +#: templates/inventory/car_detail.html:207 +#: templates/inventory/car_detail.html:265 #: templates/ledger/bank_accounts/bank_account_detail.html:57 -#: templates/ledger/coa_accounts/account_detail.html:114 +#: templates/ledger/coa_accounts/account_detail.html:140 #: templates/modal/event_details_modal.html:27 #: templates/organizations/organization_detail.html:14 -#: templates/organizations/organization_list.html:124 +#: templates/organizations/organization_list.html:121 #: templates/representatives/representative_detail.html:13 -#: templates/users/user_detail.html:84 templates/vendors/vendors_list.html:105 +#: templates/users/user_detail.html:52 templates/vendors/vendors_list.html:125 #: templates/vendors/view_vendor.html:32 #: venv/lib/python3.11/site-packages/appointment/templates/modal/event_details_modal.html:25 #: venv/lib/python3.11/site-packages/django_ledger/templates/django_ledger/customer/includes/card_customer.html:28 @@ -4348,17 +4602,21 @@ msgstr "لا" msgid "Edit" msgstr "تحديث" -#: templates/crm/leads/lead_list.html:225 -msgid "Send Email" -msgstr "إرسال البريد الإلكتروني" - -#: templates/crm/leads/lead_list.html:226 +#: templates/crm/leads/lead_list.html:273 msgid "Schedule Event" msgstr "جدولة الحدث" -#: templates/crm/leads/lead_list.html:228 -msgid "Convert" -msgstr "تحويل" +msgid "Convert to Opportunity" +msgstr "تحويل إلى فرصة" + +msgid "Lead Tracking" +msgstr "تتبع العملاء المحتملين" + +msgid "New Leads" +msgstr "عملاء محتملون جدد" + +msgid "Follow Ups" +msgstr "متابعات" #: templates/crm/notifications.html:16 #: templates/crm/notifications_history.html:14 @@ -4378,65 +4636,59 @@ msgstr "تفاصيل الفرصة" msgid "View Quotation" msgstr "مشاهدة عرض السعر" -#: templates/crm/opportunities/opportunity_detail.html:83 -msgid "Other Information" -msgstr "معلومات أخرى" - -#: templates/crm/opportunities/opportunity_detail.html:89 -msgid "Update Status" -msgstr "تحديث الحالة" - -#: templates/crm/opportunities/opportunity_detail.html:96 -msgid "Update Stage" -msgstr "تحديث المرحلة" - -#: templates/crm/opportunities/opportunity_detail.html:114 +#: templates/crm/opportunities/opportunity_detail.html:116 msgid "Quotation Amount" msgstr "مبلغ عرض السعر" -#: templates/crm/opportunities/opportunity_detail.html:169 +#: templates/crm/opportunities/opportunity_detail.html:171 #: venv/lib/python3.11/site-packages/django_ledger/templates/django_ledger/estimate/includes/card_estimate.html:14 msgid "Estimated Revenue" msgstr "الإيرادات المقدرة" -#: templates/crm/opportunities/opportunity_detail.html:219 +#: templates/crm/opportunities/opportunity_detail.html:221 msgid "Contact Name" msgstr "اسم جهة الاتصال" -#: templates/crm/opportunities/opportunity_detail.html:252 +#: templates/crm/opportunities/opportunity_detail.html:254 msgid "Create Date" msgstr "تاريخ الإنشاء" -#: templates/crm/opportunities/opportunity_form.html:8 +#: templates/crm/opportunities/opportunity_form.html:10 msgid "Edit Opportunity" msgstr "تعديل الفرصة" -#: templates/crm/opportunities/opportunity_form.html:8 -msgid "Add New Opportunity" -msgstr "إضافة فرصة جديدة" +msgid "Create New Opportunity" +msgstr "إنشاء فرصة جديدة" -#: templates/crm/opportunities/opportunity_form.html:56 -msgid "Enter probability" -msgstr "أدخل الاحتمالية" +msgid "Back to list" +msgstr "العودة إلى القائمة" -#: templates/crm/opportunities/opportunity_form.html:57 -#: ⁨templates/crm/opportunities/opportunity_list copy.html⁩:110 -#: templates/crm/opportunities/opportunity_list.html:104 -msgid "Probability" -msgstr "الاحتمالية" +msgid "Reset" +msgstr "إعادة تعيين" + +msgid "Opportunity Guidelines" +msgstr "إرشادات الفرص" + +msgid "Probability indicates conversion chance" +msgstr "تشير النسبة المئوية إلى فرصة التحويل" + +msgid "Update stage as deal progresses" +msgstr "تحديث المرحلة مع تقدم الصفقة" + +msgid "Set realistic closing dates" +msgstr "تحديد تواريخ إغلاق واقعية" #: ⁨templates/crm/opportunities/opportunity_list copy.html⁩:11 -#: templates/crm/opportunities/opportunity_list.html:11 +#: templates/crm/opportunities/opportunity_list.html:83 msgid "Add Opportunity" msgstr "إضافة فرصة" #: ⁨templates/crm/opportunities/opportunity_list copy.html⁩:55 -#: templates/crm/opportunities/opportunity_list.html:49 -#: templates/inventory/car_list_view.html:167 -#: templates/ledger/bills/bill_list.html:80 -#: templates/ledger/coa_accounts/account_list.html:117 +#: templates/inventory/car_list_view.html:231 +#: templates/ledger/bills/bill_list.html:84 +#: templates/ledger/coa_accounts/account_list.html:98 #: templates/ledger/journal_entry/includes/card_invoice.html:33 -#: templates/ledger/journal_entry/journal_entry_list.html:113 +#: templates/ledger/journal_entry/journal_entry_list.html:99 #: templates/sales/invoices/invoice_list.html:61 #: templates/sales/sales_list.html:207 #: venv/lib/python3.11/site-packages/django_ledger/templates/django_ledger/bills/includes/card_bill.html:44 @@ -4448,16 +4700,15 @@ msgstr "إضافة فرصة" msgid "View" msgstr "عرض" -#: ⁨templates/crm/opportunities/opportunity_list copy.html⁩:78 -#: templates/crm/opportunities/opportunity_list.html:72 -msgid "Expected Revenue" -msgstr "الإيرادات المتوقعة" - #: ⁨templates/crm/opportunities/opportunity_list copy.html⁩:89 -#: templates/crm/opportunities/opportunity_list.html:83 msgid "Contact" msgstr "جهة الاتصال" +#: ⁨templates/crm/opportunities/opportunity_list copy.html⁩:110 +#: templates/crm/opportunities/partials/opportunity_grid.html:81 +msgid "Probability" +msgstr "الاحتمالية" + #: ⁨templates/crm/opportunities/opportunity_list copy.html⁩:145 msgid "Delete Opportunity" msgstr "حذف الفرصة" @@ -4466,12 +4717,55 @@ msgstr "حذف الفرصة" msgid "Are you sure you want to delete this opportunity?" msgstr "هل أنت متأكد أنك تريد حذف هذه الفرصة؟" +#: ⁨templates/crm/opportunities/opportunity_list copy.html⁩:155 +#: templates/groups/group_detail.html:27 +#: templates/inventory/car_detail.html:514 +#: templates/inventory/transfer_details.html:29 +#: templates/inventory/transfer_details.html:58 +#: templates/ledger/bank_accounts/bank_account_detail.html:26 +#: templates/ledger/bills/bill_detail.html:20 +#: templates/ledger/bills/bill_detail.html:45 +#: templates/ledger/bills/bill_detail.html:123 +#: templates/ledger/coa_accounts/account_detail.html:18 +#: templates/ledger/coa_accounts/account_list.html:57 +#: templates/ledger/journal_entry/journal_entry_list.html:24 +#: templates/organizations/organization_list.html:95 +#: templates/sales/estimates/estimate_detail.html:63 +#: templates/sales/invoices/invoice_detail.html:27 +#: templates/sales/invoices/invoice_detail.html:52 +#: templates/sales/invoices/invoice_detail.html:144 +#: venv/lib/python3.11/site-packages/appointment/models.py:530 +#: venv/lib/python3.11/site-packages/appointment/tests/models/test_appointment.py:62 +#: venv/lib/python3.11/site-packages/django/forms/widgets.py:868 +msgid "No" +msgstr "لا" + +#: templates/crm/opportunities/opportunity_list.html:20 +msgid "Search opportunities..." +msgstr "ابحث في الفرص..." + +msgid "All Stages" +msgstr "جميع المراحل" + +msgid "Newest First" +msgstr "الأحدث أولاً" + +msgid "Highest Value" +msgstr "أعلى قيمة" + +msgid "Earliest Close Date" +msgstr "أقرب تاريخ إغلاق" + +msgid "View Details" +msgstr "عرض التفاصيل" + #: templates/customers/customer_form.html:15 msgid "Edit Customer" msgstr "تحديث العميل" #: templates/customers/customer_form.html:17 #: templates/customers/customer_list.html:15 +#: templates/sales/estimates/estimate_form.html:27 msgid "Add Customer" msgstr "إضافة عميل" @@ -4487,7 +4781,7 @@ msgstr "عرض العميل" msgid "Customer details" msgstr "تفاصيل العميل" -#: templates/customers/view_customer.html:53 +#: templates/customers/view_customer.html:57 #: templates/dashboards/manager.html:31 #: templates/sales/invoices/invoice_list.html:4 #: templates/sales/invoices/invoice_list.html:9 @@ -4499,35 +4793,35 @@ msgstr "تفاصيل العميل" msgid "Invoices" msgstr "الفواتير" -#: templates/customers/view_customer.html:57 +#: templates/customers/view_customer.html:61 #: templates/dashboards/manager.html:36 #: templates/sales/estimates/estimate_list.html:4 #: templates/sales/estimates/estimate_list.html:8 msgid "Quotations" msgstr "العروض" -#: templates/customers/view_customer.html:68 -#: templates/dealers/dealer_detail.html:63 +#: templates/customers/view_customer.html:72 +#: templates/dealers/dealer_detail.html:69 msgid "Default Address" msgstr "العنوان الافتراضي" -#: templates/customers/view_customer.html:110 +#: templates/customers/view_customer.html:114 msgid "Related" msgstr "مرتبط" -#: templates/customers/view_customer.html:116 -#: templates/ledger/bank_accounts/bank_account_list.html:20 -#: templates/ledger/coa_accounts/account_list.html:48 +#: templates/customers/view_customer.html:120 +#: templates/ledger/bank_accounts/bank_account_list.html:21 +#: templates/ledger/coa_accounts/account_list.html:24 #: venv/lib/python3.11/site-packages/django_ledger/templates/django_ledger/product/tags/product_table.html:8 #: venv/lib/python3.11/site-packages/django_ledger/templates/django_ledger/service/tags/services_table.html:8 msgid "Type" msgstr "النوع" -#: templates/customers/view_customer.html:118 +#: templates/customers/view_customer.html:122 msgid "Payment Status" msgstr "حالة الدفع" -#: templates/customers/view_customer.html:128 +#: templates/customers/view_customer.html:132 #: templates/sales/estimates/estimate_detail.html:79 #: templates/sales/estimates/estimate_send.html:5 #: templates/sales/estimates/sale_order_form.html:171 @@ -4535,7 +4829,7 @@ msgstr "حالة الدفع" msgid "Quotation" msgstr "عرض سعر" -#: templates/customers/view_customer.html:156 +#: templates/customers/view_customer.html:160 #: templates/ledger/bills/bill_detail.html:199 #: templates/sales/invoices/invoice_detail.html:80 #: templates/sales/invoices/invoice_detail.html:224 @@ -4545,6 +4839,11 @@ msgstr "عرض سعر" msgid "Paid" msgstr "مدفوع" +#: templates/customers/view_customer.html:223 +#: templates/inventory/car_detail.html:588 +msgid "Error loading form. Please try again later" +msgstr "حدث خطأ أثناء تحميل النموذج. يرجى المحاولة مرة أخرى لاحقًا." + #: templates/dashboards/manager.html:9 templates/dashboards/sales.html:119 msgid "As of" msgstr "حتى" @@ -4578,10 +4877,6 @@ msgstr "تم استلام الدفع عبر جميع القنوات." msgid "New Customers" msgstr "عملاء جدد." -#: templates/dashboards/sales.html:91 -msgid "New Leads" -msgstr "فرص جديدة." - #: templates/dashboards/sales.html:154 msgid "Canceled Invoices" msgstr "الفواتير الملغاة." @@ -4596,7 +4891,7 @@ msgstr "من الشهر الماضي." msgid "Gross Profit" msgstr "الربح الإجمالي" -#: templates/dealers/assign_car_makes.html:16 +#: templates/dealers/assign_car_makes.html:59 msgid "Select Car Makes You Sell" msgstr "اختر ماركات السيارات التي تبيعها" @@ -4604,64 +4899,74 @@ msgstr "اختر ماركات السيارات التي تبيعها" msgid "Profile" msgstr "الملف الشخصي" -#: templates/dealers/dealer_detail.html:37 +#: templates/dealers/dealer_detail.html:10 +#: templates/sales/orders/order_list.html:4 +#: templates/sales/orders/order_list.html:8 +msgid "Orders" +msgstr "طلبات" + +#: templates/dealers/dealer_detail.html:13 +msgid "Billing Information" +msgstr "معلومات الفوترة" + +#: templates/dealers/dealer_detail.html:43 msgid "Joined" msgstr "انضم" -#: templates/dealers/dealer_detail.html:37 +#: templates/dealers/dealer_detail.html:43 #: venv/lib/python3.11/site-packages/django_ledger/templates/django_ledger/chart_of_accounts/includes/coa_card.html:41 msgid "ago" msgstr "منذ" -#: templates/dealers/dealer_detail.html:44 +#: templates/dealers/dealer_detail.html:50 msgid "last login" msgstr "آخر تسجيل دخول" -#: templates/dealers/dealer_detail.html:48 +#: templates/dealers/dealer_detail.html:54 msgid "Total users" msgstr "إجمالي المستخدمين" -#: templates/dealers/dealer_detail.html:52 +#: templates/dealers/dealer_detail.html:58 msgid "Total cars" msgstr "إجمالي السيارات" -#: templates/dealers/dealer_detail.html:107 -#: templates/inventory/car_detail.html:336 templates/plans/current.html:28 +#: templates/dealers/dealer_detail.html:113 +#: templates/inventory/car_detail.html:364 templates/plans/current.html:28 msgid "Expired" msgstr "منتهي الصلاحية" -#: templates/dealers/dealer_detail.html:108 -#: templates/inventory/car_detail.html:327 +#: templates/dealers/dealer_detail.html:114 +#: templates/inventory/car_detail.html:353 msgid "Renew" msgstr "تجديد" -#: templates/dealers/dealer_detail.html:111 templates/plans/current.html:46 +#: templates/dealers/dealer_detail.html:117 templates/plans/current.html:46 msgid "Upgrade" msgstr "ترقية" -#: templates/dealers/dealer_detail.html:114 +#: templates/dealers/dealer_detail.html:120 #: templates/subscriptions/subscription_plan.html:85 msgid "Subscribe" msgstr "الاشتراك" -#: templates/dealers/dealer_detail.html:118 templates/plans/current.html:35 +#: templates/dealers/dealer_detail.html:124 templates/plans/current.html:35 msgid "Active until" msgstr "نشط حتى" -#: templates/dealers/dealer_detail.html:118 +#: templates/dealers/dealer_detail.html:124 msgid "Days left" msgstr "الأيام المتبقية" -#: templates/dealers/dealer_detail.html:121 +#: templates/dealers/dealer_detail.html:127 #: templates/subscriptions/subscription_plan.html:42 templates/welcome.html:107 msgid "Per month" msgstr "شهريًا" -#: templates/dealers/dealer_detail.html:151 +#: templates/dealers/dealer_detail.html:157 msgid "Makes you are selling" msgstr "الماركات التي تبيعها" -#: templates/dealers/dealer_detail.html:166 +#: templates/dealers/dealer_detail.html:172 msgid "Select Makes" msgstr "اختر العلامات التجارية" @@ -4701,7 +5006,7 @@ msgstr "الخدمة المطلوبة" #: venv/lib/python3.11/site-packages/appointment/templates/email_sender/reminder_email.html:138 #: venv/lib/python3.11/site-packages/appointment/templates/email_sender/reschedule_email.html:65 #: venv/lib/python3.11/site-packages/appointment/templates/email_sender/reschedule_email.html:70 -#: venv/lib/python3.11/site-packages/django/db/models/fields/__init__.py:2529 +#: venv/lib/python3.11/site-packages/django/db/models/fields/__init__.py:2534 msgid "Time" msgstr "الوقت" @@ -4754,7 +5059,7 @@ msgid "This is a reminder for your upcoming appointment." msgstr "هذه تذكرة بموعدك القادم." #: templates/email_sender/reminder_email.html:83 -#: templates/inventory/car_detail.html:159 +#: templates/inventory/car_detail.html:180 #: venv/lib/python3.11/site-packages/appointment/templates/email_sender/reminder_email.html:142 msgid "Location" msgstr "الموقع" @@ -4886,26 +5191,23 @@ msgstr "شكرًا لاختيارك لنا." msgid "Account Activation" msgstr "تفعيل الحساب" -#: templates/email_sender/thank_you_email.html:185 -#: venv/lib/python3.11/site-packages/appointment/templates/email_sender/thank_you_email.html:185 -#, python-format +#: templates/email_sender/thank_you_email.html:185 " msgid "" "\n" -" To activate your account and set " -"your password, please use the following secure\n" -" link: Set Your Password. Please\n" -" note that this link will expire in 2 " -"days for your security.\n" -" " +" note that this link will " +"expire in 2 days for your security.\n" +" " msgstr "" "\n" -" لتفعيل حسابك وتعيين كلمة المرور، " -"يرجى استخدام الرابط الآمن التالي: تعيين كلمة المرور. يرجى\n" -" ملاحظة أن هذا الرابط سينتهي صلاحيته " -"خلال يومين لضمان الأمان.\n" -" " +" لتفعيل حسابك وتعيين كلمة المرور، يرجى استخدام الرابط الآمن التالي:\n" +" تعيين كلمة المرور.\n" +" يرجى ملاحظة أن هذا الرابط سينتهي خلال يومين لأغراض الأمان.\n" +" " + #: templates/email_sender/thank_you_email.html:198 #: venv/lib/python3.11/site-packages/appointment/templates/email_sender/thank_you_email.html:198 @@ -4939,13 +5241,19 @@ msgid "Support" msgstr "الدعم" #: templates/email_sender/thank_you_email.html:246 -#: venv/lib/python3.11/site-packages/appointment/templates/email_sender/thank_you_email.html:246 +#, fuzzy +#| msgid "" +#| "\n" +#| " Should you have any inquiries or require " +#| "further assistance, our support team is here to\n" +#| " help. You can reach us anytime.\n" +#| " " msgid "" "\n" -" Should you have any inquiries or require " -"further assistance, our support team is here to\n" -" help. You can reach us anytime.\n" -" " +" Should you have any inquiries or " +"require further assistance, our support team is here to\n" +" help. You can reach us anytime.\n" +" " msgstr "" "\n" " إذا كان لديك أي استفسارات أو كنت بحاجة إلى " @@ -5034,19 +5342,19 @@ msgid "Users" msgstr "المستخدمون" #: templates/groups/group_detail.html:65 templates/groups/group_detail.html:94 -#: venv/lib/python3.11/site-packages/django_ledger/models/entity.py:3219 +#: venv/lib/python3.11/site-packages/django_ledger/models/entity.py:3231 msgid "No Permissions" msgstr "بدون أذونات" #: templates/groups/group_detail.html:82 templates/groups/group_list.html:24 -#: templates/users/user_detail.html:65 templates/users/user_list.html:24 +#: templates/users/user_detail.html:34 templates/users/user_list.html:32 msgid "name" msgstr "الاسم" #: templates/groups/group_detail.html:114 #: templates/ledger/bank_accounts/bank_account_detail.html:68 -#: templates/ledger/coa_accounts/account_detail.html:122 -#: templates/users/user_detail.html:95 +#: templates/ledger/coa_accounts/account_detail.html:148 +#: templates/users/user_detail.html:65 msgid "Back to List" msgstr "العودة إلى القائمة" @@ -5066,17 +5374,17 @@ msgstr "إجمالي المستخدمين" msgid "total permission" msgstr "إجمالي الأذونات" -#: templates/groups/group_list.html:27 templates/users/user_list.html:30 +#: templates/groups/group_list.html:27 templates/users/user_list.html:36 msgid "actions" msgstr "الإجراءات" -#: templates/groups/group_list.html:40 templates/inventory/car_detail.html:112 -#: templates/inventory/car_inventory.html:114 -#: templates/ledger/coa_accounts/account_detail.html:92 +#: templates/groups/group_list.html:40 templates/inventory/car_detail.html:133 +#: templates/inventory/car_inventory.html:150 +#: templates/ledger/coa_accounts/account_detail.html:102 #: templates/representatives/representative_list.html:30 #: templates/sales/estimates/estimate_list.html:50 #: templates/sales/journals/journal_list.html:34 -#: templates/users/user_list.html:52 +#: templates/users/user_list.html:58 msgid "view" msgstr "عرض" @@ -5092,33 +5400,30 @@ msgstr "تحرير الإذن" msgid "Add Permission" msgstr "إضافة إذن" -#: templates/haikalbot/chatbot.html:4 templates/haikalbot/chatbot.html:22 -#: templates/haikalbot/chatbot.html:27 templates/haikalbot/chatbot.html:78 -msgid "HaikalBot" +#: templates/haikalbot/chatbot.html:5 +msgid "Haikalbot" msgstr "هيكل بوت" -#: templates/haikalbot/chatbot.html:27 -msgid "Hello! How can I assist you today?" -msgstr "مرحبًا! كيف يمكنني مساعدتك اليوم؟" +msgid "How many cars are in inventory" +msgstr "كم عدد السيارات في المخزون" -#: templates/haikalbot/chatbot.html:32 -msgid "Type your message here..." -msgstr "اكتب رسالتك هنا..." +msgid "Show me sales analysis" +msgstr "اعرض لي تحليل المبيعات" -#: templates/haikalbot/chatbot.html:33 -#: templates/sales/estimates/estimate_send.html:27 -msgid "Send" -msgstr "إرسال" +msgid "What are the best-selling cars" +msgstr "ما هي السيارات الأكثر مبيعًا" -#: templates/haikalbot/chatbot.html:77 -msgid "You" -msgstr "أنت" +msgid "Type your message here" +msgstr "اكتب رسالتك هنا" + +msgid "Copy" +msgstr "نسخ" #: templates/header.html:27 msgid "add car" msgstr "إضافة سيارة" -#: templates/header.html:43 templates/inventory/car_inventory.html:52 +#: templates/header.html:43 templates/inventory/car_inventory.html:62 msgid "Stock" msgstr "المخزون" @@ -5150,62 +5455,66 @@ msgstr "إدارة علاقات العملاء" msgid "leads" msgstr "الفرص" -#: templates/header.html:181 templates/header.html:186 +#: templates/header.html:141 +msgid "leads Tracking" +msgstr "متابعة العملاء المحتملين" + +#: templates/header.html:195 templates/header.html:200 msgid "Financials" msgstr "البيانات المالية" -#: templates/header.html:191 +#: templates/header.html:205 #: venv/lib/python3.11/site-packages/django_ledger/models/accounts.py:436 #: venv/lib/python3.11/site-packages/django_ledger/models/chart_of_accounts.py:192 msgid "Chart of Accounts" msgstr "قائمة الحسابات" -#: templates/header.html:200 +#: templates/header.html:214 #: templates/ledger/bank_accounts/bank_account_list.html:4 #: templates/ledger/bank_accounts/bank_account_list.html:10 #: venv/lib/python3.11/site-packages/django_ledger/views/bank_account.py:33 msgid "Bank Accounts" msgstr "الحسابات المصرفية" -#: templates/header.html:209 +#: templates/header.html:223 #: venv/lib/python3.11/site-packages/django_ledger/models/ledger.py:214 msgid "Ledgers" msgstr "دفاتر الأستاذ" -#: templates/header.html:217 templates/items/service/service_list.html:10 +#: templates/header.html:231 templates/items/service/service_list.html:4 +#: templates/items/service/service_list.html:10 #: venv/lib/python3.11/site-packages/django_ledger/views/item.py:297 msgid "Services" msgstr "الخدمات" -#: templates/header.html:225 templates/items/expenses/expense_create.html:5 +#: templates/header.html:239 templates/items/expenses/expense_create.html:5 #: templates/items/expenses/expense_update.html:5 #: templates/items/expenses/expenses_list.html:4 -#: templates/items/expenses/expenses_list.html:10 -#: templates/items/service/service_list.html:4 +#: templates/items/expenses/expenses_list.html:11 #: templates/ledger/reports/dashboard.html:48 #: venv/lib/python3.11/site-packages/django_ledger/templates/django_ledger/includes/widget_ic.html:8 msgid "Expenses" msgstr "المصروفات" -#: templates/header.html:234 +#: templates/header.html:248 msgid "vendors" msgstr "الموردين" -#: templates/header.html:243 +#: templates/header.html:257 msgid "bills" msgstr "الفواتير" -#: templates/header.html:255 +#: templates/header.html:269 #: venv/lib/python3.11/site-packages/django_ledger/templates/django_ledger/ledger/tags/ledgers_table.html:11 #: venv/lib/python3.11/site-packages/django_ledger/templates/django_ledger/ledger/tags/ledgers_table.html:42 msgid "Reports" msgstr "التقارير" -#: templates/header.html:282 +#: templates/header.html:297 msgid "Cash Flow" msgstr "التدفق النقدي" -#: templates/header.html:293 templates/ledger/ledger/ledger_detail.html:117 +#: templates/header.html:308 templates/ledger/ledger/ledger_detail.html:117 #: templates/ledger/reports/income_statement.html:31 #: venv/lib/python3.11/site-packages/django_ledger/templates/django_ledger/bills/bill_detail.html:146 #: venv/lib/python3.11/site-packages/django_ledger/templates/django_ledger/bills/bill_update.html:71 @@ -5217,7 +5526,7 @@ msgstr "التدفق النقدي" msgid "Income Statement" msgstr "بيان الدخل" -#: templates/header.html:304 templates/ledger/ledger/ledger_detail.html:115 +#: templates/header.html:319 templates/ledger/ledger/ledger_detail.html:115 #: templates/ledger/reports/balance_sheet.html:36 #: venv/lib/python3.11/site-packages/django_ledger/templates/django_ledger/bills/bill_detail.html:144 #: venv/lib/python3.11/site-packages/django_ledger/templates/django_ledger/bills/bill_update.html:66 @@ -5230,37 +5539,41 @@ msgstr "بيان الدخل" msgid "Balance Sheet" msgstr "الميزانية العمومية" -#: templates/header.html:351 templates/header.html:352 +#: templates/header.html:367 templates/header.html:368 #: templates/welcome_header.html:13 templates/welcome_header.html:14 msgid "Switch theme" msgstr "تبديل النمط" -#: templates/header.html:406 templates/header.html:410 +#: templates/header.html:422 templates/header.html:426 msgid "profile" msgstr "الملف الشخصي" -#: templates/header.html:415 +#: templates/header.html:431 msgid "Staff & Groups" msgstr "الموظفون والمجموعات" -#: templates/header.html:423 +#: templates/header.html:439 msgid "Settings" msgstr "الإعدادات" +#: templates/header.html:444 +msgid "Admin Managemnet" +msgstr "xxxxxxxxxxxxxxx" + #: templates/inventory/add_colors.html:5 msgid "Add Colors" msgstr "إضافة لون" -#: templates/inventory/add_colors.html:6 +#: templates/inventory/add_colors.html:7 msgid "Select exterior and interior colors for" msgstr "اختر الألوان الخارجية والداخلية لـ" -#: templates/inventory/car_detail.html:3 templates/inventory/car_detail.html:54 -#: templates/inventory/car_history.html:4 +#: templates/inventory/car_detail.html:3 templates/inventory/car_detail.html:71 +#: templates/inventory/car_history.html:3 msgid "Car Details" msgstr "تفاصيل السيارة" -#: templates/inventory/car_detail.html:23 +#: templates/inventory/car_detail.html:24 msgid "" "This car information is not complete , please add colors and finances before " "making it ready for sale ." @@ -5268,192 +5581,157 @@ msgstr "" "معلومات هذه السيارة غير مكتملة، يرجى إضافة الألوان المعلومات المالية قبل " "تجهيزها للبيع." -#: templates/inventory/car_detail.html:30 +#: templates/inventory/car_detail.html:25 +msgid "Add Color" +msgstr "إضافة لون" + +#: templates/inventory/car_detail.html:37 msgid "Action Required , Please Approved The Tranfer Request Of This Car ." msgstr "الإجراء مطلوب، يرجى الموافقة على طلب نقل هذه السيارة." -#: templates/inventory/car_detail.html:37 +#: templates/inventory/car_detail.html:48 msgid "" "Car Is In Transfer Process To Another Dealer, Please Wait For The " "Acceptance ." msgstr "السيارة قيد عملية النقل إلى تاجر آخر، يرجى انتظار القبول." -#: templates/inventory/car_detail.html:44 +#: templates/inventory/car_detail.html:59 msgid "This car is reserved until " msgstr "هذه السيارة محجوزة حتى " -#: templates/inventory/car_detail.html:63 templates/inventory/car_list.html:119 +#: templates/inventory/car_detail.html:80 templates/inventory/car_list.html:128 msgid "year" msgstr "السنة" -#: templates/inventory/car_detail.html:67 templates/inventory/car_form.html:84 -#: ⁨templates/inventory/car_form_qabl alfalsafa.html⁩:82 -#: templates/inventory/car_list.html:79 +#: templates/inventory/car_detail.html:84 templates/inventory/car_form.html:91 +#: ⁨templates/inventory/car_form_qabl alfalsafa.html⁩:70 +#: templates/inventory/car_list.html:88 msgid "make" msgstr "الصانع" -#: templates/inventory/car_detail.html:71 templates/inventory/car_form.html:107 -#: ⁨templates/inventory/car_form_qabl alfalsafa.html⁩:99 -#: templates/inventory/car_list.html:97 +#: templates/inventory/car_detail.html:88 templates/inventory/car_form.html:114 +#: ⁨templates/inventory/car_form_qabl alfalsafa.html⁩:83 +#: templates/inventory/car_list.html:106 msgid "model" msgstr "الموديل" -#: templates/inventory/car_detail.html:75 templates/inventory/car_list.html:130 +#: templates/inventory/car_detail.html:92 templates/inventory/car_list.html:139 msgid "series" msgstr "السلسلة" -#: templates/inventory/car_detail.html:79 templates/inventory/car_form.html:94 -#: ⁨templates/inventory/car_form_qabl alfalsafa.html⁩:143 -#: templates/inventory/car_list.html:141 +#: templates/inventory/car_detail.html:96 templates/inventory/car_form.html:101 +#: ⁨templates/inventory/car_form_qabl alfalsafa.html⁩:117 +#: templates/inventory/car_list.html:150 msgid "trim" msgstr "الفئة" -#: templates/inventory/car_detail.html:109 -#: templates/inventory/car_detail.html:485 -#: templates/inventory/car_form.html:118 templates/inventory/car_form.html:228 -#: ⁨templates/inventory/car_form_qabl alfalsafa.html⁩:252 -#: ⁨templates/inventory/car_form_qabl alfalsafa.html⁩:279 -#: ⁨templates/inventory/car_form_qabl alfalsafa.html⁩:299 -#: templates/inventory/car_list.html:47 templates/inventory/car_list.html:221 +#: templates/inventory/car_detail.html:126 +#: templates/inventory/car_detail.html:536 +#: templates/inventory/car_form.html:125 templates/inventory/car_form.html:228 +#: ⁨templates/inventory/car_form_qabl alfalsafa.html⁩:196 +#: ⁨templates/inventory/car_form_qabl alfalsafa.html⁩:225 +#: ⁨templates/inventory/car_form_qabl alfalsafa.html⁩:248 +#: templates/inventory/car_list.html:48 templates/inventory/car_list.html:234 msgid "specifications" msgstr "المواصفات" -#: templates/inventory/car_detail.html:162 -#: templates/inventory/car_inventory.html:92 +#: templates/inventory/car_detail.html:185 +#: templates/inventory/car_inventory.html:124 msgid "Our Showroom" msgstr "معرضنا" -#: templates/inventory/car_detail.html:166 +#: templates/inventory/car_detail.html:194 msgid "No location available." msgstr "لا يوجد موقع متاح." -#: templates/inventory/car_detail.html:181 +#: templates/inventory/car_detail.html:210 msgid "Sell to another dealer" msgstr "بيع السيارة لمعرض آخر" -#: templates/inventory/car_detail.html:185 -#: templates/inventory/car_detail.html:240 +#: templates/inventory/car_detail.html:214 +#: templates/inventory/car_detail.html:267 msgid "Cannot Edit, Car in Transfer." msgstr "لا يمكن التعديل، السيارة قيد النقل." -#: templates/inventory/car_detail.html:193 +#: templates/inventory/car_detail.html:222 msgid "Financial Details" msgstr "التفاصيل المالية" -#: templates/inventory/car_detail.html:214 +#: templates/inventory/car_detail.html:242 msgid "Additional Fee" msgstr "رسوم إضافية" -#: templates/inventory/car_detail.html:226 +#: templates/inventory/car_detail.html:254 #: templates/plans/invoices/layout.html:111 msgid "VAT Amount" msgstr "مبلغ ضريبة القيمة المضافة" -#: templates/inventory/car_detail.html:243 +#: templates/inventory/car_detail.html:270 msgid "No finance details available." msgstr "لا توجد تفاصيل مالية متاحة." -#: templates/inventory/car_detail.html:257 +#: templates/inventory/car_detail.html:283 msgid "Colors Details" msgstr "تفاصيل الألوان" -#: templates/inventory/car_detail.html:264 +#: templates/inventory/car_detail.html:289 msgid "Exterior" msgstr "الخارجي" -#: templates/inventory/car_detail.html:273 +#: templates/inventory/car_detail.html:299 msgid "Interior" msgstr "الداخلي" -#: templates/inventory/car_detail.html:285 +#: templates/inventory/car_detail.html:310 msgid "No colors available for this car." msgstr "لا تتوفر ألوان لهذه السيارة." -#: templates/inventory/car_detail.html:304 +#: templates/inventory/car_detail.html:327 msgid "Reservations Details" msgstr "تفاصيل الحجز" -#: templates/inventory/car_detail.html:312 +#: templates/inventory/car_detail.html:335 msgid "Expires At" msgstr "ينتهي في" -#: templates/inventory/car_detail.html:313 -#: templates/ledger/coa_accounts/account_detail.html:69 -#: templates/representatives/representative_list.html:20 -#: templates/sales/estimates/estimate_list.html:19 -#: templates/sales/invoices/invoice_list.html:20 -#: templates/sales/journals/journal_list.html:20 -#: templates/sales/payments/payment_list.html:24 -#: venv/lib/python3.11/site-packages/django_ledger/templates/django_ledger/account/tags/account_txs_table.html:29 -#: venv/lib/python3.11/site-packages/django_ledger/templates/django_ledger/account/tags/accounts_table.html:30 -#: venv/lib/python3.11/site-packages/django_ledger/templates/django_ledger/account/tags/accounts_table.html:93 -#: venv/lib/python3.11/site-packages/django_ledger/templates/django_ledger/bank_account/tags/bank_accounts_table.html:39 -#: venv/lib/python3.11/site-packages/django_ledger/templates/django_ledger/bills/tags/bill_table.html:16 -#: venv/lib/python3.11/site-packages/django_ledger/templates/django_ledger/closing_entry/tags/closing_entry_table.html:13 -#: venv/lib/python3.11/site-packages/django_ledger/templates/django_ledger/closing_entry/tags/closing_entry_table.html:36 -#: venv/lib/python3.11/site-packages/django_ledger/templates/django_ledger/customer/tags/customer_table.html:13 -#: venv/lib/python3.11/site-packages/django_ledger/templates/django_ledger/data_import/tags/data_import_job_list_table.html:38 -#: venv/lib/python3.11/site-packages/django_ledger/templates/django_ledger/estimate/includes/estimate_table.html:16 -#: venv/lib/python3.11/site-packages/django_ledger/templates/django_ledger/estimate/includes/estimate_table.html:38 -#: venv/lib/python3.11/site-packages/django_ledger/templates/django_ledger/expense/tags/expense_item_table.html:13 -#: venv/lib/python3.11/site-packages/django_ledger/templates/django_ledger/financial_statements/tags/balance_sheet_statement.html:27 -#: venv/lib/python3.11/site-packages/django_ledger/templates/django_ledger/financial_statements/tags/balance_sheet_statement.html:57 -#: venv/lib/python3.11/site-packages/django_ledger/templates/django_ledger/financial_statements/tags/income_statement.html:15 -#: venv/lib/python3.11/site-packages/django_ledger/templates/django_ledger/financial_statements/tags/income_statement.html:51 -#: venv/lib/python3.11/site-packages/django_ledger/templates/django_ledger/financial_statements/tags/income_statement.html:112 -#: venv/lib/python3.11/site-packages/django_ledger/templates/django_ledger/financial_statements/tags/income_statement.html:186 -#: venv/lib/python3.11/site-packages/django_ledger/templates/django_ledger/financial_statements/tags/income_statement.html:260 -#: venv/lib/python3.11/site-packages/django_ledger/templates/django_ledger/financial_statements/tags/income_statement.html:321 -#: venv/lib/python3.11/site-packages/django_ledger/templates/django_ledger/invoice/tags/invoice_table.html:39 -#: venv/lib/python3.11/site-packages/django_ledger/templates/django_ledger/journal_entry/tags/je_table.html:16 -#: venv/lib/python3.11/site-packages/django_ledger/templates/django_ledger/ledger/tags/ledgers_table.html:16 -#: venv/lib/python3.11/site-packages/django_ledger/templates/django_ledger/ledger/tags/ledgers_table.html:95 -#: venv/lib/python3.11/site-packages/django_ledger/templates/django_ledger/product/tags/product_table.html:15 -#: venv/lib/python3.11/site-packages/django_ledger/templates/django_ledger/service/tags/services_table.html:15 -#: venv/lib/python3.11/site-packages/django_ledger/templates/django_ledger/uom/tags/uom_table.html:11 -#: venv/lib/python3.11/site-packages/django_ledger/templates/django_ledger/uom/tags/uom_table.html:33 -#: venv/lib/python3.11/site-packages/django_ledger/templates/django_ledger/vendor/tags/vendor_table.html:14 -msgid "Actions" -msgstr "الإجراءات" - -#: templates/inventory/car_detail.html:346 -#: templates/inventory/reserve_car.html:29 +#: templates/inventory/car_detail.html:377 +#: templates/inventory/reserve_car.html:22 msgid "Reserve" msgstr "حجز" -#: templates/inventory/car_detail.html:361 -#: templates/inventory/transfer_details.html:57 +#: templates/inventory/car_detail.html:392 +#: templates/inventory/transfer_details.html:70 msgid "Transfer Details" msgstr "تفاصيل النقل" -#: templates/inventory/car_detail.html:369 +#: templates/inventory/car_detail.html:400 msgid "From Showroom" msgstr "من صالة العرض" -#: templates/inventory/car_detail.html:370 +#: templates/inventory/car_detail.html:401 msgid "To Showroom" msgstr "إلى صالة العرض" -#: templates/inventory/car_detail.html:455 +#: templates/inventory/car_detail.html:505 msgid "Are you sure you want to reserve this car?" msgstr "هل أنت متأكد أنك تريد حجز هذه السيارة؟" -#: templates/inventory/car_detail.html:599 -#: templates/inventory/car_list.html:542 +#: templates/inventory/car_detail.html:651 +#: templates/inventory/car_list.html:548 #: templates/partials/specifications_modal.html:11 msgid "No specifications available." msgstr "لا توجد مواصفات متاحة." -#: templates/inventory/car_detail.html:603 -#: templates/inventory/car_list.html:546 +#: templates/inventory/car_detail.html:655 +#: templates/inventory/car_list.html:552 msgid "Error loading specifications." msgstr "حدث خطأ أثناء تحميل المواصفات." -#: templates/inventory/car_edit.html:1 templates/inventory/car_edit.html:4 +#: templates/inventory/car_edit.html:6 templates/inventory/car_edit.html:11 msgid "Edit Car" msgstr "تعديل السيارة" -#: templates/inventory/car_edit.html:10 +#: templates/inventory/car_edit.html:17 #: templates/two_factor/_wizard_actions.html:10 #: templates/two_factor/_wizard_actions.html:12 #: venv/lib/python3.11/site-packages/django_ledger/templates/django_ledger/bank_account/bank_account_create.html:25 @@ -5481,193 +5759,174 @@ msgstr "عودة" msgid "Car Finance Details" msgstr "التفاصيل المالية السيارة" -#: templates/inventory/car_finance_form.html:10 +#: templates/inventory/car_finance_form.html:11 msgid "Finance Details for" msgstr "التفاصيل المالية لـ" -#: templates/inventory/car_form.html:22 +#: templates/inventory/car_form.html:23 msgid "Please Add A Vendor, Before Adding A Car ." msgstr "يرجى إضافة مورد قبل إضافة السيارة." -#: templates/inventory/car_form.html:73 templates/inventory/car_form.html:92 -#: templates/inventory/car_form.html:105 templates/inventory/car_form.html:269 -#: templates/inventory/car_form.html:454 templates/inventory/car_form.html:471 -#: templates/inventory/car_form.html:472 templates/inventory/car_form.html:494 -#: templates/inventory/car_form.html:513 -#: ⁨templates/inventory/car_form_qabl alfalsafa.html⁩:105 -#: ⁨templates/inventory/car_form_qabl alfalsafa.html⁩:126 -#: ⁨templates/inventory/car_form_qabl alfalsafa.html⁩:148 -#: ⁨templates/inventory/car_form_qabl alfalsafa.html⁩:313 -#: ⁨templates/inventory/car_form_qabl alfalsafa.html⁩:497 -#: ⁨templates/inventory/car_form_qabl alfalsafa.html⁩:514 -#: ⁨templates/inventory/car_form_qabl alfalsafa.html⁩:515 -#: ⁨templates/inventory/car_form_qabl alfalsafa.html⁩:535 -#: ⁨templates/inventory/car_form_qabl alfalsafa.html⁩:554 +#: templates/inventory/car_form.html:80 templates/inventory/car_form.html:99 +#: templates/inventory/car_form.html:112 templates/inventory/car_form.html:268 +#: templates/inventory/car_form.html:457 templates/inventory/car_form.html:474 +#: templates/inventory/car_form.html:475 templates/inventory/car_form.html:497 +#: templates/inventory/car_form.html:516 +#: ⁨templates/inventory/car_form_qabl alfalsafa.html⁩:88 +#: ⁨templates/inventory/car_form_qabl alfalsafa.html⁩:104 +#: ⁨templates/inventory/car_form_qabl alfalsafa.html⁩:121 +#: ⁨templates/inventory/car_form_qabl alfalsafa.html⁩:262 +#: ⁨templates/inventory/car_form_qabl alfalsafa.html⁩:451 +#: ⁨templates/inventory/car_form_qabl alfalsafa.html⁩:468 +#: ⁨templates/inventory/car_form_qabl alfalsafa.html⁩:469 +#: ⁨templates/inventory/car_form_qabl alfalsafa.html⁩:489 +#: ⁨templates/inventory/car_form_qabl alfalsafa.html⁩:508 #: templates/plans/plan_table.html:120 msgid "Select" msgstr "اختيار" -#: templates/inventory/car_form.html:125 -#: ⁨templates/inventory/car_form_qabl alfalsafa.html⁩:259 -#: templates/inventory/car_list.html:27 templates/inventory/car_list.html:214 +#: templates/inventory/car_form.html:131 +#: ⁨templates/inventory/car_form_qabl alfalsafa.html⁩:202 +#: templates/inventory/car_list.html:25 templates/inventory/car_list.html:228 msgid "options" msgstr "الخيارات" -#: templates/inventory/car_form.html:205 -#: ⁨templates/inventory/car_form_qabl alfalsafa.html⁩:262 +#: templates/inventory/car_form.html:203 +#: ⁨templates/inventory/car_form_qabl alfalsafa.html⁩:206 msgid "Save and Add Another" msgstr "حفظ وإضافة آخر" -#: templates/inventory/car_form.html:208 -#: ⁨templates/inventory/car_form_qabl alfalsafa.html⁩:265 +#: templates/inventory/car_form.html:209 +#: ⁨templates/inventory/car_form_qabl alfalsafa.html⁩:210 msgid "Save and Go to Inventory" msgstr "حفظ والانتقال إلى المخزون" -#: templates/inventory/car_form.html:238 templates/inventory/car_form.html:257 -#: templates/inventory/car_form.html:277 templates/inventory/car_form.html:289 -#: ⁨templates/inventory/car_form_qabl alfalsafa.html⁩:281 -#: ⁨templates/inventory/car_form_qabl alfalsafa.html⁩:287 -#: ⁨templates/inventory/car_form_qabl alfalsafa.html⁩:301 -#: ⁨templates/inventory/car_form_qabl alfalsafa.html⁩:321 -#: ⁨templates/inventory/car_form_qabl alfalsafa.html⁩:333 -#: templates/modal/confirm_modal.html:11 templates/modal/confirm_modal.html:20 -#: templates/modal/error_modal.html:17 -#: templates/modal/event_details_modal.html:21 -#: templates/partials/scanner_modal.html:6 -#: templates/partials/specifications_modal.html:8 -#: venv/lib/python3.11/site-packages/appointment/templates/modal/confirm_modal.html:18 -#: venv/lib/python3.11/site-packages/appointment/templates/modal/error_modal.html:17 -#: venv/lib/python3.11/site-packages/appointment/templates/modal/event_details_modal.html:19 -msgid "Close" -msgstr "إغلاق" - -#: templates/inventory/car_form.html:255 -#: venv/lib/python3.11/site-packages/click/core.py:1396 +#: templates/inventory/car_form.html:254 +#: venv/lib/python3.11/site-packages/click/core.py:1140 msgid "Options" msgstr "الخيارات" #: templates/inventory/car_form.html:264 -#: ⁨templates/inventory/car_form_qabl alfalsafa.html⁩:308 -#: templates/inventory/car_list.html:152 +#: ⁨templates/inventory/car_form_qabl alfalsafa.html⁩:258 +#: templates/inventory/car_list.html:161 msgid "equipment" msgstr "التجهيزات" -#: templates/inventory/car_form.html:288 -#: ⁨templates/inventory/car_form_qabl alfalsafa.html⁩:332 +#: templates/inventory/car_form.html:289 +#: ⁨templates/inventory/car_form_qabl alfalsafa.html⁩:283 msgid "scanner" msgstr "الماسح الضوئي" -#: templates/inventory/car_form.html:293 -#: ⁨templates/inventory/car_form_qabl alfalsafa.html⁩:337 +#: templates/inventory/car_form.html:298 +#: ⁨templates/inventory/car_form_qabl alfalsafa.html⁩:292 #: templates/partials/scanner_modal.html:10 msgid "VIN will appear here." msgstr "رقم الهيكل سيظهر هنا." -#: templates/inventory/car_form.html:294 -#: ⁨templates/inventory/car_form_qabl alfalsafa.html⁩:338 +#: templates/inventory/car_form.html:299 +#: ⁨templates/inventory/car_form_qabl alfalsafa.html⁩:293 #: templates/partials/scanner_modal.html:11 msgid "Use OCR Fallback" msgstr "التعرف الآلي على الحروف" -#: templates/inventory/car_form.html:365 templates/inventory/car_form.html:366 -#: ⁨templates/inventory/car_form_qabl alfalsafa.html⁩:409 -#: ⁨templates/inventory/car_form_qabl alfalsafa.html⁩:410 +#: templates/inventory/car_form.html:368 templates/inventory/car_form.html:369 +#: ⁨templates/inventory/car_form_qabl alfalsafa.html⁩:363 +#: ⁨templates/inventory/car_form_qabl alfalsafa.html⁩:364 msgid "Please enter a valid VIN." msgstr "الرجاء إدخال رقم هيكل صالح مكون من 17 حرفًا." -#: templates/inventory/car_form.html:388 -#: ⁨templates/inventory/car_form_qabl alfalsafa.html⁩:432 +#: templates/inventory/car_form.html:391 +#: ⁨templates/inventory/car_form_qabl alfalsafa.html⁩:386 msgid "An error occurred while decoding the VIN." msgstr "حدث خطأ أثناء فك تشفير الهيكل" #: ⁨templates/inventory/car_form_qabl alfalsafa.html⁩:45 -#: templates/inventory/car_list_view.html:93 -#: templates/inventory/scan_vin.html:15 templates/partials/search_box.html:4 +#: templates/inventory/car_list_view.html:144 +#: templates/inventory/scan_vin.html:13 templates/partials/search_box.html:4 #: templates/representatives/representative_list.html:9 #: templates/representatives/representative_list.html:10 #: templates/sales/sales_list.html:50 msgid "Search" msgstr "بحث" -#: templates/inventory/car_history.html:17 +#: templates/inventory/car_history.html:24 msgid "History" msgstr "التاريخ" -#: templates/inventory/car_inventory.html:57 +#: templates/inventory/car_inventory.html:76 msgid "Showroom Location" msgstr "موقع صالة العرض" -#: templates/inventory/car_inventory.html:87 -#: templates/inventory/car_inventory.html:88 +#: templates/inventory/car_inventory.html:116 +#: templates/inventory/car_inventory.html:119 msgid "No Color" msgstr "بدون لون" -#: templates/inventory/car_inventory.html:120 +#: templates/inventory/car_inventory.html:156 msgid "No cars available." msgstr "لا توجد سيارات متاحة." -#: templates/inventory/car_inventory.html:121 +#: templates/inventory/car_inventory.html:157 msgid "Add a Car" msgstr "إضافة سيارة" -#: templates/inventory/car_list.html:70 -#: templates/ledger/bills/bill_list.html:27 -#: templates/ledger/coa_accounts/account_list.html:25 +#: templates/inventory/car_list.html:79 +#: templates/ledger/bills/bill_list.html:26 msgid "search" msgstr "بحث" -#: templates/inventory/car_list.html:81 templates/inventory/car_list.html:99 -#: templates/inventory/car_list.html:110 templates/inventory/car_list.html:121 -#: templates/inventory/car_list.html:132 templates/inventory/car_list.html:143 -#: templates/inventory/car_list.html:154 templates/inventory/car_list.html:165 -#: templates/inventory/car_list.html:179 templates/inventory/car_list.html:273 -#: templates/inventory/car_list.html:274 templates/inventory/car_list.html:275 -#: templates/inventory/car_list.html:276 templates/inventory/car_list.html:277 -#: templates/inventory/car_list.html:278 templates/inventory/car_list.html:378 -#: templates/inventory/car_list.html:379 templates/inventory/car_list.html:380 -#: templates/inventory/car_list.html:381 templates/inventory/car_list.html:382 -#: templates/inventory/car_list.html:407 templates/inventory/car_list.html:408 -#: templates/inventory/car_list.html:409 templates/inventory/car_list.html:410 -#: templates/inventory/car_list.html:436 templates/inventory/car_list.html:437 -#: templates/inventory/car_list.html:438 templates/inventory/car_list.html:463 -#: templates/inventory/car_list.html:464 templates/inventory/car_list.html:488 +#: templates/inventory/car_list.html:90 templates/inventory/car_list.html:108 +#: templates/inventory/car_list.html:119 templates/inventory/car_list.html:130 +#: templates/inventory/car_list.html:141 templates/inventory/car_list.html:152 +#: templates/inventory/car_list.html:163 templates/inventory/car_list.html:174 +#: templates/inventory/car_list.html:186 templates/inventory/car_list.html:279 +#: templates/inventory/car_list.html:280 templates/inventory/car_list.html:281 +#: templates/inventory/car_list.html:282 templates/inventory/car_list.html:283 +#: templates/inventory/car_list.html:284 templates/inventory/car_list.html:384 +#: templates/inventory/car_list.html:385 templates/inventory/car_list.html:386 +#: templates/inventory/car_list.html:387 templates/inventory/car_list.html:388 +#: templates/inventory/car_list.html:413 templates/inventory/car_list.html:414 +#: templates/inventory/car_list.html:415 templates/inventory/car_list.html:416 +#: templates/inventory/car_list.html:442 templates/inventory/car_list.html:443 +#: templates/inventory/car_list.html:444 templates/inventory/car_list.html:469 +#: templates/inventory/car_list.html:470 templates/inventory/car_list.html:494 msgid "select" msgstr "اختيار" -#: templates/inventory/car_list.html:108 +#: templates/inventory/car_list.html:117 msgid "generation" msgstr "الجيل" -#: templates/inventory/car_list.html:201 +#: templates/inventory/car_list.html:215 msgid "Enter remarks" msgstr "أدخل الملاحظات" -#: templates/inventory/car_list.html:225 +#: templates/inventory/car_list.html:235 msgid "save" msgstr "حفظ" -#: templates/inventory/car_list.html:345 +#: templates/inventory/car_list.html:351 msgid "Make not found for the decoded VIN." msgstr "لم يتم العثور على الشركة الصانعة الخاصة برقم الهيكل المدخل." -#: templates/inventory/car_list.html:353 +#: templates/inventory/car_list.html:359 msgid "Please enter a valid 17-character VIN number." msgstr "الرجاء إدخال رقم هيكل صالح مكون من 17 حرفًا." -#: templates/inventory/car_list.html:587 +#: templates/inventory/car_list.html:593 msgid "No options available." msgstr "لا توجد سيارات متاحة." -#: templates/inventory/car_list.html:591 +#: templates/inventory/car_list.html:597 msgid "Error loading options." msgstr "خطأ في تحميل الخيارات." -#: templates/inventory/car_list_table.html:13 +#: templates/inventory/car_list_table.html:10 msgid "Excel" msgstr "إكسل" -#: templates/inventory/car_list_view.html:37 -#: templates/inventory/car_list_view.html:85 +#: templates/inventory/car_list_view.html:41 +#: templates/inventory/car_list_view.html:129 #: venv/lib/python3.11/site-packages/django_ledger/templates/django_ledger/bills/bill_list.html:98 #: venv/lib/python3.11/site-packages/django_ledger/templates/django_ledger/bills/bill_list.html:110 #: venv/lib/python3.11/site-packages/django_ledger/templates/django_ledger/closing_entry/closing_entry_list.html:76 @@ -5685,41 +5944,45 @@ msgstr "إكسل" msgid "All" msgstr "الكل" -#: templates/inventory/car_list_view.html:42 +#: templates/inventory/car_list_view.html:61 msgid "Filter" msgstr "تصفية" #: templates/inventory/car_list_view.html:168 +msgid "Date Received" +msgstr "تاريخ الاستلام" + +#: templates/inventory/car_list_view.html:232 #: templates/sales/sales_list.html:207 msgid "Export" msgstr "تصدير" -#: templates/inventory/car_location_form.html:4 -#: templates/inventory/car_location_form.html:8 +#: templates/inventory/car_location_form.html:5 +#: templates/inventory/car_location_form.html:9 msgid "Manage Car Location" msgstr "إدارة موقع السيارة" -#: templates/inventory/car_transfer_form.html:4 +#: templates/inventory/car_transfer_form.html:5 msgid "Car Transfer" msgstr "نقل السيارة" -#: templates/inventory/car_transfer_form.html:8 +#: templates/inventory/car_transfer_form.html:9 msgid "Sell car to another dealer" msgstr "بيع السيارة لتاجر آخر" -#: templates/inventory/car_transfer_form.html:13 +#: templates/inventory/car_transfer_form.html:14 msgid "Sell" msgstr "بيع" -#: templates/inventory/color_palette.html:74 +#: templates/inventory/color_palette.html:72 msgid "Update Color" msgstr "تحديث اللون" -#: templates/inventory/color_palette.html:77 +#: templates/inventory/color_palette.html:75 msgid "Add Color for" msgstr "إضافة لون الى" -#: templates/inventory/color_palette.html:83 +#: templates/inventory/color_palette.html:81 msgid "Color Type" msgstr "نوع اللون" @@ -5731,137 +5994,137 @@ msgstr "الموديلات" msgid "Trims" msgstr "الفئات" -#: templates/inventory/inventory_stats.html:75 +#: templates/inventory/inventory_stats.html:74 msgid "No trims available" msgstr "لا يوجد فئات متاحة." -#: templates/inventory/inventory_stats.html:81 +#: templates/inventory/inventory_stats.html:80 msgid "No models available." msgstr "لا توجد موديلات متاحة." -#: templates/inventory/reserve_car.html:11 +#: templates/inventory/reserve_car.html:9 msgid "You are reserving" msgstr "أنت تحجز" -#: templates/inventory/reserve_car.html:16 +#: templates/inventory/reserve_car.html:13 msgid "Reservation Start Time" msgstr "وقت بدء الحجز" -#: templates/inventory/reserve_car.html:23 +#: templates/inventory/reserve_car.html:18 msgid "Reservation End Time" msgstr "وقت انتهاء الحجز" -#: templates/inventory/scan_vin.html:6 +#: templates/inventory/scan_vin.html:5 msgid "Scan Vehicle Code" msgstr "مسح رمز السيارة" -#: templates/inventory/scan_vin.html:10 +#: templates/inventory/scan_vin.html:8 msgid "VIN / Barcode / QR Code" msgstr "رمز VIN / الباركود / رمز QR" -#: templates/inventory/scan_vin.html:14 +#: templates/inventory/scan_vin.html:12 msgid "Start Scanning" msgstr "ابدأ المسح" -#: templates/inventory/scan_vin.html:22 +#: templates/inventory/scan_vin.html:20 msgid "Switch Camera" msgstr "تبديل الكاميرا" -#: templates/inventory/scan_vin.html:23 +#: templates/inventory/scan_vin.html:21 msgid "Scan" msgstr "مسح" -#: templates/inventory/transfer_car.html:6 +#: templates/inventory/transfer_car.html:7 msgid "transfer car" msgstr "نقل السيارة" -#: templates/inventory/transfer_details.html:8 +#: templates/inventory/transfer_details.html:7 msgid "Car Transfer Details" msgstr "تفاصيل نقل السيارة" -#: templates/inventory/transfer_details.html:17 +#: templates/inventory/transfer_details.html:19 msgid "Car Transfer Approve" msgstr "الموافقة على نقل السيارة" -#: templates/inventory/transfer_details.html:21 +#: templates/inventory/transfer_details.html:25 #: templates/two_factor/profile/profile.html:21 msgid "Are you sure?" msgstr "هل أنت متأكد؟" -#: templates/inventory/transfer_details.html:38 -#: templates/inventory/transfer_details.html:109 +#: templates/inventory/transfer_details.html:49 +#: templates/inventory/transfer_details.html:135 msgid "Cancel Transfer" msgstr "إلغاء النقل" -#: templates/inventory/transfer_details.html:42 +#: templates/inventory/transfer_details.html:55 #: templates/ledger/bills/bill_detail.html:15 #: templates/ledger/bills/bill_detail.html:40 msgid "Are you sure" msgstr "هل أنت متأكد" -#: templates/inventory/transfer_details.html:60 -#: templates/inventory/transfer_preview.html:220 +#: templates/inventory/transfer_details.html:76 +#: templates/inventory/transfer_preview.html:274 msgid "From" msgstr "من" -#: templates/inventory/transfer_details.html:73 +#: templates/inventory/transfer_details.html:90 #: templates/plans/invoices/layout.html:110 -#: templates/plans/order_detail_table.html:10 templates/pricing_page.html:181 +#: templates/plans/order_detail_table.html:10 templates/pricing_page.html:180 #: templates/sales/estimates/sale_order_preview.html:205 #: templates/sales/invoices/invoice_detail.html:267 msgid "VAT" msgstr "ضريبة القيمة المضافة" -#: templates/inventory/transfer_details.html:92 -#: templates/inventory/transfer_preview.html:249 +#: templates/inventory/transfer_details.html:114 +#: templates/inventory/transfer_preview.html:304 #: templates/sales/estimates/sale_order_form.html:98 #: templates/sales/estimates/sale_order_preview.html:216 msgid "Total Amount" msgstr "المبلغ الإجمالي" -#: templates/inventory/transfer_details.html:93 +#: templates/inventory/transfer_details.html:117 msgid "Total Amount written" msgstr "المبلغ بالحروف" -#: templates/inventory/transfer_details.html:93 +#: templates/inventory/transfer_details.html:117 msgid "only" msgstr "فقط لا غير" -#: templates/inventory/transfer_details.html:105 +#: templates/inventory/transfer_details.html:130 #: templates/ledger/journal_entry/includes/card_invoice.html:116 #: venv/lib/python3.11/site-packages/django_ledger/templates/django_ledger/estimate/includes/card_estimate.html:80 #: venv/lib/python3.11/site-packages/django_ledger/templates/django_ledger/invoice/includes/card_invoice.html:161 msgid "Approve" msgstr "الموافقة" -#: templates/inventory/transfer_preview.html:159 +#: templates/inventory/transfer_preview.html:190 msgid "Download transfer" msgstr "تحميل النقل" -#: templates/inventory/transfer_preview.html:162 -#: templates/inventory/transfer_preview.html:174 +#: templates/inventory/transfer_preview.html:196 +#: templates/inventory/transfer_preview.html:214 msgid "Accept transfer" msgstr "قبول النقل" -#: templates/inventory/transfer_preview.html:165 -#: templates/inventory/transfer_preview.html:193 +#: templates/inventory/transfer_preview.html:202 +#: templates/inventory/transfer_preview.html:238 msgid "Reject transfer" msgstr "رفض النقل" -#: templates/inventory/transfer_preview.html:178 +#: templates/inventory/transfer_preview.html:220 msgid "Are you sure you want to accept this transfer?" msgstr "هل أنت متأكد أنك تريد قبول هذا النقل؟" -#: templates/inventory/transfer_preview.html:197 +#: templates/inventory/transfer_preview.html:244 msgid "Are you sure you want to reject this transfer?" msgstr "هل أنت متأكد أنك تريد رفض هذا النقل؟" -#: templates/inventory/transfer_preview.html:214 +#: templates/inventory/transfer_preview.html:266 #: templates/sales/estimates/sale_order_preview.html:160 msgid "Thank you for choosing us. We appreciate your business" msgstr "شكرًا لاختيارك لنا. نحن نقدر عملك معنا." -#: templates/inventory/transfer_preview.html:231 +#: templates/inventory/transfer_preview.html:287 #: templates/ledger/bills/bill_detail.html:215 #: templates/plans/invoices/layout.html:103 #: templates/sales/estimates/estimate_detail.html:196 @@ -5871,19 +6134,19 @@ msgstr "شكرًا لاختيارك لنا. نحن نقدر عملك معنا." msgid "Unit Price" msgstr "سعر الوحدة" -#: templates/inventory/transfer_preview.html:254 +#: templates/inventory/transfer_preview.html:310 #: templates/sales/estimates/sale_order_preview.html:221 msgid "If you have any questions, feel free to contact us at" msgstr "إذا كان لديك أي أسئلة، يرجى التواصل معنا على" -#: templates/inventory/transfer_preview.html:255 +#: templates/inventory/transfer_preview.html:312 #: templates/plans/invoices/layout.html:195 #: templates/sales/estimates/sale_order_preview.html:222 msgid "Thank you for your business" msgstr "شكراً لتعاملك معنا" #: templates/items/expenses/expense_create.html:11 -#: templates/items/expenses/expenses_list.html:11 +#: templates/items/expenses/expenses_list.html:12 msgid "Add Expense" msgstr "إضافة مصروف" @@ -5891,7 +6154,7 @@ msgstr "إضافة مصروف" msgid "Update Expense" msgstr "تحديث المصروف" -#: templates/items/expenses/expenses_list.html:19 +#: templates/items/expenses/expenses_list.html:20 #: templates/items/service/service_list.html:19 #: venv/lib/python3.11/site-packages/django_ledger/models/items.py:530 #: venv/lib/python3.11/site-packages/django_ledger/templates/django_ledger/product/tags/product_table.html:9 @@ -5899,17 +6162,19 @@ msgstr "تحديث المصروف" msgid "Item Number" msgstr "رقم العنصر" -#: templates/items/expenses/expenses_list.html:21 +#: templates/items/expenses/expenses_list.html:22 #: templates/items/service/service_list.html:21 #: venv/lib/python3.11/site-packages/django_ledger/models/items.py:535 msgid "Unit of Measure" msgstr "وحدة القياس" -#: templates/items/expenses/expenses_list.html:40 -#: templates/items/service/service_list.html:50 -#: templates/sales/invoices/invoice_list.html:67 -msgid "No Invoice Found" -msgstr "لم يتم العثور على فاتورة" +#: templates/items/expenses/expenses_list.html:58 +#: templates/items/service/service_list.html:63 +#: templates/ledger/bank_accounts/bank_account_list.html:48 +#: templates/ledger/coa_accounts/account_list.html:107 +#: templates/vendors/vendors_list.html:138 +msgid "No Accounts Found" +msgstr "لم يتم العثور على أي حسابات" #: templates/items/service/service_create.html:13 #: venv/lib/python3.11/site-packages/appointment/views_admin.py:472 @@ -5956,16 +6221,16 @@ msgstr "حساب نقدي" msgid "bank account" msgstr "الحساب المصرفي" -#: templates/ledger/bank_accounts/bank_account_form.html:14 +#: templates/ledger/bank_accounts/bank_account_form.html:15 msgid "Edit Bank Account" msgstr "تحديث الحساب المصرفي" -#: templates/ledger/bank_accounts/bank_account_form.html:17 +#: templates/ledger/bank_accounts/bank_account_form.html:18 #: templates/ledger/bank_accounts/bank_account_list.html:11 msgid "Add Bank Account" msgstr "إضافة حساب بنكي" -#: templates/ledger/bank_accounts/bank_account_list.html:19 +#: templates/ledger/bank_accounts/bank_account_list.html:20 #: templates/ledger/reports/tags/income_statement.html:8 #: venv/lib/python3.11/site-packages/django_ledger/forms/bank_account.py:87 #: venv/lib/python3.11/site-packages/django_ledger/models/mixins.py:1148 @@ -5973,12 +6238,6 @@ msgstr "إضافة حساب بنكي" msgid "Account Number" msgstr "رقم الحساب" -#: templates/ledger/bank_accounts/bank_account_list.html:39 -#: templates/ledger/journal_entry/journal_entry_list.html:124 -#: templates/ledger/ledger/ledger_list.html:116 -msgid "No Bank Accounts Found" -msgstr "لم يتم العثور على أي حساب بنكي." - #: templates/ledger/bills/bill_detail.html:4 #: venv/lib/python3.11/site-packages/django_ledger/templates/django_ledger/purchase_order/includes/po_item_formset.html:61 msgid "View Bill" @@ -6044,7 +6303,7 @@ msgid "Due Amount" msgstr "المبلغ الكلي" #: templates/ledger/bills/bill_detail.html:158 -#: templates/ledger/bills/bill_list.html:45 +#: templates/ledger/bills/bill_list.html:50 #: venv/lib/python3.11/site-packages/django_ledger/models/bill.py:356 msgid "Bill Number" msgstr "رقم الفاتورة" @@ -6105,6 +6364,7 @@ msgstr "إنشاء فاتورة" #: templates/ledger/bills/bill_list.html:4 #: templates/ledger/bills/bill_list.html:8 +#: templates/ledger/bills/bill_list.html:16 #: venv/lib/python3.11/site-packages/django_ledger/models/bill.py:393 #: venv/lib/python3.11/site-packages/django_ledger/templates/django_ledger/estimate/estimate_detail.html:84 msgid "Bills" @@ -6115,26 +6375,24 @@ msgstr "الفواتير" msgid "New Bill" msgstr "فاتورة جديدة" -#: templates/ledger/bills/bill_list.html:28 +#: templates/ledger/bills/bill_list.html:32 msgid "Search bills..." msgstr "ابحث عن الفواتير ..." -#: templates/ledger/bills/bill_list.html:48 +#: templates/ledger/bills/bill_list.html:51 #: venv/lib/python3.11/site-packages/django_ledger/models/bill.py:360 msgid "Bill Status" msgstr "حالة الفاتورة" -#: templates/ledger/bills/bill_list.html:88 +#: templates/ledger/bills/bill_list.html:92 msgid "No bill found." msgstr "لم يتم العثور على فاتورة." -#: templates/ledger/bills/bill_list.html:97 -#: templates/ledger/coa_accounts/account_list.html:136 +#: templates/ledger/bills/bill_list.html:99 msgid "to" msgstr "إلى" -#: templates/ledger/bills/bill_list.html:97 -#: templates/ledger/coa_accounts/account_list.html:136 +#: templates/ledger/bills/bill_list.html:99 msgid "Items of" msgstr "عناصر" @@ -6147,7 +6405,7 @@ msgid "Are you sure you want to delete this account?" msgstr "هل أنت متأكد أنك تريد حذف هذا الحساب؟" #: templates/ledger/coa_accounts/account_detail.html:39 -#: templates/ledger/coa_accounts/account_list.html:49 +#: templates/ledger/coa_accounts/account_list.html:25 #: templates/ledger/journal_entry/journal_entry_transactions.html:19 #: templates/ledger/reports/tags/balance_sheet_statement.html:14 #: templates/sales/payments/payment_details.html:16 @@ -6173,7 +6431,7 @@ msgstr "رمز الحساب" #: templates/ledger/coa_accounts/account_detail.html:48 #: templates/ledger/coa_accounts/account_detail.html:50 -#: templates/ledger/coa_accounts/account_list.html:51 +#: templates/ledger/coa_accounts/account_list.html:27 #: templates/ledger/reports/tags/balance_sheet_statement.html:18 #: templates/ledger/reports/tags/income_statement.html:13 #: venv/lib/python3.11/site-packages/django_ledger/templates/django_ledger/account/tags/accounts_table.html:26 @@ -6183,12 +6441,12 @@ msgid "Balance Type" msgstr "نوع الرصيد" #: templates/ledger/coa_accounts/account_detail.html:48 -#: templates/ledger/coa_accounts/account_detail.html:65 -#: templates/ledger/coa_accounts/account_list.html:101 +#: templates/ledger/coa_accounts/account_detail.html:68 +#: templates/ledger/coa_accounts/account_list.html:82 #: templates/ledger/journal_entry/journal_entry_transactions.html:21 #: templates/sales/payments/payment_details.html:18 #: venv/lib/python3.11/site-packages/django_ledger/models/accounts.py:423 -#: venv/lib/python3.11/site-packages/django_ledger/models/transactions.py:424 +#: venv/lib/python3.11/site-packages/django_ledger/models/transactions.py:448 #: venv/lib/python3.11/site-packages/django_ledger/templates/django_ledger/journal_entry/tags/je_txs_table.html:13 #: venv/lib/python3.11/site-packages/django_ledger/templates/django_ledger/journal_entry/tags/je_txs_table.html:48 #: venv/lib/python3.11/site-packages/django_ledger/templates/django_ledger/transactions/tags/txs_table.html:13 @@ -6197,12 +6455,12 @@ msgid "Debit" msgstr "مدين" #: templates/ledger/coa_accounts/account_detail.html:50 -#: templates/ledger/coa_accounts/account_detail.html:66 -#: templates/ledger/coa_accounts/account_list.html:103 +#: templates/ledger/coa_accounts/account_detail.html:69 +#: templates/ledger/coa_accounts/account_list.html:84 #: templates/ledger/journal_entry/journal_entry_transactions.html:22 #: templates/sales/payments/payment_details.html:19 #: venv/lib/python3.11/site-packages/django_ledger/models/accounts.py:422 -#: venv/lib/python3.11/site-packages/django_ledger/models/transactions.py:423 +#: venv/lib/python3.11/site-packages/django_ledger/models/transactions.py:447 #: venv/lib/python3.11/site-packages/django_ledger/templates/django_ledger/journal_entry/tags/je_txs_table.html:12 #: venv/lib/python3.11/site-packages/django_ledger/templates/django_ledger/journal_entry/tags/je_txs_table.html:47 #: venv/lib/python3.11/site-packages/django_ledger/templates/django_ledger/transactions/tags/txs_table.html:12 @@ -6210,7 +6468,7 @@ msgstr "مدين" msgid "Credit" msgstr "دائن" -#: templates/ledger/coa_accounts/account_detail.html:63 +#: templates/ledger/coa_accounts/account_detail.html:66 msgid "JE Number" msgstr "رقم القيد المحاسبي" @@ -6229,32 +6487,24 @@ msgstr "إضافة حساب" #: templates/ledger/coa_accounts/account_list.html:3 #: templates/ledger/coa_accounts/account_list.html:6 -#: templates/ledger/coa_accounts/account_list.html:20 +#: templates/ledger/coa_accounts/account_list.html:14 #: venv/lib/python3.11/site-packages/django_ledger/models/accounts.py:444 #: venv/lib/python3.11/site-packages/django_ledger/templates/django_ledger/chart_of_accounts/includes/coa_card.html:54 msgid "Accounts" msgstr "الحسابات" -#: templates/ledger/coa_accounts/account_list.html:17 +#: templates/ledger/coa_accounts/account_list.html:15 msgid "New Account" msgstr "حساب جديد" -#: templates/ledger/coa_accounts/account_list.html:31 -msgid "Search accounts..." -msgstr "ابحث عن الحسابات..." - -#: templates/ledger/coa_accounts/account_list.html:72 +#: templates/ledger/coa_accounts/account_list.html:46 msgid "Delete Account" msgstr "حذف الحساب" -#: templates/ledger/coa_accounts/account_list.html:79 +#: templates/ledger/coa_accounts/account_list.html:53 msgid "Are you sure you want to delete this Account?" msgstr "هل أنت متأكد أنك تريد حذف هذا الحساب؟" -#: templates/ledger/coa_accounts/account_list.html:128 -msgid "No account found." -msgstr "لم يتم العثور على حساب." - #: templates/ledger/journal_entry/includes/card_invoice.html:15 #: venv/lib/python3.11/site-packages/django_ledger/templates/django_ledger/bills/includes/card_bill.html:16 #: venv/lib/python3.11/site-packages/django_ledger/templates/django_ledger/invoice/includes/card_invoice.html:14 @@ -6291,20 +6541,6 @@ msgstr "هذه الفاتورة هي" msgid "Amount Due" msgstr "المبلغ المستحق" -#: templates/ledger/journal_entry/includes/card_invoice.html:52 -#: templates/ledger/journal_entry/includes/card_invoice.html:63 -#: templates/ledger/journal_entry/includes/card_invoice.html:77 -#: templates/plans/invoices/layout.html:161 -#: venv/lib/python3.11/site-packages/django_ledger/models/mixins.py:976 -#: venv/lib/python3.11/site-packages/django_ledger/templates/django_ledger/bills/includes/card_bill.html:72 -#: venv/lib/python3.11/site-packages/django_ledger/templates/django_ledger/bills/includes/card_bill.html:89 -#: venv/lib/python3.11/site-packages/django_ledger/templates/django_ledger/bills/includes/card_bill.html:110 -#: venv/lib/python3.11/site-packages/django_ledger/templates/django_ledger/invoice/includes/card_invoice.html:63 -#: venv/lib/python3.11/site-packages/django_ledger/templates/django_ledger/invoice/includes/card_invoice.html:80 -#: venv/lib/python3.11/site-packages/django_ledger/templates/django_ledger/invoice/includes/card_invoice.html:101 -msgid "Due Date" -msgstr "تاريخ الاستحقاق" - #: templates/ledger/journal_entry/includes/card_invoice.html:53 #: templates/ledger/journal_entry/includes/card_invoice.html:64 #: templates/ledger/journal_entry/includes/card_invoice.html:78 @@ -6390,7 +6626,7 @@ msgid "Journal Entry Detail" msgstr "تفاصيل إدخال اليومية" #: templates/ledger/journal_entry/includes/card_journal_entry.html:17 -#: templates/ledger/journal_entry/journal_entry_list.html:66 +#: templates/ledger/journal_entry/journal_entry_list.html:52 #: templates/ledger/ledger/ledger_list.html:23 #: venv/lib/python3.11/site-packages/django_ledger/models/journal_entry.py:391 #: venv/lib/python3.11/site-packages/django_ledger/templates/django_ledger/journal_entry/includes/card_journal_entry.html:18 @@ -6400,7 +6636,7 @@ msgid "Posted" msgstr "تم النشر" #: templates/ledger/journal_entry/includes/card_journal_entry.html:24 -#: templates/ledger/journal_entry/journal_entry_list.html:67 +#: templates/ledger/journal_entry/journal_entry_list.html:53 #: templates/ledger/ledger/ledger_list.html:24 #: venv/lib/python3.11/site-packages/django_ledger/models/accounts.py:432 #: venv/lib/python3.11/site-packages/django_ledger/models/journal_entry.py:392 @@ -6413,8 +6649,8 @@ msgstr "مقفل" #: templates/ledger/journal_entry/includes/card_journal_entry.html:42 #: templates/ledger/journal_entry/journal_entry_txs.html:71 -#: templates/ledger/ledger/ledger_list.html:82 -#: venv/lib/python3.11/site-packages/django_ledger/templates/django_ledger/account/tags/accounts_table.html:113 +#: templates/ledger/ledger/ledger_list.html:84 +#: venv/lib/python3.11/site-packages/django_ledger/templates/django_ledger/account/tags/accounts_table.html:109 #: venv/lib/python3.11/site-packages/django_ledger/templates/django_ledger/journal_entry/includes/card_journal_entry.html:43 #: venv/lib/python3.11/site-packages/django_ledger/templates/django_ledger/journal_entry/je_detail_txs.html:64 #: venv/lib/python3.11/site-packages/django_ledger/templates/django_ledger/journal_entry/tags/je_table.html:76 @@ -6424,7 +6660,7 @@ msgstr "قفل" #: templates/ledger/journal_entry/includes/card_journal_entry.html:46 #: templates/ledger/journal_entry/journal_entry_txs.html:77 -#: templates/ledger/ledger/ledger_list.html:86 +#: templates/ledger/ledger/ledger_list.html:88 #: venv/lib/python3.11/site-packages/django_ledger/templates/django_ledger/journal_entry/includes/card_journal_entry.html:47 #: venv/lib/python3.11/site-packages/django_ledger/templates/django_ledger/journal_entry/je_detail_txs.html:70 #: venv/lib/python3.11/site-packages/django_ledger/templates/django_ledger/ledger/tags/ledgers_table.html:109 @@ -6433,7 +6669,7 @@ msgstr "إلغاء القفل" #: templates/ledger/journal_entry/includes/card_journal_entry.html:50 #: templates/ledger/journal_entry/journal_entry_txs.html:83 -#: templates/ledger/ledger/ledger_list.html:90 +#: templates/ledger/ledger/ledger_list.html:92 #: venv/lib/python3.11/site-packages/django_ledger/templates/django_ledger/closing_entry/includes/card_closing_entry.html:28 #: venv/lib/python3.11/site-packages/django_ledger/templates/django_ledger/journal_entry/includes/card_journal_entry.html:51 #: venv/lib/python3.11/site-packages/django_ledger/templates/django_ledger/journal_entry/je_detail_txs.html:76 @@ -6444,7 +6680,7 @@ msgstr "نشر" #: templates/ledger/journal_entry/includes/card_journal_entry.html:54 #: templates/ledger/journal_entry/journal_entry_txs.html:89 -#: templates/ledger/ledger/ledger_list.html:94 +#: templates/ledger/ledger/ledger_list.html:96 #: venv/lib/python3.11/site-packages/django_ledger/templates/django_ledger/closing_entry/includes/card_closing_entry.html:46 #: venv/lib/python3.11/site-packages/django_ledger/templates/django_ledger/journal_entry/includes/card_journal_entry.html:55 #: venv/lib/python3.11/site-packages/django_ledger/templates/django_ledger/journal_entry/je_detail_txs.html:82 @@ -6461,9 +6697,9 @@ msgid "Create Journal Entry" msgstr "إنشاء إدخال يومية" #: templates/ledger/journal_entry/journal_entry_list.html:4 -#: templates/ledger/journal_entry/journal_entry_list.html:36 +#: templates/ledger/journal_entry/journal_entry_list.html:38 #: templates/ledger/ledger/ledger_list.html:21 -#: templates/ledger/ledger/ledger_list.html:46 +#: templates/ledger/ledger/ledger_list.html:48 #: venv/lib/python3.11/site-packages/django_ledger/models/journal_entry.py:408 #: venv/lib/python3.11/site-packages/django_ledger/templates/django_ledger/journal_entry/je_list.html:19 #: venv/lib/python3.11/site-packages/django_ledger/templates/django_ledger/ledger/tags/ledgers_table.html:10 @@ -6479,16 +6715,16 @@ msgstr "إدخالات دفتر اليومية" msgid "Are you sure ?" msgstr "هل أنت متأكد؟" -#: templates/ledger/journal_entry/journal_entry_list.html:53 +#: templates/ledger/journal_entry/journal_entry_list.html:39 msgid "Add Journal Entry" msgstr "إضافة قيد يومية" -#: templates/ledger/journal_entry/journal_entry_list.html:62 +#: templates/ledger/journal_entry/journal_entry_list.html:48 #: venv/lib/python3.11/site-packages/django_ledger/templates/django_ledger/journal_entry/tags/je_table.html:8 msgid "Document Number" msgstr "رقم المستند" -#: templates/ledger/journal_entry/journal_entry_list.html:63 +#: templates/ledger/journal_entry/journal_entry_list.html:49 #: templates/ledger/journal_entry/journal_entry_transactions.html:18 #: templates/sales/payments/payment_details.html:15 #: templates/sales/payments/payment_list.html:22 @@ -6499,20 +6735,24 @@ msgstr "رقم المستند" msgid "Timestamp" msgstr "الطابع الزمني" -#: templates/ledger/journal_entry/journal_entry_list.html:68 +#: templates/ledger/journal_entry/journal_entry_list.html:54 msgid "Transaction Count" msgstr "عدد المعاملات" -#: templates/ledger/journal_entry/journal_entry_list.html:114 +#: templates/ledger/journal_entry/journal_entry_list.html:100 #: templates/ledger/journal_entry/journal_entry_transactions.html:4 #: templates/ledger/journal_entry/journal_entry_transactions.html:11 #: templates/sales/payments/payment_details.html:4 #: templates/sales/payments/payment_details.html:8 -#: venv/lib/python3.11/site-packages/django_ledger/models/transactions.py:466 +#: venv/lib/python3.11/site-packages/django_ledger/models/transactions.py:490 #: venv/lib/python3.11/site-packages/django_ledger/templates/django_ledger/journal_entry/tags/je_table.html:91 msgid "Transactions" msgstr "المعاملات" +#: templates/ledger/journal_entry/journal_entry_list.html:110 +msgid "No Bank Accounts Found" +msgstr "لم يتم العثور على أي حساب بنكي." + #: templates/ledger/journal_entry/journal_entry_transactions.html:17 #: templates/sales/payments/payment_details.html:14 msgid "#" @@ -6585,13 +6825,13 @@ msgstr "معاملات الفاتورة" #: templates/ledger/ledger/ledger_form.html:5 #: templates/ledger/ledger/ledger_form.html:9 -#: templates/ledger/ledger/ledger_list.html:14 +#: templates/ledger/ledger/ledger_list.html:13 #: venv/lib/python3.11/site-packages/django_ledger/views/ledger.py:95 msgid "Create Ledger" msgstr "إنشاء دفتر الأستاذ" #: templates/ledger/ledger/ledger_list.html:4 -#: templates/ledger/ledger/ledger_list.html:9 +#: templates/ledger/ledger/ledger_list.html:12 #: venv/lib/python3.11/site-packages/django_ledger/models/journal_entry.py:396 #: venv/lib/python3.11/site-packages/django_ledger/models/ledger.py:213 #: venv/lib/python3.11/site-packages/django_ledger/models/mixins.py:217 @@ -6608,16 +6848,20 @@ msgstr "اسم دفتر الأستاذ" msgid "Created Date" msgstr "تاريخ الإنشاء" -#: templates/ledger/ledger/ledger_list.html:99 +#: templates/ledger/ledger/ledger_list.html:101 #: venv/lib/python3.11/site-packages/django_ledger/templates/django_ledger/ledger/tags/ledgers_table.html:122 msgid "Hide" msgstr "إخفاء" -#: templates/ledger/ledger/ledger_list.html:103 +#: templates/ledger/ledger/ledger_list.html:105 #: venv/lib/python3.11/site-packages/django_ledger/templates/django_ledger/ledger/tags/ledgers_table.html:126 msgid "UnHide" msgstr "إلغاء الإخفاء" +#: templates/ledger/ledger/ledger_list.html:118 +msgid "No Entries found" +msgstr "لم يتم العثور على أي مدخلات" + #: templates/ledger/reports/balance_sheet.html:38 #: templates/ledger/reports/cash_flow_statement.html:33 #: templates/ledger/reports/income_statement.html:28 @@ -6642,7 +6886,7 @@ msgstr "الوحدة" #: templates/ledger/reports/cash_flow_statement.html:38 #: templates/ledger/reports/components/period_navigator.html:11 #: templates/ledger/reports/income_statement.html:35 -#: venv/lib/python3.11/site-packages/django_ledger/models/entity.py:3173 +#: venv/lib/python3.11/site-packages/django_ledger/models/entity.py:3186 #: venv/lib/python3.11/site-packages/django_ledger/templates/django_ledger/financial_statements/balance_sheet.html:37 #: venv/lib/python3.11/site-packages/django_ledger/templates/django_ledger/financial_statements/cash_flow.html:38 msgid "Fiscal Year" @@ -7044,7 +7288,7 @@ msgstr[5] "سينتهي حسابك %(user)s خلال %(days)s أيام." msgid "Go" msgstr "اذهب" -#: templates/notifications.html:14 +#: templates/notifications-copy.html:14 templates/notifications.html:24 msgid "Mark all as read" msgstr "وضع علامة مقروء على الكل" @@ -7187,10 +7431,15 @@ msgid "Continue" msgstr "متابعة" #: templates/plans/create_order.html:34 +#, fuzzy +#| msgid "" +#| "\n" +#| " Invoice for this order will be issued for:\n" +#| " " msgid "" "\n" -" Invoice for this order will be issued for:\n" -" " +" Invoice for this order will be issued for:\n" +" " msgstr "" "\n" " سيتم إصدار فاتورة لهذا الطلب لـ:\n" @@ -7202,13 +7451,19 @@ msgid "VAT ID" msgstr "رقم ضريبة القيمة المضافة" #: templates/plans/create_order.html:49 -#, python-format +#, fuzzy, python-format +#| msgid "" +#| "\n" +#| " If this data is not correct please edit billing data before\n" +#| " making an order.\n" +#| " " msgid "" "\n" -" If this data is not correct please edit billing data before\n" -" making an order.\n" -" " +" making an order.\n" +" " msgstr "" "\n" " إذا كانت هذه البيانات غير صحيحة، يرجى not be issued. If you need an " +#| "invoice please provide\n" +#| " billing data " +#| "before making an order.\n" +#| " " msgid "" "\n" -" Invoice will not be issued. If you need an " -"invoice please provide\n" -" billing data " -"before making an order.\n" -" " +" Invoice will not be issued. If you " +"need an invoice please provide\n" +" billing " +"data before making an order.\n" +" " msgstr "" "\n" " لن يتم إصدار فاتورة. إذا كنت بحاجة إلى فاتورة، يرجى " @@ -7238,7 +7500,7 @@ msgid "Your Account" msgstr "حسابك" #: templates/plans/current.html:42 templates/plans/extend.html:24 -#: templates/pricing_page.html:179 +#: templates/pricing_page.html:178 msgid "Plan" msgstr "الخطة" @@ -7247,22 +7509,31 @@ msgid "Plan Details" msgstr "تفاصيل الخطة" #: templates/plans/expiration_messages.html:7 -#, python-format +#, fuzzy, python-format +#| msgid "" +#| "Your account has expired.\n" +#| " Please extend your account." msgid "" "Your account has expired.\n" -" Please extend your account." +" Please extend your account." msgstr "" "لقد انتهت صلاحية حسابك.\n" " يرجى تمديد حسابك." #: templates/plans/expiration_messages.html:14 -#, python-format +#, fuzzy, python-format +#| msgid "" +#| "\n" +#| " Your account is not active. Possibly you are over some " +#| "limits.\n" +#| " Try to activate your account.\n" +#| " " msgid "" "\n" -" Your account is not active. Possibly you are over some " +" Your account is not active. Possibly you are over some " "limits.\n" -" Try to activate your account.\n" -" " +" Try to activate your account.\n" +" " msgstr "" "\n" " حسابك غير نشط. ربما تجاوزت بعض الحدود.\n" @@ -7270,13 +7541,21 @@ msgstr "" " " #: templates/plans/expiration_messages.html:23 -#, python-format +#, fuzzy, python-format +#| msgid "" +#| "\n" +#| " Your account will expire soon (in %(days_to_expire)s " +#| "days).\n" +#| " We recommend to extend your " +#| "account now.\n" +#| " " msgid "" "\n" -" Your account will expire soon (in %(days_to_expire)s days).\n" -" We recommend to extend your " +" Your account will expire soon (in %(days_to_expire)s " +"days).\n" +" We recommend to extend your " "account now.\n" -" " +" " msgstr "" "\n" " سينتهي حسابك قريبًا (خلال %(days_to_expire)s أيام).\n" @@ -7300,17 +7579,23 @@ msgid "Pricings" msgstr "السعر" #: templates/plans/extend.html:44 templates/plans/plan_table.html:95 -#: templates/pricing_page.html:68 +#: templates/pricing_page.html:67 msgid "days" msgstr "أيام" #: templates/plans/extend.html:54 -#, python-format +#, fuzzy, python-format +#| msgid "" +#| "\n" +#| " Unfortunately your current plan is not available any " +#| "more. You need to upgrade your plan.\n" +#| " " msgid "" "\n" -" Unfortunately your current plan is not available any more. " -"You need to upgrade your plan.\n" -" " +" Unfortunately your current plan is not " +"available any more. You need to upgrade your " +"plan.\n" +" " msgstr "" "\n" " للأسف، خطتك الحالية لم تعد متاحة. تحتاج إلى This plan is no longer " +"

This plan is no longer " "available.

\n" -" Upgrade to current plans →\n" -" " +" Upgrade to current plans →\n" +" " msgstr "" "\n" " هذه الخطة لم تعد متاحة ولا يمكن تمديدها." @@ -7579,47 +7864,47 @@ msgstr "اختر الخطة" msgid "Choose Your Plan" msgstr "اختر خطتك" -#: templates/pricing_page.html:58 +#: templates/pricing_page.html:57 msgid "Select a Plan" msgstr "اختر خطة" -#: templates/pricing_page.html:69 templates/welcome.html:109 +#: templates/pricing_page.html:68 templates/welcome.html:109 msgid "Included" msgstr "متضمن" -#: templates/pricing_page.html:90 +#: templates/pricing_page.html:89 msgid "Enter Your Information" msgstr "أدخل معلوماتك" -#: templates/pricing_page.html:135 templates/pricing_page.html:138 +#: templates/pricing_page.html:134 templates/pricing_page.html:137 msgid "Cardholder Name" msgstr "اسم حامل البطاقة" -#: templates/pricing_page.html:153 templates/pricing_page.html:156 +#: templates/pricing_page.html:152 templates/pricing_page.html:155 msgid "Expiry Date" msgstr "تاريخ الانتهاء" -#: templates/pricing_page.html:163 templates/pricing_page.html:166 +#: templates/pricing_page.html:162 templates/pricing_page.html:165 msgid "CVV" msgstr "رمز الأمان (CVV)" -#: templates/pricing_page.html:176 +#: templates/pricing_page.html:175 msgid "Confirm Your Information" msgstr "تأكيد معلوماتك" -#: templates/pricing_page.html:178 +#: templates/pricing_page.html:177 msgid "Order Summary" msgstr "ملخص الطلب" -#: templates/pricing_page.html:185 +#: templates/pricing_page.html:184 msgid "User Information" msgstr "معلومات المستخدم" -#: templates/pricing_page.html:192 +#: templates/pricing_page.html:191 msgid "Cardholder" msgstr "حامل البطاقة" -#: templates/pricing_page.html:194 +#: templates/pricing_page.html:193 msgid "Expiry" msgstr "الانتهاء" @@ -7717,10 +8002,14 @@ msgstr "تاريخ الحالة" #: templates/sales/estimates/estimate_list.html:56 #: templates/sales/journals/journal_list.html:40 -#: templates/sales/orders/order_list.html:41 +#: templates/sales/orders/order_list.html:34 msgid "No Quotations Found" msgstr "لم يتم العثور على عروض" +#: templates/sales/estimates/estimate_send.html:27 +msgid "Send" +msgstr "إرسال" + #: templates/sales/estimates/sale_order_form.html:5 #: templates/sales/estimates/sale_order_preview.html:159 msgid "Sale Order" @@ -7803,16 +8092,15 @@ msgstr "حالة الفاتورة" msgid "Past Due" msgstr "مستحق" +#: templates/sales/invoices/invoice_list.html:68 +msgid "No Invoice Found" +msgstr "لم يتم العثور على فاتورة" + #: templates/sales/journals/journal_form.html:5 #: templates/sales/journals/journal_form.html:9 msgid "Create Payment" msgstr "إجراء الدفع" -#: templates/sales/orders/order_list.html:4 -#: templates/sales/orders/order_list.html:8 -msgid "Orders" -msgstr "طلبات" - #: templates/sales/orders/order_list.html:14 msgid "Order Number" msgstr "رقم الطلب" @@ -7826,7 +8114,7 @@ msgid "Print" msgstr "طباعة" #: templates/sales/orders/purchase_order.html:45 -#: venv/lib/python3.11/site-packages/django_ledger/models/entity.py:3157 +#: venv/lib/python3.11/site-packages/django_ledger/models/entity.py:3170 msgid "Purchase Order" msgstr "أمر شراء" @@ -7887,6 +8175,10 @@ msgstr "حجم المخزون" msgid "Now" msgstr "الآن" +#: templates/terms_and_privacy.html:4 +msgid "Terms of use and privacy policy" +msgstr "شروط الاستخدام وسياسة الخصوصية" + #: templates/two_factor/core/backup_tokens.html:5 #: templates/two_factor/profile/profile.html:34 msgid "Backup Tokens" @@ -8183,22 +8475,22 @@ msgstr "" msgid "View Staff" msgstr "عرض الموظفين" -#: templates/users/user_detail.html:20 -msgid "Are you sure you want to delete this user?" -msgstr "هل أنت متأكد أنك تريد حذف هذا المستخدم؟" - -#: templates/users/user_detail.html:42 +#: templates/users/user_detail.html:11 msgid "User Details" msgstr "تفاصيل المستخدم" -#: templates/users/user_detail.html:52 +#: templates/users/user_detail.html:21 msgid "Role" msgstr "الدور" -#: templates/users/user_detail.html:75 +#: templates/users/user_detail.html:44 msgid "No Group" msgstr "لا يوجد مجموعة" +#: templates/users/user_detail.html:58 +msgid "Are you sure you want to delete this user?" +msgstr "هل أنت متأكد أنك تريد حذف هذا المستخدم؟" + #: templates/users/user_form.html:17 msgid "Edit Staff" msgstr "تعديل الموظف" @@ -8207,51 +8499,43 @@ msgstr "تعديل الموظف" msgid "Add Staff" msgstr "إضافة موظف" -#: templates/users/user_group_form.html:13 +#: templates/users/user_group_form.html:10 msgid "Manage Groups" msgstr "إدارة المجموعات" -#: templates/users/user_list.html:14 +#: templates/users/user_list.html:15 msgid "Add New Staff" msgstr "إضافة موظف جديد" -#: templates/users/user_list.html:15 +#: templates/users/user_list.html:16 msgid "Manage Groups & Permissions" msgstr "إدارة المجموعات والأذونات" -#: templates/users/user_list.html:25 -msgid "arabic name" -msgstr "الاسم بالعربية" +#: templates/users/user_list.html:20 +msgid "No Active Subscription,please activate your subscription." +msgstr "لا يوجد اشتراك نشط، يرجى تفعيل اشتراكك." -#: templates/users/user_list.html:27 +#: templates/users/user_list.html:34 msgid "phone number" msgstr "رقم الهاتف" -#: templates/users/user_list.html:28 +#: templates/users/user_list.html:35 msgid "role" msgstr "الدور" -#: templates/users/user_list.html:29 -msgid "groups" -msgstr "المجموعات" - #: templates/vendors/vendor_form.html:17 msgid "Edit Vendor" msgstr "تعديل مورد" -#: templates/vendors/vendor_form.html:20 templates/vendors/vendors_list.html:18 +#: templates/vendors/vendor_form.html:20 templates/vendors/vendors_list.html:15 msgid "Add Vendor" msgstr "إضافة مورد" -#: templates/vendors/vendors_list.html:27 -msgid "Enter vendor name" -msgstr "أدخل اسم المورد" - -#: templates/vendors/vendors_list.html:59 +#: templates/vendors/vendors_list.html:58 msgid "Contact name" msgstr "اسم جهة الاتصال" -#: templates/vendors/vendors_list.html:110 +#: templates/vendors/vendors_list.html:129 #: templates/vendors/view_vendor.html:37 msgid "Are you sure you want to delete this vendor" msgstr "هل أنت متأكد أنك تريد حذف هذا المورد" @@ -8802,6 +9086,40 @@ msgstr "يرجى التأكد من أن" msgid "reviews this appointment request and takes the necessary action." msgstr "يقوم بمراجعة طلب الموعد هذا واتخاذ الإجراءات اللازمة." +#: venv/lib/python3.11/site-packages/appointment/templates/email_sender/thank_you_email.html:185 +#, python-format +msgid "" +"\n" +" To activate your account and set " +"your password, please use the following secure\n" +" link: Set Your Password. Please\n" +" note that this link will expire in 2 " +"days for your security.\n" +" " +msgstr "" +"\n" +" لتفعيل حسابك وتعيين كلمة المرور، " +"يرجى استخدام الرابط الآمن التالي: تعيين كلمة المرور. يرجى\n" +" ملاحظة أن هذا الرابط سينتهي صلاحيته " +"خلال يومين لضمان الأمان.\n" +" " + +#: venv/lib/python3.11/site-packages/appointment/templates/email_sender/thank_you_email.html:246 +msgid "" +"\n" +" Should you have any inquiries or require " +"further assistance, our support team is here to\n" +" help. You can reach us anytime.\n" +" " +msgstr "" +"\n" +" إذا كان لديك أي استفسارات أو كنت بحاجة إلى " +"مزيد من المساعدة، فإن فريق الدعم لدينا هنا\n" +" لمساعدتك. يمكنك التواصل معنا في أي وقت.\n" +" " + #: venv/lib/python3.11/site-packages/appointment/templates/error_pages/304_already_submitted.html:11 #: venv/lib/python3.11/site-packages/appointment/templates/error_pages/403_forbidden_rescheduling.html:100 msgid "Not authorized!" @@ -9208,27 +9526,59 @@ msgstr "المستخدم هو مشرف عام." msgid "French" msgstr "الفرنسية" -#: venv/lib/python3.11/site-packages/click/_termui_impl.py:556 +msgid "Search files" +msgstr "البحث في الملفات" + +msgid "Select an image to embed" +msgstr "اختر صورة لإدراجها" + +msgid "Browse for the image you want, then click 'Embed Image' to continue..." +msgstr "تصفح للعثور على الصورة المطلوبة، ثم انقر على 'إدراج الصورة' للمتابعة..." + +msgid "No images found. Upload images using the 'Image Button' dialog's 'Upload' tab." +msgstr "لم يتم العثور على صور. قم بتحميل الصور باستخدام تبويب 'تحميل' في مربع حوار 'زر الصورة'." + +msgid "Images in: " +msgstr "الصور في: " + +msgid "Embed Image" +msgstr "إدراج الصورة" + +msgid "Play Slideshow" +msgstr "تشغيل عرض الشرائح" + +msgid "Pause Slideshow" +msgstr "إيقاف عرض الشرائح مؤقتاً" + +msgid "‹ Previous Photo" +msgstr "‹ الصورة السابقة" + +msgid "Next Photo ›" +msgstr "الصورة التالية ›" + +msgid "Next ›" +msgstr "التالي ›" + +msgid "‹ Prev" +msgstr "‹ السابق" + +#: venv/lib/python3.11/site-packages/click/_termui_impl.py:600 #, python-brace-format msgid "{editor}: Editing failed" msgstr "{editor}: فشل التحرير" -#: venv/lib/python3.11/site-packages/click/_termui_impl.py:560 +#: venv/lib/python3.11/site-packages/click/_termui_impl.py:604 #, python-brace-format msgid "{editor}: Editing failed: {e}" msgstr "{editor}: فشل التحرير: {e}" -#: venv/lib/python3.11/site-packages/click/core.py:1124 -msgid "Aborted!" -msgstr "تم الإلغاء!" - -#: venv/lib/python3.11/site-packages/click/core.py:1349 -#: venv/lib/python3.11/site-packages/click/core.py:1379 +#: venv/lib/python3.11/site-packages/click/core.py:1084 +#: venv/lib/python3.11/site-packages/click/core.py:1121 #, python-brace-format -msgid "(Deprecated) {text}" -msgstr "(مهمل) {text}" +msgid "{text} {deprecated_message}" +msgstr "" -#: venv/lib/python3.11/site-packages/click/core.py:1422 +#: venv/lib/python3.11/site-packages/click/core.py:1202 #, python-brace-format msgid "Got unexpected extra argument ({args})" msgid_plural "Got unexpected extra arguments ({args})" @@ -9239,27 +9589,33 @@ msgstr[3] "تم الحصول على أربعة وسائط إضافية غير م msgstr[4] "تم الحصول على خمسة وسائط إضافية غير متوقعة ({args})" msgstr[5] "تم الحصول على عدد كبير من الوسائط الإضافية غير المتوقعة ({args})" -#: venv/lib/python3.11/site-packages/click/core.py:1438 -msgid "DeprecationWarning: The command {name!r} is deprecated." +#: venv/lib/python3.11/site-packages/click/core.py:1221 +#, fuzzy +#| msgid "DeprecationWarning: The command {name!r} is deprecated." +msgid "DeprecationWarning: The command {name!r} is deprecated.{extra_message}" msgstr "تحذير إهمال: الأمر {name!r} مهمل." -#: venv/lib/python3.11/site-packages/click/core.py:1645 +#: venv/lib/python3.11/site-packages/click/core.py:1405 +msgid "Aborted!" +msgstr "تم الإلغاء!" + +#: venv/lib/python3.11/site-packages/click/core.py:1779 msgid "Commands" msgstr "الأوامر" -#: venv/lib/python3.11/site-packages/click/core.py:1677 +#: venv/lib/python3.11/site-packages/click/core.py:1810 msgid "Missing command." msgstr "الأمر مفقود." -#: venv/lib/python3.11/site-packages/click/core.py:1755 +#: venv/lib/python3.11/site-packages/click/core.py:1888 msgid "No such command {name!r}." msgstr "لا يوجد أمر باسم {name!r}." -#: venv/lib/python3.11/site-packages/click/core.py:2313 +#: venv/lib/python3.11/site-packages/click/core.py:2303 msgid "Value must be an iterable." msgstr "يجب أن تكون القيمة قابلة للتكرار." -#: venv/lib/python3.11/site-packages/click/core.py:2334 +#: venv/lib/python3.11/site-packages/click/core.py:2324 #, python-brace-format msgid "Takes {nargs} values but 1 was given." msgid_plural "Takes {nargs} values but {len} were given." @@ -9270,86 +9626,89 @@ msgstr[3] "" msgstr[4] "" msgstr[5] "" -#: venv/lib/python3.11/site-packages/click/core.py:2783 +#: venv/lib/python3.11/site-packages/click/core.py:2404 +#, fuzzy +#| msgid "DeprecationWarning: The command {name!r} is deprecated." +msgid "" +"DeprecationWarning: The {param_type} {name!r} is deprecated.{extra_message}" +msgstr "تحذير إهمال: الأمر {name!r} مهمل." + +#: venv/lib/python3.11/site-packages/click/core.py:2807 #, python-brace-format msgid "env var: {var}" msgstr "متغير البيئة: {var}" -#: venv/lib/python3.11/site-packages/click/core.py:2813 -msgid "(dynamic)" -msgstr "(ديناميكي)" - -#: venv/lib/python3.11/site-packages/click/core.py:2828 +#: venv/lib/python3.11/site-packages/click/core.py:2810 #, python-brace-format msgid "default: {default}" msgstr "القيمة الافتراضية: {default}" -#: venv/lib/python3.11/site-packages/click/core.py:2841 -msgid "required" -msgstr "مطلوب" +#: venv/lib/python3.11/site-packages/click/core.py:2870 +msgid "(dynamic)" +msgstr "(ديناميكي)" -#: venv/lib/python3.11/site-packages/click/decorators.py:457 +#: venv/lib/python3.11/site-packages/click/decorators.py:465 #, python-format msgid "%(prog)s, version %(version)s" msgstr "%(prog)s، الإصدار %(version)s" -#: venv/lib/python3.11/site-packages/click/decorators.py:520 +#: venv/lib/python3.11/site-packages/click/decorators.py:522 msgid "Show the version and exit." msgstr "عرض الإصدار والخروج." -#: venv/lib/python3.11/site-packages/click/decorators.py:541 +#: venv/lib/python3.11/site-packages/click/decorators.py:548 msgid "Show this message and exit." msgstr "إظهار رسالة المساعدة هذه والخروج" -#: venv/lib/python3.11/site-packages/click/exceptions.py:49 -#: venv/lib/python3.11/site-packages/click/exceptions.py:88 +#: venv/lib/python3.11/site-packages/click/exceptions.py:50 +#: venv/lib/python3.11/site-packages/click/exceptions.py:89 #, python-brace-format msgid "Error: {message}" msgstr "خطأ: {message}" -#: venv/lib/python3.11/site-packages/click/exceptions.py:80 +#: venv/lib/python3.11/site-packages/click/exceptions.py:81 #, python-brace-format msgid "Try '{command} {option}' for help." msgstr "حاول '{command} {option}' للحصول على المساعدة." -#: venv/lib/python3.11/site-packages/click/exceptions.py:129 +#: venv/lib/python3.11/site-packages/click/exceptions.py:130 #, python-brace-format msgid "Invalid value: {message}" msgstr "قيمة غير صالحة: {message}" -#: venv/lib/python3.11/site-packages/click/exceptions.py:131 +#: venv/lib/python3.11/site-packages/click/exceptions.py:132 #, python-brace-format msgid "Invalid value for {param_hint}: {message}" msgstr "قيمة غير صالحة لـ {param_hint}: {message}" -#: venv/lib/python3.11/site-packages/click/exceptions.py:187 +#: venv/lib/python3.11/site-packages/click/exceptions.py:190 msgid "Missing argument" msgstr "الوسيطة مفقودة" -#: venv/lib/python3.11/site-packages/click/exceptions.py:189 +#: venv/lib/python3.11/site-packages/click/exceptions.py:192 msgid "Missing option" msgstr "الخيار مفقود" -#: venv/lib/python3.11/site-packages/click/exceptions.py:191 +#: venv/lib/python3.11/site-packages/click/exceptions.py:194 msgid "Missing parameter" msgstr "المعلمة مفقودة" -#: venv/lib/python3.11/site-packages/click/exceptions.py:193 +#: venv/lib/python3.11/site-packages/click/exceptions.py:196 #, python-brace-format msgid "Missing {param_type}" msgstr "مفقود {param_type}" -#: venv/lib/python3.11/site-packages/click/exceptions.py:200 +#: venv/lib/python3.11/site-packages/click/exceptions.py:203 #, python-brace-format msgid "Missing parameter: {param_name}" msgstr "المعلمة مفقودة: {param_name}" -#: venv/lib/python3.11/site-packages/click/exceptions.py:220 +#: venv/lib/python3.11/site-packages/click/exceptions.py:223 #, python-brace-format msgid "No such option: {name}" msgstr "لا يوجد خيار باسم: {name}" -#: venv/lib/python3.11/site-packages/click/exceptions.py:232 +#: venv/lib/python3.11/site-packages/click/exceptions.py:235 #, python-brace-format msgid "Did you mean {possibility}?" msgid_plural "(Possible options: {possibilities})" @@ -9360,11 +9719,11 @@ msgstr[3] "" msgstr[4] "" msgstr[5] "" -#: venv/lib/python3.11/site-packages/click/exceptions.py:270 +#: venv/lib/python3.11/site-packages/click/exceptions.py:282 msgid "unknown error" msgstr "خطأ غير معروف" -#: venv/lib/python3.11/site-packages/click/exceptions.py:277 +#: venv/lib/python3.11/site-packages/click/exceptions.py:289 msgid "Could not open file {filename!r}: {message}" msgstr "تعذر فتح الملف {filename!r}: {message}" @@ -9372,15 +9731,15 @@ msgstr "تعذر فتح الملف {filename!r}: {message}" msgid "Usage:" msgstr "الاستخدام:" -#: venv/lib/python3.11/site-packages/click/parser.py:233 +#: venv/lib/python3.11/site-packages/click/parser.py:200 msgid "Argument {name!r} takes {nargs} values." msgstr "الوسيطة {name!r} تتطلب {nargs} قيمة." -#: venv/lib/python3.11/site-packages/click/parser.py:415 +#: venv/lib/python3.11/site-packages/click/parser.py:383 msgid "Option {name!r} does not take a value." msgstr "الخيار {name!r} لا يأخذ قيمة." -#: venv/lib/python3.11/site-packages/click/parser.py:476 +#: venv/lib/python3.11/site-packages/click/parser.py:444 msgid "Option {name!r} requires an argument." msgid_plural "Option {name!r} requires {nargs} arguments." msgstr[0] "الخيار {name!r} يتطلب وسيطة." @@ -9398,32 +9757,32 @@ msgstr "إكمال الأوامر في القشرة غير مدعوم للإصد msgid "Couldn't detect Bash version, shell completion is not supported." msgstr "تعذر اكتشاف إصدار Bash، إكمال الأوامر غير مدعوم." -#: venv/lib/python3.11/site-packages/click/termui.py:158 +#: venv/lib/python3.11/site-packages/click/termui.py:162 msgid "Repeat for confirmation" msgstr "أعد المحاولة للتأكيد" -#: venv/lib/python3.11/site-packages/click/termui.py:174 +#: venv/lib/python3.11/site-packages/click/termui.py:178 msgid "Error: The value you entered was invalid." msgstr "خطأ: القيمة التي أدخلتها غير صالحة." -#: venv/lib/python3.11/site-packages/click/termui.py:176 +#: venv/lib/python3.11/site-packages/click/termui.py:180 #, python-brace-format msgid "Error: {e.message}" msgstr "خطأ: {e.message}" -#: venv/lib/python3.11/site-packages/click/termui.py:187 +#: venv/lib/python3.11/site-packages/click/termui.py:191 msgid "Error: The two entered values do not match." msgstr "خطأ: القيمتان المدخلتان لا تتطابقان." -#: venv/lib/python3.11/site-packages/click/termui.py:243 +#: venv/lib/python3.11/site-packages/click/termui.py:247 msgid "Error: invalid input" msgstr "خطأ: إدخال غير صالح" -#: venv/lib/python3.11/site-packages/click/termui.py:773 +#: venv/lib/python3.11/site-packages/click/termui.py:866 msgid "Press any key to continue..." msgstr "اضغط أي مفتاح للمتابعة..." -#: venv/lib/python3.11/site-packages/click/types.py:267 +#: venv/lib/python3.11/site-packages/click/types.py:332 #, python-brace-format msgid "" "Choose from:\n" @@ -9432,7 +9791,7 @@ msgstr "" "اختر من:\n" "\t{choices}" -#: venv/lib/python3.11/site-packages/click/types.py:299 +#: venv/lib/python3.11/site-packages/click/types.py:369 msgid "{value!r} is not {choice}." msgid_plural "{value!r} is not one of {choices}." msgstr[0] "القيمة %(value)r ليست خياراً صالحاً." @@ -9442,7 +9801,7 @@ msgstr[3] "القيمة %(value)r ليست خياراً صالحاً." msgstr[4] "القيمة %(value)r ليست خياراً صالحاً." msgstr[5] "القيمة %(value)r ليست خياراً صالحاً." -#: venv/lib/python3.11/site-packages/click/types.py:393 +#: venv/lib/python3.11/site-packages/click/types.py:460 msgid "{value!r} does not match the format {format}." msgid_plural "{value!r} does not match the formats {formats}." msgstr[0] "" @@ -9452,60 +9811,60 @@ msgstr[3] "" msgstr[4] "" msgstr[5] "" -#: venv/lib/python3.11/site-packages/click/types.py:415 +#: venv/lib/python3.11/site-packages/click/types.py:482 msgid "{value!r} is not a valid {number_type}." msgstr "القيمة %(value)r ليست خياراً صالحاً." -#: venv/lib/python3.11/site-packages/click/types.py:471 +#: venv/lib/python3.11/site-packages/click/types.py:538 #, python-brace-format msgid "{value} is not in the range {range}." msgstr "" -#: venv/lib/python3.11/site-packages/click/types.py:612 +#: venv/lib/python3.11/site-packages/click/types.py:679 msgid "{value!r} is not a valid boolean." msgstr "القيمة %(value)r ليست خياراً صالحاً." -#: venv/lib/python3.11/site-packages/click/types.py:636 +#: venv/lib/python3.11/site-packages/click/types.py:703 msgid "{value!r} is not a valid UUID." msgstr "القيمة “%(value)s” ليست UUID صالح." -#: venv/lib/python3.11/site-packages/click/types.py:826 +#: venv/lib/python3.11/site-packages/click/types.py:893 msgid "file" msgstr "ملف" -#: venv/lib/python3.11/site-packages/click/types.py:828 +#: venv/lib/python3.11/site-packages/click/types.py:895 msgid "directory" msgstr "مجلد" -#: venv/lib/python3.11/site-packages/click/types.py:830 +#: venv/lib/python3.11/site-packages/click/types.py:897 msgid "path" msgstr "مسار" -#: venv/lib/python3.11/site-packages/click/types.py:881 +#: venv/lib/python3.11/site-packages/click/types.py:944 msgid "{name} {filename!r} does not exist." msgstr "{name} {filename!r} غير موجود." -#: venv/lib/python3.11/site-packages/click/types.py:890 +#: venv/lib/python3.11/site-packages/click/types.py:953 msgid "{name} {filename!r} is a file." msgstr "{name} {filename!r} هو ملف." -#: venv/lib/python3.11/site-packages/click/types.py:898 +#: venv/lib/python3.11/site-packages/click/types.py:961 msgid "{name} {filename!r} is a directory." msgstr "{name} '{filename}' هو دليل." -#: venv/lib/python3.11/site-packages/click/types.py:907 +#: venv/lib/python3.11/site-packages/click/types.py:970 msgid "{name} {filename!r} is not readable." msgstr "{name} {filename!r} غير قابل للقراءة." -#: venv/lib/python3.11/site-packages/click/types.py:916 +#: venv/lib/python3.11/site-packages/click/types.py:979 msgid "{name} {filename!r} is not writable." msgstr "{name} {filename!r} غير قابل للكتابة." -#: venv/lib/python3.11/site-packages/click/types.py:925 +#: venv/lib/python3.11/site-packages/click/types.py:988 msgid "{name} {filename!r} is not executable." msgstr "{name} {filename!r} غير قابل للتنفيذ." -#: venv/lib/python3.11/site-packages/click/types.py:992 +#: venv/lib/python3.11/site-packages/click/types.py:1055 #, python-brace-format msgid "{len_type} values are required, but {len_value} was given." msgid_plural "{len_type} values are required, but {len_value} were given." @@ -9566,86 +9925,86 @@ msgstr "أدخل قيمة صالحة." msgid "Enter a valid domain name." msgstr "أدخل اسم نطاق صالح." -#: venv/lib/python3.11/site-packages/django/core/validators.py:155 -#: venv/lib/python3.11/site-packages/django/forms/fields.py:768 +#: venv/lib/python3.11/site-packages/django/core/validators.py:153 +#: venv/lib/python3.11/site-packages/django/forms/fields.py:775 msgid "Enter a valid URL." msgstr "أدخل رابط URL صالحاً." -#: venv/lib/python3.11/site-packages/django/core/validators.py:216 +#: venv/lib/python3.11/site-packages/django/core/validators.py:200 msgid "Enter a valid integer." msgstr "أدخل عدداً صحيحاً صالحاً." -#: venv/lib/python3.11/site-packages/django/core/validators.py:227 +#: venv/lib/python3.11/site-packages/django/core/validators.py:211 msgid "Enter a valid email address." msgstr "أدخل عنوان بريد إلكتروني صالح." #. Translators: "letters" means latin letters: a-z and A-Z. -#: venv/lib/python3.11/site-packages/django/core/validators.py:310 +#: venv/lib/python3.11/site-packages/django/core/validators.py:289 msgid "" "Enter a valid “slug” consisting of letters, numbers, underscores or hyphens." msgstr "أدخل “Slug” صالح يتكون من أحرف وأرقام وتسطيرات سفلية أو واصلات." -#: venv/lib/python3.11/site-packages/django/core/validators.py:318 +#: venv/lib/python3.11/site-packages/django/core/validators.py:297 msgid "" "Enter a valid “slug” consisting of Unicode letters, numbers, underscores, or " "hyphens." msgstr "أدخل “Slug” صالح يتكون من أحرف يونكود وأرقام وتسطيرات سفلية أو واصلات." -#: venv/lib/python3.11/site-packages/django/core/validators.py:330 -#: venv/lib/python3.11/site-packages/django/core/validators.py:339 -#: venv/lib/python3.11/site-packages/django/core/validators.py:353 -#: venv/lib/python3.11/site-packages/django/db/models/fields/__init__.py:2215 +#: venv/lib/python3.11/site-packages/django/core/validators.py:309 +#: venv/lib/python3.11/site-packages/django/core/validators.py:318 +#: venv/lib/python3.11/site-packages/django/core/validators.py:332 +#: venv/lib/python3.11/site-packages/django/db/models/fields/__init__.py:2220 #, python-format msgid "Enter a valid %(protocol)s address." msgstr "أدخل عنوان %(protocol)s صالحًا." -#: venv/lib/python3.11/site-packages/django/core/validators.py:332 +#: venv/lib/python3.11/site-packages/django/core/validators.py:311 msgid "IPv4" msgstr "IPv4" -#: venv/lib/python3.11/site-packages/django/core/validators.py:341 +#: venv/lib/python3.11/site-packages/django/core/validators.py:320 #: venv/lib/python3.11/site-packages/django/utils/ipv6.py:43 msgid "IPv6" msgstr "IPv6" -#: venv/lib/python3.11/site-packages/django/core/validators.py:355 +#: venv/lib/python3.11/site-packages/django/core/validators.py:334 msgid "IPv4 or IPv6" msgstr "IPv4 or IPv6" -#: venv/lib/python3.11/site-packages/django/core/validators.py:396 +#: venv/lib/python3.11/site-packages/django/core/validators.py:375 msgid "Enter only digits separated by commas." msgstr "أدخل أرقاماً فقط مفصولة بفواصل." -#: venv/lib/python3.11/site-packages/django/core/validators.py:402 +#: venv/lib/python3.11/site-packages/django/core/validators.py:381 #, python-format msgid "Ensure this value is %(limit_value)s (it is %(show_value)s)." msgstr "تأكد من أن هذه القيمة هي %(limit_value)s (هي %(show_value)s)." -#: venv/lib/python3.11/site-packages/django/core/validators.py:437 +#: venv/lib/python3.11/site-packages/django/core/validators.py:416 #: venv/lib/python3.11/site-packages/djmoney/models/validators.py:51 #, python-format msgid "Ensure this value is less than or equal to %(limit_value)s." msgstr "تأكد من أن هذه القيمة أقل من أو تساوي %(limit_value)s." -#: venv/lib/python3.11/site-packages/django/core/validators.py:446 +#: venv/lib/python3.11/site-packages/django/core/validators.py:425 #: venv/lib/python3.11/site-packages/djmoney/models/validators.py:43 #, python-format msgid "Ensure this value is greater than or equal to %(limit_value)s." msgstr "تأكد من أن هذه القيمة أكبر من أو تساوي %(limit_value)s." -#: venv/lib/python3.11/site-packages/django/core/validators.py:455 +#: venv/lib/python3.11/site-packages/django/core/validators.py:434 #, python-format msgid "Ensure this value is a multiple of step size %(limit_value)s." msgstr "تأكد من أن هذه القيمة هي مضاعف لخطوة الحجم %(limit_value)s." -#: venv/lib/python3.11/site-packages/django/core/validators.py:462 +#: venv/lib/python3.11/site-packages/django/core/validators.py:441 #, python-format msgid "" "Ensure this value is a multiple of step size %(limit_value)s, starting from " "%(offset)s, e.g. %(offset)s, %(valid_value1)s, %(valid_value2)s, and so on." msgstr "" -#: venv/lib/python3.11/site-packages/django/core/validators.py:494 +#: venv/lib/python3.11/site-packages/django/core/validators.py:473 #, python-format msgid "" "Ensure this value has at least %(limit_value)d character (it has " @@ -9660,7 +10019,7 @@ msgstr[1] "" "تأكد من أن هذه القيمة تحتوي على الأقل على %(limit_value)d أحرف (تحتوي على " "%(show_value)d)." -#: venv/lib/python3.11/site-packages/django/core/validators.py:512 +#: venv/lib/python3.11/site-packages/django/core/validators.py:491 #, python-format msgid "" "Ensure this value has at most %(limit_value)d character (it has " @@ -9675,27 +10034,27 @@ msgstr[1] "" "تأكد من أن هذه القيمة تحتوي على الأكثر على %(limit_value)d أحرف (تحتوي على " "%(show_value)d)." -#: venv/lib/python3.11/site-packages/django/core/validators.py:535 -#: venv/lib/python3.11/site-packages/django/forms/fields.py:359 -#: venv/lib/python3.11/site-packages/django/forms/fields.py:398 +#: venv/lib/python3.11/site-packages/django/core/validators.py:514 +#: venv/lib/python3.11/site-packages/django/forms/fields.py:366 +#: venv/lib/python3.11/site-packages/django/forms/fields.py:405 msgid "Enter a number." msgstr "أدخل رقماً." -#: venv/lib/python3.11/site-packages/django/core/validators.py:537 +#: venv/lib/python3.11/site-packages/django/core/validators.py:516 #, python-format msgid "Ensure that there are no more than %(max)s digit in total." msgid_plural "Ensure that there are no more than %(max)s digits in total." msgstr[0] "تأكد من أن العدد الإجمالي للأرقام لا يتجاوز %(max)s رقم." msgstr[1] "تأكد من أن العدد الإجمالي للأرقام لا يتجاوز %(max)s أرقام." -#: venv/lib/python3.11/site-packages/django/core/validators.py:542 +#: venv/lib/python3.11/site-packages/django/core/validators.py:521 #, python-format msgid "Ensure that there are no more than %(max)s decimal place." msgid_plural "Ensure that there are no more than %(max)s decimal places." msgstr[0] "تأكد من أن العدد الإجمالي للأماكن العشرية لا يتجاوز %(max)s." msgstr[1] "تأكد من أن العدد الإجمالي للأماكن العشرية لا يتجاوز %(max)s." -#: venv/lib/python3.11/site-packages/django/core/validators.py:547 +#: venv/lib/python3.11/site-packages/django/core/validators.py:526 #, python-format msgid "" "Ensure that there are no more than %(max)s digit before the decimal point." @@ -9706,7 +10065,7 @@ msgstr[0] "" msgstr[1] "" "تأكد من أن العدد الإجمالي للأرقام قبل العلامة العشرية لا يتجاوز %(max)s." -#: venv/lib/python3.11/site-packages/django/core/validators.py:618 +#: venv/lib/python3.11/site-packages/django/core/validators.py:597 #, python-format msgid "" "File extension “%(extension)s” is not allowed. Allowed extensions are: " @@ -9715,16 +10074,16 @@ msgstr "" "امتداد الملف “%(extension)s” غير مسموح به. الامتدادات المسموح بها هي: " "%(allowed_extensions)s." -#: venv/lib/python3.11/site-packages/django/core/validators.py:680 +#: venv/lib/python3.11/site-packages/django/core/validators.py:659 msgid "Null characters are not allowed." msgstr "الأحرف الفارغة غير مسموح بها." -#: venv/lib/python3.11/site-packages/django/db/models/base.py:1572 +#: venv/lib/python3.11/site-packages/django/db/models/base.py:1600 #: venv/lib/python3.11/site-packages/django/forms/models.py:908 msgid "and" msgstr "و" -#: venv/lib/python3.11/site-packages/django/db/models/base.py:1574 +#: venv/lib/python3.11/site-packages/django/db/models/base.py:1602 #, python-format msgid "%(model_name)s with this %(field_labels)s already exists." msgstr "%(model_name)s مع %(field_labels)s هذا موجود بالفعل." @@ -9766,34 +10125,34 @@ msgstr "" msgid "Field of type: %(field_type)s" msgstr "حقل من النوع: %(field_type)s" -#: venv/lib/python3.11/site-packages/django/db/models/fields/__init__.py:1156 +#: venv/lib/python3.11/site-packages/django/db/models/fields/__init__.py:1162 #, python-format msgid "“%(value)s” value must be either True or False." msgstr "القيمة “%(value)s” يجب أن تكون إما True أو False." -#: venv/lib/python3.11/site-packages/django/db/models/fields/__init__.py:1157 +#: venv/lib/python3.11/site-packages/django/db/models/fields/__init__.py:1163 #, python-format msgid "“%(value)s” value must be either True, False, or None." msgstr "القيمة “%(value)s” يجب أن تكون إما True، False، أو None." -#: venv/lib/python3.11/site-packages/django/db/models/fields/__init__.py:1159 +#: venv/lib/python3.11/site-packages/django/db/models/fields/__init__.py:1165 msgid "Boolean (Either True or False)" msgstr "قيمة منطقية (إما True أو False)" -#: venv/lib/python3.11/site-packages/django/db/models/fields/__init__.py:1209 +#: venv/lib/python3.11/site-packages/django/db/models/fields/__init__.py:1215 #, python-format msgid "String (up to %(max_length)s)" msgstr "نص (حتى %(max_length)s)" -#: venv/lib/python3.11/site-packages/django/db/models/fields/__init__.py:1211 +#: venv/lib/python3.11/site-packages/django/db/models/fields/__init__.py:1217 msgid "String (unlimited)" msgstr "نص (غير محدود)" -#: venv/lib/python3.11/site-packages/django/db/models/fields/__init__.py:1320 +#: venv/lib/python3.11/site-packages/django/db/models/fields/__init__.py:1326 msgid "Comma-separated integers" msgstr "أرقام مفصولة بفواصل" -#: venv/lib/python3.11/site-packages/django/db/models/fields/__init__.py:1421 +#: venv/lib/python3.11/site-packages/django/db/models/fields/__init__.py:1427 #, python-format msgid "" "“%(value)s” value has an invalid date format. It must be in YYYY-MM-DD " @@ -9802,8 +10161,8 @@ msgstr "" "القيمة “%(value)s” تحتوي على تنسيق تاريخ غير صالح. يجب أن تكون بالتنسيق YYYY-" "MM-DD." -#: venv/lib/python3.11/site-packages/django/db/models/fields/__init__.py:1425 -#: venv/lib/python3.11/site-packages/django/db/models/fields/__init__.py:1560 +#: venv/lib/python3.11/site-packages/django/db/models/fields/__init__.py:1431 +#: venv/lib/python3.11/site-packages/django/db/models/fields/__init__.py:1566 #, python-format msgid "" "“%(value)s” value has the correct format (YYYY-MM-DD) but it is an invalid " @@ -9812,11 +10171,11 @@ msgstr "" "القيمة “%(value)s” تحتوي على التنسيق الصحيح (YYYY-MM-DD) لكنها تاريخ غير " "صالح." -#: venv/lib/python3.11/site-packages/django/db/models/fields/__init__.py:1429 +#: venv/lib/python3.11/site-packages/django/db/models/fields/__init__.py:1435 msgid "Date (without time)" msgstr "تاريخ (بدون وقت)" -#: venv/lib/python3.11/site-packages/django/db/models/fields/__init__.py:1556 +#: venv/lib/python3.11/site-packages/django/db/models/fields/__init__.py:1562 #, python-format msgid "" "“%(value)s” value has an invalid format. It must be in YYYY-MM-DD " @@ -9825,7 +10184,7 @@ msgstr "" "القيمة “%(value)s” تحتوي على تنسيق غير صالح. يجب أن تكون بالتنسيق YYYY-MM-DD " "HH:MM[:ss[.uuuuuu]][TZ]." -#: venv/lib/python3.11/site-packages/django/db/models/fields/__init__.py:1564 +#: venv/lib/python3.11/site-packages/django/db/models/fields/__init__.py:1570 #, python-format msgid "" "“%(value)s” value has the correct format (YYYY-MM-DD HH:MM[:ss[.uuuuuu]]" @@ -9834,20 +10193,20 @@ msgstr "" "القيمة “%(value)s” تحتوي على التنسيق الصحيح (YYYY-MM-DD HH:MM[:ss[.uuuuuu]]" "[TZ]) لكنها تاريخ/وقت غير صالح." -#: venv/lib/python3.11/site-packages/django/db/models/fields/__init__.py:1569 +#: venv/lib/python3.11/site-packages/django/db/models/fields/__init__.py:1575 msgid "Date (with time)" msgstr "تاريخ (مع الوقت)" -#: venv/lib/python3.11/site-packages/django/db/models/fields/__init__.py:1696 +#: venv/lib/python3.11/site-packages/django/db/models/fields/__init__.py:1702 #, python-format msgid "“%(value)s” value must be a decimal number." msgstr "القيمة “%(value)s” يجب أن تكون رقماً عشرياً." -#: venv/lib/python3.11/site-packages/django/db/models/fields/__init__.py:1698 +#: venv/lib/python3.11/site-packages/django/db/models/fields/__init__.py:1704 msgid "Decimal number" msgstr "رقم عشري" -#: venv/lib/python3.11/site-packages/django/db/models/fields/__init__.py:1859 +#: venv/lib/python3.11/site-packages/django/db/models/fields/__init__.py:1864 #, python-format msgid "" "“%(value)s” value has an invalid format. It must be in [DD] " @@ -9856,76 +10215,76 @@ msgstr "" "القيمة “%(value)s” تحتوي على تنسيق غير صالح. يجب أن تكون بالتنسيق [DD] " "[[HH:]MM:]ss[.uuuuuu]." -#: venv/lib/python3.11/site-packages/django/db/models/fields/__init__.py:1940 +#: venv/lib/python3.11/site-packages/django/db/models/fields/__init__.py:1945 msgid "File path" msgstr "مسار الملف" -#: venv/lib/python3.11/site-packages/django/db/models/fields/__init__.py:2018 +#: venv/lib/python3.11/site-packages/django/db/models/fields/__init__.py:2023 #, python-format msgid "“%(value)s” value must be a float." msgstr "القيمة “%(value)s” يجب أن تكون عدداً عشرياً." -#: venv/lib/python3.11/site-packages/django/db/models/fields/__init__.py:2020 +#: venv/lib/python3.11/site-packages/django/db/models/fields/__init__.py:2025 msgid "Floating point number" msgstr "عدد عشري" -#: venv/lib/python3.11/site-packages/django/db/models/fields/__init__.py:2060 +#: venv/lib/python3.11/site-packages/django/db/models/fields/__init__.py:2065 #, python-format msgid "“%(value)s” value must be an integer." msgstr "القيمة “%(value)s” يجب أن تكون عدداً صحيحاً." -#: venv/lib/python3.11/site-packages/django/db/models/fields/__init__.py:2062 +#: venv/lib/python3.11/site-packages/django/db/models/fields/__init__.py:2067 msgid "Integer" msgstr "عدد صحيح" -#: venv/lib/python3.11/site-packages/django/db/models/fields/__init__.py:2158 +#: venv/lib/python3.11/site-packages/django/db/models/fields/__init__.py:2163 msgid "Big (8 byte) integer" msgstr "عدد صحيح كبير (8 بايت)" -#: venv/lib/python3.11/site-packages/django/db/models/fields/__init__.py:2175 +#: venv/lib/python3.11/site-packages/django/db/models/fields/__init__.py:2180 msgid "Small integer" msgstr "عدد صحيح صغير" -#: venv/lib/python3.11/site-packages/django/db/models/fields/__init__.py:2183 +#: venv/lib/python3.11/site-packages/django/db/models/fields/__init__.py:2188 msgid "IPv4 address" msgstr "عنوان IPv4" -#: venv/lib/python3.11/site-packages/django/db/models/fields/__init__.py:2214 +#: venv/lib/python3.11/site-packages/django/db/models/fields/__init__.py:2219 msgid "IP address" msgstr "عنوان IP" -#: venv/lib/python3.11/site-packages/django/db/models/fields/__init__.py:2305 -#: venv/lib/python3.11/site-packages/django/db/models/fields/__init__.py:2306 +#: venv/lib/python3.11/site-packages/django/db/models/fields/__init__.py:2310 +#: venv/lib/python3.11/site-packages/django/db/models/fields/__init__.py:2311 #, python-format msgid "“%(value)s” value must be either None, True or False." msgstr "القيمة “%(value)s” يجب أن تكون إما None، True أو False." -#: venv/lib/python3.11/site-packages/django/db/models/fields/__init__.py:2308 +#: venv/lib/python3.11/site-packages/django/db/models/fields/__init__.py:2313 msgid "Boolean (Either True, False or None)" msgstr "قيمة منطقية (إما True أو False أو None)" -#: venv/lib/python3.11/site-packages/django/db/models/fields/__init__.py:2359 +#: venv/lib/python3.11/site-packages/django/db/models/fields/__init__.py:2364 msgid "Positive big integer" msgstr "عدد صحيح موجب كبير" -#: venv/lib/python3.11/site-packages/django/db/models/fields/__init__.py:2374 +#: venv/lib/python3.11/site-packages/django/db/models/fields/__init__.py:2379 msgid "Positive integer" msgstr "عدد صحيح موجب" -#: venv/lib/python3.11/site-packages/django/db/models/fields/__init__.py:2389 +#: venv/lib/python3.11/site-packages/django/db/models/fields/__init__.py:2394 msgid "Positive small integer" msgstr "عدد صحيح موجب صغير" -#: venv/lib/python3.11/site-packages/django/db/models/fields/__init__.py:2405 +#: venv/lib/python3.11/site-packages/django/db/models/fields/__init__.py:2410 #, python-format msgid "Slug (up to %(max_length)s)" msgstr "Slug (حتى %(max_length)s)" -#: venv/lib/python3.11/site-packages/django/db/models/fields/__init__.py:2441 +#: venv/lib/python3.11/site-packages/django/db/models/fields/__init__.py:2446 msgid "Text" msgstr "النص" -#: venv/lib/python3.11/site-packages/django/db/models/fields/__init__.py:2521 +#: venv/lib/python3.11/site-packages/django/db/models/fields/__init__.py:2526 #, python-format msgid "" "“%(value)s” value has an invalid format. It must be in HH:MM[:ss[.uuuuuu]] " @@ -9934,7 +10293,7 @@ msgstr "" "القيمة “%(value)s” تحتوي على تنسيق غير صالح. يجب أن تكون بالتنسيق " "HH:MM[:ss[.uuuuuu]]." -#: venv/lib/python3.11/site-packages/django/db/models/fields/__init__.py:2525 +#: venv/lib/python3.11/site-packages/django/db/models/fields/__init__.py:2530 #, python-format msgid "" "“%(value)s” value has the correct format (HH:MM[:ss[.uuuuuu]]) but it is an " @@ -9943,20 +10302,20 @@ msgstr "" "القيمة “%(value)s” تحتوي على التنسيق الصحيح (YYYY-MM-DD HH:MM[:ss[.uuuuuu]]" "[TZ]) لكنها تاريخ/وقت غير صالح." -#: venv/lib/python3.11/site-packages/django/db/models/fields/__init__.py:2637 +#: venv/lib/python3.11/site-packages/django/db/models/fields/__init__.py:2642 msgid "URL" msgstr "رابط URL" -#: venv/lib/python3.11/site-packages/django/db/models/fields/__init__.py:2661 +#: venv/lib/python3.11/site-packages/django/db/models/fields/__init__.py:2666 msgid "Raw binary data" msgstr "بيانات ثنائية خام" -#: venv/lib/python3.11/site-packages/django/db/models/fields/__init__.py:2726 +#: venv/lib/python3.11/site-packages/django/db/models/fields/__init__.py:2731 #, python-format msgid "“%(value)s” is not a valid UUID." msgstr "القيمة “%(value)s” ليست UUID صالح." -#: venv/lib/python3.11/site-packages/django/db/models/fields/__init__.py:2728 +#: venv/lib/python3.11/site-packages/django/db/models/fields/__init__.py:2733 msgid "Universally unique identifier" msgstr "معرّف فريد عالمي" @@ -9972,30 +10331,31 @@ msgstr "كائن JSON" msgid "Value must be valid JSON." msgstr "يجب أن تكون القيمة JSON صالح." -#: venv/lib/python3.11/site-packages/django/db/models/fields/related.py:932 -#, python-format -msgid "%(model)s instance with %(field)s %(value)r does not exist." +#: venv/lib/python3.11/site-packages/django/db/models/fields/related.py:978 +#, fuzzy, python-format +#| msgid "%(model)s instance with %(field)s %(value)r does not exist." +msgid "%(model)s instance with %(field)s %(value)r is not a valid choice." msgstr "المثال %(model)s مع %(field)s %(value)r غير موجود." -#: venv/lib/python3.11/site-packages/django/db/models/fields/related.py:934 +#: venv/lib/python3.11/site-packages/django/db/models/fields/related.py:981 msgid "Foreign Key (type determined by related field)" msgstr "مفتاح أجنبي (يحدد النوع حسب الحقل المرتبط)" -#: venv/lib/python3.11/site-packages/django/db/models/fields/related.py:1228 +#: venv/lib/python3.11/site-packages/django/db/models/fields/related.py:1275 msgid "One-to-one relationship" msgstr "علاقة واحد لواحد" -#: venv/lib/python3.11/site-packages/django/db/models/fields/related.py:1285 +#: venv/lib/python3.11/site-packages/django/db/models/fields/related.py:1332 #, python-format msgid "%(from)s-%(to)s relationship" msgstr "علاقة %(from)s-%(to)s" -#: venv/lib/python3.11/site-packages/django/db/models/fields/related.py:1287 +#: venv/lib/python3.11/site-packages/django/db/models/fields/related.py:1334 #, python-format msgid "%(from)s-%(to)s relationships" msgstr "علاقات %(from)s-%(to)s" -#: venv/lib/python3.11/site-packages/django/db/models/fields/related.py:1335 +#: venv/lib/python3.11/site-packages/django/db/models/fields/related.py:1382 msgid "Many-to-many relationship" msgstr "علاقة متعدد لمتعدد" @@ -10005,46 +10365,46 @@ msgstr "علاقة متعدد لمتعدد" msgid ":?.!" msgstr ":؟.!" -#: venv/lib/python3.11/site-packages/django/forms/fields.py:308 +#: venv/lib/python3.11/site-packages/django/forms/fields.py:315 msgid "Enter a whole number." msgstr "أدخل عدداً صحيحاً." -#: venv/lib/python3.11/site-packages/django/forms/fields.py:479 -#: venv/lib/python3.11/site-packages/django/forms/fields.py:1260 +#: venv/lib/python3.11/site-packages/django/forms/fields.py:486 +#: venv/lib/python3.11/site-packages/django/forms/fields.py:1267 msgid "Enter a valid date." msgstr "أدخل تاريخاً صالحاً." -#: venv/lib/python3.11/site-packages/django/forms/fields.py:502 -#: venv/lib/python3.11/site-packages/django/forms/fields.py:1261 +#: venv/lib/python3.11/site-packages/django/forms/fields.py:509 +#: venv/lib/python3.11/site-packages/django/forms/fields.py:1268 msgid "Enter a valid time." msgstr "أدخل وقتاً صالحاً." -#: venv/lib/python3.11/site-packages/django/forms/fields.py:529 +#: venv/lib/python3.11/site-packages/django/forms/fields.py:536 msgid "Enter a valid date/time." msgstr "أدخل تاريخاً/وقتاً صالحاً." -#: venv/lib/python3.11/site-packages/django/forms/fields.py:563 +#: venv/lib/python3.11/site-packages/django/forms/fields.py:570 msgid "Enter a valid duration." msgstr "أدخل مدة صالحة." -#: venv/lib/python3.11/site-packages/django/forms/fields.py:564 +#: venv/lib/python3.11/site-packages/django/forms/fields.py:571 #, python-brace-format msgid "The number of days must be between {min_days} and {max_days}." msgstr "يجب أن يكون عدد الأيام بين {min_days} و {max_days}." -#: venv/lib/python3.11/site-packages/django/forms/fields.py:633 +#: venv/lib/python3.11/site-packages/django/forms/fields.py:640 msgid "No file was submitted. Check the encoding type on the form." msgstr "لم يتم تقديم ملف. تحقق من نوع الترميز في النموذج." -#: venv/lib/python3.11/site-packages/django/forms/fields.py:634 +#: venv/lib/python3.11/site-packages/django/forms/fields.py:641 msgid "No file was submitted." msgstr "لم يتم تقديم أي ملف." -#: venv/lib/python3.11/site-packages/django/forms/fields.py:635 +#: venv/lib/python3.11/site-packages/django/forms/fields.py:642 msgid "The submitted file is empty." msgstr "الملف المقدم فارغ." -#: venv/lib/python3.11/site-packages/django/forms/fields.py:637 +#: venv/lib/python3.11/site-packages/django/forms/fields.py:644 #, python-format msgid "Ensure this filename has at most %(max)d character (it has %(length)d)." msgid_plural "" @@ -10054,48 +10414,48 @@ msgstr[0] "" msgstr[1] "" "تأكد من أن اسم الملف يحتوي على %(max)d أحرف كحد أقصى (يحتوي على %(length)d)." -#: venv/lib/python3.11/site-packages/django/forms/fields.py:642 +#: venv/lib/python3.11/site-packages/django/forms/fields.py:649 msgid "Please either submit a file or check the clear checkbox, not both." msgstr "يرجى إما تقديم ملف أو تحديد خانة الإزالة، وليس كليهما." -#: venv/lib/python3.11/site-packages/django/forms/fields.py:710 +#: venv/lib/python3.11/site-packages/django/forms/fields.py:717 msgid "" "Upload a valid image. The file you uploaded was either not an image or a " "corrupted image." msgstr "" "قم بتحميل صورة صالحة. الملف الذي قمت بتحميله إما ليس صورة أو صورة تالفة." -#: venv/lib/python3.11/site-packages/django/forms/fields.py:882 -#: venv/lib/python3.11/site-packages/django/forms/fields.py:968 +#: venv/lib/python3.11/site-packages/django/forms/fields.py:889 +#: venv/lib/python3.11/site-packages/django/forms/fields.py:975 #: venv/lib/python3.11/site-packages/django/forms/models.py:1592 #, python-format msgid "Select a valid choice. %(value)s is not one of the available choices." msgstr "اختر خياراً صالحاً. %(value)s ليس أحد الخيارات المتاحة." -#: venv/lib/python3.11/site-packages/django/forms/fields.py:970 -#: venv/lib/python3.11/site-packages/django/forms/fields.py:1089 +#: venv/lib/python3.11/site-packages/django/forms/fields.py:977 +#: venv/lib/python3.11/site-packages/django/forms/fields.py:1096 #: venv/lib/python3.11/site-packages/django/forms/models.py:1590 msgid "Enter a list of values." msgstr "أدخل قائمة بالقيم." -#: venv/lib/python3.11/site-packages/django/forms/fields.py:1090 +#: venv/lib/python3.11/site-packages/django/forms/fields.py:1097 msgid "Enter a complete value." msgstr "أدخل قيمة كاملة." -#: venv/lib/python3.11/site-packages/django/forms/fields.py:1332 +#: venv/lib/python3.11/site-packages/django/forms/fields.py:1339 msgid "Enter a valid UUID." msgstr "أدخل UUID صالحاً." -#: venv/lib/python3.11/site-packages/django/forms/fields.py:1362 +#: venv/lib/python3.11/site-packages/django/forms/fields.py:1369 msgid "Enter a valid JSON." msgstr "أدخل JSON صالحاً." #. Translators: This is the default suffix added to form field labels -#: venv/lib/python3.11/site-packages/django/forms/forms.py:94 +#: venv/lib/python3.11/site-packages/django/forms/forms.py:97 msgid ":" msgstr ":" -#: venv/lib/python3.11/site-packages/django/forms/forms.py:230 +#: venv/lib/python3.11/site-packages/django/forms/forms.py:239 #, python-format msgid "(Hidden field %(name)s) %(error)s" msgstr "(الحقل المخفي %(name)s) %(error)s" @@ -10159,7 +10519,7 @@ msgstr "اختر خياراً صالحاً. هذا الخيار ليس من ال msgid "“%(pk)s” is not a valid value." msgstr "“%(pk)s” ليست قيمة صالحة." -#: venv/lib/python3.11/site-packages/django/forms/utils.py:227 +#: venv/lib/python3.11/site-packages/django/forms/utils.py:229 #, python-format msgid "" "%(datetime)s couldn’t be interpreted in time zone %(current_timezone)s; it " @@ -10168,15 +10528,15 @@ msgstr "" "لم يتم تفسير %(datetime)s في المنطقة الزمنية %(current_timezone)s؛ قد يكون " "غامضاً أو قد لا يكون موجوداً." -#: venv/lib/python3.11/site-packages/django/forms/widgets.py:461 +#: venv/lib/python3.11/site-packages/django/forms/widgets.py:527 msgid "Clear" msgstr "مسح" -#: venv/lib/python3.11/site-packages/django/forms/widgets.py:462 +#: venv/lib/python3.11/site-packages/django/forms/widgets.py:528 msgid "Currently" msgstr "حالياً" -#: venv/lib/python3.11/site-packages/django/forms/widgets.py:800 +#: venv/lib/python3.11/site-packages/django/forms/widgets.py:866 msgid "Unknown" msgstr "غير معروف" @@ -10502,18 +10862,18 @@ msgstr "ديسمبر" msgid "This is not a valid IPv6 address." msgstr "هذا ليس عنوان IPv6 صالحاً." -#: venv/lib/python3.11/site-packages/django/utils/text.py:67 +#: venv/lib/python3.11/site-packages/django/utils/text.py:76 #, python-format msgctxt "String to return when truncating text" msgid "%(truncated_text)s…" msgstr "%(truncated_text)s…" -#: venv/lib/python3.11/site-packages/django/utils/text.py:278 +#: venv/lib/python3.11/site-packages/django/utils/text.py:287 msgid "or" msgstr "أو" #. Translators: This string is used as a separator between list elements -#: venv/lib/python3.11/site-packages/django/utils/text.py:297 +#: venv/lib/python3.11/site-packages/django/utils/text.py:306 #: venv/lib/python3.11/site-packages/django/utils/timesince.py:135 msgid ", " msgstr "، " @@ -10646,13 +11006,13 @@ msgstr "لم يتم تحديد اليوم" msgid "No week specified" msgstr "لم يتم تحديد الأسبوع" -#: venv/lib/python3.11/site-packages/django/views/generic/dates.py:349 -#: venv/lib/python3.11/site-packages/django/views/generic/dates.py:380 +#: venv/lib/python3.11/site-packages/django/views/generic/dates.py:353 +#: venv/lib/python3.11/site-packages/django/views/generic/dates.py:384 #, python-format msgid "No %(verbose_name_plural)s available" msgstr "لا توجد %(verbose_name_plural)s متاحة" -#: venv/lib/python3.11/site-packages/django/views/generic/dates.py:652 +#: venv/lib/python3.11/site-packages/django/views/generic/dates.py:680 #, python-format msgid "" "Future %(verbose_name_plural)s not available because " @@ -10661,7 +11021,7 @@ msgstr "" "%(verbose_name_plural)s المستقبلية غير متاحة لأن %(class_name)s. الخاصية " "allow_future هي False." -#: venv/lib/python3.11/site-packages/django/views/generic/dates.py:692 +#: venv/lib/python3.11/site-packages/django/views/generic/dates.py:720 #, python-format msgid "Invalid date string “%(datestr)s” given format “%(format)s”" msgstr "سلسلة التاريخ غير صالحة “%(datestr)s” بالصيغة “%(format)s”" @@ -10680,7 +11040,7 @@ msgstr "الصفحة ليست “الأخيرة”، ولا يمكن تحويل msgid "Invalid page (%(page_number)s): %(message)s" msgstr "صفحة غير صالحة (%(page_number)s): %(message)s" -#: venv/lib/python3.11/site-packages/django/views/generic/list.py:169 +#: venv/lib/python3.11/site-packages/django/views/generic/list.py:173 #, python-format msgid "Empty list and “%(class_name)s.allow_empty” is False." msgstr "قائمة فارغة والخاصية “%(class_name)s.allow_empty” هي False." @@ -10858,11 +11218,11 @@ msgstr "لا يمكن إنشاء إدخال إغلاق بتاريخ مستقبل msgid "Closing Date (YYYY-MM-DD)..." msgstr "تاريخ الإغلاق (YYYY-MM-DD)..." -#: venv/lib/python3.11/site-packages/django_ledger/forms/closing_entry.py:33 +#: venv/lib/python3.11/site-packages/django_ledger/forms/closing_entry.py:34 msgid "Select a Closing Date" msgstr "اختر تاريخ الإغلاق" -#: venv/lib/python3.11/site-packages/django_ledger/forms/closing_entry.py:50 +#: venv/lib/python3.11/site-packages/django_ledger/forms/closing_entry.py:51 msgid "Closing Entry Notes" msgstr "ملاحظات إدخال الإغلاق" @@ -11070,8 +11430,8 @@ msgstr "اسم المخزون" msgid "Cannot create new Journal Entries on a locked Ledger." msgstr "لا يمكن إنشاء إدخالات يومية جديدة على دفتر حسابات مقفل." -#: venv/lib/python3.11/site-packages/django_ledger/forms/journal_entry.py:63 -#: venv/lib/python3.11/site-packages/django_ledger/models/entity.py:3169 +#: venv/lib/python3.11/site-packages/django_ledger/forms/journal_entry.py:64 +#: venv/lib/python3.11/site-packages/django_ledger/models/entity.py:3182 #: venv/lib/python3.11/site-packages/django_ledger/templates/django_ledger/bills/bill_detail.html:95 #: venv/lib/python3.11/site-packages/django_ledger/templates/django_ledger/estimate/includes/estimate_item_table.html:9 msgid "Entity Unit" @@ -11114,14 +11474,14 @@ msgstr "يجب أن يتكون اسم الوحدة من 10 أحرف على ال msgid "Must provide all City/State/Zip/Country" msgstr "يجب توفير جميع المعلومات: المدينة/الولاية/الرمز البريدي/الدولة" -#: venv/lib/python3.11/site-packages/django_ledger/io/io_core.py:1357 +#: venv/lib/python3.11/site-packages/django_ledger/io/io_core.py:1379 msgid "Cannot commit on locked ledger" msgstr "لا يمكن تأكيد المعاملات على دفتر حسابات مقفل" -#: venv/lib/python3.11/site-packages/django_ledger/io/io_core.py:1566 -#: venv/lib/python3.11/site-packages/django_ledger/io/io_core.py:1695 -#: venv/lib/python3.11/site-packages/django_ledger/io/io_core.py:1812 -#: venv/lib/python3.11/site-packages/django_ledger/io/io_core.py:1936 +#: venv/lib/python3.11/site-packages/django_ledger/io/io_core.py:1592 +#: venv/lib/python3.11/site-packages/django_ledger/io/io_core.py:1721 +#: venv/lib/python3.11/site-packages/django_ledger/io/io_core.py:1838 +#: venv/lib/python3.11/site-packages/django_ledger/io/io_core.py:1962 msgid "PDF support not enabled. Install PDF support from Pipfile." msgstr "دعم PDF غير ممكّن. قم بتثبيت دعم PDF من Pipfile." @@ -11349,9 +11709,9 @@ msgid "Only one default account for role permitted." msgstr "يُسمح بحساب افتراضي واحد فقط للدور." #: venv/lib/python3.11/site-packages/django_ledger/models/bank_account.py:128 -#: venv/lib/python3.11/site-packages/django_ledger/models/closing_entry.py:69 -#: venv/lib/python3.11/site-packages/django_ledger/models/closing_entry.py:378 -#: venv/lib/python3.11/site-packages/django_ledger/models/entity.py:3166 +#: venv/lib/python3.11/site-packages/django_ledger/models/closing_entry.py:73 +#: venv/lib/python3.11/site-packages/django_ledger/models/closing_entry.py:390 +#: venv/lib/python3.11/site-packages/django_ledger/models/entity.py:3179 #: venv/lib/python3.11/site-packages/django_ledger/models/estimate.py:251 msgid "Entity Model" msgstr "نموذج الكيان" @@ -11453,7 +11813,7 @@ msgstr "هل تريد وضع الفاتورة %s كملغاة؟" #: venv/lib/python3.11/site-packages/django_ledger/models/chart_of_accounts.py:182 #: venv/lib/python3.11/site-packages/django_ledger/models/entity.py:795 -#: venv/lib/python3.11/site-packages/django_ledger/models/entity.py:3225 +#: venv/lib/python3.11/site-packages/django_ledger/models/entity.py:3237 #: venv/lib/python3.11/site-packages/django_ledger/models/purchase_order.py:217 msgid "Entity" msgstr "الكيان" @@ -11483,51 +11843,51 @@ msgstr "قائمة الحسابات نشطة حاليًا." msgid "The Chart of Accounts is currently not active." msgstr "قائمة الحسابات غير نشطة حاليًا." -#: venv/lib/python3.11/site-packages/django_ledger/models/chart_of_accounts.py:852 +#: venv/lib/python3.11/site-packages/django_ledger/models/chart_of_accounts.py:851 msgid "Default Chart of Accounts cannot be deactivated." msgstr "لا يمكن إلغاء تنشيط قائمة الحسابات الافتراضية." -#: venv/lib/python3.11/site-packages/django_ledger/models/closing_entry.py:72 +#: venv/lib/python3.11/site-packages/django_ledger/models/closing_entry.py:76 #: venv/lib/python3.11/site-packages/django_ledger/templates/django_ledger/closing_entry/tags/closing_entry_table.html:10 msgid "Is Posted" msgstr "تم النشر" -#: venv/lib/python3.11/site-packages/django_ledger/models/closing_entry.py:84 +#: venv/lib/python3.11/site-packages/django_ledger/models/closing_entry.py:88 msgid "Only one Closing Entry for Date Allowed." msgstr "مسموح بإدخال إغلاق واحد فقط لكل تاريخ." -#: venv/lib/python3.11/site-packages/django_ledger/models/closing_entry.py:273 +#: venv/lib/python3.11/site-packages/django_ledger/models/closing_entry.py:286 msgid "Cannot update transactions of a posted Closing Entry." msgstr "لا يمكن تحديث المعاملات لإدخال إغلاق تم نشره." -#: venv/lib/python3.11/site-packages/django_ledger/models/closing_entry.py:287 +#: venv/lib/python3.11/site-packages/django_ledger/models/closing_entry.py:300 msgid "" "This action will delete existing closing entry transactions and create new " "ones." msgstr "سيؤدي هذا الإجراء إلى حذف قيود الإغلاق الحالية وإنشاء قيود جديدة." -#: venv/lib/python3.11/site-packages/django_ledger/models/closing_entry.py:305 +#: venv/lib/python3.11/site-packages/django_ledger/models/closing_entry.py:318 msgid "Cannot delete a posted Closing Entry" msgstr "لا يمكن حذف إدخال إغلاق تم نشره" -#: venv/lib/python3.11/site-packages/django_ledger/models/closing_entry.py:319 +#: venv/lib/python3.11/site-packages/django_ledger/models/closing_entry.py:334 msgid "This action cannot be undone." msgstr "لا يمكن التراجع عن هذا الإجراء." -#: venv/lib/python3.11/site-packages/django_ledger/models/closing_entry.py:373 +#: venv/lib/python3.11/site-packages/django_ledger/models/closing_entry.py:385 msgid "Account Model" msgstr "نموذج الحساب" -#: venv/lib/python3.11/site-packages/django_ledger/models/closing_entry.py:387 -#: venv/lib/python3.11/site-packages/django_ledger/models/transactions.py:428 +#: venv/lib/python3.11/site-packages/django_ledger/models/closing_entry.py:399 +#: venv/lib/python3.11/site-packages/django_ledger/models/transactions.py:452 msgid "Transaction Type" msgstr "نوع المعاملة" -#: venv/lib/python3.11/site-packages/django_ledger/models/closing_entry.py:388 +#: venv/lib/python3.11/site-packages/django_ledger/models/closing_entry.py:400 msgid "Closing Entry Balance" msgstr "رصيد إدخال الإغلاق" -#: venv/lib/python3.11/site-packages/django_ledger/models/closing_entry.py:398 +#: venv/lib/python3.11/site-packages/django_ledger/models/closing_entry.py:410 msgid "Closing Entry Model" msgstr "نموذج إدخال الإغلاق" @@ -11581,7 +11941,7 @@ msgstr "نموذج وحدة الكيان" msgid "Staged Transaction Model" msgstr "نموذج المعاملة المتدرجة" -#: venv/lib/python3.11/site-packages/django_ledger/models/data_import.py:1187 +#: venv/lib/python3.11/site-packages/django_ledger/models/data_import.py:1186 msgid "Invalid Bank Account for LedgerModel. No matching Entity Model found." msgstr "" "حساب مصرفي غير صالح لنموذج دفتر الحسابات. لم يتم العثور على نموذج كيان مطابق." @@ -11628,7 +11988,7 @@ msgstr "مسموح فقط بالمعرف، UUID أو نموذج الكيان." msgid "No default_coa found." msgstr "لم يتم العثور على قائمة حسابات افتراضية." -#: venv/lib/python3.11/site-packages/django_ledger/models/entity.py:2830 +#: venv/lib/python3.11/site-packages/django_ledger/models/entity.py:2844 msgid "" "Closing books must be called by providing closing_date or " "closing_entry_model, not both." @@ -11636,32 +11996,32 @@ msgstr "" "يجب استدعاء إغلاق الدفاتر إما بتحديد تاريخ الإغلاق أو نموذج إدخال الإغلاق، " "وليس كليهما." -#: venv/lib/python3.11/site-packages/django_ledger/models/entity.py:2834 +#: venv/lib/python3.11/site-packages/django_ledger/models/entity.py:2848 msgid "" "Closing books must be called by providing closing_date or " "closing_entry_model." msgstr "" "يجب استدعاء إغلاق الدفاتر إما بتحديد تاريخ الإغلاق أو نموذج إدخال الإغلاق." -#: venv/lib/python3.11/site-packages/django_ledger/models/entity.py:3156 +#: venv/lib/python3.11/site-packages/django_ledger/models/entity.py:3169 #: venv/lib/python3.11/site-packages/django_ledger/models/journal_entry.py:407 -#: venv/lib/python3.11/site-packages/django_ledger/models/transactions.py:433 +#: venv/lib/python3.11/site-packages/django_ledger/models/transactions.py:457 msgid "Journal Entry" msgstr "إدخال دفتر اليومية" -#: venv/lib/python3.11/site-packages/django_ledger/models/entity.py:3217 +#: venv/lib/python3.11/site-packages/django_ledger/models/entity.py:3229 msgid "Read Permissions" msgstr "أذونات القراءة" -#: venv/lib/python3.11/site-packages/django_ledger/models/entity.py:3218 +#: venv/lib/python3.11/site-packages/django_ledger/models/entity.py:3230 msgid "Read/Write Permissions" msgstr "أذونات القراءة/الكتابة" -#: venv/lib/python3.11/site-packages/django_ledger/models/entity.py:3229 +#: venv/lib/python3.11/site-packages/django_ledger/models/entity.py:3241 msgid "Manager" msgstr "مدير" -#: venv/lib/python3.11/site-packages/django_ledger/models/entity.py:3234 +#: venv/lib/python3.11/site-packages/django_ledger/models/entity.py:3246 msgid "Permission Level" msgstr "مستوى الأذونات" @@ -12013,10 +12373,6 @@ msgstr "تم الاستلام" msgid "Associated Entity Unit" msgstr "وحدة الكيان المرتبطة" -#: venv/lib/python3.11/site-packages/django_ledger/models/items.py:1053 -msgid "Item Model" -msgstr "نموذج العنصر" - #: venv/lib/python3.11/site-packages/django_ledger/models/items.py:1058 msgid "Bill Model" msgstr "نموذج الفاتورة" @@ -12304,43 +12660,48 @@ msgstr "هل تريد وضع أمر الشراء %s على أنه تم التن msgid "Do you want to mark Purchase Order %s as Void?" msgstr "هل تريد إبطال أمر الشراء %s؟" -#: venv/lib/python3.11/site-packages/django_ledger/models/transactions.py:434 +#: venv/lib/python3.11/site-packages/django_ledger/models/transactions.py:88 +#: venv/lib/python3.11/site-packages/django_ledger/models/transactions.py:97 +msgid "Account list must be a list of AccountModel, UUID or str objects (codes)." +msgstr "يجب أن تكون قائمة الحسابات عبارة عن قائمة من كائنات AccountModel أو UUID أو كائنات نصية (رموز)." + +#: venv/lib/python3.11/site-packages/django_ledger/models/transactions.py:458 msgid "Journal Entry to be associated with this transaction." msgstr "إدخال دفتر اليومية المرتبط بهذه المعاملة." -#: venv/lib/python3.11/site-packages/django_ledger/models/transactions.py:440 +#: venv/lib/python3.11/site-packages/django_ledger/models/transactions.py:464 msgid "Account from Chart of Accounts to be associated with this transaction." msgstr "الحساب من مخطط الحسابات المرتبط بهذه المعاملة." -#: venv/lib/python3.11/site-packages/django_ledger/models/transactions.py:448 +#: venv/lib/python3.11/site-packages/django_ledger/models/transactions.py:472 msgid "Amount of the transaction." msgstr "مبلغ المعاملة." -#: venv/lib/python3.11/site-packages/django_ledger/models/transactions.py:455 +#: venv/lib/python3.11/site-packages/django_ledger/models/transactions.py:479 msgid "Transaction Description" msgstr "وصف المعاملة" -#: venv/lib/python3.11/site-packages/django_ledger/models/transactions.py:456 +#: venv/lib/python3.11/site-packages/django_ledger/models/transactions.py:480 msgid "A description to be included with this individual transaction." msgstr "وصف يتم تضمينه مع هذه المعاملة الفردية." -#: venv/lib/python3.11/site-packages/django_ledger/models/transactions.py:458 +#: venv/lib/python3.11/site-packages/django_ledger/models/transactions.py:482 msgid "Cleared" msgstr "تمت التسوية" -#: venv/lib/python3.11/site-packages/django_ledger/models/transactions.py:459 +#: venv/lib/python3.11/site-packages/django_ledger/models/transactions.py:483 msgid "Reconciled" msgstr "تمت المطابقة" -#: venv/lib/python3.11/site-packages/django_ledger/models/transactions.py:465 +#: venv/lib/python3.11/site-packages/django_ledger/models/transactions.py:489 msgid "Transaction" msgstr "معاملة" -#: venv/lib/python3.11/site-packages/django_ledger/models/transactions.py:574 +#: venv/lib/python3.11/site-packages/django_ledger/models/transactions.py:597 msgid "Transactions cannot be linked to root accounts." msgstr "لا يمكن ربط المعاملات بالحسابات الجذرية." -#: venv/lib/python3.11/site-packages/django_ledger/models/transactions.py:586 +#: venv/lib/python3.11/site-packages/django_ledger/models/transactions.py:609 msgid "Cannot modify transactions on locked journal entries." msgstr "لا يمكن تعديل المعاملات على إدخالات دفتر اليومية المقفلة." @@ -12358,7 +12719,7 @@ msgstr "كيان المورد" #: venv/lib/python3.11/site-packages/django_ledger/templates/django_ledger/account/account_create.html:10 #: venv/lib/python3.11/site-packages/django_ledger/templates/django_ledger/account/account_list.html:19 -#: venv/lib/python3.11/site-packages/django_ledger/views/account.py:98 +#: venv/lib/python3.11/site-packages/django_ledger/views/account.py:107 msgid "Create Account" msgstr "إنشاء حساب" @@ -12367,8 +12728,8 @@ msgid "Account Transaction List Report" msgstr "تقرير قائمة معاملات الحساب" #: venv/lib/python3.11/site-packages/django_ledger/templates/django_ledger/account/account_list.html:10 -msgid "Accounts List" -msgstr "قائمة الحسابات" +msgid "CoA Account List" +msgstr "قائمة حسابات دليل الحسابات" #: venv/lib/python3.11/site-packages/django_ledger/templates/django_ledger/account/account_list.html:21 msgid "Back to CoA List" @@ -12382,7 +12743,7 @@ msgstr "مخطط الحسابات" msgid "CoA Role Default" msgstr "الدور الافتراضي لمخطط الحسابات" -#: venv/lib/python3.11/site-packages/django_ledger/templates/django_ledger/account/tags/accounts_table.html:100 +#: venv/lib/python3.11/site-packages/django_ledger/templates/django_ledger/account/tags/accounts_table.html:96 #: venv/lib/python3.11/site-packages/django_ledger/templates/django_ledger/financial_statements/tags/balance_sheet_statement.html:64 #: venv/lib/python3.11/site-packages/django_ledger/templates/django_ledger/financial_statements/tags/income_statement.html:58 #: venv/lib/python3.11/site-packages/django_ledger/templates/django_ledger/financial_statements/tags/income_statement.html:119 @@ -12393,15 +12754,10 @@ msgid "Detail" msgstr "التفاصيل" #: venv/lib/python3.11/site-packages/django_ledger/templates/django_ledger/account/tags/accounts_table.html:105 -#: venv/lib/python3.11/site-packages/django_ledger/templates/django_ledger/bank_account/tags/bank_accounts_table.html:52 -msgid "Activate" -msgstr "تفعيل" - -#: venv/lib/python3.11/site-packages/django_ledger/templates/django_ledger/account/tags/accounts_table.html:109 msgid "Deactivate" msgstr "إلغاء التفعيل" -#: venv/lib/python3.11/site-packages/django_ledger/templates/django_ledger/account/tags/accounts_table.html:117 +#: venv/lib/python3.11/site-packages/django_ledger/templates/django_ledger/account/tags/accounts_table.html:113 #: venv/lib/python3.11/site-packages/django_ledger/templates/django_ledger/journal_entry/je_detail.html:29 #: venv/lib/python3.11/site-packages/django_ledger/templates/django_ledger/journal_entry/tags/je_table.html:80 msgid "Unlock" @@ -12614,7 +12970,7 @@ msgstr "وضع كنشط" #: venv/lib/python3.11/site-packages/django_ledger/templates/django_ledger/closing_entry/closing_entry_create.html:9 #: venv/lib/python3.11/site-packages/django_ledger/templates/django_ledger/closing_entry/closing_entry_create.html:20 -#: venv/lib/python3.11/site-packages/django_ledger/views/closing_entry.py:76 +#: venv/lib/python3.11/site-packages/django_ledger/views/closing_entry.py:72 msgid "Create Closing Entry" msgstr "إنشاء إدخال إغلاق" @@ -12750,7 +13106,7 @@ msgstr "قائمة مهام الاستيراد" msgid "Manage" msgstr "إدارة" -#: venv/lib/python3.11/site-packages/django_ledger/templates/django_ledger/data_import/tags/data_import_job_txs_imported.html:32 +#: venv/lib/python3.11/site-packages/django_ledger/templates/django_ledger/data_import/tags/data_import_job_txs_imported.html:33 msgid "View JE" msgstr "عرض إدخال الدفتر" @@ -13168,11 +13524,11 @@ msgstr "تحديث المورد" msgid "Entity Accounts" msgstr "حسابات الكيان" -#: venv/lib/python3.11/site-packages/django_ledger/views/account.py:91 +#: venv/lib/python3.11/site-packages/django_ledger/views/account.py:100 msgid "WARNING: The chart of accounts list is inactive." msgstr "تحذير: قائمة دليل الحسابات غير نشطة." -#: venv/lib/python3.11/site-packages/django_ledger/views/account.py:144 +#: venv/lib/python3.11/site-packages/django_ledger/views/account.py:153 msgid "Update Account" msgstr "تحديث الحساب" @@ -13188,10 +13544,14 @@ msgstr "إنشاء دليل الحسابات" msgid "Successfully updated {} Default Chart of Account to " msgstr "تم تحديث دليل الحسابات الافتراضي {} بنجاح إلى" -#: venv/lib/python3.11/site-packages/django_ledger/views/closing_entry.py:50 +#: venv/lib/python3.11/site-packages/django_ledger/views/closing_entry.py:48 msgid "Closing Entry List" msgstr "قائمة إدخال الإغلاق" +#: venv/lib/python3.11/site-packages/django_ledger/views/closing_entry.py:169 +msgid "Delete Closing Entry" +msgstr "حذف القيد الختامي" + #: venv/lib/python3.11/site-packages/django_ledger/views/customer.py:35 msgid "Customer List" msgstr "قائمة العملاء" @@ -13409,100 +13769,113 @@ msgstr "تحديث وحدة الكيان" msgid "Vendor List" msgstr "قائمة الموردين" -#: venv/lib/python3.11/site-packages/django_ledger/views/vendor.py:44 +#: venv/lib/python3.11/site-packages/django_ledger/views/vendor.py:50 msgid "Create New Vendor" msgstr "إنشاء مورد جديد" -#: venv/lib/python3.11/site-packages/django_ledger/views/vendor.py:71 +#: venv/lib/python3.11/site-packages/django_ledger/views/vendor.py:77 msgid "Vendor Update" msgstr "تحديث المورد" -#: venv/lib/python3.11/site-packages/django_pdf_actions/models.py:27 +#: venv/lib/python3.11/site-packages/django_pdf_actions/models.py:34 #, python-format msgid "%(value)s is not a valid hex color. Format should be #RRGGBB or #RGB" msgstr "%(value)s ليس لون سداسي عشري صالح. يجب أن يكون التنسيق #RRGGBB أو #RGB" -#: venv/lib/python3.11/site-packages/django_pdf_actions/models.py:66 +#: venv/lib/python3.11/site-packages/django_pdf_actions/models.py:73 msgid "Name of this configuration" msgstr "اسم هذا التكوين" -#: venv/lib/python3.11/site-packages/django_pdf_actions/models.py:70 +#: venv/lib/python3.11/site-packages/django_pdf_actions/models.py:77 msgid "Only one configuration can be active at a time" msgstr "يمكن أن يكون هناك تكوين نشط واحد فقط في كل مرة" -#: venv/lib/python3.11/site-packages/django_pdf_actions/models.py:78 +#: venv/lib/python3.11/site-packages/django_pdf_actions/models.py:85 msgid "Select the page size for the PDF" msgstr "اختر حجم الصفحة لملف PDF" -#: venv/lib/python3.11/site-packages/django_pdf_actions/models.py:83 +#: venv/lib/python3.11/site-packages/django_pdf_actions/models.py:90 msgid "Number of items to display per page" msgstr "عدد العناصر التي سيتم عرضها لكل صفحة" -#: venv/lib/python3.11/site-packages/django_pdf_actions/models.py:88 +#: venv/lib/python3.11/site-packages/django_pdf_actions/models.py:95 msgid "Page margin in millimeters" msgstr "هامش الصفحة بالمليمترات" -#: venv/lib/python3.11/site-packages/django_pdf_actions/models.py:96 +#: venv/lib/python3.11/site-packages/django_pdf_actions/models.py:103 msgid "Select font from available system fonts" msgstr "حدد الخط من الخطوط المتاحة في النظام" -#: venv/lib/python3.11/site-packages/django_pdf_actions/models.py:101 +#: venv/lib/python3.11/site-packages/django_pdf_actions/models.py:108 msgid "Font size for headers" msgstr "حجم الخط للعناوين" -#: venv/lib/python3.11/site-packages/django_pdf_actions/models.py:106 +#: venv/lib/python3.11/site-packages/django_pdf_actions/models.py:113 msgid "Font size for table content" msgstr "حجم الخط لمحتوى الجدول" -#: venv/lib/python3.11/site-packages/django_pdf_actions/models.py:112 +#: venv/lib/python3.11/site-packages/django_pdf_actions/models.py:119 msgid "Logo to display on PDF" msgstr "الشعار المعروض في ملف PDF" -#: venv/lib/python3.11/site-packages/django_pdf_actions/models.py:118 +#: venv/lib/python3.11/site-packages/django_pdf_actions/models.py:125 msgid "Header background color (hex format, e.g. #F0F0F0)" msgstr "لون خلفية العنوان (تنسيق سداسي عشري، مثل #F0F0F0)" -#: venv/lib/python3.11/site-packages/django_pdf_actions/models.py:122 +#: venv/lib/python3.11/site-packages/django_pdf_actions/models.py:129 msgid "Grid line color (hex format, e.g. #000000)" msgstr "لون خطوط الشبكة (تنسيق سداسي عشري، مثل #000000)" -#: venv/lib/python3.11/site-packages/django_pdf_actions/models.py:127 +#: venv/lib/python3.11/site-packages/django_pdf_actions/models.py:134 msgid "Grid line width in points" msgstr "عرض خطوط الشبكة بالنقاط" -#: venv/lib/python3.11/site-packages/django_pdf_actions/models.py:133 +#: venv/lib/python3.11/site-packages/django_pdf_actions/models.py:140 msgid "Display the header with model name" msgstr "عرض العنوان مع اسم النموذج" -#: venv/lib/python3.11/site-packages/django_pdf_actions/models.py:137 +#: venv/lib/python3.11/site-packages/django_pdf_actions/models.py:144 msgid "Display the logo in the PDF" msgstr "عرض الشعار في ملف PDF" -#: venv/lib/python3.11/site-packages/django_pdf_actions/models.py:141 +#: venv/lib/python3.11/site-packages/django_pdf_actions/models.py:148 msgid "Display export timestamp" msgstr "عرض الطابع الزمني للتصدير" -#: venv/lib/python3.11/site-packages/django_pdf_actions/models.py:145 +#: venv/lib/python3.11/site-packages/django_pdf_actions/models.py:152 msgid "Display page numbers" msgstr "عرض أرقام الصفحات" -#: venv/lib/python3.11/site-packages/django_pdf_actions/models.py:152 +#: venv/lib/python3.11/site-packages/django_pdf_actions/models.py:156 +msgid "Enable right-to-left (RTL) text support for Arabic and other RTL languages" +msgstr "تمكين دعم النص من اليمين إلى اليسار (RTL) للغة العربية واللغات الأخرى التي تُكتب من اليمين إلى اليسار" + +msgid "Text alignment for table content" +msgstr "محاذاة النص لمحتوى الجدول" + +msgid "Text alignment for table headers" +msgstr "محاذاة النص لعناوين الجدول" + +msgid "Text alignment for the title" +msgstr "محاذاة النص لعنوان التقرير" + +#: venv/lib/python3.11/site-packages/django_pdf_actions/models.py:181 msgid "Spacing between table cells in millimeters" msgstr "المسافة بين خلايا الجدول بالمليمترات" -#: venv/lib/python3.11/site-packages/django_pdf_actions/models.py:157 +#: venv/lib/python3.11/site-packages/django_pdf_actions/models.py:186 msgid "Maximum characters per line before wrapping" msgstr "الحد الأقصى لعدد الأحرف في السطر قبل الانتقال إلى سطر جديد" -#: venv/lib/python3.11/site-packages/django_pdf_actions/models.py:171 +#: venv/lib/python3.11/site-packages/django_pdf_actions/models.py:200 msgid "" "There can only be one active configuration. Please deactivate the current " "active configuration first." msgstr "" "يمكن أن يكون هناك تكوين نشط واحد فقط. يرجى إلغاء تنشيط التكوين الحالي أولاً." -#: venv/lib/python3.11/site-packages/django_pdf_actions/models.py:175 -#: venv/lib/python3.11/site-packages/django_pdf_actions/models.py:176 +#: venv/lib/python3.11/site-packages/django_pdf_actions/models.py:204 +#: venv/lib/python3.11/site-packages/django_pdf_actions/models.py:205 msgid "Export PDF Settings" msgstr "إعدادات تصدير PDF" @@ -13520,10 +13893,10 @@ msgid "" "Message Django's middlewares" msgstr "" -#: venv/lib/python3.11/site-packages/sympy/solvers/simplex.py:564 +#: venv/lib/python3.11/site-packages/sympy/solvers/simplex.py:563 msgid "x" msgstr "س" -#: venv/lib/python3.11/site-packages/sympy/solvers/simplex.py:565 +#: venv/lib/python3.11/site-packages/sympy/solvers/simplex.py:564 msgid "y" msgstr "ص" diff --git a/plan.json b/plan.json new file mode 100644 index 00000000..65f58260 --- /dev/null +++ b/plan.json @@ -0,0 +1,50 @@ +[ +{ + "model": "plans.plan", + "pk": 1, + "fields": { + "order": 0, + "created": "2025-05-03T16:27:13.240Z", + "updated_at": "2025-05-03T16:27:13.240Z", + "name": "الأساسية", + "description": "مثالية لوكالات السيارات الصغيرة أو الأفراد الذين يديرون عددًا محدودًا من السيارات\r\nتتيح الخطة إدارة ما يصل إلى 3 مستخدمين\r\nتتيح الخطة إدارة ما يصل إلى 100 مركبة\r\nتوفر ميزات أساسية لمتابعة المبيعات والمخزون بسهولة دون تكلفة مرتفعة", + "default": null, + "available": true, + "visible": true, + "customized": null, + "url": "" + } +}, +{ + "model": "plans.plan", + "pk": 2, + "fields": { + "order": 1, + "created": "2025-05-03T16:29:17.050Z", + "updated_at": "2025-05-03T16:29:17.050Z", + "name": "المتقدمة", + "description": "مصممة للوكالات المتوسطة الحجم التي تحتاج إلى إدارة عدد أكبر من المستخدمين والمخزون\r\nتدعم 6 مستخدمين\r\nوما يصل إلى 300 مركبة في المخزون\r\nتشمل أدوات إضافية لتحليل الأداء وتتبع المبيعات وإدارة المعاملات بسهولة.", + "default": null, + "available": true, + "visible": true, + "customized": null, + "url": "" + } +}, +{ + "model": "plans.plan", + "pk": 3, + "fields": { + "order": 2, + "created": "2025-05-03T16:30:47.026Z", + "updated_at": "2025-05-03T16:30:47.026Z", + "name": "البلاتينيوم", + "description": "الخيار الأمثل للوكالات الكبيرة التي تتعامل مع حجم عملاء كبير ومخزون واسع\r\nتدعم 12 مستخدمًا\r\nوما يصل إلى 1000 مركبة في المخزون\r\nتوفر ميزات متقدمة لتحسين الكفاءة مثل التحليلات المخصصة، ودعم العملاء المتميز، وإدارة العقود والمستندات", + "default": null, + "available": true, + "visible": true, + "customized": null, + "url": "" + } +} +] diff --git a/planpricing.json b/planpricing.json new file mode 100644 index 00000000..e9d4d947 --- /dev/null +++ b/planpricing.json @@ -0,0 +1,86 @@ +[ +{ + "model": "plans.planpricing", + "pk": 1, + "fields": { + "created": "2025-05-03T16:27:13.240Z", + "updated_at": "2025-05-03T16:27:13.240Z", + "plan": 1, + "pricing": 1, + "price": "600.00", + "order": 0, + "has_automatic_renewal": false, + "visible": true + } +}, +{ + "model": "plans.planpricing", + "pk": 2, + "fields": { + "created": "2025-05-03T16:27:13.241Z", + "updated_at": "2025-05-03T16:27:13.241Z", + "plan": 1, + "pricing": 2, + "price": "6480.00", + "order": 0, + "has_automatic_renewal": false, + "visible": true + } +}, +{ + "model": "plans.planpricing", + "pk": 3, + "fields": { + "created": "2025-05-03T16:29:17.051Z", + "updated_at": "2025-05-03T16:29:17.051Z", + "plan": 2, + "pricing": 1, + "price": "900.00", + "order": 0, + "has_automatic_renewal": false, + "visible": true + } +}, +{ + "model": "plans.planpricing", + "pk": 4, + "fields": { + "created": "2025-05-03T16:29:17.051Z", + "updated_at": "2025-05-03T16:29:17.051Z", + "plan": 2, + "pricing": 2, + "price": "9720.00", + "order": 0, + "has_automatic_renewal": false, + "visible": true + } +}, +{ + "model": "plans.planpricing", + "pk": 5, + "fields": { + "created": "2025-05-03T16:30:47.026Z", + "updated_at": "2025-05-03T16:30:47.026Z", + "plan": 3, + "pricing": 1, + "price": "1300.00", + "order": 0, + "has_automatic_renewal": false, + "visible": true + } +}, +{ + "model": "plans.planpricing", + "pk": 6, + "fields": { + "created": "2025-05-03T16:30:47.027Z", + "updated_at": "2025-05-03T16:30:47.027Z", + "plan": 3, + "pricing": 2, + "price": "14040.00", + "order": 0, + "has_automatic_renewal": false, + "visible": true + } +} +] diff --git a/planquota.json b/planquota.json new file mode 100644 index 00000000..71fc0ab5 --- /dev/null +++ b/planquota.json @@ -0,0 +1,68 @@ +[ +{ + "model": "plans.planquota", + "pk": 1, + "fields": { + "created": "2025-05-03T16:27:13.241Z", + "updated_at": "2025-05-03T16:27:13.241Z", + "plan": 1, + "quota": 1, + "value": 3 + } +}, +{ + "model": "plans.planquota", + "pk": 2, + "fields": { + "created": "2025-05-03T16:27:13.241Z", + "updated_at": "2025-05-03T16:27:13.241Z", + "plan": 1, + "quota": 2, + "value": 100 + } +}, +{ + "model": "plans.planquota", + "pk": 3, + "fields": { + "created": "2025-05-03T16:29:17.051Z", + "updated_at": "2025-05-03T16:29:17.051Z", + "plan": 2, + "quota": 1, + "value": 6 + } +}, +{ + "model": "plans.planquota", + "pk": 4, + "fields": { + "created": "2025-05-03T16:29:17.052Z", + "updated_at": "2025-05-03T16:29:17.052Z", + "plan": 2, + "quota": 2, + "value": 300 + } +}, +{ + "model": "plans.planquota", + "pk": 5, + "fields": { + "created": "2025-05-03T16:30:47.027Z", + "updated_at": "2025-05-03T16:30:47.027Z", + "plan": 3, + "quota": 1, + "value": 12 + } +}, +{ + "model": "plans.planquota", + "pk": 6, + "fields": { + "created": "2025-05-03T16:30:47.027Z", + "updated_at": "2025-05-03T16:30:47.027Z", + "plan": 3, + "quota": 2, + "value": 1000 + } +} +] diff --git a/pricing.json b/pricing.json new file mode 100644 index 00000000..31c66042 --- /dev/null +++ b/pricing.json @@ -0,0 +1,24 @@ +[ +{ + "model": "plans.pricing", + "pk": 1, + "fields": { + "created": "2025-05-03T16:25:31.501Z", + "updated_at": "2025-05-03T16:25:31.501Z", + "name": "شهري", + "period": 30, + "url": "" + } +}, +{ + "model": "plans.pricing", + "pk": 2, + "fields": { + "created": "2025-05-03T16:25:45.320Z", + "updated_at": "2025-05-03T16:25:45.320Z", + "name": "سنوي", + "period": 365, + "url": "" + } +} +] diff --git a/quota.json b/quota.json new file mode 100644 index 00000000..d7128b4c --- /dev/null +++ b/quota.json @@ -0,0 +1,32 @@ +[ +{ + "model": "plans.quota", + "pk": 1, + "fields": { + "order": 0, + "created": "2025-05-03T16:26:49.537Z", + "updated_at": "2025-05-03T16:26:49.537Z", + "codename": "Users", + "name": "مستخدم", + "unit": "", + "description": "", + "is_boolean": false, + "url": "" + } +}, +{ + "model": "plans.quota", + "pk": 2, + "fields": { + "order": 1, + "created": "2025-05-03T16:27:03.802Z", + "updated_at": "2025-05-03T16:27:03.802Z", + "codename": "Cars", + "name": "سيارات", + "unit": "", + "description": "", + "is_boolean": false, + "url": "" + } +} +] diff --git a/requirements.txt b/requirements.txt index d60b3bf9..e39311be 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,13 +1,14 @@ aiohappyeyeballs==2.6.1 -aiohttp==3.11.18 +aiohttp==3.12.0 aiohttp-retry==2.9.1 aiosignal==1.3.2 alabaster==1.0.0 albucore==0.0.24 -albumentations==2.0.6 +albumentations==2.0.7 annotated-types==0.7.0 anyio==4.9.0 arabic-reshaper==3.0.0 +arrow==1.3.0 asgiref==3.8.1 astor==0.8.1 astroid==3.3.10 @@ -16,6 +17,7 @@ autopep8==2.3.2 Babel==2.15.0 beautifulsoup4==4.13.4 bleach==6.2.0 +blessed==1.21.0 blinker==1.9.0 Brotli==1.1.0 cattrs==24.1.3 @@ -23,16 +25,17 @@ certifi==2025.4.26 cffi==1.17.1 chardet==5.2.0 charset-normalizer==3.4.2 -click==8.2.0 +click==8.2.1 colorama==0.4.6 commonmark==0.9.1 contourpy==1.3.2 crispy-bootstrap5==2025.4 -cryptography==44.0.3 +cryptography==45.0.3 cssselect2==0.8.0 ctranslate2==4.6.0 cycler==0.12.1 -Cython==3.1.0 +Cython==3.1.1 +dataclasses-json==0.6.7 decorator==5.2.1 defusedxml==0.7.1 desert==2020.11.18 @@ -40,13 +43,13 @@ diff-match-patch==20241021 dill==0.4.0 distro==1.9.0 dj-rest-auth==7.0.1 -dj-shop-cart==8.0.0a2 Django==5.2.1 -django-allauth==65.8.0 +django-allauth==65.8.1 django-appointment==3.8.0 django-autoslug==1.9.9 django-background-tasks==1.2.8 django-bootstrap5==25.1 +django-ckeditor==6.7.2 django-classy-tags==4.1.0 django-cors-headers==4.7.0 django-countries==7.6.1 @@ -56,6 +59,7 @@ django-extensions==4.1 django-filter==25.1 django-formtools==2.5.1 django-import-export==4.3.7 +django-js-asset==3.1.2 django-ledger==0.7.7 django-model-utils==5.0.0 django-money==3.5.4 @@ -64,7 +68,7 @@ django-nine==0.2.7 django-nonefield==0.4 django-ordered-model==3.7.4 django-pdf-actions==0.1.49 -django-phonenumber-field==8.1.0 +django-phonenumber-field==8.0.0 django-picklefield==3.3 django-plans==2.0.0 django-prometheus==2.3.1 @@ -79,23 +83,25 @@ django-sslserver==0.22 django-tables2==2.7.5 django-treebeard==4.7.1 django-view-breadcrumbs==2.5.1 +django-widget-tweaks==1.5.0 djangocms-admin-style==3.3.1 djangorestframework==3.16.0 djangorestframework_simplejwt==5.5.0 djangoviz==0.1.1 +djhtml==3.0.8 docopt==0.6.2 docutils==0.21.2 easy-thumbnails==2.10 emoji==2.14.1 et_xmlfile==2.0.0 -Faker==37.1.0 +Faker==37.3.0 filelock==3.18.0 fire==0.7.0 -Flask==3.1.0 fonttools==4.58.0 +fpdf==1.7.2 fpdf2==2.8.3 frozenlist==1.6.0 -fsspec==2025.3.2 +fsspec==2025.5.1 gprof2dot==2025.4.14 graphqlclient==0.2.4 greenlet==3.2.2 @@ -105,8 +111,9 @@ hpack==4.1.0 hstspreload==2025.1.1 httpcore==1.0.9 httpx==0.28.1 +httpx-sse==0.4.0 hyperframe==6.1.0 -icalendar==6.2.0 +icalendar==6.3.1 idna==3.10 imageio==2.37.0 imagesize==1.4.1 @@ -116,9 +123,17 @@ isodate==0.7.2 isort==6.0.1 itsdangerous==2.2.0 Jinja2==3.1.6 -jiter==0.9.0 -joblib==1.5.0 +jiter==0.10.0 +joblib==1.5.1 +jsonpatch==1.33 +jsonpointer==3.0.0 +jwt==1.3.1 kiwisolver==1.4.8 +langchain==0.3.25 +langchain-community==0.3.24 +langchain-core==0.3.61 +langchain-text-splitters==0.3.8 +langsmith==0.3.42 lazy_loader==0.4 ledger==1.0.1 libretranslatepy==2.1.4 @@ -128,54 +143,56 @@ lxml==5.4.0 Markdown==3.8 markdown-it-py==3.0.0 MarkupSafe==3.0.2 -marshmallow==4.0.0 +marshmallow==3.26.1 matplotlib==3.10.3 mccabe==0.7.0 mdurl==0.1.2 MouseInfo==0.1.3 mpmath==1.3.0 -multidict==6.4.3 +multidict==6.4.4 mypy_extensions==1.1.0 networkx==3.4.2 -newrelic==10.11.0 +newrelic==10.12.0 nltk==3.9.1 num2words==0.5.14 -numpy==2.2.5 +numpy==2.2.6 oauthlib==3.2.2 ofxtools==0.9.5 -openai==1.78.1 +openai==1.82.0 opencv-contrib-python==4.11.0.86 opencv-python==4.11.0.86 opencv-python-headless==4.11.0.86 openpyxl==3.1.5 opt_einsum==3.4.0 +orjson==3.10.18 outcome==1.3.0.post0 -packaging==25.0 +packaging==24.2 pandas==2.2.3 pango==0.0.1 pdfkit==1.0.0 phonenumbers==8.13.42 pillow==10.4.0 platformdirs==4.3.8 -prometheus_client==0.21.1 +prometheus_client==0.22.0 propcache==0.3.1 -protobuf==6.30.2 -psycopg==3.2.8 -psycopg-binary==3.2.8 -psycopg-c==3.2.8 +protobuf==6.31.0 +psycopg==3.2.9 +psycopg-binary==3.2.9 +psycopg-c==3.2.9 psycopg2-binary==2.9.10 py-moneyed==3.0 PyAutoGUI==0.9.54 pyclipper==1.3.0.post6 pycodestyle==2.13.0 pycparser==2.22 -pydantic==2.11.4 +pydantic==2.11.5 +pydantic-settings==2.9.1 pydantic_core==2.33.2 pydotplus==2.0.2 pydyf==0.11.0 PyGetWindow==0.0.9 Pygments==2.19.1 -PyJWT==2.9.0 +PyJWT==2.10.1 pylint==3.3.7 PyMsgBox==1.0.9 PyMySQL==1.1.1 @@ -184,7 +201,6 @@ pyobjc-framework-Cocoa==11.0 pyobjc-framework-Quartz==11.0 pyparsing==3.2.3 pypdf==5.5.0 -PyPDF2==3.0.1 pyperclip==1.9.0 pyphen==0.17.2 pypng==0.20220715.0 @@ -197,22 +213,25 @@ python-dateutil==2.9.0.post0 python-docx==1.1.2 python-dotenv==1.1.0 python-openid==2.2.5 -python-stdnum==2.0 +python-slugify==8.0.4 +python-stdnum==2.1 python3-saml==1.16.0 pytweening==1.2.0 pytz==2025.2 pyvin==0.0.2 -pywa==2.9.0 +pywa==2.10.0 pywhat==5.1.0 pywhatkit==5.4 PyYAML==6.0.2 pyzbar==0.1.9 qrcode==8.2 RapidFuzz==3.13.0 +redis==6.1.0 regex==2024.11.6 -reportlab==4.4.0 +reportlab==4.4.1 requests==2.32.3 requests-oauthlib==2.0.0 +requests-toolbelt==1.0.0 rfc3986==2.0.0 rich==14.0.0 rubicon-objc==0.5.0 @@ -220,16 +239,17 @@ sacremoses==0.1.1 scikit-image==0.25.2 scikit-learn==1.6.1 scipy==1.15.3 -selenium==4.32.0 +selenium==4.33.0 sentencepiece==0.2.0 -shapely==2.1.0 +shapely==2.1.1 simsimd==6.2.1 six==1.17.0 +slugify==0.0.1 sniffio==1.3.1 snowballstemmer==3.0.1 sortedcontainers==2.4.0 soupsieve==2.7 -SQLAlchemy==2.0.40 +SQLAlchemy==2.0.41 sqlparse==0.5.3 stanza==1.10.1 stringzilla==3.12.5 @@ -237,9 +257,11 @@ suds==1.2.0 swapper==1.3.0 sympy==1.14.0 tablib==3.8.0 +tenacity==9.1.2 termcolor==3.1.0 +text-unidecode==1.3 threadpoolctl==3.6.0 -tifffile==2025.5.10 +tifffile==2025.5.24 tinycss2==1.4.0 tinyhtml5==2.0.0 tomli==2.2.1 @@ -248,9 +270,10 @@ torch==2.7.0 tqdm==4.67.1 trio==0.30.0 trio-websocket==0.12.2 -twilio==9.6.0 +twilio==9.6.1 +types-python-dateutil==2.9.0.20250516 typing-inspect==0.9.0 -typing-inspection==0.4.0 +typing-inspection==0.4.1 typing_extensions==4.13.2 tzdata==2025.2 Unidecode==1.4.0 @@ -260,6 +283,7 @@ vin==0.6.2 vininfo==1.8.0 vishap==0.1.5 vpic-api==0.7.4 +wcwidth==0.2.13 weasyprint==65.1 webencodings==0.5.1 websocket-client==1.8.0 @@ -269,3 +293,4 @@ wsproto==1.2.0 xmlsec==1.3.15 yarl==1.20.0 zopfli==0.2.3.post1 +zstandard==0.23.0 diff --git a/static/images/favicons/haikalbot_v1.png b/static/images/favicons/haikalbot_v1.png new file mode 100644 index 0000000000000000000000000000000000000000..361b524769642ed8f00cfc37531ee3b2fd318f01 GIT binary patch literal 34443 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 !?~8U z{4aZni$6hTDlu`;5TPq~NZuJ#{qqz2OfiTs-Jm@xg8O~3XLTzMi+SySm%X1!_oz@3 z{Kefvj4IEIg%q>l1sB(D_#{Efi-JxI)~un z10!CjpZRiy=cKPujeUCm+bv`)o4yW|O<*`Y7HywI71U#5zdvXIsTH2fzAw^A&Y#C3 zOco<>aii^{1ADST4d}s(dnK!g=Y~%~VLkIzE_?T=vggZ#Mwf4H0{7z>xU~-X2<7d) z5DxE)n(C3*`;37lEP^G2hrf7t_;vk;YN;5QV!N`(Z1-EiLTC_lK6?fCftaNv6AD z8U?fO(YOa%lf)Kp!~m`HEY_Sj8&R#7_dqO94Riuje0IchePCHShN5Gr)IOdojEw&< zNj$R?Q8j&+pMd~eDjNn;=e5ezRHb{KOY`{a`kcP!V#7ZegFWp}$MD-a{Y(Q@gXyq2 z-3y$IzbFW%U3{kIAu=tACawssAqh5>Y##K7f@rWfSPJWG=>ZO}Fy5NpQBYq2Wn8>1IwB5Q3S zyx|0NVag)fJ&XvTk4yW_wPWl!hv)dmc{m+`=xcHfxTVPdfOo#3PH zLOZ+d#AZ>@8cpJA+Lv9NQkg0Qj|vWP_do4f=l;_CBcBE$&GriJ>ZJ>Ry8>B3k+iP5g0rw81{gzN9Cbysn53W zZgSwF=@oB^@2=VNysOKbbEteLLOrdX9;!$ML%HxzfFaoKF8|4b(dA_GA?&N^EF&$D z;-=@jsZ=vo9~=orFnrWwIK5K0??D13C(mmu)qG}Fg+QA2kmi1hFg5~usJ#I9X|W~? zn{4Lp;DO3s=jOVH(1f)w!2Z>-|3lHVcaoJ3bR@_l{%lTG7H5CW%zyMk3W3f4G+c}` zr1^xhHZ2OhOc)P?pAAw51+v28Q$ioL_aXz;4^o|!-XJRov$6h`WA>W(BV5=Ptr*>u@fcaW3Y4Nfq%Y9Dl3XSzl1HRgpd4 z#koFDAy#Y(2!n7*OZ9^ z4qaFkun+-tr%7jm*|1-&SFnC2D=*hON?) zw9xzv|4Tx`~ULCnTIL649eScVGPw-w==)iyz<+@?4 zi}Jl!?JEDHHZ=T%a{vF3tyw74s*gV_S00KJ`1y&^W1-G|0*ENjbEMr~QDeN?Q#Oa0 z@es2sxfu=-TcPaI)tXg^dQ>mR!fmxHzxI(k^1Ry3>*-(oKkKdd{AZnwYQ4;7O@R~X zaMyg`sJY;{q++)A1j-G?z&m=wk$xAb0 zL%VM(bwPK0J~Ti>S$()Gm|Ln%}b=i zTUa#4sFdkR8)MAsUPwh)c|_(d;Y_Zl9t9s-Z(axAWp555I}tJd)0v3sRe46Y$4-R) z^3EH)>pvQCZRNf2$24vFpn7-i#vEy_cYLkU3z&aZEC{WpIyLsZW{*apGC3ALQd;y) zzYLNtMbSM0;eJ-9RtzmXK0Nicm3k-ON!BWCdF8{_(1VsWcFs4@%Vdjmc{5^fw1e+- zDU!C$)fs%fgfJ-B4UuZ|R-_im`xsUr3g@3?P<5zNl%IqZE=e{LSZGx_Q}u))a$)EN z_m`Kw_sOt`XJ8MD&J$K4lPiB?teU>?-=E2;TyJAD$D7ewdF<8o2!I85b%@}k2Ept4 zcXjVx`-XsX0d!UxN9sAMy@XpyL`RMo!O8SPZ4|>}1tO7FbC(0D;%=ycwD<{-ihpkOcfUy20&TYW>&%m=_ig4Jdr<@%2AwBewP-jI zYiPHl%4+#ek;KJ~eT%BLDs^8vel?GgF9v{98n%n;aTf2LG3+L|gv4wvJ1-QrK0!Vs z-~8@w;#G>?o`pC7T_f7BS2LQtcpht`10PKTLyTg`CHPf&d~sPkC&{z#SHTF54nV6L zS*`Lgg_)I`|2{(QbMg6l$?lGTMI2GHt@t!4V!0en(7%Qbg53q)puJ|Qh`*)jaBo8i z-QYNW^7A4C!VusaN^>+Sb@=-gCj{IVg|aGmggPmSu%3NHs!h>=WCxB zsdZ?0(g9dOjt<#~eAO1nk;-@V zgVR277s1%hh!jV`$E(m?*H=%fb}|!62XE7B88M)#%I6Fc8#7E9HpOk)R~(svo!~W@ zsSOY6r?KA>;GGcA^>S8(nWdTilQHC}?hwmmtoTp#WGPIBaS|5}B#Q`n_eTE@R8hp0 zuHgVvuA}XNQtI>Ps~<&Bk{O(J9>KftrL8amR8$ahiN*JN__VAlTL)%f3{0KY@Y+AO z<_3d@S~NORjva-Y?qx&=aA<|!cC!Vaw$8j-@=?b=?dMuckjSx&i2Z7L3R+sx?@PmI3V{Q``>{{OLE`bhR7Xt@g3R&T|2(MQ zr6;@rYJI(fSFO+FJ6}WTeV}@8K{-B;Y5w*J~%--clZd#hm zjqiTko>DoPBV}b~X8$2VCVWiNJhGq|H2lhN4?zImAnSxb$phR+mi`HF|K`Uy!9(Pz zCz5g*?Y^K^5RvJWkJ}Ns z8T{PxL;!Xk~ej#srop`*C656)-_TiOb4SPsGJ^15m(+W2A? ze`1$;IB?oE==G*9+Qpz)6w)U`^F+j`U8BFHgUVDj9C;iq=8vR=(Vvj=N=>T_C*(}{ zyHI%-<%EjBExWj&dMfZR>(=@`1)j>0bGSxdc!QPav1ThTdVQdfMcW5A`Vn)aKRnc` z!%I2jZnDMJkK_92GB%WezPo}T1@B3PBd0^DR*VF0pPJ8{f!DrEKK&wiWH|lQ5r9LX z%5=CxFvsQDEixAI?hNw#LXb`~tWf7Pj(j2_qMRH3(Y)u(RpMH%9lKg#L$kU`ArE+I zlc-I`HN&6B?&@b<54h}|tj2Qwc3l0RDhgh`cRKEqa`FjlI%MrD4oB1Mh$AnZv%Q_>PD^p1Sci7-zZ3 z48D=|ZtQs~RYpsAbIT7mALM>E z;_IwodDIuRqV6eh*&t2D02dDcbd5kZE_g<_K{FwGJB~KfxC^((l?0WFSVsBb;^*~Y(^)ubJ;Bi_D4r5lShDAQ1LWIc38?mW#_et!Di7KZ~emz!e9$Z6@pPd zJNQV0Ju~nYd|rXK4eeJ_4DE1lp$}TdfBU)ZsVXu)g}C{U^hhJxbMtgee*WIC)V`N$ z(qcMBU!5Dz+=I=X5GlHNH2NPD=#fiClIoQQ;{@^lLnNTsW`QOdHu`jSzLB(VM8gp) zGYL=p;z=5DQP#M+QVUqk0~4_OCTz5r@8!F6%^bTq`okCDuz^-<0%Gs$&sgHL8xi*Q;q$L8(e(FK4H%O)Z$Rdb3nekh3 zW7bGoT-Q1VqQrIaa;LP4*t5Dawem#KeUJsN)tXZ6n6-^fueG2`D}dNiS~4-24r3p3 zBC63=a}*fXGh^iIP4~STWt%_z<>JFuXJ0x3`am^Ce)w0v4+726`~2jVDPPnSM&UAc z2wsw#sU9J1#>=mfZcorLXzakhU0nlW_R6A)^ChhpvcocZrAfYm#P5SM~Ehf4t44vBZ{0g4#o#UAr&F*ls0i8ZUpm-o-w0gOMwtO z-{~`RvJ`~;D$IX~zkz!bRqQ|%Fd~_k3m#$XCr46l)=QV5t)azCq4O41!%hs;6{hn% zh&0->nJvF0Sl=luVj!AdLN~j-CS%VWuUx%x5Q(nIsT*xUddQ7>dr$7(wu)YNKH|Bq z#ZD2-{pV`U8RuoKXjoTvH2R{p!$N-;mKCH6<{0!KhjTsl{oPLhjwksY2`Uku$=ZZv za*jb;GJ@}}&q)F~-fihOfvR=VR_H~dyxK_sR4LYu@?!7qNW(I4#tFw*ztp4KN^V3G z3mCa2U6&qF?ZEj*5xU`0UCSD03v#iC@ zMBvtkNw<3G9Z8|Tyg8`SiORr2i+mIqUou)5TE|<*gKo7*7`ax^w^NRd!ZV~7)kjkr zJP2@6ql2;-KX|)j(xjJ<8E#`Ctj(Sz|002;E`ungChH^D(3L7f?vp^f7z>7S)Z$U z0f*Msm{NI4Tjo6glD)Zf)#tg`t>Y6r4k5@9Jg0SJ%k$Fs>R6`LNTx(4RN>_SeF%nHgw zAzrQfzk1^`1}p5TRsuogtnb0~7n#PVkHwP8sK=I>3+iAlY<6xaAaxPY?(E?b5ljBw zOo1H_Wd#n0?~aa|k}@{&=_i+qVQX2gvvMlPcUp+|o3o6%>;e zg$pp!FzI)X=LNkAc5rpuuTeqy-%NTKs!YFMV0ED-1TAUp==>~q)6aZEo3M{wCl>xJ z_>^4tn5Del9OC|HH{VFHta9WWx4Av{ZZw3>Kih6|`pBtq!B&VS@o zjcSdwq%6LZ731gb;fU>dX%eCz!RBn^eDNGePax`v_*K)NA_a)T(<>e&tV2rW7b#fS zCqCfpx5Up`kac=8z{wyIT_vvI&rSCCIS1C?7Y!LlHM}J^Bc|veEqC<=cD~w^uPnRiSzdY--&Ih zk{*n#pBx#t^6Q90^K1anpd}W%9!`T{^F#N1r{I(%?(LOPn^0)WDjE62ZFpUF+qs`h zb*EN{6r=8|1E8dhsFk6Ru@1F5Jrr8DQM3(Lr75au1?nd|G~0sBiN|xTkMj5La!My` za1vB+)-L$eG};jA7Qc7NimjhmnG=eHex^S;$Y-bLKQm)=u0&tpu}nsfVXpxNM1b_s z9DXt3`3zi3IILSZ_bkH|W^$e?ree$p!C%SQM>d--Wqfh1zOK#A-A6q<@~&R@t?!qh zfotI4=3vT5o>;m?ZUcX^n@-h;KY*YDS17wjiQ4NC?LMQE=}4wG$n4uyzGPkZa2tw= zsT*UlHnJ!W*CUF<=a)sI^B&A?a3T_gS+%RE(w=fSIUZ&7_D4-(7Mjho$?iN$JUe^? zBSGKWEn*otR9!lRLA4xw_>Wj!dK_18D(+>{awbo6kTy5dT$%A`L*E~}qfuDEpB;?G zJ~XLT%Z1mASWa$LH+ccc36C=Kiy+%Ig4xOOTdz*7lIqchO!gAX_Vi2|IniVGQ4AfX zLnFo%%}DxvI`fLRmJ0jQzAdMGW=< zZ0T&AX$@++%fsp6NrE}WJ(}S;lBD55B$HfrXAa6HCLCta-Q!2<03@&%5d$l$8gpg(9uFK&u5`?^X$H{ezayzzMJA7WC`9NMe~)D{~cf!|KSN zJJ2PzALZs6_>VN&1p5BAZaot*^3OvOL!HcMI!b=Z#VK5(?wp{Km3}~Ygj7IhwdXr{ z2FJx`8Qg8p=dQyK`O5<6M&R+T4t?v0c7n+LD7tmZ4#7K4YW z5(L$5KZT4|F2um7#9DK)Gcmv(>yBcV##dmZiqgCLHa2+S8 zY^$6ml&mO9$w6!rG%rr3tO5KQ-L~PUG+lYVEBAJCYu|e6LPS3@n}>ht)u?9@UO2R1 z&ar~lBirilsEV!6=Fj(JSv`4BpC1Ut)QZ`~Ni2C*L*CBSG0`w&#r`O~p_Icq$;RzEutKZhws+ysD%;TL8l5l`# z9~N-{@q9iN^_|>~y}>%DrhgwW*D5PsTsQz9x%urXsD&#v^br>Wz!}kuP7I#ZZSImD|K#g7@qzIxE;d|F;h|#aP;%;Hju|03mC_=|M*|Z4wgpz&X5eazKCjA=eh&{~jrtZn<~PVTsGvo9EBafVl9tEc z-~{HxszZG340l{}bw>{D36;HfZ>%O$6co{;aN;qdcZI6Y#RX34sjjdSSb$R&!r_L8M$I7=tl$hoUubIqT8 zi6wGagauk2JOm|@4Vcf30jI9(f?k38yFMF2qDm#1UAYO1sA(>RuUcw^G75E9DC>p- z(Tk&5e`lre#xBlb?I!m)F&pbt>F+%j3*!n=!#R;<$@9x zJ@we&<4t>Htc)zyBta9;?UN~CQx#&16>&A1Q?+|aZ}NfGk3;#JuVfTXK+)Us=G8ge>B5%8n#RuI1Q(}EaI9-*5`p7 zGGM60Hcf)lDksscPr2|q@I!9-BSl23lp!uzoY_OvuEI^Go8RwueKLvvHe?zzQLih1 zR|V*q68{Ta`EnC{fB~mBaSdSAE}Uci4Q!(OBeECgHbt~3QYY!T%U6)dpIwt)K^e3O zQZ&)AktYdP7#%60r*vJqaX01TJr5_U+oc$sO;oPe=ddN*Vt6=QAS-&q;tqDA_Xsy5 z#l#oN=vD!^1&}?|v@5x$$Wr66k%pU8;5Pm%`umM1x1>8W#_f^!{dY<~(-O~&;u&)M zt*w}$=QI^9lV@C#p1%n`-c6v!EzK`)SkZOo*$imKT}mrvm7l;zacenBdZ+M~sPPeDKGaP)elA4jl=7ei{v*&Qc!M_)Ec zxYGGfKJWowxkd%$O;gZkaO~I2iNL=oPQaK#5$S~T;JW`Lwpbt7rV2S*z=sSYSL1AE6(Z~;3`A_Q3{`b zCPrnoGv>i{9|PV5h208(D=MfV7!$N8&f)2hMAWA8bU2%^=G~?aLqY4)zrAB4EJ&6@ z!Rh3Etu0XY-Y>^kk2hhgOQ=nehLm*`ep^!J3bh}#clYRJuz)V=Ki~qh4SaP!aq)td zTs|b&_UoPa$-`%KgCeFC#?iMj9Wo{&eEwu`_Z^^a83$e4AkCtjavhxV5V<7J@^cts zau@E2&nG@HL#nT>gb!r6*D!Czug|IROsv3Izje z1&=Y|KoRb%60Hq#w3n}EQ*^Fl;NP^>NyuNNvK6~wRoA+qZ<%gRS6i`A>BI2RO5HP?(GUIh8|FwVm*5ZPG~&rK}0i!_Pyh7#Ob&M(|T zqbQX0qiC6L;;J}A%W_945_eYjjcW6u`RIaqPM9fmE=Gfk$=n=h>mwYU$*=mE_jwm` zEfM1T;RvlQc3$nGJ!Yk$$frB{^fIYMJrr(4GfYiY)Sw$3OI2OLBt8tIQ~-UA1J39L z&S*QClE4}Q9wxS;vu+pXZ(L)L1r%kM`B01hae9X2N+#VeOpq*+{cHK~dC{>;5rksv z6)|q)eSv+HVj5knX-)0P3WKeGL~L1PvHh4PA*C)hno^SJG+(gK-6{B-9ar1Y@t6zm zLY~gie`u?(vw82RE3E~ui=k)K9qn&mr8W~rNrQ@nkxTW`q*PV3YWx-V19b6iDH%(J zTn_}7<&;(Y9l}ercbt{N;Lbxw1JxV{-FR@WA;3k?>BHxl2zjz2Z6fZay@X;wfL}4C zfqzfU9^Xj0=cnKo=awaK5~~6lg(dvicCU$fE$);9bpH$YAE@s7^v%0n$=jZ<0g(LG zVKb=i%;*G(pKh|Z9x4taET(Rd(!x>)71MsM-ZPuM9G9=RkB|DMe+y~_69$BdhSgZE z?OMlKUFxJp4}_mEfS) zTYKBjn67tr8;esnn{TmQ0Nuq*xEj7IER#CMzo$@yqMm$}Rg=Zomo})_>RLU%{spe6 z{{aIX`*dyT6=bA09*&)yZ@G`N;#m5l-1>Rr_ zMkt4J+~N|@Ds>7ALtO>wqGL2KCh|kcQxEO9Xxzas!KIV{{sZch8NMq@<;6Z5*SWUv zUmCfmY6^!S41ktEVcb9M66Ek_Gj8b*SBZ|DF*j#tY+ChO03)CQ(D(LwJE-5cq_7(`$fA{cj;T?hG`N%_nxNoMQQZx|46og z8l=yV8)!4bY#WOx05a9X)k2ui_IL$ND(Yta8U5OjyDrVOIv)!`9_Qnl%%T?Ig)SN^ zSicE%TVEQNu6B^m8swfXYNU}F=)R&^I#OrY-%6stn8L671ot44mj=SuHBoCOwg3AJ ztREy z@%NL@NnD7#Fxz91%fB|shWTE$7CSFyGvcf*auv=tH-AkY$%o!Drs;dAez~k;(Vznm z6$=d>*1xkl%8zUq>mN|D7ZY^~nsQXbjM5dY#V%;Qy+9`AS;`DV2zJ3eEw{*j*F{^# zw#1dhsc`*pLvi)gm+b;yuZyLRL;?RCU41WS(LiaFS~uN5zGqx>@Fur|ey-({_(cVm znJlg~7e=UuFCIpNVN3S;uIz4P(mjgowx~hk4^&1oxrtEtqP;W1XAUnB zd>+ZMB@%X)hulQ}eNSsoJ}Pm09*PE&&e6q;u9;Ojc{E=8CeVt)zYMAGDHsbB1zVNA zW!7@}!r-Cb{^>P!Lo3v6p32(jS?y|M^TCvWARIl~`jrH($u0FxA$wWFI)X$bL#@2t zmH{T9!7lO(d5}9nH_dur>yd@e!E6ZK^6W9%_vv*qUEwpu9|LHmbSgADu=6iIX-nC?0*|vjyuMY*k%n4E~9-(njX#BZX91}Tb7~C1^uKy&U<@j#ZVg9~LPjEJvR!^gM@pG$dHu(vzhgj?nKsDSJ81JZUksjLdgvt&>( zjkA$#Bp$%G99$eSmmP$VKK&kBusyDB&_Cu$$@UKrWg-}K^t?LKa^!#hjaB<6-)Lg% zx67L;PJL49H|6sy)&>ygVgvqpZASb7s$hk{lmx}s?p!a;qT8&>H*oFiqm}O9w6p}s ztaJ`wnC_LkftDbAImP+KNNjU7_d??5v7DOu!jE$WKS7wI0$>7lHs5~tTIT0}x`P^g z(+AS#l9^m4y%Om`irs_|Znhr#@)msI+WxoFdE)kX2YHA4WpZnzf?yFYFeAki3q$xc z#+T0`Zb<}_JRGBOb)krkPq@S)IE8S2K9^jXHz>D9`Fw8t?F|02d$yqDW`mg^>Y1zL zH+&6iQnOYW|58vgDZRP)WP~}b%AM0d_{{7=SihNTSM!ifC@t$*IQEB#71h(r>tL87 zQrjC&mtHF@YNdJ6m?-#k*t~h|%NR3zQ8}K-Pk9%{V1de1Ve6z+%guXef$mV9nty2I zPOCYcW)^EMjG78AgGUVu9JqFz6?_wR2&Cpj?%*Y$dY1VmiFNY#56bK^^)zN3N>b<_ zkkWh@*pR%dbqA3oApBNjtFkX{2v!a8uLVpTf}C>rKlva(x!kc1&z&XtZJ$~b9+Rbs){ z-|mXue+xl<$i>~`jXiVpZp@p%^G0T6pB-$aBBEPaq9b$Z<532YWZ!Pxn)g3bXl2b)LFbQX%Fj|=%C(-l69)TLw*m6OY{UjP4APpk( zmbrX`f%8o~1pv3ZgAYUnQ-&{y@pL=FUM)djzO-h?#q2rk$9gQ{Z2w=JF{AY^9h$@2 z1kX?`|9k920F;uUD(^FyQ?2}34&wsaOE2Nmoc~i?&98M__z+F^9Z9Jo^s+kleMu<( zH;80m+JV#Y%b}8shhIaL8Yj@xqujaB!jC?^67^q;wfBwV?fValQfc6*yg6$<%!uFe zM{XMXSS`Bpb_=VPU3Cy_g;eD%prs+1FKA?3bbgkm5_`Tq`XFa?&9B+9W)+bN0EJ4& zPY1#{n& z)+~7Pu0z&kJGE}w<>xivQ}^*_`#|AFv{0CSHoh#JB5pOyWzRDiGgMhwSPzQqIz|aBa_2paP5Klw5s5H?oF{{#>cOVzw(!R zR!fSUGh(z4ZSKb%<`%#_Pr+tB&HaY-aPf#zV%zmv1z+70!+($LUFajvB$E2{lq^_P zxO4A&jKv>7y6@#+#8@W|5sQdIJ#+ytv-hIqL~pyeMa_1`xDaxznIGOOI);1EWoBt9 ztc`z|JE%0B8BvIiLRVoT1DB&V7EQv)Pow4GY^RllU*jO-Jy_qLMxs+yT~DwAf#~FL z*9k4vsIQx;jQ67FmSSYE_>4?ieNyVi-Dr+p9ehf|f%z|a)7`KYbzr|Z`SF9CzX@wA zVMMd&*ec8(9zUgBkR$oT#4(Yg0nSf_aNSXU+V1{7o8h;J{`R4o>}5I=1>Rb?_&>dS zAXqvtDR-rp#dYD7 zLU#6U95UHQ!^}!}11(hFfI4g$z9$A%FS6sNBcDQlk}Jgu4fbRo?0Rb4VE^bk3a-aG zL@)l=6^odUR_9Zfeve|zun-Z?r34!{M$`q9gp z1-N1;{ROnnzdnQ}Qoo9SSLQP46axzajl!M6n6ZtAV+*`jrKASp?!c!v9pdQ;o4g10 zzDE-Ko=_hVGjUHulTbYLb;Uaerj#es%!J~9jve@rH%{kYFQ%b)E;j|U-v=r4X5F_B z@2KyzSy)=Ey=k1?SWh*>2>`7=lK1)sqs|6R%(0@^kx|B16&?!8nk0>Pbr;=q?dWQakWwJ-6icBOc% zgUMTz+Ina=7j2!Ioko~)y&d<3Ol* zD5nz7xS<`;h`E*-c+DzSKd3Gn$vTLJJD&{%{{mSb*uzf?By{Y-&TQpLQ z|9QaU)7+Z&&lqU5R_z4QJB4VO#(RV^!&pyDf){r0sl#X+~K-kDoE zZC3dG>sABT526T!c7UNOIlnLa;2h+bMA0pS@cW7jc3PcF zU2q4PM`YEyIx=THX1g1jLMw4wq^Mt*&^^Ww%+8*AN@uIFFCMSf9N!6zq#;Kv@4CYU zv3%7QN~boy1##Lwj&}|jPwf(d?EG&&4 zc+W_Y4||5ce^%H)=+R4(}hW_OrdP6pOp4gGcK-&%77ga!u*OMY{YLyCj3)xXS6yO_@ z5(7e9@cn?JZmldF!XX%`t&8U&_ZxDmY z&4Qf2g~dUFyO%Z$5O25?!sbbRwtY0TS>?2Z;1s1G_i+sat=F`XU*s zRUtxPa;F{yI!+0e#tfX*5mB3>5MYsSKtB8MYSLwjaj5JwnwdyLBEFDuCDbIram1nE zj_Ifbcc3jKQ1&BBlNjy~X^mep(9n3(`tDDk-tdX)aI~;;%GuMa zQPXBciRcj$9n-!&eA+{EVJIBpG_0X*XxYDQa5>T;IY?>zA=(lW*nC4>wW}&CWF^_9 z!iBDNRAP_7e%V}zh_lzCYy=)2VBQsbBvUpJnWGXj@K8rUF!$t)5joV^bt+l9QD-sctU%2t#Dpzhx5^(1aODd{TUU;IOI zfM5l-cCqGhUa=E$0UTcr6^gn|e%}+-e+9mLF*?!ogBPj!chBM@W%+Tn3PMDOAO>sr zO^nEX-~$)7XCe%unIt!>!1?iyu(yUNDs0Nfyjs9Rp&NcvMLWag6P?T@~q68VDs zw-orNt^4lS?G_!c`=yh*G1?36L2^(irsRd8N|+CkwBx(ZFwmaf zGGwrlZjSbssnZeQjyFbeF~yCN?bPL6`t_8jYRJfvl@iVX99EOC#}KM+LjI7!J=*GM z*+x;~?bwHrp`?bsXH>azxxp|g9zno6v9mra0K8q%u+L@Vp#tyu z&=UJsV^A_R&DoVoumX}Mt#!0{JBxo}G|UFM%$_%I7{}(D)lYFj4A(!mMVpm0C{9;% zHj*ZQJ{wv-$uE2Jpu6cZ4ZsN|5_(N(F3~rtXlPL`(taX+A)rHCjELDFN?aaibkfoJ zQ#SAff;{a14O@ICe5a!*vN+&?m(n!t=gDP%^Vih4hXFpZjrD*}n`@Q99R33}iD^^P z1w~wkT07V2<9{3#pamU>bCEa$J^!uxJqi&#=MtGnktInB8-wSf?You+E@B-z0u%we z)+& z+fnijK|GTusp%A$7vV_B!rCJA#p!ZlSCBOJH+tQ@1LGCnu}gHRm5Zv7bOVtz>7woZ z!V+Y@k8D;}@A=yPw*&vL>(4VlMo;lwb#trJzecN|V}`ISU7gi`^3;8*471CA@>g zT>du9_#290*tdz5VKgv|3Qu+M*`Ye1bCw}ArhX&;RVYOYP3D#-!Zi#W!L+H}ps>Y> zaxAyPExSdR-bOz)4KC3nvP%&0F&Ot&>t0^fv*w56*?)LQ6jUe^HheM;U6xA7wZ7CL z)+>wBP=F-zMxJnMqR=Eej;9{=5H-wfr&IZJ82e?}=r{KZ34HDi=QRtgDv%yxD4ETk!SZ7WQfjY!AbPH z+15at#ie1!7CfUSDSIzS00#^uBNu&|`D|w243QM=qT&5Qm5n56iXtE=a#xJPu4u-U zP1ae!)!!&?mq)59jzB6UCZ%*4F^JdBQTnyOhHFOodQ4yuEnt7W*}g8fwxqr9@YidY2il|?PKQt zIt2HT;O}=7Gy zBBXJB6`0S=E_jABmF1I=*C)ns-a5x1K72ZZIcVsi7-Hb>QR52T%`-|{;G@{&;_7{k zBbJ2bxLp5F&5Tpd> z=4Q!4xwlDMVLe5t6Bc-y!Pvi3Rg~cBk)F*0c_9!-OkQ2ZzxV(@$za_vH6ol=w{Onw z^$AGxIucP7pUV+3=So4qdAd9Kcso|U$@Nx&LoFs`Vp=6(_nGAFY>44BhtujColsy9 z(u$1HN-#dnBjDp-;2D1*e2>D<*WjS6i>e#?;S3W=F^d0~X+hQtdEzTD->Yc)f-|yk z{xf?-_pbV~g8hCv54SXp$*?C1WwTLKlD2-gD8FM+g08lxM2b)=T>f$q-zi>18W5~W z47||jL`cS5v1n4;5zvDH{cQkeBH*J_Ak#Dbn;YReiLm!W8CeptqT!t10+x3aH4IVb z;fIR>fYohMrs^Y;3DuGf_s5phB=pYiW`k_{n>Zm0kDbP)6Hmv!Vt{b0??qzAYfU?~ z&byhS5BWtU?Om%#J1Fq*AZj=+M)yhIH>inS|3R+Ua4Dwb ziq6W`)Uioo{1ibriD5%IX847Tlf>Rg1j);v9rCO&%!E%gj}F|7sB;t=z)ulXuF$xI zeF~v1D`R>GG5o#ky*6^ZNZzJw9PSqk1XkdV^gyX+K$ym!xV(Ou{J72MDR$h-FTfk` z%17OGp|XqMqTU48QyOl-is`Uo@?>GamW71Gk*1@bvh0v_uSQ?SXE8E3utqj?cZUd( zAV`ewAnahzX}ogS^J8p&=Hhd?! znINN9*F{4LF1@h#Rz2nL^&&zR5}B}_ zQrP|qdyBZ=$uokIP!X~%|G0ay5B23Ck6E8i;o8D)@#=7J1WzLE6`gq70~1KbnptW` z<=@pnvI_h*;ojLu550H2@sdGniH};^EW<$SL(rsW_v$o}qZI_ib4lJ(O}XyR@qe^^ z!bBF@zfOHB8}7fA0GltALD+Yr0?BXY(R9{RgGL?RQ@GM7UOzf=LyRqNu5!e?)g3f} zP*VeqW{>zb;ks~y*{5fhy~-?xCy7f#jeDqAvX1{5t>NzoVZyQH_Ht`M6Z-iU!SJ3_ z9;3MWcoaEH(zC6CB#CD?9e2#r0?87|U&=1;w?j6s14y9q`-6C4&O^{vY<3{IxXBp_ z&j()peD=$}DuTO&aOg@#2nqpT6JWHxI*8&Lc1h#(uK1odg(ALc{_=;7@bjLz(4hG7 zBBxb!HDWV+4z?qS(BC$i5(W@9?qU~v43sJb9if@s4E}4xKIF2z^ProM+eg-vw8p60 z+5z^}z%p7&23E;Idw%N+8}VSWy1l1Lzd6ok`etE z{e&BW#yHiM+Ow?tC7pC zdyz>Aglbz1|2m~r3$4uC?a4jn=})Ky=e>~nCB6UYk(Sgu5_Vrc-+J}dZIQ~#l+x+- zYB)$;f>a>%{65vMGXnUhk{m5b3db&ld7KFPP&{j9qaIKlqaSHWAP?K3(8KP87WQS@Wo{oH@l zYcvTZ&{5O>-f31LC>^D0?-0XW06z5AZR>CXYp$gBYJ!6}bOk#+E) zbAHyiO0&9`wG1MT^t$7s@Q+8ar5=}|#L)6ZjGqt3Vw$Ue>HNAeT4Pt(c;j)lG}L2z zKUO5y(4dIXERrSOR&U|K6~&|xxT)B~b*4=HCmAZgtU1+&CQ3Dk+Y&$`E?=2jN5EL&4skw6IH{`70&*Pw6Uqh4vPR$6=9)1a~aQ!;H5%ta}Qm)!0 znY!kF6&37T(eapQf#W^xNuy$r;puXYX@MihB~US^)cv_La1k0snE-#C<2h(RwUr?t z`jeDyDq0F?zZ#`gbXFukB0-DHyuo9~Wz-5GW2nB$np%-=6L|CVNP9$CfM=W7-T!+V zki*8X|8W1s(B)yvXv5MQoG?rqhO3cbcw^56Us7pTn5W6>RKn~M-s?4JTBx#&(A~Vv zFZ#3Uz}l=D6IbiOV}bjATYKLOxy-aCQJQH%adj1?2Pajr&a+pJSRTl?)zN0%Dbyug zMY%jWN~-NJpmK2Cna>f2E0LUgRiX#eofbt=C6PO~q*DK(7uRBg{wA9mNyc^GC@wPb zx>%&wu}40EiLND+c#B9`x#hxBZm+wK)UR_!g^F}G7{?pztD*H=zhX&!C4Amf^lTcn zsU6rcg^+}C4;BTNma{VmEaszU76zg~rg`dWz*T_6|90gCHD=fnwshj7x^_}nyA)kc z*rVz*Pa1S{WVuofR1hdw`1ws7_d)1!3l*7G=v+d0XF=AAw!4>bhM>}LuD2=9G#*{Z z{d0>bjVu8mtJJyw)YBK|(+{NEB*eQ*4xIOa&;VQBRonxg0*MK&PNw>QK@9+Sbl3lC zQ`1gTDuqUnETY}qe?!?tp`K!UCie$z>;C0g_z>V%s@)I$^G44;MRpdAAlHNZ=HXF; zMcPvlr;X_nbh!*V23AZ{yU^(2V`_36QIu}ebSWbCJgHkQG6;fjM&TJx?oLlHqBFX% zQVSL3Bn?Zsv-W1{%#!3s(wuSCBfe>y56k+las{j(TEF!z;G8wX+xMJZ_N{e0%=PXA zDoRwS{yaV8)*wOT&-JgT>kZeV6XX$bQy9eoCk(H=1*LKBTA9}>gy6C5$Jf@hp=5QH z6!zj>J>*`T>-JzU<@OabFJ|52r`F23LQ}37WwI{Uyz@AUBp-%RmC|k6quqO7dK4oi zK`0SE;Df$_zG3$Ac!XR24+66DFPgTL>c3M&ti0iql#CK5XR&N~6_I=DG^Lheib^rP z?uJTBKX?UF+NAWn?B=jEi=w?n$RRx(tkjfB?D=~>)uJ{(r!fqCnp_L;bA?JF9?(=I z0=0nrjnO{HpDz1BPY{!63mrQ`77bRn=fXJeLeo>}RODm0c5;;~12J-(zY;BA7Wxl` z(+)U*x4KYMx!WCi&6&;w)GTGjl3K8e!*zU_^SzCO<0>=)hZ}yV@kp;h?`2(~Y;{r# zAH*@{!wKO%&v!bOHZ715lSVE7AFsQ=Z;WnQI$)uqLopE6U+5&gHu>b~J)&FAp{`)s z6Oz-4TjoIcepw`~Du~Qk+f_x(O(nf7q$fu|sM%i-2<`yN9Ymf+NQ8`ZZ0#Nm>U8bQ zdwS-;W@iZu=4s5yUkoDZOb39i6FVZ1xRi$xL6pK=X<%9L8Y{$;@wqC)WnBj1X*Q+8 zfh(p?0nIY)myL4=edNkWqLf*GqI~sEaS#vRPrp4_ft2|%5-}PitaNL??Td?s2Q)1R zT)6!_7QGIB~1F)jKx@hN+Zy+rcshG$JvwdGe5)|RbK z?h^4yI<8S4Jg2PPp!G!dolg0n`9`*#^63B&z|3b{e$AqrQ$+&05~ zQ0RFOOCWdbHHQtflg_FT`Z$$jM7GnxZ(Zf-NG>1%ItM)s8FPy?ae_LP;f1F1Q8-IN zvW?6{ha9>!XS(w)pM9SHnP7DR1n_U3S|r1?>}I(g{V%TWOCxiUC@8z0vaatl!BzEI z;-dmG*}{yMvjtDo81TmUu1JdMjOK7OtRjx^A@;uqfTzvJ_cKsZw=TEEA59(00u!wb zzI8VW(RCCYg;cK4tS*|0VINbO7av?-?8Io`0riF!N`|;Taht4aFdnZZTh>SrWev*Z z49qquzEmKFPW)+?I3KCL2!j*O_({>L!+^B)(^R~C%bQfLHG(sm)i&)U`I_?PT?!^m zI=wBc4&%!*xkHo`9K(sjXg#!0eYCBLBr7wAt7h_^lU&Cg>1t@2N*h5 z%zVL8Uwjv(aclH0(VW|pm-fb;*VtC*vWrvr`L7=nXmv45j8M5oYtJYg!I;6M^dHFyO_8PgvD5T3Xy z&pkw_9h?WRmI8p9Jk<`)`k)0QD_!B?1uEMS<*qcB{v)v{MjiD%mjk+!VHGK>?t=8v zS`tAPJpytv^T7y0`}2K`1S`{GXiE(!XH;}H0y*)d6ZrnjMjLPpgiBYDzjQ@y7%;gl zH^_R55#N0(jw3+QPX6tJ)b=+_-P(XfokLoj5BwVlbAj$S+qvG#QeOcuS}g%T}L zcPN17TUf9-eL2tU$A?NB6OLS!J*)6?2HW*96rDtspb@{L5fCZQ@^_mds ztq~*2TRXxgX4~AMH>(PfU;lyVddjvuA>UHQWd*OsF*Xi<4RS%-v{@UqH3$i*4?Cs+ z@b?YuUS-Z$>MY8wz@h-1fwLwV8A(DF#8&ma$kIY8{bZR%D1fJwQmMqvbIzU>S8j(J zSSonIP(-N=6yB}9(alAzoN@g-3fC-|YX7GeDW)k7avIf*q*n~+&--s++U85i2wzv% z0kil1TLX_mZ34nR_J4v`QVPNq1cl`F z{nWXgOr6bYg0BLR7m!6Du&iLR5Beb#eL4njc_}u+-{Jv&h4{@eJu7}v7EM47;w5U+ zxw8xTV-KfX$Z8Mr9m2K3^C(TuXb!G#{Jm%BZaYmr`zIfp2^6ri)BfzSl@B$3Q(&tDpoJVbD`&?pQ+1xmOF zuQwWdaMSO~Z@7cw!H`gpPK7@u`)OH<@f~EtV*b*=9!r{QHCN_}iq6dx<}_-z()S>l z<^U+};Sr@>KKomi0E-78l}6U4Gh35beo;WBM2eR?NcM?_K8 zB(Ja$0I>(RhARvGRIetadcjrOO5S!QNJX2qh|GokuhMtIfYKZ0Y-?;Kbj^UvZi<SzUlg|p_pFWM%l#4~{Jl_sf-fpf;3 z+rRlQ$hPgdDU-cwu*!3|EMt5*+ixpv?ssOe(p!&W%Avjs3IZ$t7l*B<2(_8C!LC%F zfuu)@T21iNM1yP{GrZBrm3=?5G$ej%;KpF`!)6n`>r3Nht2=fAm8-d zd;vSQ>`kCu>o*ps`Kr;7fp)f>eQls#(RhTCn;WOYo4JA;DHS%4$DSxWx`~??xUI4P zjf+lQM0C~JMe;mSeVi)fnWhq9!M$hJQ&vwIrakrfQr{CL(ir7x$N4d}(5>C{qHF>~h){C0@& z{#SF{Zom7nFEcC6SzS)d(J$}kc1AUs3$tS_w#lY@>fPq$OV2+4jDAHZq~B=YI(A+m z%#X8>+gB~KY$~lmhh5;>t~qXbQ|57dlnU`Ct6w`~_{vPAG^WEmQD5lhcVABF@P%3h zzi*o3KH}|^Z1wUx0#}Z~#uDn!eG@kfE__^WEKb<#$GK}PC|0bzgORe~kA-@v>CgvW z+|YV{(wOr$a<-hbx#91Gv9t8FkJ9&Wy!V)CT-&5$@7E_Ms@#u!uFGjFWoGRgEf$+? z5xnxW$Z~P+bP$rd=U8NCGCIlhexGzLP_9y{{Ek7$S^Z^6hfP}JV|fo#eF&+(CCnqa z1I_a;xtR{cpVHF;lhOXz`5r&{+c$aLwE3e2)is0f@6AwVEjd)_S*lZv!TwR$16$0) zCr$P6ea$JesHvr>tIN~*rSd$}+b;du)R{D$xe)L8cG(ysyytJ8bN~2+H79UOrFC1c zEbI7o=X_(%w#eet@inZrl3?j+KmW@g3$3T|Ick$udNi+Cq3GeKR;)B{PGrTMvLLYz zajWHcP!!LsdCIvgcH^caPs)dua2Hpv=k_w^pOKHTQKQYdr81myHVL7;#M#F+?d^Do z{Y{r##YzJuzZuQ(=l8=XOCCBF9p4sYT{gL?qi8 zxEX&A^>kpS`*sS7-|||wSB}IcO#0W+=D!tfi{CwLi5V(uYGuECm(vy;nn4Tn+PuPes>{p5#1FJ_I& z6NgV5xqVJd_gT$x@f$Mc`*JCrBWR{lr9N|Fue&A3q^r)r#(Q=4Mf`DdcH+om3T3$0MD`?qEc<+7d{b;ZIL5@R|tx)E_yt2ZuYx&tFf`x9<(s?9~O@m8x1(i3@R0Hnsdt+2+bm%$hAF!oEA3?X{;K4Z4N2cCEz47AEHQ zI!~UNVD7(USi*>73Ey?Pciq@7TqOH_Mxc=RdYmVoR9qD)txuc#ni}>-DjFBLo8Z5G z=TJGb7QM=bD%IoFWoHG>%W;Ku6E9S*T){MDj=Fx*I`F__ThLgD86Nst5tp+sz+8W> z6n0}0PB)a9rdZv!c&H8q*P5)}dIugDnaU zitqEs*I4beGjnf*|4`QZ^WZa4T+WPi;~T{D6qzb2CBji}lp>`&J3}foskpQQL&{M6 zet^>x)h@JTpj5#{GHm{MYS@rf8fAd@0ksL4xEmwRYI%>I-Fv?N=Ese4jbR9h96@^Q+J;HtT1Fe8rNW*lvE8P zbMJ${*;ss{m%Lw%5tldf9c&2M!~RR0vQ?G7pLOF4o{nEXK@KHX`qYQPo6PpVdDk1P zS@A*JD>srZ%>UJsRk+HE*zP58KJmNEJ<=KqDIah z6Hr6CstXNp2=0Un!~C_xW*QS zDIQ@4Z>t=_XV8YFTN0|7D$LP&H@>Q}UYhrh+n=R<4OXe_kCcv1*;pjPQSjM-E%T4A zx{%~?i48w~aVhQV#D4c(oUX{(eH^_imAgBm6}5CK)8Tp2$0cNp$rmZ&MQ~`+}+p^+>P-gpArv5G7DyILn5$mPo ztA0yyENbIO$MmiYea;z>y|((#6Q#F!vK*TmJiCfJA@>HPy>H-W#Ol)@vX~8uTI!XX zImOTTa$l;i#?q!$_q%_GgQ==Hx_tqD)G5I0l4Eyr|6$UYqi@|V7@ElJ9ZgjbaCjb= z06X7hr}vT%%RB8YV4vM)yTi3^AlIz^U}kDqq)lv!+2~7!Xsol4_smRj(gIu7!8yrQ zR@py_t~pYxqIv0N(dNq4%u?L|TdeAm6H1Q{lCNdGi^~h}4qi^pyAYbV|HY;*vy9zM zI8yY1v6JM;WPh@ESX%sZV&b-`c3N*1Q9Yd zF*uDNYv9K<$hx)gjkslZD176;YGUt;AOhmpKQ83ia~XtdO{A&85vzdbQ@#Gr&)>41 zMSW>G|2jLj$Cs4_alc*G+ZCa!UnpSaax-Da*VwpfXS=)HxOK?)N9RP~V*=Q& zl_whSO$t(P&t<|d>Srb3|C=)VZimyi!B5Fo2Y8Xh*Jo*(=I3EU^Z8-K6onsu;A-_9 z%J2cj`*azY#Lh1@8xdEri_ta|fl0|W7M83fVof7Occ z$=RqMzy)GX`o0QbU(Gp1xp}*Br#Hm7GY=|o;4Sf^;KdZxEE!YcD|Xj*oT=!}2uozF zWG-*96dWHhKK$SNe(PJjHDZ|`!>le4=cp;OA}gEV-R)^S04;omQS|4hnT2nH2`6;k zAbu@e8(x_R!H{g6oVbvwR{ceS_#peuwpu~b16gy9q0HKK*qeTEgQ+yX;Ew8Fbm~QF zr&`w=wmjS}3d5SI)?O~xK5tWx;nX$Qi(gh>bg!Z>^w42kB>q*X-OLYDC-JPlcN7Dv z{;e3y!Iuhx{qW|;M)=>A=l}EK|GZnia~hlCuP|(l;7fo6Ke%pEU$^0Z9{4&eOwkMG zh~%fNE}^gS!68p;od!H$BkT%>v*r;=v;M>@A^))8bHAeYz<^BE#W}}2JD-JpDnA4- zQjD;z8GH>>EvvGrFcYKe*zGTvMY+)z zM8mseq~VfoY>8@3W11(3^dH1$GQJ24_hI0_hecrzd;a7_Uim23MK=j#3_glnMKJW& z-WlxePh7qS!5l$kk6<@ft!yCD*&{Ycf{YUUj!@jO$;GwhZKW`UVF<@QZNSzGapl5H z*8DU%3HxpJcJO`vIM}x9v(=Dg0pV2u!YGow`bqKi*fxkC#U66$c#DT)F+KmQjwhdJ)IIWZ@Clxqv*bd+>S6q2tVB(lKd%>k&oOW(27_Th$UarKU4^^z+6I zqOk3xhBN0;!z5MQLD8LImTS~$JV?KGSsXf(=Bw4`li#{(IxoXaa@eH`xQ3N(F!s&!e^j>PZi&7ND=IcuZAFlW8dQ&u zOCBX*0W|@rdP%a-E^Qux`!K%#PfrF;mgWeZ5skSgGmQ#$5yg;sxQ%f}gryUh0;kgL zx%RoL&V`#?0r%*eRJJAnXFxKa##i@!qn*vIzc?NJMCKT>`HQO}LiwAt1;N!aqimz} z-YBOGkxO_;X_``E7*B}9@$oGQ1)ZQ7)0h#r2-Z5hqf2$?O&g^f;#tMyvM zHQxT>P184Qs*+I~K|Fn3Yvphh7s>7-Y`g2<1+x*poH5(zzf4azLAUFX*DQ+_YA1-t zqk@yl@?q<)>bVyjR5F?)!?;hF>NF62_(+aAb*E3>BpBQcZ`BjuV}z-wWB1z$1kq<1uw|)m?$AqVsP(7!q?akU-J3Ie+cP< zpNPLwCq-i}XvA`Cn1!miAU9dmL-@SdS!Hpg|6=2Ibk6M~J1^pI$eE`nxL&HJq!ot! z<@}qkf7HpQ=A?n2)q{S{H69_{rX&&CTh_ zVsd@s1RkO6(qzyh{#J=?NbfPP4v5b75B4Kd{fHK?HVQn1eQ%8JQ|NUXpmp|9%Rf+i zBwN{@Om<%=$ICjZT@o&hG&vR3o_IxL>HJMvjqFGHxX8T-W$Q>#Q>;u7%7YUVPhWQ0 zkiPYl4{^qY?Los!$zc-?X4}j*#dD5Kv)N0iKhaNq{7poCih)5+`(#PBRkr`-eU1e- zg&Qx9f54?>@H*3MRi-ZubybpQGC0NPhgJk>_++2R_~VK5YHRJgH4 zI>OdEtEhaejB}>IM0xC5c?~PyO)bgWYO;tZ#LJy(_g78J@VxC>d3NVNCq8o_q>#oT zqJ7j5Rn2HlUScpfPlXwYjLhQmrts@G*x5zoo?&s5HtxOr2Y)f1toxVzy35Px1LMnA zv-k$ewqC>8j-3c!H+=C#u_+LnpVlx4cva#OTsQ6PJ1+=*kF_Fcc@oGA6)ptNXArB#`% z@LHd%r5}k>G4c(ZNcDvL{b0kb`9tKbMsq$=T#X&XSmH}QY%jdiXJ|Bw1&F6=@3b~4 z{Y?73n3dVLTT1v~vC#WdyV#$<&CNX=auq!s7wWhsAf203bHi?qAQh7aapEc98EL#d znU%~ROg=!22@PfK6FrzdxpI0}T#!SK3vtX{uUL-zxLdcK6t!kkm7l^_EJ+H4w1f!n$}Q0kim)sF&n?B!nYzYmV)hTO zTv|pOxwKTO=fj=}{VKgqmEEU`Zf7LXKN7Dp^hLG!tYBN1qldtqroib>_b&`S3fuc%HNFtEY_*Z%G$ zi()Q>@~5@hg!A3a5Ag~!v5I<)R{{uEG5TE59#Un$PW>+j5qzZsSgwNjW>8rU;@kh` znJF=7Rn#4|h(bc{WCBg$v`_24>6X!h3~AAKotx>RqP|a$_!qqH^4*N6Q1j!iRaKDj+ub(N~JI{$a zhTc4`w@G*%%?!ymX$(ir+}G*N4~XLCz873IDct{OXY0iS#M+EYRDT^|gi?Kj#%u}KnDRLm zMgJ1z=fElN;oQ(D<2B*j*`5YlIoMg=NtK=J{D+gxc^2jszq>uht7^7-H7$Xi3iZX=1l5i(a;h7d8VMftyRZlYOJ z1ct|$y!u)!wCO#tSf+W?wd8w_d-$Go{Hun)p($5*@b~z?UI(=J^c9%VJZq3f#lm$n zQrkZh#0Ed%4Rv~k8bvf2(r4iwQgDy{<+Vku(LP<6zcYEeED8`3m4+*7Fa%@hx>p_X-6|WDlz9+(`?$ruFx!_@pQPT+r)6qlAc`+n_X1`x_sFPl`94g{MoiyRu+ zdbmU;Z_%PFl@+(Zvq~Qy6z&~Hiz_*pcZXYzI4A%86+0c%ter5jlFB7=>F8!Ch# z{Ed$I2_mF$b*h%3PN;9wEhKaaEnE?a+6b=On%d6hsES@2FLMgK=0n>9d!6u0Zd~?n zpgs}bzfE-=m+MjzEvGld_v?DZix;WIG7s5(-$IDC=|67wyX<1W5dT|rp=W!Frm6)~ zdH^Saj9AhU%8WfSvXt95Bu`m`k*cN15-M3WC7w8cs3h$9o~Pf`F78W~?~ST6;Y9CD zX-djIj1ih1`_Y(Yex&j%YPZOzcn{ovY|MhwyZ7ZV!Jt^|U1MGy?iF8;-0<@(txf0- zoYuiDe2D8*Bi+&>ihep;h6ia9M;cos?%d%|2OoVfGeni0>P%rJXLDZIn2~$#_g2!M zcZcQm$d9lbmKaqEY};UMj4Pz>s^v$#HP*vFovBS9h$vnOXgx+FmQJqFwk&n_&JlBM zvZ>o_RjTIyHG1CJqA{PUvhE~$cgOs1-`mY?Qa`$U2alY8hp!s!SsmDFr(38dZ>KcH&n$g9O zOO&r4L%AtaX9BAZ%tt?v)#F546J5Xj;znHigv>a-)6u@V;s1J?aHiv%N6-@nA-}4+ z%2!%=w<3+jeb&Ti8Dr$82>aZke7-0+%Sc!L5cMbL(?UmNIZdxt6CPa18%lu9tGW+-t%9>WN!54`^LQQ$r8aA?l zaYUaY8=}=aD~_w)rfm%W!)Bd3`UxQ@>ETAWM`6otYE!u78aq+ZRGDm4NFx@VIYPqK z1|7&_Qq}gTRsq+-+`e_A;+mF;) z03At+xcf_^7ohfiZjrpJHs~YJjJS~Ke6~QMHpCToXIehKL`GVA~nNsR^09~d; zpczXK!@OZ1iOLbNAO7!x20ldhg#VRuj%)r#q)h;ka^-nSK^i}NRb*#7(^D)iT-P!< z`dO)49v4`HdqtIafO1hPCbn=!#m}L{Gs49vy_ofrBVrC|CE{*PjzL*x#LzOoOfb&=++$?v(KNjH}yaq=ZG=NmCuh|RFkid zjs*Lc4*zN9Gv&Pb4up8}S~*#_|EvuP!9Zver!%&B0>Y*KZ1fUwwI0;Sy*r4bkGr1W zs5WzZc41`Y67yK~S=_7s$n&!kc(1RHirLZ1OiHO>am4y%tEvvlxrUJv- ziAbWzGns784)7=;(eNUl(HiAG>3i)&*Ik%{cH4E$pPa+<#EwsCNf?^KXb&t$3*ce2 zSuzb3C!^@2BydLyjlObEHwDhf1U?SsdWa46S=5Ko)FEPowdalA$!pXz235P65B0)j zq@yqbRJ@u;>}DU)ut9m;p07Ez;T)B`>P#hmI$Q<;B8ZnEA40mMG4TTZhrR7fmQng& zoAFfE>SCV+0PFs*1ky?-$?y{mf#vlYqqktx6iaN+LccDtvadV#kbe(9jntLj#z^%J zx5^wMxU9TfAm?vqKzwmm#5nmJU$q@WBqC;6x+m4lO@gbjJtWWXG1r>@4dBktZ^F`P zGJvr-dzXG<$MmH93Im5U5?#MG#NNRBGF8uOQ65ou1n44%y^k!QQO#GrPq&Qp!9_HE zUJ{*$g6*8SfMyrXn@Ky)@$d657vFr1Z!na%yy0JRnNxT4eQX1?ASCw1qiKE-$c=3b zzD(g`2$yz)6I&~eoi%lmjkBH0J!AUo_q1!iOT0i;FY3xzHtN>}iF0)Ne%pIf7U$(KQq7 zg5uqK3~dyMjGZE|sofTtE~ayMUGCkS(c|b)DmEpH&~8qXKFSNzaTf-Lb#v2!ztlar z(b%LZfx#d3?ZVX$x0}4)i}wSd@S;vt)~{}grdJD*{t+qyt`C5gk(?nr9;qf4PNPnc z#=9#>uy*kM`6_DlKPL6FD)KWCQSVuqX3$(19xZtFuVY|ce7hUa3y?njfZ1nsc~!Zr zRYKo$cqm>6y@tuVfW|ih0ds9r*?}^S{^exfi6>m!dPw%i30zTm#Sqhq=}zt-s&XJ; z=8wwTAzlywO>JU{gmEw?vgsF*=Q8M!_9;Wyh$c#Gw(^%A@lJies<=>kY zKV{d68W$y-U*OrzDT%DN2$stP19RsK;@si=Dg`x3S1F`XKtPkB<%0!lNyvudezazN zeT_LQFhtnO`?X>0`3h>8P45+A&KX5y)~&>tH$RZu|n{khyvwSxxWk{`|S`U{vS2%`!ASV`i<7V!M*{->yil0Sl}< zyOW{z6xe$K>~Y06s9w94h&pa5x(Ut;lm5^{w6AwGVHYW=RGIfm7e zd$eG|I3mrf#HS6z`TP1Pvh)fPQDrbW{6DPD&5t}cKdN=y5+-skKh7kD@K=p&8}*r3 zDIHQ-2qga}c7d=f@XmB~0c516=FSkg{jzh?w-LOgKwjCF2+_Jz?>hYQ>Vh-UlnFjm zLu}N-Fp#lG!0z;k6P*3yajeO*5XO?rTsoMundK8{s6J54!H$T>pkTEQrj~A5b|@Qn z+LM@L;vr1w63`8zX%|$D_$wO7+Tv2!FFFS~mznPLnpCq-GHXbeYF`kMhi*^>%7)_C zOb0P1nEBgfFFV=u$1FRAU$id1@qG4=)`?1kA?9?sHuSpPzpmEnFyl~B2jj5&;WI`k zoh)`VXudFi-x!vu_>}tWdBA5)u%yh+|7S_7yZhjv*B`PXPEPdilil&(ZFqLKz}`lg zf>)GeW}zKbrtpBmJFrYD;FOfC5DdHYii`$dMWk_F#C;wJxGDB-{*EM?y3UxxMNv81 zf+xkO1MxT;sKiOeKuFlftdmxpV1m}HI8;xbiqg(Jozd+ucZ-%DcDpcG`V7#5m4Z=u zNdi_~(wCOG-X}(8S9>++%;+?SMWjN$Gos1b68!WQl1oGsuH$Vm#OM^%Lc>kfF z^zk;3h5e0f7(u^GUuRd!dd-j4LkK)E#o)Vo9^j!h8w^;HkIn`bgpC%-@jGVu!eaON(^^Nkk&K@mO z4wq}0P|rL;3R;{}ut=nLL4SzkA!_gCqTI%W$^D_BpySdY*JL2aC^SiVWGMCUf4Bd>#Up|d84}=U>_6(%{X1~ zu=5bAB6G?Us1>csi@y&gH;<$qox?MKt4^;4V)A3vCVra5oR~{Z2o2)Ev}8d#;d*T` zdD$nImCWSmXIy9G4zyDi!Q(Z)jR?qJg)ky9c=R7^I+f7(fJz|on88su1=J8C&{YG# zC&A~-)Qbo5Y^ISI^Jo#b-G)jgr>O(uN?OmF`1U2|LLlo|?jSjdm?(mtY&MOZ%T-stf2&v}kuPS1K%$|D*J5G<& zF@SL^{p}EWPktv3=t4~^c%REi46$Zu6e^7-O5=IqG0XmWEX@TGN(>}}BLts0TI`9r zyds~}(of0Dp^u7weZW?_!kd00BJH-ba4`cui)2PJ4o!&;vTvD2g#-8Iy;CL=PChuD z3U$xNkGP>)y&}Zk?caMdvcAh)6}{IKFeO$V`ZYk(Y`El;Q!eozP6J*#3{iJ(Y)7BV z7?NIwE!X^-r2cb)i{dm5QI2#DAWdbhFO_JxRv5^MlE^8VNAI70mvmz-m|%U^VeD7bsd}O!~k3_p*<_@}Z~(mtAp> z43D-*ZfDTigA0_u@NP%Uc?t#8)M~RhSu&1DBb(#SM>@EW7X&!+7+TWmsluCAJaRcc z&cC~Y(95odzKRA>$1)r|YrbShKjDa@8&~*{pT?5gljz}pLu4gl@@4XVNN%j4lXn7n z!rBWI)_4hxT7ec1;bXqBRvI2Hm-T)=Tj8WSy%QESBRCG$O})1)4t*~Z#7UoKeuH8V z0n}V%$AB$-SP_`SXxCrJ(`ER>3NovqTBf^E_HmxmyQ=1lOX%;a25euw-FwICFE-rQof^$u`SG< zV74;YM4HVx2?npX)_z0Fpig{3<1t$^4q9=KSLP#r@KgGT$T{e~C(2`%`-<2b_dw0; zwI>sxbq#h2R>E#2AO>(+;3OU zO=7e{4qS6l-U{-GPJ^LF$b}sb3>IAQI9jc(pxHGMsInq6j{lnq0A;Y$ayLoBh43D0 zuoXjtEjD;QU60Tt7%IO{5?af|I9^%VT?R%o7ec}TaN#C$=H)yeuNhME0t(B zm9FP+v)D6F-o}hWu@>D`WD5fHw-*E!Y-ysZXjeB>-mhrN&FesX*_QO}HhvR-rP&IN zi8Tz$-z$(STQq#M>SQCWZBVBicGtJbGc@Y8r-Zuq@3G-s6@-XzU~z`&Z|X5dz0yED zKnR#}*Sl%_U)=rK6|j#bJFb9EG5Op(mHEj(!#UR$BYQ4ey4nbELwYEEub7AkpYcoS zly+Tvql8nQ@pHxJ1k1m3V$m2TM?WYoSNrO8P7zcUt--h}gQXkr>Ot>6&iNBxSbZTr zw_%!ARV_&IzGvD0Tn>B_7G@kZgjX}_A=1C$c~Hch*BwC$>)NVNuiV)a4}lAOa_T-K zY|1G;ye6~rEVGAi`lrvgu?93hczLkf1OF{mb0YNur;@KpMnGWlS|&8NY^#6G z%R|zIoO!SZ!SWX>S#f$hT1=1if$Fs0YJ82~okwt)WBWqdG6eQT@!NP{xtVqQi2|y< z!d}tb&RR(>t14b`&{THcO|GI-J?tJHrl$^9d%gl3&VykSS8JppnAw~O1)NA;JI%x= zH%ZGCZH#7DU=-|h(r;U+mnhYInw?2mZfV8425QGF>~>@QPHs849oN>j*aQho;bI_L zY4TC+$$ih7Zd7I%-}n)lm8N=2&pSFT?9XC=wWw%bo&LxCQ#tL6mvcI@z%1Rft)*k4 zvUcgJTJ&5icS5IcmUHTWVwGfNK?7%8s*9k$p$pw~<4Gl(y`KAP1lP?fRm}f(fC|$M z!gNcdNfG;op-uxiZ_-mdZy53VEC^|vA8cp!r?+D#IQm5nY*9H8CdZ@8dvAP{@piiO zf1xPG20~Hd+J{A%$*DPtY#aAA&qXz2S(kHe+7~%6??bskv&m-iN#`K{y}Mk~v(ztg z47YdoD)DDj6PDCmN|>n$x2woENsVb5>v-Mx}AJ$Z&-ze^Em@6NpISa7QP z$J%Nbf7^xT&o(n7oVFhBSo+F-thIkjhK#H2Hj3;QPes&H^x(Ey^va2-4kB=YT`Bjd zdur)`I*2i3qL~Ex{WQhenq&4lp|QVl*O&fy&qZqu{vh~aY`w56@O|bxqAH)78?doa z!A(ORA;qx^B4*3_?GDo~?z=HQKXUi=)R*Fq+BBpB1%VH$O^ZC}2iiPnC3@W6$I9Dm z*szha;$duim|l(E4ZCMJ^jd~i=ME)>?TkEAr2(iz^bctNK}cBq&ZM3-=9C%?Ipv)Jqiva^CY|7cF(O!;*Q!HwPPqUy5+!U!ufzdc;#`bn5b=$O}T&7slX?yD=8hg zfsFLE2Twu`+t6~zcsFO5JR7J-kUnS9_wp_&zVoxGA8#V00YgMXgA*VS1|)}=leEen ztX@LFrsOP>)BDJM{ti_5J^|thwso;azh>XDt^Yg(+Rok(G_Q{2_Zc<@qx7#Tu}tCi$&QIPq05(KL$g zi8&l-ThuFsd+0Q=bG(1r1a!m6It6l$*C2K4Jb}9vqAwNv*3YICBAWK#+i;Zfn%w2Z zHb0O`c9Aai*!OYb(9L@SDz?f8Jd0MML%C2sJ#TtRjY(!uIgio!dYJ{**ANklD1Hu< z7WZpB;IvoUK~V{f@N-}%EsMBjVf%iDRz;i-+g3EW)YW@_BL45iq00cFGSIDX2-qKR zKa6#Ssk+4GS<*fJ2d_Tvvo9H+&@fEw%D9wZ@!gMe>tnJxY6e>rlG-`HW1JwkVdIO& z=+o=eqnVCUg8_J704$t+7j=b@(A>eJ$l*zZS^;U?59l3eyN(Zk6Z&perG*9Xm+hDJ zk6O2ry{HNdzN!7W)kG+n7I{@&JqE^iYG1`SQ6P3lmvtKs-nJpB zGU;q-Lxrui)kLyP4QZwWof+gL!t^Gv>7Dck=5$S?z=ulAZZAtawTr0u>5nazcw4>e zaG977tWxHqf84tulK6g5ku%ci5t%V39yvUB=Fbn4fahF)E=CMr&pw?KyjxbV!rr>w z@xsC$Zng`t>59L*Qr`y<#@I!rdbbc_+^bfBuo$o1^*C`bxr)X~b z^J#A>>kW`U&tca&3_q{e7W{!qz_`-st|^~;p?AtJZQ8>5d08u|c_ks3HmkNL__RSt z>*!9K628QqnO$vNbb0A>^@Ln@Y55{XA~H8Y_$y14PIk`*0Z=^AcQ>WW>VSXn`TfgQ z9$&s*(^wG6@3j*{j~A^_pxt_R(Qcnk$C$b$PzdOSq|9FK7vd@7HdrBd>~b@wLE~d3 zRr*{vG`qutZKCL7z=aXb0gS@FGXf$Z7y6j>v%91hG(H+~CCpyonuq7UNk%mFN1*FP z88=rABu?{jHTvQ9tAJzaUAM0X>>u0Y>6hQ@vMa@TiP1L*rPnaoKFOD11rs#U^djo+ z+A6eZsq4vjvuUTf*hG;_>_5JBk>Du0N3=O0w#JA;M@{*#c$5WS)7$pl@*cPzs{m1{+)9GVZYi4w4YOeF3{GAsJo zvN6=YC*5LNQAq@ZWZo9 zJ%lrjyz1>Rsb<}&dVE6ICup*ofs#kfR~af>yW-ex3LjTCUsqq%N66J#usWeMN~`|z zs!%*!_>7NIjGjDyP8C*fcq7yE@hQdwAW_j)OF2Tk&_$*Z?U&?Hr7xZbNjpKIdbI=a z@)GWk_W{SweU42hZ~dMLxssE39hy$ffhu!{G5rL8Xg3=gZRbRSI2)Zizk*if5!A^_ z!wnuL6(*Z!fNf?2c#y;EAIsdo<=XC(c4>p!09QS~p zTFG)k0>{*V;}Ug`AU#-FhBIoT>QA-oPGO^!d7~9oJc*kiTOSqFpHoX|BFMW4>9r@# zUUh-|Cm7c?e&H(|JueKY{ zGkr5m)*8^_bwHilyxG(~vyhN;dnT|7oH69nM*BXla6_FQa!&1M>A5RDkh$n)YL=Ej z4F4Q%`0#!K)DEMe<#tI#pu$wgkQBm$@Ldt;zadXL2PU+n`+kwS9p^!h9Z!HO=$Hw8 z1wQlGczb79y-2q|c)RwC^!F=1<7IN)W*0chazf~DgY>UQkH6kajlO3?c$IbBW=Wd6 zOqZ*%W#&+H_^ceV+M5X4(y>Al6+KycI`|tTPc{%|H6*?dcYJ8^FM@)kC$*-E*gy8T zVj@*dB6YLfUwp7z4A+%$ubDFg?fs61L(C6k@t6LN$T4m%bKdo!-g;2Xfof$Z!1g(1 znO0eV+188uUd&uC?Nj5ky#-|ILMT%WF2)jnlL|XYSQY#3O+mHN)%%L)AhkuH)%~D%3!~XZ-DeDk-pkM? zpUF_k?gfNuZT*)&<`Wn6_z=YhpskYY%|X32nl~KK<#NLPQI#-LvxlN?fiXbYuY#SAUGJ@8&u z7O@K}pGD=C43nu@XjLUAD(r3YqUJLP>V5|CZz2|d*K0%75$sy@1oVz7$zJI zahT_amdRT|xOhhB(_F$fwg->0+w=AR>TjkPcx)vVK!Z5(`PauR-|(9d0`` za_YABgY$~aM;9+H+SdG{Q*{@jC1v}srWdn(th3rZVI|8hq(;{WG`_x`(S5ndA@46} zS>(IOdtR1oru>{w45y1Bby!e}0%zMl{*gmm8Zy!wGP$Syq4&IweDs4n35?>qjmf+A zzRl+No4(d0$_hLzR+QW58d`aN1rJbOC~3&Z^jqTi`v`0}YxdvS2lEHF{$5sOUeFLb zHZMUc1RJ*p8&^9hA^-R-1Q@xJ$q>i`?S*rj^I_*3C!P@JZ+UEL8fh7g%%I;3<)T-o z^LYJxao>VN<=>Uz9n{h4F@?!J+zZ0%UT;Pyb`W-IY5#>cNRf{9s&+n64XMKcw2=)QuNE1FUl6; z*RGTysu#P{;QVeV#}sG|3}}P6w+>L;f5>%?CZ<|VIuhu}0R?XoRMpcaSK^`TC~e9q zSoi10>`p^#ytPUKVFzyXwdR`qAd{^;++0yYkfR5zV#2DLkx_7UECz!8_HI*!mb|(& z5y^DxGxvf~l4SZ6oto7?>F>EO+2=y5ywneG+#!Rz}hk%$^Lgi;mBM9E|_>a{;~xS z%{&)-moiH*(v%M3e6W!;C_nIKUi^qUR+bI0d$vNZO!#!|+@9ho^Dyl!_dVZ#p^&O%^4B3OhXW5=vkyLNxnozh&u7SbdUFI%DW`#@q#H-H|T_EXs|0EzN@< zE(UkqMu&+urOJz*D|p2W8NVfq2tyVji!ltvS|Ha#zjokeU=0cjOvXO{x0iXg`!?cq`cdDs*bowUo2?C4?12T_zvvAIP*etLZ9E{8erp+v zmQO35(E<(|S1>f61(%%EEM?6b3_bTN<4P1jT;ZS<<>LE~9G{F2r6oGza*uaGn+79* zFR?Za<%rEgwrO?-UOS~Jc!%60gX#6cc2=)k`}xbm|21~p!`=m_nu2=J@=@+YWo|g| z1ofhe!k%n;*tLrGyqYhs9%4x53Vj^=XhS*Wlwh=1Eh-D3EPwCRNsy9O{?Jy!(V!i# zAVYf8R(iXa{Bc1rx@R#DH+M{9yg^y6 zkPwKDQgA09sWr{eTPe|niGRy@*J3L%JbC@9AqF;!L&V+5YOImDSelksq~Ku!XE?)F z?z)w$byVuv5p1rIbZxSZnkY3Hbpu~>1lF09{MW9vpkDn0;L5@19`+VsUtl5mPg%P` zP2s(F@pC)nTl$osFvS)4=~-+I9m+!DrwEH4+FSGcK_4mD*}Fo+q(rxdQpifE`+_qV-!SR4AE%U?Lc`I}ZW_LxU#}L{l2iR~gKSnCD$pA8QA3 z`uF&WcsIx;O7<)z3%I6=dBLF-26{ilPdlGQgv5FK1s&^PMUKKW=5$m?=0J-hOm zOD5VtXFkVHdqGU2k7u(R>$$(Y_^)8Um*MoIu8%>0u;6iN0)+;4^mBd@-B{(9?3y!`p%X(D-UyZ}y-xZCJg%_U>9GIH?Wi)2@C3 zcyUlA1S~`MA@f|!+4I2nZ{X(qr;}wFd{I{$2?bUmu`QDf=N=r7y6E4F=QZP+&|4q| z4wLyBRUV1po^L=J_k*h)smw+%jBjMUnOy1JpRjZrsITbx`TNnI_D!eW-;N@2!$bIF zwTfTRq~R{-=25qgIo0|mk`r@1BQP}Vd0eP5ZwKJ8dIH!lJEuw3d3O6e<>a7KH>z@x{Hr#wzJ?t^ufmCGogWd!iKz{e~e?{oVZWIv^t zm3cb_mO!!LT8ajsh-ri0NYPOxM4b-v;al9yf^$$iz$?C=8~DewKd;)V%i=XB_*Mgb z6n8yN)_gX|gA18&zC1@91=XPMWI_G(l}JI-VA?=yJFw&+gQ3%})*+313_D9XyszgK zL2Wfs0GZdx92;U(-C#%wRMiYJju#b8&G(rZRDq7?9p(dZXgQo&Np+08ckCwbTGuj= zF@_giTyDrpyKNY?{YaDj!7>?RzGw8L01;mIb>L2)v8E$cYgsL+p{gck?5cvQb#M$s zE1XmusEdOXe|D+CZ;@B@rNW2jYEB+VZsOxlK`6f=sQ4{-0(BZPhj3F1hlBpuotH7) zo5IMg8{`Bs6^%J(W9-d2i`j(?mUQ|+`vu)l9`%%?pCyTiDjeD~`6wTKLtq~}6KHon*{_}IZrKYw z>Fo9wqw|4eB^>?d%BUHw3m@)#X&wxWcZ zv+HmL&sg}6eHTL>49OqHXQhR;Oa?oap00c-qqN4)pWEsJT5w0PjEl4rXmaHHAR4)2 zv8Z%~1{E6-{Zdh?A5J?;HNJuU=zB)*zmP0M8(!GYAfC_ZTmINNIO4X2@(OT5E8$x_ zp9zXPeC(GP(kNIAXMYwI;VebcO5WtkFys_Q=$zR74;%macHT3lbyp5*=Lb?I_w2`6A`+pok6&C&N^Ynj?x5j~!Kh}7UT#md9uipXX37YqNLl8+-Ll_U- z_dcg{KVl(dciuH=~nO_0N$_n2mSJ4G8k{ZA2hJ>En);G`(y z2vZeqck%rW^wG%11hb&%oEWY|2sukWxL557k@eBlc7JJoVw9VR>+v64B*P2EoX9C3 zHa^b8`snRZVHDdc=RmN!W?gTD)?>Wy7~Tt!T$Ji#2~ zH_iNpi0cGAK5eX*>9e(Jk4E86CrAJ~40xO5e z2ef>Mo^}SRk`V~y-!#zZ@4Yxn-2vJ9cfikX3L*TRrOHzW$VKkEnQxf^jnqgItenm2 z%2D{CV!Z^hN(ow&B{1_$ILX>rel`?^b_wU_-;2w;Fk5i)?ldzP^63FRb6r~gb5@Yd zG9Tp##G!EDxjYhFq;WV;5lJy$3gSaAfr2IB1bQd5;OrWJKyr}&i@c9MONz@1Xrk@Y z=vB>&(4Qamfw0yhuu?0h5Q?6z*KDdH&H-?k)vy@wYpMRK!fKQwFOvNio<$qF z0&4#YMCxltJwmw)qN3|+HLi!TgWr^jNv-9Rk};atk)A+(xxS0;6qmhmBFhO>IE1oz zEAcZi(HMNwDE(Ro+~6nNz;z8Q+RzCcLjzD6E8HX+hpt7Fve8`dA9qc;@;L1IF;{1k zAWC~I%Fj1npQAwy=L*=#)isj^V>=(OTa(EH3%z?jtu$yh)gJkE{K9qeq^pl~Y zi6d#eg00iIIGb83Nddv2>e*T9RM`8qM8o$&93J2q(UGN(k!dfH=}oxOq)~ zz+qQzOmSvj^mQ$I$xV<`J_>|-9P&|75b=q;Uu$!HI$4nORqw+SmR52T;j}?t-YzE^ zccKpnWZ$^Y-|q&=h{4c9T-#;5mAL3hrsw=2!%u5LS|W@zMuvoW(+j>uz^vsX zF!k!lFMK1T5@B zIq$4EzeSkq%&Y(A($-gHT^_pHStEU0g!8@x?%k$~M ziFNlbYNiBIAe5g;*z1l%x zf%`02WSzqt^|HQ=0c`HeNVA_$E*C9Txfd=X;EYj1;8f54A9`)}Ecm`9LS*}Ks9|Mi zO)!=$9<#r$?y-YU(V?_Uo1}A*)^j!FsRq!%d1Lu)5tIhDE#LX90#)Ze%%;5{>GZjY z@rO;q>@qkWP=0Mn-n|{hUS|h7_|MSRzrHJ({Wf=!{*(hITD;B~p`3#8n+aniFw92z z=}gdNU;WEL=e1+c>oBbiU;nCV01M@U#&MLritKvGt!W!#3f;WWsphj2M@5l*^B*^I zvo*v6k@XkedCi!`w7<+oeeUe^Qxjzr%Q{WlmV3|R?%SWe)=!wU+*7%D zO$)oHLQ?bX-J66f?F>ScaTcPN!mp+DOAam;w=eqT%99R_!I_hd`<7|uxRhI54d|4~ zh3mxa&}R3UYw5=~;=lkB^Dk=qMT0hOGw#EV+Qqx2GFI`SDO?rJ+`+9}B>UD%EU)VW z<#4}uv4gE=)`~PZL3(L<*zFSb{%kby0)Qoun0g>H{BS$%7tlbP0i#Y0|H0q-PqQ00 zFvtylh^tMabbDne>a;3&Wa;yr1Im%~TiWn-8@531Ns#?!KsgCfUke^I2|dOAxa%jP zJdZ%71ay3^-CMwg#YJtwQm0nWH$!Zd;^!so!9Y6vHgy8cPsX9pGeS z*xF_l6}mOvNn3~5LBJ}cROII#AFb(q&LS#8veNPS7w}I-Ixifn2ok?-gKC)lKiack zGr9de2#1$Tox0^aK(>4zhq!L!Ma&Cl+KEM@o)!j9Q1WcRjtDE={rUqAA5r1Revyx` z!{0X>NSECAFnsp4KyJjAUF1XJ2HN&z*zF>hw72DLfIncND|1SGZi}mY$X4|n*mbxg zG`t`l--d)?AC_3X-rJ?dAB1X@H+H_9=?RVl&HJ^|?-`YK&Hae0=>5A~{(IvX`Cx+* zgPRJ<*PRj{yivw16SKScoSSs%Le*iYo%?+U!3Uhh=mPn=)|J|G3A#|v7;(YPT{#%A zARmWnOb4oM5;5gW(icAU`V{Ti+rMsC`!i@}*yPycCDZqBYI>IS&fD5j!s6#Xi!;_1 z)^NJaX1|5*R0)qPCI)SRMwx*qY!?C{EvwT=YW*3zAYTY^89j5Khe7~n-d`;{j{>>;F+BEyt%;NJ|Fh%eQ8|S^(5td zR-0Gx&0x6}qUxSoXlmym<77f+?|bEMIc^eXqX(;UY&_HZF0%d)PwyR1_51&iKMxt1 zDYHZ&WNTQ7URjk@nc1skl##v8(J~`RR#FLNXYX?mB2pwIj_kenanAWZj`!#HyWL)Y zy#B~}KCkC>U5|Oc-yaT;SX4oB*$Q z3&j&gH|Yc?!`!k|;x}zo`aB7ACm`{iB-_S5m^_Ctfg}|^>R=T{iH{=1N7WE6K6TWqsS(ybu(DIMo=WrX@G**LO zkQhe(Ns4tk?~29xlanF&`~pSs!U0Ym&TdIApH*o4V=b8rf&lr4p7v4}tn|$vu5^L$ z={i)Rd_9Ao{i{p*c=^+Mb;86%7a;a*d{EN@qj7qUmGG}?TL0S z*eNESl#`Hh`9e%09sekv3_qN%rgV>nwN7;;HyslmgK4^`De3i4|o^W_LZ>p z&RS^x|EY7BY|GZqOZQRY>;P#UYbGc^uH$qjE{2B~Do&k7QqcOOJHqQ%4PSPi_qgH2uB$p@dmuT>IzpZ0c=K zaiUL}zsl#nWy%wW9CmpsE_`N7|CJuP19h>5mW();=4thDzf1eKi570tgY&7K1ecV} zDM~r~T2_hmv!^D7oM5krV6P&%A6!u>=Zo5Vnbu$%^4HUrfYo>XVx946Hn3%T@K3^Y ztn=%_g{_WB#;$_i*;q&*hV1u(KO+i!ho&K}a*~07Y=GH)b8mBz4#>gi?y5r`?2?w~ z@ElR}P<`7^bdqLWL=SG}cZ(#`OAp=F=XEvJ{rz2uRvyV9xf{RhsNlJl&PPXTd{j&@3?g@boHRhqAf(`Zf+h@F9X=CN86N<;JcBg@w;uXgO0DFtddUWQbP`R-|L~i zcO_PLsc9i=aP@R0e~=y=h~u z>rHoWO7Mn2}@0-{2`{0<-*kNhFy6DLgswqAM2? zg4o&W5Y`!?y~(Xx`BQS1NYVw1U%1m@`A~cF6b3r3Ows66pcgHTvGK5YDcOG4RAsX8 zX1>Y~NX68QDmR;KfJ{{f_J4Nf$XtV@hkif`cNP@(Z4s?QMzvCCTNR*OAdc zbt~$z3EaY^h_A2am#7ZO(%v*Ufcrbj4pcq@O|1_(y)a%QI}?L}WMww(~d z+xgv?1R& ze=Ho$Pu`Djn^5IspdA)S8$&7bAP-`DjTAr!Q)82rbfF~e%9(99%>|*GTp!|1SMD6l ze)e)NySNH}a;Mc+YJQ$*s=jz0h#jsI0c^&*TDK?g4j&2-BO{dn2q>?AGPX7meYIWj zG(7zA!_d|Q@dN_c`L}JPcvJ@urJp3jB??5tx_l_pChq~e{61QszI+1u$HL?nOVaA& zTETqpiTpk#N;CU?nKQ(=ug=RMJ~Uwip5L0&q6_Bw-k4fn5d0mpR+6$k=AOY${dCp8 zP8v8`xzHgfY+>WQg9oBRidkKV)_^Lj&5sofu4C-jQ9T)RvP&^~IbB=5+-LKqn>$>j zcszD*1;r{0&nw=4-Xa*vXOQ7{^&jTBbM3R?@7%Iow>QHUtm2WYJdD`!B8Qi~q%j`z zlP3-{sHm$KR82H)qGL}=byNaUb`kF1<=u29oHEkE!GIL?Kz3sG>1NgXuRD7m7UFCr zHebv<6u9Z7#3E5^8&7fzj47Bife$O)lJW1OWrMBHYy1E~i@e%BRL8e9C#gJiZ8Ua; z+xW_7Gy3grI5VmPu5#)1iS6f}svci!hl_g(SSwLq6&3q;yRKi_f229qo_v3hklx1G zPf%?-r%No5A@YBpsheJ^zyriz2S8kQP!YWBaK6&P1e3&^Y*F6}KkDrnyubyywb~oK z(WN|lE-JVgOJ+jjdUuNDW6q!Hcd-cN^x5IH~J(vA1>9W*gk+Yz%I`7#(3rIj` zO65LcBMA=)zZ{UdL^8=wxVdmi=W?4!>}-_SX>qE%lr`YueW}r+E+|kCugko3O4*D# zsefuEU8+^;fVx^P>kn_@AM*;|X$SM`&{8b`w|g3zu-pvcihzaknXTA$GdAri^CFt? zMl;)w_*CsOljoW>WLxgNv_+d&U0$KFifz57EzfyHAk7KLD%tt1?|sXcy$+LSyz?$& z-ixLymVK^&@qJR|BE062%MA&RMlNM%?S%H~G%&;OFzhIq2XHc3Am=vgBUUUB^|MO4 z0AT+o)H)*hbKfOE?(4BfN zMCzF`eS!f{e_VBe>S*J4EARO@+u51wy&GVS(!C0dYQm^I&meb>;%k#ihkuhJ*Yo!A zH4s?*1lK8hLw)D-I;heu$+=rR+9YgglQ`I_2=~u;kC_PtebQaA)iiV|Gf6YGu2EO7 zM}O^kT1K!BU=}~X^g*=U`n9R`8r)qx585>8j!L1H?v&>eKu@fS(VQ515o(*38$iJY z5u{J*N?fx!lGcMXON=N{cnw&5MH<7-wE-KDCE<4&an=~sgH80iaX`3GFf-n{DM;tr}g zQESzeI{U1pDKmbV-{%Y>)4P4AS!mlv(bUxP$#YpAVvDn@$^&gGYd9=e|F1p$bFo%}zSO`ma>*&%{U*ZBn)MZ`h}fQi zzlBgmRP;N8sG($!KpOs+#hhrO@g+f=oxhkTb_XilN5 zQlA|Id*vsUB$ZB~8FsF#)1kKqW(BdMtxwF^mKVUIVFtxe}u3DuMZa6mso zI`?EfoesXA&PB@i`!A4e#8&mexbR{ZoHta;w+(B(R!nkV;RN}|X-b3WA6%ok71QzT z1^PoJ{~#vf(#tEfJo#vgP%_J!tNG{fTe!Di0=MdS8ov)aG(GHrQ!xi+r?PIc1M-y0 zE@!1P!sBT5mTFq(MM+MU8p?7q#o9Hp?QuHCswS`&`6`A+z4{u)kKRORg(ZWy8fj>z zb0c10m59=}?d8un>aC5daPzghSPy*BdzV*i7`W9?QA@wPhm`q>YGl5^QlNXvT@e~c zDUJOa^HFVU8aMAx3O zkvv?lUu8y2YkP7aTjO#r$w6uDj_gyaO-{%cE)vydD|>Zg$K=R+o4jW#;+Cby zSDWV?$ZZG{%@;#Ko+gELVRCOl;d!V= z7)17%S+x`xAf>{-wON$@y9xd=x$aj;Vpbg>(!*}A(I`z!8p@1d>y2~M3n3ayyZxJjzKRsmm0cI~A% zHp=c-&eaB_gQfwutP(0<3bpP-d;I_gVC5r~yT=KRdL-47c%8cM4gG)uzCMbc&Ov9I z1v>!%33U3Zh##oG%tMH#M}kURu=@C*o#c*VKmYu>ZVLoq*m&V6fHF z5)g-t)!lLA*VrWGU^}8S+s+$PeG*Eu|KlFeVfz%gkGcMGEe~m&;T}=QT_6p04T0jAzVxeWc*up(9`AqJ-WdwA z4V>B(kzW!Kz;nGochG**KtOWs6`ba3Q&`|B849i& z)*Nj4hEmoc|Eu}BtLIyhlOgb3zC(JZG~N}oSOxV(TKFj`^6Hr-jp@0`wZRBbM)CU? zzIPokq2>}?D2NGt0jc!Pc*=Ch|8T6veUOE+7NwYW0kFFNxTUJy4Z{|RU6WDL4`k%} z^KRx7ANI)Ne6)_PiU^oL(_H%mx_;(>%b7jc8qVXh_GDpwLGQlu71N#8`Qo6e;F z?;49f&dAK)<4q4O8*@Xo6511T9mvMWBno#UsK?e&ZHoj|A94Ay&u^? zGpzm>7xC6sW}_GB!m1}m_1@L3c9o(#1asj!e&&fC+S>bm-=iDVz~>U@E(+}^W2H5u zIz9wGm$5~(t>GhM;0Fl@sP@5P-g;&#-Bp!$b0~57p@PttM6Z z0U23VsYRijZ27(=akz(W#!(1fsfrIf3A$rXuF@R{RBy`NI{m7hHQ|v6wV}qBQ-rlM z1!*#}?1)Y8k6sGW^QEc6c=5$EI!`Wt^2(Q?v$5ip8*#f^Lt*In$S0FVp)qw^r7(;f z$dqu!F(q~Gb1ty;q8gmpMlL`R#sptomzwHzsVEHXKLf3*Nhe#;6TDyKc{G3S#|y6? zIQ=n5V`SD_gIGYc1C`_rbb-mStZz`APc<|mdMO{BNNH26~AM&PyV4g4P3QS^i>ge1mH=0plpql8L4q&}U~6o<{D zVEM0++v%Kdk?Db7c<-J z9+zKH?djeK185A{v27|iA^jwp`$kFc?kS@i_d)kTLTXL})44$~IFQ5&>FFuJUOIL2 zF!U3L+rf3SbGdL&7WIN4R4F*#T7ax`iCpnJ?{31T=<@GV5LRKXG6D-HDt@Me|5M~@ z@`kC9O0tY>*X%}1p>xizE!)nGE;S*t={Z3TRMJ5ieo!uu2Yp-Z$8cVG@TNth&wJ6t zVqE)b6Oi0{)OyarF^G-(H;9ZxdkB%HJfAeCLtZxc6Oy3#gGbg1%yR1*7kuh6_kYw- zu=Bu(7iQ;rejk3=dB&u@K>(z^Dd)yL>0LZIerBGrmM<$PBf~5gC~Qwr@Hv#C1y}Gn zhAz^&w;$kH3i6b7jkXKF{2XU!-U_(*rf<_9FeFjm1K4cNhG0P!CG#rX<2Huv#Gy8? z-32>d=Kh-5F7QVn55si!?uIo)Z>zwJYS5z%n>lijCOE-)gVZR4bCP*Q(Zsc=0EYys zeS3Ni=cki(KAIlj^4TPvtQ)+Z0UI{lqy-fUkKA z{Is+E3)XxIe)<$O-y$*O)K05F37pp7AhAIT{Nxqfjj}Cn%x!4xb>2AJJyU#}510&Y z!n|2{NV!{v(bnMLD5t1SAUAgy2wIQ4%Bj5O?mISZuWRpi611-EK|mzv8~;fk3g=CL z<%(Ddi_~~vD}SSEDB@WdlV1`bs=vbJa{=5d@l2Hkw$HcY`L+Db@_iq51gwZno+$D* z-8PWiHJ^C~>lA31bQ+@Njp_oeLHQbd-qFikxJusgKj@cV$PECgXf-k-I#ArM5LL_Q z=~v%&BmCx30;_c@tZQqmOn1uYmwS6Jjf6IPCXWsmFeEk+zuijJpHcqZD_#zhoy*u2gYA_@wTb|1m2SaWiA2mB;fd*bQ2 zqg>kN0s&f--=zl3^`|9<2d=YEM151i3z{jZUM_J3Q6mFTVyWa+=D74YAK^YyAMqoq z7aiRR$*X{gsEYY67b>8FipkkF%(j0xM1xj@ID{Q8?R72ZtAW#T*(jk4s@)f2F4(+< zl3orts-?9a{XFv~^X!*d5lvtpP%yD>QCu z?sz^if$GpUa4uNlI=NJ;kDAUTMneZ(%YMc&8>+1aJ*B?=hggLjq!WfMqaGK6Y-Qw% z3jXDHa+&rfc57`nA`ZHv_ti|uzK7dP2KYGcSOM`;A4nw_UW*O4@Ege6V{h$$T*K}p zCG?UO@vWssK$rUrA$ce87uecVg=fJ2lT}XaEQLjx;ErmiAt_mPC1$zUzfb*SPJ-W2 zPV0o){_&R}r7Pe{gOdex)O|GoZkT+^+2x@dYhuy{@PNCF`?L3=_!ppD{HPk`fD2w5 zFS2X(FeY?`hs#@wTA8@XrSslm4v69Aw;2G*)b@z&KXsr~6wG&LRMkD`l@h8wVKx;2 zY+M7d*bip87YFB7f-XhRd6qC<;$o|qUt$<3V+Xx(Ok2>|8_id~bo_(q4bo>EE4E%> zv7b5XN&x!8^5IO?H86|h0s+j|26;(cmirvfQC(?9P1VO@;@6|XUBQYuh@}PlOB^0` zxE$yKy=xvY_ho_pOTDwv@U64E)Bs=K($(G7d;biv)9+jm>#@;>142E? zZW>MRxFTd(amo`~Tx^A2kyOG~CbFO>6mDuxL{p@Cq#&PAG{`YD2ln!5h>FM&6pj;X zfb3CYdWHEurH0x0hr_4qwe)tqEvW{ANL4vGDgqFUNRW1LrU_yRcOjG&1awMLWF8;b`0@~%a{|s|6`ovo)fj65A|5+wb_-7~1cx|M&k&~kBKJ5uZ zIkWYH!GS|OR`5i{I^hi}-oQ^vcy1@L<1$LxU z)&V8bTgD+RQZ*Z+i;4R8TBv;vJYEqq%8^WOT{{6EQJ4T>G%F$q0q(zCa>V#CdApxA z027+DppZEM1uMa}qt~StR;K`Ld6_Fqh5UUp)MI+v8tUaK`M>pV7guosFD?~_!)AzR+Ii=d+|$He}tErUK>nR z|2SFP(CGFC{}CgxM041yemIo6o4(ZHOz0zLr5&o%9s3vu-)8KpYih%KiRE6Ftl-3s zLA|H!v-{l{daSez+lHpvU#Y(H0;`$(hivn6X|HDA2EoW>gFLntAbO(fEdUkD0jNN^ ztaqMp~7hE?04K@W@T6jyK)$&rC&kMaEABoj`lP}sH161ni--V(- zT>6(BC+^l~2<;e?q9xf@04pw%m|La=hGkin%xfb6*{3u(iG^T3JG`omsg50^G$?5B*uo@{UTz~Ahq+yhL9gHGBQQM?idlCm~5 zTulQr1q2-7u5{gAYZfV6|6O-?sWq>1XK!;8vI|!hzog%2+^tuU2sq_Va0!g}!s+Z^ zed8j@aGUx^a9bin*;GXwz>+~sE!2d`6_h&U)bVK6%1$5!uSye!vBkA}va-Ydv>epx z^XQUe6aCn;)dj7vye6@P+2BW^3F)f=+~Z*bFWM%|0do!5g@yf{>}j~kW+R=jvuY;f zmC3wf6K$qR@=-OqQGXK5B&gy`2#e>E3t`_1+=Z2GiU3ih`Y<$sRl>hczJ1y5l4?f% z^zrlmfeM0CnVGNXD{&L()8)PjdXvtuP1Lb&(Qzp=)8{TigBwqhdKDtN$DziHC+)Q#11k|;+I}*SqHQ3lpwC$e`nY281l+*=m9ic4#*vjn-RE^tE zkWpo#-IL~khtR{a-atKZ5xn;Qp){#uB;voxJ8$gzgRb~g=BcHvTD~q;LyfBbknOC3 zY_s5hgNY+i;iX`D>#WEF0Pn=+ZtRlppELJ0-Sn4#D4sWOUk`~dVRS*y^)>ghOfDI> zUc9>IuOXL6UUimv`-kmNOGf70`wFwz-{%$z!NC{7-56E$TE&7Ae2+%`M=@9Jmc5U^ zX9M1u=ElKcJz%150p+I zP5)ml3ekB79nd<^+4wzm5?By&reaj*jy{{JvM8wdbBMJ?)LOLeJnY4dnGS0B725Zm zjw_;ed)U-AtiL(LuEo%44b`KiLz1MRjCd9x@JLUt^{DTNV?T6MB~3&_zQQfl3{9Ar zf+ZZWlbChtu4*Za^hk3fS+7+yGa!r~2y|Ei+48(9q&N?1`B5|Hgq@Cygae3GHF0|ZKI@v+|9Xx%_>i6o>~r!6oy6%Wh2X5y^D7}|7O(273TdNW}tl|Ab_8v z#D+4~5*#St#dE#G?*{n7vm^_-}Iu*Ic7H2d!clH>*z4ac=7Va<)U6$^1F zBuh^$p71&+hktSH5LW~)sMzo;h|w*EKzDll!=nbj1JvRLhQfroVl?<6DMSL;WovFf zC_Okw=t?|*&KS%fykA#o0L@p{vTXnchVIzTIA8#o!uP7fA(dil!=I{|m_X;t(_I{) zMsZO-#d#(9!>_GvN||nGFW%0c%-L&dKmD+o4uDE5RILvYh{~9VJoKX;;zfY ze^b?>b)z}KWpQaQyDR%$AXz)1-BNB$7Q6rGc1f=Cc(`;^N+7h~dg~~|^jd&bRs5BW zW9*Tq*+HcD(@)o7D+sUwFts-Kqm2w8efj?_9BMIs^O!JGA{}RJ?>kH)KENYeX2wQ_ z?~~W&mWG2i3k#CR7(s4)hsdDeqV}n)=l-5mec)_=(KXNkWEHzr@Pu!{d;&XkoQaw5 zFxhf_{ARg*_vqRCK;Nwv>j#Le|$pNsW}n&Y+lo|WUDh9*Y+<$D5VB#vAJV4 z@5PH`y+{zinHU+>HN@Ds2Z6W-P5!HpCtjXZ2D<$WMb}}lLL%h8P~rb%kUE#`8q0*p zoQLu>0Blws?~6~rO{b1{r`w-b7_w1~SEKsWBO?U+%%J}OCqxK{|+TrU7ZkdwV+6za>aOcw(fT#uW+5=MG; z#Qv8{t~gHYb1fI348i%n`4vG7#wZPnAgiw2*D=&MouYHBBkK_xt-{>{PnlOnl3;s} zeK>ol=z`w5@)pY){8Vb6`61oiH9`%L=fy1Sy= zcP~6_Sb^3}0>m?3vXKapmg)uncSX{psi@>-lMic;@*=}?=Bj<|B?C-a1*j2)0#hlh zu6q3+irGXm6s}XUI%y!zEh(@uX_i1`-KuZnE#!2Ve9A~VToAX?o;2tK;1+?W+cO5j z-cIE1?zJ?^DvAx+Emr-leL@_U_(hI0#Yh7uR3kbRGjtFe{+R>w1swyIk)Id?*xoOh zbDnaL{=bcHKq0Ta10JM(A|o+P-O8BwITvhYU1A=jAThR*M@dy?`5~GtEC<*J&|*k4 zMp2ETR1U`qLY)n(*f4%8#Pm8KF^G}x|MvfH4Mm0r07b`Vt0tk474&JH&^<#n{aw(x z(HK*ufwECqHz&%YpG&i8@B!o=2wOvNeh+~>L+^|N(vcsshLEan=GXs@u(7c`S6cm2 zoIPEPZ~@u%Mp0CUlkP#1SF+QnCYbwQ;{Hu)Y+0aCHmiwIwOGyjkF6`Fp)8 zAbsgU^+k&ET*^2HX0v^+mQo`5Jmm^0h!%~a7x(Y4%xU5zYER>x>8`!V!%%M+#!@k{ z9EwRgvgi0c3*rlBs9(>(e#}940dfBe{Y|uo)1P!RKQTakj}@&SEgrQFSp-YsmIlYZ z`mO?d2UlclJjoL2ph^;icTQD&n-S=o4R-VJr}?NfCSVP}hJePA$uFEy9vQpi#D@dK zMXdO%cJ|}hNrMX{4(MHo@iHp(!L@k<*XGV@p*~1Dv$GHEG0Ur`%R-%zCSf}SBLiHCTxS)Ob6A7 zDNgY+9Gmq5($a-p{hnW1O5lTWsH)31tfQV5y2C7^LyQ`f_E*zSOi%vJTw<2H#E8YH zs+$k5&pPmFoIwjgU6k8qhacgL2BnFC|Lu7K2D?rz@Z$5o)5xO3IDvHbs?ngNj4BtilQ>}5sDG*zgE`b(({ti zF0%xA*MsoU0g+Sk4~nEl>ZK6m0v%>;kg{(#px~X)LZU`4+=4Ar>-ojie~2*#x8Qji zK1`;aE6wx*Wx;?fuqjW{a-YAjsSiUxx(B!vfs26)p+Jr}G^###seul7(m^Qi-2=kT z(uL!6yHNmsynimWBK{FIN|DoD6D&*!lm$9B(Y_f2e-)~DRPXKI76;EAW0*xz)Z>BR zPUgK~SpMrEJP08s?|)E=$medQ@)6k+fRh&wCog7^>eALMIc@W%6J;<$gM{=>h&@gX zlsuD!jUy2}D;>3dg&=pd6yPkED286Cq!qs2Q+PIWofeD^DStm#?f5{_C)pmN4Od@4 z23&+tPLomp6iEI)V-bpktdEkkT?6RAZzKXs)zjVMg%pOT5&dgj38IrDY!KU4b_;WUD){uiBv6S4m( zQKOP+WI*XhM_z+vao^INNh|YYqeqgCi2NRV^t9eHj>hIUlOz?irIO*5*-}Rv=%M1P zHCtUT^hp1}TY8yh`0I4AHk0?tdYx(X^IAjNDLy(z0TM8>q0!FAC)vf6B>>Oojo-KC zq1qmgk+<+A7zWT1ZVMlDm5I75{L2+XYb$!(sdnzr01gh&f$f1sPjLjE?%7)xKUy@RI4&^+(t zG6R#=1b!KL4e=bGcbow#3&>zW*`UuDUyMF>37ZcQRu+B4_&Sf*db*f^F}k4wh0gUs78*Jjg{OK0wBg$tZXp8TBCf&0^_PC4b4p`L zgW6eEqYgF*LU{c*94`a&sooh4pjmt{P3)R6yQp z5Q3CbYFB8_d43Fyy_5JQh00YOIN|h=69oX?Cd_M-*h90w#fc#_h=w|Q42c@k?BQv@ zFhI>WI(iVNe9Y|EuX77^&`eY<7UVVsU?u2ZOR-fWS$t%ko{X(&Y;Y6#l>%tkb2jP; zY*>QKHbfdAs%v^KIO+||^D24pM4&L#K!}ey445hjjS`qoS}2^q+8`xT5TxQI(jknt z7ddy%XWK)(LD|VVAg|NNeR;_C@>*{qeF^1BY(4fr0R8~gymKPdaCZbj!QzT~{ooWO zyn7opI1w-im@HD$jKYu4oXj*Jz10hy0mBSrBoAEmwR|gV)BksIToa&30=yZKTl=2c z-_hyB2mn>G2M;l7UI$9Mm={XtJn2Z5nlI{YjhPQ1ZAm%yH^5RsDa`sTIJawvgaAYo zZlIW{S_+@!2xHi*wdQWM$5NP2nbS&)2U*UbPn=`>1oF-i;pTv~hX&m-x-od`k>3kx zqcEl=0mbTTEwqxwY!hethvWqy>A!$Z#y$13`A;lf5^(ohlp6Y#5~3{$U-hR#!%zPK zu+zTt{35xPfBOi-8BUjL(I7=blYjn5v-*W|97dujw?F=vi*dPrgK*rBoOCJ7j0OsK z3*434HXamaR_^ZGoDoW3eNHzx9WL!nDjPO1T$Gy+RMl^C&D4xg!&-ZM3o(d52RZVV zQ$#q-3Jj&6X$h(f3c~x({?gpzq2{x@eE^XF&FsSO#_{3bpWg$OT!*nJpC9MyNJQAU0oe^pMko%qViK~19QBWN>fO;aT)?KKU$ z_5Vbh<@TBZlbn38hO)~pXZZp{dt?z@G`AT&g^lbE9s4z(1CRb)ZosHoOI$RBKLvEj z>z<`)RU`FZp#CI5iT(Qp5;}u5)$0fLkB3cV{narj+{ma0MjGaxhm*@hp8hTqPmJ`k zsx93NPW1b`NVvek4Wo+N6LR=&F5_<;rL>B02n_yUy%{$Zj^dB@7 z-L3w)qJQYf@Q+XIW@dYFk#{Iwbnskir!NZxZzm9iEa>*hw&`Rk?j;wgeY*Ki9do)- zweljVs2eXTb7#!CA4QBM4q;dj`QzFlMrWhB}0;CZKRj887v^dSmqd@PZF9bl+7V_Ql|-L6gYeGL4EN@Bniz7M@5U zS~rlQKHNVv5K?I=mt5!fWWc;Xn4!ybNK8xjrAxX!R`zgaP9${JU7MzIXD5G+mv`Mx z?{+SGC?Y>9LP=q5q96rcf`+mRqyFs#21N7hx_8giM(ynHs0)hlZTw15`b+1(rZx{ZiWoCpn>m?4FhaKF_>HCuv| z=L6&Fc69+^!iEk5e8?kEz$tzT-z#dOeJJCd(SFk83g#E8+u-EzeSI)w(E2mw;X01i zr_-b`!?u{D6Qs}uS@&)0lue){nnSNR1UO&MIN!8W&QNSZCO;#Bn{Cc(IHJ{c0$5_qOSdWB*$qPs*2?i6#^Z zqWPfDCsYgd&PD^u__Ma+Gl!P7p`{={4=aWMAkMkWM|0N~wI1@!Uf^Kb>&1WQ$uMC7 z^8wd?Gy4W38t866QLG+6sSty^l7~Z_w6lfhN&%bZLdoMpy7Cy8-q}N*aHd+^X!4$s zx}jxX9YtOt?I0r}bD9#dGUq8bG#XTOA3y?4XQ;OCe>M!LINo4W1c@WqaD%T_wwglmn`?u6qJT(QyqPr{C<+ z;1l6JsBmLXFeVYoKMv@!YaDUfuM&fNeZ*uCoCDN+<-wjq)|SMl7F8sr8%XHnDmQ>N zlNuW^HKtN{6NSU>cA`jh>)TC`i-CSqckn~;5K0{nG5Z$JwV~Y|fd5Pf^S05xU}4|FsAwLuXd|PE3;+$OxM|5u zyGb4$c0G5rB9SCQ^@GM;haG9j1_Q0Jzr}!E%6?7R;)CFGW}sN<^zRd8E|u3To~EdZ zWC0f<1e^}2(j1;qWjfS~Qyp2^7>u_YHr7xFfQx?F1$er{PVI07GpzR@%)n5KDh7`| z3E=|ScK_*z>r26qC??s;5#ly?oqM$GL_8+<;p9Hu>2wMJco1=4bmUxyAaS50n zXuUdln$`w@22_g)G{?HrP~RRtePcc9~ZQ6O4m_UMPi+hGME}O3d>59Yqa z+`mr1iV38Ie*{Y*l^e>@Nr|_Q{B)JO4I`rt?A!k}JJV6sNZV$F0p)%Zzf^YwBDBdm zo6D4zgl37qnUW%xCDN*n8rh~q27!haut`c3-xqBnXT1k?F zBd#Xmt1sa%o@m!~OnkE8?Ku9sYFCUZ*EDf>Zj0!n%2xIBsp$``GUGmA{cwQhl|c8Q zxGXPHy2ZkvK&`Rq<=*kTEUBcz@bDB6?+0lXWX=9U+};JAH+$4;I2aJQM`WF&hw)_X zTbo=I0pD+51pl+PiZyTJh>U$sYK`<18VR396ppT?Y9Gm9xE*q&8uY?deM17b;=#Lm z09+c0#wP%AKxNDP)6 z;BEcUw+iyx=j_!6xTwce!DyEd>MTB6C2AvaoMX5~hxJWmj9Kym#XD3f%$8urj!ISzS<0v9~hS zBf$}O1Rkea%r0H;toPNd64l}8Rx1esYo*H;)b`Xd4cEAE)R14eq>la<3sL-1pTNJV zh@Uh+4#mBK{VUzP$7aRP0uI6J(I4`8ww3U&RSR`r$OEQPlF-ezxh0(F#&In(I;*OD zNNS;WaAH>)I#w`$a`5*#$xlws)pIlC{;7(}_#KUm0gJ-kSydpbguEZVJ6sP<(!4CE zV?gWAY$NMp+Nz)mHVjcV)1PjLWhX&_2x!I>Fk$*%)2M*f4Z5ZIQ{<3f$=%CrJCo0| zi%%gw+`B0uz^6m2!t^&fSOBYKU!gJk1Z2_NZ>3rqU48$<^o60oyk-UB9&4*RclVHh ztj9O&Q>8M0JqULRa?;xxH%Prx8>Amo-uUs20P+o4D`oNxCF!L6CN$T#jxibZ4RwkN z##*!I1n86nbwRHq)qeLZVh+LjF@O_0rbDl$Rk`S;DReHgol|y)uhPT;GZ98H@?98r z@}josh8)8aLh9p?Gjd(aMr^E_0zQ;TUV7a3B$V=QHAJAwbIb@SNwKX^mJ2F~ly3Ul zF#s*q06D$_v||bhLBsqJE0?!fi?J7T@L^sTRTwg-<`&n?I$OVohrhfwQS(ZyHy28* z7v;xf@!@C|n^aKjUyaxZJ#Gm{fsaYo&rFiIl9LnU&>c!~E$*V*%21)5IjNsPkGXnm zn8w|f@CsUNdIRjN)k59LK_Jb*CrNkZtrm#2Rf8N_67OGH-2Tg%`a*3Fq#dBO;tk)7A9VXUf9#|U{e985wbP3s z$ERd10B|TXetgdE;=d(g0B^trssPnrZ@L^KGgpnkYz|~ATs~p|1IS7NI{JvAn)205 z2bNx|)K&2ni@c5j7XkQ^K45U!_89@u?zC|=au~1*>h~h)ETPYgry!ZGkOfgZvK@)ISpHIK3hxvser2wNo zA%N#!W{(6a&pTCqpdv#(ysjzB?}u971cOE#HlA35sQ1%SCbfZyAg7ifFiFFyWMGd$ z>%Hyal+G-n?t!JShoPz)F!o%SU`{Z%Y)PTjB!mCs&_@z1Xw= z3m##zxT=xgCB>&}!*tvk!u*32Jq(SH)!bLhcghB+yiMgX;VX^PoEevA4-5X2yI`JT zzkBzJV_@{asWB(=&d`cit20SyZE1}f;5w9srM^@`yL44iyeKb$pS@@rDh$GkLFCU7 zjEo)c-w}2|(7aGjZB<&J_%r7QR5-YRMo~eloQdyxcke7?(V^WC)n)11qYRdxb%kP(y{L|)MeBUUhFQg{?K-pMs zom*QRgg(nR;P;0CU2F+}>4N(AzodhTf~r7^GkQx5{tI@Kz2rci4Z#`_ho`pA-hGPc zjcp3ie~^i-(Z)#%48Or=SZm=}o8FD2gOWw--vAHasps3F_Ei8=8pe!cxwzPqG}KI5 zJas^S4WiX*<>Ot^B?5u&)J~mh>7*F>V}f1{dYjJj@dnF* zybWb+g&+=uRY4(!2P(4hB3x3OMs+{^>Y<`%{y)>qUH!fa8h^jv+g9kV@V4C-FoF&b zKhR7Qca?QSkQS%uE}fErUjq!T*lT53gxWVXAeHApj>8BrQS*k+hI>bP!AS4N<1fHt z*@#d#&BG8GY>#spUpePNtd3D{VU)+~h^pD4i@l|I71FQ~>Aze;M&2*|Zrkj`UWMB= z4&>iYK$weu`#&JweFq(iT30FjVH=&zo5?Nv-|a|}HtcrLpLjG|oS(#KfuW1_U6>BU zX#-#F!#Yu=eVkGL&vAP7AgkD$VkQNz9+~T8cJ(1A8&39D+wlq*9?oC-_alkbM3}!TTRC@>dR+!~lSMbDM z)av<#jnf--D{$R{SqW)?*llIi-gS&ixO~Zt4M3RQx<*(Zh`T>hdcA$a&t+pNJvC1y zTAXk&UfL_JX7Kn|kE(MEY4DBORakEvz$utkmG4ga7pU=m=8O7U-`lO$-PUKi!~c*9 za~{H$E*N5z5FctQC)6_#03xi-z@^CeqqUQqPa0C&r7hc$58#vU4Cuypy}b;x{?Jj2 zwxPPRks?NHJHt@)Jq8cqpC4$-YM(I2NzycY=1pg!}6AQw6EQQ<7W}FV1}EF(;Bf7WAa)8FgQ+c9{vd$R8W>AwK89 z_bH*7+1;S}^rbCrHssOdE}=x>0#OG`9l9{GynIz@2=(?&;Yzhz2I8*LwF!DgE4NAv z;s=8aB+00bZ1L=^Zq^3P*n1jjO6v28KSC^B^z_vBCUJ1 zh>G&rTcl5&3u&q=ipJ65JISBYmleL~QfoF;VOzs`XZr|jUyB^h&ZK{!$DCB$s{bYv zE&tcTYG756`?cZ4g5dZMHQv=OHNsYN+1HWf$={?Uc50og5eq|gORNGi>P-s?Wdtxq z@!7&H{dRIQatXg|)Listdj+p5Mt9z6K*3N}2EVolKXt61;QDr1|X%LZIYg;tljYlE+lJ%O$n6 z(cf9EYkqyG{e;D2w-?GZiuPtWU$rDtY- zb!~Wv6<&=l9hhnR;YRK&^b*@(1b$kS1q)n=x0R$}q0aGKBFllBN@=?c-dRw-b9EM& zx)|!#GVu2gnfdDE<{~PWJQibCS3qq4SHg8CJ3Zx!&~ScF?rx3bV&CAbem6dSEfV?e zg^88u&?A5CoapVm^j_V8w{OmEO+o!8=7z`Ol4tJi;4uEs?bFHUtbaL|)!)h{lOZ-b zH`d(9_$cONOyrKm?DY0_oRT8*+raCIPRKoWq*k#FZ6soTNNonUE ztLRW4Jr=d|x5Ufy7xu!+(wnKJvP%BlzM4xmOI}Devew}8;4HqRrUJjJs;=H_=)b4< zUn_E8;iDOG^sPPjQ#j{h--_!s;qlzWzlB3JrPX?LcE~2H7+!qFR;f<#l4WiE(p$tm z#e{&3-xFbp&9P4D{IGNCq0i=~b+v*#u`|o5UN`MS&s9=a%G8q0FY@Z&NTiOD`uCBD zFM%Zk^Q;FB@e7PhuFmRSU0N73w94k@D8PQBOK2M2Srt5)di7W!T|%J5%ulH>f6K8P zi?z@v12g3RJB{Ro+qX2T3TZAa{?Rz_RsE^U=o&|gn9?D}AUt|_S?UqF2cdv5+ZjdTl+py&zX7?(0SID$pd zT#OMDy&DzR0v><+H@szMMNrVUHm4dkvl`rj+gNI?81zuj7x_5l@;M~U0CArx4}QF+ z{b1|w`uG&hVUEkTw}aQ*va^Nx()F^f1ZyV9wY|jTDOHR6E>sGyyHqWtIM9U6_CLDV zM{0ie7U$)3d-n2G^d`FG}-}KY` zz?Iy!vrcVNKmN+Ao+U;HWc(w^pYS=XIqJ<9R{7th`Ip+6aRVsaw`WhPy8iqf4t|iH z{opw6*7v&XW8dz)87QvYSR3s4HU9ecEq_^N+z}eY_x=L;;8owH1^yuO=bqEElwK6K{DSo0Lkaq2^y13F66 zhk|6!%aR_$UuIjfd=@_V^t^IHlVLuScd**TnZ|E}}-K7M}y_kFJW z8qe!_J+Id*lp=t=dk5E{`}^m?G9_gw?K2}|vq_=Z&B@5l44mrDQ*<>Br$TIOGh%Fb zvdTc`rDllug@SiJb}sodub4ca4`1VLkwr6f~^b)Qz{PA#ni z)1He>uv_O-BVUd2n5)*LWTFmmf}c2^j)oH3zv5|*u{|#-F53IpT$vy!c)Z1T!2GsW zO6-BiNcxX(LP*G{e!yz?C=9Jh4oDHtb(Z_tXkqKe;Yl`bf8mbP3wx;3&V^V*b%I;` zwLF>t|7|#uP!T?__tTfuW?6#md$9eZ?5T3#OXF?xnxesed;v$!fxgKVf857<1Cx1IX#haR$i=wQy8hA9l{JJ`PCyt_5~et9c%ayp0+ZT4O{{a2?{BVsdxRO$+IWa+-;Il{ zlEGH9Y2N)i`t?_Dw`Mr2h48KjiSIm|X$a=c_7w^k*n2WAt9X%AQtG4l?i16wj=rSJ z49y!V$OEZFx+|?rFWBkaPb4W+J1=Z{6fnB^#2ga?i(h*Nvt;9^EM`>NF!(XNWc0_-nMxtI^TSFI(XfXCN>>U z1;0|tNVJHFuP1Zx;cFU>Yqzu7rz4!D60!4cFLyoZfAlR9R3TM53AAX~z-m9nS~fuM z9FjaxO{niD;dZagL{c=o937j;zbCQa+?CN^7@2ZVoxh>of%DkXqIQvU!2BoBk;!Th z;c#$Z{RgsB^xXqSxsUKLYL07>!baWkTWt7ig3a>w$`+C69GdCMePE8=}hFeAv>Os*~`(aXn>db*S!nchlVQ z%$RCSlh>cgE0_=I<;2PJ$YsZRw|{@QDI5Qe8JkyoK62W@!UsY<Ce;{~biI2rhWbEh&u28i^8p z#Cg7Im*}17W{^L`9S(~twmlbL06*sQK10m=Qjxm*>BJt!~s zrkwBGwN^OFy-FS6Zir4Q%6%Z>sK(9B&_AVnBWt~TZS{do*s3vFxvthYz6b|<6NWv z^oga8)jT+{Id*cm<`?CB_v_|82SADLfo~|I+*gU#GBG4|EX7xK-`IBVcHh&=%S{{D z@#!BsD8yeL347J4Fc0_8%8Rgn&v_I70INn)O~p&SQCPw-Z&sEAc{xcLhy~orwKy$h zzJ~CrS32(08^vvxiiXTnG{laX8|`0*qbVPepZd@mxY{e9KB}>Pq?dLf2{rVz{oTn*kI#yG0co_!P zxvY8}K6KtC>Cn`H)>97$?}*ALycrV@YDTAT=S?g>D*?c%1&%!OlQ4VXG8u(F8Oz3K zY7<}mf8WACtR2O)xSduur9&7BchDxK6*Q{6veqOiCGo(ZQGE4e8&+#6fyNvvK9w^`K{Rc?S9Gy1x`OCD*-*2D#+BMvpcK&ARXY z<2)Js8}jC}jB+xj#x*6{Cn|tRy!1{?Yg-B-qHWvWX~v4AFXZ2G*6L|O#)K%+HgS|& zrf^)21sO9|Ozu7reLS`?T{S6d!Pk-X{H9jxMnzXZaS$!r7zRtAr4A-x6^&`i{3OP$CvnO{hgiLI?C7`(qKUtC$*da1B~!mpO;f>(;q$kDJ!iuS2rQ zjBcCTaTUVaH0+Q*P`-?YCb6=XNLhFmnUdR86tGXMUr^~tsqYOgt^gQ@zWo^R&W$Z+4y;ZuQmw%@ZA2KzqbzHP3t=-nZvR*HbRMHE_EcY#(7VU+9Q zg6&3qLe?HbW#PXy4@$(`hn2!n{b80~n>H0QW5EL_9|Ef)!|Q`2c^4yJnv=ADSUu3b zS9mR6X3SK}_O7Lm_3vG>!JtvL6X|GQ`s0MWiNe*k$Njyv?$iaE1UUzj9RrNouoJ@3_qY+kDyEzVOt z#Bx&95&Doix14`&Bl)OjisQCjFE)85Z<5AWFhDa{X5+9#hPN*l#Z>0RgJpnH%$d=% zXw=p@vgJNF%f=f#A?_{z{X}4H_K*#zIEh>yMUy&*whn&i%e?#IqLaI1G6*CFS5)oq zdda@-G+YHe{;G~Z3PB$!ntGKb(6VoIz^Ke98D%LLpdo%suiS9Rzhhc_mur3|@$Rg< z&Dyp?WCb}wzl?cPM8ZIX3bOH>`!!u_J7+Y>FM>8+Mn_c1tS`hvV$XY)7;}(r;Z)D% zU8M&7jS==N6u1J8n?5F7*=}aa$(0ks_e&DA_c^|Qf?U4;1StFceL2sJ7+O>FCpGh> z@2P_4Ke%m4Z%iC=vCYObWg=7aX2i)6(y!HrE5ncY4PW&5Lk{TA84w(ttier52&?1F zE?xdfC(pE1__n)#Xu9Wn?GwsCnYd2>%Mg-|zH3v|oFVUM1Kh*9jx_!w#@%@I(|K@u zx-~cEgjcnnW%# zIT?G-wuO}3%?~&Nh;ATY|BgO8w&DzMc|$b`#h`Up;@mOi;W1 zI^tzQPUz&0oK&&%R6{_mQ_X@Zg(#J z_|pVVuan|Lg!c|^zM0*h_lg4p-oG$_9J2Ivu0QQT&-=TTU$Jjy2{MZ2;PlT)Xa&Z8 z+|t%Ej*E@ij|<@4JI%385zv_bzdl^y6Kvgnzx5{G|MpHAZrp^Vu4@c87l@nUyd@Tx zbFEby#(w;9ethP1o2--NU1Jdk{&_Z)D>5-MaRzvcKd$e5PpWaQY4^v>818c%&IoKw zZ#}O9X&yK~a-Z*kzbmsT1|6{9$k>RVAJ9?0Baq@T-05AS$Z_XSY$LNj{F2|sl4CZY7E7Yjc7Gx#HXbGSVJyJ=Ut#l;-=TZ;LAF|Z{ z(^AZJL_S!j7+}9{#5GOofNbbWRmccZDW3RL-Fsn+8L_9bNKH3IT(-KV=YNvcrjjVa zXy=6DX;HmC8c&}IY(Dz8qZJ%iSp1Z=yQE(Crks?U^Kiq-lzsDrwhXi-Lix9~|9zp_ zl5%YgSI)$=IsuPe07vG;1rAF*X^#k^6kMHK2<2)>NerY-+jdK0C zFTvHfa0j&~h7>-8-gTaBs=%NSkcHShq}mh8TtJxVU1=46*q-@YR>LQ+gQp6aB1m$H zu?$B`BKsjB+HZYnl-I6qM9D5vBi$<~H1;ORNv9YEgp)JfJO&aIgwc2M`RF+Bm;XqO zjNbmOr#o9*BcC;l&hCh=v^QARV!`=)f%l7la^|%2_K1CCN$`CVQC z<0?)Z0XiZ`aw##Dr)^kK?%$!w^sB(D4T-S_yB03nPOASC=_N4YjG~1*bou9%r<|O8 zHYzzoR2E;K{@ed^R%SDTX1V3tm^J+J`;Zw|p3^rz)&nE;{upR_3!GWA<^LWamkg

Ffd(^isj_xadV^Udj0Qc(em~Bk1=#;)PW6K*MZqhwj=V$)d$|_hgdZ}|H25p zN&|%TwxW_b9eiv3+`-ft*Oxhn+zc?tUgW3fZ2t@MAju<9xYuvoFbyjqbB-%6yIZz< z&#q7fm2`G$5g_l`^^&2n7(*o;FS1|F%9>I$|AOZcCf%TJ0;!6)c1i* z%&fpgTbXk2iD;?LQTcH~>alc`tzcp@e>H;n{nZCvZodtmzrnEGXg(OWpyFu!l$iAX zAUf`zV)G1>862%_DpYe3z`}Q_&XC*^2Ibu)my96{TQh{VJEozQ2-mWnI9{{7x>BAc z(B4f>8k#%&ETlke@k&H(y~8pElSGn&!mUPe^U>BEQ`vx+u1Q+)6w(K-XHA3cKU+G; zF#ctPyG2NjZC`H3(Q8r{&3{znQHo3Cqi=MeIUGej%iYGt9ZT!@0Pz@~wIUT~FfQ3H zVd+pFwO~HpDDgMX8K?wHjR}$w*LXK)>8YAwMgYI#9N7^^6+Rtk0gm5V9iJFar@V+% z@5c%*Y$+FexEU*FtjVgBB2zL1=kF6Fv2t;R6gmOn3Nnc%%;M&J+pYu4Lb}HEc_m`} z7sgiL0Ym(s&Jojt*ctGd!yl)#^I5>+= zG<+F1HTMf@<#~myPZK1&Uf)B9)|9zt+-*`XEQnUJVpP6;I*FXAT|v7VFUwsfQ~~Fp z4j#evBSSBhDIGn`I%n;y9(U>ipWIiePVXmYPFKo4XrSR#z+{XZvHb2N{6mBjzli1Z zICHpAR|$O&-9h@n@ZGc#$IcEv5~{{brBZ}UjgZ6^3f8ZZN+7Ei+!qk^*G&mRhj$pS z$SqxUDm7-&3%+U#2z*dUE8X(2>6MG|zBuspXZMV-ybDoIAwEhGPrp6W>+(yznXQML z0UY~iZEEVg+Zr;zA|8>UBaEmyJ*tU@;|>Dp_QpPuQhDv5OWY29QFI~aW6TQbxF7O` zE%fHvr@Kazd8dNchdxXrXIBqW5Q$}~sSrnjN6=;04+C&gdTi2zX}SZ4HJ6|M<%y`A zKjr1nInPPdUS8#>SgC!5EU$3=2e=D&r_XPZ4`nDLUVHF2jExg&!3sIF?$f_GvgG*B z&eds_yjh^PFBiLHN}vD8Nft`~8z}t_(W?f6hN~;05&!83!3D2#sK&}4i@wIi*TE)9 zCn?v}tKbmK#^jntD@{~Ttu3yjm5%{#<)|oY8$6-^G!Z|#^maE^q%B`Hi1Je z8TjAJp9dfMC6P1!@2}f)iQV_Gi{9K{2HCg8Vib>l*tI*c2j&LI=(2=FW?Y~7JAVYz z6v(NOyF}A`mGs(r6nj1Bqh=3Jzz(j#8JK4=u%{DbAzbS;(~W?4?NE6jUsgb}N$g(` znc;}?Kl;WR(~yATtoN~!R{s8x&%Vl-3m-%;_oAzJP<|Ekm~NY`1cwK`Yk5uCm3^%E z-8q(y;shxZ48igK!?UGzrJJiCrURV2{5S+|ZE`^;u==o+Fy}yp$FOBm1en|t;Aw-I zcXL9{5vSjjW&c&x#dp81)e9%_UX9LbJB?sEGW!2RDU~GYr*DBFRV8C)3ZXTxx_!XV z1H3Q(do3k*-x3mj6;^J}_U|{UsY!V4UeMlxm?pnx@$w_IiVisr0azH46|GK-VA6?P zhg((#x6|Q+^JYh4^2$?P_|>kt7EWe0{fcx&!lc4(YAkx}KCf$3M3tk!bnLpOT3-L%d!D1@rOQ=r?HLBRF;n) zB!$u{f1fwcW7FD;g}so&!?u-M-yk*q#L!;>u9TcsO4@a{Z$xu0xIsC*7%d)7cKnj| z-d-DN>m}s6;>DfM4P$#eE2~^j(*d2o0OEwz!)Fx>7F2*cVN4n2U&@&nn-spk0V5T*~)#zY-Au9b*od4yay#>!AhKK?fm z4iU5xUn)$D$K}39yskCOJBV;`uML3XO^(!4UQv}vc~af_QLXM5h0ef4@Ci(1o%sHT z^u_fOz{+3MGoy3C;&yvQ%SVCktEJ|d*hInbzb@bYmRLL;Zn&AN;AEmWfa z`|=9-w<@)jY_{C4t&6DgU*Qe{5U)++08ee=?)kkYM^oC`*zOlwiOOH9+%AUS=Z*s* zAKYc`E~*Rvn>&Ss(KxYYY02JUy9(4{g6v&xiY}3cxnd()R~{E2 z4=XBbVdZnV+0*R>->n#Fgu);fUrUQbnbL5#12?&QfNLXR`S}uBTcyim^?n7`2Hte2 zx%*Esg>x^Sji~xh&fQeobeR3MfZj_A31DG#xUyY|NbnD+*5s54Oqj)}qfCAG3={s_ zu{iM)qhNaPxGidO{`G!i+BYcz5VLR)O+dN6z-UM{T8YnhtNy$JN%irQuDORYNs`a5 zGrL0s|8jG;kEP<{18#s-gCG$Pz?)4cSf89Rlir_;Fp9eq>5G5x$J_zjL@m31;Rnii zx1(6fh!Z`UV!DTRSzRPVy!;~U04?qBmpeFa@q)r4N14rIFn+6k>hz-mXFtPunL&>V z3I6lR=itkGu_w1w8EZeWATSS@E_Jm9Uvtc7%?JZ;}I z`Y&MvpS_0vYTBOpjXm%UhJ*2Lvc=_3XLj6E-kyz)Y)GIx(n1$%*Kyk+puYWKF+LL3(a%?4u(wYJ;&0o+xCa%;4l^O z!XJ0-65%Cv(U5a*-f(6iFO=bY=!&sy{w;2l1V@6SJ=8be#(tURHX0+ThycU^9c8? z@OT!!asIXO^s~I+3T^4cdV^f-JN8{m&A3*a`h*GelDxF^>JPtATXF-pRNvcbZ>oW$ z!ZkScjPi$)r6i@JjE&83p{-W05MCe#9D6P*-{g-`DH&WeKO>+>7|78`Ut_E&%Ry941{we1!}MLUO4U&L zcl~Qhm{)CY#W9HI>-$)yckXnX&~ckUZDEa9&&CZE=e1U!v2M6W1#`um4>ke$K2Hzs z$tU>ApY=>VK1dOO=L`?ds0PKsbCjofbdfOYswBH(UbM}X_A8I<4=^6Y6KM~XwYe<> zk-1c=!!5qvJ3HrRLk9YOwk%y{xOkHLcV1j9SZNp<9@g)*2vbfFl5UJdUj7Nh(`?h@ zoCk-P^&DYvXSldEUr#QRPFi!fcjuxrR7#5GadPXW|ErcvZZInBrsAL+GfPT3Wnw=1 z?+e-5#~_G}V$SgaLh2}HrSMqg;N3HRWsI4s*+YLS$URM-ywYrzZ(a`lU&lQ`^cIB1 zgG)}h<+?h)#iJ~kEj@vhou34;Xy*durpmh2_UWK(A2WXLTpE;C0`nc-gVmjq(pA4;mKh2N9J-ZvVGF=cQihJP}y{W>tq zbm=oE_UdXsVybYn@!V%f8hfZWkgeTExZmGR5{~ybOZii;@Jnz{bzrPA4kkaEJztxs zp~BkM*sOiHdiIo?Nwsfb?4L4j89mIm&h65{2T}qD3{(@Kgivkw`wuGt)e9hUB{B7$ z(E?C8`r=m2{ZQw%ld>waV%o4E8=|cd?F;4u%pO(oGJ@hK`fPr96#EaRK2wf*Gp?Jn zeeGO6XR;16UFbR3|m&N4I5nr3sY*o=`p)o~{Wy~J* z^Y4V>+u_TG=beM5VLX;)&gQCan%iAsyXDna*_nge?NFPpq>K?FdU4l7M{h;w+a>x4Csnq>xY`qNZGA4tkWxE%%2Oq81VloEFGx;e@Li#QXj2q? z-LynDxgAD1C*?rnCY<0Ea){*){Y*X`;jJkp}#JBAOcM zvHNZ8$761t=G*z^hL!qIY_v$^5IE|DKcTLh-di&Z0We^Gee1HRY5-FXehJ48CYc;s zomk=n?uuy%L$x%v<_#KU3K$zU!(qN5pJM{wOMhX$sdE8QTjlkF>(OM7tMJv$@mjS` z5Y`GktB9%jC=-9{N`zn;CQp`Kmg1G5fx(chL$Fni^t>GM*sZoG@x3rwH~DO81Lp9v zM2!p1e_;^H-L!Kd&zVJ~^M3z%WQ#%IhP7b8CuYQFcYc-Rb5+;6UU%=|WcsTj$OVwx ziM8pdGIK@es01JX>Ft)M;ylfC;G*YJMqOjHGT%?Da*a$!=OzT2sa9L0|E%a-mJ^(x)?Z!!t}_6v6ru2~RD-d;eS4?KOJWn@`8R zRhR;8XpMn!jl#XeRG54eNtw5!Wy1uwEnQS%6+{6)?@!lr?J8Dv9+Hf`YW;!&?QR0Q_p@6-9Fp< zB|7)!q>kLeZMm_11*RN6!6rfiioS5mVavQM;ssREsT4npQ^q=b&7iT774B$%vq^EP zDs%94pr!y(RvvN(G(kQ!ERWRT>PdD?(+PIa@2N)Dupm@S7lDYDfvjWbZez7t0~;7R0Tuw%Bmsf8hCKU zwDAhhtA@{L?KgA8rNR?Yi+=Owv&AxGo4#VqB=nMy*bJap_UCR7BT9&cz z;kJ$iQ!zbqVtp`OVSt{QR0Z95^3QQLUjS!O)657FERE#Lbx@7qs;$nYzE&S&kiqLDy(C|gId zn_GP${fYw*EkJ0$YS9t{=dqKfYUzc&j&P&w-qN(9#wxRlSoGjIl-8Dm6Yk1 zta9<#;cRz{r2Z543cXyfn*tsA2IS9p-!u0^0!YdGL^(*}=dAud3WKZONFR3kzaRWf zyN%4}r}6#lUc1TPx%Bk~GvkTrX)#^FJ#qq!o=8jM%b9R=xpnF}M6g0M8wZujJ1e$A zKo|B@95lf;)-_vA+xZ-Y&731VQ`V;S7SO`xfFI=M4zj26M&xAD+RG{r(;?>YsrgPx z#+=AePJ8uiGCa~4(dz&`5b z#{pArqEgdyo-e|;p1_^X1_4&&dBfd!o;JD5pZ!19^E9`%6K1VslJ+9yP0*r$Tq;5M zpy5alK%wlLlJDdyD*xL!rB3GL1AYO2bQI`VO-eRba%)!uRE4Oz#i}c<9)+kSXn?kD zM(8J#UOtps)#Q5p!wG>$$z84wZEYw zS+}5-KZIPH@wsO5J>tpA!Lws`e$3VF?ko}}lU>`5^eC>zupLzc4$5Nap%HdkRh+Hh zey+WG)l#^gDZYemBPwzrQt>x?S!+=SZ$!hL?{g|E*2gMfe=I~7l%SPV z={90DhwS-4iiJokz%YA1%YS_O_NNId41M$dT77NtaSx`yli!v-S|H5d1BYg`XXs(^|MQ-C_gil8I_6W} z+=nAPCmWDhItSJvxD%C=V8^&`EYs+USUY9|shF**7s!G&qC*BTj+$>+Ez-2$T)kdUCY`%zssxEG z&N$}l3n?GqP2U54MV^=cS4F}@klKm72|6YVoJRCkVtz{P+B;Cgk&^pU#=eRClJ)62 zLRl!M&5uUcIl9~Jc7pKpBMmhQREWCg>iO#Gtj4WUFFS={3Wi$2oy`QX+KR&i0c&(2&-T;q!xH`3X>`Ag=pd-DS zGQO02_V(`D)w^Zi{^K)JSC^EpoHyAObB>gKFkU2AbSgSA$JR}zp+cqWdd|Pgoz~BQevN@xEth-RT4a!rWIoF7wk*GsX=KS=7lX#B84z zcrpBYOjD&V*Fd)H{Y6>Dz3)n-??yoZ6NQWlc9+%^e>j9SikX;?|LfmDInvv8)l)o| z#@rUU*Pc~X+iAg(N_-|}f)$Fpdd?ebPgg#|wu@LArn0uG%p26VHu8J5_qVuQU99B; z?4wb}tH8Wm1CC{zicPV=41spSo4;uO)apC(v@@{X>Oz7PPARGF;4v32BbD#-?lAX+ z9YOtP*Xa?zt)DGJqpY)8dXz7zc?_JTSO$!2f9?(A3z)8`-TWE%Hh%vs<_h&s;!%%T zlHe#8*KOfH*EWxaSLuHIYYmFF{UID+Sr+5`p~q)khhz%oTY;r&WtqFHaZFhiR4ongc%Kg7gTeRyKal)}{9|G~I}5v| z6&Z#g72encAM@{lG(tE?XFY$&qq==x$6~h;f&`b6VV+*`OJI8qAc<_46nAHIOotYuj@Dj65HOk=|{d?Jf5@5a3)Y}2zP&w^gZA3r_COotwyM~_Ebv+{Muz|2YP&^vMS z+TyysV$ga0r+twp?PtnaXAnRWazMa`g4_ph@w;%{IC8BRw{w8CHL~#ay|=;$Qtgvn zSa#mlVopBaMGpxvN`T9~!!y zzY;Qe_Z_2nP4AcDx+jwdKL*}_)C6*$9AsPv30V3Q#mel2f3QKAXu++6#)j9_d=k-L z+^^t?egzqL7$%P-rY4Z~fMyxHK#ILqojMLI(KrBvj3v5dT~3=L>bcQx_&7R5DF*J% z>7O5Q$gg~K;?xTjT|rhK_xChri1@v3Vquw0ku8olH_M8XhHdma#G3@C}8s7Ugch%H*~IETM|Rih_Q92?GhdATR)6)b zM`&t?mk3>Q+>t>psV^1NVN@6Y=vzVitxL>{^3R=f9V)tVxyHl!*1NmrCTP4Lx;ym{ zknz(e&cxOOT)0Gb;C$1L@ay~OXEfz{z1{8a;bGFT<@%6qVhj1#Sjr}jRUGVozt)fd z#NA04g7@wt$Jl@puI%vciR>EFcu{kSUmVXH5*vlpcwrjxXD#DOh4dTZBq4KiH zlByyjK(?K9l6nzr*MBJY)MO!4`MWLaU82+mxp$(PS`y>mwq;nH_gw|ym9q6J_V--Z zTSTLs=8Oj4oi}gt4u*%jw_Js&Z*cpYvQpN_$Zq2Jh*{__%K_j9!^eh)Df#`J_dfz% zG_6unnb>Jdx`>Ud6^p$&A$1~Dq*0s!ID#@^hvJb3T0`uwM_}6b6_o$=YWy*HvhFx5 zq36e+>mN|T>o;vzJ--kv4O`;psv`VCKVVN5x+#1mgmJQc{?VU;PwOBM^KVtYM z-*HnzQSwgg2n=?(2Ta2-FhtOR#YrTXKT1t_!S*-T;#p;VT140PbVKQ$5zBZ*2C#tm znYzDc)6tiu8TKj*#%#3Zad;(>g<8Mlc4_LD@$MFzCJDUuebVnR13$4y@S+5BVEb>(5!{vT*IwOe-i-RcU?#2rxVl_6U6x z-tysm7WH-hk6yG$MMh5Oy2VgiGkOLbX_YfkJzL#a%#w`Gqtt4OLGhG@tb43F;K1KC zU?ht)4mnCOp8R%wQiC~q5iS{aJp%H$UH;>tw}4ga1};Q-gq}Je?47XhM8&2b)l|#M zPnWgDmLZFOoJSD)yGqy{!1bpiVda8*q65M|yADob zxrfgd7eerY^;FuuF>MGYzRy$0b4h>>)6o+rp_g|#*?Iqh$ob5!xW%qF4yV*TgK|fI zzPgD~j(#g1PM*UjLK})ce&p0*l+dUC50XVg<^cQA!Y9@Gb{G!@Zw+PjHFIM#v>K2j z$X1jQaeA7N5DV@FHQhUXMe?Kh<+iNU-=dw3qM0)(l&|)|WNZ2g&2fIo6Ek)|Esd3v z93B%dAuf$IW=Op4_nBF5*fy!x@F_umAq|${_exSD-^Qd^T)Jea;Z?B0O!?fLw_$IW z9hevKVvi#l7nV|ul2i9y$k)FZuYVj)qO6F7fY^tHD)KgH!FeP@sS1HcX>N9--42vI z*q+o##PSP}pu}jWdE2x#Q#6@j`9rq30>_b3GPyigkj|(VGm|>l7K@%D(zw{umGq;H zpujLjh%PG>6-wA$3qE4e{i+v-P`bE3+3qKU&RzhWdWgqTHr>=w*xz%Wxcjd9m!2jfE}muYbd&HH zA0Pfc!fJ|{Ul&-{G5hr4i4or)KL)P%tY81OrN3tcxgr2l2?AwJD6&58luZ7dW=IM4 z?1CpLgc7oNoH`n~46f+3t727YA%8O&r*%$F4`DM}B(HZTC3q0lz`X-7u+Uc=D;|y| zOBc^0W68dc#ObHE;f<80uL%PqcBH>1KgJz35skQimlG_mHgLl zrXfhUt4kaX3XU`_h$wSSD!X(1G{r!p5H;uCc-WJ=5y;fzD#Y5?#5?CTv2+j0XBZB7jibb z!H82=8H7S=WG-utR)n~G0r zClMHjgDmdayIb0EI5@`l1uzld&$mL2)bb6C z_=`zJfF}v78-T3#de5^LgFk0?QU!0h8wr*ZOZe`A>0PpX(sf|G{>5l~__JMKPU_PC zEFqc(C%o=DudNpGa|iTXn04pck$ZbvZ7nJdR3v<-`d}LNVsNYJpSx`YNdcy?k|&Xu zlI8e@l=Bjx$NfI(@~zNR_;SZIXxfm1#j*Y9(DlBUT?V1CdgO3vQPHv=FbBTGSGt%F z_t;u)_FQ?{6GNq?u#nWZVmzk%muF|aAwhuf0KToB9?qGE>R&%H1 z&=G_R)+}(7b2-nP(YebocbHP?Z=Sf4DShc8sbld6(e4+v!EDW8sw=2R>Vz+_(8i!` zy2MGY72@aSCgNfGi0eeLM)l*^u{FeiBOiO5uS zx%aNclBzh;Q)tbDc7dOUi^HJb31|KNztc4OA)tB-34D&H0xgCEXd=jRzNV^ulPSh z4igqAdf-3P0MCVVl~$Ipk6`dGmcy2Ba0Yq|O^%O}oYi$D?1yO1T+7INnen2MH<~!xA`Gy)B!zcPyRY3Al64O&9jMi zEFcwX7|YvcltgAOt%Rfm!X}2eAEht+C-wZowGH!sFsc23)55G2GUg7}eh56$URrso zP)8b45moax!QIblr`it=4c9s)#xk+$dTwi1>xg=r#^t`1)*A`MbDvoGPhRHiDymtw zM{J^tS8&~qrN$O+p*U|oczI%dk>jk`pgqz1I4NA~4GFIETlKNv?Q-}OtM*Pd@W}bQ zpktkk-BOCb=457sh-(rxsUJ`N(%FtD9zKNBz%X5Q+tv8oS_*x~X&+OqzSQWH?}9%q zH0GC^7n8&4&R5SzM(IOHgwQws>-rVMuH_3m^6>HHU^OpRKi-VWMMW&edW%ag%w5s- z)%(_!!h{u7H(&3y%oEd@*;LFH+(YGFr$L(cw$+LjL7w;EOXommJ@mS{@(9;&Ouz{^ zW=gYv>-54J$p_vdx%X)aaqoi(OLXxGoEN)xwCxCFz3tj(>TbF~Im$=WxX_*Jo zSDFTrH*k|Od=F@8ku%V;$~p@J8{Lu#E#{Kj%7LA$=vdCqBr##9)o28Gjpu=*otY&n z0VAZ6Q|g!0*Gxyp2rb=JWq%tmt!IqO4e{6~kDO*XOTDl5v<0DTdo*2m-)m4TPj}c_ zmp0FXOg??{t*rT*iR){i~iX#6ro0Dq1^ z1nttvcZ)yta9`xz2`NpaJY4Q>+S-3BiP6VfO9{)!G=1sfdQqvk%62@&dq-l2R}1vD{LI7@d$a60IGaVai95Z)x>82ppwy zHYc^Y0-0(jkKJL_ZjE04O|II_s;vGadv}}($$X`vzD4<;m;cmf#atNP-Sn30PGRfJ zaoZDl1=qOPKboEnE9u{z->Sha{P~O`1iZ=JnttlYn^{Uc3&*Zd&xU}!lCV7R2g)T4 zvh^`F2XR*VbcS>vrgn*iQJ9yR`VtGV2dY_t66fu;z0#Ck8f>gSS%^-l;LMHrrx5Ds zjcK?L>S>bK5&f2}<38yjQWX3XS`cZh;@;%U1flyIu3^yD)*>lyRTXM#q)H7Uen%8n zPwvhz*LC43gwD)Z)WyctUuga=5?%&%@4~*E$iVJxb#?Y)I;88?-#fXi<2M50 zYYMa^M)x}}ExFr?1jJd*KYnDBtE8Z~Q0jMQ>l9(+`q_1-l;w9Hwz(>5R*&JzQ;<9u zrHQI*?<$DbgL=T<#mQ&!o+$Yqq!)KA^f1tk;$kwe+ZWCu>+b&tv~vUBOn;7!9`dal z@{L*vF_Bp0%Y(u8KpTbf+Mc;=vI<_cgk#eW$ov!0bsxI_oxKMuc7=0xSrZ@oH%a`) z=(8*Hen(6BpmVwqGWa>R<34YH%U~fixmRmnGZ;{-%vV%xULOct%bu)=_6~EK_w&fhLZ#;J75!NSTd+tCVzPEaM z?Ri{>EeYEwuJj?Mt-hZyX-0pTD8|a^PEHE;1Jlew0E|!$I{GxVO$Nfn~ z3f|AjOmOatx8Q%QPm+bG_-?sBa`1L$qGJtineAF#D%qh3sof-%EPCi56*UtnH+&+D znoU<QG8(JwzBk+>;+$N?v?&=l8oSh*yu)5+w*; zyh%fUb-=M;2j zzC5tT@XVF5gl?8bta9ip9aGb%gnsbpM=LhmA2+y;M_IqptWfJDrZ{0sJKxcfl*zb` zu(?7P5YJaDHZOOG|6^A>q4Dv%m5`XNU6w;#eMx`4akczyaBhlo-2f_Y3(G?wbR33~v~{F46zGM(fMJC_U!Y)JYeSFfMB z>F3;5&}cK{@542&rgUFg<#K-onq+t1@}o6+RG?cXB;-D&d=C4{yPr*E_LVNKasAcU z-Oenpc%WW9$ZS{EO!sJmMgce2)Z7?5itd>yXaf_rPLZ!IUVQxS1mEUd8p=r^7D?E*#E zA}wgd8QFt>$prBfJL@AZnCt>i(B|v`f{3SPq6;{j%Zbl}9!zy#PFlAzF%=lQUPVDt zlc||H*ZAcZz5LOv}3vn`&slwNnUj!DM>IVOv;}rnjMKag1(1mN~PVg1Bn^WqZT0ysyrsFkfdZl38!1Erj}g4 zZ~w7{Zin1RKdsnX{Du7`4T&F(=*5g#DQIgd#MIpK{>M-i}@4I#_%eOQgMjjcs7*c`?&3-_d zQU?Um1kTnkwFHBJ$L|o8<^gC)`h)F}RudvPG?+k`>JCDd)XXI}vLL9X2`oGwy4~Ev z^I#}t6c|4gOyNJzFC4}R^vAUPkve!t-P_v+zuUDK6-BgU^Ua{#)GipGc&mKA$AgJ; zXJ3+>#R?gBsFxC4qiYrP{);0mAfIGpf$2=M_=&lh0q_jC{Ta38vi#aXPMY)|9)rE6 zcpuJm((mAmF^skeu)V9l1l1Hf2HK5RL6od8$84D)cJ6d|_{dEN#;%VWo3LWLhy$~o zQnkhuUgZ?L*3Y~>FLSqrqyXr+l&jjpT3$K?K5{n=0$*(>OB%K})V=`2Ty(3uyZ9pT zb;X3cdBZ0P_fIHqEpJZ&XjxAKKY~6-sXylg>CN{%WC%~z{e4e0_>P9O}WlK^$O>)vna{QRy_FA`8^ zxAy&R>{0oh1a;UQuBhvKb9UNqvYl)mRk&im`}$r49uD_&{!t>!1+j06bv}Wju>IPn z!577sv;ACXv6`+#px&P|gF_hVCDe?a4b_%T=v?Ieq3 z7z~Zlyr<$hP<$`wL`Le1E)pA@?cFeY^};8;xRc&5YU5w);2y@zjAC>($tthBFxmT~ z0a9Z~t3f$k30sI1ek3UO+zkv0JHE?-=tKwbX58M=@#DWdd1RO??CJh4s%g5v`W<~m z@Md)GVcw| zn!&s$BT2Ih&2$#Tx=}_d?R%MTIA=e4ux)2ES(Y~6Z_Rl_rVgZCWp=qVrCDa;N7yVA z14;*DHe*ZinZvi-Ko!&kx8}$RJNGSo;$HV1LKCW%a?0Nj;%Bk zNnm|w%1}KmWzpc+{i5ZU-jb{I7o)7fI23z3dS&;Y3?hoP0U|D;H<^JxI-#rn)!Xy_kocEM z75hKB-*9>Fiv1cPU@uy`D<{=^IRw)W?_M2=pI(V?1gW-Tfk{|Lqbzc17@3Q~jguZk zqCE_;OogZ&^+i74S)=l74iQi-P?agtjJ?e*#?Os7U&y&lFNwu$^onIZ4pNaKr`6AP zqynQ32z4Y8JeDMqvW5}v?cq1OkL1$ui6!$Sd%GODY`paIM%Nr+@=?hZ-<#I+W|gHw z)MHC=sj*pqkol5I2qKY3-9wjO7@VCKIP#>`i!4k_Y)+K)3-#gG#d-a&V!4*3W zbrFtqmVO96$-sO=l~7&xD)Khbp2DUe)-C_&PlJwZ!8p}HzROCL92%;J+rRvmT1(O! zqyAQ2pyU6}e)JYwX~qUXZk4-2P0^Ade;HbPk=?K1HL#O}2O(Qo{TLbL288$&Y&xKU zpBOIq%31$)4`YR z+<^x(F7+KL(8;L^7&fZ7t+DshDF)u!zY3L|I_>7ylFKCkMGS#ykFIR0g2wu*#u)?3{ze|*(1GMdt3HHm48BMzrWl;-%}%}>QB9`xfFxQXKo=bX2l!S(lCI@1>JmI8 zf7q2#(uh&+7mO9Z%RBFrR3i}DOqx4b1M~^1XYd`9I zM1D5ZGE0j>1jsv8b{+u+e^AqFH);e;i>o~*R9=D5*R0}U(gXV*j)5i5sG=X~@BD3- z#nmBSin#BHZBe5$hG@r&Px&-JVVJ)moJ8TDMan9Ewx5oyVcJL1;Y4eO6Ajl0MJOij z>34~xtMurn8zcOyP;h03XbJ5A5G%PkqD0|zxE$CD@skHXH?)ESUUT1W@>*~`^Ojc~ zD`j-zUR?;ODEL&1sSL~~58o&D1B$M=EyNNca6~)({8X?blnKlOpRy@20Cf-;u)T(h zIoM^C%>I|LFrNM-hOL)-uww4~dO4?r?R+Ok9Y z%M_cwwE8|flq1v`<7~D-DBeP_N9#@^6s{PQ4))PIfDf_8u@6w)T?$tz6@I*81R<~8 z#bPlx?YETbm2YOmr+&Je!$}42$yZbRKS%CvfiZX{g>l6WU7as5s3hRiiaCa}IXa+* zp>aXp>o^}hnhsc~cQ}0u4u(LmoY%9I)aLfwY8pQFbl6GsiTI zfBWIR2pL~0;wzpJNN%xJ$Exx*3q^u8jEzV2B%tD=!~gwFoptZLS8>V%r9ct z^TSpd$B>YSuuAr07Q}&GX5Mo;&!<;@2t;P*_ITJM%*dgX7d3-b+Mp*<%z6l#2Zf=MN zYP~V&k<1*zZ0d4*Gs+TrYcazsi1w&xA0rqJok~cb*SwW>W2dt5YOPQZ#hq6rj9#14 z9GRW?Y<+~(bbWG0(+&Wyb)I1D8rS2kK=PDmxS<@)X}z`}8Fab#m;0D$f21-i=Rqf@ zhHb1N0^WtLs>E+B@79sZkqLBnxesxZm=)B(k(3mx0+La2AOEV=0LQRcJ$)6iaQ_G% zhoSMJm4WM*k)FRO{bdU7Pd$Z23sqvE#4(iM5T@*U3nf13S0|Je< zRdP(nJs4IS+VXqX;V0O|a#uj{Kx(CH^nQmJ4`1If2@j$eNP%P%nbI%3ra*{Cu7jw^ zk6UoXSe)hvn<1t)3!8IAxZn}TfC`n@IP-od@jCiCi2vZt=5LzK`g8G zq*cTjugwwCZnAN*v)Pq<@9yHaDzmV0SuDO2Qv__quv|;u52F-# zb4PsMVu*Y-ck{Zk+T$D3O4<2id?+`xrR$Q3j9ds%Mq=FHQ_>CNcs{30Q~Q_ZDloxk z{CM0+T4&i#)ff{seDvu$KGzKflR<%{Le#oF|R>9#~gT_I7?6Y6r# zPMJHqtGw^pFx}|Az2w}ggwx;Tas5~hotW1$8`z(j0cx{qGl5L_FY<~-1AOkoXUik>c5-Tg!8=W$@u<}-DlYx*1ZB$t!c zq^Vm9`PT94Z|zyf3XBQ{x!Vl#a#`-}tX031WeB{r0p4^i+l{(APvEedc7Q@ft2OT3 zM(YRyoay!TuGpM^Rr9Q8;r`uox`aEnH@mx$cHU=TCLkLy!K!=KWunJ!!up~tqW#+w zRex%Mw6&9?Z=hGK_@VfdW+jQ(tESsX6(cWf4?q@t6Q~O}ZJz#Ofr9%@VU(&pgYcvb zpOFND(95dMauPB^g^Tf>oJ$9uYr*(l)kMfqDm2DO0a!If%1p*HvP>xIjDSm<2oC(S zSj`jvJ9&5y>>^v?ischc&byRLHyIUeR{)jSR zeFX+Z}*uPeEIm3CnfcpEgrV6U92>+WN@rNXTg6v3c4*Fw07tpo(DAa=dtX>pJqi{ zgaHzxoxfGxUh;D(#geTgw-^dSRq?ONAjQLKmt?4ruPe-TrgMI_b#=8v=)HoVobBYa z@Mt|9v$O{v66_n16J^i|+`X;9Xi6ZtFWe4aPQkVlo6*@l2fvpUZ?Q&7uL_WG419Nl zr<7gq{R;uswfYU&85~wDltQ7iAV=!aat*7mkSAVv*(PM=t?DG7`>Ves|C~eQIc8>N zRzq0yjdO-0PY!P!{Ih;NZc``zXTl-+;lCHF?jWS~xY-7Wx+}py9#4?K*C6V`qr^S7 zjGJHQDk55dYD=rphY?4J3;lR}BS`>2#)xu+th?eJzqh zC60W`&F?!`GfS_jS4rJ0u8k-8t_GJ!$(DZ>Hh!INNGBF2SY6^!0Wmudogh%t3NAKa z7f2pe_Rq^E!UIrEaIF_@QH_q!WL?!wzm2yBVN!SC2GBN55I0|QOjI5Q=bRaY{`@hj zjA$>r_DmSw+&b1=gI z;o$2(9vBDkt%uS9568jA?+23dQXppgaG7*{@#UUm2#ra#M_@)kuU_^@PODV*W z6W{L?W?&$XN_txRxfE$VTQI?@v>y*)-`Mu?8+YwLV^KB#Qg$Ck7 zp;?KQ*w%0b@*PQD7zNVF#Z?8QjS{7$2+inRHS1K;C3zjuPlC}$h3t|(vfzn4K6ZEF z`MvYbXY_i>5TX^?sDCca6xOTlKHMbZ$4G`UhpafW(+GaqwqUCQ(%N`NFhSMB4I-fE za&k!>Hi=?Xb{Do~TLIkicATW?BB%u+F$~Q1`q{Y--KR&gczJID9w&iA>Exh;nKuqCSWj9gvt;hx2-K91P8v=2-KJM z*6rKbm|(@{Xc3YKLUKDmVlgJ9F-WMY@3Y-0dW9uJ4Vu(i{3Zl4z!x(w0bOo2ExK)) zBaQyCR`z-_+{W>E91i^nVTHypH;=^rNg&6V48qu)xI_Z}9v%g=7p3AavKU#HvJUW^ zW~Ba&gEb5xnhfkj&#S4mm|i>Uq3K*LK#vF13D?|JWN@~LBnbH~C5B~92vX@oHDcC- zdJ&&FA<$iXRBx=nyFi+vvjR-U@QKKHW9Fp znk;;h`;c18N$R~=YB|QOvX{p7v2yY?hebgIsUyz{20;#WMTwY`Xv1C0F{2855Y+{~ z5UOj7Kk8$-=x&%KJrtt{0{!7+*8$<<(X`Ky?L?6_cyq<1q?Wm58AMk!2UyeR@lgy+ z?-%!x=>SKk*g8GC<^?ths7ztE3_9iLql+&s)B}-*Kjl*@Ed1tM1cMYTspNg zErIAy%MfULKHI)N>`t50K`DMF#Y?Hxd<(o`aQuG z;7s*n0t*vkHvJC$#~4k&!^p^+O$3_IXUtLyL>rxgrDDAZ&iUzgCwL$AoE)gi5l{o( z$W8TsJrn#Tk?$vG1O2N7O})a^1jzW^^+AHt+va^n$Y$Z>_b8RDfQ-*f|6|c?xTARr z0CE8UwJ%c%^r72-K&Nx3dOEclM$~m=5;83WHde;v$yuWDZ7>DHsVQ`+`yo{OW~#L+ z+{CP6HQgGne=6`j0Fm!$TZ_Q(cg_5ICzp>Ayyh3kyJ>Fr7vY0XO05{zPCB zZ)y7*wDl}`9$IjF1;%=K&&WJfGuYor(zYBE-j;=ZLOgt+c*9(( znDfv+SDFS1x(<}az_fZslByDd!wM-P0O8$w9u|Gz-EQgkXycW8jP|Im#Ng z09OqSUP*>8&`%(UbW%+hTy3M-<2@jZA5{hIvz!s|&QR8zsAmY@Xc+_P4Gt6hKXJn6 zBSl)SGkE~$^Z|dSgG+??1{fsmY2mtY!DgzBG^Ed#67J|psk_&kh1>0Odp3EFD5}Y$ zGFL(l;msdxR zV(#fK+JF8Ywvu4KG&5KM-vHuLpeAV?dm+9}?AOBxsA^sEul|zB<5cDM%5*uj?K>!C znTeUw2uMV^3067#0pWYG-XwohSq7uN5@jQ0*5auamDorHR9_(RcSu^C z2;vpxf4>8BH0ShjU_k@KK9dwm_TG!g&BLYwzVDcjImoS;?4TkY(ad|OdH9Rz?fVt> zbdLgNIx(FHnm}-DBfa`vCXyOb`@pf85vZ4j@v>S)--;0GB)3A+$yHJ__4=SW3){wMu zm@~4`Sb@|wsPcZ$r`WOA1zBW60sqE_O3-SHKk=6i8+CP7V0R@OCQnhM4M&2FBP`Xk zH2Q<5Up(wZ^U$qn4s{*o?+6zZtk+#ZwQ``mduKoXlpQD2#0Z!Y7|6T#0(=v1+`gfa z3)qhb?7N58ahj#(hQ&_lE2kmAacr|y*u{ChRN_!TI@ajnk@C#wfq~^1YuAaf1qQ^h zXMnbB^S9|Z);zq~04%o}n|QGxfM#*Did|`whd0s&H7Fw&DvOCncm~LvaMUc6tm9=$ zlP$Dy;Jxs~Z=MZt1~qWMPAzs{0+v?LOQ=V=BStY1lgRM`C>ihl`#Io3XJAecT0?{| z!{Y@*%*dq<@ehs>65Ua{6pSV4ctz_h8li_E^aM^d$8UK97+l`u%af;NLGeRv5Xp!@ z8u)k2(%E3U8T>B2f0QoLv}>Fnf)mox8`vw`6KaPy*A9j`iDIyQqAqM3;3@gKcyhbl z1G0EGhmw~oh|P_5Lgvms{TOAR6QP{Im|}>*o*Fy;&}oKUrTc{N4^cL0y5A-8D1LTk z&r06k$S0EKEcQ#D+IMf@iqGu_sBFGC%*TZM;AtCSZh)QeM<$}_TduidR&*tCbaKE} zFyMu=i9sT-IKX{E(?{YR#cY`3rRWWCuy~8cNvV&JLnr?!|Ns1R@)s`}!R_E7q!{9% zsijZ;MdUdkC=-v?OyKIoqaydeZU{3A@enX3pa0Kpv>vWa;TCg_JtGB*&XtUC36SKq qK!e%7d8E}%Ty-}O?J1VvijyJ&suwr?h

{{form1|crispy}} + {{ _("Read Terms of Service and Privacy Policy")}}
diff --git a/templates/crm/leads/lead_tracking.html b/templates/crm/leads/lead_tracking.html index ec68c50b..2fc18128 100644 --- a/templates/crm/leads/lead_tracking.html +++ b/templates/crm/leads/lead_tracking.html @@ -5,14 +5,12 @@ {% block customCSS %} +
+
- #chatbox { - border: 1px solid #ccc; - border-radius: 5px; - padding: 10px; - height: 200px; - overflow-y: scroll; +
+ {% trans 'home' %} + {% trans 'home' %} +
+ + +
+ + + + + + +
+
+ +
+
+ +
+ +
+
+ + + +
+
+ + +
+ + + +
+
+
+
+
+ + + + + + + if (response[recsKey] && response[recsKey].length > 0) { + formattedResponse += '{{ LANGUAGE_CODE }}' === 'ar' ? ' التوصيات\n\n' : ' Recommendations\n\n'; + response[recsKey].forEach(rec => { + formattedResponse += `- ${rec}\n`; + }); + } + + return formattedResponse || '{{ LANGUAGE_CODE }}' === 'ar' ? 'تم تحليل البيانات بنجاح.' : 'Data analyzed successfully.'; + } + + // Initialize + scrollToBottom(); + }); + messageInput.addEventListener('input', function() { + const currentLength = this.value.length; + charCount.textContent = currentLength; + + // Optional: Add warning when approaching limit + if (currentLength > 350) { + charCount.style.color = 'red'; + } else { + charCount.style.color = 'inherit'; + } + }); + +{% endblock %} + +{% block customJS %} + +{% endblock %} + + + + + + + + + + + -
-{% endblock content %} diff --git a/templates/header.html b/templates/header.html index 82f80f6a..498d15f0 100644 --- a/templates/header.html +++ b/templates/header.html @@ -268,6 +268,7 @@ {% trans 'Reports' %} + {% if request.user.dealer.entity %} {% if perms.django_ledger.view_accountmodel %}
{% endif %} + {% endif %} {% endif %} diff --git a/templates/terms_and_privacy.html b/templates/terms_and_privacy.html new file mode 100644 index 00000000..09177017 --- /dev/null +++ b/templates/terms_and_privacy.html @@ -0,0 +1,271 @@ +{% extends 'base.html' %} +{% load static i18n %} + +{% block title %}{{ _("Terms of use and privacy policy")}}{% endblock title %} +{% block content %} + + +
+
+
+ +

Date: 1/1/2025

+
+

Terms of Service

+

Welcome to Haikal, an advanced car inventory management platform owned and operated by Tenhal Information Technology Company ("we", "our", "us"). By accessing or using the Haikal system ("the Service"), you agree to be legally bound by the terms outlined below.

+

1. Acceptance of Terms

+

By using the Service, you confirm that you are authorized to act on behalf of a business entity, agree to these Terms of Service, and comply with all applicable laws and regulations.

+ +

2. Description of Service

+

Haikal provides car dealers and authorized users with tools for managing car inventory, sales, branches, financial transactions, and analytics. Additional services may include integration with government systems, API access, and reporting modules.

+ +

3. Account Registration & Security

+
    +
  • You must register and maintain a secure account with accurate information.
  • +
  • You are solely responsible for any activity under your account.
  • +
  • You must notify us immediately if you suspect unauthorized access or breach of your account.
  • +
+ +

4. License and Restrictions

+
    +
  • We grant you a non-exclusive, non-transferable, revocable license to use the Service in accordance with these terms.
  • +
  • You may not copy, modify, distribute, resell, reverse-engineer, or decompile any part of the Service.
  • +
+ +

5. User Obligations

+
    +
  • You agree not to upload illegal, harmful, or offensive data to the system.
  • +
  • You are responsible for maintaining compliance with data privacy regulations when inputting customer data.
  • +
  • You must not attempt to access systems or data not explicitly made available to you.
  • +
+ +

6. Intellectual Property

+

All content, software, user interface designs, databases, and trademarks within Haikal are the intellectual property of Tenhal Information Technology Company and are protected under local and international IP laws.

+ +

7. Service Availability & Modifications

+
    +
  • We aim to provide 99.9% uptime but do not guarantee uninterrupted access.
  • +
  • We may modify or discontinue parts of the service at any time with or without notice.
  • +
+ +

8. Third-Party Integrations

+

We may integrate with external services such as VIN databases, payment processors, or government systems. Use of those services is subject to their own terms and privacy policies.

+ +

9. Limitation of Liability

+

To the fullest extent permitted by law, Tenhal is not liable for indirect, incidental, punitive, or consequential damages resulting from your use of the Service. Our total liability is limited to the amount you paid us in the last 12 months.

+ +

10. Termination

+

We may suspend or terminate your access if you violate these terms. Upon termination, your access to the Service and associated data may be revoked or deleted.

+ +

11. Governing Law

+

These terms are governed by the laws of the Kingdom of Saudi Arabia. Any disputes will be resolved exclusively in courts located in Riyadh.

+
+ +
+ +
+

Privacy Policy

+ +

We value your privacy and are committed to protecting your personal and business data. This Privacy Policy explains how we collect, use, and protect your information when you use Haikal.

+ +

1. Information We Collect

+
    +
  • Account Information: Name, email, phone number, user role, and login credentials.
  • +
  • Business Data: Inventory details, financial transactions, customer and supplier records.
  • +
  • Technical Data: IP addresses, browser types, login timestamps, session logs, device identifiers.
  • +
+ +

2. How We Use Your Information

+
    +
  • To operate and improve the Service.
  • +
  • To secure accounts and prevent misuse or fraud.
  • +
  • To provide customer support and respond to inquiries.
  • +
  • To comply with legal obligations and cooperate with regulators when required.
  • +
+ +

3. Data Sharing

+
    +
  • We do not sell your information to third parties.
  • +
  • We may share data with trusted processors (e.g., hosting, support tools) under strict confidentiality terms.
  • +
  • We may disclose data to authorities when legally required.
  • +
+ +

4. Data Storage and Security

+
    +
  • Your data is stored securely on encrypted servers with access control policies in place.
  • +
  • We apply firewalls, intrusion detection, and regular audits to safeguard information.
  • +
+ +

5. Your Rights

+
    +
  • You have the right to access, correct, or request deletion of your data.
  • +
  • You may contact us to object to processing or request data portability.
  • +
+ +

6. Data Retention

+

We retain data as long as necessary to provide the service, comply with legal obligations, or enforce agreements. Upon request, we may anonymize or delete your data.

+ +

7. Cookies and Tracking

+

We may use cookies to enhance your experience. These may include session cookies, authentication tokens, and analytics tools.

+ +

8. International Data Transfers

+

If data is processed outside of Saudi Arabia, we ensure adequate protection via agreements and security standards aligned with applicable laws.

+ +

9. Changes to this Policy

+

We may revise this Privacy Policy from time to time. Updates will be posted here with a revised effective date.

+
+ + + +
+
+

التاريخ: ١/١/٢٠٢٥

+ +
+

شروط الخدمة

+

مرحبًا بك في هيكل، منصة متقدمة لإدارة مخزون السيارات، مملوكة وتديرها شركة تنحل لتقنية المعلومات ("نحن"، "خاصتنا"). باستخدامك لنظام هيكل، فإنك توافق على الالتزام القانوني بالشروط التالية:

+ +

١. قبول الشروط

+

باستخدامك للخدمة، فإنك تؤكد أنك مفوض بالتصرف نيابة عن كيان تجاري، وتوافق على شروط الخدمة هذه، وتلتزم بجميع القوانين والأنظمة المعمول بها.

+ +

٢. وصف الخدمة

+

يوفر هيكل أدوات لتجار السيارات والمستخدمين المخولين لإدارة المخزون، المبيعات، الفروع، المعاملات المالية، والتحليلات. تشمل الخدمات الإضافية تكاملات مع أنظمة حكومية، وصول API، وتقارير.

+ +

٣. التسجيل والحماية

+
    +
  • يجب تسجيل حساب دقيق وآمن.
  • +
  • أنت مسؤول عن كل نشاط يتم عبر حسابك.
  • +
  • يجب إبلاغنا فورًا عند الاشتباه في اختراق الحساب.
  • +
+ +

٤. الترخيص والقيود

+
    +
  • نمنحك ترخيصًا غير حصري وقابل للإلغاء لاستخدام الخدمة.
  • +
  • لا يحق لك نسخ، تعديل، توزيع، أو عكس هندسة أي جزء من الخدمة.
  • +
+ +

٥. التزامات المستخدم

+
    +
  • عدم تحميل بيانات غير قانونية أو ضارة.
  • +
  • أنت مسؤول عن الامتثال لقوانين خصوصية البيانات.
  • +
  • لا تحاول الوصول لبيانات أو أنظمة غير مصرّح بها.
  • +
+ +

٦. الملكية الفكرية

+

جميع المحتويات، البرمجيات، قواعد البيانات، والتصاميم تخص تنحل وتخضع للقوانين المحلية والدولية.

+ +

٧. توفر الخدمة والتعديلات

+
    +
  • نهدف لتوفير الخدمة بنسبة تشغيل 99.9٪ ولكن لا نضمن عدم الانقطاع.
  • +
  • قد نقوم بتحديث أو تعديل أو إيقاف الخدمة في أي وقت.
  • +
+ +

٨. تكامل الأطراف الخارجية

+

قد نتكامل مع خدمات خارجية مثل قواعد بيانات VIN، ومعالجات الدفع، والأنظمة الحكومية. يخضع استخدام هذه الخدمات لشروطها الخاصة.

+ +

٩. حدود المسؤولية

+

أقصى مسؤولية لنا عن أي ضرر غير مباشر أو عرضي تقتصر على ما دفعته خلال الـ 12 شهرًا الماضية.

+ +

١٠. الإنهاء

+

يجوز لنا إنهاء أو تعليق حسابك إذا انتهكت هذه الشروط. وقد يتم حذف بياناتك بعد الإنهاء.

+ +

١١. القانون الحاكم

+

تخضع هذه الشروط لقوانين المملكة العربية السعودية، ويكون الاختصاص القضائي لمحاكم الرياض فقط.

+
+ +
+ +
+

سياسة الخصوصية

+ +

نحن نهتم بخصوصيتك وملتزمون بحماية بياناتك الشخصية والتجارية. توضح هذه السياسة كيفية جمع واستخدام وحماية بياناتك عند استخدام نظام هيكل.

+ +

١. المعلومات التي نجمعها

+
    +
  • بيانات الحساب: الاسم، البريد الإلكتروني، الهاتف، الدور، بيانات تسجيل الدخول.
  • +
  • بيانات الأعمال: تفاصيل السيارات، المعاملات المالية، سجلات العملاء والموردين.
  • +
  • بيانات تقنية: عناوين IP، أنواع المتصفحات، أوقات الدخول، سجلات الجلسات، معرفات الأجهزة.
  • +
+ +

٢. استخدام البيانات

+
    +
  • لتشغيل الخدمة وتحسينها.
  • +
  • لحماية الحسابات ومنع الاحتيال.
  • +
  • لدعم العملاء والاستجابة للاستفسارات.
  • +
  • للالتزام بالقوانين والتعاون مع الجهات التنظيمية.
  • +
+ +

٣. مشاركة البيانات

+
    +
  • لا نبيع بياناتك لأي طرف ثالث.
  • +
  • قد نشارك البيانات مع مزودين موثوقين بموجب اتفاقيات سرية.
  • +
  • قد نكشف عن البيانات للجهات المختصة عند الطلب القانوني.
  • +
+ +

٤. التخزين والحماية

+
    +
  • تُخزن البيانات على خوادم مشفرة مع سياسات وصول صارمة.
  • +
  • نطبق جدران حماية، واكتشاف التسلل، ومراجعات دورية.
  • +
+ +

٥. حقوقك

+
    +
  • لك الحق في الوصول إلى بياناتك أو تعديلها أو طلب حذفها.
  • +
  • يمكنك الاعتراض على المعالجة أو طلب نقل البيانات.
  • +
+ +

٦. الاحتفاظ بالبيانات

+

نحتفظ بالبيانات طالما كانت ضرورية لتقديم الخدمة أو للامتثال للأنظمة. يمكننا إزالتها أو إخفاؤها حسب الطلب.

+ +

٧. الكوكيز والتتبع

+

قد نستخدم الكوكيز لتحسين تجربتك، بما في ذلك جلسات التوثيق والتحليلات.

+ +

٨. نقل البيانات خارجياً

+

إذا تم نقل البيانات خارج السعودية، نضمن حمايتها وفق اتفاقيات ومعايير قانونية مناسبة.

+ +

٩. التحديثات

+

قد نُجري تغييرات على هذه السياسة، وسيتم نشر التعديلات مع تاريخ سريان جديد.

+
+ +
+
+
+
+
+

Contact Information

+

If you have any questions or concerns about these Terms or Privacy practices, please contact us:

+

+ Tenhal Information Technology Company
+ Riyadh, Saudi Arabia
+ 📧 info@tenhal.sa
+ 🌐 www.tenhal.sa +

+
+
+
+
+

معلومات التواصل

+

لأي استفسار حول هذه الشروط أو سياسة الخصوصية، يرجى التواصل معنا:

+

+ شركة تنحل لتقنية المعلومات
+ الرياض، المملكة العربية السعودية
+ 📧 info@tenhal.sa
+ 🌐 tenhal.sa +

+
+
+
+
+ + + + + +{% endblock content %} \ No newline at end of file diff --git a/test.txt b/test.txt index 83f97a67..fe076804 100644 --- a/test.txt +++ b/test.txt @@ -250,3 +250,36 @@ send_mail( "OPC minivan 5-doors": "ميني فان OPC 5 أبواب", "Hardtop 2-doors": "Hardtop 2 أبواب", "JP-spec Sedan 4-doors": "جي بي مواصفات سيدان 4 أبواب", + + + +python manage.py dumpdata inventory.CarMake --indent 4 > carmake.json +python manage.py dumpdata inventory.CarModel --indent 4 > carmodel.json +python manage.py dumpdata inventory.CarSerie --indent 4 > carserie.json +python manage.py dumpdata inventory.CarTrim --indent 4 > cartrim.json +python manage.py dumpdata inventory.CarEquipment --indent 4 > carequipment.json +python manage.py dumpdata inventory.CarSpecification --indent 4 > carspecification.json +python manage.py dumpdata inventory.CarSpecificationValue --indent 4 > carspecificationvalue.json +python manage.py dumpdata inventory.CarOption --indent 4 > caroption.json +python manage.py dumpdata inventory.CarOptionValue --indent 4 > caroptionvalue.json +python manage.py dumpdata plans.Plan --indent 4 > plan.json +python manage.py dumpdata plans.Pricing --indent 4 > pricing.json +python manage.py dumpdata plans.PlanPricing --indent 4 > planpricing.json +python manage.py dumpdata plans.Quota --indent 4 > quota.json +python manage.py dumpdata plans.PlanQuota --indent 4 > planquota.json + + +python manage.py loaddata carmake.json +python manage.py loaddata carmodel.json +python manage.py loaddata carserie.json +python manage.py loaddata cartrim.json +python manage.py loaddata carequipment.json +python manage.py loaddata carspecification.json +python manage.py loaddata carspecificationvalue.json +python manage.py loaddata caroption.json +python manage.py loaddata caroptionvalue.json +python manage.py loaddata plan.json +python manage.py loaddata pricing.json +python manage.py loaddata planpricing.json +python manage.py loaddata quota.json +python manage.py loaddata planquota.json diff --git a/test_ollama.py b/test_ollama.py new file mode 100644 index 00000000..c1cd8e01 --- /dev/null +++ b/test_ollama.py @@ -0,0 +1,194 @@ +import os +import django + + +os.environ.setdefault("DJANGO_SETTINGS_MODULE", "car_inventory.settings") +django.setup() + +from django.test import TestCase, RequestFactory +from django.contrib.auth.models import User +from django.http import JsonResponse +import json + +from unittest.mock import patch, MagicMock +from haikalbot.views import ModelAnalystView +from haikalbot.models import AnalysisCache + + + + + +class ModelAnalystViewTest(TestCase): + def setUp(self): + self.factory = RequestFactory() + self.user = User.objects.create_user( + username='testuser', email='test@example.com', password='testpass' + ) + self.superuser = User.objects.create_superuser( + username='admin', email='admin@example.com', password='adminpass' + ) + self.view = ModelAnalystView() + + def test_post_without_prompt(self): + """Test that the view returns an error when no prompt is provided.""" + request = self.factory.post( + '/analyze/', + data=json.dumps({}), + content_type='application/json' + ) + request.user = self.user + + response = self.view.post(request) + + self.assertEqual(response.status_code, 400) + content = json.loads(response.content) + self.assertEqual(content['status'], 'error') + self.assertEqual(content['message'], 'Prompt is required') + + def test_post_with_invalid_json(self): + """Test that the view handles invalid JSON properly.""" + request = self.factory.post( + '/analyze/', + data='invalid json', + content_type='application/json' + ) + request.user = self.user + + response = self.view.post(request) + + self.assertEqual(response.status_code, 400) + content = json.loads(response.content) + self.assertEqual(content['status'], 'error') + self.assertEqual(content['message'], 'Invalid JSON in request body') + + @patch('ai_analyst.views.ModelAnalystView._process_prompt') + @patch('ai_analyst.views.ModelAnalystView._check_permissions') + @patch('ai_analyst.views.ModelAnalystView._generate_hash') + @patch('ai_analyst.views.ModelAnalystView._get_cached_result') + @patch('ai_analyst.views.ModelAnalystView._cache_result') + def test_post_with_valid_prompt(self, mock_cache_result, mock_get_cached, + mock_generate_hash, mock_check_permissions, + mock_process_prompt): + """Test that the view processes a valid prompt correctly.""" + # Setup mocks + mock_check_permissions.return_value = True + mock_generate_hash.return_value = 'test_hash' + mock_get_cached.return_value = None + mock_process_prompt.return_value = { + 'status': 'success', + 'insights': [{'type': 'test_insight'}] + } + + # Create request + request = self.factory.post( + '/analyze/', + data=json.dumps({'prompt': 'How many cars do we have?', 'dealer_id': 1}), + content_type='application/json' + ) + request.user = self.user + + # Call view + response = self.view.post(request) + + # Assertions + self.assertEqual(response.status_code, 200) + content = json.loads(response.content) + self.assertEqual(content['status'], 'success') + self.assertEqual(len(content['insights']), 1) + + # Verify function calls + mock_check_permissions.assert_called_once_with(self.user, 1) + mock_generate_hash.assert_called_once_with('How many cars do we have?', 1) + mock_get_cached.assert_called_once_with('test_hash', self.user, 1) + mock_process_prompt.assert_called_once_with('How many cars do we have?', self.user, 1) + mock_cache_result.assert_called_once() + + @patch('ai_analyst.views.ModelAnalystView._get_cached_result') + @patch('ai_analyst.views.ModelAnalystView._check_permissions') + @patch('ai_analyst.views.ModelAnalystView._generate_hash') + def test_post_with_cached_result(self, mock_generate_hash, mock_check_permissions, mock_get_cached): + """Test that the view returns cached results when available.""" + # Setup mocks + mock_check_permissions.return_value = True + mock_generate_hash.return_value = 'test_hash' + mock_get_cached.return_value = { + 'status': 'success', + 'insights': [{'type': 'cached_insight'}], + 'cached': True + } + + # Create request + request = self.factory.post( + '/analyze/', + data=json.dumps({'prompt': 'How many cars do we have?', 'dealer_id': 1}), + content_type='application/json' + ) + request.user = self.user + + # Call view + response = self.view.post(request) + + # Assertions + self.assertEqual(response.status_code, 200) + content = json.loads(response.content) + self.assertEqual(content['status'], 'success') + self.assertEqual(content['cached'], True) + + # Verify function calls + mock_check_permissions.assert_called_once_with(self.user, 1) + mock_generate_hash.assert_called_once_with('How many cars do we have?', 1) + mock_get_cached.assert_called_once_with('test_hash', self.user, 1) + + def test_check_permissions_superuser(self): + """Test that superusers have permission to access any dealer data.""" + result = self.view._check_permissions(self.superuser, 1) + self.assertTrue(result) + + result = self.view._check_permissions(self.superuser, None) + self.assertTrue(result) + + def test_analyze_prompt_count(self): + """Test that the prompt analyzer correctly identifies count queries.""" + analysis_type, target_models, query_params = self.view._analyze_prompt("How many cars do we have?") + self.assertEqual(analysis_type, 'count') + self.assertEqual(target_models, ['Car']) + self.assertEqual(query_params, {}) + + analysis_type, target_models, query_params = self.view._analyze_prompt( + "Count the number of users with active status") + self.assertEqual(analysis_type, 'count') + self.assertEqual(target_models, ['User']) + self.assertTrue('active' in query_params or 'status' in query_params) + + def test_analyze_prompt_relationship(self): + """Test that the prompt analyzer correctly identifies relationship queries.""" + analysis_type, target_models, query_params = self.view._analyze_prompt( + "Show relationship between User and Profile") + self.assertEqual(analysis_type, 'relationship') + self.assertTrue('User' in target_models and 'Profile' in target_models) + + analysis_type, target_models, query_params = self.view._analyze_prompt( + "What is the User to Order relationship?") + self.assertEqual(analysis_type, 'relationship') + self.assertTrue('User' in target_models and 'Order' in target_models) + + def test_analyze_prompt_statistics(self): + """Test that the prompt analyzer correctly identifies statistics queries.""" + analysis_type, target_models, query_params = self.view._analyze_prompt("What is the average price of cars?") + self.assertEqual(analysis_type, 'statistics') + self.assertEqual(target_models, ['Car']) + self.assertEqual(query_params['field'], 'price') + self.assertEqual(query_params['operation'], 'average') + + analysis_type, target_models, query_params = self.view._analyze_prompt("Show maximum age of users") + self.assertEqual(analysis_type, 'statistics') + self.assertEqual(target_models, ['User']) + self.assertEqual(query_params['field'], 'age') + self.assertEqual(query_params['operation'], 'maximum') + + def test_normalize_model_name(self): + """Test that model names are correctly normalized.""" + self.assertEqual(self.view._normalize_model_name('users'), 'User') + self.assertEqual(self.view._normalize_model_name('car'), 'Car') + self.assertEqual(self.view._normalize_model_name('orderItems'), + 'OrderItem') # This would actually need more logic to handle camelCase