o
    zi;                     @   sd  d dl mZ d dlZd dlZd dlZd dlZd dlmZmZmZ d dl	m
Z
 d dlZd dlmZ ddlmZmZmZmZmZ ddlmZmZ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#m$Z$ ddl%m&Z&m'Z'm(Z( ddl)m*Z*m+Z+ ddl,m-Z-m.Z. ee/Z0e
  dZ1ej23ej24e5dZ6dZ7dZ8dZ9dZ:dZ;dd Z<dd Z=ej>dddd Z?dS )    )	getLoggerN)datetimetimezone	timedelta)load_dotenv)
celery_app   ) create_deals_table_if_not_existssanitize_col_nameload_watermarksave_watermarkDB_PATH)fetch_deals_for_dealsfetch_product_batchvalidate_asin)TokenManager)FUNCTION_LIST)get_seller_info_for_single_deal)load_settingscalculate_all_in_costcalculate_profit_and_margincalculate_min_listing_price)get_1yr_avg_sale_priceget_percent_discount	get_trend)classify_seasonalityget_sells_period)_process_single_dealclean_numeric_valuesdealszheaders.json
   update_recent_deals_locki  2      c                 C   s(   t dddtjd}|t| d }| S )zFConverts Keepa time (minutes since 2011-01-01) to ISO 8601 UTC string.  r   tzinfo)minutes)r   r   utcr   	isoformat)keepa_minuteskeepa_epoch	dt_object r-   2/var/www/agentarbitrage/keepa_deals/simple_task.py_convert_keepa_time_to_iso/   s   r/   c                 C   sD   | sdS t | tj}t dddtjd}|| }t| d S )zIConverts an ISO 8601 UTC string to Keepa time (minutes since 2011-01-01).r   r$   r   r%   <   )r   fromisoformat
astimezoner   r(   inttotal_seconds)iso_strr,   r+   deltar-   r-   r.   _convert_iso_to_keepa_time5   s   r7   z+keepa_deals.simple_task.update_recent_deals)namec            2         s8  t jtjj} | jttd}|j	ddst
d d S zt
d t  td}td}|sCt
d W |  t
d	 d S t|}|  t }t
d
 |dsnt
d|j d W |  t
d	 d S t }|d u rt
d W |  t
d	 d S t|}t
d| d| d d}g }	d}
d}d}t
d 	 |
tkrt
dt d n&t|	tkrt
dt|	 d d}n|dst
d|j d d}nd}t
d| d|
  d }d}t|D ]S}z"t|
|||d\}}}|d ur	|| |rd |v rW  n1W q tyD } z"t
d!|
 d"|d#  d$| d%|  t !d&|d#   W Y d }~qd }~ww |rMd |vri|
dkrct
d' W |  t
d	 d S t
d( nr|d  d) svt
d* ned+d, |d  d) D }|
dkr|r|d "d-d}d}|D ].}|d- |krt
d.|"d/ d0|d-  d1| d2||d-   d3	 d} n|	#| q|rt
d4|
 d5 n
