U
    €wÃjÏ¤  ã                   @   sî  d dl Z d dlZd dlZd dlmZmZ d dlmZ d dlm	Z	 d dl
mZ d dlmZ d dlmZ d dlmZ d d	lmZ d d
lmZ d dlmZ ddlmZ d dlmZ d dlmZ d dlmZmZ 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! d dlm"Z"mZ ddlm#Z#m$Z$m%Z%m&Z&m'Z'm(Z(m)Z)m*Z*m+Z+ d dl,m-Z-m.Z.m/Z/ e-dƒZ0ddej1fdd„Z2ej3fdd„Z4dd„ Z5dd„ Z6G dd„ deƒZ7ddej1fd d„Z2ej3dfd!d„Z4d"d#„ Z8d$d%„ Z9d&d'd(d)d*hZ:d+d,d-hZ;d.d/d0hZ<d1Z=d2Z>d3Z?e  @d4¡ZAe  @d5¡ZBd6d7„ ZCd8d9„ ZDd:d;„ ZEd<d=„ ZFG d>d„ deƒZ7G d?d@„ d@eƒZGG dAdB„ dBeƒZHG dCdD„ dDeƒZIG dEdF„ dFeƒZJG dGdH„ dHeƒZKG dIdJ„ dJeƒZLG dKdL„ dLeƒZMejNdMdN„ ƒZOG dOdP„ dPeƒZPdS )Qé    N)ÚauthenticateÚlogin)ÚUser)ÚContentFile)Útransaction)ÚQ©Ústatus)ÚAPIView©ÚResponse)ÚIsAuthenticated)ÚRefreshTokené   )ÚProfiles)Úmake_password)ÚObjectDoesNotExist)ÚMultiPartParserÚ
FormParserÚ
JSONParser)ÚAllowAnyr   )	ÚPropertyÚPropertyImageÚPropertyVideoÚPropertyDocumentÚBuyerEnquiryÚSellerEnquiryÚSellerEnquiryPhotoÚSellerEnquiryVideoÚSellerEnquiryDocument)ÚDecimalÚInvalidOperationÚROUND_HALF_UPz0.01c                 C   s.   t |ddœd dœ|rd|ini d| i–|d�S )NÚsuccess©ÚcodeÚresponse)r	   ÚerrorÚmessageÚdatar   r   ©r)   r(   r%   © r+   ú//var/www/html/VPFITNESS/school/./myapp/views.pyÚok1   s    þ üûr-   c                 C   s   t |ddœd| dœ|d�S )NÚfailedr$   T)r	   r'   r(   r   r   ©r(   r%   r+   r+   r,   Úfail:   s    ýür0   c              
   C   s^   | dks| dkr t d|› d�ƒ‚ztt| ƒƒW S  tt tfk
rX   t d|› d�ƒ‚Y nX dS )zÓ
    Validate + coerce a value into a Decimal, raising a clear message on bad
    input. Goes through str() first so binary floating-point artifacts
    (e.g. 0.1 + 0.2 != 0.3) never leak into money fields.
    NÚ ú'z' is required.z' must be a valid number.)Ú
ValueErrorr    Ústrr!   Ú	TypeError)ÚvalueÚ
field_namer+   r+   r,   Ú
to_decimalB   s    r8   c                 C   s   t | ƒjttd�S )zKRound a Decimal to exactly 2 places using standard rounding (not banker's).)Úrounding)r    ÚquantizeÚ
TWO_PLACESr"   ©r6   r+   r+   r,   Úq2P   s    r=   c                   @   s   e Zd ZdZdd„ ZdS )ÚLoginAPIViewu<  
    Accepts either a username or an email in `username`, plus `password`.
    `fcm_token` (optional) is stored against the profile for push notifications â€”
    it is intentionally NOT written into `pincode`; that was a bug in the
    previous version. Adjust the field name below to match your Profile model.
    c                 C   sŒ  |j }| d¡pd ¡ }| d¡}| d¡}|r4|s@tdtjƒS t d|¡}|rŽztj	j|d�}|j
}W q’ tjk
rŠ   tdtjƒ Y S X n|}t|||d	�}	|	d kr´tdtjƒS |	jsÆtd
tjƒS t||	ƒ t |	¡}
d }d }d }zTtj	j|	jd�}|�r||_|jdgd� |j�r(| |jj¡nd }|j}|j}W n tjk
�rR   Y nX t|	j
|	j|	j
|	j|	jt|
ƒt|
j ƒ|d||dœdd�S ©NÚusernamer1   ÚpasswordÚ	fcm_tokenz)Username/email and password are required.z[^@]+@[^@]+\.[^@]+)Zemail__iexactzInvalid username or password.)r@   rA   zThis account has been disabled.©Úuser_id)Úupdate_fieldsÚloop)ÚnameÚidr@   ÚemailZisSuperZrefreshÚtokenÚprofileZcompanynameÚphoneÚrolezLogin success©r(   ©!r)   ÚgetÚstripr0   r	   ÚHTTP_400_BAD_REQUESTÚreÚmatchr   Úobjectsr@   ÚDoesNotExistZHTTP_401_UNAUTHORIZEDr   Ú	is_activeÚHTTP_403_FORBIDDENr   r   Zfor_userr   rH   rB   ÚsaveÚprofilesÚbuild_absolute_uriÚurlrL   rM   r-   rI   Úis_superuserr4   Zaccess_token©ÚselfÚrequestr)   Zusername_or_emailrA   rB   Úis_emailÚmatchedZusername_to_authÚuserrJ   Zprofile_photorL   rM   rK   r+   r+   r,   Úpost^   sb    





