
    /i                    (   d dl mZ d dlZd dlmZ d dlmZmZmZm	Z	m
Z
 d dlmZ d dlZd dlmZmZ d dlmZmZmZmZ d dlmZ d d	lmZ d d
lmZ d dlmZ d dlmZ d dl m!Z!  ejD                  e#      Z$dZ%dZ&dZ'dZ(d%dZ)d&dZ*d'dZ+ddd(dZ,d)dZ-	 	 	 	 d*	 	 	 	 	 	 	 	 	 	 	 d+dZ.d,dZ/dd	 	 	 	 	 d-dZ0d.dZ1d/dZ2dddd	 	 	 	 	 	 	 	 	 d0dZ3ddd 	 	 	 	 	 	 	 d1d!Z4	 	 	 	 	 	 d2d"Z5	 	 d3	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 d4d#Z6	 	 	 	 	 	 	 	 	 	 	 	 d5d$Z7y)6    )annotationsN)BytesIO)AnyIterableListOptionalTuple)UUID)HTTPExceptionstatus)funcselectupdatedelete)AsyncSession)Select)Vendor	ViolationScrapingResult)settingsu7   Price Violation Notice – Immediate Attention RequiredzProduct Name: {{PRODUCT_NAME}}
Minimum Selling Price (MSP): {{MSP}}
Current Selling Price: {{SCRAPED_PRICE}}
Product URL: {{PRODUCT_URL}}
Detected On: {{VIOLATION_DATE}}a  Dear {{VENDOR_NAME}},

We hope you are doing well.

We have identified that one or more of your product listings are currently being sold below the agreed Minimum Selling Price (MSP).

This may lead to pricing inconsistencies across the market and impact brand positioning.

Below are the details of the identified violation:

{{VIOLATIONS}}

We kindly request you to review the above listing(s) and take corrective action at the earliest to ensure compliance with the pricing policy.

If you believe this has been flagged incorrectly or need further clarification, please feel free to reach out to us.

We appreciate your cooperation and prompt action in resolving this matter.

Best regards,
{{COMPANY_NAME}}
{{SUPPORT_EMAIL}}u
  <!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Price Violation Notice</title>
<style>
  body {{
    font-family: Arial, sans-serif;
    background-color: #f4f6f8;
    margin: 0;
    padding: 0;
  }}
  .container {{
    max-width: 650px;
    margin: 40px auto;
    background: #ffffff;
    padding: 30px;
    border-radius: 8px;
    box-shadow: 0 4px 12px rgba(0,0,0,0.05);
  }}
  h2 {{
    color: #d9534f;
    margin-bottom: 20px;
  }}
  .content p {{
    font-size: 14px;
    color: #333333;
    line-height: 1.6;
  }}
  .violation-box {{
    background: #fff4f4;
    border-left: 4px solid #d9534f;
    padding: 15px;
    margin: 20px 0;
    font-size: 14px;
  }}
  .button {{
    display: inline-block;
    padding: 12px 22px;
    background-color: #007bff;
    color: #ffffff !important;
    text-decoration: none;
    border-radius: 5px;
    margin-top: 20px;
    font-size: 14px;
  }}
  .footer {{
    margin-top: 30px;
    font-size: 12px;
    color: #888888;
    text-align: center;
    border-top: 1px solid #eeeeee;
    padding-top: 15px;
  }}
</style>
</head>
<body>
  <div class="container">
    
    <h2>⚠ Price Violation Notice</h2>

    <div class="content">
      <p>Hello {VENDOR_NAME},</p>

      <p>
        We have identified a pricing violation for one of your listed products 
        associated with the brand <strong>{BRAND_NAME}</strong>.
      </p>

      <div class="violation-box">
        <strong>Violation Details:</strong><br><br>
        Product Name: {PRODUCT_NAME}<br>
        Minimum Selling Price (MSP): ₹{MSP}<br>
        Detected Selling Price: ₹{SCRAPED_PRICE}<br>
        Price Difference: ₹{PRICE_DIFFERENCE}<br>
        Violation Detected On: {VIOLATION_DATE}<br>
        Product URL: 
        <a href="{PRODUCT_URL}" target="_blank">
          View Listing
        </a>
      </div>

      <p>
        As per the agreed pricing policy, selling below the MSP is not permitted. 
        We request you to review and correct the pricing at the earliest.
      </p>

     
      <p style="margin-top: 20px;">
        If you believe this notification was sent in error, 
        Please contact us at <strong>{SUPPORT_EMAIL}</strong>.
      </p>

      <p>
        We appreciate your prompt attention to this matter.
      </p>

      <p>
        Regards,<br>
        <strong>{COMPANY_NAME}</strong>
      </p>
    </div>

    <div class="footer">
      &copy; 2026 {COMPANY_NAME}. All rights reserved.<br>
      This is an automated notification — please do not reply directly to this email.
    </div>

  </div>
</body>
</html>c                 K   | j                  t        t              j                  t        j                  |k(               d {   }|j                         rt        t        j                  d      |t        |      }t        |||||      }| j                  |       | j                          d {    | j                  |       d {    |S 7 7 !7 
w)NzEmail already registeredstatus_codedetail)name
brand_nameemailwebsite_url	is_active)executer   r   wherer   scalar_one_or_noner   r   HTTP_409_CONFLICTstraddcommitrefresh)dbr   r   r   r    r!   existingvendors           A/var/www/html/marco-python-backend/app/services/vendor_service.pycreate_vendorr.      s     ZZv 4 4V\\U5J KLLH""$(@(@Icdd +&*E{fopFFF6N
))+
**V
M M s7   ACCA0C5C6CCCCCc                  K   | j                  t        t              j                  t        j                  |k(               d {   }|j                         }|st        t        j                  d      |S 7 3w)NzVendor not foundr   )	r"   r   r   r#   idr$   r   r   HTTP_404_NOT_FOUND)r*   	vendor_idresultr,   s       r-   
get_vendorr4      s_     ::fVn22699	3IJKKF&&(F(A(AJ\]]M	 Ls   AA:A84A:c                 K   t        | |       d{   }| j                  t        t              j	                  t        j
                  |k(               d{   }|j                         j                         }||fS 7 l7 (w)zuReturn the vendor and a list of all its violations.

    Raises HTTPException(404) if the vendor does not exist.
    r2   N)r4   r"   r   r   r#   r2   scalarsall)r*   r2   r,   r3   
