
    RRj+>                        d Z ddlZddlZddlmZmZ 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mZ dd
lmZmZmZ ddlmZ  ej2                  e      ZdZdZ ej<                  ddg      d        Z ej<                  ddg      d        Z  ej<                  ddg      d        Z! ej<                  ddg      d        Z" ej<                  ddg      d        Z#defdZ$ ej<                  ddg      d        Z% ej<                  ddg      d        Z& ej<                  d d!g      d"        Z' ej<                  d d#g      d$        Z(y)%u6  
Endpoints do módulo Full (Fulfillment ML) — Fase 1, read-only.

  GET  /full/overview            resumo operacional (unidades, valor imobilizado, alertas)
  GET  /full/inventory           lista por produto (estoque por estado, cobertura, custo real/un)
  GET  /full/inventory/<ad_id>   detalhe + série histórica diária
  POST /full/sync                dispara sync manual (mesmo do job diário)
  GET/POST/PUT/DELETE /full/tariffs[/<id>]   CRUD da tabela de tarifas (Settings)

Nada escreve no ML. O custo real calculado aqui alimenta ProductFinancialMetric.
    N)date	timedelta)requestjsonify)func)api_bp)SessionLocal)Ad)ProductFinancialMetric)FullInventoryFullStockDailyFullStorageTariff)	TinyStockZ      z/full/replenishmentGET)methodsc                     t               } 	 t        dt        dt        j                  j                  ddt                          }t        dt        |t        j                  j                  ddt                          }i }| j                  t              j                  t        j                  j                  d	            j                         D ]E  }|j                  |j                  d
      t        |j                  xs d
      z   ||j                  <   G i i }}| j                  t              j                  t        j                  j                  d	            j                         D ]  }t        |j                  xs d
      }|j                  |j                  d
      |z   ||j                  <   |j                   sU|j#                  |j                  g       j%                  |j                   |d        i }| j                  t&              j                  t&        j(                  dk(  t&        j                  j                  d	            j                         D ]E  }	|j#                  |	j                  |	d
d      }
|
dxx   t        |	j*                  xs d
      z  cc<   G g }|j-                         D ]  \  }}
|
d   }	|j                  |d
      }|j                  |d
      }|
d   dz  }|d
k  r=t/        ||z  d      }||k\  rRt1        j2                  ||z        }t        d
||z
        }t        ||      }|j%                  |	j4                  ||	j6                  |||j                  |g       |
d   t/        |d      |||||d
kD  rdndddddd        |j9                  d        t;        ||t=        |      |dd      | j?                          S # t@        $ rJ}tB        jE                  d|        t;        dtG        |      i      dfcY d	}~| j?                          S d	}~ww xY w# | j?                          w xY w) zCRead-only replenishment suggestions from real Full and local stock.   r   target_days   )type   trigger_daysr   Nr   )	warehouse	availableT)ad	sales_30dr   r   g      >@   readyno_local_stockzfull_inventory (ML Full, real)ztiny_stock (local, real)zads.sales_30d / 30 (estimate))full_availablelocal_availablevelocity)ad_idskutitler"   r#   local_warehousesr   daily_sales_estimatecoverage_daystarget_full_quantityquantity_neededquantity_suggestedstatussourcesc                     | d   S )Nr*    )items    D/var/www/hypershopcomercio.com.br/hyper-ai/app/api/endpoints/full.py<lambda>z4full_replenishment_recommendations.<locals>.<lambda>^   s    D$9     keysuggestion_only)r   r   countitemsmodez$full_replenishment_recommendations: error  )$r	   maxminr   argsgetintqueryr   filterr&   isnotallavailable_qtyr   r   r   
setdefaultappendr
   is_fullr   r:   roundmathceilidr'   sortr   lenclose	Exceptionloggerr<   str)dbr   r   full_by_skurowlocal_by_skuwarehouses_by_skuquantity
