
    jiE                     |   d dl Z d dlZd dlZd dlZd dl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 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 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& d dl'm(Z(  e jR                  e*      Z+d dl,m-Z- d dl.m/Z/m0Z0 d dl1m2Z2 d dl3m4Z4  G d d      Z5y)    N)and_)Session)settings)SessionLocal)MeliApiService)TinyApiService)Ad)Metric)
OAuthToken)SaleSystemConfig)TinyProduct)
AdTinyLinkAdVariation)MarginCalculatorService)SyncControl)InitialLoadService)IncrementalSyncService)MlVisit)MlOrderMlOrderItem)	TinyStock)MlMetricsDailyc            	           e Zd Zd Zd Zd Zd(defdZd Zd)de	d	e	fd
Z
d Zdede	fdZde	defdZd Zd Zd ZdefdZd ZdefdZd*dedededefdZde	fdZd efd!Zd"efd#Zd$ Zd% Zd& Zd' Zy)+
SyncEnginec                 6   t               | _        t        | j                        | _        t	               | _        t               | _        ddlm	}  || j                        | _
        t        | j                        | _        t        | j                        | _        y )N
db_sessionr   )MetricProcessor)r   dbr   meli_servicer   tiny_servicer   margin_calculatorapp.services.metric_processorr!   metric_processorr   init_servicer   inc_service)selfr!   s     F/var/www/hypershopcomercio.com.br/hyper-ai/app/services/sync_engine.py__init__zSyncEngine.__init__#   sj    .*dgg>*,!8!:A / 8 /tww71$'':    c                     | j                   j                  t              j                  t        j                  dk(        j                         }|r|j                  r|j                  S t        j                  S )Nmercadolivre)	r"   queryr   filterproviderfirstuser_idr   MELI_USER_ID)r*   tokens     r+   get_seller_idzSyncEngine.get_seller_id/   sR    j)001D1D1VW]]_U]]== $$$r-   c           
         	 t         j                  d       ddlm} ddl}t
        j
                  j                         j                         }|t        j                  d      z
  }|j                  d      }|j                  d      }| j                  j                  d||      }|st         j                  d       yt        d	 |D              }t        d
 |D              }	t        d |D              }
t        d |D              }||z
  j                  dz   }||z  }|	|z  }|
|z  }||z  }| j                  j                  |      j!                  |j                  |k\  |j                  |k        j#                          | j                  j%                          t'        |      D ]X  }|t        j                  |      z   } |d|t)        |d      t)        |d      ||      }| j                  j+                  |       Z | j                  j%                          t         j                  d|dd|	d       y# t,        $ r<}t         j/                  d|        | j                  j1                          Y d}~yd}~ww xY w)z
        Syncs Ads metrics (last 7 days) using ONE bulk API call to avoid rate limits.
        For historical backfill (30 days), run patch_sync.py separately.
        z6Starting Ads Metrics Sync (Last 7 days - bulk call)...r   )MlAdsMetricN   )days%Y-%m-%dz%No Ads data returned for last 7 days.c              3   Z   K   | ]#  }t        |j                  d d      xs d       % yw)costr   Nfloatget.0rs     r+   	<genexpr>z.SyncEngine.sync_ads_metrics.<locals>.<genexpr>M   s%     LaU155#3#8q9L   )+c              3   Z   K   | ]#  }t        |j                  d d      xs d       % yw)amountr   Nr?   rB   s     r+   rE   z.SyncEngine.sync_ads_metrics.<locals>.<genexpr>N   s%     Q1aeeHa&8&=A >QrF   c              3   Z   K   | ]#  }t        |j                  d d      xs d       % yw)clicksr   NintrA   rB   s     r+   rE   z.SyncEngine.sync_ads_metrics.<locals>.<genexpr>O   s%     Ns1551#5#:;NrF   c              3   Z   K   | ]#  }t        |j                  d d      xs d       % yw)printsr   NrK   rB   s     r+   rE   z.SyncEngine.sync_ads_metrics.<locals>.<genexpr>P   s%     #SQCh(:(?a$@#SrF      PADS   )campaign_iddater>   revenuerJ   impressionsz#Ads Metrics Sync Completed! cost=R$z.2fz, revenue=R$zAds Metrics Sync Failed: )loggerinfoapp.models.ml_ads_metricsr9   timedatetimenowrS   	timedeltastrftimer#   get_ads_performancesumr;   r"   r0   r1   deletecommitrangeroundadd	Exceptionerrorrollback)r*   r9   rY   end_date