õôúLoginAPIView.postN)Ú__name__Ú
__module__Ú__qualname__Ú__doc__rd   r+   r+   r+   r,   r>   V   s   r>   ZSuccessc                 C   s   t |ddœd || dœ|d�S )Nr#   r$   ©r	   r'   r(   r)   r   r   r*   r+   r+   r,   r-   £   s    üûc                 C   s   t |ddœd| |dœ|d�S )Nr.   r$   Trj   r   r   )r(   r%   r)   r+   r+   r,   r0   ¬   s    üûc                 C   sV   | r
| j sdS | js| jrdS ztjj| jd�}|jdkW S  tk
rP   Y dS X dS )zšMatches the role convention used in LoginAPIView (Profiles.role).
    Adjust the role value below if your project uses a different number
    for "admin".FTrC   r   N)	Úis_authenticatedr]   Úis_staffr   rU   rP   rH   rM   Ú	Exception)rc   rK   r+   r+   r,   Úis_admin_userµ   s    
rn   c                 C   s2   |sd S z|   |j¡W S  tk
r,   Y d S X d S ©N)r[   r\   rm   )r`   Úfieldr+   r+   r,   Úbuild_file_urlÄ   s    rq   ZjpgZjpegZpngZwebpZgifZmp4ZwebmZoggZpdfÚdocZdocxé
   éÈ   é   z^\+?\d{10,13}$z^[^@\s]+@[^@\s]+\.[^@\s]+$c                 C   s   | rt  |  dd¡¡sdS d S )Nú r1   z+Enter a valid mobile number (10-13 digits).)Ú	MOBILE_RErT   Úreplacer<   r+   r+   r,   Úvalidate_mobileâ   s    ry   c                 C   s   | rt  | ¡sdS d S )NzEnter a valid email address.)ÚEMAIL_RErT   r<   r+   r+   r,   Úvalidate_email_formatè   s    r{   c              	   C   sˆ   d| j kr | j  dd¡d  ¡ nd}||krPd| j › d|› dd t|ƒ¡› d�S | jd	 }||kr„d| j › d
|d›d|› d|› d�	S dS )z;Returns an error string, or None if the file is acceptable.Ú.r   éÿÿÿÿr1   r2   z' is not a supported z format. Allowed: z, i   z' is z.1fu   MB â€” z files must be under zMB.N)rG   ÚrsplitÚlowerÚjoinÚsortedÚsize)ÚfÚallowed_extensionsZmax_mbÚlabelÚextZsize_mbr+   r+   r,   Úvalidate_uploadî   s    $$
"r‡   c                 C   sH   | sdS |   d¡ z|  ¡ }W 5 |  ¡  X | j dd¡d }t||d�S )uý   Reads an existing uploaded file and returns a ContentFile so it can
    be saved onto a different model's FileField/ImageField â€” used when a
    seller's submitted photos/videos/documents are copied onto the live
    Property listing at approval time.NÚrbú/r   r}   )rG   )ÚopenÚcloseÚreadrG   r~   r   )Z
file_fieldÚcontentrG   r+   r+   r,   Úcopy_django_fileú   s    

rŽ   c                   @   s   e Zd ZdZegZdd„ ZdS )r>   z 
    Accepts either a username or an email in `username`, plus `password`.
    `fcm_token` (optional) is stored against the profile for push notifications.
    c                 C   sŒ  |j }| d¡pd ¡ }| d¡}| d¡}|r4|s@tdtjƒS t d|¡}|rŽztj	j|d�}|j
}W q’ tjk
rŠ   tdtjƒ Y S X n|}t|||d	�}	|	d kr´tdtjƒS |	jsÆtd
tjƒS t||	ƒ t |	¡}
d }d }d }zTtj	j|	jd�}|�r||_|jdgd� |j�r(| |jj¡nd }|j}|j}W n tjk
�rR   Y nX t|	j
|	j|	j
|	j|	jt|
ƒt|
j ƒ|d||dœdd�S r?   rO   r^   r+   r+   r,   rd     sb    





õôre   N)rf   rg   rh   ri   r   Úpermission_classesrd   r+   r+   r+   r,   r>     s   c                   @   sJ   e Zd ZdZegZeeegZ	ddd„Z
dd„ Zdd„ Zd	d
„ Zdd„ ZdS )ÚPropertyAPIViewal  
    GET    /api/v1/property/        -> list (search, place_name, property_type, featured, status)
    GET    /api/v1/property/<id>/   -> single property with images/videos/documents
    POST   /api/v1/property/        -> create (admin only)
    PUT    /api/v1/property/<id>/   -> update (admin only)
    DELETE /api/v1/property/<id>/   -> delete (admin only)
    Fc                    sð   |j jdd� dd¡}|j|j|j|j|j|j|j	d k	rBt
|j	ƒnd |j|j|j|j|j| ¡ rptˆ | ¡ jƒnd dœ}|rì| |j|j|j|j‡ fdd„|D ƒ‡ fdd„|jjdd� dd¡D ƒ‡ fd	d„|jjdd� dd¡D ƒd
œ¡ |S )Nr   r   ÚorderrH   )rH   ÚtitleÚ
place_nameÚdistrictÚproperty_typeÚ	land_areaÚpriceÚprice_displayÚshort_descriptionÚis_featuredr	   Ú
created_atZcover_imagec                    s,   g | ]$}|j tˆ |jƒ|j|j|jd œ‘qS ))rH   ÚimageÚcaptionÚis_coverr‘   )rH   rq   rœ   r�   rž   r‘   )Ú.0Zim©r`   r+   r,   Ú
<listcomp>v  s   ÿz5PropertyAPIView.get_property_data.<locals>.<listcomp>c                    s,   g | ]$}|j tˆ |jƒ|j|j|jd œ‘qS ))rH   ÚvideoÚ	video_urlr’   r‘   )rH   rq   r¢   r£   r’   r‘   ©rŸ   Úvr    r+   r,   r¡   z  s   ÿc                    s(   g | ] }|j tˆ |jƒ|j|jd œ‘qS ))rH   Údocumentr’   r‘   )rH   rq   r¦   r’   r‘   ©rŸ   Údr    r+   r,   r¡   ~  s   ÿ)Úfull_addressÚmap_linkÚdescriptionÚ
updated_atÚimagesÚvideosÚ	documents)r­   ÚfilterÚorder_byrH   r’   r“   r”   r•   r–   r—   r4   r˜   r™   rš   r	   r›   Úfirstrq   rœ   Úupdater©   rª   r«   r¬   r®   r¯   )r_   r`   ÚpropÚdetailedr­   r)   r+   r    r,   Úget_property_data^  s@    ó
þ
þ
þóz!PropertyAPIView.get_property_datac                    s˜  |  d¡}|d k	rZztjj |d�}W n  tk
rD   tdtjƒ Y S X tˆjˆ |dd�ƒS ˆ j	  dd¡ 
¡ }ˆ j	  dd¡ 
¡ }ˆ j	  d	d¡ 
¡ }ˆ j	  d
d¡ 
¡ }	ˆ j	  dd¡ 
¡ }
tj ¡  dd¡}tˆ jƒ�r|
�rz|jt|
ƒd�}W n tk
�r   Y nX n|jdd�}|�rF| t|d�t|d�B t|d�B t|d�B ¡}|�rX|j|d�}|�rj|j|d�}|	dk�r€|jdd�}t‡ ‡fdd„|D ƒƒS )NrH   ©rH   úProperty not foundT©rµ   Úsearchr1   r“   r•   Úfeaturedr	   ú-created_atr   r   )Zplace_name__icontains)Zdistrict__icontains)Ztitle__icontains)Zfull_address__icontains)Zplace_name__iexact)r•   Ú1©rš   c                    s   g | ]}ˆ  ˆ |¡‘qS r+   )r¶   ©rŸ   Úp©r`   r_   r+   r,   r¡   ¬  s     z'PropertyAPIView.get.<locals>.<listcomp>)rP   r   rU   r   r0   r	   ÚHTTP_404_NOT_FOUNDr-   r¶   Úquery_paramsrQ   Úallr±   rn   rc   r°   Úintr3   r   )r_   r`   ÚargsÚkwargsrH   r´   rº   r“   r•   r»   Ústatus_paramÚ
propertiesr+   rÁ   r,   rP   …  sF    
ÿÿÿ
zPropertyAPIView.getc                 O   s¦  t |jƒstdtjƒS |j}�zD| d¡}| d¡}| d¡}|rJ|rJ|sXtdtjƒW S | d¡}|dkr²z t|ƒdkrˆtd	tjƒW W S W n& t	t
fk
r°   td
tjƒ Y W S X t|j||| d¡| d¡| d¡| d¡|| d¡pêd | d¡| d¡| d¡t| d¡ƒdk�rdndt| dd¡ƒdk�r6dndd�}	|	 ¡  t| j||	dd�dtjd�W S  tk
�r  }
 ztdt|