|
d#7 }
t !d# q|	st
d6 W |  t
d	 d S t
d7t|	 d8 t
d9 i }d:d, |	D }tdt|t$D ]L}|||t$  }d;t| }|%| t&||d<d#d;d=\}}}}|| |rVd>|v rV|rH|"d?sV|d> D ]	}|||d/ < qLt !d@ qt
dAt| dB t
dC t't(}t)*|} W d    n	1 sw   Y  g }!|	D ]=}|d/ }"|"|vrq||" }#|#+| t,|#||}$t-|#|$|}%|%rt.|%}%t/0t1j23 |%dD< dE|%dF< |!#|% qt
dGt|! dH |!st
dI W |  t
d	 d S t
dJt|! dK zt45t6}&|&7 }'dLd, | D }(|(8dDdFg g })|!D ] t9 fdMdN| D  "dD "dFf }*|)#|* qdO:dPdN |(D }+dO:dQgt|( },dO:dRdN |(D }-dSt; dT|+ dU|, dV|- }.|'<|.|) |&=  t
dW|'j> dX dYd, |!D }/|/rtj?dZ|/gd[ t
d\t|/ d] W d    n	1 sw   Y  W n: t4j@y } zt
jd^| dd_ W Y d }~n!d }~w ty } zt
jd`| dd_ W Y d }~nd }~ww | p|}0|0r||krtA|}1tB|1 t
da|1  n|r|st
db t
dc W |  t
d	 d S |  t
d	 w )dN)timeoutF)blockingzI--- Task: update_recent_deals is already running. Skipping execution. ---z)--- Task: update_recent_deals started ---KEEPA_API_KEY	XAI_TOKENz KEEPA_API_KEY not set. Aborting.z=--- Task: update_recent_deals finished and lock released. ---z"Step 1: Initializing Delta Sync...   zUpserter: Low tokens (z ). Skipping run to allow refill.zfCRITICAL: Watermark not found. The backfiller must be run at least once before the upserter. Aborting.zLoaded watermark: z (Keepa time: )r   z4Step 2: Paginating through deals to find new ones...Tz/Safety Limit Reached: Stopped pagination after z pages to prevent runaway task.zNew Deal Limit Reached: Found zI new deals. Stopping fetch to process current batch and update watermark.zLow tokens during pagination (z). Stopping fetch loop.   z Fetching deals using Sort Type: z (Last Update). Page:    )	sort_typetoken_managerr   zFetch failed on page z
 (Attempt r   /z):    zMFailed to fetch Page 0 after retries. Aborting task to prevent partial state.z5Failed to fetch subsequent page. Stopping pagination.drz6No more deals found (empty list). Stopping pagination.c                 S   s   g | ]}t |d r|qS asin)r   get.0dr-   r-   r.   
<listcomp>   s    z'update_recent_deals.<locals>.<listcomp>
lastUpdatezStop Trigger: Deal rG   z
 (Update: z) <= Watermark (z	). Diff: z min.z.Found a deal older than the watermark on page z. Stopping pagination.z7Step 2 Complete: No new deals found since the last run.zStep 2 Complete: Found z new deals.z.Step 3: Fetching product data for new deals...c                 S   s   g | ]}|d  qS rF   r-   rI   r-   r-   r.   rL             iG  )dayshistoryoffersproductserror_status_code   z*Step 3 Complete: Fetched product data for z ASINs.zStep 4: Processing deals...last_seen_utcupsertersourcezStep 5 Complete: Processed z deals.z!No rows to upsert. Task finished.zStep 6: Upserting z rows into database...c                 S   s   g | ]}t |qS r-   )r
   rJ   hr-   r-   r.   rL     rN   c                 3   s    | ]}  |V  qd S )N)rH   rY   row_dictr-   r.   	<genexpr>  s    z&update_recent_deals.<locals>.<genexpr>z, c                 s   s    | ]	}d | d V  qdS )"Nr-   rY   r-   r-   r.   r]     s    ?c                 s   s*    | ]}|d krd| d| dV  qdS )ASINr^   z"=excluded."Nr-   rY   r-   r-   r.   r]     s   ( zINSERT INTO z (z
) VALUES (z") ON CONFLICT(ASIN) DO UPDATE SET z/Step 6 Complete: Successfully upserted/updated z rows.c                 S   s   g | ]
}d |v r|d  qS )r`   r-   )rJ   rowr-   r-   r.   rL     s    z4keepa_deals.sp_api_tasks.check_restriction_for_asins)argsz$--- Triggered restriction check for z new ASINs from upserter. ---z-Step 6 Failed: Database error during upsert: )exc_infoz/Step 6 Failed: Unexpected error during upsert: z"Successfully updated watermark to zXTask was incomplete due to token limits. Skipping watermark update to prevent data loss.z*--- Task: update_recent_deals finished ---)CredisRedisfrom_urlceleryconf
broker_urllockLOCK_KEYLOCK_TIMEOUTacquireloggerinfor	   osgetenverrorreleaser   sync_tokensbusiness_load_settingshas_enough_tokenswarningtokensr   r7   MAX_PAGES_PER_RUNlenMAX_NEW_DEALS_PER_RUNranger   update_after_call	ExceptiontimesleeprH   appendMAX_ASINS_PER_BATCHrequest_permission_for_callr   openHEADERS_PATHjsonloadupdater   r   r   r   nowr   r(   r)   sqlite3connectr   cursorextendtuplejoin
TABLE_NAMEexecutemanycommitrowcount	send_taskErrorr/   r   )2redis_clientrj   api_keyxai_api_keyrB   business_settingswatermark_isowatermark_keepa_timenewest_deal_timestampall_new_dealspageincomplete_runhit_new_deal_limitSORT_TYPE_LAST_UPDATEdeal_responsemax_page_retriesattempttokens_consumedtokens_leftedeals_on_pagefound_older_dealdealall_fetched_products	asin_listibatch_asinsestimated_costproduct_responseapi_infopfheadersrows_to_upsertrG   product_dataseller_data_cacheprocessed_rowconnr   sanitized_headersdata_for_upsert	row_tuplecols_strvals_str
update_str
upsert_sql	new_asinsshould_update_watermarknew_watermark_isor-   r[   r.   update_recent_deals?   s  




 _ 

 N 
 I 



&

  

6
H
r



"





3*  	
r   )@loggingr   rp   r   r   r   r   r   r   dotenvr   rd   workerr   rg   db_utilsr	   r
   r   r   r   	keepa_apir   r   r   rB   r   field_mappingsr   seller_infor   business_calculationsr   ru   r   r   r   new_analyticsr   r   r   seasonality_classifierr   r   
processingr   r   __name__rn   r   pathr   dirname__file__r   r   rk   rl   ry   r{   r/   r7   taskr   r-   r-   r-   r.   <module>   s>    