violationss        r-   get_vendor_with_violationsr:      sl     
 bI66F::fY/55i6I6IY6VWXXF!%%'J: 7Xs"   BB ABB'BB)
changed_byc                 K   t        | |       d {   }i }d|v r|d   t        |d         |d<   |j                         D ]8  \  }}t        ||      st	        ||      }||k7  s%||f||<   t        |||       : |rUt        j                  dt        |      ||d       | j                          d {    | j                  |       d {    |S 7 7 !7 
w)Nr6   r    zvendor updated)r2   changesr;   )extra)
r4   r&   itemshasattrgetattrsetattrloggerinfor(   r)   )	r*   r2   datar;   r,   updateskeyvalueolds	            r-   update_vendorrJ      s     bI66FGm!4!@!$}"56]jjl ,
U63&#&Ce| #U|U+, $#i.U\lv,wxiikjj   M! 7 	 sA   CCACC)AC8C9CCCCCc               `  K   ddl m} ddlm} 	 | j	                  t        |      j                  |j                  |k(               d{    t        j                  d|        | j	                  t        |      j                  |j                  |k(               d{    t        j                  d|        | j	                  t        t              j                  t        j                  |k(               d{    | j                          d{    t        j                  d| d       y7 7 7 :7 $# t        $ rf}| j                          d{  7   t        j                  d	t!        |              t#        t$        j&                  d
t!        |             d}~ww xY ww)zKDelete a vendor and cascade-delete related scraping results and violations.r   r   r   Nz4[Vendor Delete] Deleted scraping results for vendor z.[Vendor Delete] Deleted violations for vendor u   [Vendor Delete] ✓ Vendor z& and related data deleted successfullyu-   [Vendor Delete] ✗ Failed to delete vendor: zFailed to delete vendor: r   )app.models.scraping_resultr   app.models.violationr   r"   r   r#   r2   loggingrD   r   r0   r(   	Exceptionrollbackerrorr&   r   r   HTTP_500_INTERNAL_SERVER_ERROR)r*   r2   r   r   es        r-   delete_vendorrT      s\    9.
jj/55n6N6NR[6[\]]]KI;WX jj	*001D1D	1QRSSSEi[QR jj--fii9.DEFFFiik29+=cde 	^ 	T 	G  
kkmEc!fXNO==.s1vh7
 	

s   F.9D< 	D4
AD< D6 AD< =D8>D< D:D< 3F.4D< 6D< 8D< :D< <	F+F&EAF&&F++F.c                $  K   t        t              }|r2|j                  t        j                  j	                  d| d            }t        t        j                               j                  t              }|r2|j                  t        j                  j	                  d| d            }| j                  |       d {   j                         }|dk(  r!|j                  t        j                        }n#|dk(  rq|j                  t              j                  t        j                        j                  t        j                  t        j                        j                               }n|dk(  rt        j                   t        j"                  t        j$                  t        j&                  z
  t        j$                  z        d      }|j                  t              j                  t        j                        j                  |j                               }|dz
  |z  }	|j)                  |	      j+                  |      }| j                  |       d {   }