ƒ› �tjƒ W Y ¢S d }
~
X Y nX d S )Nz(You are not authorized to add a propertyr’   r“   r–   z,title, place_name and land_area are requiredr—   ©Nr1   r   ú Price must be a positive number.úPrice must be a valid number.r”   r©   rª   r•   r˜   r«   r™   rš   ©r½   ÚtrueÚTruer   r	   r½   )rc   r’   r“   r”   r©   rª   r•   r–   r—   r˜   r«   r™   rš   r	   Tr¹   zProperty added successfullyr/   úAn error occurred: )rn   rc   r0   r	   rX   r)   rP   rR   Úfloatr5   r3   r   r4   rY   r-   r¶   ÚHTTP_201_CREATEDrm   ÚHTTP_500_INTERNAL_SERVER_ERROR)r_   r`   rÆ   rÇ   r)   r’   r“   r–   Ú	raw_pricer´   Úer+   r+   r,   rd   ®  sN    




ò ÿzPropertyAPIView.postc           
   
   O   sr  t |jƒstdtjƒS | d¡}|j}ztjj|d�}W n  t	k
rX   tdtj
ƒ Y S X ddddd	d
ddddg
}|D ]}||krvt||| |¡ƒ qvd|k�r| d¡}	|	dkrözt|	ƒdkrÎtdtjƒW S W n$ ttfk
rô   tdtjƒ Y S X |	� pþd |_d|k�r*t| d¡ƒdk�r$dnd|_d|k�rRt| d¡ƒdk�rLdnd|_| ¡  t| j||dd�dd�S )Nz.You are not authorized to update this propertyrH   r·   r¸   r’   r“   r”   r©   rª   r•   r–   r˜   r«   r™   r—   rÊ   r   rË   rÌ   rš   rÍ   r   r	   Tr¹   zProperty updated successfullyrN   )rn   rc   r0   r	   rX   rP   r)   r   rU   r   rÂ   ÚsetattrrÑ   rR   r5   r3   r—   r4   rš   rY   r-   r¶   )
r_   r`   rÆ   rÇ   rH   r)   r´   Úfieldsrp   rÔ   r+   r+   r,   ÚputÛ  sJ    

        þ



