
    _ܪis                        d dl Z d dlZd dlmZ d dlZd dlZd dlZd dlZd dlm	Z	 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Zdd
lmZmZmZmZmZmZmZmZmZmZ d dlZd dlZd dl Z d dl!Z!d dl"m#Z# d dl$Z$d dl%Z&d dl'm(Z( d dl)m*Z* d dl+m,Z, d dl-m.Z. d dl/m0Z0 d dl1Z1d dl2Z2d dl3m4Z4 d dl5Z5ejl                  jo                  ejl                  jo                  e8            Z9ejl                  ju                  e9ddd      Z; e<e;      5 Z= e5j|                  e=      Z?ddd       d9dZ@ ej                  eB      ZCd:dZDd;dZE ej                  eB      ZCd ZFd ZGd<dZHd ZId ZJd ZK G d d      ZLd eMd!eMfd"ZNd# ZOd$ ZPd%eMd&eMd!eQfd'ZRd( ZSd) ZTd* ZUd+ ZV ej                  eB      ZCd, ZWd- ZX G d. d/      ZYd0 ZZd1 Z[d2 Z\d;d3Z]d4 Z^d5 Z_d6 Z` G d7 d8      Zay# 1 sw Y   xY w)=    N)quote)TfidfVectorizer)cosine_similarity)User)EmailMessage)settings   )
UserClient)
r
   TblCandidateResumeTblJobDescription
EmailQueueWhatsAppQueueSMSQueueAssignJdTblMatchedProfiles
PublicLink	TblClient)etree)timezone)	timedelta)validate_email)ValidationError)SMTPRecipientsRefused)defaultdictmastersmail_configszemail_templates.jsonc                     t         d   |    }|d   }|d   }|r*t         d   d   }|j                  dd      }d| | d	}||fS t         d   d
   }|dz   |z   }||fS )Nemailstitlebodyfooterhtml
z<br>z&<html><body style='font-family:Arial'>z</body></html>text

)EMAIL_CONFIGreplace)keyis_htmltemplatesubjectr    r!   s         (/var/www/auto_recruiter/masters/utils.pyget_email_templater-   '   s    H%c*HwGFDh'/||D&)7vfX^T
 D= h'/f}v%D=    c                 F   t        j                         j                  d d }t        d       t        d|       t        d|        t        d|       t        d|       t        j
                  j                  || ||      }t        d|j                         t        d	       |S )
N   z,========== GENERATING PUBLIC LINK ==========zGenerated Token:
Resume ID:JD ID:z
Link Type:)token	resume_idjd_id	link_typezSaved Object ID:z+===========================================)uuiduuid4hexprintr   objectscreateid)r4   r5   r6   r3   objs        r,   generate_public_linkr?   :   s    JJLSb!E	
89	
e$	,	"	(E	,	"



#
#	 $ C 

cff%	
78Lr.   c                 <   t        |t              r|g}g }|D ]  }	 t        |       |j                  |       ! g }|r7t        |t              r|g}|D ]  }		 t        |	       |j                  |	       ! |st
        j                  d       y	 t        | ||||      }|rd|_	        |j                  d       t
        j                  d| d	|        y
# t        $ r t
        j                  d|        Y w xY w# t        $ r t
        j                  d|	        Y w xY w# t        $ r`}
t
        j                  d|
        t        j                  j                  dj!                  |      | ||ddt        |
             Y d }
~
yd }
~
wt"        $ r}
t%        j&                         t)        d      z   }t
        j                  d| d| d|
        t        j                  j                  dj!                  |      | ||dd|t        |
             Y d }
~
yd }
~
wt        $ re}
t+        d| d|
        t
        j                  d| d|
        t        j                  j                  || ||ddt        |
             Y d }
~
yd }
~
wt"        $ r}
t%        j&                         t)        d      z   }t+        d| d| d|
        t
        j                  d| d| d|
        t        j                  j                  || ||dd|t        |
             Y d }
~
yd }
~
ww xY w)Nz&[EMAIL-SEND] INVALID_TO_SKIPPED email=z#[EMAIL-SEND] INVALID_CC_SKIPPED cc=z&[EMAIL-SEND] No valid recipient emailsFr+   r    
from_emailtoccr"   fail_silentlyz[EMAIL-SEND] status=SENT to=z cc=Tz:[EMAIL-SEND] status=FAILED reason=INVALID_RECIPIENT error=,FAILEDr   )to_emailr+   r    rB   statusretry_count
last_error   minutesz[EMAIL-SEND] status=QUEUED to=z next_retry_at= error=PENDINGr	   )rI   r+   r    rB   rJ   rK   next_retry_atrL   z7[EMAIL-SEND] status=FAILED reason=INVALID_RECIPIENT to=)
isinstancestrr   appendr   loggerwarningerrorr   content_subtypesendinfor   r   r;   r<   join	Exceptionr   nowr   r:   )r+   r    rI   rB   	cc_emailsr)   valid_toemailvalid_ccrD   e
next_retrys               r,   send_email_safere   O   sY   (C :H M	M5!OOE"M Hi%"I 	KBKr"#	K =>a!
 $*E!


'*8*D
C	
 K  	MNNCE7KL	M # K!DRDIJK6 ! HL	
 	!!XXh'!1v 	" 	
  \\^i&::
,XJoj\QXYZX[\	
 	!!XXh'!$1v 	" 		
   GzQXYZX[\]EhZwWXVYZ	
 	!!!1v 	" 	
  \\^i&::
,XJ 7'Ls4	
 	,XJ 7'Ls4	

 	!!!$1v 	" 		
 -sd   CC<AD# !C98C9<!D D #	L,AFLA>HL"AJLBLLc                 f   dt         j                   d}d| d|ddid|D cg c]  }dt        |      d	 c}d
gdd}dt         j                   dd}	 t	        j
                  |||d      }|j                  dk(  rt        j                  d|         yt        |j                        c c}w # t        $ ru}t        j                         t        d      z   }	t        j                  j!                  | ||dd|	t        |             t        j#                  d|  d|        Y d }~yd }~ww xY w)Nz!https://graph.facebook.com/v19.0/z	/messageswhatsappr*   codeenr    r$   )typer$   )rj   