|
j-                         j/                         j1                         }||fS 7 7 7w)N%r   violation_countaverage_discountr      )r   r   r#   r   iliker   countselect_fromr"   
scalar_oneorder_by	outerjoinr   group_byr0   desccoalesceavgmspscraped_priceoffsetlimitr7   uniquer8   )r*   page	page_sizesort_bysearchstmt
count_stmttotal_countavg_exprrf   r3   vendorss               r-   list_vendorsrr      s     &>Dzz&++++axqM:; 

%11&9J%%fkk&7&7!F81&FG
J//;;=K &}}V[[)	%	% NN9%Xfii Xdjj.3356 	
 
&	&==9==9;R;R+RV_VcVc*c!dfghNN9%Xfii Xhmmo& 	 Qh)#F;;v$$Y/D::d##Fnn%%'++-GK5 0. $s%   B<J>J?FJJ5JJc                   K   | j                  t        t        j                  t        j
                        t        j                  t        j                  t        j                  t        j                  z
  t        j                  z  dz        d            j                  t        j                  |j
                  k(               d {   }|j                         \  }}t        |xs d      t        |xs d      fS 7 5w)Nd   r   g        )r"   r   r   r[   r   r0   rb   rc   rd   re   r#   r2   oneintfloat)r*   r,   r3   r[   rc   s        r-   compute_metricsrx   (  s     ::JJy||$MM$((IMMI4K4K$Ky}}#\_b#bcefg	
 %	##vyy0
1	 F JE3uz?E#*---s   CC>C<6C>)
vendor_idsc                 K   t        t        t              j                  t              }|r<t	        |      dkD  r.|j                  t        j                  j                  |            }| j                  |       d {   }|j                         }t        j                         }|j                  }d|_        g d}|j                  |       |D ]  \  }}	|j                  |	j                  |	j                   |j"                  |j$                  xs d|j&                  xs dt)        |j*                        t)        |j,                        t)        |j*                  |j,                  z
        |j.                  j1                         |j2                  g
        t5               }
|j7                  |
       |
j9                         S 7 Cw)Nr   
Violations)
Vendor Name
Brand NameProduct NameBarcode NumberReference IDMSPScraped PricePrice DifferenceViolation DateURL )r   r   r   joinlenr#   r2   in_r"   r8   openpyxlWorkbookactivetitleappendr   r   product_namebarcode_numberreference_idrw   rd   re   violation_date	isoformaturlr   savegetvalue)r*   ry   rm   r3   rowswbwsheaders	violationr,   streams              r-   export_violationsr   4  sh    
 )V$))&1D c*o)zz)--11*=>::d##F::<D				B	BBHG IIg! 	6
		KK""$$*""(b)-- )))*)--)"9"99:$$..0MM
 	 YFGGFO??G $s   A:G<F?=EGc                 K   ddl m } t        t        t              j	                  t              j                  t        j                  j                  t        |                  }| j                  |       d {   }|j                         }|st        t        j                  d      i }|D ]E  \  }}|j                  |vr|g f||j                  <   ||j                     d   j                  |       G |j                         D ]H  \  }	\  }}
t!        ||
       |