ads_by_skur   entryr:   r&   r"   r#   daily_salesr*   target_quantityneeded	suggestedes                        r3   "full_replenishment_recommendationsrb       s    
BA!SW\\%5%5mRc%5%RST1c+w||/?/?PRY\/?/]^_88M*11-2C2C2I2I$2OPTTV 	]C#.??377A#>SEVEVE[Z[A\#\K 	] +-b'88I&--imm.A.A$.GHLLN 	C3==-A.H$0$4$4SWWa$@8$KL!}}!,,SWWb9@@!$XB 		 
((2,%%bjjD&8"&&,,t:LMQQS 	9B))"&&!2LME+#bll&7a"88	9 $**, !	JCtB(__S!4N*..sA6O,t3Ka!.;">BM,"iik(ABOOn<=FFO4ILL"0#2$5$9$9#r$B";/(-k1(=!.(7#)&/%.]'8H&F'A ? !	F 	

9
:{L!$UeEVX Y 	
	  /;A3?@Q()3..

	/ 	
s7   F4O HO 	P+!/P&P+P. &P++P. .Q z/full/overviewc                     t               } 	 | j                  t              j                         }|s t	        ddi i d      | j                          S |D cg c]  }|j                  s|j                   }}|rh| j                  t              j                  t        j                  j                  |            j                         D ci c]  }|j                  | c}ni }dx}x}}d}	t               }
dx}x}}|D ]4  }||j                  xs dz  }||j                  xs dz  }||j                  xs dz  }|j                  r|
j                  |j                         |j!                  |j                        }|r5|j"                  r)|	|j                  xs dt%        |j"                        z  z  }	|j&                  |j&                  t(        k  r|dz  }|j*                  |j*                  t,        kD  r|dz  }|j                  xs ddkD  s|j&                  |j&                  dkD  s0|dz  }7 t	        dt/        |
      t/        |      |||t1        |	d	      d
|||dd      | j                          S c c}w c c}w # t2        $ rK}t4        j7                  d|        t	        dt9        |      d      dfcY d }~| j                          S d }~ww xY w# | j                          w xY w)NFzISem dados de Full. Rode o sync: python -m app.scripts.backfill_full_stock)has_datamessagesummaryalertsr   g        r      Tr   )products_countinventories_countunits_availableunits_in_transitunits_not_availableimmobilized_value)low_coverage
aged_stockstranded)rd   rf   rg   zfull_overview: rd   r<   r=   )r	   rC   r   rF   r   rQ   r%   r
   rD   rN   in_setrG   in_transit_qtynot_available_qtyaddrA   costfloatdays_of_stockLOW_COVERAGE_DAYSoldest_stock_daysAGED_DEFAULTrP   rK   rR   rS   r<   rT   )rU   rowsrad_idsaads_maprk   units_transitunits_naimmobilizedproductslow_covagedrq   r   ra   s                   r3   full_overviewr   h   s   	B6xx&**,!f f 	
Y $(3a177!''33U[BHHRL$7$7		&8I$J$N$N$PQq1447Qac5666-(5$%%%$ 	Aq3!3OQ--22M++0q0HwwQWW%QWW%Bbgg 41bggFF*qAR/R1"".13F3F3U	$1)q/F!//\_J_A	  "%h-%(Y#2$1'/%*;%: !("$
 ( 	
Y 4QN  Bqc*+ECF;<cAA

	B 	
sg   4J J I;'I;5AJ 
J D0J J -=J ;
J 	K0K>K?K KK K.z/full/inventoryc                     t               } 	 t        j                  j                  dd      }t        j                  j                  d      dk(  }| j	                  t
              j                         }|D cg c]  }|j                  s|j                   }}|D cg c]  }|j                  s|j                   }}|rh| j	                  t              j                  t        j                  j                  |            j                         D ci c]  }|j                  | c}ni }i }	|rg| j	                  t              j                  t        j                  j                  |            j                         D 
ci c]  }
|
j                  |
 }	}