parameters)namelanguage
components)messaging_productrC   rj   r*   Bearer application/json)AuthorizationContent-Type
   jsonheaderstimeout   z[WHATSAPP] SENT to=TrM   rN   rQ   r	   )to_phonetemplate_nametemplate_paramsrJ   rK   rR   rL   z[WHATSAPP] QUEUED to=rP   F)r   WHATSAPP_PHONE_NUMBER_IDrT   WHATSAPP_ACCESS_TOKENrequestspoststatus_coderV   r[   r]   r$   r   r^   r   r   r;   r<   rW   )
rz   r{   r|   urlppayloadrw   resrc   rd   s
             r,   send_whatsapp_safer      sN   -h.O.O-PPY
ZC (! # "1# "(Q8#
	G( #8#A#A"BC*G
mmCgwK??c!KK-hZ89!!+#.  \\^i&::
$$'+$1v 	% 	
 	.xjsCDs%   B-A B2 B2 2	D0;A+D++D0c                    t        |       j                  dd      j                  dd      j                  dd      } | j                  d      sd| z   } d|d| d}t        j                  d	d
}	 t        j                  t        j                  ||d      }|j                  dk(  r<|j                         }|j                  d      du rt        j                  d|         yt        |j                        # t        $ rt}t        j                          t#        d      z   }t$        j&                  j)                  | |dd|t        |             t        j+                  d|  d|        Y d }~yd }~ww xY w)N+  -91qenglish)routemessagerm   numbersrq   )authorizationrs   rt   ru   ry   returnTz[SMS] SENT to=rM   rN   rQ   r	   )rz   r   rJ   rK   rR   rL   z[SMS] QUEUED to=rP   F)rT   r'   
startswithr   FAST2SMS_API_KEYr   r   FAST2SMS_URLr   rv   getrV   r[   r]   r$   r   r^   r   r   r;   r<   rW   )rz   r   r   rw   r   response_datarc   rd   s           r,   send_sms_safer     s`    	H	b		b		b		  t$(? 	G "22*G
mm!!	
 ??c!HHJM  *d2nXJ78!! \\^i&::
$1v 	  	
 	)(71#>?s    -A1C4 C4 4	E1=A*E,,E1c                     t         j                  t         j                  z   dj                  fdt	        |       D              }|S )Nr   c              3   H   K   | ]  }t        j                          y wN)randomchoice).0_
characterss     r,   	<genexpr>z$generate_password.<locals>.<genexpr>D  s     L6==4Ls   ")stringascii_lettersdigitsr\   range)lengthpasswordr   s     @r,   generate_passwordr   ?  s6    ))FMM9
 77LeFmLLr.   c                 @    t         j                   d| j                   S )Nz/apply/)r   CAREERapply_token_urljds    r,   generate_apply_linkr   H  s    oogb&8&8%9::r.   c                     t        |d      }d| }d|  dd}t        j                  ||      }|j                  dk(  S )	Nr   )safez%https://api.linkedin.com/v2/ugcPosts/rp   z2.0.0)rr   zX-Restli-Protocol-Version)rw      )r   r   deleter   )access_tokenpost_urnencoded_urnr   rw   r   s         r,   delete_linkedin_postr   K  sQ    r*K1+
?C #<.1%,G
 //#w
/C??c!!r.   c                     d}dd| j                    d}| j                  |j                  ||j                  |j                  d}ddt        |j                        z   dS )	Nz"https://api.foundit.in/v1/job/postrq   zBasic )rs   rr   )username	job_titlejob_descriptionlocationexperience_minsuccessFI_)rJ   foundit_job_id)portal_passwordportal_usernamer   job_locationyears_of_experiencerT   pk)configr   r$   r   rw   r   s         r,   post_to_founditr   W  sj    
.C +!&"8"8!9:G **\\OO00G  53ruu:3EFFr.   c                   $    e Zd Zd Zd Zd Zd Zy)
LlmPromptsc                     d|  dS )Na  
            Role:
            Act as an Expert HR Data Parser and Resume Analyst.
            Input Data:
            I will provide you with the raw text from an EMAIL BODY containing a candidate's resume or profile. The text may include email headers, signatures, forwarding history, and conversational text (e.g., "Please find attached...").
            Your Task:
            Noise Filtering: actively ignore email metad ata, "Sent from my iPhone" footers, legal disclaimers, and conversational introductions. Isolate the actual candidate profile data.
            Semantic Analysis:
            Standardization: transfer the specific to given JSON format.
            Format: Output the data strictly into the JSON format defined below.
            Rules for Extraction:
            Name: Identify the candidate's name, not the recruiter's or sender's name.
            Age : Calculate the age from the date of birth, blank if date for birth is not specified
            Gender : Gender of the candidate either Male or FeMale, blank if not gende is not available 	
            Employment type : Current Job type like Contract or Employee or Part Time or Freelancer, leave blank if not available 
            Dates: Ensure dates are formatted consistently (e.g., "Month Year" or "Year").
            Title: Identify from the resume. if resume doesn't have the title, create a suitable title for the resume.
            Primary Skills: more experience skills
            Responsibility Summary: summary of all the skills, work experience responsibilities and project experience.
            Domain Skills: Industry or Buisiness Related skills
            Missing Data: If a specific field is not found, return "Not Specified" (do not use null or empty strings).
            Output Format:
            Return ONLY a single valid JSON object. Do not include any conversational text.
            ```json
            {
                "personal_information": {
                    "first_name": "String",
                    "last_name" : "String",
                    "full_name": "String",
                    "email": "String",
                    "mobile": "String",
                    "linkedin_url": "String",
                    "portfolio_url": "String",
                    "location": "String",
					"age": "String",
					"gender": "String",
					"notice_period": "String",
					"empoyment_type"
                },
                "title": "String",
                "total_exp": "String",
                "salary" : "String",
                "professional_summary": "String",
                "responsibility_summary": "String',
                "primary_skills": ["String"],
                "skills": {
                    "technical_skills": ["String"],
                    "soft_skills": ["String"],
                    "tools_and_frameworks": ["String"]
                },
                "domain_skills": ["String"],
                "work_experience": [
                    {
                        "job_title": "String",
                        "company": "String",
                        "location": "String",
                        "start_date": "String",
                        "end_date": "String",
                        "is_current": Boolean,
                        "responsibilities": "String"
                    }
                ],
                "education": [
                    {
                        "degree": "String",
                        "institution": "String",
                        "location": "String",
                        "graduation_year": "String"
                    }
                ],
                "projects": [
                    {
                        "project_name": "String",
                        "description": "String",
                        "technologies_used": ["String"]
                    }
                ],
                "certifications": [
                    {
                        "name": "String",
                        "issuer": "String",
                        "year": "String"
                    }
                ],
                "languages": ["String"]
            }
            ```
            Input Email Body:	
            	
         )resume_texts    r,   resume_extraction_promptz#LlmPrompts.resume_extraction_promptl  s"    Xp M 	qY Y	r.   c                     d|  d}|S )NaQ  
            Role:
            Act as an Expert Technical Recruiter and Data Parsing AI.
            Input Data:
            I will provide you with the raw text from an EMAIL BODY or PDF or Word, which containing an  unstructured Job Description (JD).
            Your Task:
            Analyze: Read the text and identify key job details. Ignore email metadata (signatures, "Sent from my iPhone", greetings, and thread headers).
            Semantic Extraction & Tuning:
            Interpret Meaning: If the email says, "looking for a rockstar in Python," interpret this as "Expert proficiency in Python" under skills.
            Standardize: Expand only universal recruitment abbreviations (e.g., "wfh" -> "Remote"). Strictly preserve Client Acronyms, Project Codes, and Proper Nouns exactly as written (e.g., keep "LTA", "JPMC", "DBS" as is; do not expand them).
            Categorize: Semantically distinguish between what is "Required" (Must have) vs. "Preferred" (Nice to have/Bonus).
            Refine: Clean up the grammar and tone of the extracted text to be professional and suitable for a formal JD.
            Audit Transformation: Track every specific change made, including which input headers were mapped to which output keys.
            Format: Output the data strictly into the specific JSON format defined below.
            Rules for Extraction:
            If a field is not mentioned in the email, return "Not Specified".
            jd_date: Extract the date from the email text if present, otherwise use "Current".
            job_title : Retain the given title in the JD
            ai_title : Tuned and Generated Title from the JD
            job_type: type of Job in the JD example Contract or Employee or etc..
            job_id: reference for the JD or JD identifier
            duration : Duration of the Job requirement in months, if not specified use 24+ months
            about_company: If not explicitly stated, try to infer the company name/domain from the context, or leave as "Not Specified".
            no_of_open_positions: If not explicitly stated, give default value as 1
            primary_skills: highly important skills required for the JD
            secondary_skills: technical skills exclude the primary skills
            domain_requirements: must specified as domain skills in the JD
            Specific Instruction for "changes" field:
            You must generate a semicolon-separated string listing THREE types of changes:
            MAPPING: Which input section was mapped to which JSON key (e.g., "Mapped 'Key Responsibilities' to 'responsibilities'").
            CORRECTION: Content fixes (e.g., "Corrected '58 years' to '5-8 Years'").
            INFERENCE: Data derived from context (e.g., "Inferred 'LTA' is the Domain/Client").
            Output Format:
            Return ONLY a single valid JSON object. Do not include any conversational text.
            ```json
            {
            "ai_title" : "String",
            "job_title" : "String",
            "job_type" : "String",
            "job_id" : "String",
            "about_company"  : "String",
            "no_of_open_positions" : "String",
            "job_summary"  : "String",
            "responsibilities" : "String",
            "domain_requirements" : "String",
            "certification_requirements" : "String",
            "security_clearance_requirements" : "String",
            "years_of_experience" : "String",
            "duration" : "String",
            "onsite_job" : "String",
            "job_location" : "String",
            "salary_range" : "String",
            "required_qualifications" : "String",
            "preferred_qualifications" : "String",
            "working_hours" : "String",
            "benefits" : "String",
            "requirement_priority" : "String",
            "search_pattern" : {
                "job_title": "String",
                "location": "String",
                "education": ["String"],
                "primary_skills": ["String"],
                "secondary_skills": ["String"],
                "soft_skills": ["String"],
                "tools_and_frameworks": ["String"],
                "salary_range": "String",
                "keywords": ["String"],
                "domain_requirements": ["String"]
            },
            "changes": "String",
            }
            ```

            Input Email Body:
            r   r   )final_body_textjd_generate_prompts     r,   jd_extraction_promptzLlmPrompts.jd_extraction_prompt  s)    J"T  	UKX "!r.   c                     d|  dS )Na  
            Role:
            Act as an Expert Technical Recruiter and Data Parsing AI.
            Input Data:
            I will provide you with the JSON text, which containing list of structured Job Description (JD).
            Your Task:
            Analyze: Read each JD in the JSON and generate the search patterns in specific JSON structure
            Format: Output the data strictly into the specific JSON format defined below.
            Rules for Extraction:
            jd_id : Retain the given jd_id in the JD
            job_title : Retain the given title in the JD
            primary_skills: highly important skills required for the JD
            secondary_skills: technical skills exclude the primary skills
            domain_requirements: must specified as domain skills in the JD
            Output Format:
            Return list of valid JSON object. Do not include any conversational text.
            ```json
            [
                {
                    "jd_id" : "String",
                    "search_pattern" : {
                        "job_title": "String",
                        "location": "String",
                        "education": ["String"],
                        "primary_skills": ["String"],
                        "secondary_skills": ["String"],
                        "soft_skills": ["String"],
                        "tools_and_frameworks": ["String"],
                        "salary_range": "String",
                        "keywords": ["String"],
                        "domain_requirements": ["String"]
                    }
                }
            ]
            ```
            
            Input JSON:
            r   r   )r   s    r,   jd_search_pattern_promptz#LlmPrompts.jd_search_pattern_prompt  s     %J  	K& &	r.   c                     d|  dS )Nz`
            Generate a structured JSON report  for this interview.
            Interview Logs: a  

            Output Format:
            ``` json 
            {
                "Candidate_Strengths" : "String[]",
                "Candidate_Weaknesses": "String[]",
                "Score": {
                    "communication": 'String", 
                    "attitude": "String", 
                    "Technical": "String"
                },
                "Final_Hiring_Recommendation": "String (Excellent/Very Good/Good/Fair/Poor)"
            }
            ```
        r   )interview_datas    r,   l0_interview_summary_promptz&LlmPrompts.l0_interview_summary_prompt@  s    +, -	 	r.   N)__name__