D ]  }|j#                         |_         | j'                          d {    J y 7 7 	w)Nr   datetime!No violations found for given IDsr   rY   )r   r   r   r   r   r#   r0   r   listr"   r8   r   r   r1   r   r?   _send_violation_emailutcnownotification_sent_atr(   )r*   violation_idsr   rm   r3   recordsviolations_by_vendorr   r,   r2   r9   s              r-   send_violation_notificationsr   e  s9    ! )V$))&177	8H8HmI\8]^D::d##FjjlG(A(AJmnn HJ$ =	69900/5rl +VYY'*11)<= ,@+E+E+G '	'FJfj1 $ 	?I-5__->I*	? iik $* 	s%   A7E9E:CEEEEc                   t         j                  }t         j                  }t         j                  }t         j                  }t         j
                  }|r|r|st        d      d}t        |d      D ]  \  }}	t        |	j                        d}
|	j                  rt        |	j                        dnd}|	j                  r+t        |	j                        t        |	j                        z
  nd}|d}|d| d|	j                   d	|
 d
| d| d|	j                  j                          d|	j                   dz  } d| j                   dt!        |      dk(  rdnt!        |       d dt!        |      dk(  rdnd d| j"                   dt!        |       d| dt!        |      dk(  rdnd d|xs d d}ddlm}  |       }d t!        |       d!t!        |      dk(  rd"nd# |d$<   ||d%<   | j(                  |d&<   |j+                  d'       |j-                  |d()       dd l}|j1                  ||      5 }|j3                          |j5                          |j3                          |r@|r>|j7                  |j9                         |j;                  d!d      j9                                |j=                  |       d d d        y # 1 sw Y   y xY w)*NSMTP configuration incompleter   rY   .3fN/Ar   zp
        <div class="violation-item">
            <h4 style="margin: 15px 0 10px 0; color: #d9534f;">Violation #aF  </h4>
            <table style="width: 100%; border-collapse: collapse; font-size: 13px;">
                <tr>
                    <td style="padding: 5px 10px; border-bottom: 1px solid #eee; font-weight: bold; width: 40%;">Product Name:</td>
                    <td style="padding: 5px 10px; border-bottom: 1px solid #eee;">u  </td>
                </tr>
                <tr>
                    <td style="padding: 5px 10px; border-bottom: 1px solid #eee; font-weight: bold;">Minimum Selling Price (MSP):</td>
                    <td style="padding: 5px 10px; border-bottom: 1px solid #eee;">₹u  </td>
                </tr>
                <tr>
                    <td style="padding: 5px 10px; border-bottom: 1px solid #eee; font-weight: bold;">Detected Selling Price:</td>
                    <td style="padding: 5px 10px; border-bottom: 1px solid #eee;">₹u  </td>
                </tr>
                <tr>
                    <td style="padding: 5px 10px; border-bottom: 1px solid #eee; font-weight: bold;">Price Difference:</td>
                    <td style="padding: 5px 10px; border-bottom: 1px solid #eee;">₹a  </td>
                </tr>
                <tr>
                    <td style="padding: 5px 10px; border-bottom: 1px solid #eee; font-weight: bold;">Violation Detected On:</td>
                    <td style="padding: 5px 10px; border-bottom: 1px solid #eee;">a  </td>
                </tr>
                <tr>
                    <td style="padding: 5px 10px; border-bottom: 1px solid #eee; font-weight: bold;">Product URL:</td>
                    <td style="padding: 5px 10px; border-bottom: 1px solid #eee;">
                        <a href="z" target="_blank" style="color: #007bff; text-decoration: none;">View Listing</a>
                    </td>
                </tr>
            </table>
        </div>
        u  <!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Price Violation Notice</title>
<style>
  body {
    font-family: Arial, sans-serif;
    background-color: #f4f6f8;
    margin: 0;
    padding: 0;
  }
  .container {
    max-width: 700px;
    margin: 40px auto;
    background: #ffffff;
    padding: 30px;
    border-radius: 8px;
    box-shadow: 0 4px 12px rgba(0,0,0,0.05);
  }
  h2 {
    color: #d9534f;
    margin-bottom: 20px;
  }
  .content p {
    font-size: 14px;
    color: #333333;
    line-height: 1.6;
  }
  .violations-box {
    background: #fff4f4;
    border-left: 4px solid #d9534f;
    padding: 20px;
    margin: 20px 0;
  }
  .violation-item {
    margin-bottom: 20px;
    padding-bottom: 20px;
  }
  .violation-item:last-child {
    margin-bottom: 0;
    padding-bottom: 0;
    border-bottom: none;
  }
  .button {
    display: inline-block;
    padding: 12px 22px;
    background-color: #007bff;
    color: #ffffff !important;
    text-decoration: none;
    border-radius: 5px;
    margin-top: 20px;
    font-size: 14px;
  }
  .footer {
    margin-top: 30px;
    font-size: 12px;
    color: #888888;
    text-align: center;
    border-top: 1px solid #eeeeee;
    padding-top: 15px;
  }
  .violation-count {
    background: #e8f4f8;
    padding: 10px;
    border-radius: 4px;
    margin-bottom: 15px;
    color: #0066cc;
    font-weight: bold;
  }
</style>
</head>
<body>
  <div class="container">
    <h2>⚠ Price Violation Notice</h2>

    <div class="content">
      <p>Hello z,,</p>

      <p>
        We have identified za pricing violationz pricing violations for zone of your listed productszyour listed productsz, 
        associated with the brand <strong>z|</strong>.
      </p>

      <div class="violations-box">
        <div class="violation-count">
          Total Violations: z
        </div>
        z
      </div>

      <p>
        As per the agreed pricing policy, selling below the MSP is not permitted. 
        We request you to review and correct the pricing at the earliest.
      </p>

      <p style="margin-top: 20px;">
        If you believe zthis notificationzany of these notificationsz: was sent in error, 
        please contact us at <strong>support@company.comu  </strong>.
      </p>

      <p>
        We appreciate your prompt attention to this matter.
      </p>

      <p>
        Regards,<br>
        <strong>Your Company</strong>
      </p>
    </div>

    <div class="footer">
      &copy; 2026 Your Company. All rights reserved.<br>
      This is an automated notification — please do not reply directly to this email.
    </div>

  </div>
</body>
</html>EmailMessagezPrice Violation Notice -  r   r{   SubjectFromToz+This email requires an HTML capable client.html)subtype)r   	SMTP_HOST	SMTP_PORT	SMTP_USER	SMTP_PASS	SMTP_FROMRuntimeError	enumeraterw   rd   re   r   r   r   r   r   r   r   email.messager   r   set_contentadd_alternativesmtplibSMTPehlostarttlsloginstripreplacesend_message)r,   r9   hostport	smtp_user	smtp_passsenderviolation_items_htmlidxr   msp_formattedscraped_price_formattedprice_differenceprice_difference_formattedr   r   msgr   smtps                      r-   r   r     sJ   DD""I""IFt6:;; #J2 'Y /4MVMdMdU9+B+B%CC$HjoT]TkTk5/%	8O8O2PPqr(8'=" %KKN% PS T]SiSiRj kV WdUd eV WnUn oV WqUq rS T]SkSkSuSuSwRx y"
 #,-- 1	7 !  	'TMZ }  69_5I1RUV`RaQbbuOvww|  _b  cm  _n  rs  _s  ~[  yO  }P P++1+<+<*= >
 !_- .		 	 03:!/C+Ief g&&/&H3H%I JEvDp +