g }|D ]  }|j                  |j                        }|	j                  |j                        }|r!|j                  rt        |j                        nd }|r!|j                   rt        |j                         nd }|j"                  d uxr |j"                  t$        kD  }|j&                  d uxr |j&                  t(        k  }|r|s|s|j+                  i d|j,                  d|j                  d|j                  d|j.                  d	|r|j0                  nd d
|r|j2                  nd d|r|j4                  nd d|j6                  d|j8                  d|j:                  d|j<                  d|j&                  d|j"                  d|d|d|d|d|j>                  r|j>                  jA                         nd i        |dk(  r|jC                  d        n,|dk(  r|jC                  d        n|jC                  d        tE        tG        |      tI        |      |d      | jK                          S c c}w c c}w c c}w c c}
w # tL        $ rK}tN        jQ                  d|        tE        dtS        |      d       d!fcY d }~| jK                          S d }~ww xY w# | jK                          w xY w)"Nsort_bycoveragerg   1inventory_idr%   r&   variation_idr'   	thumbnail	permalinkrG   ru   rv   	total_qtyrz   r|   storage_cost_unitstorage_risk_unitis_agedis_low_coverage
updated_atr   c                 $    | d   d u | d   xs d fS )Nr|   r   r1   xs    r3   r4   z%full_inventory_list.<locals>.<lambda>   s%    a(;&<&DJ]H^HcbcFd%e r5   r6   r   c                     | d   xs d S )NrG   r   r1   r   s    r3   r4   z%full_inventory_list.<locals>.<lambda>   s    q'9'>Q%? r5   c                 "    | d   d u | d   xs dfS )Nrz   g    eAr1   r   s    r3   r4   z%full_inventory_list.<locals>.<lambda>   s     a&8D&@!OBTB[X[%\ r5   )rd   r9   r:   zfull_inventory_list: Frr   r=   )*r	   r   r@   rA   rC   r   rF   r%   r&   r
   rD   rN   rs   r   storage_costry   storage_risk_costr|   r}   rz   r{   rI   r   r   r'   r   r   rG   ru   rv   r   r   	isoformatrO   r   boolrP   rQ   rR   rS   r<   rT   )rU   r   only_alertsr~   r   r   skusr   r   
metric_mapmr:   r   metricstorage_unitstorage_riskr   is_lowra   s                      r3   full_inventory_listr      s   	B;,,""9j9ll&&x0C7xx&**,#'3a177!''33#-!quu--U[BHHRL$7$7		&8I$J$N$N$PQq1447Qac
,.HH5K,L!6"8"<"<"@"@"FGOq!%%( OJ O  	AQWW%B^^AEE*F9?FDWDW5!4!45]aL>DIaIa5!9!9:gkL))5\!:M:MP\:\G__D0XQ__GX5XFGvLL  quu 	
 RT RR\\T RR\\T   !!"2"2 $Q%8%8 Q[[   $Q%8%8 $\ $\  7!" "6#$ !,,all446D% 	B fJJeJf#JJ?J@JJ\J]DK#e*uUV
 	
m 4-QOZ  B,QC01ECF;<cAA

	B 	
su   A)O2 5OOO2 O#-O#;AO2 O($AO2 >O-H;O2 O2 2	Q;0Q+Q,Q	 QQ	 	Qz/full/inventory/<ad_id>c                    t               }	 |j                  t              j                  t        j                  | k(        j                         }|st        ddi      df|j                          S |j                  t              j                  t        j                  | k(        j                         }|D cg c]  }|j                   }}t        j                         t        d      z
  }|j                  t        j                   t#        j$                  t        j&                        t#        j$                  t        j(                        t#        j$                  t        j*                              j                  t        j                  j-                  |      t        j                   |k\        j/                  t        j                         j1                  t        j                         j                         }t        | |r|j2                  nd |r|j4                  nd |D cg c]]  }|j                  |j6                  |j&                  |j(                  |j*                  |j8                  |j:                  |j<                  d_ c}|D cg c]J  }|d   j?                         tA        |d   xs d      tA        |d	   xs d      tA        |d
   xs d      dL c}d      |j                          S c c}w c c}w c c}w # tB        $ rJ}	tD        jG                  d|	        t        dtI        |	      i      dfcY d }	~	|j                          S d }	~	ww xY w# |j                          w xY w)Nr<   u$   Sem estoque Full para este anúncio.  <   )days)r   r   rG   ru   rv   r   rz   r|   r   r   r      )r   r   
in_transitnot_available)r%   r'   r   inventoriesdaily_serieszfull_inventory_detail: r=   )%r	   rC   r   rD   r%   rF   r   rQ   r
   rN   firstr   r   todayr   r   dayr   sumrG   ru   rv   rs   group_byorder_byr'   r   r   r   rz   r|   r   rB   rR   rS   r<   rT   )
r%   rU   r~   r   r   inv_idssincedailydra   s
             r3   full_inventory_detailr      s   	B-xx&--m.A.AU.JKOOQG%KLMsRT 	
Q XXb\  %0668+/0a1>>00 

yb11HH^112HH^223HH^556	

 &''++G4%'
 (>%%
&xx0B0B'CCCE 	 !#RXX)+ 	  !" !!""#"2"2%&%8%8[[!"%&%8%8	 	 
 	 !( 1^!!A$)!n!$QqTYQ	 
 2 	
O 1$	  /.qc23Q()3..

	/ 	
sd   AK? 0AK? 7K0
EK?  A"K5K? AK:K? 0K? ?	M/M7M8M MM M'z
/full/syncPOSTc                  T   ddl m}   |        }	 |j                         }t        ddi|      |j	                          S # t
        $ rK}t        j                  d|        t        dt        |      d      dfcY d	}~|j	                          S d	}~ww xY w# |j	                          w xY w)
uD   Dispara o sync + custo sob demanda (o job diário também faz isso).r   )FullServicesuccessTzfull_sync: Fr   r<   r=   N)	app.services.full_servicer   sync_and_costr   rQ   rR   rS   r<   rT   )r   svcresultra   s       r3   	full_syncr     s     6
-C""$	42623
 				  A{1#&'53q6:;S@@			A 			s-   > 	B0B7B8B BB B'tc           
      *   | j                   | j                  | j                  | j                  | j                  t        | j                        nd | j                  t        | j                        nd | j                  | j                  | j                  d	S )N)	rN   namemin_volume_lmax_volume_l	daily_feeinbound_feeaged_days_thresholdaged_daily_factoractive)
