
    !+i=                     `    d dl m Z mZ d dlmZ d dlmZ d dlmZ d dlm	Z	 d dl
Z G d d      Zy)	    )datetime	timedelta)Session)func)MlMetricsDaily)AdNc                       e Zd ZdefdZddedefdZddedefdZdede	de	fd	Z
defd
Zdede	fdZdede	de	fdZy)PricingEnginedbc                     || _         y )N)r   )selfr   s     I/var/www/hypershopcomercio.com.br/hyper-ai/app/services/pricing_engine.py__init__zPricingEngine.__init__	   s	        item_iddaysc                    t        j                         j                         t        |      z
  }| j                  j                  t        j                  t        j                  t        j                        j                  t        j                  |k(  t        j                  |k\  t        j                  dkD        j                  t        j                        j                         }t        |      dk  rddddS i }|D ]]  }|j                  rt        |j                        nd}|dk(  r,t        |      }||vrg ||<   ||   j!                  |j                         _ t        |      dk  rdd	d
dS g }	|j#                         D ]0  \  }
}t%        |      t        |      z  }|	j!                  |
|d       2 |	j'                  d        |	d   }|	d   }|d   |d   }}|d   |d   }}|dkD  r||z
  |z  nd}|dkD  r||z
  |z  nd}|dk(  rddddS t)        ||z        }|dkD  rd}d}d}n|dk  rd}d}d}nd}d}d}t        |d      |||d| d| d t        |d!       d"t        |d!       d#	d$S )%z
        Calculates Price Elasticity of Demand (PED) for a given item.
        Returns a dictionary with the score, classification, and suggestion.
        r   r      NzDados Insuficientesu"   Aguarde mais histórico de vendas.)scorelabel
suggestion   u   Preço Estávelu;   Não houve variação de preço para calcular elasticidade.)pricevelocityc                     | d   S )Nr    )xs    r   <lambda>z4PricingEngine.calculate_elasticity.<locals>.<lambda>?   s
    '
 r   )keyr   r   Errou   Variação de preço nula.      ?u   Elástica (Sensível)u3   Cuidado ao subir preço. Demanda cai muito rápido.HOLD_OR_LOWERg?u   Inelástica (Resistente)u<   Oportunidade! Subir preço provavelmente aumentará o lucro.RAISEu   Unitária (Equilibrada)u)   Preço ideal próximo. Monitore a margem.OPTIMIZE_MARGINzAo subir de R$ z	 para R$ u   , a venda média mudou de    z para z/dia.)r   r   r   actionanalysis)r   utcnowdater   r   queryr   	avg_price	sales_qtyfilterr   order_byalllenfloatroundappenditemssumsortabs)r   r   r   cutoff_datehistoryprice_pointsdayr   rounded_pricedatap
sales_listavg_daily_sales	low_point
high_pointp1q1p2q2pct_change_qpct_change_p
elasticityr   r   r(   s                            r   calculate_elasticityz"PricingEngine.calculate_elasticity   s   
 oo',,.1EE ''--$$$$
 &""g-;.$$q(
 (>&&
' 	 w<!.B   	>C,/MME#--(qEz8!%LML0.0]+'..s}}=	> |q *[  )//1 	CMAz!*oJ?OKK!AB	C
 			*	+ G	"X
7#Yz%:BG$j&<B *,aR2~Q)+aR2~Q1&@\]]45
 ,UOZ%V#/UXZV.UEZ'V :q)$)"Yrd:TUZ[]^_U`Taaghmnpqrhsgttyz
 	
r   c                    d}t        j                         j                         t        |      z
  }| j                  j                  t        j                  t        j                  t        j                        j                  t        j                  |k(  t        j                  |k\  t        j                  dkD        j                         }t        |      dk  r|dd| dt        |      dS g }|D ]?  }|j                  dkD  s|j                  |j                  z  d	z  }|j                  |       A |s|dd
| dddS t        t        j                   |            }	t        t        j"                  |            }
t%        ||	|
z
        }t'        |d      dt'        |	d      t'        |
d      d|	dd|
dd|ddt        |      dS )a  
        Calculates the minimum acceptable conversion rate for a product.
        Uses historical data if available, otherwise falls back to ML benchmark (1.5%).
        
        Returns:
            dict with threshold, method used, and explanation
        r#   r   r      	benchmarku;   Sem histórico suficiente. Usando média do Mercado Livre: %)	thresholdmethodexplanationdays_analyzedd   u5   Dados insuficientes. Usando média do Mercado Livre: r   