__module____qualname__r   r   r   r   r   r.   r,   r   r   k  s    ZxM"^'Rr.   r   r   r   c                     | sy| j                         j                         } t        j                  dd|       } t        j                  dd|       } t        j                  dd|       j                         } | S )Nr   z[_\-\/]+r   z[^a-z0-9 ]+\s+)striplowerresub)r   s    r,   normalize_resume_titler   T  sb    KKM!E FF;U+EFF>2u-EFF63&,,.ELr.   c                 b   t        j                  d|       }t        j                  d|      }t        j                  d||      }g }g }|j	                         D ]3  \  }}}	}
}dj                  |||	       }dj                  ||
|       }|dk(  rI|j                  t        j                  |             |j                  t        j                  |             |dk(  rQ|j                  dt        j                  |       d       |j                  dt        j                  |       d       |d	k(  r*|j                  dt        j                  |       d       |d
k(  s|j                  dt        j                  |       d       6 dj                  |      dj                  |      fS )z
    Returns (old_html, new_html)
    old_html: highlights removed/changed words (blue)
    new_html: highlights added/changed words (green)
    z\w+|\s+|[^\w\s]Nr   equalr'   zD<span style='background:#dbeafe;border-radius:4px;padding:1px 3px;'>z</span>zD<span style='background:#dcfce7;border-radius:4px;padding:1px 3px;'>r   insert)	r   findalldifflibSequenceMatcherget_opcodesr\   rU   r"   escape)old_linenew_line
old_tokens
new_tokenssm
old_result
new_resulttagi1i2j1j2old_partnew_parts                 r,   highlight_inline_diffr   f  s    .9J.9J		 	 z:	>BJJ!~~/ ERR77:b,-77:b,-'>dkk(34dkk(34I deiepepqyezd{  |C  D  E deiepepqyezd{  |C  D  EH_ deiepepqyezd{  |C  D  EH_ deiepepqyezd{  |C  D  E!E$ 77:
 333r.   c                 F   dd| j                    d| j                   d| j                   g}| j                  r|j	                  d| j                          t        | j                        }|j                  d| d| j                   g       dj                  |      |fS )	Nu   🚀 We are Hiring!u   🔹 Role: u   📍 Location: u   🧠 Experience: u   💰 Salary: u   👉 Apply here: u   🆔 Ref ID: r%   )	r   r   r   salary_rangerU   r   jd_display_idextendr\   )r   lines	apply_urls      r,   build_facebook_post_textr     s    