.C0Z0ARUV`RaefRf;lxByzC	NCKCI OOABf-	dD	! T				JJy()*;*;C*D*J*J*LM#  s   /BJ<<K)r2   
product_idstatus_filterc                 K   t        t              }|r"|j                  t        j                  |k(        }|r"|j                  t        j                  |k(        }|r"|j                  t        j
                  |k(        }|j                  t        j                  j                               }| j                  |       d{   }|j                         j                         }t        j                         }|j                  }d|_        g d}	|j!                  |	       |D ]  }
|j!                  |
j"                  |
j$                  xs d|
j&                  xs d|
j(                  |
j*                  t-        |
j.                        |
j0                  rt-        |
j0                        nd|
j2                  rt-        |
j2                        nd|
j4                  rt-        |
j4                        nd|
j
                  |
j6                  |
j                  j9                         g        t;               }|j=                  |       |j?                         S 7 w)z Export scraping results to XLSX.NScraping Resultsr~   zProduct ReferenceBarcoder|   z
Vendor URLr   r   r   zPercentage DifferenceStatusSource Typez
Scraped Atr   r   ) r   r   r#   r2   r   compliance_statusr^   
scraped_atra   r"   r7   r8   r   r   r   r   r   r   r   barcodevendor_name
vendor_urlrw   rd   re   r   percentage_differencesource_typer   r   r   r   )r*   r2   r   r   rm   r3   r   r   r   r   scraping_resultr   s               r-   export_scraping_resultsr   B  s     .!Dzz.22i?@zz.33zABzz.::mKL==22779:D::d##F>>!D				B	B!BHG IIg 
		((((.B##)r''&&/%%&4C4Q4QE///0W\7F7W7WE/223]b<K<a<aE/778gl--''&&002
 	  YFGGFO??S $s   B=I?I	 F
I)r2   r   c               F  K   t        t        t              j                  t              }|r"|j	                  t        j
                  |k(        }|r	 | j                  |       d{   }|j                         }t        t              }|r"|j	                  t        j
                  |k(        }|r"|j	                  t        j                  |k(        }| j                  |       d{   }|j                         j                         }t        j                         }	|	j                  }
d|
_        g d}|
j                  |       |D ]   \  }}|
j                  |j                   |j"                  |j$                  |j&                  xs d|j(                  xs dt+        |j,                        t+        |j.                        t+        |j,                  |j.                  z
        |j0                  |j2                  |j4                  j7                         |j8                  r|j8                  j7                         nd|j:                  g        |	j=                  d      }g d}|j                  |       |D ]  }|j                  |j$                  |j(                  xs d|j>                  xs d|j@                  |jB                  t+        |j,                        |j.                  rt+        |j.                        nd|jD                  rt+        |jD                        nd|jF                  rt+        |jF                        nd|jH                  |j2                  |jJ                  j7                         g        tM               }|	jO                  |       |jQ                         S 7 67 w)zAExport combined report with both violations and scraping results.Nr{   )r|   r}   r~   r   r   r   r   r   zConfirmation Countr   r   zLast Confirmedr   r   r   r   r   ))r   r   r   r   r#   r2   r"   r8   r   r   r7   r   r   r   r   r   r   r   r   r   r   rw   rd   re   confirmation_countr   r   r   last_confirmed_dater   create_sheetr   r   r   r   r   r   r   r   r   r   )r*   r2   r   violation_stmtviolation_resultr9   scraping_stmtr   scraping_resultsr   ws_violationsviolation_headersr   r,   
ws_resultsresult_headerssrr   s                     r-   export_combined_reportr     s     Iv.33F;N'--i.A.AY.NOZZ77!%%'J >*M%++N,D,D	,QR%++N,E,E,STJJ}55O&..0446				B IIM&M *+' 	6KK""$$*""(b)-- )))*)--)"9"99:((!!$$..09B9V9VI))335\^MM
 	$ !34JN n% OOOO!rJJ"NNMM"&&M')'7'7E"""#U*,*=*=E"%%&5/1/G/GE"**+U  NNMM##%
 	  YFGGFO??u 8 6s&   A#N!%N&A?N!%N&J6N!N!c                 K   t        t        t              j                  t              j	                  t        j
                  j                  t        |                  }| j                  |       d{   }|j                         }|st        t        j                  d      i }|D ]#  \  }}|j
                  |vs|||j
                  <   % d}t        |      dk(  r&t        |j                               d   j                  }|t         t"        t        |      |j                         D 	cg c]  }	|	j$                   c}	t        |      dkD  rddS ddS 7 c c}	w w)aX  
    Get pre-fill data for the notification modal.
    
    Returns:
    - recipient_email: Auto-fetched from vendor (None if multiple vendors)
    - default_subject: Default subject template
    - default_message_body: Default message template
    - violations_count: Number of violations
    - vendor_names: List of vendor names involved
    Nr   r   rY   r   zMultiple vendors detected)recipient_emaildefault_subjectdefault_message_bodyviolations_countvendor_namesnote)r   r   r   r   r#   r0   r   r   r"   r8   r   r   r1   r   valuesr   DEFAULT_NOTIFICATION_SUBJECTDEFAULT_NOTIFICATION_MESSAGEr   )
r*   r   rm   r3   r   vendors_setr   r,   r   vs
             r-   get_violations_prefill_datar    s:      )V$))&177	8H8HmI\8]^D::d##FjjlG(A(AJmnn K$ ,	699K'%+K		",
 O
;1{1134Q7== +7 <L)4););)=>A>/2;/?!/C+  JN % $. ?s,   A1E3E4A	E>A.E,E?EEc	           	         dt        |      d}	|rdt        |      dnd}
|||	|
||||d}| }|j                         D ]   \  }}|j                  |t        |            }" |S )a5  
    Substitute template variables in message body.
    Handles both plain text and HTML content.
    
    Supported variables:
    - {{VENDOR_NAME}}
    - {{PRODUCT_NAME}}
    - {{MSP}}
    - {{SCRAPED_PRICE}}
    - {{PRODUCT_URL}}
    - {{VIOLATION_DATE}}
    - {{COMPANY_NAME}}
    - {{SUPPORT_EMAIL}}
    u   ₹r   r   )z{{VENDOR_NAME}}z{{PRODUCT_NAME}}z{{MSP}}z{{SCRAPED_PRICE}}z{{PRODUCT_URL}}z{{VIOLATION_DATE}}z{{COMPANY_NAME}}z{{SUPPORT_EMAIL}})rw   r?   r   r&   )message_bodyr   r   rd   re   product_urlr   company_namesupport_emailr   r   substitutionsr3   placeholderrH   s                  r-   _substitute_template_variablesr
    s    4 %*S)*MBOE-$8#=>UZ '( 4&,(*	M F+113 9USZ89 M    c               p  K   ddl m } ddlm} ddl}t        j                  d       t        j                  dt        |              t        j                  d|        t        j                  d|r|dd	 nd
        t        j                  d|rt        |      nd d       |r;t        j                  d|dd         t        j                  dd|v xr d|v         |r|j                         dk(  rt        t        j                  d      |r|j                         dk(  rt        t        j                  d      t        t        t              j                  t              j!                  t        j"                  j%                  t        |                  }| j'                  |       d{   }	|	j)                         }
|
st        t        j*                  d      t        j                  d|        |r#t-        |t.              r.|j                         dk(  rt        t        j                  d      t        j                  d|        t0        j2                  }t0        j4                  }t0        j6                  }t0        j8                  }t0        j:                  }|r|r|st=        d      g }|
D ]  \  }}|j?                  |        |
r|
d   d   nd}tA        ||r|jB                  nddddddtE        t0        dd      |xs d 	      }d!| d"| d#} |       }||d$<   ||d%<   ||d&<   |jG                  |d'd()       t        j                  d*|        t        j                  d+|        t        j                  d,t        |       d-       t        j                  d.t        |              t        j                  d/|dd0  d1       t        j                  d2|jI                                 t        j                  d3tK        |jM                                       	 |jO                  ||      5 }|jQ                          |jS                          |jQ                          |r@|r>|jU                  |j                         |jW                  d4d      j                                |jY                  |       ddd       t        j                  d5| d6t        |       d7       |D ]  }|j[                         |_.         | j_                          d{    y7 q# 1 sw Y   fxY w7 # |j`                  $ rA}t        jc                  d8t/        |              t        t        jd                  d9      d}~w|jf                  $ rM}t        jc                  d:t/        |              t        t        jd                  d;t/        |             d}~wth        $ rM}t        jc                  d<t/        |              t        t        jd                  d=t/        |             d}~ww xY ww)>aH  
    Send custom violation notification email to specified recipient.
    
    If recipient_email is not provided, automatically fetches vendor email.
    If multiple violations from different vendors without recipient_email, raises error.
    
    The message_body supports template variables:
    - {{VENDOR_NAME}}, {{PRODUCT_NAME}}, {{MSP}}, {{SCRAPED_PRICE}}
    - {{PRODUCT_URL}}, {{VIOLATION_DATE}}, {{COMPANY_NAME}}, {{SUPPORT_EMAIL}}
    
    If multiple violations are provided, each violation will be sent with
    individually substituted variables for that violation.
    r   r   r   Nz:[send_custom_violation_notification] Function called with:z  - violation_ids: z  - recipient_email: z  - subject: rt   EMPTYz  - message_body length: z charsz,  - message_body preview (first 300 chars): i,  z%  - message_body contains HTML tags: <>r   zMessage body cannot be emptyr   zSubject cannot be emptyr   z([send_custom] recipient_email received: zgrecipient_email is required. Please provide the email address where you want to send this notification.z%[send_custom] Email will be sent to: r   rY   r   COMPANY_NAMEYour Companyr   )	r  r   r   rd   re   r  r   r  r  z<<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>zT</title>