start_dated_fromd_toads_data
total_costtotal_revenuetotal_clickstotal_impressionsdays_in_range
daily_costdaily_revenuedaily_clicksdaily_impressionsidaymetrices                        r+   sync_ads_metricszSyncEngine.sync_ads_metrics6   s<   
5	KKPQ=((,,.335H!H$6$6A$>>J((4F$$Z0D ((<<T64PHCD L8LLJQQQMNXNNL ##S(#S S%
2881<M#m3J)M9M'=8L 1] B GGMM+&--  J.  H, fhGGNN =) 
$ 8#5#51#==$ &z1-!-3' 1 F#
$ GGNNKK=j=M\ZghkYlmn 	LL4QC89GG	s   B:H6 =E8H6 6	I;?2I66I;Nlookback_hoursc                 n    t         j                  d| d       | j                  j                  |       y)z>
        Triggers the V2 Incremental Sync for orders.
        z0Triggering V2 Incremental Sync Orders (lookback=)...r{   N)rV   rW   r)   sync_orders_incremental)r*   r{   s     r+   r   z"SyncEngine.sync_orders_incrementalr   s3     	F~FVVZ[\000Or-   c                 :   | j                   j                  t              j                  t        j                  dk(        j                         }|r|j                  dk7  r/t        j                  d       | j                  j                          | j                   j                  t              j                  t        j                  dk(        j                         }|r|j                  dk7  r0t        j                  d       | j                  j                          yy)z7
        Triggers V2 Initial Load if not done.
        orders	completedz"Starting V2 Initial Load Orders...adszStarting V2 Initial Load Ads...N)r"   r0   r   r1   entityr3   initial_load_statusrV   rW   r(   load_ordersload_ads)r*   controlcontrol_adss      r+   check_initial_loadzSyncEngine.check_initial_loady   s     ''--,33K4F4F(4RSYY['55DKK<=))+ ggmmK0778J8Je8STZZ\k==LKK9:&&( Mr-   log_typestatusc	                 P   	 d }	|r[t         j                   j                         }
|j                  r|j                  d       }t	        |
|z
  j                         dz        }	|dk(  rdnd}dd l}||||d}d}|||xs d	| |j                  |      |	|d
}| j                  j                  t        j                  |      |       | j                  j                          y # t        $ r<}t        j                  d|        | j                  j!                          Y d }~y d }~ww xY w)Ntzinfoi  rf   ERRORINFOr   )	processedsuccesserror_countraw_detailszINSERT INTO system_logs (module, level, message, details, duration_ms, status, timestamp) VALUES (:module, :level, :message, :details, :duration, :status, NOW())zSync )modulelevelmessagedetailsdurationr   zFailed to write log: )rZ   r[   r   replacerL   total_secondsjsondumpsr"   execute
sqlalchemytextra   re   rV   rf   rg   )r*   r   r   r   r   rf   msgr   
start_timer   now_nowr   r   detail_datasqlparamsry   s                    r+   	_log_synczSyncEngine._log_sync   s   #	H"++//1$$!+!3!34!3!@J* 4CCELM%0GfE&"$&	K vC #2E&"2::k2$ F GGOOJOOC0&9GGNN 	LL045GG	s   CC   	D%)2D  D%c                 r   t         j                  d       t        j                  j                         }| j	                  dd|       d}d}d}	 | j                         }|st        d      | j                  j                  |      }t        |      }t         j                  d| d       d	}t        d||      D ]d  }	||	|	|z    }
	 | j                  j                  |
      }|D ]  }	 | j                  ||       |d
z  }|d
z  }! | j                  j!                          f t         j                  d       | j	                  dd||||       y # t        $ r9}t         j                  d|j                  d       d|        |d
z  }Y d }~d }~ww xY w# t        $ r1}t         j                  d|        |t        |
      z  }Y d }~d }~ww xY w# t        $ r]}| j                  j#                          t         j                  d|        | j	                  dd|||t%        |      |       Y d }~y d }~ww xY w)NzStarting Ads Sync...listingsrunningr   r   zNo Seller ID found.Found z active items.2   rO   zFailed to process ad id: zChunk failed: zAds Sync completed.r   zAds Sync failed: rf   )rV   rW   rZ   r[   r   r7   re   r#   get_user_itemslenrb   get_item_details
