
    gi?                        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!m"Z"m#Z#m$Z$m%Z%m&Z&m'Z' d dl(m)Z)  e jT                  e jV                  d       dD ]-  Z, e jZ                  e,      j]                  e jV                         /  e jZ                  e/      Z0defdZ1 e1       Z2y)    N)FastAPI)CORSMiddleware)delete)text)SQLAlchemyError)router)Base)engine)utcnow)PasswordResetToken)UserRefreshTokenVendor	ViolationProductScrapingResultSiteSettings)SchedulerServicez4%(asctime)s - %(name)s - %(levelname)s - %(message)s)levelformat)appzapp.serviceszapp.apireturnc                     t        d      } | j                  t        ddgdddgdg       | j                  d	      dd
       }| j                  d	      dd       }| j                  d      dd       }| j	                  t
        ddg       | j	                  t        dg       | j	                  t        ddg       | j	                  t        ddg       | j	                  t        ddg       | j	                  t               | S )NzMARCO Scraping)titlez#https://marco-fe.testyourapp.onlinezhttps://sncp.esz,^https?:\/\/(localhost|127\.0\.0\.1)(:\d+)?$T*)allow_originsallow_origin_regexallow_credentialsallow_methodsallow_headersstartupc            	        K   	 t        j                         4 d {   } | j                  t        j                  j
                         d {    | j                  t        d             d {    | j                  t        t              j                  t        j                  t               k  t        j                  j                  d       z               d {    | j                  t        d             d {    | j                  t        d             d {    | j                  t        d             d {    | j                  t        d             d {    | j                  t        d             d {    | j                  t        d             d {    | j                  t        d             d {    | j                  t        d	             d {    | j                  t        d
             d {    | j                  t        d             d {    | j                  t        d             d {    | j                  t        d             d {    | j                  t        d             d {    | j                  t        d             d {    | j                  t        d             d {    | j                  t        d             d {    | j                  t        d             d {    | j                  t        d             d {    | j                  t        d             d {    | j                  t        d             d {    | j                  t        d             d {    | j                  t        d             d {    | j                  t        d             d {    | j                  t        d             d {    | j                  t        d             d {    | j                  t        d             d {    | j                  t        d             d {    | j                  t        d             d {    | j                  t        d             d {    | j                  t        d             d {    | j                  t        d              d {    | j                  t        d!             d {    | j                  t        d"             d {    | j                  t        d#             d {    | j                  t        d$             d {    | j                  t        d%             d {    | j                  t        d&             d {    | j                  t        d'             d {    | j                  t        d(             d {    | j                  t        d)             d {    | j                  t        d*             d {    | j                  t        d+             d {    | j                  t        d,             d {    | j                  t        d-             d {    | j                  t        d.             d {    | j                  t        d/             d {    d d d       d {    y 7 7 7 7 ;7 7 7 7 7 7 7 b7 C7 $7 7 7 7 7 7 j7 K7 ,7 7 7 7 7 7 r7 S7 47 7 7 7 7 7 z7 [7 <7 7 7 7 7 7 7 c7 D7 %7 7 7 7 7 # 1 d {  7  sw Y   y xY w# t        $ r}t!        d0      |d }~ww xY ww)1NzQALTER TABLE users ADD COLUMN IF NOT EXISTS tokens_invalid_before TIMESTAMPTZ NULLzLALTER TABLE violations ADD COLUMN IF NOT EXISTS barcode_number VARCHAR(255);zJALTER TABLE violations ADD COLUMN IF NOT EXISTS reference_id VARCHAR(255);zIALTER TABLE violations ADD COLUMN IF NOT EXISTS confidence_score INTEGER;zMALTER TABLE violations ADD COLUMN IF NOT EXISTS confidence_label VARCHAR(20);zUALTER TABLE violations ADD COLUMN IF NOT EXISTS confirmation_count INTEGER DEFAULT 1;z]ALTER TABLE violations ADD COLUMN IF NOT EXISTS source_type VARCHAR(50) DEFAULT 'registered';zUALTER TABLE violations ADD COLUMN IF NOT EXISTS last_confirmed_date TIMESTAMPTZ NULL;zVALTER TABLE violations ADD COLUMN IF NOT EXISTS notification_sent_at TIMESTAMPTZ NULL;zIALTER TABLE violations ADD COLUMN IF NOT EXISTS vendor_name VARCHAR(512);zIALTER TABLE violations ADD COLUMN IF NOT EXISTS marketplace VARCHAR(255);z<ALTER TABLE violations ALTER COLUMN vendor_id DROP NOT NULL;zBALTER TABLE scraping_results ALTER COLUMN vendor_id DROP NOT NULL;zIALTER TABLE violations ADD COLUMN IF NOT EXISTS price_difference NUMERIC;zNALTER TABLE violations ADD COLUMN IF NOT EXISTS percentage_difference NUMERIC;zTALTER TABLE products ADD COLUMN IF NOT EXISTS price_1_pack NUMERIC(10, 2) DEFAULT 0;zTALTER TABLE products ADD COLUMN IF NOT EXISTS price_2_pack NUMERIC(10, 2) DEFAULT 0;zTALTER TABLE products ADD COLUMN IF NOT EXISTS price_3_pack NUMERIC(10, 2) DEFAULT 0;zTALTER TABLE products ADD COLUMN IF NOT EXISTS price_4_pack NUMERIC(10, 2) DEFAULT 0;zTALTER TABLE products ADD COLUMN IF NOT EXISTS price_5_pack NUMERIC(10, 2) DEFAULT 0;zTALTER TABLE products ADD COLUMN IF NOT EXISTS price_6_pack NUMERIC(10, 2) DEFAULT 0;zUALTER TABLE products ADD COLUMN IF NOT EXISTS price_12_pack NUMERIC(10, 2) DEFAULT 0;zHALTER TABLE violations ADD COLUMN IF NOT EXISTS packs INTEGER DEFAULT 1;zQALTER TABLE products ADD COLUMN IF NOT EXISTS last_scraped_date TIMESTAMPTZ NULL;zOALTER TABLE products ADD COLUMN IF NOT EXISTS last_execution_time VARCHAR(255);zYALTER TABLE products ADD COLUMN IF NOT EXISTS scraping_status VARCHAR(50) DEFAULT 'idle';zSALTER TABLE products ADD COLUMN IF NOT EXISTS scraping_started_at TIMESTAMPTZ NULL;zUALTER TABLE products ADD COLUMN IF NOT EXISTS scraping_completed_at TIMESTAMPTZ NULL;zOALTER TABLE products ADD COLUMN IF NOT EXISTS scraping_error VARCHAR(500) NULL;zOALTER TABLE scraping_results ADD COLUMN IF NOT EXISTS domain_name VARCHAR(255);zZALTER TABLE site_settings ADD COLUMN IF NOT EXISTS scraping_enabled BOOLEAN DEFAULT FALSE;zbALTER TABLE site_settings ADD COLUMN IF NOT EXISTS scraping_frequency VARCHAR(50) DEFAULT 'daily';z\ALTER TABLE site_settings ADD COLUMN IF NOT EXISTS scraping_time VARCHAR(5) DEFAULT '02:00';zCALTER TABLE site_settings ALTER COLUMN scraping_time DROP NOT NULL;zeALTER TABLE site_settings ADD COLUMN IF NOT EXISTS scraping_day_of_week VARCHAR(50) DEFAULT 'monday';zZALTER TABLE site_settings ADD COLUMN IF NOT EXISTS scraping_custom_cron VARCHAR(255) NULL;zYALTER TABLE site_settings ADD COLUMN IF NOT EXISTS enable_discovery BOOLEAN DEFAULT TRUE;zVALTER TABLE site_settings ADD COLUMN IF NOT EXISTS headless_mode BOOLEAN DEFAULT TRUE;zVALTER TABLE site_settings ADD COLUMN IF NOT EXISTS timeout_seconds INTEGER DEFAULT 15;zWALTER TABLE site_settings ADD COLUMN IF NOT EXISTS last_scheduled_run TIMESTAMPTZ NULL;z^ALTER TABLE site_settings ADD COLUMN IF NOT EXISTS last_scheduled_run_status VARCHAR(50) NULL;z`ALTER TABLE site_settings ADD COLUMN IF NOT EXISTS last_scheduled_run_summary VARCHAR(500) NULL;z]ALTER TABLE site_settings ADD COLUMN IF NOT EXISTS client_timezone VARCHAR(50) DEFAULT 'UTC';zCALTER TABLE violations ADD COLUMN IF NOT EXISTS product_id INTEGER;a  
                        DO $$
                        BEGIN
                            IF NOT EXISTS (
                                SELECT 1 FROM information_schema.table_constraints 
                                WHERE table_name = 'violations' 
                                AND constraint_name = 'fk_violations_product_id'
                            ) THEN
                                ALTER TABLE violations 
                                ADD CONSTRAINT fk_violations_product_id 
                                FOREIGN KEY (product_id) REFERENCES products(id) ON DELETE CASCADE;
                            END IF;
                        END $$;
                        zOCREATE INDEX IF NOT EXISTS idx_violations_product_id ON violations(product_id);aA  
                        UPDATE violations v
                        SET product_id = p.id
                        FROM products p
                        WHERE v.product_id IS NULL
                        AND v.barcode_number IS NOT NULL
                        AND p.barcode = v.barcode_number;
                        zDatabase connection failed during startup. Check DATABASE_URL in .env (username/password/host/port/db) and ensure Postgres is running.)r
   beginrun_syncr	   metadata
create_allexecuter   r   r   where
expires_atr   used_atis_notr   RuntimeError)connes     ./var/www/html/marco-python-backend/app/main.py_create_tablesz"create_app.<locals>._create_tablesB   s    R	||~ L LmmDMM$<$<===llZ   ll-.44+66&(B-55<<TBD   llfh   lldf  
 llde   llhi   lloq   llwy   lloq   llpr   llce   llce  
 llV  
 ll\   llce   llhj   lln  
 lln  
 lln  
 lln  
 lln  
 lln  
 llo   llb   llkm  
 llik  
 lls   llm   llo   lli   llik  
 llt  
 ll|  
 llv   ll]  
 ll  
 llt  
 lls  
 llp  
 llp  
 llq  
 llx  
 llz  
 llw   ll]   ll  & lli   ll	  CL L L=






















&CL L L LZ  	n 	s  _^9 \^9 -^$\!^$/\0A-^$\!^$?\ !^$!\"!^$\!!^$%\$&!^$\'!^$)\**!^$\-!^$-\0.!^$\3!^$1\62!^$\9!^$5\<6!^$\?!^$9]:!^$]!^$=]>!^$] !^$]!^$#]$!^$]!^$'](!^$	]
!^$+],!^$] !^$/]#0!^$]&!^$3])4!^$],!^$7]/8!^$]2!^$;]5<!^$]8!^$?]; !^$!]>"!^$^!^$%^&!^$^!^$)^
*!^$^!^$-^.!^$^!^$1^2!^$^!^$5^6!^$^!^$9^ :^$>^9 	^"
^9 _^9 ^$^$^$^$^$!^$$^$'^$*^$-^$0^$3^$6^$9^$<^$?^$^$^$^$^$^$^$^$^$^$^$ ^$#^$&^$)^$,^$/^$2^$5^$8^$;^$>^$^$^$^$
^$^$^$^$^$^$^$^$ ^$"^9 $^6*^-+^62^9 5_6^9 9	____c                    K   t        j                  dd      j                         dv } | st        j	                  d       y	 t        j	                  d       t        j	                  d       t        j	                  d       t        j                          d{    y7 # t        $ r-}t        j                  d	t        |       d
       Y d}~yd}~ww xY ww)zGStart the scheduler when the app starts (only if ENABLE_SCHEDULER=true)ENABLE_SCHEDULERfalse)true1yesuH   [Scheduler] ⊘ Scheduler disabled (set ENABLE_SCHEDULER=true to enable)NzQ
================================================================================u5   🚀 [Scheduler] Starting scheduler at app startup...zP================================================================================u+   ❌ [Scheduler] Failed to start scheduler: T)exc_info)
osgetenvlowerloggerinfor   start_scheduler	Exceptionerrorstr)enable_schedulerr.   s     r/   _start_schedulerz$create_app.<locals>._start_schedulerX  s     
 99%7AGGIMaaKKbc	`KK&KKOPKK"22444 	`LLFs1vhOZ^L__	`sB   ?CAB  BB  CB   	C)#CCCCshutdownc                     K   	 t        j                          d{    y7 # t        $ r+} t        j	                  dt        |               Y d} ~ yd} ~ ww xY ww)z*Stop the scheduler when the app shuts downNu-   ⚠️ [Scheduler] Error stopping scheduler: )r   stop_schedulerr>   r;   r?   r@   )r.   s    r/   _stop_schedulerz#create_app.<locals>._stop_schedulerl  sJ     	S"11333 	SLLHQQRR	Ss6   A# !# A# 	A!AAAAz/authauth)prefixtagsvendors)rI   z/api/productsproductsz/api/violations
violationsz/api	dashboard)r   N)r   add_middlewarer   on_eventinclude_routerauth_routervendor_routerproduct_routerviolations_routerdashboard_routeradmin_settings_router)r   r0   rB   rF   s       r/   
create_apprW   +   s+   
(
)C - G%%  
 	\\)S Sj 	\\)` `& 	\\*S S {7&B}I;7~oZLQ(1B,X'k]K,-J    )3loggingr8   fastapir   fastapi.middleware.corsr   
sqlalchemyr   r   sqlalchemy.excr   app.api.routes.productsr   rS   app.api.routes.authrQ   app.api.routes.vendorsrR   app.api.routes.violationsrT   app.api.routes.dashboardrU   app.api.routes.admin_settingsrV   app.db.baser	   app.db.sessionr
   app.core.securityr   app.models.password_reset_tokenr   
app.modelsr   r   r   r   r   r   r   app.services.scheduler_servicer   basicConfigINFOlogger_name	getLoggersetLevel__name__r;   rW   r    rX   r/   <module>rq      s     	  2   * < 5 : A ? I  ! $ > c c c ;   
,,A
 6 :KGk"++GLL9: 
		8	$OG Ob
 lrX   