
    <hN7                    %   % S SK J r Jr  S SKrS SKrS SKJrJrJrJrJ	r	J
r
  S SKJr  S SKJr  S SKJr  S SKJrJr  S SKJr  S SKrS S	KJr  S S
KJr  S SKJr  S SKrS SKJr  \" 5         \R@                  " SS5      r!\"" \R@                  " SS5      5      r#\R@                  " SS5      r$\R@                  " SS5      r%\R@                  " SS5      r&\" S/SS9r'\" 5       r(\R@                  " S\RR                  RU                  \RV                  " 5       S5      5      r,\RZ                  " \,SS9  \(R]                  S\" \,S9SS 9  \(R_                  \/ S!QS/ S"QS#/S$9  \R@                  " S\RR                  RU                  \RV                  " 5       S5      5      r,\RZ                  " \,SS9  \(R]                  S\" \,S9SS 9  \0" \Rb                  " 5       5      r2\Rf                  " S%\2 3\"" \R@                  " S&S'5      5      \!\#\$\%\&SS(9r4S) r5S* r6S+\0S,\74S- jr8\(Rs                  S.5      S/ 5       r:\(Rw                  S.5      S0\<4S1 j5       r=\(R}                  S25      S3\"S0\<4S4 j5       r?\(R                  S25      S3\"4S5 j5       rA\(Rs                  S65      S7 5       rB\(Rw                  S65      S0\<4S8 j5       rC\(R}                  S95      S3\"S0\<4S: j5       rD\(R                  S95      S3\"4S; j5       rE\(Rs                  S<5      S= 5       rF\(Rw                  S<5      S0\<4S> j5       rG\(R}                  S?5      S3\"S0\<4S@ j5       rH\(R                  S?5      S3\"4SA j5       rI\(Rs                  SB5      SC 5       rJ\(Rw                  SB5      S0\<4SD j5       rK\(R}                  SE5      S3\"S0\<4SF j5       rL\(R                  SE5      S3\"4SG j5       rM\(Rs                  SH5      SI 5       rN\(Rw                  SH5      S0\<4SJ j5       rO\(R}                  SK5      S3\"S0\<4SL j5       rP\(R                  SK5      S3\"4SM j5       rQ\(Rs                  SN5      SO 5       rR\(Rw                  SN5      S0\<4SP j5       rS\(R}                  SQ5      S3\"S0\<4SR j5       rT\(R                  SQ5      S3\"4SS j5       rU\(Rs                  ST5      SU 5       rV\(Rw                  ST5      S0\<4SV j5       rW\(R}                  SW5      S3\"S0\<4SX j5       rX\(R                  SW5      S3\"4SY j5       rY\(Rs                  SZ5      S[ 5       rZ\(Rw                  SZ5      S0\<4S\ j5       r[\(R}                  S]5      S3\"S0\<4S^ j5       r\\(R                  S]5      S3\"4S_ j5       r]\(Rs                  S`5      Sa 5       r^\(Rw                  S`5      S0\<4Sb j5       r_\(R}                  Sc5      S3\"S0\<4Sd j5       r`\(R                  Sc5      S3\"4Se j5       ra\(Rs                  Sf5      Sg 5       rb\(Rw                  Sf5      S0\<4Sh j5       rc\(R}                  Si5      S3\"S0\<4Sj j5       rd\(R                  Si5      S3\"4Sk j5       re\(Rs                  Sl5      Sm 5       rf\(Rw                  Sl5      S0\<4Sn j5       rg\(R}                  So5      S3\"S0\<4Sp j5       rh\(R                  So5      S3\"4Sq j5       riSr rjSs rk " St Su\5      rl " Sv Sw\5      rm " Sx Sy\5      rn " Sz S{\5      ro " S| S}\5      rp " S~ S\5      rq " S S\5      rr " S S\5      rs " S S\5      rt " S S\5      ru " S S\5      rv " S S\5      rw " S S\5      rx " S S\5      ry " S S\5      rx " S S\5      rz " S S\5      r{ " S S\5      r|\(R                  S5      S 5       r~\(Rs                  S5      S 5       r\(Rs                  S5      S 5       r\(Rs                  S5      S 5       r\(Rs                  S5      S3\"4S j5       r\(Rw                  S5      S\s4S j5       r\(R}                  S5      S3\"S\s4S j5       r\(R                  S5      S3\"4S j5       r\(Rs                  S5      S 5       r\(Rs                  S5      S3\"4S j5       r\(Rw                  S5      S\t4S j5       r\(R}                  S5      S3\"S\t4S j5       r\(R                  S5      S3\"4S j5       r\(Rs                  S5      S 5       r\(Rs                  S5      S3\"4S j5       r\(Rw                  S5      S\u4S j5       r\(R}                  S5      S3\"S\u4S j5       r\(R                  S5      S3\"4S j5       r\(Rs                  S5      S 5       r\(Rw                  S5      S\v4S j5       r\(R}                  S5      S\"S\v4S j5       r\(R                  S5      S\"4S j5       r\(Rs                  S5      S 5       r\(Rw                  S5      S\w4S j5       r\(R}                  S5      S\"S\w4S j5       r\(R                  S5      S\"4S j5       r\(Rs                  S5      S 5       r\(Rs                  S5      S 5       r\(Rs                  S5      S 5       r\(Rs                  S5      S 5       r\(Rw                  S5      S0\<4S j5       r\(R}                  S5      S3\"S0\<4S j5       r\(R                  S5      S3\"4S j5       r\(Rw                  S5      S\x4S j5       r\(R}                  S5      S3\"S\x4S j5       r\(R                  S5      S3\"4S j5       r0 SS_SS_SS_SS_SS_SS_SS_SS_SS_SS_SS_SS_SS_SS_SS_SS_SS_0 SS_SS_SS_SS_SS_SS_SS_SS_SS_SS_SS_SS_SS_SS_SS_SS_SS_E0 SS_SS_SS_SS_SS_SS_SS_SS_SS_SS_SS_SS_SS_GS GS _GSGS_GSGS_GSGS_EGSGSGSGS.Er\<\\0\04   \\0\04   4   \GS'   GS	\0S,\\0   4GS
 jrGS\\0   S,\04GS jr\(Rs                  GS5      GS\0GS\04GS j5       r\(R}                  GS5      GS\0GS\0S\y4GS j5       r\(Rs                  GS5      GS 5       r\(Rs                  GS5      GS 5       r\(Rs                  GS5      GS 5       r\(Rs                  GS5      GS 5       r\(Rw                  GS5      S0\<4GS j5       r\(R}                  GS5      S3\"S0\<4GS j5       r\(R                  GS5      S3\"4GS j5       r\(Rs                  GS5      GS 5       r\(Rs                  GS 5      GS! 5       r\(Rs                  GS"5      GS# 5       r\(Rs                  GS$5      GS% 5       r\(Rs                  GS&5      GS' 5       r\(Rs                  GS(5      GS)\"4GS* j5       r\(Rs                  GS+5      \
" GS,GS-GS.94GS/\4GS0 jj5       r\(Rs                  GS15      GS2\"4GS3 j5       r\(R                  GS15      GS2\"4GS4 j5       r\(R}                  GS15      GS2\"S0\|4GS5 j5       r\(Rw                  GS65      GS2\"4GS7 j5       r\(R                  GS85      GS2\"4GS9 j5       r\(Rw                  GS+5      S0\|4GS: j5       r\(Rs                  GS;5      GS2\"4GS< j5       r\(Rw                  GS;5      \" GS=5      4GS2\"GS>\4GS? jj5       r\(Rs                  GS@5      GSA 5       r\(Rw                  S5      S\r4GSB j5       r\(R}                  GS(5      GS)\"S\r4GSC j5       r\(R                  GS(5      GS)\"4GSD j5       r\(Rs                  GSE5      GS)\"4GSF j5       r\(Rw                  GSE5      \" GS=5      4GS)\"GS>\4GSG jj5       r\(R}                  GSH5      GS)\"GSI\"S\<4GSJ j5       r\(R                  GSH5      GS)\"GSI\"4GSK j5       r\(Rs                  GSL5      GS)\"GSI\"4GSM j5       r\(Rw                  GSN\mGSO9S0\l4GSP j5       r\(Rw                  GSQ5      S0\o4GSR j5       r\(Rw                  GSS5      S0\p4GST j5       r\(Rs                  GSU5      GSV 5       r " GSW GSX\5      r\(R}                  GSY5      GSZ\"S\4GS[ j5       r " GS\ GS]\5      r\(Rw                  GSU5      S\4GS^ j5       r " GS_ GS`\5      r\(R}                  GSa5      GSZ\"S\4GSb j5       r " GSc GSd\5      r\(R}                  GSe5      GSZ\"S\4GSf j5       r\(Rs                  GSg5      GSh 5       r\(Rs                  GSi5      GSj\"4GSk j5       r\(Rw                  GSg5      GSl\q4GSm j5       r\(R}                  GSi5      GSj\"GSl\q4GSn j5       r\(R                  GSi5      GSj\"4GSo j5       r\(Rs                  GSp5      GSq\"4GSr j5       r\(Rw                  GSp5      \" GS=5      4GSq\"GS>\4GSs jj5       r\(R}                  GSt5      GSq\"GSI\"S\<4GSu j5       r\(R                  GSt5      GSq\"GSI\"4GSv j5       r\(Rs                  GSw5      GSq\"GSI\"4GSx j5       r\(Rs                  GSy5      GSz 5       r\(Rw                  GSy5      GS{\n4GS| j5       r\(Rs                  GS}5      GSq\"4GS~ j5       r\(R}                  GS}5      GSq\"GS{\n4GS j5       r\(R                  GS}5      GSq\"4GS j5       r\GS:X  a  S SKr\GR                  " GSGSGSSGSGS9  gg(      )datetime	timedeltaN)FastAPIHTTPException
UploadFileFileResponseQuery)FileResponse)StaticFiles)CORSMiddleware)	BaseModelEmailStr)CryptContext)pooling)Optional)load_dotenv)EmailMessageDB_HOST	localhostDB_PORT3306DB_USERbullseye_userDB_PASSWORDz4#zqJOSeownWs86cDB_NAMESouthernDirectionsql4bcryptauto)schemes
deprecated
UPLOAD_DIRuploadsTexist_okz/uploads)	directory)name)zhttps://bullseye.mysouth.iozhttp://localhost:40773zhttp://127.0.0.1:40773)GETPOSTPUTDELETEOPTIONS*)allow_originsallow_credentialsallow_methodsallow_headersbe_pool_DB_POOL_SIZE15)	pool_name	pool_sizehostportuserpassworddatabase
autocommitc            
           [         R                  5       $ ! [        R                  R                  R
                   a9    [        R                  R                  [        [        [        [        [        SS9s $ f = f)NT)r7   r8   r9   r:   r;   r<   )connection_poolget_connectionmysql	connectorerrors	PoolErrorconnectr   r   r   r   r        !C:\Projects\Bulls Eye\app\main.pyr?   r?   B   sc    
--//??!!++ 	
&&  ' 
 	
	
s    AA76A7c                 d    [        U [        5      (       a  U R                  5       nUS:w  a  U$ S $ U $ )N )
isinstancestrstrip)valuevs     rG   _blank_to_nonerO   Q   s0    %KKMGq%%LrF   
table_namereturnc                    [        5       n UR                  SS9n UR                  SU  35        UR                  5       =(       d    / nU Vs1 s H+  n[	        U[
        5      (       d  M  UR                  S5      iM-     snUR                  5         $ s  snf ! [         a    [        5       s UR                  5         $ f = f! UR                  5         f = f)zKReturn set of column names for the given table. Empty set if table missing.T
dictionaryzSHOW COLUMNS FROM Field)
r?   cursorexecutefetchallrJ   dictgetclose	Exceptionset)rP   conncurrowsrs        rG   _get_table_columnsrb   X   s    D	kkTk*	KK,ZL9:<<>'RD,0HDqJq$4GNAEE'NDH 	

	 I 	5L

	 	

s@   C 1B B*B?B B B>+C =B>>C Cz/items/line-item-rug-mountc                  v   [        5       n  U R                  SS9n UR                  S5        UR                  5       =(       d    /  U R                  5         $ ! [        R                  R
                   a.  n[        USS 5      S:X  a  / s S nAU R                  5         $ e S nAff = f! U R                  5         f = f)NTrS   z
                SELECT id, category, name, notes
                FROM line_item_rug_mount
                WHERE is_active = 1
                ORDER BY category, name
                errnoz  	r?   rV   rW   r@   rA   Errorgetattrr[   rX   r^   r_   es      rG   list_items_line_item_rug_mountrk   g       DkkTk*	KK ||~##

 $$ 	q'4(D0	 	

 	 	

?   B& A B& B#5BB#B& BB##B& &B8payloadc                 B   SS/nU H=  nU R                  U5      =(       d    SR                  5       (       a  M2  [        SSU 3S9e   [        5       n UR	                  5       nUR                  SU R                  S5      U R                  S5      [        U R                  S5      5      [        U R                  S	S
5      5      R                  5       S;  a  SOS45        UR                  5         SUR                  0UR                  5         $ ! UR                  5         f = f)Ncategoryr'   rI     Missing required field: status_codedetailz
            INSERT INTO line_item_rug_mount
              (category, name, notes, is_active)
            VALUES (%s, %s, %s, %s)
            notes	is_active10falseFalse   r   idrZ   rL   r   r?   rV   rW   rO   rK   commit	lastrowidr[   rn   requiredkr^   r_   s        rG   create_line_item_rug_mountr   ~       F#HA$"++--C:RSTRU8VWW  Dkkm J'F#w{{734[#67==?G^^de		
 	cmm$



   B(D Dz&/items/line-item-rug-mount/{record_id}	record_idc                    [        5       n UR                  5       nUR                  SUR                  S5      UR                  S5      [	        UR                  S5      5      [        UR                  SS5      5      R                  5       S;  a  SOS	U 45        UR                  S	:X  a
  [        S
SS9eUR                  5         SS0UR                  5         $ ! UR                  5         f = f)Nz
            UPDATE line_item_rug_mount
            SET category=%s, name=%s, notes=%s, is_active=%s
            WHERE id=%s
            rp   r'   rv   rw   rx   ry   r}   r     Rug Mount line item not foundrs   successTr?   rV   rW   rZ   rO   rK   rL   rowcountr   r   r[   r   rn   r^   r_   s       rG   update_line_item_rug_mountr      s    Dkkm J'F#w{{734[#67==?G^^de	
 <<1C8WXX4 



   B9C C(c                    [        5       n UR                  5       nUR                  SU 45        UR                  S:X  a
  [	        SSS9eUR                  5         SS0UR                  5         $ ! UR                  5         f = f)Nz+DELETE FROM line_item_rug_mount WHERE id=%sr   r   r   rs   r   Tr?   rV   rW   r   r   r   r[   r   r^   r_   s      rG   delete_line_item_rug_mountr      si    DkkmAI<P<<1C8WXX4 



   AA- -A?z/items/line-item-misc-productsc                  v   [        5       n  U R                  SS9n UR                  S5        UR                  5       =(       d    /  U R                  5         $ ! [        R                  R
                   a.  n[        USS 5      S:X  a  / s S nAU R                  5         $ e S nAff = f! U R                  5         f = f)NTrS   z
                SELECT id, section, item, `option`, internal_note, notes, price_usd
                FROM line_item_misc_products
                WHERE is_active = 1
                ORDER BY section, item, `option`
                rd   re   rf   ri   s      rG   "list_items_line_item_misc_productsr      rl   rm   c                 n   SS/nU H=  nU R                  U5      =(       d    SR                  5       (       a  M2  [        SSU 3S9e   [        5       n UR	                  5       nUR                  SU R                  S5      U R                  S5      [        U R                  S5      5      [        U R                  S	5      5      [        U R                  S
5      5      [        U R                  S5      5      [        U R                  S5      5      [        U R                  S5      5      [        U R                  S5      5      [        U R                  SS5      5      R                  5       S;  a  SOS4
5        UR                  5         SUR                  0UR                  5         $ ! UR                  5         f = f)NsectionitemrI   rq   rr   rs   z
            INSERT INTO line_item_misc_products
              (section, item, `option`, internal_note, notes, price_zar, price_usd, price_eur, price_bwp, is_active)
            VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s)
            optioninternal_noterv   	price_zar	price_usd	price_eur	price_bwprw   rx   ry   r}   r   r~   r   r   s        rG   create_line_item_misc_productsr      s[   6"HA$"++--C:RSTRU8VWW  Dkkm I&F#w{{845w{{?;<w{{734w{{;78w{{;78w{{;78w{{;78[#67==?G^^de	
& 	cmm$



   D>F" "F4z*/items/line-item-misc-products/{record_id}c                    [        5       n UR                  5       nUR                  SUR                  S5      UR                  S5      [	        UR                  S5      5      [	        UR                  S5      5      [	        UR                  S5      5      [	        UR                  S5      5      [	        UR                  S5      5      [	        UR                  S	5      5      [	        UR                  S
5      5      [        UR                  SS5      5      R                  5       S;  a  SOSU 45        UR                  S:X  a
  [        SSS9eUR                  5         SS0UR                  5         $ ! UR                  5         f = f)Na  
            UPDATE line_item_misc_products
            SET section=%s, item=%s, `option`=%s, internal_note=%s, notes=%s,
                price_zar=%s, price_usd=%s, price_eur=%s, price_bwp=%s,
                is_active=%s
            WHERE id=%s
            r   r   r   r   rv   r   r   r   r   rw   rx   ry   r}   r   r   !Misc products line item not foundrs   r   Tr   r   s       rG   update_line_item_misc_productsr      s+   Dkkm I&F#w{{845w{{?;<w{{734w{{;78w{{;78w{{;78w{{;78[#67==?G^^de	
, <<1C8[\\4 



   EE, ,E>c                    [        5       n UR                  5       nUR                  SU 45        UR                  S:X  a
  [	        SSS9eUR                  5         SS0UR                  5         $ ! UR                  5         f = f)Nz/DELETE FROM line_item_misc_products WHERE id=%sr   r   r   rs   r   Tr   r   s      rG   delete_line_item_misc_productsr     si    DkkmE	|T<<1C8[\\4 



r   z/items/line-item-half-mountc                  v   [        5       n  U R                  SS9n UR                  S5        UR                  5       =(       d    /  U R                  5         $ ! [        R                  R
                   a.  n[        USS 5      S:X  a  / s S nAU R                  5         $ e S nAff = f! U R                  5         f = f)NTrS   z
                SELECT id, category, name, notes
                FROM line_item_half_mount
                WHERE is_active = 1
                ORDER BY category, name
                rd   re   rf   ri   s      rG   list_items_line_item_half_mountr   *  rl   rm   c                 B   SS/nU H=  nU R                  U5      =(       d    SR                  5       (       a  M2  [        SSU 3S9e   [        5       n UR	                  5       nUR                  SU R                  S5      U R                  S5      [        U R                  S5      5      [        U R                  S	S
5      5      R                  5       S;  a  SOS45        UR                  5         SUR                  0UR                  5         $ ! UR                  5         f = f)Nrp   r'   rI   rq   rr   rs   z
            INSERT INTO line_item_half_mount
              (category, name, notes, is_active)
            VALUES (%s, %s, %s, %s)
            rv   rw   rx   ry   r}   r   r~   r   r   s        rG   create_line_item_half_mountr   A  r   r   z'/items/line-item-half-mount/{record_id}c                    [        5       n UR                  5       nUR                  SUR                  S5      UR                  S5      [	        UR                  S5      5      [        UR                  SS5      5      R                  5       S;  a  SOS	U 45        UR                  S	:X  a
  [        S
SS9eUR                  5         SS0UR                  5         $ ! UR                  5         f = f)Nz
            UPDATE line_item_half_mount
            SET category=%s, name=%s, notes=%s, is_active=%s
            WHERE id=%s
            rp   r'   rv   rw   rx   ry   r}   r   r   Half Mount line item not foundrs   r   Tr   r   s       rG   update_line_item_half_mountr   ]  s    Dkkm J'F#w{{734[#67==?G^^de	
 <<1C8XYY4 



r   c                    [        5       n UR                  5       nUR                  SU 45        UR                  S:X  a
  [	        SSS9eUR                  5         SS0UR                  5         $ ! UR                  5         f = f)Nz,DELETE FROM line_item_half_mount WHERE id=%sr   r   r   rs   r   Tr   r   s      rG   delete_line_item_half_mountr   x  i    DkkmBYLQ<<1C8XYY4 



r   z"/items/line-item-african-map-mountc                  v   [        5       n  U R                  SS9n UR                  S5        UR                  5       =(       d    /  U R                  5         $ ! [        R                  R
                   a.  n[        USS 5      S:X  a  / s S nAU R                  5         $ e S nAff = f! U R                  5         f = f)NTrS   z
                SELECT id, category, name, notes, price_zar, price_usd, price_eur, price_bwp, is_active
                FROM line_item_african_map_mount
                WHERE is_active = 1
                ORDER BY category, name
                rd   re   rf   ri   s      rG   &list_items_line_item_african_map_mountr     rl   rm   c                 
   SS/nU H=  nU R                  U5      =(       d    SR                  5       (       a  M2  [        SSU 3S9e   [        5       n UR	                  5       nUR                  SU R                  S5      U R                  S5      [        U R                  S5      5      [        U R                  S	5      5      [        U R                  S
5      5      [        U R                  S5      5      [        U R                  S5      5      [        U R                  SS5      5      R                  5       S;  a  SOS45        UR                  5         SUR                  0UR                  5         $ ! UR                  5         f = f)Nrp   r'   rI   rq   rr   rs   z
            INSERT INTO line_item_african_map_mount
              (category, name, notes, price_zar, price_usd, price_eur, price_bwp, is_active)
            VALUES (%s, %s, %s, %s, %s, %s, %s, %s)
            rv   r   r   r   r   rw   rx   ry   r}   r   r~   r   r   s        rG   "create_line_item_african_map_mountr     s9   F#HA$"++--C:RSTRU8VWW  Dkkm J'F#w{{734w{{;78w{{;78w{{;78w{{;78[#67==?G^^de		
" 	cmm$



   DE0 0Fz./items/line-item-african-map-mount/{record_id}c                    [        5       n UR                  5       nUR                  SUR                  S5      UR                  S5      [	        UR                  S5      5      [	        UR                  S5      5      [	        UR                  S5      5      [	        UR                  S5      5      [	        UR                  S5      5      [        UR                  S	S
5      5      R                  5       S;  a  SOSU 4	5        UR                  S:X  a
  [        SSS9eUR                  5         SS0UR                  5         $ ! UR                  5         f = f)Nz
            UPDATE line_item_african_map_mount
            SET category=%s, name=%s, notes=%s, price_zar=%s, price_usd=%s, price_eur=%s, price_bwp=%s, is_active=%s
            WHERE id=%s
            rp   r'   rv   r   r   r   r   rw   rx   ry   r}   r   r   African Map line item not foundrs   r   Tr   r   s       rG   "update_line_item_african_map_mountr     s	   Dkkm J'F#w{{734w{{;78w{{;78w{{;78w{{;78[#67==?G^^de
	
$ <<1C8YZZ4 



   DD: :Ec                    [        5       n UR                  5       nUR                  SU 45        UR                  S:X  a
  [	        SSS9eUR                  5         SS0UR                  5         $ ! UR                  5         f = f)Nz3DELETE FROM line_item_african_map_mount WHERE id=%sr   r   r   rs   r   Tr   r   s      rG   "delete_line_item_african_map_mountr     si    DkkmII<X<<1C8YZZ4 



r   z/items/line-item-skullsc                  v   [        5       n  U R                  SS9n UR                  S5        UR                  5       =(       d    /  U R                  5         $ ! [        R                  R
                   a.  n[        USS 5      S:X  a  / s S nAU R                  5         $ e S nAff = f! U R                  5         f = f)NTrS   z
                SELECT id, category, name, surcharge_pct, notes
                FROM line_item_skulls
                WHERE is_active = 1
                ORDER BY category, name
                rd   re   rf   ri   s      rG   list_items_line_item_skullsr     rl   rm   c                 t   SS/nU H=  nU R                  U5      =(       d    SR                  5       (       a  M2  [        SSU 3S9e   [        5       n UR	                  5       nUR                  SU R                  S5      U R                  S5      [        U R                  S5      5      [        U R                  S	5      5      [        U R                  S
S5      5      R                  5       S;  a  SOS45        UR                  5         SUR                  0UR                  5         $ ! UR                  5         f = f)Nrp   r'   rI   rq   rr   rs   z
            INSERT INTO line_item_skulls
              (category, name, surcharge_pct, notes, is_active)
            VALUES (%s, %s, %s, %s, %s)
            surcharge_pctrv   rw   rx   ry   r}   r   r~   r   r   s        rG   create_line_item_skullsr        F#HA$"++--C:RSTRU8VWW  Dkkm J'F#w{{?;<w{{734[#67==?G^^de	
 	cmm$



   CD% %D7z#/items/line-item-skulls/{record_id}c                    [        5       n UR                  5       nUR                  SUR                  S5      UR                  S5      [	        UR                  S5      5      [	        UR                  S5      5      [        UR                  SS5      5      R                  5       S;  a  S	OS
U 45        UR                  S
:X  a
  [        SSS9eUR                  5         SS0UR                  5         $ ! UR                  5         f = f)Nz
            UPDATE line_item_skulls
            SET category=%s, name=%s, surcharge_pct=%s, notes=%s, is_active=%s
            WHERE id=%s
            rp   r'   r   rv   rw   rx   ry   r}   r   r   Skulls line item not foundrs   r   Tr   r   s       rG   update_line_item_skullsr     s    Dkkm J'F#w{{?;<w{{734[#67==?G^^de	
 <<1C8TUU4 



   CC/ /Dc                    [        5       n UR                  5       nUR                  SU 45        UR                  S:X  a
  [	        SSS9eUR                  5         SS0UR                  5         $ ! UR                  5         f = f)Nz(DELETE FROM line_item_skulls WHERE id=%sr   r   r   rs   r   Tr   r   s      rG   delete_line_item_skullsr   8  si    Dkkm>M<<1C8TUU4 



r   z/items/line-item-pedestal-basesc                  v   [        5       n  U R                  SS9n UR                  S5        UR                  5       =(       d    /  U R                  5         $ ! [        R                  R
                   a.  n[        USS 5      S:X  a  / s S nAU R                  5         $ e S nAff = f! U R                  5         f = f)NTrS   z
                SELECT id, item, category, internal_note_applicable_to, price_usd
                FROM line_item_pedestal_bases
                WHERE is_active = 1
                ORDER BY category, item
                rd   re   rf   ri   s      rG   #list_items_line_item_pedestal_basesr   E  rl   rm   c                 
   SS/nU H=  nU R                  U5      =(       d    SR                  5       (       a  M2  [        SSU 3S9e   [        5       n UR	                  5       nUR                  SU R                  S5      U R                  S5      [        U R                  S5      5      [        U R                  S	5      5      [        U R                  S
5      5      [        U R                  S5      5      [        U R                  S5      5      [        U R                  SS5      5      R                  5       S;  a  SOS45        UR                  5         SUR                  0UR                  5         $ ! UR                  5         f = f)Nr   rp   rI   rq   rr   rs   z
            INSERT INTO line_item_pedestal_bases
              (item, category, internal_note_applicable_to, price_usd, price_eur, price_zar, price_bwp, is_active)
            VALUES (%s, %s, %s, %s, %s, %s, %s, %s)
            internal_note_applicable_tor   r   r   r   rw   rx   ry   r}   r   r~   r   r   s        rG   create_line_item_pedestal_basesr   \  s:   
#HA$"++--C:RSTRU8VWW  Dkkm F#J'w{{+HIJw{{;78w{{;78w{{;78w{{;78[#67==?G^^de		
" 	cmm$



r   z+/items/line-item-pedestal-bases/{record_id}c                    [        5       n UR                  5       nUR                  SUR                  S5      UR                  S5      [	        UR                  S5      5      [	        UR                  S5      5      [	        UR                  S5      5      [	        UR                  S5      5      [	        UR                  S5      5      [        UR                  S	S
5      5      R                  5       S;  a  SOSU 4	5        UR                  S:X  a
  [        SSS9eUR                  5         SS0UR                  5         $ ! UR                  5         f = f)Nz
            UPDATE line_item_pedestal_bases
            SET item=%s, category=%s, internal_note_applicable_to=%s, price_usd=%s, price_eur=%s, price_zar=%s, price_bwp=%s, is_active=%s
            WHERE id=%s
            r   rp   r   r   r   r   r   rw   rx   ry   r}   r   r   "Pedestal bases line item not foundrs   r   Tr   r   s       rG   update_line_item_pedestal_basesr   |  s
   Dkkm F#J'w{{+HIJw{{;78w{{;78w{{;78w{{;78[#67==?G^^de
	
$ <<1C8\]]4 



r   c                    [        5       n UR                  5       nUR                  SU 45        UR                  S:X  a
  [	        SSS9eUR                  5         SS0UR                  5         $ ! UR                  5         f = f)Nz0DELETE FROM line_item_pedestal_bases WHERE id=%sr   r   r   rs   r   Tr   r   s      rG   delete_line_item_pedestal_basesr     i    DkkmFU<<1C8\]]4 



r   z(/items/line-item-pedestal-shoulder-mountc                  v   [        5       n  U R                  SS9n UR                  S5        UR                  5       =(       d    /  U R                  5         $ ! [        R                  R
                   a.  n[        USS 5      S:X  a  / s S nAU R                  5         $ e S nAff = f! U R                  5         f = f)NTrS   z
                SELECT id, category, name, surcharge_pct, notes
                FROM line_item_pedestal_shoulder_mount
                WHERE is_active = 1
                ORDER BY category, name
                rd   re   rf   ri   s      rG   ,list_items_line_item_pedestal_shoulder_mountr     rl   rm   c                 t   SS/nU H=  nU R                  U5      =(       d    SR                  5       (       a  M2  [        SSU 3S9e   [        5       n UR	                  5       nUR                  SU R                  S5      U R                  S5      [        U R                  S5      5      [        U R                  S	5      5      [        U R                  S
S5      5      R                  5       S;  a  SOS45        UR                  5         SUR                  0UR                  5         $ ! UR                  5         f = f)Nrp   r'   rI   rq   rr   rs   z
            INSERT INTO line_item_pedestal_shoulder_mount
              (category, name, surcharge_pct, notes, is_active)
            VALUES (%s, %s, %s, %s, %s)
            r   rv   rw   rx   ry   r}   r   r~   r   r   s        rG   (create_line_item_pedestal_shoulder_mountr     r   r   z4/items/line-item-pedestal-shoulder-mount/{record_id}c                    [        5       n UR                  5       nUR                  SUR                  S5      UR                  S5      [	        UR                  S5      5      [	        UR                  S5      5      [        UR                  SS5      5      R                  5       S;  a  S	OS
U 45        UR                  S
:X  a
  [        SSS9eUR                  5         SS0UR                  5         $ ! UR                  5         f = f)Nz
            UPDATE line_item_pedestal_shoulder_mount
            SET category=%s, name=%s, surcharge_pct=%s, notes=%s, is_active=%s
            WHERE id=%s
            rp   r'   r   rv   rw   rx   ry   r}   r   r   +Pedestal Shoulder Mount line item not foundrs   r   Tr   r   s       rG   (update_line_item_pedestal_shoulder_mountr     s    Dkkm J'F#w{{?;<w{{734[#67==?G^^de	
 <<1C8eff4 



r   c                    [        5       n UR                  5       nUR                  SU 45        UR                  S:X  a
  [	        SSS9eUR                  5         SS0UR                  5         $ ! UR                  5         f = f)Nz9DELETE FROM line_item_pedestal_shoulder_mount WHERE id=%sr   r   r   rs   r   Tr   r   s      rG   (delete_line_item_pedestal_shoulder_mountr     sk    DkkmOR[Q]^<<1C8eff4 



r   z-/items/line-item-wall-pedestal-shoulder-mountc                  v   [        5       n  U R                  SS9n UR                  S5        UR                  5       =(       d    /  U R                  5         $ ! [        R                  R
                   a.  n[        USS 5      S:X  a  / s S nAU R                  5         $ e S nAff = f! U R                  5         f = f)NTrS   z
                SELECT id, category, name, notes
                FROM line_item_wall_pedestal_shoulder_mount
                WHERE is_active = 1
                ORDER BY category, name
                rd   re   rf   ri   s      rG   1list_items_line_item_wall_pedestal_shoulder_mountr     rl   rm   c                 B   SS/nU H=  nU R                  U5      =(       d    SR                  5       (       a  M2  [        SSU 3S9e   [        5       n UR	                  5       nUR                  SU R                  S5      U R                  S5      [        U R                  S5      5      [        U R                  S	S
5      5      R                  5       S;  a  SOS45        UR                  5         SUR                  0UR                  5         $ ! UR                  5         f = f)Nrp   r'   rI   rq   rr   rs   z
            INSERT INTO line_item_wall_pedestal_shoulder_mount
              (category, name, notes, is_active)
            VALUES (%s, %s, %s, %s)
            rv   rw   rx   ry   r}   r   r~   r   r   s        rG   -create_line_item_wall_pedestal_shoulder_mountr     r   r   z9/items/line-item-wall-pedestal-shoulder-mount/{record_id}c                    [        5       n UR                  5       nUR                  SUR                  S5      UR                  S5      [	        UR                  S5      5      [        UR                  SS5      5      R                  5       S;  a  SOS	U 45        UR                  S	:X  a
  [        S
SS9eUR                  5         SS0UR                  5         $ ! UR                  5         f = f)Nz
            UPDATE line_item_wall_pedestal_shoulder_mount
            SET category=%s, name=%s, notes=%s, is_active=%s
            WHERE id=%s
            rp   r'   rv   rw   rx   ry   r}   r   r   0Wall Pedestal Shoulder Mount line item not foundrs   r   Tr   r   s       rG   -update_line_item_wall_pedestal_shoulder_mountr   8  s    Dkkm J'F#w{{734[#67==?G^^de	
 <<1C8jkk4 



r   c                    [        5       n UR                  5       nUR                  SU 45        UR                  S:X  a
  [	        SSS9eUR                  5         SS0UR                  5         $ ! UR                  5         f = f)Nz>DELETE FROM line_item_wall_pedestal_shoulder_mount WHERE id=%sr   r   r   rs   r   Tr   r   s      rG   -delete_line_item_wall_pedestal_shoulder_mountr   S  sk    DkkmTW`Vbc<<1C8jkk4 



r   z/items/line-item-shoulder-mountc                  v   [        5       n  U R                  SS9n UR                  S5        UR                  5       =(       d    /  U R                  5         $ ! [        R                  R
                   a.  n[        USS 5      S:X  a  / s S nAU R                  5         $ e S nAff = f! U R                  5         f = f)NTrS   z
                SELECT id, category, name, notes
                FROM line_item_shoulder_mount
                WHERE is_active = 1
                ORDER BY category, name
                rd   re   rf   ri   s      rG   #list_items_line_item_shoulder_mountr   `  rl   rm   c                 B   SS/nU H=  nU R                  U5      =(       d    SR                  5       (       a  M2  [        SSU 3S9e   [        5       n UR	                  5       nUR                  SU R                  S5      U R                  S5      [        U R                  S5      5      [        U R                  S	S
5      5      R                  5       S;  a  SOS45        UR                  5         SUR                  0UR                  5         $ ! UR                  5         f = f)Nrp   r'   rI   rq   rr   rs   z
            INSERT INTO line_item_shoulder_mount
              (category, name, notes, is_active)
            VALUES (%s, %s, %s, %s)
            rv   rw   rx   ry   r}   r   r~   r   r   s        rG   create_line_item_shoulder_mountr   w  r   r   z+/items/line-item-shoulder-mount/{record_id}c                    [        5       n UR                  5       nUR                  SUR                  S5      UR                  S5      [	        UR                  S5      5      [        UR                  SS5      5      R                  5       S;  a  SOS	U 45        UR                  S	:X  a
  [        S
SS9eUR                  5         SS0UR                  5         $ ! UR                  5         f = f)Nz
            UPDATE line_item_shoulder_mount
            SET category=%s, name=%s, notes=%s, is_active=%s
            WHERE id=%s
            rp   r'   rv   rw   rx   ry   r}   r   r   "Shoulder Mount line item not foundrs   r   Tr   r   s       rG   update_line_item_shoulder_mountr     s    Dkkm J'F#w{{734[#67==?G^^de	
 <<1C8\]]4 



r   c                    [        5       n UR                  5       nUR                  SU 45        UR                  S:X  a
  [	        SSS9eUR                  5         SS0UR                  5         $ ! UR                  5         f = f)Nz0DELETE FROM line_item_shoulder_mount WHERE id=%sr   r   r   rs   r   Tr   r   s      rG   delete_line_item_shoulder_mountr     r   r   z/items/line-item-full-mountc                  v   [        5       n  U R                  SS9n UR                  S5        UR                  5       =(       d    /  U R                  5         $ ! [        R                  R
                   a.  n[        USS 5      S:X  a  / s S nAU R                  5         $ e S nAff = f! U R                  5         f = f)NTrS   z
                SELECT id, category, base_type, name, surcharge_pct, notes, price_usd
                FROM line_item_full_mount
                WHERE is_active = 1
                ORDER BY category, base_type, name
                rd   re   rf   ri   s      rG   list_items_line_item_full_mountr     rl   rm   c                 n   SS/nU H=  nU R                  U5      =(       d    SR                  5       (       a  M2  [        SSU 3S9e   [        5       n UR	                  5       nUR                  SU R                  S5      [        U R                  S5      5      U R                  S5      [        U R                  S	5      5      [        U R                  S
5      5      [        U R                  S5      5      [        U R                  S5      5      [        U R                  S5      5      [        U R                  S5      5      [        U R                  SS5      5      R                  5       S;  a  SOS4
5        UR                  5         SUR                  0UR                  5         $ ! UR                  5         f = f)Nrp   r'   rI   rq   rr   rs   z
            INSERT INTO line_item_full_mount
              (category, base_type, name, surcharge_pct, notes, price_zar, price_usd, price_eur, price_bwp, is_active)
            VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s)
            	base_typer   rv   r   r   r   r   rw   rx   ry   r}   r   r~   r   r   s        rG   create_line_item_full_mountr     s[   F#HA$"++--C:RSTRU8VWW  Dkkm J'w{{;78F#w{{?;<w{{734w{{;78w{{;78w{{;78w{{;78[#67==?G^^de	
& 	cmm$



r   z'/items/line-item-full-mount/{record_id}c                    [        5       n UR                  5       nUR                  SUR                  S5      [	        UR                  S5      5      UR                  S5      [	        UR                  S5      5      [	        UR                  S5      5      [	        UR                  S5      5      [	        UR                  S5      5      [	        UR                  S	5      5      [	        UR                  S
5      5      [        UR                  SS5      5      R                  5       S;  a  SOSU 45        UR                  S:X  a
  [        SSS9eUR                  5         SS0UR                  5         $ ! UR                  5         f = f)Na  
            UPDATE line_item_full_mount
            SET category=%s, base_type=%s, name=%s, surcharge_pct=%s, notes=%s,
                price_zar=%s, price_usd=%s, price_eur=%s, price_bwp=%s,
                is_active=%s
            WHERE id=%s
            rp   r   r'   r   rv   r   r   r   r   rw   rx   ry   r}   r   r   Full Mount line item not foundrs   r   Tr   r   s       rG   update_line_item_full_mountr     s+   Dkkm J'w{{;78F#w{{?;<w{{734w{{;78w{{;78w{{;78w{{;78[#67==?G^^de	
, <<1C8XYY4 



r   c                    [        5       n UR                  5       nUR                  SU 45        UR                  S:X  a
  [	        SSS9eUR                  5         SS0UR                  5         $ ! UR                  5         f = f)Nz,DELETE FROM line_item_full_mount WHERE id=%sr   r   r   rs   r   Tr   r   s      rG   delete_line_item_full_mountr     r   r   z/items/line-item-skinsc                  v   [        5       n  U R                  SS9n UR                  S5        UR                  5       =(       d    /  U R                  5         $ ! [        R                  R
                   a.  n[        USS 5      S:X  a  / s S nAU R                  5         $ e S nAff = f! U R                  5         f = f)NTrS   z
                SELECT id, category, skin_type, tanning_type, name, notes, add_on_price_usd
                FROM line_item_skins
                WHERE is_active = 1
                ORDER BY category, name
                rd   re   rf   ri   s      rG   list_items_line_item_skinsr   $  rl   rm   c                 n   SS/nU H=  nU R                  U5      =(       d    SR                  5       (       a  M2  [        SSU 3S9e   [        5       n UR	                  5       nUR                  SU R                  S5      [        U R                  S5      5      [        U R                  S	5      5      U R                  S5      [        U R                  S
5      5      [        U R                  S5      5      [        U R                  S5      5      [        U R                  S5      5      [        U R                  S5      5      [        U R                  SS5      5      R                  5       S;  a  SOS4
5        UR                  5         SUR                  0UR                  5         $ ! UR                  5         f = f)Nrp   r'   rI   rq   rr   rs   a  
            INSERT INTO line_item_skins
              (category, skin_type, tanning_type, name, notes, add_on_price_zar, add_on_price_usd, add_on_price_eur, add_on_price_bwp, is_active)
            VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s)
            	skin_typetanning_typerv   add_on_price_zaradd_on_price_usdadd_on_price_euradd_on_price_bwprw   rx   ry   r}   r   r~   r   r   s        rG   create_line_item_skinsr  ;  s_   F#HA$"++--C:RSTRU8VWW  Dkkm J'w{{;78w{{>:;F#w{{734w{{+=>?w{{+=>?w{{+=>?w{{+=>?[#67==?G^^de	
& 	cmm$



r   z"/items/line-item-skins/{record_id}c                    [        5       n UR                  5       nUR                  SUR                  S5      [	        UR                  S5      5      [	        UR                  S5      5      UR                  S5      [	        UR                  S5      5      [	        UR                  S5      5      [	        UR                  S5      5      [	        UR                  S	5      5      [	        UR                  S
5      5      [        UR                  SS5      5      R                  5       S;  a  SOSU 45        UR                  S:X  a
  [        SSS9eUR                  5         SS0UR                  5         $ ! UR                  5         f = f)Na  
            UPDATE line_item_skins
            SET category=%s, skin_type=%s, tanning_type=%s, name=%s, notes=%s,
                add_on_price_zar=%s, add_on_price_usd=%s, add_on_price_eur=%s, add_on_price_bwp=%s,
                is_active=%s
            WHERE id=%s
            rp   r   r   r'   rv   r  r  r  r  rw   rx   ry   r}   r   r   Skins line item not foundrs   r   Tr   r   s       rG   update_line_item_skinsr  ]  s/   Dkkm J'w{{;78w{{>:;F#w{{734w{{+=>?w{{+=>?w{{+=>?w{{+=>?[#67==?G^^de	
, <<1C8STT4 



r   c                    [        5       n UR                  5       nUR                  SU 45        UR                  S:X  a
  [	        SSS9eUR                  5         SS0UR                  5         $ ! UR                  5         f = f)Nz'DELETE FROM line_item_skins WHERE id=%sr   r   r  rs   r   Tr   r   s      rG   delete_line_item_skinsr
    si    Dkkm=	|L<<1C8STT4 



r   c                     [        5       n  U R                  5       n UR                  S5        UR                  5       (       d  UR                  S5         UR                  S5        UR                  5       (       d  UR                  S5         U R                  SS9nUR                  S5        UR                  5       =(       d    /  Vs1 s H  o3R                  S5      iM     nn/ nS	U;  a  UR                  S
5        SU;  a  UR                  S5        SU;  a  UR                  S5        SU;  a  UR                  S5        SU;  a  UR                  S5        SU;  a  UR                  S5        SU;  a  UR                  S5        SU;  a  UR                  S5        SU;  a  UR                  S5        U(       a#  UR                  SSR                  U5      -   5         UR                  S5        UR                  5       (       d  UR                  S5         U R                  SS9nUR                  S5        UR                  5       =(       d    /  Vs1 s H  o3R                  S5      iM     nn/ nS U;  a  UR                  S!5        S"U;  a  UR                  S#5        U(       a#  UR                  S$SR                  U5      -   5         UR                  S%5        UR                  5       (       d  UR                  S&5         UR                  S'5        UR                  5       (       d  UR                  S(5        UR                  S)5        UR                  5       (       d  UR                  S*5         UR                  S+5         UR                  S,5         UR                  S-5        UR                  5       (       d  UR                  S.5        UR                  S/5        UR                  5       (       d  UR                  S05         UR                  S15        UR                  5       S2   nUS2:X  a  / S3QnUR                  S4U5         UR                  S55         UR                  S65        UR                  5       (       d  UR                  S75         UR                  S85        UR                  S95        UR                  5       (       d  UR                  S:5         UR                  S;5         UR                  S<5         UR                  S=5        UR                  5       n[        U(       a  US2   b  US2   OS25      n	UR                  S>5        UR                  5       =(       d    /  Vs/ s H  o3S2   PM	     n
nU	nU
 H!  nUS?-  nS@USA 3nUR                  SBX45        M#      UR                  SC5        UR                  SD5        UR                  5       (       d  UR                  SE5        UR                  SF5        UR                  5       (       d  UR                  SG5        UR                  SH5        UR                  5       (       d  UR                  SI5        UR                  SJ5        UR                  5       (       d  UR                  SK5        UR                  SL5        UR                  5       (       d  UR                  SM5         UR                  SN5         UR                  SO5        UR                  SP5        UR                  5       (       d  UR                  SQ5        UR                  SR5        UR                  5       (       d  UR                  SS5        UR                  ST5        UR                  5       (       d  UR                  SU5         UR                  SV5         UR                  SW5        UR                  SX5        UR                  5       (       d  UR                  SY5        UR                  SZ5        UR                  5       (       d  UR                  S[5        UR                  S\5        UR                  5       (       d  UR                  S]5        UR                  S^5        UR                  5       (       d  UR                  S_5         UR                  S`5         UR                  Sa5        UR                  Sb5        UR                  5       (       d  UR                  Sc5        O6 UR                  Sd5         UR                  Se5         UR                  Sf5        UR                  Sg5        UR                  5       (       d  UR                  Sh5        SiSjSkSlSmSnSoSpSqSqSrSsSt.SuSvSwSxSySzS{S|S}S~SSSt.SSSSlSSSoSqSqSqSSSt./nU HE  nUR                  SUS   US   US   US   US   US   US   US   US   US   US   US   45        MG     U R                  5         g ! [         a     G	Nf = f! [         a     G	Npf = fs  snf ! [         a     GN3f = f! [         a     GNf = fs  snf ! [         a     GNpf = f! [         a     GNIf = f! [         a     GN"f = f! [         a     GNf = f! [         a     GNf = f! [         a     GNf = f! [         a     GN[f = f! [         a     GNZf = f! [         a     GN3f = f! [         a     GN2f = f! [         a     GNf = f! [         a     GNf = fs  snf ! [         a     GNkf = f! [         a     GNjf = f! [         a     GNVf = f! [         a     GNUf = f! [         a     GNf = f! [         a     GNf = f! [         a     GNf = f! [         a     GNf = f! [         a     GNf = f! [         a     GNf = f! [         a     GNf = f! U R                  5         f = f)NzSHOW TABLES LIKE 'company_info'aS  
                    CREATE TABLE company_info (
                      id INT AUTO_INCREMENT PRIMARY KEY,
                      company_name VARCHAR(160) NOT NULL,
                      company_registration_number VARCHAR(64) NULL,
                      company_vat_number VARCHAR(64) NULL,
                      veterinary_approval_number VARCHAR(64) NULL,
                      company_physical_address TEXT NULL,
                      company_postal_address TEXT NULL,
                      company_email VARCHAR(160) NULL,
                      company_phone_number VARCHAR(64) NULL,
                      company_mobile_number VARCHAR(64) NULL,
                      company_whatsapp_number VARCHAR(64) NULL,
                      company_website VARCHAR(160) NULL
                    ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
                    z"SHOW TABLES LIKE 'banking_details'a  
                    CREATE TABLE banking_details (
                      id INT AUTO_INCREMENT PRIMARY KEY,
                      bank_name VARCHAR(160) NOT NULL,
                      account_name VARCHAR(160) NULL,
                      account_number VARCHAR(64) NULL,
                      account_type VARCHAR(64) NULL,
                      branch_code VARCHAR(64) NULL,
                      swift_code VARCHAR(64) NULL,
                      iban VARCHAR(64) NULL,
                      bank_address TEXT NULL,
                      notes TEXT NULL
                    ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
                    TrS   z!SHOW COLUMNS FROM banking_detailsrU   	bank_namez*ADD COLUMN bank_name VARCHAR(160) NOT NULLaccount_namez)ADD COLUMN account_name VARCHAR(160) NULLaccount_numberz*ADD COLUMN account_number VARCHAR(64) NULLaccount_typez(ADD COLUMN account_type VARCHAR(64) NULLbranch_codez'ADD COLUMN branch_code VARCHAR(64) NULL
swift_codez&ADD COLUMN swift_code VARCHAR(64) NULLibanz ADD COLUMN iban VARCHAR(64) NULLbank_addressz!ADD COLUMN bank_address TEXT NULLrv   zADD COLUMN notes TEXT NULLzALTER TABLE banking_details , z SHOW TABLES LIKE 'banking_terms'a  
                    CREATE TABLE banking_terms (
                      id INT AUTO_INCREMENT PRIMARY KEY,
                      title VARCHAR(160) NOT NULL,
                      term_text TEXT NOT NULL
                    ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
                    zSHOW COLUMNS FROM banking_termstitlez&ADD COLUMN title VARCHAR(160) NOT NULL	term_textz"ADD COLUMN term_text TEXT NOT NULLzALTER TABLE banking_terms z SHOW TABLES LIKE 'master_animal'a  
                    CREATE TABLE master_animal (
                      id INT AUTO_INCREMENT PRIMARY KEY,
                      common_name VARCHAR(100) NOT NULL UNIQUE,
                      dip_pack TINYINT(1) NOT NULL DEFAULT 0,
                      tanning_of_skins TINYINT(1) NOT NULL DEFAULT 0,
                      felting_of_skins_add_on TINYINT(1) NOT NULL DEFAULT 0,
                      full_mount TINYINT(1) NOT NULL DEFAULT 0,
                      shoulder_mount TINYINT(1) NOT NULL DEFAULT 0,
                      wall_pedestal_shoulder_mount TINYINT(1) NOT NULL DEFAULT 0,
                      pedestal_shoulder_mount TINYINT(1) NOT NULL DEFAULT 0,
                      skull TINYINT(1) NOT NULL DEFAULT 0,
                      rug_mount TINYINT(1) NOT NULL DEFAULT 0,
                      africa_map_mount TINYINT(1) NOT NULL DEFAULT 0,
                      half_mount TINYINT(1) NOT NULL DEFAULT 0,
                      open_mouth_add_on TINYINT(1) NOT NULL DEFAULT 0,
                      miscellaneous_manufactured_items TINYINT(1) NOT NULL DEFAULT 0
                    ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
                    z(SHOW TABLES LIKE 'master_animal_pricing'a  
                    CREATE TABLE master_animal_pricing (
                      id INT AUTO_INCREMENT PRIMARY KEY,
                      common_name VARCHAR(120) NOT NULL UNIQUE,
                      shoulder_mount_usd VARCHAR(64) NULL,
                      shoulder_mount_eur VARCHAR(64) NULL,
                      shoulder_mount_pula VARCHAR(64) NULL,
                      shoulder_mount_zar VARCHAR(64) NULL,
                      wall_pedestal_shoulder_mount_usd VARCHAR(64) NULL,
                      wall_pedestal_shoulder_mount_eur VARCHAR(64) NULL,
                      wall_pedestal_shoulder_mount_pula VARCHAR(64) NULL,
                      wall_pedestal_shoulder_mount_zar VARCHAR(64) NULL,
                      pedestal_shoulder_mount_usd VARCHAR(64) NULL,
                      pedestal_shoulder_mount_eur VARCHAR(64) NULL,
                      pedestal_shoulder_mount_pula VARCHAR(64) NULL,
                      pedestal_shoulder_mount_zar VARCHAR(64) NULL,
                      full_mount_usd VARCHAR(64) NULL,
                      full_mount_eur VARCHAR(64) NULL,
                      full_mount_pula VARCHAR(64) NULL,
                      full_mount_zar VARCHAR(64) NULL,
                      full_mount_note VARCHAR(160) NULL,
                      skull_usd VARCHAR(64) NULL,
                      skull_eur VARCHAR(64) NULL,
                      skull_pula VARCHAR(64) NULL,
                      skull_zar VARCHAR(64) NULL,
                      rug_mount_usd VARCHAR(64) NULL,
                      rug_mount_eur VARCHAR(64) NULL,
                      rug_mount_pula VARCHAR(64) NULL,
                      rug_mount_zar VARCHAR(64) NULL,
                      tanning_of_skins_usd VARCHAR(64) NULL,
                      tanning_of_skins_eur VARCHAR(64) NULL,
                      tanning_of_skins_pula VARCHAR(64) NULL,
                      tanning_of_skins_zar VARCHAR(64) NULL,
                      felting_of_skins_add_on_usd VARCHAR(64) NULL,
                      felting_of_skins_add_on_eur VARCHAR(64) NULL,
                      felting_of_skins_add_on_pula VARCHAR(64) NULL,
                      felting_of_skins_add_on_zar VARCHAR(64) NULL,
                      africa_map_mount_usd VARCHAR(64) NULL,
                      africa_map_mount_eur VARCHAR(64) NULL,
                      africa_map_mount_pula VARCHAR(64) NULL,
                      africa_map_mount_zar VARCHAR(64) NULL,
                      half_mount_usd VARCHAR(64) NULL,
                      half_mount_eur VARCHAR(64) NULL,
                      half_mount_pula VARCHAR(64) NULL,
                      half_mount_zar VARCHAR(64) NULL,
                      dip_pack_price_usd VARCHAR(64) NULL,
                      open_mouth_add_on_usd VARCHAR(64) NULL,
                      open_mouth_add_on_eur VARCHAR(64) NULL,
                      open_mouth_add_on_pula VARCHAR(64) NULL,
                      open_mouth_add_on_zar VARCHAR(64) NULL
                    ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
                    zSHOW TABLES LIKE 'customers'a  
                CREATE TABLE customers (
                  id INT AUTO_INCREMENT PRIMARY KEY,
                  customer_unique_number VARCHAR(50) GENERATED ALWAYS AS (CONCAT('CUST-', LPAD(id, 6, '0'))) STORED UNIQUE,
                  status ENUM('Active','Inactive','On-Hold') NOT NULL DEFAULT 'Active',
                  customer_type ENUM('Export','Local') NOT NULL,
                  first_names VARCHAR(255) NOT NULL,
                  surname VARCHAR(255) NOT NULL,
                  email VARCHAR(255) NOT NULL UNIQUE,
                  contact_number VARCHAR(50) NOT NULL,
                  whatsapp_number VARCHAR(50) DEFAULT NULL,
                  physical_country VARCHAR(100) DEFAULT NULL,
                  physical_street VARCHAR(255) DEFAULT NULL,
                  physical_province_state VARCHAR(100) DEFAULT NULL,
                  physical_city VARCHAR(100) DEFAULT NULL,
                  physical_postal_code VARCHAR(20) DEFAULT NULL,
                  ship_country VARCHAR(100) DEFAULT NULL,
                  ship_street VARCHAR(255) DEFAULT NULL,
                  ship_province_state VARCHAR(100) DEFAULT NULL,
                  ship_city VARCHAR(100) DEFAULT NULL,
                  ship_postal_code VARCHAR(20) DEFAULT NULL,
                  referred_by VARCHAR(255) DEFAULT NULL,
                  preferred_currency ENUM('USD','EUR','BWP','ZAR') DEFAULT 'USD',
                  citizenship ENUM('South African Citizen','Foreign National') NOT NULL,
                  rsa_id VARCHAR(50) DEFAULT NULL,
                  passport_number VARCHAR(50) DEFAULT NULL,
                  documents TEXT DEFAULT NULL,
                  office_notes TEXT DEFAULT NULL,
                  created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
                  updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
                  CONSTRAINT chk_citizenship_id CHECK (
                    (citizenship = 'South African Citizen' AND rsa_id IS NOT NULL AND passport_number IS NULL)
                    OR (citizenship = 'Foreign National' AND passport_number IS NOT NULL AND rsa_id IS NULL)
                  )
                ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
                z2DROP TRIGGER IF EXISTS customers_set_unique_numberz
                ALTER TABLE customers
                  MODIFY customer_unique_number VARCHAR(50)
                  GENERATED ALWAYS AS (CONCAT('CUST-', LPAD(id, 6, '0'))) STORED UNIQUE
                z%SHOW TABLES LIKE 'customer_documents'af  
                    CREATE TABLE customer_documents (
                      id INT AUTO_INCREMENT PRIMARY KEY,
                      customer_id INT NOT NULL,
                      file_path VARCHAR(512) NOT NULL,
                      file_name VARCHAR(255) DEFAULT NULL,
                      mime_type VARCHAR(100) DEFAULT NULL,
                      created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
                      deleted_at TIMESTAMP NULL DEFAULT NULL,
                      INDEX idx_cust_docs_customer_id (customer_id)
                    ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
                    zSHOW TABLES LIKE 'partners'a  
                CREATE TABLE partners (
                  id INT AUTO_INCREMENT PRIMARY KEY,
                  partner_unique_number VARCHAR(50) UNIQUE,
                  status ENUM('Active','Inactive','On-Hold') NOT NULL DEFAULT 'Active',
                  partner_type ENUM('Professional Hunter','Outfitter','Professional Hunter & Outfitter','Shipping') NOT NULL,
                  company_name VARCHAR(255) NOT NULL,
                  company_vat VARCHAR(100) DEFAULT NULL,
                  company_email VARCHAR(255) NOT NULL,
                  company_contact_number VARCHAR(50) NOT NULL,
                  company_country VARCHAR(100) NOT NULL,
                  company_street VARCHAR(255) NOT NULL,
                  company_province VARCHAR(100) NOT NULL,
                  company_city VARCHAR(100) NOT NULL,
                  company_postal_code VARCHAR(20) NOT NULL,
                  first_name VARCHAR(100) NOT NULL,
                  surname VARCHAR(100) NOT NULL,
                  email VARCHAR(255) NOT NULL,
                  contact_number VARCHAR(50) NOT NULL,
                  hunting_outfitter_id VARCHAR(100) DEFAULT NULL,
                  comms_local_percent DECIMAL(5,2) DEFAULT NULL,
                  comms_export_percent DECIMAL(5,2) DEFAULT NULL,
                  outfitter_documents TEXT DEFAULT NULL,
                  professional_hunter_id VARCHAR(100) DEFAULT NULL,
                  professional_hunter_permit_type ENUM('Standard','Dangerous Game','Standard & Dangerous Game') DEFAULT NULL,
                  professional_hunter_permit_issue_date DATE DEFAULT NULL,
                  professional_hunter_permit_expiry_date DATE DEFAULT NULL,
                  professional_hunter_documents TEXT DEFAULT NULL,
                  office_notes TEXT DEFAULT NULL,
                  created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
                  updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
                ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
                zSELECT COUNT(*) FROM partnersr   ))Active	OutfitterzSavanna SafarisVAT123zinfo@savanna.examplez012-345-6789South Africaz
12 Main RdLimpopo	Polokwane0700PeterMasilelazpeter@savanna.examplez082-000-1111zOUT-001g      $@g      .@NNNNNzTrusted outfitter)r  zProfessional HunterzKudu PlainsNzoffice@kuduplains.examplez011-222-3333r  z45 Bushveld Avez
North West
Rustenburg0299LeratoKhozazlerato@kuduplains.examplez083-111-2222NNNNzPH-0099zDangerous Gamez
2024-01-10z
2026-01-09zExperienced PH)zOn-HoldShippingzWildShip LogisticsNzcontact@wildship.examplez021-555-8888r  z
78 Dock StzWestern Capez	Cape Town8001AishaKhanzaisha@wildship.examplez084-333-4444NNNNNNNNzPending reviewa  
                    INSERT INTO partners (
                      status, partner_type,
                      company_name, company_vat, company_email, company_contact_number,
                      company_country, company_street, company_province, company_city, company_postal_code,
                      first_name, surname, email, contact_number,
                      hunting_outfitter_id, comms_local_percent, comms_export_percent, outfitter_documents,
                      professional_hunter_id, professional_hunter_permit_type,
                      professional_hunter_permit_issue_date, professional_hunter_permit_expiry_date,
                      professional_hunter_documents, office_notes
                    ) VALUES (
                      %s,%s,%s,%s,%s,%s,%s,%s,%s,%s,
                      %s,%s,%s,%s,%s,%s,%s,%s,%s,%s,
                      %s,%s,%s,%s,%s
                    )
                    z1DROP TRIGGER IF EXISTS partners_set_unique_numberz$SHOW TABLES LIKE 'partner_documents'ae  
                    CREATE TABLE partner_documents (
                      id INT AUTO_INCREMENT PRIMARY KEY,
                      partner_id INT NOT NULL,
                      file_path VARCHAR(512) NOT NULL,
                      file_name VARCHAR(255) DEFAULT NULL,
                      mime_type VARCHAR(100) DEFAULT NULL,
                      created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
                      deleted_at TIMESTAMP NULL DEFAULT NULL,
                      INDEX idx_partner_docs_partner_id (partner_id)
                    ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
                    z
                ALTER TABLE partners
                  MODIFY partner_unique_number VARCHAR(50)
                  GENERATED ALWAYS AS (CONCAT('PART-', LPAD(id, 6, '0'))) STORED UNIQUE
                zSHOW TABLES LIKE 'quotes'a"
  
                CREATE TABLE quotes (
                  id INT AUTO_INCREMENT PRIMARY KEY,
                  quote_unique_number VARCHAR(50) UNIQUE,
                  partner_id INT DEFAULT NULL,
                  partner_name VARCHAR(255) DEFAULT NULL,
                  order_no VARCHAR(50) NOT NULL,
                  quote_date DATE NOT NULL,
                  order_type ENUM('Local','Export') NOT NULL,
                  customer_id INT DEFAULT NULL,
                  customer_first_names VARCHAR(255) NOT NULL,
                  customer_surname VARCHAR(255) NOT NULL,
                  customer_email VARCHAR(255) NOT NULL,
                  customer_contact_number VARCHAR(50) NOT NULL,
                  customer_country VARCHAR(100) NOT NULL,
                  customer_street VARCHAR(255) NOT NULL,
                  customer_province_state VARCHAR(100) DEFAULT NULL,
                  customer_city VARCHAR(100) NOT NULL,
                  customer_postal_code VARCHAR(20) NOT NULL,
                  company_name VARCHAR(255) NOT NULL,
                  company_physical_address VARCHAR(255) NOT NULL,
                  company_phone_number VARCHAR(50) NOT NULL,
                  company_email VARCHAR(255) NOT NULL,
                  company_vat_number VARCHAR(100) DEFAULT NULL,
                  company_registration_number VARCHAR(100) DEFAULT NULL,
                  company_logo_url VARCHAR(500) DEFAULT NULL,
                  quote_status ENUM('Draft - In Progress','Draft - For Customer Review','Draft - Customer Requested Changes','Draft - Pending Office Approval','Rejected','Accepted - Deposit Due','Accepted - Deposit Received','Accepted - Converted to Order') NOT NULL DEFAULT 'Draft - In Progress',
                  quote_currency ENUM('USD','EUR','BWP','ZAR') NOT NULL DEFAULT 'USD',
                  sub_total DECIMAL(12,2) NOT NULL DEFAULT 0.00,
                  vat_amount DECIMAL(12,2) NOT NULL DEFAULT 0.00,
                  total_amount DECIMAL(12,2) NOT NULL DEFAULT 0.00,
                  deposit_percent DECIMAL(5,2) DEFAULT NULL,
                  deposit_amount_due DECIMAL(12,2) DEFAULT NULL,
                  terms_and_conditions TEXT DEFAULT NULL,
                  payment_details TEXT DEFAULT NULL,
                  office_notes TEXT DEFAULT NULL,
                  created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
                  updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
                  deleted_at TIMESTAMP NULL DEFAULT NULL
                ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
                z/DROP TRIGGER IF EXISTS quotes_set_unique_numberzt
                ALTER TABLE quotes
                  MODIFY quote_unique_number VARCHAR(50) UNIQUE
                z
                SELECT COALESCE(MAX(CAST(SUBSTRING(quote_unique_number, 3) AS UNSIGNED)), 0)
                FROM quotes
                WHERE quote_unique_number REGEXP '^Q-[0-9]+'
                z
                SELECT id
                FROM quotes
                WHERE quote_unique_number IS NULL OR quote_unique_number = ''
                ORDER BY id
                r}   Q-04dz8UPDATE quotes SET quote_unique_number = %s WHERE id = %szx
                ALTER TABLE quotes
                  ADD COLUMN deleted_at TIMESTAMP NULL DEFAULT NULL
                z#SHOW TABLES LIKE 'quote_line_items'a  
                CREATE TABLE quote_line_items (
                  id INT AUTO_INCREMENT PRIMARY KEY,
                  quote_id INT NOT NULL,
                  item_quantity INT NOT NULL DEFAULT 1,
                  item_type ENUM('Animal','Bird','Administrative') NOT NULL,
                  species VARCHAR(255) DEFAULT NULL,
                  unit_price DECIMAL(12,2) NOT NULL DEFAULT 0.00,
                  total_price DECIMAL(12,2) NOT NULL DEFAULT 0.00,
                  detailed_instructions TEXT DEFAULT NULL,
                  line_item_status ENUM('Draft','Approved','Cancelled') NOT NULL DEFAULT 'Draft',
                  created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
                  updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
                  INDEX idx_quote_id (quote_id),
                  CONSTRAINT fk_quote_line_items_quote FOREIGN KEY (quote_id) REFERENCES quotes(id) ON DELETE CASCADE
                ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
                z,SHOW TABLES LIKE 'quote_line_item_processes'a  
                CREATE TABLE quote_line_item_processes (
                  id INT AUTO_INCREMENT PRIMARY KEY,
                  line_item_id INT NOT NULL,
                  processing_type ENUM('Dip & Pack','Skins','Full Mount','Shoulder Mount','Wall Pedestal Shoulder Mount','Pedestal Shoulder Mount','Skull Mount','Rug Mount','Africa Map Mount','Half Mount','Standalone Bases','Manufactured Product') NOT NULL,
                  processing_subtype VARCHAR(255) DEFAULT NULL,
                  INDEX idx_line_item_id (line_item_id),
                  CONSTRAINT fk_qli_process_item FOREIGN KEY (line_item_id) REFERENCES quote_line_items(id) ON DELETE CASCADE
                ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
                z"SHOW TABLES LIKE 'quote_documents'ai  
                CREATE TABLE quote_documents (
                  id INT AUTO_INCREMENT PRIMARY KEY,
                  quote_id INT NOT NULL,
                  file_url VARCHAR(500) NOT NULL,
                  file_name VARCHAR(255) DEFAULT NULL,
                  mime_type VARCHAR(100) DEFAULT NULL,
                  created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
                  INDEX idx_quote_doc_quote_id (quote_id),
                  CONSTRAINT fk_quote_documents_quote FOREIGN KEY (quote_id) REFERENCES quotes(id) ON DELETE CASCADE
                ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
                z!SHOW TABLES LIKE 'quote_hs_codes'a  
                CREATE TABLE quote_hs_codes (
                  id INT AUTO_INCREMENT PRIMARY KEY,
                  quote_id INT NOT NULL,
                  hs_code VARCHAR(50) NOT NULL,
                  INDEX idx_quote_hs_quote_id (quote_id),
                  CONSTRAINT fk_quote_hs_codes_quote FOREIGN KEY (quote_id) REFERENCES quotes(id) ON DELETE CASCADE
                ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
                zSHOW TABLES LIKE 'messages'a  
                CREATE TABLE messages (
                  id INT AUTO_INCREMENT PRIMARY KEY,
                  message_unique_number VARCHAR(50) UNIQUE,
                  customer_id INT NOT NULL,
                  customer_name VARCHAR(255) NOT NULL,
                  message_title VARCHAR(255) NOT NULL,
                  message_status ENUM('Open','Awaiting Reply','Closed','Archived') NOT NULL DEFAULT 'Open',
                  opened_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
                  last_message_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
                  assigned_staff_id INT DEFAULT NULL,
                  assigned_staff_name VARCHAR(255) DEFAULT NULL,
                  related_quote_id INT DEFAULT NULL,
                  related_quote_number VARCHAR(50) DEFAULT NULL,
                  message_priority ENUM('Normal','Urgent','Follow-Up') NOT NULL DEFAULT 'Normal',
                  created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
                  updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
                  INDEX idx_messages_customer_id (customer_id)
                ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
                z1DROP TRIGGER IF EXISTS messages_set_unique_numberz
                ALTER TABLE messages
                  MODIFY message_unique_number VARCHAR(50)
                  GENERATED ALWAYS AS (CONCAT('MSG-', LPAD(id, 6, '0'))) STORED UNIQUE
                z"SHOW TABLES LIKE 'message_entries'a  
                CREATE TABLE message_entries (
                  id INT AUTO_INCREMENT PRIMARY KEY,
                  message_id INT NOT NULL,
                  sender_role ENUM('Customer','Staff') NOT NULL,
                  sender_name VARCHAR(255) NOT NULL,
                  message_header VARCHAR(255) DEFAULT NULL,
                  message_content TEXT NOT NULL,
                  created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
                  INDEX idx_message_entries_message_id (message_id),
                  CONSTRAINT fk_message_entries_message FOREIGN KEY (message_id) REFERENCES messages(id) ON DELETE CASCADE
                ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
                z&SHOW TABLES LIKE 'message_attachments'a  
                CREATE TABLE message_attachments (
                  id INT AUTO_INCREMENT PRIMARY KEY,
                  entry_id INT NOT NULL,
                  file_url VARCHAR(500) NOT NULL,
                  file_name VARCHAR(255) DEFAULT NULL,
                  mime_type VARCHAR(100) DEFAULT NULL,
                  created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
                  INDEX idx_message_attachments_entry_id (entry_id),
                  CONSTRAINT fk_message_attachments_entry FOREIGN KEY (entry_id) REFERENCES message_entries(id) ON DELETE CASCADE
                ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
                zSHOW TABLES LIKE 'invoices'u
  
                CREATE TABLE invoices (
                  id INT AUTO_INCREMENT PRIMARY KEY,
                  invoice_unique_number VARCHAR(50) UNIQUE,
                  related_quote_id INT DEFAULT NULL,
                  related_quote_number VARCHAR(50) DEFAULT NULL,
                  partner_id INT DEFAULT NULL,
                  partner_name VARCHAR(255) DEFAULT NULL,
                  invoice_date DATE NOT NULL,
                  order_no VARCHAR(50) DEFAULT NULL,
                  order_type ENUM('Local','Export') NOT NULL,
                  customer_id INT DEFAULT NULL,
                  customer_first_names VARCHAR(255) NOT NULL,
                  customer_surname VARCHAR(255) NOT NULL,
                  customer_email VARCHAR(255) DEFAULT NULL,
                  customer_contact_number VARCHAR(50) DEFAULT NULL,
                  customer_country VARCHAR(100) NOT NULL,
                  customer_street VARCHAR(255) DEFAULT NULL,
                  customer_province_state VARCHAR(100) DEFAULT NULL,
                  customer_city VARCHAR(100) DEFAULT NULL,
                  customer_postal_code VARCHAR(20) DEFAULT NULL,
                  company_name VARCHAR(255) NOT NULL,
                  company_physical_address VARCHAR(255) NOT NULL,
                  company_phone_number VARCHAR(50) NOT NULL,
                  company_email VARCHAR(255) NOT NULL,
                  company_vat_number VARCHAR(100) DEFAULT NULL,
                  company_registration_number VARCHAR(100) DEFAULT NULL,
                  company_logo_url VARCHAR(500) DEFAULT NULL,
                  invoice_type ENUM('Pro-Forma Invoice','Tax Invoice') NOT NULL,
                  payment_type ENUM('Deposit','Installment','Final') NOT NULL,
                  invoice_status ENUM('Draft – In Progress','Issued','Partial Payment Received','Paid in Full','Withdrawn') NOT NULL DEFAULT 'Draft – In Progress',
                  invoice_currency ENUM('USD','EUR','BWP','ZAR') NOT NULL,
                  sub_total DECIMAL(12,2) NOT NULL DEFAULT 0.00,
                  vat_amount DECIMAL(12,2) NOT NULL DEFAULT 0.00,
                  total_amount DECIMAL(12,2) NOT NULL DEFAULT 0.00,
                  deposit_percent DECIMAL(5,2) DEFAULT NULL,
                  deposit_amount_due DECIMAL(12,2) DEFAULT NULL,
                  terms_and_conditions TEXT DEFAULT NULL,
                  payment_details TEXT DEFAULT NULL,
                  office_notes TEXT DEFAULT NULL,
                  created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
                  updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
                ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
                z1DROP TRIGGER IF EXISTS invoices_set_unique_numberz
                ALTER TABLE invoices
                  MODIFY invoice_unique_number VARCHAR(50)
                  GENERATED ALWAYS AS (CONCAT('INV-', LPAD(id, 6, '0'))) STORED UNIQUE
                z%SHOW TABLES LIKE 'invoice_line_items'a  
                CREATE TABLE invoice_line_items (
                  id INT AUTO_INCREMENT PRIMARY KEY,
                  invoice_id INT NOT NULL,
                  item_quantity INT NOT NULL DEFAULT 1,
                  item_type ENUM('Animal','Bird','Administrative') NOT NULL,
                  species VARCHAR(255) DEFAULT NULL,
                  processing_type ENUM('Dip & Pack','Skins','Full Mount','Shoulder Mount','Wall Pedestal Shoulder Mount','Pedestal Shoulder Mount','Skull Mount','Rug Mount','Africa Map Mount','Half Mount','Standalone Bases','Manufactured Product') DEFAULT NULL,
                  processing_subtype VARCHAR(255) DEFAULT NULL,
                  unit_price DECIMAL(12,2) NOT NULL DEFAULT 0.00,
                  total_price DECIMAL(12,2) NOT NULL DEFAULT 0.00,
                  created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
                  updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
                  INDEX idx_invoice_id (invoice_id),
                  CONSTRAINT fk_invoice_line_items_invoice FOREIGN KEY (invoice_id) REFERENCES invoices(id) ON DELETE CASCADE
                ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
                z#SHOW TABLES LIKE 'invoice_hs_codes'a  
                CREATE TABLE invoice_hs_codes (
                  id INT AUTO_INCREMENT PRIMARY KEY,
                  invoice_id INT NOT NULL,
                  hs_code VARCHAR(50) NOT NULL,
                  INDEX idx_invoice_hs_invoice_id (invoice_id),
                  CONSTRAINT fk_invoice_hs_codes_invoice FOREIGN KEY (invoice_id) REFERENCES invoices(id) ON DELETE CASCADE
                ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
                z#SHOW TABLES LIKE 'invoice_payments'ap  
                CREATE TABLE invoice_payments (
                  id INT AUTO_INCREMENT PRIMARY KEY,
                  invoice_id INT NOT NULL,
                  payment_date DATE NOT NULL,
                  amount DECIMAL(12,2) NOT NULL,
                  notes VARCHAR(255) DEFAULT NULL,
                  created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
                  INDEX idx_invoice_payments_invoice_id (invoice_id),
                  CONSTRAINT fk_invoice_payments_invoice FOREIGN KEY (invoice_id) REFERENCES invoices(id) ON DELETE CASCADE
                ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
                zSHOW TABLES LIKE 'orders'a  
                CREATE TABLE orders (
                  id INT AUTO_INCREMENT PRIMARY KEY,
                  order_unique_number VARCHAR(50) UNIQUE,
                  related_quote_id INT DEFAULT NULL,
                  related_quote_number VARCHAR(50) DEFAULT NULL,
                  related_invoice_id INT DEFAULT NULL,
                  related_invoice_number VARCHAR(50) DEFAULT NULL,
                  order_type ENUM('Export','Local') NOT NULL,
                  processing_type ENUM('Fully Processed','Dip & Pack','Fully Processed + D&P','Other') NOT NULL,
                  customer_id INT NOT NULL,
                  customer_name VARCHAR(255) NOT NULL,
                  order_delivery ENUM('Shipping Partner','Customer Collect') NOT NULL,
                  deposit_received VARCHAR(100) DEFAULT 'No',
                  instructions_finalised ENUM('Yes','No') NOT NULL DEFAULT 'No',
                  order_paid_in_full VARCHAR(100) DEFAULT 'No',
                  office_notes TEXT DEFAULT NULL,
                  created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
                  updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
                  INDEX idx_orders_customer_id (customer_id)
                ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
                z/DROP TRIGGER IF EXISTS orders_set_unique_numberz
                ALTER TABLE orders
                  MODIFY order_unique_number VARCHAR(50)
                  GENERATED ALWAYS AS (CONCAT('ORD-', LPAD(id, 6, '0'))) STORED UNIQUE
                z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) DEFAULT 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?ALTER TABLE users MODIFY COLUMN password_hash VARCHAR(255) 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, %s)
                    r,  r-  r.  r/  r0  r1  r2  r3  r4  r5  r6  r7  )r?   rV   rW   fetchoner\   rX   rZ   appendjoinexecutemanyintr[   )r^   r_   cur2ra   colsalterscountsamplesrowmax_seqmissingseqquote_id_to_fillqnosample_ordersorders                   rG   ensure_schemarL    sw   Dpkkm	KK9:<<>>,	KK<=<<>>(	;;$;/DLL<=-1]]_-B-BD-BqEE'N-BDDF$&JKT)IJt+JKT)HID(GH4'FGT!@AT)ABd":;:TYYv=NNO
	KK:;<<>>	;;$;/DLL:;-1]]_-B-BD-BqEE'N-BDDFd"FG$&BC8499V;LLM	KK:;<<>>0:	KKBC<<>>35r 	23||~~KK#%N	KKLM
	KK	KK?@<<>>$ 	12||~~KK "H5	KK78LLN1%Ez:   #,	KKKL
	KK>?<<>> 		KK 	/0||~~KK(*X	KKIJ	KK	KK ,,.CCCF,>#a&AFGKK '*lln&:&:<&:t&:G<C$+ q3s)nN+ %,	KK 	9:||~~KK* 	BC||~~KK	 	89||~~KK  	78||~~KK
 	12||~~KK.	KKKL		KK 	89||~~KK  	<=||~~KK  	12||~~KK+-^	KKKL		KK 	;<||~~KK( 	9:||~~KK
 	9:||~~KK  	/0||~~KK2	KKIJ		KK 	./||~~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	 '" 	

q  		.  		 E,  		   		 E  		6  		x  		\  		  		,  		|  		
  		*  		  		h  		  		0 =  		  		N  		  		t  		  		l  		  		6    
  x 	

s  n8 7g 7g/ ;h h "C=h  7h ;h, h'-Ah, 
7h= 7i 97n8 1i i0 7j 7n8 A j j# 7j4 k  7n8 k *k' <A*k= &k84+k=  l 1Dn8 l l0 (B%n8 m  m 1Cn8 m#  m4 18n8 *n <n n' B.n8 
g,(n8 +g,,n8 /
g=9n8 <g==n8  h 
hn8 hn8 
h$ n8 #h$$n8 'h, ,
h:6n8 9h::n8 =
in8 
in8 
in8 in8 
i-)n8 ,i--n8 0
i>:n8 =i>>n8 
jn8 jn8 
j n8 j  n8 #
j1-n8 0j11n8 4
k>n8 kn8 
kn8 kn8 
k$ n8 #k$$n8 '
k51n8 4k55n8 8k= =
ln8 
ln8 
ln8 ln8 
l-)n8 ,l--n8 0
l>:n8 =l>>n8 
mn8 mn8 
m n8 m  n8 #
m1-n8 0m11n8 4
n>n8 nn8 
nn8 nn8 
n$ n8 #n$$n8 '
n51n8 4n55n8 8o
c                  \   [        5       n  U R                  5       nSnSn[        R                  S5      nUR	                  SU45        UR                  5       nU(       a  UR	                  SXCU45        OUR	                  SX#U45        U R                  5         g! U R                  5         f = f)z6Seed or update the default admin user in the database.adminzadmin@localhostz	Admin@123(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)r?   rV   pwd_contexthashrW   r:  r[   )r^   r_   admin_usernameadmin_email
admin_hashrD  s         rG   ensure_admin_userrU  B  s    Dkkm ' %%k2
>@QRllnKKn.9
 KKgj9
 	



s   A<B B+c                   *    \ rS rSr% \\S'   \\S'   Srg)LoginRequesti[  
identifierr:   rE   N__name__
__module____qualname____firstlineno__rK   __annotations____static_attributes__rE   rF   rG   rW  rW  [  s    OMrF   rW  c                   H    \ rS rSr% \\S'   Sr\S-  \S'   Sr\S-  \S'   Sr	g)LoginResponsei`  messageNcustomer_idrolerE   )
rZ  r[  r\  r]  rK   r^  rc  r>  rd  r_  rE   rF   rG   ra  ra  `  s#    L"Kt"D#*rF   ra  c                      \ rS rSr% Sr\\   \S'   Sr\\	   \S'   \	\S'   \	\S'   \	\S'   \	\S'   \
\S	'   \	\S
'   Sr\\	   \S'   Sr\\	   \S'   Sr\\	   \S'   Sr\\	   \S'   Sr\\	   \S'   Sr\\	   \S'   Sr\\	   \S'   Sr\\	   \S'   Sr\\	   \S'   Sr\\	   \S'   Sr\\	   \S'   Sr\\	   \S'   Sr\\	   \S'   \	\S'   Sr\\	   \S'   Sr\\	   \S'   Sr\\	   \S'   Sr\\	   \S'   Srg)CustomerRecordif  Nr~   customer_unique_numberstatuscustomer_typefirst_namessurnameemailcontact_numberwhatsapp_numberphysical_countryphysical_streetphysical_province_statephysical_cityphysical_postal_codeship_countryship_streetship_province_state	ship_cityship_postal_codereferred_bypreferred_currencycitizenshiprsa_idpassport_number	documentsoffice_notesrE   )rZ  r[  r\  r]  r~   r   r>  r^  rg  rK   r   rn  ro  rp  rq  rr  rs  rt  ru  rv  rw  rx  ry  rz  r|  r}  r~  r  r_  rE   rF   rG   rf  rf  f  s:   B,0HSM0KLO%)OXc])&*hsm*%)OXc])-1Xc]1#'M8C='*.(3-."&L(3-&!%K#%)-#-#Ix}#&*hsm*!%K#%(,, FHSM %)OXc])#Ix}#"&L(3-&rF   rf  c                        \ rS rSr% \\S'   Srg)ForgotPasswordRequesti  rl  rE   N)rZ  r[  r\  r]  r   r^  r_  rE   rF   rG   r  r    s    OrF   r  c                   *    \ rS rSr% \\S'   \\S'   Srg)ResetPasswordRequesti  tokennew_passwordrE   NrY  rE   rF   rG   r  r    s    JrF   r  c                   8   \ rS rSr% Sr\\   \S'   Sr\\	   \S'   Sr
\\   \S'   Sr\\	   \S'   Sr\\   \S'   Sr\\	   \S'   \	\S	'   \	\S
'   \\S'   \	\S'   \	\S'   Sr\\	   \S'   Sr\\	   \S'   Sr\\	   \S'   Sr\\	   \S'   Sr\\	   \S'   Sr\\	   \S'   Srg)OrderRecordi  Nr~   order_unique_numberrelated_quote_idrelated_quote_numberrelated_invoice_idrelated_invoice_number
order_typeprocessing_typerc  customer_nameorder_deliverydeposit_receivedinstructions_finalisedorder_paid_in_fullr  
created_at
updated_atrE   )rZ  r[  r\  r]  r~   r   r>  r^  r  rK   r  r  r  r  r  r  r  r  r  r  r_  rE   rF   rG   r  r    s    B)-#-&*hsm**.(3-.(,,,0HSM0O&*hsm*,0HSM0(,,"&L(3-& $J$ $J$rF   r  c                      \ rS rSr% Sr\\   \S'   Sr\\	   \S'   \	\S'   \	\S'   \	\S'   Sr
\\	   \S'   \\S	'   \	\S
'   \	\S'   \	\S'   \	\S'   \	\S'   \	\S'   \	\S'   \	\S'   \\S'   \	\S'   Sr\\	   \S'   Sr\\   \S'   Sr\\   \S'   Sr\\	   \S'   Sr\\	   \S'   Sr\\	   \S'   Sr\\	   \S'   Sr\\	   \S'   Sr\\	   \S'   Sr\\	   \S'   Srg)PartnerRecordi  Nr~   partner_unique_numberrh  partner_typecompany_namecompany_vatcompany_emailcompany_contact_numbercompany_countrycompany_streetcompany_provincecompany_citycompany_postal_code
first_namerk  rl  rm  hunting_outfitter_idcomms_local_percentcomms_export_percentoutfitter_documentsprofessional_hunter_idprofessional_hunter_permit_type%professional_hunter_permit_issue_date&professional_hunter_permit_expiry_dateprofessional_hunter_documentsr  rE   )rZ  r[  r\  r]  r~   r   r>  r^  r  rK   r  r   r  r  floatr  r  r  r  r  r  r  r  r_  rE   rF   rG   r  r    s   B+/8C=/K!%K#%OLO*.(3-.+/%/,0(5/0)-#-,0HSM059#Xc]9;?)8C=?<@*HSM@37!8C=7"&L(3-&rF   r  c                       \ rS rSr% Sr\\   \S'   \\S'   Sr	\\   \S'   Sr
\\   \S'   Sr\\   \S'   Sr\\   \S'   Sr\\   \S	'   Sr\\   \S
'   Sr\\   \S'   Sr\\   \S'   Sr\\   \S'   Sr\\   \S'   Srg)CompanyInfoRecordi  Nr~   r  company_registration_numbercompany_vat_numberveterinary_approval_numbercompany_physical_addresscompany_postal_addressr  company_phone_numbercompany_mobile_numbercompany_whatsapp_numbercompany_websiterE   )rZ  r[  r\  r]  r~   r   r>  r^  rK   r  r  r  r  r  r  r   r  r  r  r  r_  rE   rF   rG   r  r    s    B15#5(,,044.2hsm2,0HSM0(,M8H%,*.(3-.+/8C=/-1Xc]1%)OXc])rF   r  c                       \ rS rSr% Sr\\   \S'   \\S'   Sr	\\   \S'   Sr
\\   \S'   Sr\\   \S'   Sr\\   \S'   Sr\\   \S	'   Sr\\   \S
'   Sr\\   \S'   Sr\\   \S'   Srg)BankingDetailsRecordi  Nr~   r  r  r  r  r  r  r  r  rv   rE   )rZ  r[  r\  r]  r~   r   r>  r^  rK   r  r  r  r  r  r  r  rv   r_  rE   rF   rG   r  r    s    BN"&L(3-&$(NHSM("&L(3-&!%K#% $J$D(3-"&L(3-&E8C=rF   r  c                   >    \ rS rSr% Sr\\   \S'   \\S'   \\S'   Sr	g)BankingTermRecordi  Nr~   r  r  rE   )
rZ  r[  r\  r]  r~   r   r>  r^  rK   r_  rE   rF   rG   r  r    s    BJNrF   r  c                       \ rS rSr% Sr\\   \S'   \\S'   Sr	\
\S'   Sr\
\S'   Sr\
\S'   Sr\
\S	'   Sr\
\S
'   Sr\
\S'   Sr\
\S'   Sr\
\S'   Sr\
\S'   Sr\
\S'   Sr\
\S'   Sr\
\S'   Sr\
\S'   Srg)MasterAnimalRecordi  Nr~   common_nameFdip_packtanning_of_skinsfelting_of_skins_add_on
full_mountshoulder_mountwall_pedestal_shoulder_mountpedestal_shoulder_mountskull	rug_mountafrica_map_mount
half_mountopen_mouth_add_on miscellaneous_manufactured_itemsrE   )rZ  r[  r\  r]  r~   r   r>  r^  rK   r  boolr  r  r  r  r  r  r  r  r  r  r  r  r_  rE   rF   rG   r  r    s    BHd"d"$)T)J ND ). $.$)T)E4It"d"J#t#-2$d2rF   r  c                      \ rS rSr% Sr\\   \S'   \\S'   Sr	\\   \S'   Sr
\\   \S'   Sr\\   \S'   Sr\\   \S'   Sr\\   \S	'   Sr\\   \S
'   Sr\\   \S'   Sr\\   \S'   Sr\\   \S'   Sr\\   \S'   Sr\\   \S'   Sr\\   \S'   Sr\\   \S'   Sr\\   \S'   Sr\\   \S'   Sr\\   \S'   Sr\\   \S'   Sr\\   \S'   Sr\\   \S'   Sr\\   \S'   Sr\\   \S'   Sr\\   \S'   Sr\\   \S'   Sr \\   \S'   Sr!\\   \S'   Sr"\\   \S'   Sr#\\   \S'   Sr$\\   \S '   Sr%\\   \S!'   Sr&\\   \S"'   Sr'\\   \S#'   Sr(\\   \S$'   Sr)\\   \S%'   Sr*\\   \S&'   Sr+\\   \S''   Sr,\\   \S('   Sr-\\   \S)'   Sr.\\   \S*'   Sr/\\   \S+'   Sr0\\   \S,'   Sr1\\   \S-'   Sr2\\   \S.'   Sr3\\   \S/'   Sr4\\   \S0'   Sr5\\   \S1'   Sr6\\   \S2'   S3r7g)4MasterAnimalPricingRecordi  Nr~   r  shoulder_mount_usdshoulder_mount_eurshoulder_mount_pulashoulder_mount_zar wall_pedestal_shoulder_mount_usd wall_pedestal_shoulder_mount_eur!wall_pedestal_shoulder_mount_pula wall_pedestal_shoulder_mount_zarpedestal_shoulder_mount_usdpedestal_shoulder_mount_eurpedestal_shoulder_mount_pulapedestal_shoulder_mount_zarfull_mount_usdfull_mount_eurfull_mount_pulafull_mount_zarfull_mount_note	skull_usd	skull_eur
skull_pula	skull_zarrug_mount_usdrug_mount_eurrug_mount_pularug_mount_zartanning_of_skins_usdtanning_of_skins_eurtanning_of_skins_pulatanning_of_skins_zarfelting_of_skins_add_on_usdfelting_of_skins_add_on_eurfelting_of_skins_add_on_pulafelting_of_skins_add_on_zarafrica_map_mount_usdafrica_map_mount_eurafrica_map_mount_pulaafrica_map_mount_zarhalf_mount_usdhalf_mount_eurhalf_mount_pulahalf_mount_zardip_pack_price_usdopen_mouth_add_on_usdopen_mouth_add_on_europen_mouth_add_on_pulaopen_mouth_add_on_zarrE   )8rZ  r[  r\  r]  r~   r   r>  r^  rK   r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r_  rE   rF   rG   r  r    s   B(,,(,,)-#-(,,6:$hsm:6:$hsm:7;%x};6:$hsm:15#515#526 (3-615#5$(NHSM($(NHSM(%)OXc])$(NHSM(%)OXc])#Ix}##Ix}# $J$#Ix}##'M8C='#'M8C='$(NHSM(#'M8C='*.(3-.*.(3-.+/8C=/*.(3-.15#515#526 (3-615#5*.(3-.*.(3-.+/8C=/*.(3-.$(NHSM($(NHSM(%)OXc])$(NHSM((,,+/8C=/+/8C=/,0HSM0+/8C=/rF   r  c                       \ rS rSr% Sr\\   \S'   \\S'   \\S'   Sr	\\   \S'   Sr
\\   \S'   Sr\\   \S'   Sr\\   \S	'   Sr\\   \S
'   Sr\\   \S'   Srg)DipPackPricingRecordi*	  Nr~   animal_groupcompositionrv   r   r   r   r   hs_coderE   rZ  r[  r\  r]  r~   r   r>  r^  rK   rv   r   r   r   r   r  r_  rE   rF   rG   r  r  *	  p    BE8C=#Ix}##Ix}##Ix}##Ix}#!GXc]!rF   r  c                   &    \ rS rSr% \\   \S'   Srg)EnumUpdateRequesti5	  valuesrE   N)rZ  r[  r\  r]  listrK   r^  r_  rE   rF   rG   r  r  5	  s    IrF   r  c                       \ rS rSr% Sr\\   \S'   \\S'   \\S'   Sr	\\   \S'   Sr
\\   \S'   Sr\\   \S'   Sr\\   \S	'   Sr\\   \S
'   Sr\\   \S'   Srg)r  i8	  Nr~   r   r  rv   r   r   r   r   r  rE   r  rE   rF   rG   r  r  8	  r  rF   c                   4    \ rS rSr% \\S'   Sr\\   \S'   Srg)QuoteLineItemProcessRecordiD	  r  Nprocessing_subtyperE   )	rZ  r[  r\  r]  rK   r^  r  r   r_  rE   rF   rG   r  r  D	  s    (,,rF   r  c                       \ rS rSr% \\S'   \\S'   Sr\\   \S'   \	\S'   \	\S'   Sr
\\   \S'   S	r\\S
'   / r\\   \S'   Srg)QuoteLineItemRecordiI	  item_quantity	item_typeNspecies
unit_pricetotal_pricedetailed_instructionsDraftline_item_status	processesrE   )rZ  r[  r\  r]  r>  r^  rK   r  r   r  r  r  r  r  r  r_  rE   rF   rG   r  r  I	  sQ    N!GXc]!+/8C=/#c#24It./4rF   r  c                      \ rS rSr% Sr\\   \S'   Sr\\	   \S'   \	\S'   \	\S'   \	\S'   Sr
\\   \S'   \	\S	'   \	\S
'   \	\S'   \	\S'   \	\S'   \	\S'   Sr\\	   \S'   \	\S'   \	\S'   \	\S'   \	\S'   \	\S'   \	\S'   Sr\\	   \S'   Sr\\	   \S'   Sr\\	   \S'   Sr\\	   \S'   \	\S'   Sr\\   \S'   Sr\\   \S'   Sr\\   \S'   Sr\\   \S'   Sr\\   \S'   Sr\\	   \S '   Sr\\	   \S!'   Sr\\	   \S"'   / r\\   \S#'   / r\\	   \S$'   S%rg)&QuoteCreateRequestiT	  N
partner_idpartner_nameorder_no
quote_dater  rc  customer_first_namescustomer_surnamecustomer_emailcustomer_contact_numbercustomer_countrycustomer_streetcustomer_province_statecustomer_citycustomer_postal_coder  r  r  r  r  r  company_logo_urlquote_statusquote_currency	sub_total
vat_amounttotal_amountdeposit_percentdeposit_amount_dueterms_and_conditionspayment_detailsr  
line_itemshs_codesrE   )rZ  r[  r\  r]  r  r   r>  r^  r  rK   rc  r$  r  r  r'  r(  r*  r  r+  r,  r-  r.  r/  r0  r  r1  r  r  r2  r_  rE   rF   rG   r  r  T	  sc    $J$"&L(3-&MOO!%K#%  -1Xc]1!!(,,15#5&*hsm*"&L(3-&!%Ix%"&J&$(L(5/('+OXe_+*..*.(3-.%)OXc])"&L(3-&,.J().Hd3irF   r  startupc                  ,    [        5         [        5         g N)rL  rU  rE   rF   rG   
on_startupr6  	  s    OrF   z/healthc                     S n  [        5       n U R                  5       nUR                  S5        UR                  5         SSS. U b  U R	                  5         $ $ ! [
         a     $ f = f! [
         a>  nSS[        U5      S.s S nA U b  U R	                  5         $ $ ! [
         a     $ f = fS nAff = f!  U b  U R	                  5         f f ! [
         a     f f = f= f)NzSELECT 1T)okdbF)r8  r9  error)r?   rV   rW   r:  r[   r\   rK   ri   s      rG   healthr;  	  s    DkkmJ$'	

   		  :%#a&99	

   		:	

   		sw   ?A) A
A&%A&)
B13B,B1B4 B
B)(B),B11B4 4C6C	C
CCCCz	/partnersc                      [        5       n  U R                  SS9nUR                  S5        UR                  5       U R	                  5         $ ! U R	                  5         f = f)NTrS   a  
            SELECT id, partner_unique_number, status, partner_type,
                   company_name, company_vat, company_email, company_contact_number,
                   company_country, company_street, company_province, company_city, company_postal_code,
                   first_name, surname, email, contact_number,
                   hunting_outfitter_id, comms_local_percent, comms_export_percent, outfitter_documents,
                   professional_hunter_id, professional_hunter_permit_type,
                   professional_hunter_permit_issue_date, professional_hunter_permit_expiry_date,
                   professional_hunter_documents, office_notes, created_at
            FROM partners
            ORDER BY created_at DESC
            r?   rV   rW   rX   r[   r^   r_   s     rG   list_partnersr?  	  sN    DkkTk*	
 ||~



   /A Az/company-infoc                      [        5       n  U R                  SS9nUR                  S5        UR                  5       U R	                  5         $ ! U R	                  5         f = f)NTrS   a"  
            SELECT id,
                   company_name,
                   company_registration_number,
                   company_vat_number,
                   veterinary_approval_number,
                   company_physical_address,
                   company_postal_address,
                   company_email,
                   company_phone_number,
                   company_mobile_number,
                   company_whatsapp_number,
                   company_website
            FROM company_info
            ORDER BY id DESC
            r=  r>  s     rG   list_company_inforB  	  sN    DkkTk*	
$ ||~



r@  z/company-info/{record_id}c                     [        5       n UR                  SS9nUR                  SU 45        UR                  5       nU(       d
  [	        SSS9eUUR                  5         $ ! UR                  5         f = f)NTrS   a  
            SELECT id,
                   company_name,
                   company_registration_number,
                   company_vat_number,
                   veterinary_approval_number,
                   company_physical_address,
                   company_postal_address,
                   company_email,
                   company_phone_number,
                   company_mobile_number,
                   company_whatsapp_number,
                   company_website
            FROM company_info
            WHERE id = %s
            r   Record not foundrs   r?   rV   rW   r:  r   r[   r   r^   r_   rD  s       rG   get_company_inforG  	  sk    DkkTk*  L#	
& llnC8JKK



   AA! !A3bodyc                    [        5       n UR                  5       nUR                  SU R                  [	        U R
                  5      [	        U R                  5      [	        U R                  5      [	        U R                  5      [	        U R                  5      [	        U R                  5      [	        U R                  5      [	        U R                  5      [	        U R                  5      [	        U R                  5      45        UR                  nUR!                  5         SU0UR#                  5         $ ! UR#                  5         f = f)Na  
            INSERT INTO company_info (
              company_name,
              company_registration_number,
              company_vat_number,
              veterinary_approval_number,
              company_physical_address,
              company_postal_address,
              company_email,
              company_phone_number,
              company_mobile_number,
              company_whatsapp_number,
              company_website
            ) VALUES (
              %s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s
            )
            r~   )r?   rV   rW   r  rO   r  r  r  r  r  r  r  r  r  r  r   r   r[   rI  r^   r_   new_ids       rG   create_company_inforM  	  s    D&kkm$ !!t??@t667t>>?t<<=t::;t112t889t99:t;;<t334%	
@ f~



s   DD1 1Ec                    [        5       n UR                  5       nUR                  SUR                  [	        UR
                  5      [	        UR                  5      [	        UR                  5      [	        UR                  5      [	        UR                  5      [	        UR                  5      [	        UR                  5      [	        UR                  5      [	        UR                  5      [	        UR                  5      U 45        UR                  S:X  a
  [!        SSS9eUR#                  5         SS0UR%                  5         $ ! UR%                  5         f = f)Na  
            UPDATE company_info SET
              company_name=%s,
              company_registration_number=%s,
              company_vat_number=%s,
              veterinary_approval_number=%s,
              company_physical_address=%s,
              company_postal_address=%s,
              company_email=%s,
              company_phone_number=%s,
              company_mobile_number=%s,
              company_whatsapp_number=%s,
              company_website=%s
            WHERE id = %s
            r   r   rD  rs   r   T)r?   rV   rW   r  rO   r  r  r  r  r  r  r  r  r  r  r   r   r   r[   r   rI  r^   r_   s       rG   update_company_inforP  
  s
   D&kkm  !!t??@t667t>>?t<<=t::;t112t889t99:t;;<t334!	
> <<1C8JKK4 



s   D#E   Ec                     [        5       n UR                  5       nUR                  SU 45        UR                  S:X  a
  [	        SSS9eSS0UR                  5         $ ! UR                  5         f = f)Nz&DELETE FROM company_info WHERE id = %sr   r   rD  rs   r   Tr?   rV   rW   r   r   r[   r   s      rG   delete_company_inforS  G
  s`    Dkkm<ylK<<1C8JKK4 



   A A A/z/banking-detailsc                      [        5       n  U R                  SS9nUR                  S5        UR                  5       =(       d    / nUU R	                  5         $ ! U R	                  5         f = f)NTrS   z.SELECT * FROM banking_details ORDER BY id DESCr=  )r^   r_   r`   s      rG   list_banking_detailsrV  U
  sR    DkkTk*DE||~#



s   :A A)z/banking-details/{record_id}c                     [        5       n UR                  SS9nUR                  SU 45        UR                  5       nU(       d
  [	        SSS9eUUR                  5         $ ! UR                  5         f = f)NTrS   z+SELECT * FROM banking_details WHERE id = %sr   rD  rs   rE  rF  s       rG   get_banking_detailrX  b
  sb    DkkTk*AI<PllnC8JKK



rH  c                    [        5       n UR                  5       n[        S5      nSU R                  4S[	        U R
                  5      4S[	        U R                  5      4S[	        U R                  5      4S[	        U R                  5      4S[	        U R                  5      4S[	        U R                  5      4S	[	        U R                  5      4S
[	        U R                  5      4/	nU VVs/ s H  u  pVXS;   d  M  UPM     nnnU VVs/ s H  u  pXXS;   d  M  UPM     n	nnSR                  S/[        U	5      -  5      n
UR                  SSR                  U5       SU
 S3[!        U	5      5        UR"                  nUR%                  5         SU0UR'                  5         $ s  snnf s  snnf ! UR'                  5         f = f)Nbanking_detailsr  r  r  r  r  r  r  r  rv   ,%szINSERT INTO banking_details (
) VALUES ()r~   )r?   rV   rb   r  rO   r  r  r  r  r  r  r  rv   r<  lenrW   tupler   r   r[   rI  r^   r_   r@  allowedc_insert_colsrN   insert_valsplaceholdersrL  s               rG   create_banking_detailrh  p
  s   Dkkm!"34$..)^D,=,=>?~d.A.ABC^D,=,=>?N4+;+;<=>$//:;^DII./^D,=,=>?nTZZ01

 &-:WTQ	qW:%,:WTQ	qW:xx[)9 9:+CHH[,A+B*\NZ[\+	
 f~

 ;: 	

s7   CF+ +F:F F+ F%F%A1F+ F+ +F=c                    [        5       n UR                  5       n[        S5      n/ n/ nSU;   a,  UR                  S5        UR                  UR                  5        SU;   a5  UR                  S5        UR                  [        UR                  5      5        SU;   a5  UR                  S5        UR                  [        UR                  5      5        SU;   a5  UR                  S	5        UR                  [        UR                  5      5        S
U;   a5  UR                  S5        UR                  [        UR                  5      5        SU;   a5  UR                  S5        UR                  [        UR                  5      5        SU;   a5  UR                  S5        UR                  [        UR                  5      5        SU;   a5  UR                  S5        UR                  [        UR                  5      5        SU;   a5  UR                  S5        UR                  [        UR                  5      5        U(       d  SS0UR                  5         $ UR                  U 5        UR                  SSR!                  U5       S3[#        U5      5        UR$                  S:X  a
  ['        SSS9eUR)                  5         SS0UR                  5         $ ! UR                  5         f = f)NrZ  r  zbank_name=%sr  zaccount_name=%sr  zaccount_number=%sr  zaccount_type=%sr  zbranch_code=%sr  zswift_code=%sr  ziban=%sr  zbank_address=%srv   znotes=%sr   TzUPDATE banking_details SET r   WHERE id = %sr   r   rD  rs   )r?   rV   rb   r;  r  rO   r  r  r  r  r  r  r  rv   r[   rW   r<  r`  r   r   r   r   rI  r^   r_   r@  updatesparamss          rG   update_banking_detailrn  
  s*   D kkm!"34$NN>*FMM$..,IT!NN,-v}}^DL]L]=^/_t#NN./~dNaNa?b1cT!NN,-v}}^DL]L]=^/_D NN+,fmmN4K[K[<\.]4NN?+V]]>$//;Z-[T>NN9%v}}^DII5N'OT!NN,-v}}^DL]L]=^/_d?NN:&nTZZ6P(Qt$ 	

 	i 1$))G2D1E^TV[\bVcd<<1C8JKK4 



s   H3K A,K Kc                     [        5       n UR                  5       nUR                  SU 45        UR                  S:X  a
  [	        SSS9eSS0UR                  5         $ ! UR                  5         f = f)Nz)DELETE FROM banking_details WHERE id = %sr   r   rD  rs   r   TrR  r   s      rG   delete_banking_detailrp  
  s`    Dkkm?)N<<1C8JKK4 



rT  z/banking-termsc                  0   [        5       n  U R                  SS9nUR                  S5        UR                  5       =(       d    / nS[        S[        4S jnU Vs/ s H
  oC" U5      PM     snU R                  5         $ s  snf ! U R                  5         f = f)NTrS   z,SELECT * FROM banking_terms ORDER BY id DESCrD  rQ   c           
      :   U R                  S5      =(       d    S nU(       d  U R                  S5      =(       d)    U R                  S5      =(       d    U R                  S5      nU R                  S5      =(       dA    U R                  S5      =(       d)    U R                  S5      =(       d    U R                  S5      nU(       a  U(       a  U S	U 3R                  5       nO,U=(       d#    U=(       d    U R                  S
5      =(       d    SnU R                  S5      =(       d    S nUcz  U R                  S5      =(       db    U R                  S5      =(       dJ    U R                  S5      =(       d2    U R                  S5      =(       d    U R                  S5      =(       d    SnU R                  S5      nU(       a  U(       a  U SU 3OSU 3nU R                  S5      U=(       d    SU=(       d    SU R                  S
5      U R                  S5      =(       d)    U R                  S5      =(       d    U R                  S5      U R                  S5      =(       dA    U R                  S5      =(       d)    U R                  S5      =(       d    U R                  S5      U R                  S5      =(       dY    U R                  S5      =(       dA    U R                  S5      =(       d)    U R                  S5      =(       d    U R                  S5      U R                  S5      S.$ )Nr  r   term_sectionheadingclause_codecoder'   label doc_contextrI   r  clause_texttextcontentrM   descriptionnote
Note: Note: r~   )r~   r  r  ry  r   ru  rz  r~  )rZ   rL   )rD  r  section_rawclause_code_rawr  r~  s         rG   	normalize%list_banking_terms.<locals>.normalize
  sm   GGG$,E!ggi0aCGGN4KaswwW`Oa"%''-"8"rCGGFO"rswwW]"rbebibijqbr?*m1_,=>DDFE+Z{Zcggm>TZXZE,4I GGM2  Pcggfo  PQZI[  P_b_f_fgn_o  Psvszsz  |I  tJ  P  NP	776?D<Eyk$8VTXSY?	 ggdm"&_""ww}5779-^1H^CGGT]L^"ww}5ooCGGTZOo_b_f_fgn_o"ww}5   M   MCGGT]L^   Mbebibijqbr   Mvyv}v}  L  wM	 	rF   )r?   rV   rW   rX   rY   r[   )r^   r_   r`   r  ra   s        rG   list_banking_termsr  
  s    D#kkTk*BC||~#	4 	D 	: '++d	!d+

 ,

s   AB A>+B >B Bz/banking-terms/{record_id}c                    [        5       n UR                  SS9nUR                  SU 45        UR                  5       nU(       d
  [	        SSS9eUR                  S5      =(       d)    UR                  S5      =(       d    UR                  S	5      nUR                  S
5      =(       dA    UR                  S5      =(       d)    UR                  S5      =(       d    UR                  S5      nUR                  S5      =(       dO    U(       a  U(       a  U SU 3R                  5       O+U=(       d#    U=(       d    UR                  S5      =(       d    SnUR                  S5      =(       dz    UR                  S5      =(       db    UR                  S5      =(       dJ    UR                  S5      =(       d2    UR                  S5      =(       d    UR                  S5      =(       d    SnUR                  S5      nU(       a  U(       a  U SU 3OSU 3nUR                  S5      U=(       d    SU=(       d    SS.UR                  5         $ ! UR                  5         f = f)NTrS   z)SELECT * FROM banking_terms WHERE id = %sr   rD  rs   r   rs  rt  ru  rv  r'   rw  r  rx  ry  rI   r  rz  r{  r|  rM   r}  r~  r  r  r~   )r~   r  r  )r?   rV   rW   r:  r   rZ   rL   r[   )	r   r^   r_   rD  r   ru  r  r  r~  s	            rG   get_banking_termr  
  s   DkkTk*?)NllnC8JKK'')$U(?U3779CUggm,ff3776?fVYV]V]^eVf   b7Wby+%?%E%E%Git  j`x  j`  DG  DK  DK  LY  DZ  j`  ^`GGK(  `CGGM,B  `cggfo  `Y\Y`Y`ajYk  `orovovw~o  `  DG  DK  DK  LY  DZ  `  ^`	wwv8A9+XdV4PTvIwwt}u{VXZ



s   H'I Ic                 :   [        5       n UR                  5       n[        S5      nSU R                  4SU R                  4/nU VVs/ s H  u  pVXS;   d  M  UPM     nnnU VVs/ s H  u  pXXS;   d  M  UPM     n	nnSR                  S/[        U	5      -  5      n
UR                  SSR                  U5       SU
 S3[        U	5      5        UR                  nUR                  5         S	U0UR                  5         $ s  snnf s  snnf ! UR                  5         f = f)
Nbanking_termsr  r  r[  r\  zINSERT INTO banking_terms (r]  r^  r~   )r?   rV   rb   r  r  r<  r_  rW   r`  r   r   r[   ra  s               rG   create_banking_termr    s    Dkkm!/2djj!$..)
 &-:WTQ	qW:%,:WTQ	qW:xx[)9 9:)#((;*?)@
<.XYZ+	
 f~

 ;: 	

s6   <D C<C<D %D4D:A1D <D Dc                 x   [        5       n UR                  5       n[        S5      n/ n/ nSU;   a,  UR                  S5        UR                  UR                  5        SU;   a,  UR                  S5        UR                  UR
                  5        U(       d  SS0UR                  5         $ UR                  U 5        UR                  SS	R                  U5       S
3[        U5      5        UR                  S:X  a
  [        SSS9eUR                  5         SS0UR                  5         $ ! UR                  5         f = f)Nr  r  ztitle=%sr  zterm_text=%sr   TzUPDATE banking_terms SET r  rj  r   r   rD  rs   )r?   rV   rb   r;  r  r  r[   rW   r<  r`  r   r   r   rk  s          rG   update_banking_termr    s    Dkkm!/2d?NN:&djj(A$NN>*FMM$..,It$ 	

 	i /		'0B/C>RTYZ`Tab<<1C8JKK4 



s   BD' *A,D' 'D9c                     [        5       n UR                  5       nUR                  SU 45        UR                  S:X  a
  [	        SSS9eSS0UR                  5         $ ! UR                  5         f = f)Nz'DELETE FROM banking_terms WHERE id = %sr   r   rD  rs   r   TrR  r   s      rG   delete_banking_termr  3  `    Dkkm=	|L<<1C8JKK4 



rT  z/master-animalsc                  h   [        5       n  U R                  SS9nUR                  S5        UR                  5       =(       d    / nU HB  n[	        UR                  5       5       H"  nUS:w  d  M  US:w  d  M  [        X4   5      X4'   M$     MD     UU R                  5         $ ! U R                  5         f = f)NTrS   a  
            SELECT id, common_name, dip_pack, tanning_of_skins, felting_of_skins_add_on,
                   full_mount, shoulder_mount, wall_pedestal_shoulder_mount, pedestal_shoulder_mount,
                   skull, rug_mount, africa_map_mount, half_mount, open_mouth_add_on, miscellaneous_manufactured_items
            FROM master_animal
            ORDER BY common_name
            r~   r  )r?   rV   rW   rX   r  keysr  r[   )r^   r_   r`   ra   r   s        rG   list_master_animalsr  ?  s    DkkTk*	
 ||~#A!&&(^9m!3:AD $  



s   AB .B 6B B1c                 
   [        5       n UR                  5       nUR                  SU R                  R	                  5       [        [        U R                  5      5      [        [        U R                  5      5      [        [        U R                  5      5      [        [        U R                  5      5      [        [        U R                  5      5      [        [        U R                  5      5      [        [        U R                  5      5      [        [        U R                  5      5      [        [        U R                  5      5      [        [        U R                   5      5      [        [        U R"                  5      5      [        [        U R$                  5      5      [        [        U R&                  5      5      45        UR(                  nUR+                  5         SU0UR-                  5         $ ! UR-                  5         f = f)Na  
            INSERT INTO master_animal (
              common_name, dip_pack, tanning_of_skins, felting_of_skins_add_on,
              full_mount, shoulder_mount, wall_pedestal_shoulder_mount, pedestal_shoulder_mount,
              skull, rug_mount, africa_map_mount, half_mount, open_mouth_add_on, miscellaneous_manufactured_items
            ) VALUES (
              %s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s
            )
            r~   )r?   rV   rW   r  rL   r>  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r   r   r[   rK  s       rG   create_master_animalr  X  s_   D!kkm   &&(D'(D../0D5567D)*D,,-.D::;<D5567D$%D()D../0D)*D//01D>>?@	
6 f~



s   GG0 0Hz/master-animals/{animal_id}	animal_idc                 (   [        5       n UR                  5       nUR                  SUR                  R	                  5       [        [        UR                  5      5      [        [        UR                  5      5      [        [        UR                  5      5      [        [        UR                  5      5      [        [        UR                  5      5      [        [        UR                  5      5      [        [        UR                  5      5      [        [        UR                  5      5      [        [        UR                  5      5      [        [        UR                   5      5      [        [        UR"                  5      5      [        [        UR$                  5      5      [        [        UR&                  5      5      U 45        UR(                  S:X  a
  [+        SSS9eUR-                  5         SS0UR/                  5         $ ! UR/                  5         f = f)Na3  
            UPDATE master_animal SET
              common_name=%s,
              dip_pack=%s,
              tanning_of_skins=%s,
              felting_of_skins_add_on=%s,
              full_mount=%s,
              shoulder_mount=%s,
              wall_pedestal_shoulder_mount=%s,
              pedestal_shoulder_mount=%s,
              skull=%s,
              rug_mount=%s,
              africa_map_mount=%s,
              half_mount=%s,
              open_mouth_add_on=%s,
              miscellaneous_manufactured_items=%s
            WHERE id = %s
            r   r   Animal not foundrs   r   T)r?   rV   rW   r  rL   r>  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r   r   r   r[   )r  rI  r^   r_   s       rG   update_master_animalr    su   D,kkm&   &&(D'(D../0D5567D)*D,,-.D::;<D5567D$%D()D../0D)*D//01D>>?@'$	
J <<1C8JKK4 



s   G"G? ?Hc                     [        5       n UR                  5       nUR                  SU 45        UR                  S:X  a
  [	        SSS9eSS0UR                  5         $ ! UR                  5         f = f)Nz'DELETE FROM master_animal WHERE id = %sr   r   r  rs   r   TrR  )r  r^   r_   s      rG   delete_master_animalr    r  rT  z/master-animal-pricingc                      [        5       n  U R                  SS9nUR                  S5        UR                  5       =(       d    /  U R	                  5         $ ! U R	                  5         f = f)NTrS   zj
            SELECT *
            FROM master_animal_pricing
            ORDER BY common_name
            r=  r>  s     rG   list_master_animal_pricingr    sV    DkkTk*	
 ||~##



s   8A A(c                 b   [        5       n UR                  5       nUR                  S/ U R                  PU R                  PU R
                  PU R                  PU R                  PU R                  PU R                  PU R                  PU R                  PU R                  PU R                  PU R                  PU R                  PU R                   PU R"                  PU R$                  PU R&                  P[)        U R*                  5      PU R,                  PU R.                  PU R0                  PU R2                  PU R4                  PU R6                  PU R8                  PU R:                  PU R<                  PU R>                  PU R@                  PU RB                  PU RD                  PU RF                  PU RH                  PU RJ                  PU RL                  PU RN                  PU RP                  PU RR                  PU RT                  PU RV                  PU RX                  PU RZ                  PU R\                  PU R^                  PU R`                  PU Rb                  PU Rd                  P75        URf                  nURi                  5         SU0URk                  5         $ ! URk                  5         f = f)Na-  
            INSERT INTO master_animal_pricing (
              common_name,
              shoulder_mount_usd, shoulder_mount_eur, shoulder_mount_pula, shoulder_mount_zar,
              wall_pedestal_shoulder_mount_usd, wall_pedestal_shoulder_mount_eur, wall_pedestal_shoulder_mount_pula, wall_pedestal_shoulder_mount_zar,
              pedestal_shoulder_mount_usd, pedestal_shoulder_mount_eur, pedestal_shoulder_mount_pula, pedestal_shoulder_mount_zar,
              full_mount_usd, full_mount_eur, full_mount_pula, full_mount_zar, full_mount_note,
              skull_usd, skull_eur, skull_pula, skull_zar,
              rug_mount_usd, rug_mount_eur, rug_mount_pula, rug_mount_zar,
              tanning_of_skins_usd, tanning_of_skins_eur, tanning_of_skins_pula, tanning_of_skins_zar,
              felting_of_skins_add_on_usd, felting_of_skins_add_on_eur, felting_of_skins_add_on_pula, felting_of_skins_add_on_zar,
              africa_map_mount_usd, africa_map_mount_eur, africa_map_mount_pula, africa_map_mount_zar,
              half_mount_usd, half_mount_eur, half_mount_pula, half_mount_zar,
              dip_pack_price_usd,
              open_mouth_add_on_usd, open_mouth_add_on_eur, open_mouth_add_on_pula, open_mouth_add_on_zar
            ) VALUES (
              %s,%s,%s,%s,%s,
              %s,%s,%s,%s,
              %s,%s,%s,%s,
              %s,%s,%s,%s,%s,
              %s,%s,%s,%s,
              %s,%s,%s,%s,
              %s,%s,%s,%s,
              %s,%s,%s,%s,
              %s,%s,%s,%s,
              %s,
              %s,%s,%s,%s
            )
            r~   )6r?   rV   rW   r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  rO   r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r   r   r[   rK  s       rG   create_master_animal_pricingr    s   D4kkm:  '')-)@)@BFBZBZ\`\s\s 55 8<7\7\ _c  _E  _E GK  Gl  Gl 00	 372R2R	 UYTuTu	 x|  xX  xX	
 ##
 &*%8%8
 ;?:N:N
 QUPcPc
 fttx  uI  uI  fJ  !% 15 BF "" %)$6$6 9=8K8K NRM_M_ )) ,0+D+D GKF`F` cgb{b{ 00 372R2R UYTuTu x|  xX  xX )) ,0+D+D GKF`F` cgb{b{ ## &*%8%8 ;?:N:N QUPcPc '' ** -1,F,F IMHcHc fjee=-	
\ f~



s   I?J J.z#/master-animal-pricing/{pricing_id}
pricing_idc                    [        5       n UR                  5       nUR                  S/ UR                  PUR                  PUR
                  PUR                  PUR                  PUR                  PUR                  PUR                  PUR                  PUR                  PUR                  PUR                  PUR                  PUR                   PUR"                  PUR$                  PUR&                  P[)        UR*                  5      PUR,                  PUR.                  PUR0                  PUR2                  PUR4                  PUR6                  PUR8                  PUR:                  PUR<                  PUR>                  PUR@                  PURB                  PURD                  PURF                  PURH                  PURJ                  PURL                  PURN                  PURP                  PURR                  PURT                  PURV                  PURX                  PURZ                  PUR\                  PUR^                  PUR`                  PURb                  PURd                  PU P75        URf                  S:X  a
  [i        SSS9eURk                  5         SS0URm                  5         $ ! URm                  5         f = f)Na  
            UPDATE master_animal_pricing SET
              common_name=%s,
              shoulder_mount_usd=%s, shoulder_mount_eur=%s, shoulder_mount_pula=%s, shoulder_mount_zar=%s,
              wall_pedestal_shoulder_mount_usd=%s, wall_pedestal_shoulder_mount_eur=%s, wall_pedestal_shoulder_mount_pula=%s, wall_pedestal_shoulder_mount_zar=%s,
              pedestal_shoulder_mount_usd=%s, pedestal_shoulder_mount_eur=%s, pedestal_shoulder_mount_pula=%s, pedestal_shoulder_mount_zar=%s,
              full_mount_usd=%s, full_mount_eur=%s, full_mount_pula=%s, full_mount_zar=%s, full_mount_note=%s,
              skull_usd=%s, skull_eur=%s, skull_pula=%s, skull_zar=%s,
              rug_mount_usd=%s, rug_mount_eur=%s, rug_mount_pula=%s, rug_mount_zar=%s,
              tanning_of_skins_usd=%s, tanning_of_skins_eur=%s, tanning_of_skins_pula=%s, tanning_of_skins_zar=%s,
              felting_of_skins_add_on_usd=%s, felting_of_skins_add_on_eur=%s, felting_of_skins_add_on_pula=%s, felting_of_skins_add_on_zar=%s,
              africa_map_mount_usd=%s, africa_map_mount_eur=%s, africa_map_mount_pula=%s, africa_map_mount_zar=%s,
              half_mount_usd=%s, half_mount_eur=%s, half_mount_pula=%s, half_mount_zar=%s,
              dip_pack_price_usd=%s,
              open_mouth_add_on_usd=%s, open_mouth_add_on_eur=%s, open_mouth_add_on_pula=%s, open_mouth_add_on_zar=%s
            WHERE id = %s
            r   r   Pricing not foundrs   r   T)7r?   rV   rW   r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  rO   r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r   r   r   r[   )r  rI  r^   r_   s       rG   update_master_animal_pricingr  	  s   D*kkm"  '')-)@)@BFBZBZ\`\s\s 55 8<7\7\ _c  _E  _E GK  Gl  Gl 00	 372R2R	 UYTuTu	 x|  xX  xX	
 ##
 &*%8%8
 ;?:N:N
 QUPcPc
 fttx  uI  uI  fJ  !% 15 BF "" %)$6$6 9=8K8K NRM_M_ )) ,0+D+D GKF`F` cgb{b{ 00 372R2R UYTuTu x|  xX  xX )) ,0+D+D GKF`F` cgb{b{ ## &*%8%8 ;?:N:N QUPcPc '' ** -1,F,F IMHcHc fjee %"	
F <<1C8KLL4 



s   JJ, ,J>c                     [        5       n UR                  5       nUR                  SU 45        UR                  S:X  a
  [	        SSS9eSS0UR                  5         $ ! UR                  5         f = f)Nz/DELETE FROM master_animal_pricing WHERE id = %sr   r   r  rs   r   TrR  )r  r^   r_   s      rG   delete_master_animal_pricingr  9  s`    DkkmE
}U<<1C8KLL4 



rT  z/items/african-map-mountc                  v   [        5       n  U R                  SS9n UR                  S5        UR                  5       =(       d    /  U R                  5         $ ! [        R                  R
                   a.  n[        USS 5      S:X  a  / s S nAU R                  5         $ e S nAff = f! U R                  5         f = f)NTrS   z
                SELECT id, animal_common_name, frame, add_on,
                       base_price_usd, add_on_price_usd, notes
                FROM african_map_mount
                ORDER BY animal_common_name
                rd   re   rf   ri   s      rG   list_items_african_map_mountr  G  rl   rm   z/items/bird-speciesc                  p   [        5       n  U R                  SS9n UR                  S5        UR                  5       =(       d    /  U R	                  5         $ ! [
        R                  R                   a  n[        USS 5      S:w  a  e  UR                  S5        UR                  5       =(       d    / s S nAU R	                  5         $ ! [
        R                  R                   a3  n[        USS 5      S:X  a  / s S nAs S nAU R	                  5         $ e S nAff = fS nAff = f! U R	                  5         f = f)NTrS   z~SELECT id, common_name, scientific_name, cites_status, tops_status
                FROM item_bird_species ORDER BY common_namerd   re   z}SELECT id, common_name, scientific_name, cites_status, tops_status
                    FROM bird_species ORDER BY common_name	r?   rV   rW   rX   r[   r@   rA   rg   rh   r^   r_   e1e2s       rG   list_items_bird_speciesr  ^  s   DkkTk*	KK? <<>'R'" 	

! $$ 	r7D)T1	> ||~++ 	

 ??(( 2w-5II 	

 	  	

p   D# )A D 5D)C1D 2D# D%D7D8D<D =D# DDDD  D# #D5z/items/dip-pack-pricingc                  p   [        5       n  U R                  SS9n UR                  S5        UR                  5       =(       d    /  U R	                  5         $ ! [
        R                  R                   a  n[        USS 5      S:w  a  e  UR                  S5        UR                  5       =(       d    / s S nAU R	                  5         $ ! [
        R                  R                   a3  n[        USS 5      S:X  a  / s S nAs S nAU R	                  5         $ e S nAff = fS nAff = f! U R	                  5         f = f)NTrS   zSELECT id, animal_group, composition, notes, price_usd, hs_code
                FROM dip_pack_pricing ORDER BY animal_group, compositionrd   re   zSELECT id, animal_group, composition, notes, price_usd, hs_code
                    FROM item_dip_pack ORDER BY animal_group, compositionr  r  s       rG   list_items_dip_pack_pricingr  }  s   DkkTk*	KKL <<>'R'" 	

! $$ 	r7D)T1	M ||~++ 	

 ??(( 2w-5II 	

 	  	

r  z/items/line-item-dip-packc                  v   [        5       n  U R                  SS9n UR                  S5        UR                  5       =(       d    /  U R                  5         $ ! [        R                  R
                   a.  n[        USS 5      S:X  a  / s S nAU R                  5         $ e S nAff = f! U R                  5         f = f)NTrS   a&  
                SELECT id, category, size_type, name, feet_count, notes,
                       price_zar, price_usd, price_eur, price_bwp, is_active
                FROM line_item_dip_pack
                WHERE is_active = 1
                ORDER BY category, size_type, name
                rd   re   rf   ri   s      rG   list_items_line_item_dip_packr    s    DkkTk*	KK ||~##

 $$ 	q'4(D0	 	

 		 	

rm   c                 n   SS/nU H=  nU R                  U5      =(       d    SR                  5       (       a  M2  [        SSU 3S9e   [        5       n UR	                  5       nUR                  SU R                  S5      [        U R                  S5      5      U R                  S5      [        U R                  S	5      5      [        U R                  S
5      5      [        U R                  S5      5      [        U R                  S5      5      [        U R                  S5      5      [        U R                  S5      5      [        U R                  SS5      5      R                  5       S;  a  SOS4
5        UR                  5         SUR                  0UR                  5         $ ! UR                  5         f = f)Nrp   r'   rI   rq   rr   rs   z
            INSERT INTO line_item_dip_pack
              (category, size_type, name, feet_count, notes, price_zar, price_usd, price_eur, price_bwp, is_active)
            VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s)
            	size_type
feet_countrv   r   r   r   r   rw   rx   ry   r}   r   r~   r   r   s        rG   create_line_item_dip_packr    s[   F#HA$"++--C:RSTRU8VWW  Dkkm J'w{{;78F#w{{<89w{{734w{{;78w{{;78w{{;78w{{;78[#67==?G^^de	
& 	cmm$



r   z%/items/line-item-dip-pack/{record_id}c                    [        5       n UR                  5       nUR                  SUR                  S5      [	        UR                  S5      5      UR                  S5      [	        UR                  S5      5      [	        UR                  S5      5      [	        UR                  S5      5      [	        UR                  S5      5      [	        UR                  S	5      5      [	        UR                  S
5      5      [        UR                  SS5      5      R                  5       S;  a  SOSU 45        UR                  S:X  a
  [        SSS9eUR                  5         SS0UR                  5         $ ! UR                  5         f = f)Nz
            UPDATE line_item_dip_pack
            SET category=%s, size_type=%s, name=%s, feet_count=%s, notes=%s,
                price_zar=%s, price_usd=%s, price_eur=%s, price_bwp=%s,
                is_active=%s
            WHERE id=%s
            rp   r  r'   r  rv   r   r   r   r   rw   rx   ry   r}   r   r   Dip & Pack line item not foundrs   r   Tr   r   s       rG   update_line_item_dip_packr    s+   Dkkm J'w{{;78F#w{{<89w{{734w{{;78w{{;78w{{;78w{{;78[#67==?G^^de	
, <<1C8XYY4 



r   c                    [        5       n UR                  5       nUR                  SU 45        UR                  S:X  a
  [	        SSS9eUR                  5         SS0UR                  5         $ ! UR                  5         f = f)Nz*DELETE FROM line_item_dip_pack WHERE id=%sr   r   r  rs   r   Tr   r   s      rG   delete_line_item_dip_packr    si    Dkkm@9,O<<1C8XYY4 



r   c                    [        5       n UR                  5       nUR                  SU R                  U R                  [        U R                  5      U R                  =(       d    SU R                  =(       d    SU R                  =(       d    SU R                  =(       d    S[        U R                  5      45        UR                  nUR                  5         SU0UR                  5         $ ! UR                  5         f = f)Nz
            INSERT INTO dip_pack_pricing (
              animal_group, composition, notes,
              price_zar, price_usd, price_eur, price_bwp,
              hs_code
            ) VALUES (%s,%s,%s,%s,%s,%s,%s,%s)
            Not Applicabler~   )r?   rV   rW   r   r  rO   rv   r   r   r   r   r  r   r   r[   rK  s       rG   create_items_dip_pack_pricingr    s    Dkkm !!  tzz*2"22"22"22"2t||,		
& f~



   CC, ,C>z#/items/dip-pack-pricing/{record_id}c                     [        5       n UR                  5       nUR                  SUR                  UR                  [        UR                  5      UR                  =(       d    SUR                  =(       d    SUR                  =(       d    SUR                  =(       d    S[        UR                  5      U 4	5        UR                  S:X  a
  [        SSS9eUR                  5         SS0UR                  5         $ ! UR                  5         f = f)	Nz
            UPDATE dip_pack_pricing
            SET animal_group=%s, composition=%s, notes=%s,
                price_zar=%s, price_usd=%s, price_eur=%s, price_bwp=%s,
                hs_code=%s
            WHERE id=%s
            r  r   r   Dip & Pack row not foundrs   r   T)r?   rV   rW   r   r  rO   rv   r   r   r   r   r  r   r   r   r[   rO  s       rG   update_items_dip_pack_pricingr  '  s    Dkkm !!  tzz*2"22"22"22"2t||,
	
( <<1C8RSS4 



s   CC; ;Dc                    [        5       n UR                  5       nUR                  SU 45        UR                  S:X  a
  [	        SSS9eUR                  5         SS0UR                  5         $ ! UR                  5         f = f)Nz(DELETE FROM dip_pack_pricing WHERE id=%sr   r   r  rs   r   Tr   r   s      rG   delete_items_dip_pack_pricingr  H  si    Dkkm>M<<1C8RSS4 



r   )dip_pack_pricingr   )item_dip_packr   )	fullmountr   )r  standard_pose)r  special_pose)r  add_on)item_full_mountr   )r  r  )r  r  )r  r  )african_map_mountframe)r  r  )item_african_map_mountr  )r  r  )bird_speciescites_status)r  tops_status)item_bird_speciesr  )r  r  )r  	variation)r  r  )item_half_mountr  )r  r  )misc_productssub_category)item_misc_productsr  )r  type)r  r  )item_rug_mountr  )r  r  )r  r  )r  special_variation)r  r  )item_shoulder_mountr  )r  r  )r  r  )skinsr   )r  r   )r  leather_tan_color)r  r  )
item_skinsr   )r  r   )r  r  )r  r  )skulls
skull_type)r  r  )r  surcharge_type)r  special_base)item_skullsr  )r  r  )r  r  )r  r  )r  r  r  r  !item_wall_pedestal_shoulder_mountr  r  r  )r  r  r  
SAFE_ENUMScolumn_typec                 8   U R                  5       R                  S5      (       d  / $ X R                  S5      S-   U R                  S5       n/ nSnSnSnU[	        U5      :  a{  X   nUS:X  a6  U(       a'  US-   [	        U5      :  a  XS-      S:X  a
  US-  o5S-  nO-U(       + nO%US	:X  a  U(       d  UR                  U5        SnOX6-  nUS-  nU[	        U5      :  a  M{  U(       a  UR                  U5        S
 U 5        Vs/ s H  owS:w  d  M
  UPM     sn$ s  snf )Nzenum((r}   r^  rI   Fr   'r[  c              3   @   #    U  H  oR                  5       v   M     g 7fr5  )rL   ).0ss     rG   	<genexpr>#_parse_enum_list.<locals>.<genexpr>  s     /3a		3s   )lower
startswithfindrfindr_  r;  )r  inneroutcurrentin_quoteichrN   s           rG   _parse_enum_listr    s   ))'22	((-a/0A0A#0FGECGH	A
c%j.X9AECJ.51:3D3Q'<3YxJJwGMG	Q c%j. 

7/3/;/!7A/;;;s   	DDr  c           
      |    SR                  U  Vs/ s H  nSUR                  SS5      -   S-   PM     sn5      $ s  snf )Nr[  r  z'')r<  replace)r  rN   s     rG   _quote_enum_valuesr    s8    88vFv!S199S$//#5vFGGFs   "9z/admin/enums/{table}/{column}tablecolumnc                 >   X4[         ;  a
  [        SSS9e[         X4   u  p#[        5       n UR                  SS9nUR	                  SX#45        UR                  5       nU(       Gd  US:X  a%  UR	                  SS	U45        UR                  5       nO*US
:X  a$  UR	                  SSU45        UR                  5       nU(       Gd  US:X  a$  UR	                  SSU45        UR                  5       nU(       d*  US:X  a$  UR	                  SSU45        UR                  5       nU(       d*  US:X  a$  UR	                  SSU45        UR                  5       nU(       d*  US:X  a$  UR	                  SSU45        UR                  5       nU(       d*  US:X  a$  UR	                  SSU45        UR                  5       nU(       d*  US:X  a$  UR	                  SSU45        UR                  5       nU(       d*  US:X  a$  UR	                  SSU45        UR                  5       nU(       d*  US:X  a$  UR	                  SSU45        UR                  5       nU(       d
  [        SSS9e[        US   =(       d    S 5      US!   S":H  US#   S$.UR                  5         $ ! UR                  5         f = f)%Nrq   Unsupported enum columnrs   TrS   z
            SELECT COLUMN_TYPE, IS_NULLABLE, COLUMN_DEFAULT
            FROM information_schema.COLUMNS
            WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = %s AND COLUMN_NAME = %s
            r  z
                    SELECT COLUMN_TYPE, IS_NULLABLE, COLUMN_DEFAULT
                    FROM information_schema.COLUMNS
                    WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = %s AND COLUMN_NAME = %s
                    r  r  r  r  z
                        SELECT COLUMN_TYPE, IS_NULLABLE, COLUMN_DEFAULT
                        FROM information_schema.COLUMNS
                        WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = %s AND COLUMN_NAME = %s
                        r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r   zColumn not foundCOLUMN_TYPErI   IS_NULLABLEYESCOLUMN_DEFAULT)r  nullabledefault)r  r   r?   rV   rW   r:  r  r[   )r  r   target_tabletarget_columnr^   r_   rD  s          rG   get_enum_valuesr    s   j(4MNN",e_"=LDBkkTk*
 )	
 lln|+
 m, lln!DD
 4]C lln=0KK
 "=1 ,,.C|/@@KK
 %m4 ,,.C|/GGKK
 -m< ,,.C|/@@KK
 &}5 ,,.C|/BBKK
 (7 ,,.C|/??KK
 %m4 ,,.C|/CCKK
 )-8 ,,.C|/DDKK
 *=9 ,,.C'C@RSS&s='9'?R@M*e3+,
 	



s   IJ
 
Jc                    X4[         ;  a
  [        SSS9eUR                  (       d
  [        SSS9e[         X4   u  p4[        5       n UR	                  5       n[        UR                  5      nSU SU SU S3nUR                  U5        UR                  5         S	S
0UR                  5         $ ! UR                  5         f = f)Nrq   r  rs   zMust include at least one valuezALTER TABLE `z
` MODIFY `z` ENUM(z
) NOT NULLr   T)	r  r   r  r?   rV   r  rW   r   r[   )	r  r   rI  r	  r
  r^   r_   quotedsqls	            rG   update_enum_valuesr  >  s    j(4MNN;;4UVV",e_"=LDkkm#DKK0l^:m_GF8S]^C4 



s   AB. .C z/items/full-mountc                  v   [        5       n  U R                  SS9n UR                  S5        UR                  5       =(       d    /  U R                  5         $ ! [        R                  R
                   a.  n[        USS 5      S:X  a  / s S nAU R                  5         $ e S nAff = f! U R                  5         f = f)NTrS   zSELECT id, animal_common_name, base_type, standard_pose, special_pose,
                             base_price_usd, add_on, add_on_price_usd, notes
                       FROM fullmount ORDER BY animal_common_namerd   re   rf   ri   s      rG   list_items_full_mountr  Q  s    DkkTk*		KKE ||~##

 $$ 	q'4(D0	 	

 	 	

rm   z/items/half-mountc                  v   [        5       n  U R                  SS9n UR                  S5        UR                  5       =(       d    /  U R                  5         $ ! [        R                  R
                   a.  n[        USS 5      S:X  a  / s S nAU R                  5         $ e S nAff = f! U R                  5         f = f)NTrS   zSELECT id, animal_common_name, variation, base_price_usd, add_on, add_on_price_usd, pricing_rule_note, notes
                FROM half_mount ORDER BY animal_common_namerd   re   rf   ri   s      rG   list_items_half_mountr  e  s    DkkTk*	KK? ||~##

 $$ 	q'4(D0	 	

 	 	

rm   z/items/misc-productsc                  v   [        5       n  U R                  SS9n UR                  S5        UR                  5       =(       d    /  U R                  5         $ ! [        R                  R
                   a.  n[        USS 5      S:X  a  / s S nAU R                  5         $ e S nAff = f! U R                  5         f = f)NTrS   zSELECT id, sub_category, product_name, option_name, price_usd, internal_note
                FROM misc_products ORDER BY sub_category, product_namerd   re   rf   ri   s      rG   list_items_misc_productsr  x  s    DkkTk*	KKJ ||~##

 $$ 	q'4(D0	 	

 	 	

rm   z/items/item-misc-productsc                  v   [        5       n  U R                  SS9n UR                  S5        UR                  5       =(       d    /  U R                  5         $ ! [        R                  R
                   a.  n[        USS 5      S:X  a  / s S nAU R                  5         $ e S nAff = f! U R                  5         f = f)NTrS   zSELECT id, sub_category, product_name, option_name, price_usd, internal_note
                FROM item_misc_products ORDER BY sub_category, product_namerd   re   rf   ri   s      rG   list_item_misc_productsr    s    DkkTk*	KKO ||~##

 $$ 	q'4(D0	 	

 	 	

rm   c                 F   SS/nU H=  nU R                  U5      =(       d    SR                  5       (       a  M2  [        SSU 3S9e   [        5       n UR	                  5       nUR                  SU R                  S5      U R                  S5      [        U R                  S5      5      [        U R                  S	5      5      [        U R                  S
5      5      45        UR                  5         SUR                  0UR                  5         $ ! UR                  5         f = f)Nr  product_namerI   rq   rr   rs   z
            INSERT INTO item_misc_products (sub_category, product_name, option_name, price_usd, internal_note)
            VALUES (%s, %s, %s, %s, %s)
            option_namer   r   r~   )
rZ   rL   r   r?   rV   rW   rO   r   r   r[   r   s        rG   create_item_misc_productr    s    /HA$"++--C:RSTRU8VWW  Dkkm
 N+N+w{{=9:w{{;78w{{?;<	
 	cmm$



s   B*D D z%/items/item-misc-products/{record_id}c                    [        5       n UR                  5       nUR                  SUR                  S5      UR                  S5      [	        UR                  S5      5      [	        UR                  S5      5      [	        UR                  S5      5      U 45        UR
                  S:X  a
  [        SS	S
9eUR                  5         SS0UR                  5         $ ! UR                  5         f = f)Nz
            UPDATE item_misc_products
            SET sub_category=%s, product_name=%s, option_name=%s, price_usd=%s, internal_note=%s
            WHERE id=%s
            r  r  r  r   r   r   r   Misc product not foundrs   r   T)	r?   rV   rW   rZ   rO   r   r   r   r[   r   s       rG   update_item_misc_productr    s    Dkkm N+N+w{{=9:w{{;78w{{?;<	
 <<1C8PQQ4 



s   B;C C*c                    [        5       n UR                  5       nUR                  SU 45        UR                  S:X  a
  [	        SSS9eUR                  5         SS0UR                  5         $ ! UR                  5         f = f)Nz*DELETE FROM item_misc_products WHERE id=%sr   r   r  rs   r   Tr   r   s      rG   delete_item_misc_productr     si    Dkkm@9,O<<1C8PQQ4 



r   z/items/rug-mountc                  v   [        5       n  U R                  SS9n UR                  S5        UR                  5       =(       d    /  U R                  5         $ ! [        R                  R
                   a.  n[        USS 5      S:X  a  / s S nAU R                  5         $ e S nAff = f! U R                  5         f = f)NTrS   zSELECT id, animal_common_name, type, base_price_usd, add_on, add_on_price_usd, notes
                FROM rug_mount ORDER BY animal_common_namerd   re   rf   ri   s      rG   list_items_rug_mountr"    s    DkkTk*	KK> ||~##

 $$ 	q'4(D0	 	

 	 	

rm   z/items/shoulder-mountc                  v   [        5       n  U R                  SS9n UR                  S5        UR                  5       =(       d    /  U R                  5         $ ! [        R                  R
                   a.  n[        USS 5      S:X  a  / s S nAU R                  5         $ e S nAff = f! U R                  5         f = f)NTrS   zSELECT id, animal_common_name, variation, special_variation, base_price_usd, add_on, add_on_price_usd, notes
                FROM shoulder_mount ORDER BY animal_common_namerd   re   rf   ri   s      rG   list_items_shoulder_mountr$    s    DkkTk*	KKC ||~##

 $$ 	q'4(D0	 	

 	 	

rm   z/items/skinsc                     [        5       n  U R                  SS9n UR                  S5        UR                  5       =(       d    /  U R                  5         $ ! [        R                  R
                   aV  n[        USS 5      S:X  a?  UR                  S5        UR                  5       =(       d    / s S nAU R                  5         $ e S nAff = f! U R                  5         f = f)NTrS   zSELECT id, animal_common_name, skin_type, tanning_type, base_price_usd, add_on, add_on_price_usd, surcharge_note
                FROM skins ORDER BY animal_common_namerd   re   zSELECT id, animal_common_name, skin_type, tanning_type, base_price_usd, add_on, add_on_price_usd, surcharge_note
                    FROM item_skins ORDER BY animal_common_name)	r?   rV   rW   r@   rA   rg   rh   rX   r[   ri   s      rG   list_items_skinsr&  	  s    DkkTk*	KK: ||~##

 $$ 	q'4(D0C ||~++ 	

 	 	

s?   C A C C5:C/C0C CCC C z/items/skullsc                  v   [        5       n  U R                  SS9n UR                  S5        UR                  5       =(       d    /  U R                  5         $ ! [        R                  R
                   a.  n[        USS 5      S:X  a  / s S nAU R                  5         $ e S nAff = f! U R                  5         f = f)NTrS   zSELECT id, animal_common_name, skull_type, base_price_usd, discount_percent,
                             add_on, add_on_price_usd, surcharge_type, surcharge_percent, notes
                FROM skulls ORDER BY animal_common_namerd   re   rf   ri   s      rG   list_items_skullsr(  !  s    DkkTk*		KK; ||~##

 $$ 	q'4(D0	 	

 	 	

rm   z#/items/wall-pedestal-shoulder-mountc                  v   [        5       n  U R                  SS9n UR                  S5        UR                  5       =(       d    /  U R                  5         $ ! [        R                  R
                   a.  n[        USS 5      S:X  a  / s S nAU R                  5         $ e S nAff = f! U R                  5         f = f)NTrS   zSELECT id, animal_common_name, variation, base_price_usd, add_on, add_on_price_usd, notes
                FROM wall_pedestal_shoulder_mount ORDER BY animal_common_namerd   re   rf   ri   s      rG   list_items_wpsmr*  5  s    DkkTk*	KKQ ||~##

 $$ 	q'4(D0	 	

 	 	

rm   z/partners/{partner_id}r  c                     [        5       n UR                  SS9nUR                  SU 45        UR                  5       nU(       d
  [	        SSS9eUUR                  5         $ ! UR                  5         f = f)NTrS   a  
            SELECT id, partner_unique_number, status, partner_type,
                   company_name, company_vat, company_email, company_contact_number,
                   company_country, company_street, company_province, company_city, company_postal_code,
                   first_name, surname, email, contact_number,
                   hunting_outfitter_id, comms_local_percent, comms_export_percent, outfitter_documents,
                   professional_hunter_id, professional_hunter_permit_type,
                   professional_hunter_permit_issue_date, professional_hunter_permit_expiry_date,
                   professional_hunter_documents, office_notes, created_at
            FROM partners
            WHERE id = %s
            r   Partner not foundrs   rE  )r  r^   r_   rD  s       rG   get_partnerr-  H  sk    DkkTk* M	
 llnC8KLL



rH  z/quotesFz(If true, return only soft-deleted quotes)r}  deletedc                     [        5       n UR                  SS9nU (       a  UR                  S5        OUR                  S5        UR                  5       UR	                  5         $ ! UR	                  5         f = f)NTrS   a  
                SELECT id,
                       quote_unique_number,
                       partner_id,
                       partner_name,
                       order_no,
                       quote_date,
                       order_type,
                       customer_id,
                       customer_first_names,
                       customer_surname,
                       quote_status,
                       quote_currency,
                       sub_total,
                       vat_amount,
                       total_amount,
                       deposit_percent,
                       deposit_amount_due,
                       created_at
                FROM quotes
                WHERE deleted_at IS NOT NULL
                ORDER BY created_at DESC
                a  
                SELECT id,
                       quote_unique_number,
                       partner_id,
                       partner_name,
                       order_no,
                       quote_date,
                       order_type,
                       customer_id,
                       customer_first_names,
                       customer_surname,
                       quote_status,
                       quote_currency,
                       sub_total,
                       vat_amount,
                       total_amount,
                       deposit_percent,
                       deposit_amount_due,
                       created_at
                FROM quotes
                WHERE deleted_at IS NULL
                ORDER BY created_at DESC
                r=  )r.  r^   r_   s      rG   list_quotesr0  e  sd    D8kkTk*KK4 KK2 ||~



s   AA% %A7z/quotes/{quote_id}quote_idc                    [        5       n UR                  SS9nUR                  SU 45        UR                  5       nU(       d
  [	        SSS9eUR                  SU 45        UR                  5       =(       d    / n0 nU(       a  U Vs/ s H  ofS   PM	     nnS	R                  S
/[        U5      -  5      nUR                  SU S3[        U5      5        UR                  5       =(       d    /  H'  n	UR                  U	S   / 5      R                  U	5        M)     U H  n
UR                  U
S   / 5      U
S'   M     UR                  SU 45        UR                  5       =(       d    /  Vs/ s H  oS   PM	     nnUR                  SU 45        UR                  5       =(       d    / nXCS'   XS'   XS'   UUR                  5         $ s  snf s  snf ! UR                  5         f = f)NTrS   zk
            SELECT *
            FROM quotes
            WHERE id = %s AND deleted_at IS NULL
            r   Quote not foundrs   z|
            SELECT *
            FROM quote_line_items
            WHERE quote_id = %s
            ORDER BY id
            r~   r[  r\  z?SELECT * FROM quote_line_item_processes WHERE line_item_id IN (r^  line_item_idr  z6SELECT hs_code FROM quote_hs_codes WHERE quote_id = %sr  wSELECT id, file_url, file_name, mime_type, created_at FROM quote_documents WHERE quote_id = %s ORDER BY created_at DESCr1  r2  r~  )r?   rV   rW   r:  r   rX   r<  r_  r`  
setdefaultr;  rZ   r[   )r1  r^   r_   quoteitemsitem_id_to_processesrD  item_idsformat_stringspitra   r2  r~  s                 rG   	get_quoter>    s   D8kkTk*
 K	
 C8IJJ 	 K	
 $" 79-23UcD	UH3 XXtfs8}&<=NKKQR`Qaabch \\^)r)$//.0A2FMMaP *"6":":2d8R"H;  	LxkZ+.<<>+?R+?A+?QiL+?A 	 FK	
 LLN(b	#l$j&k

7 4 B 	

s+   A<G GCG (G6;G 
G Gc                    [        5       n UR                  5       nUR                  SU 45        UR                  S:X  a
  [	        SSS9eUR                  5         SS0UR                  5         $ ! UR                  5         f = f)NzIUPDATE quotes SET deleted_at = NOW() WHERE id = %s AND deleted_at IS NULLr   r   r3  rs   r   Tr   r1  r^   r_   s      rG   delete_quoterA    sn    DkkmWK	
 <<1C8IJJ4 



r   c                    UR                   b  UR                   O[        S UR                   5       5      nUR                  S:X  a  SOSnUR                  b  UR                  O[        X#-  S5      nUR                  b  UR                  O[        X$-   S5      nUR                  nUck  UR                  S:X  a  UR                  S:X  a  SnOHUR                  S:X  a  UR                  S	;   a  S
nO%UR                  S:X  a  UR                  S:X  a  SnOS
nUR                  b  UR                  O[        XVS-  -  S5      n[        5       n UR                  5         UR                  5       n	U	R                  SU 45        U	R                  5       n
U
(       d
  [        SSS9eU	R                  S/ UR                   PUR"                  PUR$                  PUR&                  PUR                  PUR(                  PUR*                  PUR,                  PUR.                  PUR0                  PUR2                  PUR4                  PUR6                  PUR8                  PUR:                  PUR<                  PUR>                  PUR@                  PURB                  P[E        URF                  5      P[E        URH                  5      P[E        URJ                  5      PURL                  =(       d    SPUR                  PUPUPUPUPUP[E        URN                  5      P[E        URP                  5      P[E        URR                  5      PU P75        U	RT                  S:X  a
  [        SSS9eU	R                  SU 45        U	RW                  5       =(       d    /  Vs/ s H  oS   PM	     nnU(       a=  SRY                  S/[[        U5      -  5      nU	R                  SU S3[]        U5      5        U	R                  SU 45        UR                  (       Ga  UR                  5       nUR                   H  nUR                  SXR^                  UR`                  [E        URb                  5      URd                  URf                  [E        URh                  5      URj                  =(       d    S45        URl                  nURn                  (       d  M  UR                  5       nURn                   H5  nUR                  SUURp                  [E        URr                  5      45        M7     M     U	R                  SU 45        URt                  (       a7  UR                  5       nURt                   H  nUR                  SU U45        M     URw                  5         UR                  SS 9nUR                  S!U 45        UR                  5       =(       d    0 nU URy                  S"5      X$XVUS#.UR{                  5         $ s  snf ! UR{                  5         f = f)$Nc              3   J   #    U  H  oR                   =(       d    S v   M     g7fr   Nr  r  lis     rG   r  update_quote.<locals>.<genexpr>        L(:"	1	(:   !#r8  333333?           ZAR     Q@r*  USDEUR      I@BWP      Y@zKSELECT quote_unique_number FROM quotes WHERE id = %s AND deleted_at IS NULLr   r3  rs   a<  
            UPDATE quotes SET
              partner_id=%s, partner_name=%s, order_no=%s, quote_date=%s, order_type=%s,
              customer_id=%s, customer_first_names=%s, customer_surname=%s, customer_email=%s, customer_contact_number=%s,
              customer_country=%s, customer_street=%s, customer_province_state=%s, customer_city=%s, customer_postal_code=%s,
              company_name=%s, company_physical_address=%s, company_phone_number=%s, company_email=%s,
              company_vat_number=%s, company_registration_number=%s, company_logo_url=%s,
              quote_status=%s, quote_currency=%s,
              sub_total=%s, vat_amount=%s, total_amount=%s, deposit_percent=%s, deposit_amount_due=%s,
              terms_and_conditions=%s, payment_details=%s, office_notes=%s
            WHERE id = %s
            Draft - In Progressr   z3SELECT id FROM quote_line_items WHERE quote_id = %sr[  r\  z=DELETE FROM quote_line_item_processes WHERE line_item_id IN (r^  z0DELETE FROM quote_line_items WHERE quote_id = %s  
                    INSERT INTO quote_line_items (
                      quote_id, item_quantity, item_type, species, unit_price, total_price, detailed_instructions, line_item_status
                    ) VALUES (%s,%s,%s,%s,%s,%s,%s,%s)
                    r  kINSERT INTO quote_line_item_processes (line_item_id, processing_type, processing_subtype) VALUES (%s,%s,%s)z.DELETE FROM quote_hs_codes WHERE quote_id = %s=INSERT INTO quote_hs_codes (quote_id, hs_code) VALUES (%s,%s)TrS   z4SELECT quote_unique_number FROM quotes WHERE id = %squote_unique_numberr~   rZ  r*  r+  r,  r-  r.  )>r*  sumr1  r  r+  roundr,  r-  r)  r.  r?   start_transactionrV   rW   r:  r   r  r  r  r  rc  r  r  r   r!  r"  r#  r$  r%  r&  r  r  r  r  rO   r  r  r'  r(  r/  r0  r  r   rX   r<  r_  r`  r  r  r  r  r  r  r  r   r  r  r  r2  r   rZ   r[   )r1  rn   r*  vat_rater+  r,  r-  r.  r^   r_   rD  ra   r:  	in_clausecur_lirG  r4  cur_procprcur_hsrv  r?  row2s                          rG   update_quoterf    sz    &-%6%6%B!! L(/(:(:L II ))W4t#H'.'9'9'E##5QZQeghKiJ+2+?+?+K7''QVW`WmopQqL--O(W-C-Cu-L"O8+0F0F.0X"O8+0F0F%0O"O"O7>7Q7Q7]33chiu  LQ  zQ  jR  TU  dVDW kkmadlcnollnC8IJJ 	
""
$+$8$8
:A:J:J
LSL^L^
`g`r`r
##
%,%A%A
CJC[C[
]d]s]s
u|  vU  vU
 ((
 +2*A*A
 DKCbCb
 eldydy
 |C  |X  |X
 $$	
 '.&F&F	
 IPHdHd	
 gnf{f{	

 w99:

 =K7KnKn<o

 r@  AH  AY  AY  rZ
 %%>)>
 BIAWAW
 
 &
 (4
 6E
 GY
 w;;<
 ?MWMdMd>e
 hvv}  wK  wK  hL
 
	
2 <<1C8IJJ 	IH;W#&<<>#7R#79#7QaD#79$#h-!78IKKWXaWbbcdfkltfuvFT[[]F(( !"2"2BLL.QSQ[Q[B\^`^k^kmom{m{  ~L  MO  Me  Me  ~f  ik  i|  i|  iG  @G	  &//<<<#{{}H ll (( J)2+=+=~bNcNc?de + )* 	DxkR[[]F((St$ ) 	{{d{+Kh[Y}}$"txx@U7Ven  [g  cu  v

] :\ 	

s'   H>W! WDW! 6DW! W! !W3z/quotes/{quote_id}/restorec                    [        5       n UR                  5       nUR                  SU 45        UR                  S:X  a
  [	        SSS9eUR                  5         SS0UR                  5         $ ! UR                  5         f = f)NzLUPDATE quotes SET deleted_at = NULL WHERE id = %s AND deleted_at IS NOT NULLr   r   zQuote not found or not deletedrs   r   Tr   r@  s      rG   restore_quoterh  c  sn    DkkmZK	
 <<1C8XYY4 



r   z/quotes/{quote_id}/permanentc                    [        5       n UR                  5       nUR                  SU 45        UR                  S:X  a
  [	        SSS9eUR                  5         SS0UR                  5         $ ! UR                  5         f = f)Nz DELETE FROM quotes WHERE id = %sr   r   r3  rs   r   Tr   r@  s      rG   permanently_delete_quoterj  t  si    D	kkm6D<<1C8IJJ4 



r   c                 
   U R                   b  U R                   O[        S U R                   5       5      nU R                  S:X  a  SOSnU R                  b  U R                  O[        X-  S5      nU R                  b  U R                  O[        X-   S5      nU R                  nUck  U R                  S:X  a  U R                  S:X  a  SnOHU R                  S:X  a  U R                  S	;   a  S
nO%U R                  S:X  a  U R                  S:X  a  SnOS
nU R                  b  U R                  O[        XES-  -  S5      n[        5       n UR                  5         UR                  5       nUR                  S5        UR                  5       n	[        U	(       a  U	S   b  U	S   OS5      n
[        U	(       a  U	S   b  U	S   OS5      n[!        X5      S-   nSUS 3nUR                  S/ UPU R"                  PU R$                  PU R&                  PU R(                  PU R                  PU R*                  PU R,                  PU R.                  PU R0                  PU R2                  PU R4                  PU R6                  PU R8                  PU R:                  PU R<                  PU R>                  PU R@                  PU RB                  PU RD                  P[G        U RH                  5      P[G        U RJ                  5      P[G        U RL                  5      PU RN                  =(       d    SPU R                  PUPUPUPUPUP[G        U RP                  5      P[G        U RR                  5      P[G        U RT                  5      P75        URV                  nU R                  (       Ga  UR                  5       nU R                   H  nUR                  SUURX                  URZ                  [G        UR\                  5      UR^                  UR`                  [G        URb                  5      URd                  =(       d    S45        URV                  nURf                  (       d  M  UR                  5       nURf                   H5  nUR                  SUURh                  [G        URj                  5      45        M7     M     U Rl                  (       a7  UR                  5       nU Rl                   H  nUR                  SUU45        M     URo                  5         XXXEUS.URq                  5         $ ! [r         a)  n URu                  5         Ue! [r         a     Uef = fS nAff = f! URq                  5         f = f)Nc              3   J   #    U  H  oR                   =(       d    S v   M     g7frD  rE  rF  s     rG   r  create_quote.<locals>.<genexpr>  rI  rJ  r8  rK  rL  rM  rN  rO  r*  rP  rS  rT  rU  z
            SELECT
              COALESCE(MAX(CAST(SUBSTRING(quote_unique_number, 3) AS UNSIGNED)), 0) AS max_seq,
              COUNT(*) AS row_count
            FROM quotes
            r   r}   r(  r)  a  
            INSERT INTO quotes (
              quote_unique_number,
              partner_id, partner_name, order_no, quote_date, order_type,
              customer_id, customer_first_names, customer_surname, customer_email, customer_contact_number,
              customer_country, customer_street, customer_province_state, customer_city, customer_postal_code,
              company_name, company_physical_address, company_phone_number, company_email,
              company_vat_number, company_registration_number, company_logo_url,
              quote_status, quote_currency,
              sub_total, vat_amount, total_amount, deposit_percent, deposit_amount_due,
              terms_and_conditions, payment_details, office_notes
            ) VALUES (
              %s,
              %s,%s,%s,%s,%s,
              %s,%s,%s,%s,%s,
              %s,%s,%s,%s,%s,
              %s,%s,%s,%s,
              %s,%s,%s,
              %s,%s,
              %s,%s,%s,%s,%s,
              %s,%s,%s
            )
            rV  rW  r  rX  rY  r[  );r*  r\  r1  r  r+  r]  r,  r-  r)  r.  r?   r^  rV   rW   r:  r>  maxr  r  r  r  rc  r  r  r   r!  r"  r#  r$  r%  r&  r  r  r  r  rO   r  r  r'  r(  r/  r0  r  r   r  r  r  r  r  r  r  r  r  r  r2  r   r[   r\   rollback)rn   r*  r_  r+  r,  r-  r.  r^   r_   row_maxrE  	row_countnext_seqnext_quote_numberr1  ra  rG  r4  rb  rc  rd  rv  rj   s                          rG   create_quotert    s&    &-%6%6%B!! L(/(:(:L II ))W4t#H'.'9'9'E##5QZQeghKiJ+2+?+?+K7''QVW`WmopQqL --O(W-C-Cu-L"O8+0F0F.0X"O8+0F0F%0O"O"O7>7Q7Q7]33chiu  LQ  zQ  jR  TU  dVDd kkm 		
 ,,.G
0FgajANg'!*2H
aP	w*Q. #/.
!
""
$+$8$8
:A:J:J
LSL^L^
`g`r`r
 ##
 &-%A%A
 DKC[C[
 ^e]s]s
 v}  vU  vU
 ((	
 +2*A*A	
 DKCbCb	
 eldydy	
 |C  |X  |X	

 $$

 '.&F&F

 IPHdHd

 gnf{f{
 w99:
 =K7KnKn<o
 r@  AH  AY  AY  rZ
 %%>)>
 BIAWAW
 
 &
 (4
 6E
 GY
 w;;<
 ?MWMdMd>e
 hvv}  wK  wK  hL
1#	
H == [[]F(( !""2"2BLL.QSQ[Q[B\^`^k^kmom{m{  ~L  MO  Me  Me  ~f  ik  i|  i|  iG  @G	  &//<<<#{{}H ll (( J)2+=+=~bNcNc?de + ), [[]F((St$ ) 	 W`  MY  Ug  h 	

  	MMO   		 	

sJ   LT B7T 
U
"T42U4
U>UUUU

U Uz/quotes/{quote_id}/documentsc                     [        5       n UR                  SS9nUR                  SU 45        UR                  5       UR	                  5         $ ! UR	                  5         f = f)NTrS   r5  r=  r@  s      rG   list_quote_documentsrv    sT    DkkTk* FK	
 ||~



   1A A .filec                 \   [         R                  R                  [        SU  35      n[         R                  " USS9  [        [        R                  " 5       R                  5       5       S[        R                  " S5       SUR                   3n[         R                  R                  X#5      n[        US5       nUR                  UR                  R                  5       5        S S S 5        [         R                  R!                  U[        5      R#                  SS5      n[%        5       n UR'                  5       nUR)                  S	XUR                  UR*                  45        UR,                  n	U	S
U 3S.UR/                  5         $ ! , (       d  f       N= f! UR/                  5         f = f)Nquote_Tr$   rd     wb\/z[INSERT INTO quote_documents (quote_id, file_url, file_name, mime_type) VALUES (%s,%s,%s,%s)	/uploads/)r~   file_urlospathr<  r"   makedirsr>  r   utcnow	timestampsecrets	token_hexfilenameopenwriterx  readrelpathr  r?   rV   rW   content_typer   r[   )
r1  rx  safe_dirunique_name	file_pathr  rel_pathr^   r_   doc_ids
             rG   upload_quote_documentr    s9   ww||J&
(;<HKK4(*44678':K:KA:N9OqQUQ^Q^P_`KX3I	i	#		$)).."# 
wwy*5==dCHHD	kkmi0A0AB	
 IhZ*@A

 
	 	

   :*F+AF 
FF+z	/hs-codesc                     [        5       n  U R                  SS9n UR                  S5        UR                  5       (       a1  UR                  S5        UR	                  5       U R                  5         $  UR                  S5        UR	                  5       U R                  5         $ ! [         a     N=f = f! U R                  5         f = f)NTrS   z"SHOW TABLES LIKE 'hs_codes_master'zFSELECT code as hs_code, description FROM hs_codes_master ORDER BY codezGSELECT DISTINCT hs_code as hs_code FROM quote_hs_codes ORDER BY hs_code)r?   rV   rW   r:  rX   r[   r\   r>  s     rG   list_hs_codesr  )  s    DkkTk*	KK<=||~~de||~ 	

 
 	]^||~

  		
 	

s/   B5 AB% 3!B5 %
B2/B5 1B22B5 5Cc                    [        5       n UR                  5       nUR                  SU R                  =(       d    SU R                  U R
                  U R                  U R                  U R                  U R                  U R                  U R                  U R                  U R                  U R                  U R                  U R                   U R"                  [%        U R&                  5      U R(                  U R*                  [%        U R,                  5      [%        U R.                  5      [%        U R0                  5      [%        U R2                  5      [%        U R4                  5      [%        U R6                  5      [%        U R8                  5      45        UR:                  nUR=                  5         SU0UR?                  5         $ ! UR?                  5         f = f)Na   
            INSERT INTO partners (
              status, partner_type,
              company_name, company_vat, company_email, company_contact_number,
              company_country, company_street, company_province, company_city, company_postal_code,
              first_name, surname, email, contact_number,
              hunting_outfitter_id, comms_local_percent, comms_export_percent, outfitter_documents,
              professional_hunter_id, professional_hunter_permit_type,
              professional_hunter_permit_issue_date, professional_hunter_permit_expiry_date,
              professional_hunter_documents, office_notes
            ) VALUES (
              %s,%s,%s,%s,%s,%s,%s,%s,%s,%s,
              %s,%s,%s,%s,%s,%s,%s,%s,%s,%s,
              %s,%s,%s,%s,%s
            )
            r  r~   ) r?   rV   rW   rh  r  r  r  r  r  r  r  r  r  r  r  rk  rl  rm  rO   r  r  r  r  r  r  r  r  r  r  r   r   r[   rK  s       rG   create_partnerr  <  sx   D"kkm" (4+<+<!!4#3#3T5G5GIdId$$d&9&94;P;PRVRcRceie}e}tzz4;N;Nt8894;S;SUYUnUnp~  @D  @X  @X  qYt::;^DLpLp=qtIIJN[_  \G  \G  MHtAABNSWSdSdDe	#	
8 f~



s   F%G Gc                    [        5       n UR                  5       nUR                  SUR                  UR                  UR
                  UR                  UR                  UR                  UR                  UR                  UR                  UR                  UR                  UR                  UR                  UR                   UR"                  [%        UR&                  5      UR(                  UR*                  [%        UR,                  5      [%        UR.                  5      [%        UR0                  5      [%        UR2                  5      [%        UR4                  5      [%        UR6                  5      [%        UR8                  5      U 45        UR:                  S:X  a
  [=        SSS9eUR?                  5         SS0URA                  5         $ ! URA                  5         f = f)Na  
            UPDATE partners SET
              status=%s, partner_type=%s,
              company_name=%s, company_vat=%s, company_email=%s, company_contact_number=%s,
              company_country=%s, company_street=%s, company_province=%s, company_city=%s, company_postal_code=%s,
              first_name=%s, surname=%s, email=%s, contact_number=%s,
              hunting_outfitter_id=%s, comms_local_percent=%s, comms_export_percent=%s, outfitter_documents=%s,
              professional_hunter_id=%s, professional_hunter_permit_type=%s,
              professional_hunter_permit_issue_date=%s, professional_hunter_permit_expiry_date=%s,
              professional_hunter_documents=%s, office_notes=%s
            WHERE id = %s
            r   r   r,  rs   r   T)!r?   rV   rW   rh  r  r  r  r  r  r  r  r  r  r  r  rk  rl  rm  rO   r  r  r  r  r  r  r  r  r  r  r   r   r   r[   )r  rI  r^   r_   s       rG   update_partnerr  d  s   D kkm T..!!4#3#3T5G5GIdId$$d&9&94;P;PRVRcRceie}e}tzz4;N;Nt8894;S;SUYUnUnp~  @D  @X  @X  qYt::;^DLpLp=qtIIJN[_  \G  \G  MHtAABNSWSdSdDe
	
2 <<1C8KLL4 



s   F+G Gc                    [        5       n UR                  5       nUR                  SU 45        UR                  S:X  a
  [	        SSS9eUR                  5         SS0UR                  5         $ ! UR                  5         f = f)Nz5UPDATE partners SET status = 'Inactive' WHERE id = %sr   r   r,  rs   r   Tr   r  r^   r_   s      rG   delete_partnerr    sk     DkkmKj][<<1C8KLL4 



r   z /partners/{partner_id}/documentsc                     [        5       n UR                  SS9nUR                  SU 45        UR                  5       UR	                  5         $ ! UR	                  5         f = f)NTrS   z
            SELECT id, file_path, file_name, mime_type, created_at
            FROM partner_documents
            WHERE partner_id = %s AND deleted_at IS NULL
            ORDER BY created_at DESC
            r=  r  s      rG   list_partner_documentsr    sU    DkkTk* M	
 ||~



rw  c                 \   [         R                  R                  [        SU  35      n[         R                  " USS9  [        [        R                  " 5       R                  5       5       S[        R                  " S5       SUR                   3n[         R                  R                  X#5      n[        US5       nUR                  UR                  R                  5       5        S S S 5        [         R                  R!                  U[        5      R#                  SS5      n[%        5       n UR'                  5       nUR)                  S	XUR                  UR*                  45        UR,                  n	U	S
U 3S.UR/                  5         $ ! , (       d  f       N= f! UR/                  5         f = f)Npartner_Tr$   rd  r{  r|  r}  r~  z`INSERT INTO partner_documents (partner_id, file_path, file_name, mime_type) VALUES (%s,%s,%s,%s)r  r~   r  r  )
r  rx  r  r  r  r  r  r^   r_   r  s
             rG   upload_partner_documentr    s;   ww||J(:,(?@HKK4(*44678':K:KA:N9OqQUQ^Q^P_`KX3I	i	#		$)).."# 
 wwy*5==dCHHD	kkmn4==$2C2CD	
 Yxj+AB

 
	 	

r  z)/partners/{partner_id}/documents/{doc_id}r  c                 X   UR                  S5      =(       d    SR                  5       nU(       d
  [        SSS9e[        5       n UR	                  5       nUR                  SX1U 45        UR                  S:X  a
  [        SS	S9eS
S0UR                  5         $ ! UR                  5         f = f)N	file_namerI   rq   file_name is requiredrs   zMUPDATE partner_documents SET file_name = %s WHERE id = %s AND partner_id = %sr   r   Document not foundr   TrZ   rL   r   r?   rV   rW   r   r[   )r  r  rI  new_namer^   r_   s         rG   rename_partner_documentr    s    %+224H4KLLD
kkm[z*	
 <<1C8LMM4 



   AB B)c                     [        5       n UR                  5       nUR                  SX45        UR                  S:X  a
  [	        SSS9eSS0UR                  5         $ ! UR                  5         f = f)NzQUPDATE partner_documents SET deleted_at = NOW() WHERE id = %s AND partner_id = %sr   r   r  rs   r   TrR  )r  r  r^   r_   s       rG   soft_delete_partner_documentr    sf    D
kkm_ 	
 <<1C8LMM4 



rT  z2/partners/{partner_id}/documents/{doc_id}/downloadc                 ,   [        5       n UR                  SS9nUR                  SX45        UR                  5       nU(       d
  [	        SSS9e[
        R                  R                  [        US   5      n[
        R                  R                  U5      (       d
  [	        SSS9eUS	   =(       d    [
        R                  R                  U5      n[        XTR                  S
5      =(       d    SUS9UR                  5         $ ! UR                  5         f = f)NTrS   zvSELECT file_path, file_name, mime_type FROM partner_documents WHERE id = %s AND partner_id = %s AND deleted_at IS NULLr   r  rs   r  File missingr  	mime_typeapplication/octet-stream
media_typer  r?   rV   rW   r:  r   r  r  r<  r"   isfilebasenamer   rZ   r[   )r  r  r^   r_   rD  abs_pathr  s          rG   download_partner_documentr    s    DkkTk* E 	
 llnC8LMM77<<
C,<=ww~~h''CGG{#Arww'7'7'AH1E1cIcnvw



   C$D Dz/auth/login)response_modelc                    [        5       n UR                  SS9nUR                  SU R                  U R                  45        UR	                  5       nU(       a  UR                  S5      (       d
  [        SSS9e[        R                  U R                  US   5      (       d
  [        SSS9eUR                  SUS	   45        S
US	   UR                  S5      S.UR                  5         $ ! UR                  5         f = f)NTrS   zKSELECT id, password_hash, role FROM users WHERE username = %s OR email = %spassword_hashi  zInvalid credentialsrs   z1UPDATE users SET last_login = NOW() WHERE id = %sr~   zLogin successfulrd  )rb  rc  rd  )r?   rV   rW   rX  r:  rZ   r   rP  verifyr:   r[   )rn   r^   r_   rD  s       rG   loginr    s    DkkTk*Y!3!34	
 lln#''/22C8MNN!!'"2"2C4HIIC8MNNG#d)V-c$iQTQXQXY_Q`a



s   CC* *C<z/auth/forgot-passwordc                    [        5       n UR                  SS9nUR                  SU R                  45        UR	                  5       nU(       d  SS0UR                  5         $ [        R                  " S5      n[        R                  " 5       [        SS9-   nUR                  5       nUR                  S	XEUS
   45        SU 3n[        R                  " S5      n[        [        R                  " SS5      5      n	[        R                  " SS5      R                  5       S;   n
[        R                  " S5      n[        R                  " S5      nU(       a  U(       a  U(       a   [        5       nSUS'   XS'   U R                  US'   UR!                  SU S35        ["        R$                  " XSS9 nU
(       a  UR'                  5         UR)                  X5        UR+                  U5        S S S 5        SXGS.UR                  5         $ ! , (       d  f       N#= f! [,         a  n[/        SU 35         S nANCS nAff = f! UR                  5         f = f)NTrS   %SELECT id FROM users WHERE email = %srb  z/If the email exists, a reset link has been sent0   r}   )hourszUUPDATE users SET password_reset_token = %s, password_reset_expires = %s WHERE id = %sr~   z&http://localhost:40773/reset-password/	SMTP_HOST	SMTP_PORT587SMTP_STARTTLStrue)rx   r  yeson	SMTP_USERSMTP_PASSWORDzPassword Reset InstructionsSubjectFromTozHello,

A password reset was requested for your account. If you made this request, click the link below to reset your password. This link will expire in 1 hour.

zA

If you did not request this, you can safely ignore this email.
   )timeoutz%[forgot-password] Email send failed: )rb  r  
reset_link)r?   rV   rW   rl  r:  r[   r  token_urlsafer   r  r   r  getenvr>  r  r   set_contentsmtplibSMTPstarttlsr  send_messager\   print)rn   r^   r_   rD  r  
expires_atr?  r  	smtp_host	smtp_portsmtp_starttls	smtp_usersmtp_passwordmsgserverrj   s                   rG   forgot_passwordr    s   D.kkTk*;gmm=MNllnPQP 	

O %%b)__&);;
{{}cD	*	
 >eWE
 IIk*			+u56			/6:@@BF``IIk*			/2}C"n!>I'F#MMD	;;E, GWX \\)Cv$)LL:'',	 D MW\w

 DC
  C=aSABBC 	

sb   AH= #D H= $AH 0:H*H 2H= 
HH H= H 
H:"H50H= 5H::H= =Iz/auth/reset-passwordc                     [        U R                  5      S:  a
  [        SSS9e[        5       n UR	                  SS9nUR                  SU R                  45        UR                  5       nU(       d
  [        SSS9eUS	   [        R                  " 5       :  a
  [        SS
S9e[        R                  U R                  5      nUR	                  5       nUR                  SXCS   45        SS0UR                  5         $ ! UR                  5         f = f)Nr{  rq   &Password must be at least 8 charactersrs   TrS   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 = %sr~   rb  zPassword reset successful)r_  r  r   r?   rV   rW   r  r:  r   r  rP  rQ  r[   )rn   r^   r_   rD  r  r?  s         rG   reset_passwordr  F  s    
7 1$4\]]DkkTk*Z]]	
 llnCHH'(8??+<<CHH#(()=)=>{{}{I&	
 67



s   B;C; ;Dz/usersc                      [        5       n  U R                  SS9nUR                  S5        UR                  5       U R	                  5         $ ! U R	                  5         f = f)NTrS   z
            SELECT id, username, email, role, last_login, created_at
            FROM users
            ORDER BY username
            r=  r>  s     rG   
list_usersr  b  sN    DkkTk*	
 ||~



r@  c                        \ rS rSr% \\S'   Srg)UpdateRoleRequestis  rd  rE   NrY  rE   rF   rG   r  r  s  s    
IrF   r  z/users/{user_id}/roleuser_idc                    UR                   R                  5       R                  5       n1 SknX#;  a
  [        SSS9eUS;   a  UOUn[	        5       n UR                  5       nUR                  SX@45        UR                  S:X  a
  [        SS	S9eUR                  5         S
S0UR                  5         $ ! UR                  5         f = f)N>   r9   rN  staffofficecustomerrq   Invalid rolers   >   r9   rN  r  z(UPDATE users SET role = %s WHERE id = %sr   r   User not foundr   T)
rd  rL   r  r   r?   rV   rW   r   r   r[   )r  rI  rd  validrole_dbr^   r_   s          rG   update_user_roler  w  s    99??""$D<ENCC99dtGDkkm>@RS<<1C8HII4 



s   AB2 2Cc                   R    \ rS rSr% \\S'   Sr\\   \S'   \\S'   Sr	\\   \S'   Sr
g)CreateUserRequesti  usernameNrl  rd  r:   rE   )rZ  r[  r\  r]  rK   r^  rl  r   r   r:   r_  rE   rF   rG   r  r    s)    M $E8H$
I"Hhsm"rF   r  c                    U R                   R                  5       R                  5       n1 SknX;  a
  [        SSS9eU R                  R                  5       nU(       d
  [        SSS9eU R
                  b#  [        U R
                  5      S:  a
  [        SSS9e[        5       n UR                  SS	9nUR                  S
U45        UR                  5       (       a
  [        SSS9eU R                  (       a<  UR                  SU R                  45        UR                  5       (       a
  [        SSS9eU R
                  (       a  [        R                  U R
                  5      OS nUR                  5       nUR                  SX0R                  Xa45        UR                  nUR                  5         SU0UR!                  5         $ ! UR!                  5         f = f)N>   rN  r  r  rq   r  rs   zUsername is requiredr{  r  TrS   rO  Username already in user  Email already in usezPINSERT INTO users (username, email, password_hash, role) VALUES (%s, %s, %s, %s)r~   )rd  rL   r  r   r  r:   r_  r?   rV   rW   r:  rl  rP  rQ  r   r   r[   )	rI  rd  r  r  r^   r_   password_hash_valuer?  r  s	            rG   create_userr    sm   99??""$D(ENCC}}""$H4JKK}} S%7!%;4\]]DkkTk*>L<<>>C8QRR::KK?$**O||~~#<RSSAEk..t}}=TX{{}^zz#6=	
 ..g



s   "DG   Gc                        \ rS rSr% \\S'   Srg)ChangePasswordRequesti  r  rE   NrY  rE   rF   rG   r  r    s    rF   r  z/users/{user_id}/passwordc                    [        UR                  5      S:  a
  [        SSS9e[        R	                  UR                  5      n[        5       n UR                  5       nUR                  SX 45        UR                  S:X  a
  [        SSS9eUR                  5         S	S
0UR                  5         $ ! UR                  5         f = f)Nr{  rq   r  rs   z1UPDATE users SET password_hash = %s WHERE id = %sr   r   r  r   T)r_  r  r   rP  rQ  r?   rV   rW   r   r   r[   )r  rI  r  r^   r_   s        rG   change_user_passwordr    s    
4!4\]]$$T%6%67MDkkmG-Iab<<1C8HII4 



s   AB/ /Cc                   >    \ rS rSr% Sr\\   \S'   Sr\\	   \S'   Sr
g)UpdateUserRequesti  Nr  rl  rE   )rZ  r[  r\  r]  r  r   rK   r^  rl  r   r_  rE   rF   rG   r  r    s    "Hhsm" $E8H$rF   r  z/users/{user_id}c                    [        5       n UR                  SS9nUR                  SU 45        UR                  5       nU(       d
  [	        SSS9eUR
                  =(       d    US   R                  5       nUR                  b  UR                  OUS   nUR                  S	XP45        UR                  5       (       a
  [	        S
SS9eU(       a2  UR                  SX`45        UR                  5       (       a
  [	        S
SS9eUR                  5       nUR                  SXVU 45        UR                  S:X  a
  [	        SSS9eUR                  5         SS0UR                  5         $ ! UR                  5         f = f)NTrS   z3SELECT id, username, email FROM users WHERE id = %sr   r  rs   r  rl  z5SELECT id FROM users WHERE username = %s AND id <> %srq   r  z2SELECT id FROM users WHERE email = %s AND id <> %sr  z8UPDATE users SET username = %s, email = %s WHERE id = %sr   r   )r?   rV   rW   r:  r   r  rL   rl  r   r   r[   )r  rI  r^   r_   existingnew_username	new_emailr?  s           rG   update_userr    s>   DkkTk*IG:V<<>C8HII=*)=DDF#'::#9TZZx?P	 	KlMde<<>>C8QRRKKLyNbc||~~#<RSS{{}Fg.	
 ==AC8HII4 



s   EE   E2z/ordersc                      [        5       n  U R                  SS9nUR                  S5        UR                  5       U R	                  5         $ ! U R	                  5         f = f)NTrS   a  
            SELECT id,
                   order_unique_number,
                   related_quote_id,
                   related_quote_number,
                   related_invoice_id,
                   related_invoice_number,
                   order_type,
                   processing_type,
                   customer_id,
                   customer_name,
                   order_delivery,
                   deposit_received,
                   instructions_finalised,
                   order_paid_in_full,
                   office_notes,
                   created_at,
                   updated_at
            FROM orders
            ORDER BY created_at DESC
            r=  r>  s     rG   
get_ordersr
    sN    DkkTk*	
. ||~



r@  z/orders/{order_id}order_idc                     [        5       n UR                  SS9nUR                  SU 45        UR                  5       nU(       d
  [	        SSS9eUUR                  5         $ ! UR                  5         f = f)NTrS   a  
            SELECT id,
                   order_unique_number,
                   related_quote_id,
                   related_quote_number,
                   related_invoice_id,
                   related_invoice_number,
                   order_type,
                   processing_type,
                   customer_id,
                   customer_name,
                   order_delivery,
                   deposit_received,
                   instructions_finalised,
                   order_paid_in_full,
                   office_notes,
                   created_at,
                   updated_at
            FROM orders
            WHERE id = %s
            r   Order not foundrs   rE  )r  r^   r_   rD  s       rG   	get_orderr    sk    DkkTk** K-	
0 llnC8IJJ



rH  rK  c                    [        5       n UR                  5       nUR                  SU R                  U R                  U R
                  U R                  U R                  U R                  U R                  U R                  U R                  U R                  =(       d    SU R                  =(       d    SU R                  =(       d    SU R                  45        UR                   nUR                  SS9nUR                  SU45        UR#                  5       nX5=(       d    0 R%                  S5      S.UR'                  5         $ ! UR'                  5         f = f)Na0  
            INSERT INTO orders (
                related_quote_id,
                related_quote_number,
                related_invoice_id,
                related_invoice_number,
                order_type,
                processing_type,
                customer_id,
                customer_name,
                order_delivery,
                deposit_received,
                instructions_finalised,
                order_paid_in_full,
                office_notes
            ) VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)
            r+  TrS   z4SELECT order_unique_number FROM orders WHERE id = %sr  )r~   r  )r?   rV   rW   r  r  r  r  r  r  rc  r  r  r  r  r  r  r   r:  rZ   r[   )rK  r^   r_   rL  r?  rD  s         rG   create_orderr  :  s   D+kkm$ &&**((,,  %%!!##$$&&.$,,4((0D""%!	
D {{d{+KfYWmmoiR__EZ5[\



s   D%E Ec                    [        5       n UR                  5       nUR                  SUR                  UR                  UR
                  UR                  UR                  UR                  UR                  UR                  UR                  UR                  UR                  UR                  UR                  U 45        UR                   S:X  a
  [#        SSS9eSS0UR%                  5         $ ! UR%                  5         f = f)Na>  
            UPDATE orders SET
                related_quote_id = %s,
                related_quote_number = %s,
                related_invoice_id = %s,
                related_invoice_number = %s,
                order_type = %s,
                processing_type = %s,
                customer_id = %s,
                customer_name = %s,
                order_delivery = %s,
                deposit_received = %s,
                instructions_finalised = %s,
                order_paid_in_full = %s,
                office_notes = %s
            WHERE id = %s
            r   r   r  rs   r   T)r?   rV   rW   r  r  r  r  r  r  rc  r  r  r  r  r  r  r   r   r[   )r  rK  r^   r_   s       rG   update_orderr  k  s    D)kkm$ &&**((,,  %%!!##$$&&,,((""%"	
F <<1C8IJJ4 



r  c                     [        5       n UR                  5       nUR                  SU 45        UR                  S:X  a
  [	        SSS9eSS0UR                  5         $ ! UR                  5         f = f)Nz DELETE FROM orders WHERE id = %sr   r   r  rs   r   TrR  )r  r^   r_   s      rG   delete_orderr    s`    Dkkm6D<<1C8IJJ4 



rT  z"/customers/{customer_id}/documentsrc  c                     [        5       n UR                  SS9nUR                  SU 45        UR                  5       nUUR	                  5         $ ! UR	                  5         f = f)NTrS   z
            SELECT id, file_path, file_name, mime_type, created_at
            FROM customer_documents
            WHERE customer_id = %s AND deleted_at IS NULL
            ORDER BY created_at DESC
            r=  )rc  r^   r_   r`   s       rG   list_customer_documentsr    sZ    DkkTk* N	
 ||~



s   3A A"c                 h   [         R                  R                  [        [	        U 5      5      n[         R
                  " USS9  [        [        R                  " 5       R                  5       5       S[        R                  " S5       SUR                   3n[         R                  R                  X#5      n[        US5       nUR                  UR                  R!                  5       5        S S S 5        [         R                  R#                  U[        5      R%                  SS5      n['        5       n UR)                  5       nUR+                  SXUR                  UR,                  45        UR.                  n	U	S	U 3S
.UR1                  5         $ ! , (       d  f       N= f! UR1                  5         f = f)NTr$   rd  r{  r|  r}  r~  zbINSERT INTO customer_documents (customer_id, file_path, file_name, mime_type) VALUES (%s,%s,%s,%s)r  r  )r  r  r<  r"   rK   r  r>  r   r  r  r  r  r  r  r  rx  r  r  r  r?   rV   rW   r  r   r[   )
rc  rx  r  r  r  r  r  r^   r_   r  s
             rG   upload_customer_documentr    s9   ww||JK(89HKK4(*44678':K:KA:N9OqQUQ^Q^P_`KX3I	i	#		$)).."# 
 wwy*5==dCHHD	kkmpDMM43D3DE	
 Yxj+AB

 
	 	

s    *F1AF 
FF1z+/customers/{customer_id}/documents/{doc_id}c                 X   UR                  S5      =(       d    SR                  5       nU(       d
  [        SSS9e[        5       n UR	                  5       nUR                  SX1U 45        UR                  S:X  a
  [        SS	S9eS
S0UR                  5         $ ! UR                  5         f = f)Nr  rI   rq   r  rs   zOUPDATE customer_documents SET file_name = %s WHERE id = %s AND customer_id = %sr   r   r  r   Tr  )rc  r  rI  r  r^   r_   s         rG   rename_customer_documentr    s    %+224H4KLLD
kkm]{+	
 <<1C8LMM4 



r  c                     [        5       n UR                  5       nUR                  SX45        UR                  S:X  a
  [	        SSS9eSS0UR                  5         $ ! UR                  5         f = f)NzSUPDATE customer_documents SET deleted_at = NOW() WHERE id = %s AND customer_id = %sr   r   r  rs   r   TrR  )rc  r  r^   r_   s       rG   soft_delete_customer_documentr    sf    D
kkma!	
 <<1C8LMM4 



rT  z4/customers/{customer_id}/documents/{doc_id}/downloadc                 ,   [        5       n UR                  SS9nUR                  SX45        UR                  5       nU(       d
  [	        SSS9e[
        R                  R                  [        US   5      n[
        R                  R                  U5      (       d
  [	        SSS9eUS	   =(       d    [
        R                  R                  U5      n[        XTR                  S
5      =(       d    SUS9UR                  5         $ ! UR                  5         f = f)NTrS   zxSELECT file_path, file_name, mime_type FROM customer_documents WHERE id = %s AND customer_id = %s AND deleted_at IS NULLr   r  rs   r  r  r  r  r  r  r  )rc  r  r^   r_   rD  r  r  s          rG   download_customer_documentr    s    DkkTk* G!	
 llnC8LMM77<<
C,<=ww~~h''CGG{#Arww'7'7'AH1E1cIcnvw



r  z
/customersc                      [        5       n  U R                  SS9nUR                  S5        UR                  5       nUU R	                  5         $ ! U R	                  5         f = f)NTrS   aI  
            SELECT id, customer_unique_number, status, customer_type, first_names, surname,
                   email, contact_number, whatsapp_number,
                   physical_country, physical_street, physical_province_state, physical_city, physical_postal_code,
                   ship_country, ship_street, ship_province_state, ship_city, ship_postal_code,
                   referred_by, preferred_currency, citizenship, rsa_id, passport_number,
                   documents, office_notes, created_at
            FROM customers
            ORDER BY created_at DESC
            r=  )r^   r_   results      rG   get_customersr!  	  sS    DkkTk*		
 



rw  r  c                 6   [        5       n UR                  5       n UR                  SU R                  =(       d    SU R                  U R
                  U R                  U R                  U R                  U R                  U R                  U R                  U R                  U R                  U R                  U R                  U R                   U R"                  U R$                  U R&                  U R(                  U R*                  U R,                  U R.                  U R0                  U R2                  U R4                  45        UR@                  nU R                  (       a  U R                  OSU 3nUR                  5       nUnS	n UR                  S
U45        URC                  5       (       d  OUS	-  nU U 3nM6  Un	S n
 UR                  SXR                  U
SU45        URE                  5         SU0URG                  5         $ ! [6        R8                  R:                   a!  n[=        USS 5      S:X  a
  [?        SSS9ee S nAff = f! [6        R8                  R:                   a!  n[=        USS 5      S:X  a
  [?        SSS9ee S nAff = f! URG                  5         f = f)NaF  
                INSERT INTO customers (
                  status, customer_type, first_names, surname, email, contact_number, whatsapp_number,
                  physical_country, physical_street, physical_province_state, physical_city, physical_postal_code,
                  ship_country, ship_street, ship_province_state, ship_city, ship_postal_code,
                  referred_by, preferred_currency, citizenship, rsa_id, passport_number, documents, office_notes
                ) VALUES (%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s)
                r  rd   &  rq   r  rs   r  r}   rO  z
                INSERT INTO users (username, email, password_hash, role, customer_id)
                VALUES (%s, %s, %s, %s, %s)
                r~   )$r?   rV   rW   rh  ri  rj  rk  rl  rm  rn  ro  rp  rq  rr  rs  rt  ru  rv  rw  rx  ry  rz  r{  r|  r}  r~  r  r@   rA   rg   rh   r   r   r:  r   r[   )r  r^   r_   rj   rL  r  r?  	candidatesuffixusername_finalr  s              rG   create_customerr'     sa   D?kkm	KK __083I3I8K_K_aiaqaqs{  tB  tB++X-E-ExG`G`bjbzbz44h6L6LhNkNk))8+?+?A]A]_g_q_q--x/C/CXE`E`bjbvbvOOX%=%=x?Q?QS[ShSh.  &.^^8>>8F89L{{}	LLCi\R==??aKF#*VH-I  # #	LL  1DjRXY 	f~

S $$ 	q'4(D0#<RSS	@ $$ 	q'4(D0#<RSS		 	

sT   J D#H  A=J > I J I H<<IJ J"I>>JJ Jz/customers/{customer_id}c                     [        5       n UR                  SS9nUR                  SU 45        UR                  5       nU(       d
  [	        SSS9eUUR                  5         $ ! UR                  5         f = f)NTrS   a>  
            SELECT id, customer_unique_number, status, customer_type, first_names, surname,
                   email, contact_number, whatsapp_number,
                   physical_country, physical_street, physical_province_state, physical_city, physical_postal_code,
                   ship_country, ship_street, ship_province_state, ship_city, ship_postal_code,
                   referred_by, preferred_currency, citizenship, rsa_id, passport_number,
                   documents, office_notes, created_at
            FROM customers
            WHERE id = %s
            r   Customer not foundrs   rE  )rc  r^   r_   rD  s       rG   get_customerr*  e  sk    DkkTk*	 N	
 llnC8LMM



rH  c                    [        5       n UR                  5       n UR                  SUR                  UR                  UR
                  UR                  UR                  UR                  UR                  UR                  UR                  UR                  UR                  UR                  UR                  UR                   UR"                  UR$                  UR&                  UR(                  UR*                  UR,                  UR.                  UR0                  UR2                  UR4                  U 45        UR@                  S:X  a
  [?        SS	S9eURC                  5         S
S0URE                  5         $ ! [6        R8                  R:                   a!  n[=        USS 5      S:X  a
  [?        SSS9ee S nAff = f! URE                  5         f = f)Na  
                UPDATE customers SET
                  status = %s,
                  customer_type = %s,
                  first_names = %s,
                  surname = %s,
                  email = %s,
                  contact_number = %s,
                  whatsapp_number = %s,
                  physical_country = %s,
                  physical_street = %s,
                  physical_province_state = %s,
                  physical_city = %s,
                  physical_postal_code = %s,
                  ship_country = %s,
                  ship_street = %s,
                  ship_province_state = %s,
                  ship_city = %s,
                  ship_postal_code = %s,
                  referred_by = %s,
                  preferred_currency = %s,
                  citizenship = %s,
                  rsa_id = %s,
                  passport_number = %s,
                  documents = %s,
                  office_notes = %s
                WHERE id = %s
                rd   r#  rq   r  rs   r   r   r)  r   T)#r?   rV   rW   rh  ri  rj  rk  rl  rm  rn  ro  rp  rq  rr  rs  rt  ru  rv  rw  rx  ry  rz  r{  r|  r}  r~  r  r@   rA   rg   rh   r   r   r   r[   )rc  r  r^   r_   rj   s        rG   update_customerr,    s   DEkkm=	KK: OO**(($$NN++,,--,,44**11))((00&&--((//((OO,,&&))3;8z <<1C8LMM4 

 $$ 	q'4(D0#<RSS	 	

s/   F8 DE6 8-F8 6F5F00F55F8 8G
c                    [        5       n UR                  5       nUR                  SU 45        UR                  S:X  a
  [	        SSS9eUR                  5         SS0UR                  5         $ ! UR                  5         f = f)Nz6UPDATE customers SET status = 'Inactive' WHERE id = %sr   r   r)  rs   r   Tr   )rc  r^   r_   s      rG   delete_customerr.    si    D	kkmL{n]<<1C8LMM4 



r   __main__zmain:appz0.0.0.0i  info)r7   r8   reload	log_level)r   r   r  r  fastapir   r   r   r   r	   r
   fastapi.responsesr   starlette.staticfilesr   fastapi.middleware.corsr   pydanticr   r   passlib.contextr   mysql.connectorr@   r   typingr   dotenvr   r  email.messager   r  r   r>  r   r   r   r   rP  appr  r<  getcwdr"   r  mountadd_middlewarerK   getpid_pool_suffixMySQLConnectionPoolr>   r?   rO   r]   rb   rZ   rk   postrY   r   putr   deleter   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r  r  r
  rL  rU  rW  ra  rf  r  r  r  r  r  r  r  r  r  r  r  r  r  r  on_eventr6  r;  r?  rB  rG  rM  rP  rS  rV  rX  rh  rn  rp  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r`  r^  r  r  r  r  r  r  r  r  r  r  r  r   r"  r$  r&  r(  r*  r-  r  r0  r>  rA  rf  rh  rj  rt  rv  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r
  r  r  r  r  r  r  r  r  r  r!  r'  r*  r,  r.  rZ  uvicornrunrE   rF   rG   <module>rJ     s   ( ( 	  M M * - 2 ( (  #    &  ))I{
+
bii	6*
+
))I
/ii'9:
))I6
7H:&AiYY|RWW\\"))+y%IJ
 J & 		*kJ7i	 H   
 =%  
 YY|RWW\\"))+y%IJ
 J & 		*kJ7i	 H 299;--'"))ND12				
3 3  	%& ', 
&'  (6 	12#   34 45
# 
 6
 	)* +, 
*+D  ,B 	56c D  7D 89
c 
 :
 	&' (, 
'(  )6 	233   44 56
3 
 7
 	-. /, 
./  0> 	9:#   ;< <=
# 
 >
 	"# $, 
#$T  %8 	./s T  06 12
s 
 3
 	*+ ,, 
+,T  -> 	67s T  8< 9:
s 
 ;
 	34 5, 
45d  68 	?@ d  A6 BC
 
 D
 	89 :, 
9:4  ;6 	DES 4  F4 GH
S 
 I
 	*+ ,, 
+,T  -6 	67s T  84 9:
s 
 ;
 	&' (, 
'(  )B 	233   4D 56
3 
 7
 	!" #, 
"#D  $B 	-.c D  /D 01
c 
 2
rj29 
I 'Y ':I 9 
%) %( 'I  'H*	 *
 9 
 	 3 3"00	 00d	"9 	"	 	"9 	"- -
5) 5) )X i 
  &  0  6 	$%  &> /(/ ( (V 	$%(3 (.? ( &(V '(	3 	 )	 		 	 	'(
# 
 )
 
 4  > 	'("S "0D " )"J *+	S 	 ,	 	% %P 	%&  '* 
/  . 	%&3 .?  '. ()	3 	 *	 	 0 
#1 # #L 	&'.C ./A . (.b )*	C 	 +	 	!" #  
"#6'@ 6 $6r 	./,S ,8Q , 0,^ 12	S 	 3	 	#$ %, 	  < 	"# $< 	$% &0 
%&t  'B 	01 t  2D 34
 
 5
 
#$(<  %< 	./S 8L  0@ 12
S 
 3
A6(*NA6%'HA6  :	A6
 #$BA6 "#@A6 4A6 %&FA6 )*NA6 ()LA6 "#@A6 #$BA6 $%DA6 ()LA6  )*N!A6$ %&F%A6& $%D'A6( *+P)A6* )*N+A6.  !</A60 61A62 %&F3A64 "#@5A68 &'H9A6: +,R;A6> 0?A6@ 4AA6B  :CA6D !">EA6H $%DIA6J ,-TKA6L !">MA6N )*NOA6P 12^QA6R &'HSA6V 2WA6X 8YA6Z #$B[A6\ ,]A6^  !<_A6` #$BaA6b ()LcA6d 6eA6h 6iA6j .kA6l !">mA6n  :oA6p "#@qA6r 8sA6t &'HuA6v $%DwA6z 23`{A6| 1[8j5dAA6
DsCx%S/12 AF<# <$s) <2HtCy HS H 	()G3 G G *GR 	()c 3 6G  *$ 	 & 	 $ 	  !$ 	$% &$ 
%&d  '6 	01 d  26 34
 
 5
 	 $ 	 ! "$  .  & 	./ 0$ 	!"C  #8  %e9c d : : :z 	: : :z  !3  "  	m3 m); m m` 
&'C  (  *+s  , )|, | |~ 	'(
3 
 )
 
()<@I C z  *.  $ +$ $ $N 	!""s "- " #"J $%s  & 	+,s  -$ 
,-@DS	  :  .. 	45 S   6$ 78S #  9 	=># s  ?( -6<  7( 
!"02 0 #0f 
 !0  "6   	  	 !c ):  "&#	 # ( '    FI  	$%# -B  & %	 %
 	   $5    F  @ 	! ! !H )- - -` 	+3 +{ + +\  !	3 	 "	 	-.  /& 
./BFs) # Z  0. 	67# s $  8$ 9:s C  ; 	?@C   A$  , ,An A AH 	#$c  %2 	#$G G G %GT &'  ( zKK
dfU rF   