""" خدمة التسعير غير المتزن """ import pandas as pd import numpy as np from datetime import datetime import os import config class UnbalancedPricing: """خدمة التسعير غير المتزن للبنود""" def __init__(self): """تهيئة خدمة التسعير غير المتزن""" self.strategies = { 'front_loading': self.apply_front_loading, 'back_loading': self.apply_back_loading, 'confirmed_items': self.apply_confirmed_items_loading, 'variable_items': self.apply_variable_items_discount } def apply_strategy(self, items_df, strategy, params=None): """تطبيق استراتيجية تسعير غير متزن على البنود""" # نسخة من البيانات المدخلة للعمل عليها df = items_df.copy() # إضافة عمود إستراتيجية التسعير إذا لم يكن موجوداً if 'إستراتيجية التسعير' not in df.columns: df['إستراتيجية التسعير'] = 'متوازن' # تطبيق الإستراتيجية المطلوبة if strategy in self.strategies: df = self.strategies[strategy](df, params) else: # إذا كانت الإستراتيجية غير معروفة، أعد البيانات بدون تغيير pass # حساب الإجمالي بعد التعديل df['الإجمالي'] = df['الكمية'] * df['سعر الوحدة'] return df def apply_front_loading(self, items_df, params=None): """تطبيق استراتيجية التحميل الأمامي (Front Loading)""" df = items_df.copy() # استخراج المعلمات الافتراضية إذا لم يتم تحديدها if params is None: params = { 'early_increase': 1.3, # زيادة 30% للبنود المبكرة 'late_decrease': 0.7, # تخفيض 30% للبنود المتأخرة 'early_percentage': 0.33, # نسبة البنود المبكرة 33% 'late_percentage': 0.33 # نسبة البنود المتأخرة 33% } # تحديد البنود المبكرة والمتأخرة والمتوسطة items_count = len(df) early_count = int(items_count * params['early_percentage']) late_count = int(items_count * params['late_percentage']) early_items = df.iloc[:early_count].index middle_items = df.iloc[early_count:items_count-late_count].index late_items = df.iloc[items_count-late_count:].index # تطبيق الزيادة والنقصان for idx in early_items: df.at[idx, 'سعر الوحدة'] = df.at[idx, 'سعر الوحدة'] * params['early_increase'] df.at[idx, 'إستراتيجية التسعير'] = 'زيادة' for idx in middle_items: df.at[idx, 'إستراتيجية التسعير'] = 'متوازن' for idx in late_items: df.at[idx, 'سعر الوحدة'] = df.at[idx, 'سعر الوحدة'] * params['late_decrease'] df.at[idx, 'إستراتيجية التسعير'] = 'نقص' return df def apply_back_loading(self, items_df, params=None): """تطبيق استراتيجية التحميل الخلفي (Back Loading)""" df = items_df.copy() # استخراج المعلمات الافتراضية إذا لم يتم تحديدها if params is None: params = { 'early_decrease': 0.7, # تخفيض 30% للبنود المبكرة 'late_increase': 1.3, # زيادة 30% للبنود المتأخرة 'early_percentage': 0.33, # نسبة البنود المبكرة 33% 'late_percentage': 0.33 # نسبة البنود المتأخرة 33% } # تحديد البنود المبكرة والمتأخرة والمتوسطة items_count = len(df) early_count = int(items_count * params['early_percentage']) late_count = int(items_count * params['late_percentage']) early_items = df.iloc[:early_count].index middle_items = df.iloc[early_count:items_count-late_count].index late_items = df.iloc[items_count-late_count:].index # تطبيق الزيادة والنقصان for idx in early_items: df.at[idx, 'سعر الوحدة'] = df.at[idx, 'سعر الوحدة'] * params['early_decrease'] df.at[idx, 'إستراتيجية التسعير'] = 'نقص' for idx in middle_items: df.at[idx, 'إستراتيجية التسعير'] = 'متوازن' for idx in late_items: df.at[idx, 'سعر الوحدة'] = df.at[idx, 'سعر الوحدة'] * params['late_increase'] df.at[idx, 'إستراتيجية التسعير'] = 'زيادة' return df def apply_confirmed_items_loading(self, items_df, params=None): """تطبيق استراتيجية تحميل البنود المؤكدة""" df = items_df.copy() # استخراج المعلمات الافتراضية إذا لم يتم تحديدها if params is None: params = { 'confirmed_increase': 1.25, # زيادة 25% للبنود المؤكدة 'others_decrease': 0.85, # تخفيض 15% للبنود الأخرى 'confirmed_items_indices': [] # قائمة مؤشرات البنود المؤكدة } # إذا لم يتم تحديد البنود المؤكدة، استخدم قواعد اختيار افتراضية if not params['confirmed_items_indices']: # البنود التي تحتوي على كلمات مثل "أساسات" أو "هيكل" عادة ما تكون مؤكدة confirmed_items = [] for idx, row in df.iterrows(): description = row['وصف البند'].lower() if any(term in description for term in ['أساس', 'خرسان', 'هيكل', 'إنشائي']): confirmed_items.append(idx) else: confirmed_items = params['confirmed_items_indices'] # تحديد البنود غير المؤكدة all_indices = set(range(len(df))) confirmed_indices = set(confirmed_items) variable_indices = list(all_indices - confirmed_indices) # تطبيق الزيادة والنقصان for idx in confirmed_items: df.at[idx, 'سعر الوحدة'] = df.at[idx, 'سعر الوحدة'] * params['confirmed_increase'] df.at[idx, 'إستراتيجية التسعير'] = 'زيادة' for idx in variable_indices: df.at[idx, 'سعر الوحدة'] = df.at[idx, 'سعر الوحدة'] * params['others_decrease'] df.at[idx, 'إستراتيجية التسعير'] = 'نقص' return df def apply_variable_items_discount(self, items_df, params=None): """تطبيق استراتيجية تخفيض البنود المحتمل زيادتها""" df = items_df.copy() # استخراج المعلمات الافتراضية إذا لم يتم تحديدها if params is None: params = { 'variable_decrease': 0.7, # تخفيض 30% للبنود المحتمل زيادتها 'others_increase': 1.15, # زيادة 15% للبنود الأخرى 'variable_items_indices': [] # قائمة مؤشرات البنود المحتمل زيادتها } # إذا لم يتم تحديد البنود المحتمل زيادتها، استخدم قواعد اختيار افتراضية if not params['variable_items_indices']: # البنود التي تحتوي على كلمات مثل "حفر" أو "ردم" عادة ما تكون محتمل زيادتها variable_items = [] for idx, row in df.iterrows(): description = row['وصف البند'].lower() if any(term in description for term in ['حفر', 'ردم', 'تمديد', 'صرف', 'مياه']): variable_items.append(idx) else: variable_items = params['variable_items_indices'] # تحديد البنود الأخرى all_indices = set(range(len(df))) variable_indices = set(variable_items) other_indices = list(all_indices - variable_indices) # تطبيق الزيادة والنقصان for idx in variable_items: df.at[idx, 'سعر الوحدة'] = df.at[idx, 'سعر الوحدة'] * params['variable_decrease'] df.at[idx, 'إستراتيجية التسعير'] = 'نقص' for idx in other_indices: df.at[idx, 'سعر الوحدة'] = df.at[idx, 'سعر الوحدة'] * params['others_increase'] df.at[idx, 'إستراتيجية التسعير'] = 'زيادة' return df def calibrate_prices(self, original_df, unbalanced_df): """معايرة الأسعار للحفاظ على إجمالي التسعير الأصلي""" # حساب الإجماليات original_total = original_df['الإجمالي'].sum() unbalanced_total = unbalanced_df['الإجمالي'].sum() # نسخة من البيانات المدخلة للعمل عليها df = unbalanced_df.copy() # حساب معامل التعديل adjustment_factor = original_total / unbalanced_total if unbalanced_total > 0 else 1.0 # تعديل الأسعار df['سعر الوحدة'] = df['سعر الوحدة'] * adjustment_factor # حساب الإجمالي بعد التعديل df['الإجمالي'] = df['الكمية'] * df['سعر الوحدة'] return df