
    h0A              
          d dl m Z mZ d dlZd dlZd dlmZmZ d dlmZ d dl	m
Z
mZ d dlmZ d dlZd dlmZ d dlmZ d d	lmZ  e         ej*                  d
d      Z e ej*                  dd            Z ej*                  dd      Z ej*                  dd      Z ej*                  dd      Z edgd      Z e       Zej=                  edgdg ddg        ej>                  ddeeeeed      Z d Z!d  Z"d! Z# G d" d#e
      Z$ G d$ d%e
      Z% G d& d'e
      Z& G d( d)e
      Z' G d* d+e
      Z(ejS                  d,      d-        Z*ejW                  d.      d/        Z,ej[                  d0e%1      d2e$fd3       Z.ej[                  d4      d2e&fd5       Z/ej[                  d6      d2e'fd7       Z0ejW                  d8      d9        Z1ejW                  d:      d;efd<       Z2ej[                  d8      d=e(fd>       Z3eji                  d:      d;ed=e(fd?       Z5ejm                  d:      d;efd@       Z7ejW                  dA      dB        Z8e9dCk(  r2d dl:Z: e:jv                  dDdE e ej*                  dFdG            dH       yy)I    )datetime	timedeltaN)FastAPIHTTPException)CORSMiddleware)	BaseModelEmailStr)CryptContext)pooling)Optional)load_dotenvDB_HOST	localhostDB_PORT3306DB_USERrootDB_PASSWORD DB_NAMEbullseye_dbbcryptauto)schemes
deprecatedzhttps://bullseye.mysouth.ioT)GETPOSTPUTDELETEOPTIONS*)allow_originsallow_credentialsallow_methodsallow_headersbe_pool   )	pool_name	pool_sizehostportuserpassworddatabase
autocommitc                  *    t         j                         S N)connection_poolget_connection     (/home/bogus/BullsEye/backend/app/main.pyr3   r3   1   s    ))++r5   c                     t               } 	 | j                         }|j                  d       |j                         s|j                  d       n$	 |j                  d       	 |j                  d       |j                  d       |j                         s|j                  d       ddd	d
dddddddddddddddddddddddd d!d
d"d#ddddd$d%dg}|D ]D  }|j                  d&|d'   |d(   |d)   |d*   |d+   |d,   |d-   |d.   |d/   |d0   |d1   |d2   f       F | j                          y # t        $ r Y w xY w# t        $ r Y w xY w# | j                          w xY w)3NzSHOW TABLES LIKE 'users'a   
                CREATE TABLE users (
                    id INT AUTO_INCREMENT PRIMARY KEY,
                    username VARCHAR(64) NOT NULL UNIQUE,
                    email VARCHAR(255) DEFAULT NULL UNIQUE,
                    password_hash VARCHAR(255) NOT NULL,
                    role ENUM('customer','partner','staff','admin','office') NOT NULL DEFAULT 'customer',
                    customer_id INT DEFAULT NULL,
                    partner_id INT DEFAULT NULL,
                    created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
                    last_login DATETIME DEFAULT NULL,
                    password_reset_token VARCHAR(100) DEFAULT NULL,
                    password_reset_expires DATETIME DEFAULT NULL
                ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
                zYALTER TABLE users ADD COLUMN IF NOT EXISTS password_reset_token VARCHAR(100) DEFAULT NULLzWALTER TABLE users ADD COLUMN IF NOT EXISTS password_reset_expires DATETIME DEFAULT NULLz"SHOW TABLES LIKE 'customer_orders'a<  
                CREATE TABLE customer_orders (
                    id INT AUTO_INCREMENT PRIMARY KEY,
                    orderUniqueNumber VARCHAR(50) NOT NULL UNIQUE,
                    relatedQuoteNumber VARCHAR(50),
                    relatedInvoiceNumber VARCHAR(50),
                    orderType ENUM('Export', 'Local') NOT NULL,
                    processingType ENUM('Fully Processed', 'Dip & Pack', 'Fully Processed + D&P', 'Other') NOT NULL,
                    customerName VARCHAR(255) NOT NULL,
                    orderDelivery ENUM('Shipping Partner', 'Customer Collect') NOT NULL,
                    depositReceived VARCHAR(100),
                    instructionsFinalised ENUM('Yes', 'No') NOT NULL,
                    orderPaidInFull VARCHAR(100),
                    officeNotes TEXT,
                    date DATE NOT NULL,
                    created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
                    updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
                ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
                zSO-1001zQ-501zINV-9001ExportzFully ProcessedzJohn DoezShipping PartnerzYes - 01-06-2024NozAwaiting collection preferencez
2024-05-01)orderUniqueNumberrelatedQuoteNumberrelatedInvoiceNumber	orderTypeprocessingTypecustomerNameorderDeliverydepositReceivedinstructionsFinalisedorderPaidInFullofficeNotesdatezSO-1002zQ-502zINV-9002Localz
Dip & Packz
Jane SmithzCustomer CollectzYes - 15-06-2024YeszYes - 30-06-2024zPaid and readyz
2024-06-10zSO-1003zQ-503zINV-9003zFully Processed + D&PzRobert BrownzPending depositz
2024-06-20a  
                    INSERT INTO customer_orders (
                        orderUniqueNumber, relatedQuoteNumber, relatedInvoiceNumber, orderType,
                        processingType, customerName, orderDelivery, depositReceived,
                        instructionsFinalised, orderPaidInFull, officeNotes, date
                    ) VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)
                    r:   r;   r<   r=   r>   r?   r@   rA   rB   rC   rD   rE   )r3   cursorexecutefetchone	Exceptionclose)conncursample_ordersorders       r6   ensure_schemarQ   5   s   D{kkm./||~KK&wxuv
 	89||~KK2 *3*1,6!)&7$.%7'9-1'+#C( *3*1,6!(&2$0%7'9-2'9#3( *3*1,6!)&=$2%7'+-1'+#4(;+MZ '  12E:N4OQVWmQnk*E2B,CU>EZo.6G0H%PgJh/0%2Ff	" 	