<style>
  body { font-family: Arial, sans-serif; }
</style>
</head>
<body>
z
</body>
</html>r   r   r   r   zutf-8)r   charsetz[Email Debug] Sending to: z[Email Debug] Subject: z[Email Debug] HTML length: z charactersz [Email Debug] Total violations: z$[Email Debug] Message body preview:    z...z#[Email Debug] Content-Type header: z[Email Debug] Full headers: r   u    ✓ Custom notification sent to r   z violation(s)u    ✗ SMTP Authentication failed: z@SMTP Authentication failed. Please check your email credentials.u   ✗ SMTP Error: zSMTP error: u(   ✗ Failed to send custom notification: zFailed to send notification: )5r   r   r   r   rC   rD   r   r   r   r   r   HTTP_400_BAD_REQUESTr   r   r   r   r#   r0   r   r"   r8   r1   
isinstancer&   r   r   r   r   r   r   r   r   r
  r   rA   r   get_content_typedictr?   r   r   r   r   r   r   r   r   r(   SMTPAuthenticationErrorrQ   rR   SMTPExceptionrO   )r*   r   r   subjectr  r   r   r   rm   r3   r   r   r   r   r   r   violations_listr   r,   first_vendorcombined_html_bodyhtml_contentr   r   rS   s                            r-   "send_custom_violation_notificationr  J  s    * "* KKLN