bll^$
"//*+
B2234	E 
}R__$567#B$4$45I	LL
I;'
(()* 
 ;;uy((r.   title1title2c                     | r|syt        d      }|j                  | |g      }t        |dd |dd       d   d   }t        |dz  d      S )Ng        r   )
stop_wordsr   r	      d   )r   fit_transformr   round)r   r  
vectorizertfidf_matrix
similaritys        r,   calculate_title_similarityr    s_     I6J++VV,<=L"<!#4l1Q6GHKANJc!1%%r.   c                     | r|sy | j                         } |j                         }t        |       dk  st        |      dk  ry t        | |      S )N   )r   lenr  )ai_titler   s     r,   safe_similarityr    sI    9~~H!I
8}qC	NQ.%h	::r.   c                     t         j                  j                  dt        j                  j                  |       j	                  dd            j                         S )z@
    Returns Delivery Managers assigned to the given client
    zDelivery Manager (DM)clientuser_idTflat)groups__nameid__in)r   r;   filterr
   values_listdistinctr  s    r,   get_client_delivery_managersr    sV     <<,!!(( ) 

+id+
+	  
 hjr.   c                    	 | D ]  }|j                   st        dd      \  }}|j                  |      }|j                  |j                  xs d d|j                  xs d j                         |||      }t        ||j                         |j                   t        j                  d        y	 y # t        $ r}t        d
|       Y d }~yd }~ww xY w)Nai_title_mismatch_notificationFr)   )r
  r   r   )dm_namer   r   r  r+   r    rI   rB   r)   TEmail unexpected error:)ra   r-   format
first_name	last_namer   re   r   EMAIL_HOST_USERr]   r:   )	dm_usersr   r  r
  r   dmr+   r    rc   s	            r,   notify_dm_low_matchr)    s     	B88./OMGT nn% % G ;;==.B/q1C0DEKKM+#!	  D ZZ\#33 3	4  '+s   B/B4 2B4 4	C=CCc                    | j                   r| j                  syt        | j                   | j                        }|y|| _        | j	                  dg       |dk\  ry| j
                  syt        | j
                        }|j                         st        d| j
                         yt        || j                  | j                   || j                         y)z=
    jd_obj must already be saved (jd_display_id exists)
    Nai_title_similarity)update_fieldsP   z&No Delivery Managers found for client:)r  r   r  r+  save	client_idr  existsr:   r)  r   )jd_objr
  r'  s      r,   $check_ai_title_similarity_and_notifyr2    s    
 ??&"2"2 J
 !+F