zPropertyAPIView.putc                 O   sh   t |jƒstdtjƒS | d¡}ztjj|d�}W n  tk
rR   tdtj	ƒ Y S X | 
¡  td dd�S )Nz.You are not authorized to delete this propertyrH   r·   r¸   zProperty deleted successfullyrN   )rn   rc   r0   r	   rX   rP   r   rU   r   rÂ   Údeleter-   )r_   r`   rÆ   rÇ   rH   r´   r+   r+   r,   rÙ   ÿ  s    

zPropertyAPIView.deleteN)F)rf   rg   rh   ri   r   r�   r   r   r   Úparser_classesr¶   rP   rd   rØ   rÙ   r+   r+   r+   r,   r�   S  s   

')-$r�   c                   @   s   e Zd ZdZegZdd„ ZdS )ÚPropertyLocationAPIViewzNGET /api/v1/property-location/ -> distinct active place names, alphabetically.c                 O   sD   t jjdd�jdd�jdd�jddd�}tt|ƒd	d
„ d�}t|ƒS )Nr   r   T)Zplace_name__isnullr1   )r“   r“   )Úflatc                 S   s   |   ¡ S ro   )r   )Úsr+   r+   r,   Ú<lambda>  ó    z-PropertyLocationAPIView.get.<locals>.<lambda>)Úkey)r   rU   r°   ÚexcludeÚvalues_listr�   Úsetr-   )r_   r`   rÆ   rÇ   ÚnamesZunique_sortedr+   r+   r,   rP     s    ÿÿ þÿzPropertyLocationAPIView.getN©rf   rg   rh   ri   r   r�   rP   r+   r+   r+   r,   rÛ     s   rÛ   c                   @   s   e Zd ZdZegZdd„ ZdS )ÚDashboardSummaryAPIViewzNGET /api/v1/dashboard-summary/ -> counts for the admin dashboard (admin only).c              
   O   sŒ   t |jƒstdtjƒS tj ¡ tjjdd� ¡ tjjdd� ¡ t	j ¡ t	jjdd� ¡ t