A    x 	

sO   AE	 D+ "D: 3B'E	 +	D74E	 6D77E	 :	EE	 EE	 	Ec                  V   t               } 	 | j                         }d}d}t        j                  d      }|j	                  d|f       |j                         }|r|j	                  d|||f       n|j	                  d|||f       | j                          y# | j                          w xY w)z6Seed or update the default admin user in the database.adminzadmin@localhostz	Admin@123z(SELECT id FROM users WHERE username = %sz\UPDATE users SET password_hash=%s, role='admin', email=COALESCE(email, %s) WHERE username=%szUINSERT INTO users (username, email, password_hash, role) VALUES (%s, %s, %s, 'admin')N)r3   rH   pwd_contexthashrI   rJ   rL   )rM   rN   admin_usernameadmin_email
admin_hashrows         r6   ensure_admin_userrZ      s    Dkkm ' %%k2
>@QRllnKKn[.9
 KKgj9
 	



s   A9B B(c                   "    e Zd ZU eed<   eed<   y)LoginRequest
identifierr-   N__name__
__module____qualname__str__annotations__r4   r5   r6   r\   r\      s    OMr5   r\   c                   ,    e Zd ZU eed<   dZedz  ed<   y)LoginResponsemessageNcustomer_id)r_   r`   ra   rb   rc   rg   intr4   r5   r6   re   re      s    L"Kt"r5   re   c                       e Zd ZU eed<   y)ForgotPasswordRequestemailN)r_   r`   ra   r	   rc   r4   r5   r6   rj   rj      s    Or5   rj   c                   "    e Zd ZU eed<   eed<   y)ResetPasswordRequesttokennew_passwordNr^   r4   r5   r6   rm   rm      s    Jr5   rm   c                       e Zd ZU dZee   ed<   eed<   eed<   eed<   eed<   eed<   eed<   eed	<   eed
<   eed<   eed<   eed<   eed<   dZee   ed<   dZ	ee   ed<   y)OrderRecordNidr:   r;   r<   r=   r>   r?   r@   rA   rB   rC   rD   rE   
created_at
updated_at)
r_   r`   ra   rr   r   rh   rc   rb   rs   rt   r4   r5   r6   rq   rq      sr    BN
I $J$ $J$r5   rq   startupc                  ,    t                t                y r1   )rQ   rZ   r4   r5   r6   
on_startuprw      s    Or5   z/healthc                     	 t               } | j                         }|j                  d       |j                          ddd	 | j	                          S # t
        $ r Y S w xY w# t
        $ r9}ddt        |      dcY d }~	  j	                          S # t
        $ r Y S w xY wd }~ww xY w# 	  j	                          w # t
        $ r Y w w xY wxY w)NzSELECT 1T)okdbF)ry   rz   error)r3   rH   rI   rJ   rL   rK   rb   )rM   rN   es      r6   healthr}      s    kkmJ$'	JJL 		  :%#a&99	JJL 		:	JJL 		sw   ?A" A	AA"	B$+B9B$:B' ?B	BBB$$B' 'C	)B:9C	:	CC	CC	z/auth/login)response_modelpayloadc                    t               }	 |j                  d      }|j                  d| j                  | j                  f       |j	                         }|r|j                  d      st        dd      t        j                  | j                  |d         st        dd      |j                  d|d	   f       d
|d	   d|j                          S # |j                          w xY w)NT
dictionaryzKSELECT id, password_hash, role FROM users WHERE username = %s OR email = %spassword_hashi  zInvalid credentialsstatus_codedetailz1UPDATE users SET last_login = NOW() WHERE id = %srr   zLogin successful)rf   rg   )r3   rH   rI   r]   rJ   getr   rT   verifyr-   rL   )r   rM   rN   rY   s       r6   loginr   
  s    DkkTk*Y!3!34	
 lln#''/2C8MNN!!'"2"2C4HIC8MNNG#d)V-c$iH



s   B7C C&z/auth/forgot-passwordc                    t               }	 |j                  d      }|j                  d| j                  f       |j	                         }|sddi|j                          S t        j                  d      }t        j                         t        d      z   }|j                         }|j                  d	|||d
   f       d| }d||d|j                          S # |j                          w xY w)NTr   z%SELECT id FROM users WHERE email = %srf   z/If the email exists, a reset link has been sent0      )hourszUUPDATE users SET password_reset_token = %s, password_reset_expires = %s WHERE id = %srr   z&http://localhost:40773/reset-password/zReset link generated)rf   rn   
reset_link)r3   rH   rI   rk   rJ   rL   secretstoken_urlsafer   utcnowr   )r   rM   rN   rY   rn   
expires_atcur2r   s           r6   forgot_passwordr     s    DkkTk*;gmm=MNllnPQ 	

 %%b)__&);;
{{}cJD	*	
 >eWE
1EQ[\



s   AC !A(C C,z/auth/reset-passwordc                 *   t        | j                        dk  rt        dd      t               }	 |j	                  d      }|j                  d| j                  f       |j                         }|st        dd      |d	   t        j                         k  rt        dd
      t        j                  | j                        }|j	                         }|j                  d||d   f       ddi|j                          S # |j                          w xY w)N   i  z&Password must be at least 8 charactersr   Tr   zLSELECT id, password_reset_expires FROM users WHERE password_reset_token = %szInvalid tokenpassword_reset_expireszToken expiredzmUPDATE users SET password_hash = %s, password_reset_token = NULL, password_reset_expires = NULL WHERE id = %srr   rf   zPassword reset successful)lenro   r   r3   rH   rI   rn   rJ   r   r   rT   rU   rL   )r   rM   rN   rY   r   r   s         r6   reset_passwordr   6  s    
7 1$4\]]DkkTk*Z]]	
 llnCHH'(8??+<<CHH#(()=)=>{{}{CI&	
 67



s   B>D   Dz/ordersc                      t               } 	 | j                  d      }|j                  d       |j                         }|| j	                          S # | j	                          w xY w)NTr   au  
            SELECT id, orderUniqueNumber, relatedQuoteNumber, relatedInvoiceNumber, 
                   orderType, processingType, customerName, orderDelivery, 
                   depositReceived, instructionsFinalised, orderPaidInFull, 
                   officeNotes, date, created_at, updated_at
            FROM customer_orders 
            ORDER BY date DESC
        r3   rH   rI   fetchallrL   )rM   rN   orderss      r6   
get_ordersr   R  sS    DkkTk*  	 



   4A A#z/orders/{order_id}order_idc                     t               }	 |j                  d      }|j                  d| f       |j                         }|st	        dd      ||j                          S # |j                          w xY w)NTr   ap  
            SELECT id, orderUniqueNumber, relatedQuoteNumber, relatedInvoiceNumber, 
                   orderType, processingType, customerName, orderDelivery, 
                   depositReceived, instructionsFinalised, orderPaidInFull, 
                   officeNotes, date, created_at, updated_at
            FROM customer_orders 
            WHERE id = %s
          Order not foundr   )r3   rH   rI   rJ   r   rL   )r   rM   rN   rP   s       r6   	get_orderr   e  sk    DkkTk*  [	 C8IJJ



s   AA" "A4rP   c                    t               }	 |j                         }|j                  d| j                  | j                  | j
                  | j                  | j                  | j                  | j                  | j                  | j                  | j                  | j                  | j                  f       |j                  }d|i|j!                          S # |j!                          w xY w)Nai  
            INSERT INTO customer_orders (
                orderUniqueNumber, relatedQuoteNumber, relatedInvoiceNumber, orderType,
                processingType, customerName, orderDelivery, depositReceived,
                instructionsFinalised, orderPaidInFull, officeNotes, date
            ) VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)
        rr   )r3   rH   rI   r:   r;   r<   r=   r>   r?   r@   rA   rB   rC   rD   rE   	lastrowidrL   )rP   rM   rN   r   s       r6   create_orderr   z  s    Dkkm  ##U%=%=u?Y?YOOU1153E3E!6!68S8S!!5#4#4ejj	
	 ==h



s   B5C C$c                    t               }	 |j                         }|j                  d|j                  |j                  |j
                  |j                  |j                  |j                  |j                  |j                  |j                  |j                  |j                  |j                  | f       |j                  dk(  rt!        dd      ddi|j#                          S # |j#                          w xY w)Na  
            UPDATE customer_orders SET
                orderUniqueNumber = %s, relatedQuoteNumber = %s, relatedInvoiceNumber = %s,
                orderType = %s, processingType = %s, customerName = %s,
                orderDelivery = %s, depositReceived = %s, instructionsFinalised = %s,
                orderPaidInFull = %s, officeNotes = %s, date = %s
            WHERE id = %s
        r   r   r   r   successT)r3   rH   rI   r:   r;   r<   r=   r>   r?   r@   rA   rB   rC   rD   rE   rowcountr   rL   )r   rP   rM   rN   s       r6   update_orderr     s    Dkkm  ##U%=%=u?Y?YOOU1153E3E!6!68S8S!!5#4#4ejj(	
	 <<1C8IJJ4 



s   CC# #C5c                     t               }	 |j                         }|j                  d| f       |j                  dk(  rt	        dd      ddi|j                          S # |j                          w xY w)Nz)DELETE FROM customer_orders WHERE id = %sr   r   r   r   r   T)r3   rH   rI   r   r   rL   )r   rM   rN   s      r6   delete_orderr     s`    Dkkm?(M<<1C8IJJ4 



s   AA A1z
/customersc                      t               } 	 | j                  d      }|j                  d       |j                         }|| j	                          S # | j	                          w xY w)NTr   z
            SELECT DISTINCT customerName, COUNT(*) as order_count
            FROM customer_orders 
            GROUP BY customerName
            ORDER BY customerName
        r   )rM   rN   	customerss      r6   get_customersr     sS    DkkTk*  	 LLN	



r   __main__zapp.main:appz0.0.0.0PORT4000)r*   r+   reload)<r   r   osr   fastapir   r   fastapi.middleware.corsr   pydanticr   r	   passlib.contextr
   mysql.connectormysqlr   typingr   dotenvr   getenvr   rh   r   r   r   r   rT   appadd_middlewareMySQLConnectionPoolr2   r3   rQ   rZ   r\   re   rj   rm   rq   on_eventrw   r   r}   postr   r   r   r   r   r   putr   deleter   r   r_   uvicornrunr4   r5   r6   <module>r      s   ( 	  * 2 ( (  #    "))I{
+
ibii	6*
+
"))Iv
&biir*
"))I}
-H:&Ai   01=%   .'--				,}@29 
#I #
I 9 
%) %$ i 
    -6<  7( 
!"2  #, 
 !0  "6  $ 	  ( )  , 	3 {  0  !	3 	 "	    zGKKYS669R5S\`a r5   