KK45K6R+F,<,<=H??68H8HIr.   c                    t        dd      \  }}|j                  |||d      }	 t        ||j                         | gt        j
                  d       y# t        $ r"}t        j                  d|        Y d }~yd }~ww xY w)	Nuser_created_accountFr  z,https://auto-recruiter.itconnectus.com/login)	full_namer   r   	login_urlr!  TzEmail sending failed: )	r-   r#  re   r   r   r&  r]   rV   rX   )ra   r   r   r5  r+   r    rc   s          r,   send_user_created_mailr7  	  s    &'=uMMGT;;@	  DW//	
  -aS12s   -A 	B A;;B c                    	 t        dd      \  }}|j                  |      }|j                  ||      }t        ||j                         | gt        j
                  d       y# t        $ r}t        d|       Y d }~yd }~ww xY w)	Nresume_acknowledgementFr  r   )candidate_namer   r!  Tr"  )r-   r#  re   r   r   r&  r]   r:   )rI   r;  r   r+   r    rc   s         r,   send_resume_ack_emailr<  "  s    *+CUS..9.5{{)  

 	Z//	
  '+s   A"A% %	B.A??Bc                   d    e Zd Zd Zd Zd Zd Zed        Zed        Z	de
de
fd	Zed
        Zy)DocumentTextExtractionc                    g }ddi}t        j                  |       5 }|j                         D ]  }|j                  d      st	        j
                  |j                  |            }|j                  d|      D ]S  }|j                  s|j                  j                         s+|j                  |j                  j                                U  	 d d d        dj                  |      S # 1 sw Y   xY w)Nw<http://schemas.openxmlformats.org/wordprocessingml/2006/mainzword/header.//w:t
namespacesr#   )zipfileZipFilenamelistr   r   
fromstringreadxpathr$   r   rU   r\   )	file_pathrw   rD  zrl   rootts          r,   extract_headers_xmlz*DocumentTextExtraction.extract_headers_xml=  s    YZ
__Y' 	;1

 ;??=1 ++AFF4L9D!ZZZZH ;66afflln#NN166<<>:;;	; yy!!	; 	;s   %C+AC+	C+$-C++C4c                 t   	 t        j                  |       5 }|j                  d      }d d d        t        j                        }ddi}g }g }|j                  d|      D ]V  }|j                  j                  d      rz|j                  d|      }|D ]*  }	|	j                  s|j                  |	j                         , |sddj                  |      j                         }
|
r|j                  |
       g }|j                  j                  d	      s|j                  d
|      D ]  }g }|j                  d|      D ]O  }|j                  d|      }dj                  d |D              j                         }|s?|j                  |       Q |sm|j                  dj                  |              Y dj                  |      }|j                         st        d      |j                         S # 1 sw Y   xY w# t        $ r*}t        d|        t        dt        |             d }~ww xY w)Nzword/document.xmlr@  rA  z.//w:body/*rC  z}prB  r   z}tblz.//w:trz.//w:tcc              3   N   K   | ]  }|j                   s|j                     y wr   )r$   r   rN  s     r,   r   z:DocumentTextExtraction.extract_docx_xml.<locals>.<genexpr>j  s     0VAqvv0Vs   %%z | r#   z(No readable text found in Word document.z&Failed to extract Word Document text: z+Failed to extract text from Word document: )rE  rF  rI  r   rH  rJ  r   endswithr$   rU   r\   r   r]   r:   rT   )rK  rL  xml_contentrM  rD  r   current_lineelementtextsrN  linerow	row_cellscell
cell_texts
cell_valuedoc_textrc   s                     r,   extract_docx_xmlz'DocumentTextExtraction.extract_docx_xmlK  s   /	T+ :qff%89: ##K0D]^JEL::m
:K @;;''-#MM(zMJE" 866(//78 $!ww|4::<!LL.')[[))&1&}}Y:}N @$&	$'IIiJI$O =D)-H)TJ)+0V0V)V)\)\)^J) ) 0 0 <= %!LLI)>?@@8 yy'H>># JKK>>##U: :X  	T:1#>?I#a&RSS	TsO   H G7A;H %H AH A)H  H A H 7H<H 	H7%H22H7c           
         	 t        j                         5 }t        j                  dddd| d|gt        j                  t        j                  d       t
        j                  j                  t
        j                  j                  |             d   }t
        j                  j                  ||d	z         }t
        j                  j                  |      st        d
      t        |ddd      5 }|j                         j                         }d d d        st        d      |cd d d        S # 1 sw Y   !xY w# 1 sw Y   y xY w# t        $ r}t        d|       d }~ww xY w)Nlibreofficez
--headlessz--convert-toztxt:Textz--outdirT)stdoutstderrcheckr   z.txtzLibreOffice conversion failedrzutf-8ignore)encodingerrorszEmpty LibreOffice outputzLibreOffice extraction failed: )tempfileTemporaryDirectory
subprocessrunDEVNULLospathsplitextbasenamer\   r0  r]   openrI  r   )rK  tmpdirbasetxt_filefr$   rc   s          r,   extract_with_libreofficez/DocumentTextExtraction.extract_with_libreoffice}  s:   	C,,. &%$&
!"F &--%-- ww''(8(8(CDQG77<<v>ww~~h/#$CDD(C'(K ,q668>>+D, #$>??5 (, ,) 8  	C=aSABB	CsM   E CD9.D-D9#	E -D6	2D99E>E E 	E!EE!c                     	 t        j                  |       5  	 d d d        y# 1 sw Y   y xY w# t         j                  $ r Y yw xY w)NTF)rE  rF  
BadZipFile)rK  s    r,   is_docxzDocumentTextExtraction.is_docx  sB    	+   !! 		s#   . ". +. . AAc                 6   t         j                  |       rG	 t         j                  |       }t         j                  |       }dj	                  d ||fD              }|S 	 t         j                  |       S # t
        $ r Y !w xY w# t
        $ r Y t        d      w xY w)Nr#   c              3   &   K   | ]	  }|s|  y wr   r   rR  s     r,   r   z6DocumentTextExtraction.process_word.<locals>.<genexpr>  s      '1A's   z)Unable to extract text from Word document)r>  rz  r_  rO  r\   r]   rw  )rK  	body_textheader_text