j ¡ t
jjdd� ¡ t
jjdd� ¡ dœ}t|ƒS )NúYou are not authorizedr   r   r¾   é   )Ztotal_propertiesZactive_propertiesZfeatured_propertiesZtotal_buyer_enquiriesZnew_buyer_enquiriesZtotal_seller_enquiriesZnew_seller_enquiriesZpending_seller_approvals)rn   rc   r0   r	   rX   r   rU   Úcountr°   r   r   rá   r-   )r_   r`   rÆ   rÇ   r)   r+   r+   r,   rP     s    
ø
zDashboardSummaryAPIView.getNrå   r+   r+   r+   r,   ræ     s   ræ   c                   @   s.   e Zd ZdZegZeegZdd„ Z	dd„ Z
dS )ÚPropertyImageAPIViewu½   
    POST   /api/v1/property-image/        -> upload (form fields: property, images[] files) â€” admin only
    DELETE /api/v1/property-image/<id>/   -> remove one image â€” admin only
    c                 O   sæ   t |jƒstdtjƒS |j d¡}|j d¡}zt	j
j|d�}W n  tk
r`   tdtjƒ Y S X |srtdtjƒS |D ]&}t|ttdƒ}|rvt|tjƒ  S qvg }	|D ].}tj
j||d�}
|	 |
jt||
jƒd	œ¡ q¦t|	d
tjd�S )Nrç   Úpropertyr­   r·   r¸   zNo images providedrœ   ©rë   rœ   ©rH   rœ   zImages uploaded successfullyr/   )rn   rc   r0   r	   rX   r)   rP   ÚFILESÚgetlistr   rU   r   rÂ   rR   r‡   ÚIMAGE_EXTENSIONSÚMAX_IMAGE_MBr   ÚcreateÚappendrH   rq   rœ   r-   rÒ   )r_   r`   rÆ   rÇ   Úproperty_idÚfilesr´   rƒ   r'   ÚcreatedÚimgr+   r+   r,   rd   <  s&    
zPropertyImageAPIView.postc                 O   sd   t |jƒstdtjƒS | d¡}ztjj|d� ¡  W n  t	k
rV   tdtj
ƒ Y S X td dd�S )Nrç   rH   r·   zImage not foundzImage deleted successfullyrN   )rn   rc   r0   r	   rX   rP   r   rU   rÙ   r   rÂ   r-   ©r_   r`   rÆ   rÇ   rH   r+   r+   r,   rÙ   W  s    

zPropertyImageAPIView.deleteN©rf   rg   rh   ri   r   r�   r   r   rÚ   rd   rÙ   r+   r+   r+   r,   rê   4  s
   rê   c                   @   s.   e Zd ZdZegZeegZdd„ Z	dd„ Z
dS )ÚPropertyVideoAPIViewuÈ   
    POST   /api/v1/property-video/        -> upload (form fields: property, videos[] files, video_url) â€” admin only
    DELETE /api/v1/property-video/<id>/   -> remove one video â€” admin only
    c                 O   s  t |jƒstdtjƒS |j d¡}|j d¡}|j d¡}zt	j
j|d�}W n  tk
rl   tdtjƒ Y S X |D ]&}t|ttdƒ}	|	rrt|	tjƒ  S qrg }
|D ].}tj
j||d�}|
 |jt||jƒd	œ¡ q¢|rútj
j||d
�}|
 |j|jdœ¡ |