KK%d=&9%:;<
KK''89:
KK-gFGH
KK+C,=ST+UU[\]B<PTQTCUBVWX;C<<O<gTW[gTg;hij <--/25331
 	

 gmmo+33,
 	
 )V$))&177	8H8HmI\8]^D::d##FjjlG(A(AJmnn
KK:?:KLM z/3?ODYDYD[_aDa33|
 	

 KK77HIJ DD""I""IFt6:;; O$ *	6y)* %,71:a=L7!)5L%%8X~~F8#8
 	y    L .CC	NCKCI OOL&'OB KK,_,=>?
KK)'34
KK-c,.?-@LM
KK233G2HIJ
KK6|DS7I6J#NO
KK5c6J6J6L5MNO
KK.tCIIK/@.ABC"
\\$% 	#IIKMMOIIKY

9??,i.?.?R.H.N.N.PQc"	# 	66GuSQ`MaLbbopq ) 	?I-5__->I*	? iikM $p	# 	# 	** 
7Ax@A==U
 	
    
'Ax01==!#a&*
 	
  
?AxHI==23q6(;
 	

sw   F1X63T$4I7X6,T5 >BT'AT5 T3T5 #X6'T0,T5 5X3<V  X3AWX3&AX..X33X6)r*   r   r   r&   r   r&   r   r&   r    Optional[str]r!   boolreturnr   )r*   r   r2   r
   r"  r   )r*   r   r2   r
   r"  ztuple[Vendor, List[Violation]])