historicalu    Calculado do histórico: média .1fu	   % - 1σ (z%) = )rQ   rR   meanstdrS   rT   )r   r*   r+   r   r   r,   r   visitsr.   r/   r   r1   r2   r5   r3   nprX   rY   maxr4   )r   r   r   ML_BENCHMARKr:   r;   conversion_ratesr=   rate	mean_convstd_convcalculated_thresholds               r   calculate_conversion_thresholdz,PricingEngine.calculate_conversion_thresholdh   s    oo',,.1EE ''--!!$$
 &""g-;.!!A%
 #% 	 w<")%!\]i\jjkl!$W	   	.CzzA~

2c9 ''-	.
  )%!VWcVddef!"	  "''"234	 012  #<X1EF 3Q7")Q'1%=i_IV^_bUcchi}  B  iC  CD  E \
 	
r   current_pricetarget_pricec                 *   | j                  |      }|j                  d      }d}d}g }|}	d}
t        j                         j	                         }||kD  r|	|k  r|
dk  r|
dz  }
|	|z   }||dz
  k\  r|}|t        |
dz        z   }|j                  |
|j                  d	      |j                  d
      t        |d      t        ||z
  |z  dz  d      |
dk(  r|nd|
 d|dd       |}	|	|k\  rn|	|k  r|
dk  r|||t        |      t        |      dz  dS )aB  
        Calculates safe price adjustment steps based on product elasticity.
        
        - Elastic products (>1.5): small 1% steps
        - Unitary products (0.8-1.5): medium 2% steps  
        - Inelastic products (<0.8): larger 3% steps
        
        Returns list of price steps with dates and reasons.
        r   g?u,   Estratégia Fixa: Aumento de R$ 0,40 por diar      r'   g{Gzt?r   z%Y-%m-%dz%d/%mr   rU   zStep z: +R$ .2f)stepr+   date_displayr   increase_pctreason)stepsstep_size_fixedrK   total_stepsestimated_days)
rL   getr   r*   r+   r   r5   strftimer4   r2   )r   r   rd   re   elasticity_dataelasticity_scorestep_fixed_valuereason_baserm   r   step_num	base_date	new_price	step_dates                 r   calculate_safe_price_stepsz(PricingEngine.calculate_safe_price_steps   se    33G<*..w7  D OO%**,	 -'<'HsNA!$44	u 44 ,I%	x!|(DD	$%..z:$-$6$6w$?"9a0$)I,E+VZ]*]_`$a-5]k%zQWXhilWm@n  "L() <'HsN. /)u:!%j1n
 	
r   c                 d   t        j                         j                         }|t        d      z
  }| j                  j                  t        j                  t        j                        j                  d      t        j                  t        j                        j                  d            j                  t        j                  |k(  t        j                  |k\  t        j                  |k        j                         }|j                  xs d}|j                   xs d}d}|dkD  r||z  dz  }| j                  j                  t              j                  t        j                  |k(  t        j                  |k(        j                         }d}	d}
|r-|j                  dkD  r|j                  |j                  z  dz  }	d	}
|
sdd
t#        |d      dddS |dk(  rdddt#        |	d      ddS ||	z
  |z  }|dkD  }||rd|dz  dd|ddndt#        |d      t#        |	d      t#        |dz  d      dS )z
        Checks if the item triggers the Automatic Reversion logic:
        Condition: Conversion drops > 15% compared to 7-day average.
           r   total_salestotal_visitsr           rU   FTz"Aguardando dados de visita de hojer   )	triggeredrl   avg_7dcurrentdrop_pctu"   Histórico insuficiente (Média 0)g333333?zALERTA: Queda de rW   z% (Meta 7d: z%)u"   Conversão dentro da margem segurar'   )r   r*   r+   r   r   r,   r   r7   r   r.   r   rZ   r/   r   firstr~   r   r4   )r   r   today	cutoff_7d