_upsert_adrf   rA   r"   ra   rg   str)r*   r   processed_countsuccess_countr   	seller_iditem_idstotal_items
chunk_sizerv   chunkitems_detailsiteme_iteme_chunkry   s                   r+   sync_adszSyncEngine.sync_ads   s%   *+&&**,
z9D!	|**,I 566((77	BHh-KKK&^<=J1k:6 . 1Z<0.$($5$5$F$Fu$MM - -- OOD)<)Q.M (1,- GGNN$." KK-.NN:y/=R]jtNu  ) -"LL+@$@PPRSYRZ)[\'1,K-
 ! .LL>'!;<3u:-K.  	|GGLL,QC01NN:wP[]`ab]cpzN{{	|sn   A6G  F'E>!F.G 	F/FFFF	G&GG GG 	H6AH11H6	item_datar   c                 j   |d   }| j                   j                  t              j                  t        j                  |k(        j                         }|s't        |      }| j                   j                  |       ||_        |j                  d      d d |_	        |j                  d      |_
        |j                  d      |_        |j                  d      |_        |j                  d      |_        |j                  d	      |_        |j                  d	      |_        |j                  d
      |_        t!        |j                  d      t"              r!|j                  di       j                  d      n|j                  d      |_        t'        |j                  dd            |_        |j                  d      rt'        |j                  d            nd |_        |j                  d      |_        t/        |j                  dd            |_        t/        |j                  dd            |_        |j                  d      |_        |j                  d      |_        |j                  d      |_        |j                  di       }|j                  dd      |_        |j                  d      |_        |j                  d      dk(  |_        |j                  d      rt'        |j                  dd            nd|_         d }d }|j                  d	g       D ]X  }|j                  d      }	|j                  d      }
|	dk(  r|
r|
jC                         nd }?|	dk(  sE|
r|
jC                         nd }Z ||_"        ||_#        	 dd l$m%} dd!l&m'} | j                   j                  |      j                  |jP                  d"k(        j                         }|rt'        |jR                        }n" || j                         }|jU                         }| j                   j                  |      j                  |jP                  d#k(        j                         }|rt'        |jR                        nd}d}|j>                  r^| j                   j                  |      j                  |jP                  d$k(        j                         }|rt'        |jR                        nd}| jW                  ||||       t`        j`                  jc                         |_2        t`        j`                  jc                         |_3        d'|v r&|d'   r | ji                  |j                  |d'          y y y # tX        $ rN}tZ        j]                  d%|j                   d&|        |j^                  |j(                  rd|_/        Y d }~d }~ww xY w)(Nr   r   titlei  category_id	permalink	thumbnailpictures
attributesvideo_idshort_descriptioncontentpricer   original_pricecurrency_idavailable_quantitysold_quantityr   listing_type_idshippingfree_shippingFmodelogistic_typefulfillmenthealth        
value_name
SELLER_SKUGTIN
TaxServicer   aliquota_simplescusto_fixo_pedidoavg_inbound_costzError processing costs for ad r   
variations)5r"   r0   r	   r1   r   r3   rd   r   rA   r   category_namer   r   r   r   r   
isinstancedictr   r@   r   r   r   rL   r   r   r   r   listing_typer   shipping_modeis_fullr   stripskugtinapp.services.tax_servicer   app.models.system_configr   keyvalueupdate_system_tax_rate_process_ad_costre   rV   rf   tax_costrZ   r[   last_updated
updated_at_upsert_variations)r*   r   r   ad_idadr   r   r   attraidvalr   r   sc_taxtax_ratetssc_fixed
fixed_costinbound_cost
sc_inboundry   s                        r+   r   zSyncEngine._upsert_ad   s   $WW]]2%%beeun5;;=uBGGKKO ==)$3/$==7 }}[1 }}[1mmJ/!l3!l3mmJ/Xbclcpcp  rE  dF  HL  YMy}}-@"EII)T  S\  S`  S`  at  Su w23FOmmTdFeE)--0@"ABko"}5 #IMM2F$J Ky}}_a@AMM(+	&]]+<=#--(9:==R0#<<?#<</ll?3}D
9Bx9PE)--!45VY	MM,3 	4D((4.C((<(Cl"%(ciikd&)syy{t	4 ,"	";= WW]]<0778H8HL^8^_eegF .
  (446 ww}}\299,:J:JNa:abhhjH2:x~~.J Lzz!WW]]<8??@P@PTf@fgmmo
:DuZ%5%56# !!"h
LI #++//1 ))--/9$<)@$$RUUIl,CD *A$  	"LL9"%%1#FG{{"rxx!		"s   E)U 	V2$AV--V2r   variations_datac           	      j   |D ]  }t        |j                  d            }| j                  j                  t              j                  t        j                  |k(        j                         }|s(t	        ||      }| j                  j                  |       d }d|v rR|j                  dg       D ]=  }|j                  d      dk(  s|j                  d      }|r|j                         nd } n ||_
        t        |j                  dd            |_        t        |j                  dd            |_        t        |j                  d	d            |_        g }	d
|v r>|d
   D ]6  }