r*   r   r2   r
   rE   zdict[str, Any]r;   r   r"  r   )r*   r   r2   r
   r"  None)rY      NN)r*   r   ri   rv   rj   rv   rk   z
str | Nonerl   r   r"  zTuple[List[Vendor], int])r*   r   r,   r   r"  zTuple[int, float])r*   r   ry   zOptional[List[UUID]]r"  bytes)r*   r   r   Iterable[UUID]r"  r#  )r,   r   r9   zList[Violation]r"  r#  )
r*   r   r2   Optional[UUID]r   Optional[int]r   r   r"  r%  )r*   r   r2   r'  r   r(  r"  r%  )r*   r   r   r&  r"  r  )r  r   )r  r&   r   r&   r   r&   rd   rw   re   rw   r  r&   r   r&   r  r&   r  r&   r"  r&   )r*   r   r   r&  r   r   r  r&   r  r&   r"  r#  )8
__future__r   rN   ior   typingr   r   r   r   r	   uuidr
   r   fastapir   r   
sqlalchemyr   r   r   r   sqlalchemy.ext.asyncior   sqlalchemy.sqlr   app.models.vendorr   rM   r   rL   r   app.core.configr   	getLogger__name__rC   r   VIOLATION_DETAILS_TEMPLATEr   EMAIL_TEMPLATEr.   r4   r:   rJ   rT   rr   rx   r   r   r   r   r   r  r
  r   r  r-   <module>r8     s]   "   7 7   ) 3 3 / ! $ * 5 $			8	$  Y #   .nb" qu (
<  ) ) 
)  )  	) 
 )  ) X	. (,.. %. 	.b:~F !% $#';; ; 	;
 !; ;B !% $	ii i 	i
 iX** "* 
	*j '.... . 
	.
 . . . . . 	.bk
k
 "k
 #	k

 k
 k
 
k
r  