�stdtjƒS t|
dtjd�S )Nrç   rë   r®   r£   r·   r¸   r¢   ©rë   r¢   ©rH   r¢   )rë   r£   )rH   r£   zNo videos providedzVideos uploaded successfullyr/   )rn   rc   r0   r	   rX   r)   rP   rî   rï   r   rU   r   rÂ   r‡   ÚVIDEO_EXTENSIONSÚMAX_VIDEO_MBrR   r   rò   ró   rH   rq   r¢   r£   r-   rÒ   )r_   r`   rÆ   rÇ   rô   rõ   r£   r´   rƒ   r'   rö   r¥   r+   r+   r,   rd   k  s.    
zPropertyVideoAPIView.postc                 O   sd   t |jƒstdtjƒS | d¡}ztjj|d� ¡  W n  t	k
rV   tdtj
ƒ Y S X td dd�S )Nrç   rH   r·   zVideo not foundzVideo deleted successfullyrN   )rn   rc   r0   r	   rX   rP   r   rU   rÙ   r   rÂ   r-   rø   r+   r+   r,   rÙ   Š  s    

zPropertyVideoAPIView.deleteNrù   r+   r+   r+   r,   rú   c  s
   rú   c                   @   s.   e Zd ZdZegZeegZdd„ Z	dd„ Z
dS )ÚPropertyDocumentAPIViewuÉ   
    POST   /api/v1/property-document/        -> upload (form fields: property, documents[] files) â€” admin only
    DELETE /api/v1/property-document/<id>/   -> remove one document â€” admin only
    c                 O   sæ   t |jƒstdtjƒS |j d¡}|j d¡}zt	j
j|d�}W n  tk
r`   tdtjƒ Y S X |srtdtjƒS |D ]&}t|ttdƒ}|rvt|tjƒ  S qvg }	|D ].}tj
j||d�}
|	 |
jt||
jƒd	œ¡ q¦t|	d
tjd�S )Nrç   rë   r¯   r·   r¸   zNo documents providedr¦   ©rë   r¦   ©rH   r¦   zDocuments uploaded successfullyr/   )rn   rc   r0   r	   rX   r)   rP   rî   rï   r   rU   r   rÂ   rR   r‡   ÚDOCUMENT_EXTENSIONSÚMAX_DOCUMENT_MBr   rò   ró   rH   rq   r¦   r-   rÒ   )r_   r`   rÆ   rÇ   rô   rõ   r´   rƒ   r'   rö   r¨   r+   r+   r,   rd   ž  s&    
zPropertyDocumentAPIView.postc                 O   sd   t |jƒstdtjƒS | d¡}ztjj|d� ¡  W n  t	k
rV   tdtj
ƒ Y S X td dd�S )Nrç   rH   r·   zDocument not foundzDocument deleted successfullyrN   )rn   rc   r0   r	   rX   rP   r   rU   rÙ   r   rÂ   r-   rø   r+   r+   r,   rÙ   ¹  s    

zPropertyDocumentAPIView.deleteNrù   r+   r+   r+   r,   rÿ   –  s
   rÿ   c                   @   s>   e Zd ZdZegZdd„ Zdd„ Zdd„ Zdd	„ Z	d
d„ Z
dS )ÚBuyerEnquiryAPIViewu|  
    GET    /api/v1/buyer-enquiry/        -> list, admin only (filter by ?status=)
    GET    /api/v1/buyer-enquiry/<id>/   -> single, admin only
    POST   /api/v1/buyer-enquiry/        -> public â€” buyer submits a requirement
    PUT    /api/v1/buyer-enquiry/<id>/   -> update status / admin_notes, admin only
    DELETE /api/v1/buyer-enquiry/<id>/   -> delete, admin only
    c                 C   sF   |j |j|j|j|j|j|j|j|j|jr2|j	j
nd |j|j|jdœS )N)rH   Ú	full_nameÚmobile_numberrI   Úpreferred_locationr•   Úbudgetr(   rô   Zproperty_titler	   Úadmin_notesr›   )rH   r  r  rI   r  r•   r  r(   rô   rë   r’   r	   r	  r›   )r_   Úenquiryr+   r+   r,   Úget_dataÓ  s    ózBuyerEnquiryAPIView.get_datac                    sÐ   t |jƒstdtjƒS | d¡}|d k	rjztjj|d�}W n  tk
rZ   tdtj	ƒ Y S X t
ˆ  |¡ƒS |j dd¡ ¡ }tj ¡  d¡}|rºz|jt|ƒd�}W n tk
r¸   Y nX t
‡ fd	d
„|D ƒƒS )Nrç   rH   r·   úEnquiry not foundr	   r1   r¼   r   c                    s   g | ]}ˆ   |¡‘qS r+   ©r  ©rŸ   rÕ   ©r_   r+   r,   r¡   ø  s     z+BuyerEnquiryAPIView.get.<locals>.<listcomp>)rn   rc   r0   r	   rX   rP   r   rU   r   rÂ   r-   r  rÃ   rQ   rÄ   r±   r°   rÅ   r3   ©r_   r`   rÆ   rÇ   rH   r
  rÈ   Z	enquiriesr+   r  r,   rP   ä  s"    

zBuyerEnquiryAPIView.getc              
   O   s.  |j }zä| d¡}| d¡}|r$|s2tdtjƒW S t|ƒpFt| d¡ƒ}|rZt|tjƒW S d }| d¡ršztjj| d¡d�}W n t	k
r˜   d }Y nX t
jj||| d¡| d¡| d¡| d	¡| d
¡|d�}	t|  |	¡dtjd�W S  tk
�r( }
 ztdt|
ƒ› �tjƒ W Y ¢S d }
~
X Y nX d S )Nr  r  z(full_name and mobile_number are requiredrI   rë   r·   r  r•   r  r(   )r  r  rI   r  r•   r  r(   rë   z8Thank you! Your enquiry has been submitted successfully.r/   rÐ   )r)   rP   r0   r	   rR   ry   r{   r   rU   r   r   rò   r-   r  rÒ   rm   r4   rÓ   )r_   r`   rÆ   rÇ   r)   r  r  r'   Zproperty_objr
  rÕ   r+   r+   r,   rd   ú  s>    



ø
þzBuyerEnquiryAPIView.postc                 O   sœ   t |jƒstdtjƒS | d¡}|j}ztjj|d�}W n  t	k
rX   tdtj
ƒ Y S X d|krn| d¡|_d|kr‚| d¡|_| ¡  t|  |¡dd�S )	Nrç   rH   r·   r  r	   r	  úEnquiry updated successfullyrN   )rn   rc   r0   r	   rX   rP   r)   r   rU   r   rÂ   r	  rY   r-   r  )r_   r`   rÆ   rÇ   rH   r)   r
  r+   r+   r,   rØ      s    