|	j!                  |
j                  d       d|
j                  d              8 dj#                  |	      |_         y )Nr   )r   r   r   r   r   r   r   r   r   attribute_combinationsnamer   z, )r   rA   r"   r0   r   r1   r   r3   rd   r   r   r@   r   rL   r   r   appendjoinattribute_combination)r*   r   r  var_datavar_id	variationvar_skur   r   comb	comb_attrs              r+   r   zSyncEngine._upsert_variationsH  sz   ' 	>Hd+,Fk299+..F:RSYY[I'6?	I&Gx'$LLr: Dxx~5#xx525399;4	
 $IM#HLL!$<=IO+.x||<PRS/T+UI(&)(,,*J&KI#D'83"*+C"D ]YkkY]]6%:$;2immL>Y=Z"[\].2iioI+/	>r-   c                     	 | j                   j                  |dd      S # t        $ r%}t        j	                  d| d|        Y d }~y d }~ww xY w)Nx   rw   )lastunitzThread fetch failed for r   )r#   get_visits_time_windowre   rV   rf   )r*   r   ry   s      r+   _fetch_visits_wrapperz SyncEngine._fetch_visits_wrapperb  sS    	%%<<USX<YY 	\\4UG2aSAB	s     	AA		Ac                 x	   t         j                  d       t        j                  j                         }d}d}d}	 | j	                         }| j
                  j                  t              j                  t        j                  dk(        j                         }t        |      }t         j                  d| d       | j                  j                          |D ci c]  }|j                  | }	}t        |	j!                               }
t"        j$                  j'                  d      5 }|
D ci c]  }|j)                  | j*                  |      |! }}t"        j$                  j-                  |      D ]U  }||   }|	|   }|dz  }	 |j/                         }|rd	|v r|d	   D ]  }|j1                  d
      d d }|j1                  dd      }t        j                  j3                  |d      j5                         }| j
                  j                  t6              j                  t6        j8                  |k(  t6        j4                  |k(        j;                         }|s(t7        ||      }| j
                  j=                  |       |j1                  dd      |_        | j
                  j                  t@              j                  t@        j8                  |k(  t@        j4                  |k(        j;                         }|r|j1                  dd      |_        rtA        |||j1                  dd            }| j
                  j=                  |        tC        d |d	   D              }||_"        ||_#        t        j                  j                         |_$        |dz  }n||dz  }|dz  dk(  s<| j
                  jO                          X 	 d d d        | j
                  jO                          | jQ                  dd||||       y c c}w c c}w # tJ        $ r*}t         jM                  d| d|        |dz  }Y d }~d }~ww xY w# 1 sw Y   {xY w# tJ        $ r]}| j
                  jS                          t         jM                  d|        | jQ                  dd|||tU        |      |       Y d }~y d }~ww xY w)NzStarting Visits Sync...r   activezSyncing visits for z active ads (Parallel).   )max_workersrO   resultsrS   
   visitsr<   item_idrS   total)r  rS   r  c              3   @   K   | ]  }|j                  d d        yw)r  r   N)rA   )rC   ds     r+   rE   z)SyncEngine.sync_visits.<locals>.<genexpr>  s     5aAaeeGQ6G5as   zProcessing result failed for r   r   r   r   zVisits Sync Failed: rf   )+rV   rW   rZ   r[   r7   r"   r0   r	   r1   r   allr   r#   get_headersr   listkeys
concurrentfuturesThreadPoolExecutorsubmitr  as_completedresultrA   strptimerS   r   r  r3   rd   r  r   r_   
visits_30dtotal_visitsvisits_last_updatedre   rf   ra   r   rg   r   )r*   r   r   r   rf   r   r   r  r   ad_mapad_idsexecutorr   future_to_idfuturedataday_data
v_date_strv_countv_date	visit_recexisting_metric
new_metrictotal_visits_period	e_processry   s                             r+   sync_visitszSyncEngine.sync_visitsi  s   -.&&**,
	C	h**,I''--#**299+@AEEGCHEKK-eW4KLM))+*-.BbeeRi.F.&++-(F##6616E 1)aghZ]0J0JC PRU Uhh(00==lK .)F&v.CBNI'#%}}I$5,0O <-5\\&-A#2-F
*2,,x*C)1):):)C)CJPZ)[)`)`)b,0GGMM',B,I,I'//]`J`bibnbnrxbx,y,,  -B	'007&0QI$(GGKK	$:3;<<3K	 0 37''--2O2V2V$2$:$:c$A$2$7$76$A3" #(%' !0
 $3=E\\'ST=UO$:1?RXaiamamnuwxay1zJ$(GGKK