final_texts       r,   process_wordz#DocumentTextExtraction.process_word  s    !)))4	2CCIN	4HHS!YY ' +Y7' 
 "!	)BB9MM	  
  	CDD	s$   AA3 B 3	A?>A?	BBc                 p   	 t        j                  |       5 }g }|j                  D ]&  }|j                         }|s|j	                  |       ( 	 d d d        st        d      dj                  |      S # 1 sw Y   'xY w# t
        $ r*}t        d|        t        dt        |             d }~ww xY w)NzNo readable text found in PDF.r#   zFailed to extract PDF text: z!Failed to extract text from PDF: )	
pdfplumberrr  pagesextract_textrU   r]   r\   r:   rT   )rK  pdfpdf_textpager$   rc   s         r,   process_pdfz"DocumentTextExtraction.process_pdf  s    	J+ .sII .D,,.D -	..  @AA99X&&. .  	J045?AxHII	Js3   B $A6A6%B 6A?;B 	B5%B00B5headerr   c                     t        j                  dd| j                  dd      j                         j	                               S )Nr   r   r   )r   r   r'   r   r   )r  s    r,   normalize_excel_headerz-DocumentTextExtraction.normalize_excel_header  s9    vvNN3$**,224
 	
r.   c                    |dv rt        j                  |       }n|dv r	 t        j                  |       }i dg ddg dd	g d
dddgdddgdddgdddgdg ddddgdddgddd gd!g d"d#d$d%gd&d'gd(d(d)gd*d+d,gd-d.d/gd0d1gg d2d3}j                  D ci c]  }t
        j                  |      | }}i }|j                         D ]/  \  }}|D ]%  }	t
        j                  |	      }
|
|v s||
   ||<    / 1 g }|j                         D ]y  \  }}i }|j                         D ]N  }|j                  |      }|r4t        j                  ||         rt        ||         j                         nd4||<   P |j                  |       { |S # t        $ r t        j                  | d      }Y w xY wc c}w )5N)z.xlsxz.xls)z.csvlatin1)rg  r   )z	job titlejobtitledesignationr   job_type)zjob typejobtyperj   r   )zyears of experience
experiencezrequired experienceabout_companyzabout companyzcomapany aboutjob_summaryzjob summarysummaryresponsibilitieszroles & responsibilitiesdomain_requirementszdomain requirementsdomainrequirementscertification_requirements)zcertification requirementszcertifications requirementscertificationscertificationzrequired certificationzrequired certificationssecurity_clearance_requirementszsecurity clearance requirementszclearance requirements
onsite_jobz
onsite jobonsiter   zjob locationr   required_qualifications)zrequired qualificationsqualificationszqualification requiredpreferred_qualificationszpreferred qualificationszqualification preferredworking_hourszworking hoursbenefitsbenefitsearch_patternzsearch patternpatternrequirement_priorityzrequirement prioritypriorityzsalary rangesalary)zopen positionszrequired positionsznumber of positions)r   no_of_open_positionsr   )pd
read_excelread_csvUnicodeDecodeErrorcolumnsr>  r  itemsiterrowskeysr   notnarT   r   rU   )rK  	extensiondfheader_name_mapcolexcel_headersheader_lookup	key_value
variationsvariantnormalized_variantnormalized_rowsr   rY  normalized_rowexcel_columns                   r,   process_excel_or_csvz+DocumentTextExtraction.process_excel_or_csv  s   ))y)B("?[[+
J
7
 "#_
 o/?@	

 M95
 !35O P
 "$9;O#P
 )  +@
 .0QSk/l
 <2
 ^Z8
 &'n
 ')CE^(_
 o.
 Y/
  /;!
" #%;Z$H#
$ ,X6$c'
, ]_\f\fgUX/FFsKSPgg%4%:%:%< 	!Iz% %;%R%RSZ%["%6/<=O/PM),		 kkm 	3FAsN,113 	,00; $\1B(C L)*002 y) "">2	3 e & ?[[X>?2 hs   F "F< F98F9N)r   r   r   rO  r_  rw  rz  staticmethodr  r  rT   r  r  r   r.   r,   r>  r>  <  sm    "0TdCB E E( J J$
s 
s 
 8 8r.   r>  c                    	 t         j                  j                  d      j                  |       }t        j                  j                  |      }|j
                  }|st        d       y|j                  }|st        d       y|j                  j                   d|j                  j                   j                         }|j                  }|j                   d|j                   }	t        d	d
      \  }
}|
j!                  ||	      }
t#        |j                  |j                  d      }t$        j&                   d| d}t        d|       t#        |j                  |j                  d      }t$        j&                   d| d}|r7t#        |j                  |j                  d      }t$        j(                   d| }n7t#        |j                  |j                  d      }t$        j&                   d| d}t        d|       t*        j                  j-                  |      j                  d      }|D cg c]:  }|j.                  r,|j.                  j
                  r|j.                  j
                  < }}g }|j0                  r:t3        |j0                        }|D cg c]  }|j
                  r|j
                   }}t5        t7        ||z               }||v r|j9                  |       |j!                  ||j:                  ||	||      }t        d       t=        |
|j                         ||t$        j>                  d
       tA        |d||g       t        d       y