zBuyerEnquiryAPIView.putc                 O   sd   t |jƒstdtjƒS | d¡}ztjj|d� ¡  W n  t	k
rV   tdtj
ƒ Y S X td dd�S ©Nrç   rH   r·   r  zEnquiry deleted successfullyrN   )rn   rc   r0   r	   rX   rP   r   rU   rÙ   r   rÂ   r-   rø   r+   r+   r,   rÙ   3  s    

zBuyerEnquiryAPIView.deleteN)rf   rg   rh   ri   r   r�   r  rP   rd   rØ   rÙ   r+   r+   r+   r,   r  É  s   &r  c                 C   s  t jj| j|j|j|j|j|jd|j|j	p.|j
|j	p<|j
p<ddd… ddd�}|j ¡ D ]"}t|jƒ}|rXtjj||d� qX|j ¡ D ]"}t|jƒ}|r†tjj||d� q†|j ¡ D ]"}t|jƒ}|r´tjj||d	� q´d
|_d|j› d�}|j�r|j› d|› � ¡ n||_| ¡  |S )zˆConverts an approved seller submission into a live Property listing,
    copying across any photos/videos/documents the seller uploaded.Nr1   i  r   r   )rc   r’   r“   r”   r•   r–   r—   r˜   r«   r™   rš   r	   rì   rû   r   rè   z$Approved and published as property #r|   Ú
)r   rU   rò   rc   Úproperty_nameÚlocationr•   r–   Úexpected_pricer«   Úadditional_infoÚphotosrÄ   rŽ   rœ   r   r®   r¢   r   r¯   r¦   r   r	   rH   r	  rQ   rY   )r`   r
  r´   ZphotoZcopiedr¢   rr   Znoter+   r+   r,   Úapprove_seller_enquiryC  s>    
ô


"r  c                   @   sH   e Zd ZdZegZeeegZ	dd„ Z
dd„ Zdd„ Zdd	„ Zd
d„ ZdS )ÚSellerEnquiryAPIViewuƒ  
    GET    /api/v1/seller-enquiry/                 -> list, admin only (filter by ?status=)
    GET    /api/v1/seller-enquiry/<id>/             -> single, admin only
    POST   /api/v1/seller-enquiry/                  -> public â€” seller submits property details
                                                        (multipart: photos[], videos[], documents[])
    PUT    /api/v1/seller-enquiry/<id>/             -> update status / admin_notes, admin only
    PUT    /api/v1/seller-enquiry/<id>/?val=approve -> approve & publish as a live Property, admin only
    DELETE /api/v1/seller-enquiry/<id>/             -> delete, admin only
    c                    s€   |j |j|j|j|j|j|j|j|j|j	|j
|j|j|j‡ fdd„|j ¡ D ƒ‡ fdd„|j ¡ D ƒ‡ fdd„|j ¡ D ƒdœS )Nc                    s    g | ]}|j tˆ |jƒd œ‘qS )rí   )rH   rq   rœ   r¿   r    r+   r,   r¡   Š  s     z1SellerEnquiryAPIView.get_data.<locals>.<listcomp>c                    s    g | ]}|j tˆ |jƒd œ‘qS )rü   )rH   rq   r¢   r¤   r    r+   r,   r¡   ‹  s     c                    s    g | ]}|j tˆ |jƒd œ‘qS )r  )rH   rq   r¦   r§   r    r+   r,   r¡   Œ  s     )rH   Úseller_namer  rI   r  r  r•   r–   r  r«   r  r	   r	  r›   r  r®   r¯   )rH   r  r  rI   r  r  r•   r–   r  r«   r  r	   r	  r›   r  rÄ   r®   r¯   )r_   r`   r
  r+   r    r,   r  z  s$    ïzSellerEnquiryAPIView.get_datac                    sÔ   t ˆ jƒstdtjƒS | d¡}|d k	rlztjj|d�}W n  tk