$;+<4 365aQUV_Q`5a2a/,?BM.ABO5=5F5F5J5J5LB2#qLG#|UaZU !2~*(].)1)f GGNNNN8Y	7EV`Nao /  iX % #'DSEI;%WX
#[1) 1)l  	hGGLL/s34NN8Wi%Q\fNgg	hs   BQ P.;Q )Q.$P4QHP%Q/Q9Q Q Q	Q P?:Q?QQQQ 	R9AR44R9c                 R    t         j                  d       | j                  d       y)z
        [DEPRECATED Logic] Now redirects to V2 Incremental Sync.
        Syncs recent orders, populates ml_orders, and metrics.
        zIStarting Orders Sync (Redirecting to V2 Incremental with 48h lookback)...0   r~   N)rV   rW   r   r*   s    r+   sync_orderszSyncEngine.sync_orders  s'    
 	_`$$B$7 	r-   
order_datac                    t        |d         }| j                  j                  t              j	                  t        j
                  |k(        j                         }|s't        |      }| j                  j                  |       t        |j                  di       j                  d            |_	        |j                  d      |_
        |d   }|j                  d      r|j                  dd      }t        j                  j                  |      }|j                  r)|j!                  t        j"                  j$                        }|j                  d       |_        t)        |j                  d	d
            |_        |j                  d      |_        t        |j                  di       j                  d            |_        |j                  dg       }d
d l}|j3                  |      |_        t        |j                  d            |_        |j                  di       }|j                  d      rt        |j                  d            nd |_        d|_        |j                  dg       }	|	D ]  }
|
j                  di       j                  d      }| j                  j                  t<              j	                  t<        j
                  |k(  t<        j>                  |k(        j                         }|s(t=        ||      }| j                  j                  |       |
j                  di       j                  d      |_         |
j                  di       j                  d      |_!        tE        |
j                  dd            |_#        t)        |
j                  dd
            |_$        t)        |
j                  dd
            |_%        |j&                  jM                         }| j                  j                  tN              j	                  tN        jP                  |k(  tN        jL                  |k(        j                         }|s(tO        ||      }| j                  j                  |        y )Nr   )ml_order_idsellerr   date_createdZz+00:00r   total_amountr   r   buyertagsstatus_detailr   r   order_itemsr   )rF  
ml_item_id
seller_skur   quantityrO   
unit_pricesale_feer  ))r   r"   r0   r   r1   rF  r3   rd   rA   r   r   endswithr   rZ   fromisoformatr   
astimezonetimezoneutcrH  r@   rJ  r   buyer_idr   r   rL  rM  shipping_idshipping_costr   rO  r   r   rL   rQ  rR  rS  rS   r   r  )r*   rD  rF  orderdt_strdt_obj	tags_listr   r   
items_dataitem_drO  db_item	sale_date
metric_recs                  r+   _process_order_fullzSyncEngine._process_order_full  s   *T*+ g&--g.A.A[.PQWWY4EGGKKjnnXr:>>tDE!~~h/ N+??3nnS(3V""008==''(9(9(=(=>V#^^4^8":>>.!#DE&NN=9Z^^GR8<<TBC NN62.	ZZ	*
!*.."AB>>*b17?||D7ICT 23t!  ^^M26
   	FFB/33D9J ggmmK0778O8OS^8^`k`v`v  {E  aE  F  L  L  NG%+*UG$ **VR044\BGK"JJvr266w?GM"6::j!#<=G!&vzz,'B!CG$VZZ
A%>?G **//1I~6==n>T>TXb>bdrdwdw  |E  eE  F  L  L  NJ+JYO
J' A 	r-   c                    t         j                  d       t        j                  j                         }| j	                  dd|       d}d}d}	 | j
                  j                  t              j                         }t        |      }t         j                  d| d       |D ]  }|dz  }	 | j
                  j                  t              j                  t        j                  |j                  k(        j                         }|r|j                  sp|j                  }	| j                   j#                  |	      }
|
r/t%        |
j'                  d	d            }| j
                  j                  t(              j                  t(        j                  |	k(        j                         }|s't)        |	
      }| j
                  j+                  |       ||_        t        j                  j                         |_        | j
                  j                  t0              j                  t0        j                  |j2                  k(        j                         }|r||_        |j6                  |z
  |_        |j                  r| j                   j;                  t=        |j                              }|rt?        |j'                  dd            }||_         |j'                  d|jB                        |_!        t        j                  j                         |_        | j
                  j                  t0              j                  t0        j                  |j2                  k(        j                         }|r||_         |dz  } | j
                  jI                          | j	                  dd||||       t         j                  d       | jK                          y# tD        $ r5}t         jG                  d|j                   d|        |dz  }Y d}~cd}~ww xY w# tD        $ r]}| j
                  jM                          t         jG                  d|        | j	                  dd|||t=        |      |       Y d}~yd}~ww xY w)z.Syncs stock from Tiny for all linked products.zStarting Tiny Stock Sync...stockr   r   r   zChecking stock for z linked products.rO   saldo)r   preco_custor   nomez Stock/Cost Sync failed for link r   Nr   z3Triggering Variation Costs Sync after Stock Sync...zStock Sync Failed: rf   )'rV   rW   rZ   r[   r   r"   r0   r   r"  r   r   r1   r   tiny_product_idr3   r   r$   	get_stockrL   rA   r   rd   rQ  r   r	   r   