c c}w c c}w # t         jB                  $ r t        d       Y yt        jB                  $ r t        d       Y ytD        $ r}t        d |       Y d }~yd }~ww xY w)!Ncandidate_idr4   r5   z2Shortlist email skipped: Candidate email not foundFzHShortlist Mobile number skipped: Candidate Mobile number email not foundr   r   shortlisted_candidate_htmlTr  )r   tracking_tokenjobz/job/l0//zGenerated Job URL:	shortlist/shortlist-details/client_submission_consentz"/client_submission_consent/?token=zGenerated Shortlist URL:r   user)r;  resume_sourcer   r  form_urljd_urlz-----mail sendingr+   r    rI   r_   rB   r)   r9  rz   r{   r|   z-----mail sent successfullyz'Shortlist email error: Resume not foundz#Shortlist email error: JD not foundz!Shortlist email unexpected error:)#r   r;   select_relatedr   r   ra   r:   mobile_numberr  r$  r%  r   r   r4   r5   r-   r#  r?   r   r   	INTERVIEWr   r  r  r/  r  listsetremover  re   r&  r   DoesNotExistr]   )r4   r5   consent_requiredresumer   rI   	to_mobiler;  r   r  r+   r    token_careerr  r3   r  assigned_usersarecruiter_emails	dm_emailsdelivery_managersr(  r_   rc   s                           r,   send_shortlist_emailr    s   z#++::>JNN O 
 &&***7<<FG((	\]"//::;1V=P=P=Z=Z<[\bbdLL	",,-Qrxxj9*+GQUV..) ! 

 ,F,<,<bhhNOO$H\N!<"F+$V%5%5rxxMoo&&9%B()9)9288E`aE",,--OPUwWH()9)9288[QE"//**=eWAFH((3!))00 1 

.
  	
 #1
vv!&&,, FFLL
 

 	<< <R\\ J#488 I 
 -	9:;	y X&{{) ..)  
 	!"//	
 	2	
, 	+,{
n ** 78)) 34 115sP   A(M) +M) F0M) 5?M4)M) M$<B"M) 
M) )O	O(O0OOc                  z   t         j                  j                  dt        j                         d      } | D ]  }t        |j                  |j                  |j                        }|rd|_	        n;|xj                  dz  c_
        t        j                         t        d      z   |_        |j                           y )NrQ   r  )rJ   next_retry_at__lteretry_count__ltSENTr	   rM   rN   )r   r;   r  r   r^   r   rz   r{   r|   rJ   rK   r   rR   r.  )msgsmsgr   s      r,   retry_pending_whatsappr    s      ''#<<> ( D  $LL
 CJOOq O (11E EC
r.   c                    t         j                  j                  | j                        j	                         }t
        j                  j                  | j                        j	                         }|r|sy|j                  }t        j                  j                  |      j	                         }|sy|j                  }| j                  j                  d      }|j                   d|j                   }|j                   d|j                   }t        j                    d| }	t#        d	d
      \  }
}|
j%                  |j&                        }
|j%                  ||	      }t)        |
|j+                         |j,                  t        j.                  d
       t1        |j2                  d||j&                  || j4                  g       y
)Nr  r  Fr   %d %b %Y %I:%M %pr   r   r  $candidate_interest_confirmation_htmlTr  r:  )r;  r  r!  interview_schedule_candidater  )r   r;   r  job_idfirstr   r4   r  r   r  interview_datetimestrftimer$  r%  r5   r   r   r-   r#  r   re   r   ra   r&  r   r  interview_link)matched_profiler   r  candidate_profileassigned	recruiterinterview_dtr;  r  r  r+   r    s               r,   send_thanks_notificationsr    s   		"	"	)	)$$ 
* 
eg   ''..!++ / eg  V++&&"&-335HI"55>>?RSL)445Q7H7R7R6STN(()288*5N//""5n5EFH&.MGT
 nn,,  G ;;%  D
 ZZ\"((++ &448..		
 r.   c                     	 t        d|        | j                  d      \  }}t        d|       t        d|       t        j                  j	                  ||      j                         }|st        d       yt        d|j                         ||_        d	|_        t        j                         |_        |j                          t        d
       t        |       y# t        $ r)}t        d       t        j                           Y d }~yd }~ww xY w)NzProcessing token:r   r1   r2   )r4   r  u   ❌ No matched profile foundFzMatched found:
Interestedu   ✅ Status updatedTu   ❌ ERROR OCCURRED)r:   splitr   r;   r  r  r=   accepted_messagerJ   r   r^   accepted_atr.  r  r]   	traceback	print_exc)r  
reply_text
interestedr4   r5   matchedrc   s          r,   process_shortlist_replyr    s    #!>2)//4	5lI&h$,,33 4 
 %' 	
 01

+#- %&lln"#!'* "#s   A4C 7A#C 	D$DDc                    t        t        j                               }|j                  d      }|j                  d      }|t	        d      z   j                  d      }t        | j                  | j                  d      }	t        j                   d|	 }d| d| d| d	| d
| d| d| dt        j                   d| d}
|
S )Nz%Y%m%dT%H%M%SZ   rN   l0_interview/interview_welcome/?token=zXBEGIN:VCALENDAR
VERSION:2.0
PRODID:-//AutoRecruiter//EN
METHOD:REQUEST
BEGIN:VEVENT
UID:z	
DTSTAMP:z	
DTSTART:z
DTEND:z
SUMMARY:Interview - z*
DESCRIPTION:Online Interview\nJoin here: z

LOCATION:z!
ORGANIZER;CN=ITConnectUS:MAILTO:z(
ATTENDEE;CN=Candidate;RSVP=TRUE:MAILTO:z5
STATUS:CONFIRMED
SEQUENCE:0
END:VEVENT
END:VCALENDAR)rT   r7   r8   r  r   r?   r4   r  r   r  r&  )r  candidate_emailr  r  jd_titleuiddtstampdtstartdtendr3   ics_contents              r,   generate_ics_filer     s   
djjl
C##$45G##$45GIb11;;<LME !!E !**++EeWMN	
 e ) )  'j )55C4D E"# $++3+C+C*D E22A1B C	 * r.   c                    	 t         j                  j                  | j                        }t        j                  j                  | j
                        }|j                  }| j                  }t        | j
                  | j                  d      }t        j                   d| }t        j                  j                  |      j                  d      j                         }|r8|j                  r,|j                  j                   r|j                  j                   nd }|j"                   d|j$                   }	|j'                  d      }