rZ   tdtj	ƒ Y S X t
ˆ ˆ |¡ƒS ˆ j dd¡ ¡ }tj ¡  d¡}|r¼z|jt|ƒd�}W n tk
rº   Y nX t
‡ ‡fd	d
„|D ƒƒS )Nrç   rH   r·   r  r	   r1   r¼   r   c                    s   g | ]}ˆ  ˆ |¡‘qS r+   r  r  rÁ   r+   r,   r¡   £  s     z,SellerEnquiryAPIView.get.<locals>.<listcomp>)rn   rc   r0   r	   rX   rP   r   rU   r   rÂ   r-   r  rÃ   rQ   rÄ   r±   r°   rÅ   r3   r  r+   rÁ   r,   rP   �  s"    

zSellerEnquiryAPIView.getc                 O   s  |j }�zÎ| d¡}| d¡}| d¡}| d¡}|rB|rB|rB|sPtdtjƒW S t|ƒpdt| d¡ƒ}	|	rxt|	tjƒW S |j d¡}
|j d¡}|j d	¡}|
D ](}t	|t
td
ƒ}	|	r t|	tjƒ  W S q |D ](}t	|ttdƒ}	|	rÎt|	tjƒ  W S qÎ|D ](}t	|ttdƒ}	|	rüt|	tjƒ  W S qütjj||| d¡||| d¡| d¡| d¡| d¡| d¡d�
}|
D ]}tjj||d� �qn|D ]}tjj||d� �qŠ|D ]}tjj||d� �q¦t|  ||¡dtjd�W S  tk
�r } ztdt|ƒ› �tjƒ W Y ¢S d }~X Y nX d S )Nr  r  r  r  zCseller_name, mobile_number, property_name and location are requiredrI   r  r®   r¯   rœ   r¢   r¦   r•   r–   r  r«   r  )
r  r  rI   r  r  r•   r–   r  r«   r  )Úseller_enquiryrœ   )r  r¢   )r  r¦   zBThank you! Your property details have been submitted successfully.r/   rÐ   )r)   rP   r0   r	   rR   ry   r{   rî   rï   r‡   rð   rñ   rý   rþ   r  r  r   rU   rò   r   r   r   r-   r  rÒ   rm   r4   rÓ   )r_   r`   rÆ   rÇ   r)   r  r  r  r  r'   r  r®   r¯   rƒ   r
  rÕ   r+   r+   r,   rd   ¥  sh    



ÿöþzSellerEnquiryAPIView.postc              
   O   s:  t |jƒstdtjƒS | d¡}|j}|j d¡}ztj	j|d�}W n  t
k
rd   tdtjƒ Y S X |dkrò|jdkr„tdtjƒS zt||ƒ}W n< tk
rÎ }	 ztd	t|	ƒ› �tjƒ W Y ¢S d }	~	X Y nX |  ||¡}
|j|
d
< t|
dd�S d|k�r| d¡|_d|k�r| d¡|_| ¡  t|  ||¡dd�S )Nrç   rH   Úvalr·   r  Zapproverè   z8This submission has already been approved and published.z!Could not publish this property: rô   z2Approved! The property is now live on the website.rN   r	   r	  r  )rn   rc   r0   r	   rX   rP   r)   rÃ   r   rU   r   rÂ   rR   r  rm   r4   rÓ   r  rH   r-   r	  rY   )r_   r`   rÆ   rÇ   rH   r)   r  r
  r´   rÕ   Úresultr+   r+   r,   rØ   ä  s2    


,


zSellerEnquiryAPIView.putc                 O   sd   t |jƒstdtjƒS | d¡}ztjj|d� ¡  W n  t	k
rV   tdtj
ƒ Y S X td dd�S r  )rn   rc   r0   r	   rX   rP   r   rU   rÙ   r   rÂ   r-   rø   r+   r+   r,   rÙ     s    

zSellerEnquiryAPIView.deleteN)rf   rg   rh   ri   r   r�   r   r   r   rÚ   r  rP   rd   rØ   rÙ   r+   r+   r+   r,   r  m  s   	
?!r  )QrS   ÚtimeÚbase64Údjango.contrib.authr   r   Údjango.contrib.auth.modelsr   Údjango.core.files.baser   Ú	django.dbr   Údjango.db.modelsr   Úrest_frameworkr	   Zrest_framework.viewsr
   Zrest_framework.responser   Zrest_framework.permissionsr   Zrest_framework_simplejwt.tokensr   Úmodelsr   Údjango.contrib.auth.hashersr   Údjango.core.exceptionsr   Zrest_framework.parsersr   r   r   r   r   r   r   r   r   r   r   r   r   Údecimalr    r!   r"   r;   ZHTTP_200_OKr-   rR   r0   r8   r=   r>   rn   rq   rð   rý   r  rñ   rþ   r  Úcompilerw   rz   ry   r{   r‡   rŽ   r�   rÛ   ræ   rê   rú   rÿ   r  Úatomicr  r  r+   r+   r+   r,   Ú<module>   sx   ,	M		



H ;/33z
)