stock_tinyr   stock_divergenceget_product_detailsr   r@   r>   r  re   rf   ra   sync_variation_costsrg   )r*   r   r   r   rf   linksr  link	tiny_prodr   
stock_dataqtyr   r   r   new_coste_stockry   s                     r+   sync_tiny_stockzSyncEngine.sync_tiny_stock  st   12&&**,
w	jA	F	g GGMM*-113EJEKK-eW4EFG 3Q	1 $k : A A+..TXThThBh i o o qI$IMM #--C "&!2!2!<!<S!AJ! "*..!"<= "WW]]95<<Y]]c=QRXXZ!!*s!3B GGKKO&)*2*;*;*?*?*A "WW]]2.55beetzz6IJPPR,/BM242G2G#2MB/ !||"&"3"3"G"GILLHY"Z"(-gkk-.M(NX.6Y^.5kk&)...QY^6>6G6G6K6K6MY3 #'''--"3":":255DJJ;N"O"U"U"WR "+3 qLGa3j GGNNNN7Iy'5U_N` KKMN%%' ! LL#CDGG9Bwi!XYQJE  	gGGLL.qc23NN7GYA[eNff	gsS   AP ,A%OP I O2AP 	P
*P?P P

P 	Q3AQ..Q3r   c                      y N )r*   r   s     r+   _update_visits_metricz SyncEngine._update_visits_metric^  s     	r-   r   r   r  c           	         |j                   r|j                   j                         nd }|s}ddlm} | j                  j                  |      j                  |j                  |j                  k(        j                         }|r&|j                   r|j                   j                         }d }| j                  j                  t              j                  t        j                  |j                  k(        j                         }	|	r| j                  j                  t              j                  t        j                  |	j                  k(        j                         }|sXt        j                  d|j                   d       | j                  j                  |	       | j                  j!                          |s0|r-| j                  j                  t              j                  t        j                   |k(        j                         }|sc|j"                  rW| j                  j                  t              j                  t        j                   |j"                  k(        j                         }|stt        j%                  d|        | j'                  |      }|sI|j"                  r=t        j%                  d|j"                          | j'                  |j"                        }|r	 | j                  j)                         5  | j                  j                  t              j                  t        j                  |j                  k(        j                         }
|
st        |j                  |j                        }| j                  j+                  |       | j                  j!                          t        j%                  d|j                   d	|j                          d d d        |r|j0                  |j0                  |_        | j2                  j5                  |||||       y # 1 sw Y   HxY w# t,        $ r<}t        j/                  d
|j                   d	|j                   d|        Y d }~d }~ww xY w)Nr   r   zOrphan AdTinyLink found for Ad z. removing link.zSyncing from Tiny API for SKU: z Syncing from Tiny API for GTIN: )r   rk  z
Linked Ad z to TinyProduct zFailed to link Ad r   )r   r   app.models.ad_variationr   r"   r0   r1   r   r   r3   r   r   rk  rV   warningr`   flushr   rW   _fetch_and_save_tinybegin_nestedrd   re   rf   r>   r%   calculate_margin)r*   r   r   r   r  r   r   varrs  rr  existing_linknew_linkry   s                r+   r   zSyncEngine._process_ad_costl  s/    "bffllnD;''--,33K4E4E4NOUUWCswwggmmo	 ww}}Z(//
0@0@BEE0IJPPRk299+..DL`L`:`aggiI!@GWXYt$ S{3::;??c;QRXXZY "''"ggmmK8??SUSZSZ@Z[aac) >seDE!66s; "bgg[[#CBGG9!MN!%!:!:277!CY
c''..0 ])-z)B)I)I*JZJZ^`^c^cJc)d)j)j)l -(2PYP\P\(]X!WW[[2!WW]]_#[[:beeW<LY\\N)[\] 3 ~~RW 	//IxUab%] ] " c\\$6ruug=Mill^[]^_]`"abbcs1   &P2  CP&P2 &P/+P2 2	Q7;2Q22Q7r   c                    | j                   j                  |      }|rW|j                  d      }|sy | j                   j                  t	        |            }|s|}|j                  d      }|rt	        |      dk7  rt	        |      t	        |      k7  rt
        j                  d| d| d       | j                   j                  t	        |            }|rv| j                  |       d|v r| j                  |d          | j                  j                  t              j                  t        j                  |k(        j                         S | j                  |      }d|v r| j                  |d          |S y )Nr   id_produto_pai0zSKU z has parent z. Fetching parent & siblings...	variacoes)r$   search_productrA   ro  r   rV   rW   _save_tiny_product_from_data_process_variations_listr"   r0   r   r1   r   r3   )r*   r   p_datatiny_idr   	parent_idparent_detailstps           r+   r  zSyncEngine._fetch_and_save_tiny  sL   ""11#6jj&G '';;CLIG   $45IS^s2s9~W7Ud3%|I;>]^_!%!2!2!F!Fs9~!V!55nE"n455n[6QR  77==5<<[^^w=VW]]__ 227;B g%--gk.BCIr-   r5  c                    t        |j                  d            }| j                  j                  t              j                  t        j                  |k(        j                         }|s't	        |      }| j                  j                  |       |j                  d      |_	        |j                  d      |_
        t        |j                  dd            |_        | j                  j                          |S )Nr   r   codigorj  ri  r   )r   rA   r"   r0   r   r1   r   r3   rd   r   r  r@   r>   r  )r*   r5  t_idr  s       r+   r  z'SyncEngine._save_tiny_product_from_data  s    488D>"WW]];'..{~~/EFLLN%BGGKKO(#((6"23	r-   r   c                 \    |D ]'  }|j                  d      }|s| j                  |       ) y)z
        Process list of variations from Tiny API details.
        Format: [{'variacao': {'id':..., 'codigo':..., ...}}, ...]
        variacaoN)rA   r  )r*   r   	v_wrapperv_datas       r+   r  z#SyncEngine._process_variations_list  s2    
 $ 	:I]]:.F11&9	:r-   c                    t         j                  d       	 | j                  ddt        j                  j	                                | j                          | j                  ddt        j                  j	                                | j                          | j                  ddt        j                  j	                                | j                  j                          | j                  j                          | j                  j                          | j                  ddt        j                  j	                                | j!                          y# t        $ rv}| j                  j                          t         j                  d|        | j                  dd	t        |      t        j                  j	                         
       Y d}~d}~ww xY w)z
        Runs the processing: 
        1. Sync Visits from ML.
        2. Sync Orders from ML.
        3. Process Trends & Aggregations (MetricProcessor).
        4. Recalculate Margins (MarginCalculator).
        z'Starting Metrics & Margin Processing...r  r   r   r   metrics_processingr   zMetrics Processing failed: rf   r   r   N)rV   rW   r   rZ   r[   r?  rC  r'   aggregate_sales_metricsaggregate_daily_salesprocess_allre   r"   rg   rf   r   sync_margins)r*   ry   s     r+   sync_metricszSyncEngine.sync_metrics  se    	=>	jNN8Y8;L;L;P;P;RNS NN8Y8;L;L;P;P;RNS NN/xGXGXG\G\G^N_ !!99;!!779 !!--/NN/xGXGXG\G\G^N_ 	  	jGGLL6qc:;NN/c!fQYQbQbQfQfQhNii	js   D.E 	GA,GGc           	         t         j                  d       t        j                  j                         }	 ddlm}  || j                        }|j                          | j                         }| j                  j                  t              j                         }| j                  j                  t              j                  t        t        j                  dk(  t        j                   dk(              j#                         }|r!|j$                  rt'        |j$                        nd}| j                  j                  t              j                  t        j                   dk(        j#                         }|r!|j$                  rt'        |j$                        nd	}	t)        |      }