t)        d	d
      \  }}|j+                  |j,                        }|j+                  |	|j,                  |
|      }t/        | |j                   |||j,                        }t1        ||j3                         t        j4                  |j                   g|r|gng       }d|_        |j9                  d|d       |j;                  d       y
# t<        $ r}t?        d|       Y d }~yd }~ww xY w)Nr  r  r  r	  r   r  r   r  interview_scheduled_calendarTr  r:  )r;  r   r  r  rA   r"   zinterview_invite.icsztext/calendar; method=REQUEST)filenamecontentmimetypeFrE   zICS email error:) r   r;   r   r  r   r4   r  r  r?   r   r  r   r  r  r  r  ra   r$  r%  r  r-   r#  r   r  r   r   r&  rY   attachrZ   r]   r:   )r  r   r  	candidater  r3   r  r  recruiter_emailr;  formatted_dtr+   r    r  ra   rc   s                   r,   send_interview_calendar_inviter  G  s   >&&**1G1G*H#++///:S:S/T''	&99$_%>%>@V@VXfg !!""<UGD 	 ##**b*1@@HNNP19hmmPXP]P]PcPc(----im%00193F3F2GH#,,-@A*+ISWX..ll ! 
 {{)ll+)	  
 (OOLL
 // $3 
 !'+4 	 	
 	


'  !$s   HH! !	I *H;;I c                    t        t              }| D ]   }||j                     j                  |       " |j	                         D ]  \  }}|r|j
                  sg }t               }|D ]  }|j                  }|j                  }|j                  d|j                   d|j                   d|r|j                  nd dt        j                  |j                        j                  d       d	       |st!        |      }	|	D ]*  }
|
j
                  s|j#                  |
j
                         ,  t%        |      }t'        dd	
      \  }}|j)                  |      }|j)                  |j*                  xs |j,                  dj/                  |      d      }t1        ||j3                         |j
                  t        |      t4        j6                  d	        y )Nz#
                JD Reference ID : z#
                Job Title       : z#
                Client          : zN/Az#
                Assigned Time   : z%d-%m-%Y %I:%M %pz
                jd_assignment_notificationFr  )jd_countr   z6https://auto-recruiter.itconnectus.com/job_description)recruiter_namejd_listr6  r  )r   r  r  rU   r  ra   r  r   r/  r   r   client_namer   	localtime
created_atr  r  addr  r-   r#  r$  r   r\   re   r   r   r&  )assignmentsgroupedassignr  recruiter_assignmentsjd_linesr_   r   
client_objr  r(  r  r+   r    s                 r,   notify_recruiter_multiple_jdsr+    s   $G ,##F+, -4MMO 0
(	(	E	+ 	0FBJOO##%#3#3"4 5##%<<. 1#=G:#9#9U"S T##+#5#5f6G6G#H#Q#QRe#f"g h	 $@$L!+ 0Bxx!bhh/0	0& ,-*+GQVW.. ! 
 {{$//E93E3EGGH%N  
 	__9o//	
S0
r.   c                       e Zd Zd Zd Zy)DBAuthFiltersc                 "   | r| j                   j                  ddg      j                         s| j                  r,t	        t
        j                  j                  dd            }|S t	        | j                  j                  dd            }|S g S )N	RecruiterImplementer Super Adminname__inr/  Tr  )	groupsr  r0  is_superuserr  r   r;   r  client_mappings)r  
client_idss     r,   get_client_by_auth_userz%DBAuthFilters.get_client_by_auth_user  s    {{!!K9R+S!T[[]aearar!%%11+D1I
 	 "((44[t4L
  Ir.   c                 d   | r,| j                   j                  dg      j                         r<t        t        j
                  j                  |       j                  dd            }|S | j                   j                  dg      j                         s| j                  r,t        t        j
                  j                  dd            }|S t        | j                  j                  d	d            }t        t        j
                  j                  |
      j                  dd            }|S g S )Nr/  r1  )r  r   Tr  r0  r5   r/  )client_id__in)
r3  r  r0  r  r   r;   r  r4  r   r5  )r  jd_idsr6  s      r,   get_jd_by_auth_userz!DBAuthFilters.get_jd_by_auth_user  s   {{!!K=!9@@B$$+++6BB4dBS$ M ##.G-H#IPPRVZVgVg%--99'9M M "((44[t4L
 %--V*V5 [t[4 MIr.   N)r   r   r   r7  r;  r   r.   r,   r-  r-    s     r.   r-  )F)NNcareer)NF)   )br   r   urllib.parser   r   r   r   r"   sklearn.feature_extraction.textr   sklearn.metrics.pairwiser   django.contrib.auth.modelsr   django.core.mailr   django.confr   modelsr
   rn  r   r   r   r   r   r   r   r   r   loggingrk  ri  rE  lxmlr   r  pandasr  django.utilsr   datetimer   django.core.validatorsr   django.core.exceptionsr   smtplibr   r   r7   collectionsr   rv   ro  dirname__file__BASE_DIRr\   TEMPLATE_FILErr  rv  loadr&   r-   	getLoggerr   rV   r?   re   r   r   r   r   r   r   r   rT   r   r   r   floatr  r  r  r)  r2  r7  r<  r>  r  r  r  r  r  r  r+  r-  r   r.   r,   <module>rU     s      	   ; 6 + )    	 `  `  `        !  1 2 )   # 77??277??845Xy.BXY	-  A499Q<L " 
		8	$*~@ 
		8	$3j7r;
"G(g gR# # $"4H)(&s &C &E &
;	@%N 
		8	$24Q Qf{zZ>@%N%N?B7
r( ({,   s   GG