rN   r   r   r   r   ry   r   r   r   r   )r   s    r3   _tariff_dictr   *  so    dd+,;;+BU1;;'/0}}/HuQ]]+d 4400((
 
r5   z/full/tariffsc            	      4   t               } 	 | j                  t              j                  t        j                        j                         }t        d|D cg c]  }t        |       c}i      | j                          S c c}w # | j                          w xY w)Ntariffs)	r	   rC   r   r   r   rF   r   r   rQ   )rU   r   r   s      r3   full_tariffs_listr   8  sn    	B((,-667H7U7UVZZ\	W#ELO#EFG

 $F

s   A
B B 
(B  B Bc                  x   t               } 	 t        j                  d      xs i }t        |j	                  d      t        |j	                  d      xs d      |j	                  d      dvrt        |d         nd t        |j	                  d      xs d      t        |j	                  d	      xs d      t        |j	                  d
      xs d      t        |j	                  d      xs d      t        |j	                  dd                  }| j                  |       | j                          t        dt        |      d      df| j                          S # t        $ rC}| j                          t        dt        |      d      dfcY d }~| j                          S d }~ww xY w# | j                          w xY w)NTsilentr   r   r   r   N r   r   r   r   r         @r   )r   r   r   r   r   r   r   r   r   tariff   Fr     )r	   r   get_jsonr   rA   ry   rB   r   rw   commitr   r   rQ   rR   rollbackrT   )rU   r   r   ra   s       r3   full_tariffs_creater   B  s^   	BD)/Rvquu^49:56UU>5JR\5\q01bfAEE+.3!4aeeM27a8 #AEE*?$@$FB G#AEE*=$>$E#Fh-.	
 	q	
		4<?CDcI
 	
	  A
53q6:;S@@

	A 	
s0   D;E 	F$!(F	F$
F' F$$F' 'F9z/full/tariffs/<int:tariff_id>PUTc                    t               }	 |j                  t              j                  |       j	                         }|s t        ddd      df|j                          S t        j                  d      xs i }d|v r
|d   |_	        d	|v rt        |d	   xs d
      |_        d|v r|d   dvrt        |d         nd |_        d|v rt        |d   xs d
      |_        d|v rt        |d   xs d
      |_        d|v rt        |d   xs d      |_        d|v rt        |d   xs d      |_        d|v rt%        |d         |_        |j)                          t        dt+        |      d      |j                          S # t,        $ rC}|j/                          t        dt1        |      d      dfcY d }~|j                          S d }~ww xY w# |j                          w xY w)NrN   F   Tarifa não encontradar   r   Tr   r   r   r   r   r   r   r   r   r   r   r   r   r   r   )r	   rC   r   	filter_byr   r   rQ   r   r   r   ry   r   r   r   r   rB   r   r   r   r   r   r   rR   r   rT   )	tariff_idrU   r   r   ra   s        r3   full_tariffs_updater   [  s   	BHH&'11Y1?EEGu7OPQSVV" 	
! D)/RQ;6Qq7H7MA1NQ9:>9JR\9\U1^#45bfAN!5;1D1+EQ[AuQ}5E5J/Kq} A%s1EZC[Ca_a?bq'<!#5CVAWA^[^;_Q%8q=T!H+%6!(
		4<?CD
 	
	  A
53q6:;S@@

	A 	
s7   AE> !DE> >	G
(G/G
0G G

G GDELETEc                    t               }	 |j                  t              j                  |       j	                         }|s t        ddd      df|j                          S |j                  |       |j                          t        ddi      |j                          S # t        $ rC}|j                          t        dt        |      d      dfcY d }~|j                          S d }~ww xY w# |j                          w xY w)	Nr   Fr   r   r   r   Tr   )r	   rC   r   r   r   r   rQ   deleter   rR   r   rT   )r   rU   r   ra   s       r3   full_tariffs_deleter   u  s    	BHH&'11Y1?EEGu7OPQSVV 	
 			!
			4()
 	
	  A
53q6:;S@@

	A 	
s6   AB !-B 	C+((C&C+C. &C++C. .D ))__doc__loggingrL   datetimer   r   flaskr   r   
sqlalchemyr   app.apir   app.core.databaser	   app.models.adr
   app.models.financialr   app.models.fullr   r   r   app.models.tiny_stockr   	getLogger__name__rS   r}   r{   routerb   r   r   r   r   r   r   r   r   r   r1   r5   r3   <module>r      s  
   $ "   *  7 L L +			8	$  #eW5D 6DN 08 18v %1= 2=@ '%9/ :/d lVH- ."%  ow/ 0 ox0 10 -w? @2 -zB Cr5   