t         j                  d
|
 d| d|	 d       d}|D ]>  }	 | j+                  |||	       |dz  }|dz  dk(  s%| j                  j3                          @ | j                  j3                          t         j                  d       | j5                  dd|
||       y# t,        $ r/}t         j/                  d|j0                   d|        Y d}~d}~ww xY w# t,        $ rZ}| j                  j7                          t         j/                  d|        | j5                  ddt9        |      |       Y d}~yd}~ww xY w)z
        Recalculates margins and taxes for all active ads.
        Indepedent step to ensure tax updates even if metrics fail.
        zStarting Margin Processing...r   r   r   geralr   g      )@fixed_packaging_costr   zRecalculating margins for z active ads (Tax: z
%, Fixed: r}   rO   zAd z calc failed: Nd   zMargin Processing completed.marginsr   )r   r   r   zMargin Processing failed: rf   r  )rV   rW   rZ   r[   r   r   r"   r   r7   r0   r	   r"  r   r1   r   groupr   r3   r   r@   r   r   re   rf   r   ra   r   rg   r   )r*   r   r   tax_servicer   r   
tax_configr   fixed_pkg_config	fixed_pkgr  idxr   e_adry   s                  r+   r  zSyncEngine.sync_margins  sh   
 	34&&**,
+	R;$8K ..0**,I''--#'')C |4;;\''72L4D4DHZ4Z[eg 
 3=AQAQuZ--.W[H#ww}}\:AA,BRBRVlBlmssu9IN^NdNd.445jmIHEKK4UG;MhZWabkallpqrC %D))"h	B1HC 9>GGNN$% GGNNKK67NN9i5#ZdNe ! DLL3ruug^D6!BCCD  	RGGLL5aS9:NN9g3q6jNQQ	RsJ   FJ
 I$J
 -A!J
 	J%J=J
 JJ
 
	K-AK((K-c                      y rz  r{  rB  s    r+   sync_ads_spendzSyncEngine.sync_ads_spendH  s    r-   c           	         t         j                  d       | j                  ddt        j                  j	                                	 ddlm} ddlm} | j                  j                   ||j                              j                  |j                  dk7        j                         }|D cg c]  }|d   s	|d    }}t         j                  d	t        |       d
       d}d}d}|D ]y  }| j                  j                  t              j                  t        j                  |k(        j!                         }|r!|j"                  r|j"                  dkD  r|dz  }t	 | j$                  j'                  |      }	|	r|	j)                  d      rt+        |	j)                  dd      xs d      }
