
    !+i:                         d Z ddlZddlmZmZ ddlmZmZmZ ddlm	Z	 ddl
mZ  ej                  e      Z G d d      Zy)	z
Dynamic Multiplier Service
Loads ALL multipliers from MultiplierConfig table and applies them dynamically.
No hardcoded factors - everything comes from database.
    N)datetimedate)DictOptionalList)Session)Decimalc            	           e Zd ZdZdefdZdeeeeef   f   fdZ	ddedededefd	Z
d
ededeeef   fdZdeeef   fdZdeeef   fdZdedefdZdee   fdZdeeef   defdZy)DynamicMultipliersz
    Loads and applies ALL multipliers from the database.
    This replaces hardcoded constants with database-driven values.
    
    When new multipliers are added to MultiplierConfig, they are
    automatically included in calculations.
    dbc                 <    || _         i | _        d | _        d| _        y )Ni,  )r   _cache_cache_time
_cache_ttl)selfr   s     W/var/www/hypershopcomercio.com.br/hyper-ai/app/services/forecast/multipliers/dynamic.py__init__zDynamicMultipliers.__init__   s        returnc                    ddl m} t        j                         }| j                  r>| j
                  r2|| j
                  z
  j                  | j                  k  r| j                  S | j                  j                  |      j                         }i }|D ]<  }|j                  }||vri ||<   t        |j                        ||   |j                  <   > || _        || _        t        j!                  dt#        |       dt#        |       d       |S )zt
        Load all multipliers from database, grouped by type.
        Returns: { "type": { "key": value } }
        r   )MultiplierConfigz[MULTIPLIERS] Loaded z multipliers from z types)app.models.forecast_learningr   r   nowr   r   secondsr   r   queryalltipofloatvalorchaveloggerdebuglen)r   r   r   all_configsgroupedconfigr   s          r   _load_all_multipliersz(DynamicMultipliers._load_all_multipliers   s    
 	Blln;;4++t7G7G1G0P0PSWSbSb0b;;ggmm$4599;! 	>F;;D7" "*/*=GDM&,,'		> ,S-=,>>PQTU\Q]P^^defr   r   r    defaultc                 f    | j                         }|j                  |i       j                  ||      S )z Get a specific multiplier value.)r'   get)r   r   r    r(   	all_multss        r   get_multiplierz!DynamicMultipliers.get_multiplier9   s.    ..0	}}T2&**5'::r   target_datetarget_hourc                    | j                         }i }i | _        g d}|j                         }||   }|j                  di       j                  |d      |d<   || j                  d<   |j                  }|dk  rd}	n
|dk  rd}	nd}	|j                  d	i       j                  |	d      |d	<   |	| j                  d	<   |j                  }|d
z
  dz  d
z   }
d|
 }|j                  di       j                  |d      |d<   || j                  d<   |dv r@t        |      }|j                  di       j                  |d      |d<   || j                  d<   nd|d<   d| j                  d<   |dd}|j                  di       j                  |d      |d<   || j                  d<   |dv r(d}|j                  di       j                  |d      |d<   n'd}|j                  di       j                  |d      |d<   || j                  d<   |dv r7d}|j                  di       j                  |d      |d<   || j                  d<   nd|d<   d| j                  d<   |j                  }|dv r(d}|j                  di       j                  |d      |d<   n3|d v r(d!}|j                  di       j                  |d      |d<   nd"}d|d<   || j                  d<   |j                  d#      }|j                  d$i       j                  |d      |d$<   |d$   dk7  r|nd| j                  d$<   d%d&lm	} | |d
'      z
  j                  d#      }||j                  d$i       v r5|j                  d(i       j                  dd      |d(<   d| j                  d(<   nd|d(<   d)| j                  d(<   	 d%d*l
m}  |       }|r|nd|d+<   |d+   d,| j                  d+<   t        j                  d-|d+   d,       |j                  d1i       j                  d2d      |d1<   d2| j                  d1<   |S # t        $ r6}t        j                  d.|        d|d+<   d/| j                  d+<   Y d0}~pd0}~ww xY w)3a*  
        Get ALL global multipliers that apply to the given date/hour.
        These are factors that affect ALL products equally.
        
        Returns dict with all applicable multipliers and their values.
        Also populates self.factor_metadata with categorical keys for logging.
        )segundatercaquartaquintasextasabadodomingoday_of_week      ?
   inicio   meiofimperiod_of_month      semana_week_of_month)   r9      r;      payment_day333333?off02dhhourly_pattern)
   r@                  r;         peakmobile_hoursoff_peak)rN   rO   rQ   r;   rR   rS      activeimpulse_hoursnormal)rN   r?      veraoseasonal)rL   r@   rM   invernoneutroz%m-%deventr   )	timedelta)dayspost_feriadoinactive)get_overall_weather_multiplierweatherz.3fz[WEATHER] Multiplier: z*[WEATHER] Failed to fetch, using neutral: neutralNgoogle_trendscurrent)r'   factor_metadataweekdayr*   daystrmonthstrftimer   ra   app.services.weather_servicere   r!   info	Exceptionwarning)r   r-   r.   r+   result	dow_names	dow_indexdow_namerl   
period_keyweekweek_keypayment_keyhour_key
mobile_keyimpulse_keyrn   seasonal_keydate_keyra   yesterday_keyre   weather_multes                           r   get_all_global_multipliersz-DynamicMultipliers.get_all_global_multipliers>   s    ..0	  " [	'')	Y' )mR @ D DXs S}.6]+ oo"9!JBYJJ$-MM2CR$H$L$LZY\$] !2<./ ooaA~!TF#"+--"D"H"HSV"W08_- %%c(K$-MM-$D$H$HVY$ZF=!2=D  /$'F=!27D  / "#&a(#,==1A2#F#J#J8UX#Y 19-. ??J%.]]>2%F%J%J:WZ%[F>"#J%.]]>2%F%J%J:WZ%[F>"/9^, 66"K&/mmOR&H&L&L[Z]&^F?#4?D  1&)F?#4<D  1 !!J"L!*z2!>!B!B<QT!UF:i$L!*z2!>!B!B<QT!UF:#L!$F:+7Z( ''0#--4883Gw4:7Os4JPXW% 	'$ya'88BB7KIMM'266%.]]>2%F%J%J8UX%YF>"3;D  0%(F>"3=D  0		8S9;L0<#F917	1B30GD  +KK0	1B30GHI #,--"D"H"HTW"X09_-  	8NNGsKL #F9.7D  +	8s   AP 	Q,Q

Qc                     t        | di       S )a  
        Get categorical key names for factors (NOT numeric values).
        Call this AFTER get_all_global_multipliers().
        
        Returns dict mapping factor names to their categorical keys.
        Example: {'day_of_week': 'segunda', 'seasonal': 'verao'}
        rj   )getattr)r   s    r   get_factor_metadataz&DynamicMultipliers.get_factor_metadata   s     t.33r   c                    | j                         i }dt        dt        dt        dt        ffd}t        |dd      }|dk  rd|d	<   nZ|j                  rIt        |j                        }|d
k  r |d	dd      |d	<   n&|dk  r |d	dd      |d	<   n |d	dd      |d	<   nd|d	<   t        |dd      }|r |d|d      |d<   n |ddd      |d<   t        |dd      }|rG|dk  r |ddd      |d<   n9|dk  r |ddd      |d<   n&|dk  r |ddd      |d<   n |ddd      |d<   nd|d<   t        |dd       }|r |d!d"d#      |d!<   n |d!d$d      |d!<   t        |d%d      }	|	r |d&|	d      |d&<   nd|d&<   t        |d'd      }
|
r |d'|
d      |d'<   nd|d'<   t        |d(d       }|r |d(d"d#      |d(<   n |d(d$d      |d(<   t        |d)d       }|r |d*d"d      |d*<   n |d*d$d      |d*<   t        |d+d       }|r |d,d"d-      |d,<   n |d,d$d      |d,<   t        |d.d      }t        |d/d      }|d0k(  r#|r!t        t        |      d1z  d      }d|z   |d2<   n-|d3k(  r#|r!t        t        |      d1z  d4      }d|z   |d2<   nd|d2<   d|d5<   d|d6<   d|d7<   t        |d8d      }|d9k(  r&j                  d:i       j                  d9d      |d:<   n[|d;k(  r&j                  d:i       j                  d;d      |d:<   n0|d<k(  r&j                  d:i       j                  d<d      |d:<   nd|d:<   t        |d=d       }|r'j                  d>i       j                  d"d-      |d><   |S d|d><   |S )?z
        Get ALL product-specific multipliers.
        These are factors that vary by product.
        
        Args:
            product: ProductForecast object
            
        Returns dict with all applicable multipliers and their values.
        factor_type
factor_keyr(   r   c                 x    d|  }|v r||   v r|   |   S j                  | i       j                  ||      S )z=Get value from product_<type> first, then fallback to <type>.product_)r*   )r   r   r(   product_typer+   s       r   get_calibratedzFDynamicMultipliers.get_all_product_multipliers.<locals>.get_calibrated   sQ    %k]3Ly(Z9\;R-R .z::==b155j'JJr   stock_currentr   g        stock_pressure   criticalg      ?r@   lowg?rZ   r8   listing_healthNrg   search_positionrC   top5g?r9   top10gffffff?r;   top20below20has_free_shippingFfree_shippingrX   g?rd   shipping_typeshipping_advantagelisting_type
gold_medalcatalog_listingcatalog_boost	has_promopromo_activerG   trend	trend_pctupd   visits_trenddowng      conversion_rateprice_competitivenesscompetitor_stockoutcurveAvelocity_scoreBCis_top_sellertop_sellers)r'   rm   r   r   days_of_coverageminmaxr*   )r   productrt   r   r   rb   healthpositionr   r   r   	has_medal
in_catalogr   r   r   boost	reductionr   r   r+   s                       @r   get_all_product_multipliersz.DynamicMultipliers.get_all_product_multipliers   s    ..0		K 	K 	Ku 	KQV 	K  !<A(+V$%%%112Dax+9:JJX[+\'(+9:JESV+W'(+9:JHVY+Z'('*F#$ "2D9'56FPS'TF#$'56F	SV'WF#$ 7$5t<1},:;LfVY,Z()R,:;LgW[,\()R,:;LgWZ,[(),:;LiY\,]()(+F$% $G-@%H&4_hPS&TF?#&4_jRU&VF?#  $?+9:NP]_b+cF'(+.F'( w=%3NLRU%VF>"%(F>" G\59	#1,##NF< #1,
C#PF<  W&7?
&4_hPT&UF?#&4_jRU&VF?# G[%8	%3NHc%RF>"%3NJPS%TF>" $/G[$7	D=Yi(3.4E%(5[F>"f_E),s2D9I%(9_F>"%(F>" %( ! +.&' ),$% $/C<'0}}5Er'J'N'NsTW'XF#$c\'0}}5Er'J'N'NsTW'XF#$c\'0}}5Er'J'N'NsTW'XF#$'*F#$  %@$-MM-$D$H$HSV$WF=!  %(F=!r   rl   c                 4    |dk  ry|dk  ry|dk  ry|dk  ryy	)
z Get period key for day of month.rC   r:   r9   pos_pagamentor;   r<   rE   pre_salarior=    )r   rl   s     r   _get_period_keyz"DynamicMultipliers._get_period_keyN  s-    !8BY"BYBY r   c                 T    | j                         }t        |j                               S )z#Get all available multiplier types.)r'   listkeys)r   r+   s     r   get_multiplier_typesz'DynamicMultipliers.get_multiplier_types[  s"    ..0	INN$%%r   multipliersc                 >    d}|j                         D ]  }||z  }	 |S )z
        Calculate the combined multiplier from all individual multipliers.
        All multipliers are multiplicative (product of all values).
        r8   )values)r   r   combinedvalues       r   calculate_combined_multiplierz0DynamicMultipliers.calculate_combined_multiplier`  s0    
  '') 	EH	r   N)r8   )__name__
__module____qualname____doc__r   r   r   rm   r   r'   r,   r   intr   r   r   r   r   r   r   r   r   r   r   r      s    7 tCc5j1A,A'B 6;3 ;s ;U ;U ;
td t tQUVY[`V`Qa tl4T#s(^ 4Nd3:6F N`3 3 &d3i &
c5j9I e r   r   )r   loggingr   r   typingr   r   r   sqlalchemy.ormr   decimalr	   	getLoggerr   r!   r   r   r   r   <module>r      s<   
  # ' ' " 			8	$Y Yr   