metrics_7dtotal_sales_7dtotal_visits_7davg_conversion_7dcurrent_metriccurrent_conversionhas_today_datar   r   s                r   check_auto_reversion_statusz)PricingEngine.check_auto_reversion_status   sI   
 !&&(I1--	 WW]]HH^--.44]CHH^**+11.A
 &""g-9,%'
 %' 	 $//41$116QQ!//!AS H ~6==""g-5(
 %' 	
 !n33a7"0":":^=R=R"RVY!Y!N "> 115  !"> !3Q7  &(::>OO tO	 #en)(3,s);<HYZ]G^^`a  uY-q1/3hna0
 	
r   ry   c                    | j                   j                  t              j                  t        j                  |k(        j                         }|r|j                  r|j                  dk  ry|j                  xs d}|j                  xs d}d}|j                  r(|j                  dkD  r|j                  |j                  z  }d}|j                  r|j                  }n4|j                  r(|j                  dkD  r|j                  |j                  z  }|j                  }|2|j                  |j                  |z  z
  |j                  |z  z
  |z
  |z
  }d}	|j                  r,|j                  dkD  r|j                  xs d|j                  z  }	|	dk(  s|dk  ry||z  }
||z  }||
z
  |z
  |z
  |z
  }|dk  ry||	z  |z  }t        |dz  d      S )z
        Calculates the conversion rate required at 'new_price' to maintain the same
        Total Profit (in Reais) as the current price, assuming constant traffic.
        
        Formula: NewConv = (OldMarginValue * OldConv) / NewMarginValue
        r   r   g     8@rU   r   )r   r,   r   r/   idr   r   costshipping_costtax_costcommission_percentcommission_costmargin_valuer   sold_quantityr4   )r   r   ry   adcost_productcost_shippingtax_rate	comm_ratecurrent_margin_valuer   new_comm_costnew_tax_costnew_margin_valuerequired_conversions                 r   calculate_break_even_conversionz-PricingEngine.calculate_break_even_conversion%  s    WW]]2%%beew&67==?RXX]
 ww~#((/C ;;288a<{{RXX-H	  --IBHHqL**RXX5I  "'$&HH90D$ET\I\$]`m$mp|$|! !??r2"$"2"2"7a2??!J"&:a&? "I- 8+$}4|CmSVbbq   46HHL\\(3.22r   c                 r   | j                   j                  t              j                  t        j                  |k(        j                         }d}|r;|j                  r/|j                  dkD  r |j                  xs d|j                  z  dz  }| j                  |      }| j                  |||      }| j                  |      }| j                  ||      }	t        |d      |d   |d   |d   |	d||d	   |d
   |j                  dd      |d   d|dd|d   |d	   j                  dd      d|d   d|	 dddS )z
        Returns complete strategy data for frontend display.
        Includes conversion threshold, elasticity, price steps, and reversion status.
        r   r   rU   r   rQ   rR   rS   )r   rQ   rR   rS   break_even_at_targetrK   rm   rn   rp   u8   Taxa de conversão = (Vendas ÷ Visitas) × 100. Atual: rh   rP   r   u,   Calculado do histórico de preços × vendasuC   Ajustes inteligentes buscando preços psicológicos (.40, .74, .90)rl   uG   Para manter o mesmo lucro total, a conversão não pode cair abaixo de )
conversionrQ   rK   rm   	reversion
break_even)r   reversion_statusrK   price_stepsstep_size_pctrp   tooltips)r   r,   r   r/   r   r   r   r   rc   r{   r   r   r4   rq   )
r   r   rd   re   r   r   conversion_dataprice_steps_datar   r   s
             r   get_strategy_datazPricingEngine.get_strategy_data`  sk    WW]]2%%beew&67==? "//boo&9"$"2"2"7a2??!JS!P==gF::7MS_`;;GD#CCG\Z !!3Q7,[9)(3.}=(< !1*<8+G4-112CQG./?@ XYkloXppqr,];.|<@@O}~^-h7 gh|g}}~
 	
r   N)   )Z   )__name__
__module____qualname__r   r   strintrL   rc   r3   r{   r   r   r   r   r   r   r
   r
      s    7 Z
C Z
s Z
x<
c <
 <
|5
# 5
e 5
[` 5
nF
3 F
P93s 93u 93v&
 &
U &
RW &
r   r
   )r   r   sqlalchemy.ormr   
sqlalchemyr   app.models.ml_metrics_dailyr   app.models.adr   numpyr[   r
   r   r   r   <module>r      s#    ( "  6  ~
 ~
r   