|r)|
|_        |	j)                  d|j,                        |_        n`t        t/        |	j)                  d            |	j)                  d      |	j)                  d      |
      }| j                  j1                  |       |dz  }|dz  dk(  r | j                  j3                          n|dz  }| | j                  j3                          t         j                  d| d| d| d       | j                  ddt        j                  j	                                yc c}w # t4        $ r+}t         j7                  d| d|        |dz  }Y d}~d}~ww xY w# t4        $ rv}| j                  j9                          t         j;                  d|        | j                  ddt/        |      t        j                  j	                                Y d}~yd}~ww xY w)z
        Sync costs for all unique SKUs from order items.
        For each SKU not already in TinyProduct (or with cost=0), 
        fetches from Tiny API and saves to database.
        Called by sync_tiny_stock and general sync.
        z Starting Variation Costs Sync...variation_costsr   r   r   )distinct)r   Nr   z unique SKUs in order itemsrO   r   ri  rj  r  )r   r   r  r>   r   zError syncing SKU r   zVariation Costs Sync complete: z	 synced, z
 skipped, z errorsr   zVariation Costs Sync failed: rf   r  )rV   rW   r   rZ   r[   r   r  app.models.ml_orderr   r"   r0   r   r1   r"  r   r   r3   r>   r$   r  rA   r@   r  r   rd   ra   re   r  rg   rf   )r*   r  r   all_skusr   syncedskippederrorsexistingr  r>   new_tpry   s                r+   rp  zSyncEngine.sync_variation_costsK  s    	67()@Q@Q@U@U@WX9	g+7 ww}}Xkoo%>?FF{Z^G^_cceH*2=3c!fA=H=KK&X/JKLFGF " 77==5<<[__PS=STZZ\(--!2CqLG !..==cBF&**T"2$VZZq%A%FQG#,0HM,2JJvx}},MHM%0#&vzz$'7#8$*JJx$8%+ZZ%7%)	&F !GGKK/! "B;!+ GGNN,!?" H GGNNKK9&7)S]^d]eelmnNN,iHDUDUDYDYD[N\] >P !  NN%7uBqc#BCaKF   	gGGLL8<=NN,g3q6hN_N_NcNcNeNff	gs_   A%L ,
K7K>B L DK$A,L L 	L
 L?L L

L 	NA,NNrz  )r   r   r   NNN)r   ) __name__
__module____qualname__r,   r7   rz   rL   r   r   r   r   r   r   r   r$  r   r  r?  rC  re  rx  r	   r|  r@   r   r  r  r  r  r  r  rp  r{  r-   r+   r   r   "   s   
;%:xPc P)$# $s $L*|XlED lES lE\> >d >4JhXFd FPQgf @c2 @c @cE @cY^ @cD& &P :4 :%N2RhCgr-   r   )6loggingrZ   rY   concurrent.futuresr&  r   r   sqlalchemy.ormr   app.core.configr   app.core.databaser   app.services.meli_apir   app.services.tiny_apir   app.models.adr	   app.models.metricr
   app.models.oauth_tokenr   app.models.saler   r   r   app.models.tiny_productr   app.models.ad_tiny_linkr   r~  r   app.services.margin_calculatorr   app.models.syncr   !app.services.sync_v2.initial_loadr    app.services.sync_v2.incrementalr   	getLoggerr  rV   app.models.ml_visitr   r  r   r   app.models.tiny_stockr   app.models.ml_metrics_dailyr   r   r{  r-   r+   <module>r     sy          " $ * 0 0  $ -   1 / . / / B ' @ C			8	$ ' 4 + 6lg lgr-   