o
    Z hy                    @   sT  d dl Z d dlZd dlZd dlmZ d dlmZmZmZmZm	Z	m
Z
mZmZmZmZmZmZ d dl mZ d dlmZ ddlmZmZmZmZmZmZmZmZmZmZmZm Z m!Z!m"Z" ddl#T dd	l$m%Z%m&Z& d d
l'm(Z(m)Z)m*Z*m+Z+ d dl,m-Z-m.Z. ddl/m0Z0 ddl1m2Z2 d dl3Z3d dl4Z4ddl5m6Z6m7Z7m8Z8 ddl9m9Z9 d dl:Z:d dl;m<Z< d dl=Z=d dl>Z?d dl@mAZA ddlBmCZC d dlDmEZEmFZF ddlGmHZHmIZI d dlJmKZKmLZL ddlMmNZNmOZO ddlPmQZQ e3R Se3Te4jU edeVZWe&XdZYdZZeZej[d< ej\]eZs
e^eZ eWj_dddgde+e2d d!d"d# Z`eWj_d$ddgde+e2d!d%d& ZaeWj_d'dgde+e2d!d(d) ZbeWj_d*ddgde+e2d!d+d, ZceWj_d-ddgde+e2d!d.d/ ZdeWj_d0dgde+d1d2 ZeeWj_d3dgde+e2d!d4d5 ZfeWj_d6ddgde+e2d!d7d8 ZgeWj_d9ddgde+d:d; ZheWj_d<dgde+e2d!d=d> ZieWj_d?ddgde+e2d!eFjjd@dAdBdC ZkdDdE ZldFdG ZmeW_dHe+e2dId!eFjjd@dAdJdK ZneWj_dLdgde+dMdN ZoeWj_dOdgde+dPdQ ZpeWj_dRdgde+dSdT ZqeWj_dUdgde+dVdW ZreWj_dXdgde+dYdZ ZseWj_d[dgde+d\d] ZteWj_d^dgde+d_d` ZueWj_daddgde+dbdc ZveWj_ddddgddedf ZweWj_dgdgddhdi ZxeWj_djdgde+dkdl ZyeW_dmeW_dne+eFjjd@dAdodp Zzdqdr Z{eWj_dsddgddtdu Z|eWj_dvddgddwdx Z}eW_dydzd{ Z~eW_d|d}d~ ZeW_ddd ZeWj_ddgde+dd ZeWj_ddgde+dd ZeWj_dddgde+dd ZeWj_ddgde+dd ZeWj_ddgde+dd ZeWj_ddgde+dd Zdd ZeW_de+dd ZeW_de+dd ZeW_de+dd ZeWj_ddgde+dd Zd dlmZmZ d dlZdd ZeWj_ddgde+dd ZeW_de+dd ZeW_de+dd ZeW_de+dd ZeW_de+dd ZeW_de+dd ZeW_de+dd ZeW_de+dd ZeWj_ddgde+dd ZeW_de+dd ZeW_de+ddÄ Zd dlZeWj_dddgdddƄ ZeWj_dddgdddɄ ZeWj_ddgddd̄ ZeWj_ddgdddτ ZdS )    N)datetime)	Blueprintrequestjsonify	send_fileredirecturl_forflashrender_templatemake_responsecurrent_appsessionafter_this_request)BytesIO)generate_password_hash   )GISMapServerFolderServiceLayerProfileNotificationBillingInfoSubscriptionPlanUserSettingsCompanyPlanInvoice
InvitationBlockDWGData)*)dboauth)current_user
login_userlogout_userlogin_required)urlparseurljoin)download_layer_task)role_required)get_weatherget_forecastdeg_to_cardinal)weather_icons)secure_filename)URLSafeTimedSerializer)
send_email)bcryptcache)generate_invoicecalculate_sales_tax)fuzzprocess)get_next_distribution_woparse_distribution_prefixprocess_filemaingooglez /home/ubuntu/webapp/app/uploads/UPLOAD_FOLDERz/assign_roleGETPOST)methodsadminSuper Adminc                  C   s   t j } t }tjdkrtdtj | r@|j	j
}|jj
}||jvr5|j| tj  tdd ntdd ttdS ttdS )Nr@   zrequest.formRole assigned successfully.successUser already has this role.warningmain.admin_dashboard)UserqueryallRoleAssignFormr   methodprintformvalidate_on_submituserdatarolerolesappendr!   r   commitr	   r   r   )usersrO   rQ   rS    rX   !/home/ubuntu/webapp/app/routes.pyassign_role.   s   




rZ   z/edit_user/<int:user_id>c                 C   s   t j| }t|d}| r8|jj|_|jj|_|jj|_|j	j|_
|jj|_|jj|_tj  ttdS ttd| dS )NobjrH   user_id)rI   rJ   
get_or_404EditUserFormrP   
first_namerR   	last_nameemailcompany_name
company_id	is_activerT   r!   r   rV   r   r   )r^   rQ   rO   rX   rX   rY   	edit_userD   s   







rg   z/delete_user/<int:user_id>c                 C   8   t j| }tj| tj  tdd tt	dS )NzUser deleted successfullyrE   rH   )
rI   rJ   r_   r!   r   deleterV   r	   r   r   )r^   rQ   rX   rX   rY   delete_userV   
   

rj   z	/add_planc                  C   sp   t  } tjdkr2|  r2t| jj| jj| jj| j	jd}t
j| t
j  tdd ttdS ttdS )Nr@   )namedescriptioncostusage_limitNew plan added successfullyrE   rH   )EditPlanFormr   rM   rP   r   rl   rR   rm   rn   ro   r!   r   addrV   r	   r   r   rO   planrX   rX   rY   add_plan`   s   


ru   z/edit_plan/<int:plan_id>c                 C   sV   t j| }t|d}| r$|| tj  t	dd t
tdS td||dS )Nr[   zPlan updated successfullyrE   plan_managementzedit_plan.htmlrs   )r   rJ   r_   rq   rP   populate_objr!   r   rV   r	   r   r   r
   )plan_idrt   rO   rX   rX   rY   	edit_planu   s   



ry   z!/toggle_plan_status/<int:plan_id>c                 C   sR   t j| }|j dkrd|_nd|_tj  td|j dd t	t
dS )NactiveInactiveActivezPlan status updated to .rE   main.company_dashboard)r   rJ   r_   statuslowerr!   r   rV   r	   r   r   rx   rt   rX   rX   rY   toggle_plan_status   s   
r   z /delete_company/<int:company_id>c                 C   rh   )NzCompany deleted successfully.rE   rH   )
r   rJ   r_   r!   r   ri   rV   r	   r   r   )re   companyrX   rX   rY   delete_company   rk   r   z/edit_company/<int:company_id>c                 C   s   t j| }t|d}| r=|jj|_|jj|_|jj|_|j	j|_	|j
j|_
|jj|_tj  tdd ttdS tjdkr[|j|j_|j|j_|j	|j	_|j
|j
_|j|j_td||ddS )	Nr[   zCompany updated successfully.rE   rH   r?   zedit_company.htmlzEdit Company)rO   r   title)r   rJ   r_   UpdateCompanyAddressFormrP   rl   rR   street_addresscitystatezip_codecountryr!   r   rV   r	   r   r   r   rM   r
   )re   r   companyFormrX   rX   rY   edit_company   s&   














r   z(/update_company_address/<int:company_id>c                 C   sn   t j| }tjd tdrtj| kr'tjd t	dd t
tdS t }tjd td||d	S )
NzLoading html...Company AdminzPermission garntedz2You do not have permission to update this address.error
main.indexzGot itzupdate_company_address.html)rO   r   )r   rJ   r_   r   loggerinfor#   has_rolere   r	   r   r   r   r
   )re   r   rO   rX   rX   rY   update_company_address   s   
!r   z/delete_plan/<int:plan_id>c                 C   rh   )NzPlan deleted successfullyrE   rv   )
r   rJ   r_   r!   r   ri   rV   r	   r   r   r   rX   rX   rY   delete_plan   rk   r   z/admin<   )timeoutc                  C   s  t j } tj }tj }tj }t }t }t }t	 }t
dd |D  dd |D |j_tjdkrdtjv ri| ri|jj}|jj}	|	|jvr^|j|	 tj  tdd ntdd	 ttd
S dtjv r| rt
d t|jj|jj|jj|jj|jjd}
tj |
 tj  tdd ttd
S dtjv r| rt
d t|jjd}tj | tj  tdd ttd
S t
d |j!" D ]\}}|D ]}t
d| d|  td| d| d qqt
dt#|  t$d| |||||||dd
S )Nc                 S      g | ]}|j |jfqS rX   idrl   .0r   rX   rX   rY   
<listcomp>      z#admin_dashboard.<locals>.<listcomp>c                 S   r   rX   r   r   rX   rX   rY   r     r   r@   add_rolerD   rE   rF   rG   rH   ru   zadd plan worked)rl   rm   rn   re   ro   rp   add_companyzadd company workedrl   zNew company added successfullyzwe got a problem	Error in : zCompanies added: z
admin.htmlzAdmin Panel)	rW   plansr   rO   pformcformeforminvoicesr   )%rI   rJ   rK   r   r   r   rL   rq   AddCompanyFormr   rN   re   choicesr   rM   rO   rP   rQ   rR   rS   rT   rU   r!   r   rV   r	   r   r   rl   rm   rn   ro   rr   errorsitemsstrr
   )rW   r   	companiesr   rO   r   r   r   rQ   rS   rt   r   fieldr   r   rX   rX   rY   admin_dashboard   sh   












r   c                 C   s&   t | |d}tj| tj  d S )Nr^   message)r   r!   r   rr   rV   )r^   r   notificationrX   rX   rY   create_notification6  s   r   c                 C   s   t jj| dd S )Nunreadr^   r   )r   rJ   	filter_byrK   r]   rX   rX   rY   get_unread_notifications;  s   r   z/companyr   c               	   C   s   t jjtjd } tjjtjd }tj }t	jj| j
d }tjjtj
dd }tjd }|D ]}dd |jD |_q5td	| |||||d
S )Nr   )rd   re   r   r   z
 Dashboardc                 S      g | ]}|j qS rX   r   r   rS   rX   rX   rY   r   K      z%company_dashboard.<locals>.<listcomp>zcompany.html)r   rW   r   r   notificationsr   )r   rJ   r   r#   rd   firstrI   rK   r   r   r   r   rT   
role_namesr
   )r   rW   r   r   r   r   rQ   rX   rX   rY   company_dashboard>  s   


r   z/company/usersc                  C   s4   t jstdd ttdS tjjt jd } | S )Nz(You are not associated with any company.r   indexr   )	r#   re   r	   r   r   rI   rJ   r   rK   )rW   rX   rX   rY   
view_usersQ  s
   
r   z-/generate_invoice/<int:user_id>/<int:plan_id>c                 C   s&   t | |}tdd ttd|jdS )NzInvoice generated successfully.rE   zmain.view_invoice)
invoice_id)r4   r	   r   r   r   )r^   rx   invoicerX   rX   rY   generate_invoice_route\  s   

r   z/invoice/<int:invoice_id>c                 C   s8   t j| }tdstdd ttdS td|dS )NrC   z0You do not have permission to view this invoice.r   zmain.list_invoiceszinvoice.htmlr   )	r   rJ   r_   r#   r   r	   r   r   r
   )r   r   rX   rX   rY   view_invoicer  s
   

r   z&/invoice/<int:invoice_id>/download/pdfc              
   C   s   z1t j| }td|d}d}tj|d}tj|d|d}t|}d|jd< d	|  d
|jd< |W S  t	yR } zt
jd|  t|dfW  Y d }~S d }~ww )Nzinvoice_pdf.htmlr   z/usr/bin/wkhtmltopdf)wkhtmltopdfF)configurationzapplication/pdfzContent-Typezattachment; filename=invoice_z.pdfzContent-DispositionzError generating PDF:   )r   rJ   r_   r
   pdfkitr   from_stringr   headers	Exceptionr   r   r   r   )r   r   renderedpath_wkhtmltopdfconfigpdfresponseerX   rX   rY   download_invoice_pdf{  s   
r   z(/invoice/<int:invoice_id>/download/excelc                 C   s   t j| }t|j|j|jj|j	|j
|j|j|j|j|j|jdg}t }tj|dd}|j|ddd W d    n1 sBw   Y  |d t|d|  d	d
ddS )N)z
Order DatezShipped Electronically Tor   zPlan DescriptionPriceQtyzExtended PriceSubtotalz	Sales TaxTotalzBalance Due
xlsxwriter)engineFr   )r   
sheet_namer   invoice_z.xlsxTzAapplication/vnd.openxmlformats-officedocument.spreadsheetml.sheet)download_nameas_attachmentmimetype)r   rJ   r_   pd	DataFrame
order_dateshipped_electronically_tort   rl   plan_descriptionpriceqtyextended_pricesubtotal	sales_taxtotalbalance_dueior   ExcelWriterto_excelseekr   )r   r   dfoutputwriterrX   rX   rY   download_invoice_excel  s2   


r   z/create_invoicec                  C   s  t d t tj t tj tdstdd ttdS t d tj	
d} t| d}tj	
d	}tj	
d
}tj	
d}t | tj|}t |j tj|}d }t t|j |jD ],}t d|j d|j ddd |jD   |drt d|j d|j  |} nqa|r|jnd }	|rtj|}|j}	n|j}|j}
d}|
| }|}t|j|}|| }|}t|j|r|nd ||	|j|j|
||||||dd}tj| tj   tdd ttdS )Nzwelcome to invoicingrC   z2You do not have permission to perform this action.r   r   zyou are a super adminbilling_periodz%Y-%m-%dr   rt   rQ   zChecking user:  z	, Roles: c                 S   r   rX   r   r   rX   rX   rY   r     r   z"create_invoice.<locals>.<listcomp>r   zFound company admin: r   F)re   r^   r   r   rx   r   r   r   r   r   r   r   r   is_paidzInvoice created successfully.rE   rH   )!rN   r#   ra   rc   r   r	   r   r   r   rO   getr   strptimer   rJ   r_   rl   r   r   rW   rb   rT   rI   r   rn   r5   r   r   rm   r!   r   rr   rV   )billing_period_strr   re   rx   r^   r   rt   company_adminrQ   	recipientr   r   r   r   r   r   r   r   rX   rX   rY   create_invoice  sr   





*



r   z/user/<int:user_id>/update_rolec                 C   s   t j| }tjd}|dvrtdd ttdS |j	
  tjj|d }|r<|j	| tj  tdd ntd	d ttdS )
NrS   rI   AdminInvalid role selected.r   r~   r   zUser role updated successfully.rE   zRole not found.)rI   rJ   r_   r   rO   r   r	   r   r   rT   clearRoler   r   rU   r!   r   rV   )r^   rQ   new_rolerS   rX   rX   rY   update_user_role  s   



r  z/invite_userc            
   
   C   sP  t jdkrt jd} t jd}t jd}t jd}|dvr,tdd ttd	S tjj	|d

 }|rBtdd ttd	S ttjd j|dd}ttj|| |||d}tj| tj  td|dd}td|dd}t|dd| ||||d ttjd| d| dd}	tj|	 tj  tdd ttdS ttdS )Nr@   ra   rb   rc   rS   r   r   r   zmain.invite_userrc   z2An invitation has already been sent to this email.
SECRET_KEYinvite-salt)salt)re   rc   ra   rb   rS   tokenzmain.accept_inviteT)r	  	_externalzmain.decline_invitez#You are invited to join our companyinvite_email)tosubjecttemplatera   rb   rS   invite_linkdecline_linkzInvitation sent to z for z role.r   zInvitation sent successfully.rE   r~   )r   rM   rO   r   r	   r   r   r   rJ   r   r   r0   r   r   dumpsr#   rd   r!   r   rr   rV   r1   r   r   )
ra   rb   rc   rS   existing_invitationr	  
invitationr  r  r   rX   rX   rY   invite_user  sX   


	


r  z/accept_invite/<token>c                 C   s  zt tjd j| ddd}W n   tdd ttd Y S tjj	| |d
 }|jd	kr:td
d ttdS tjdkrtjd}t|d}t|j|j|j|j|dd}tjj	|jd }|rm|j| tj| d	|_tj   tdd ttdS t!d| dS )Nr  r    r  max_age.The invitation link is invalid or has expired.r   r   r	  rc   acceptedz*This invitation has already been accepted.r@   passwordzutf-8T)ra   rb   rc   rd   password_hash
_is_activer   z)You have successfully joined the company.rE   
main.loginzset_password.html)r	  )"r0   r   r   loadsr	   r   r   r   rJ   r   first_or_404r   r   rM   rO   r   r2   r   decoderI   ra   rb   rc   re   r  rS   r   rT   rU   r!   r   rr   rV   r
   )r	  rc   r  r  r  rQ   rS   rX   rX   rY   accept_inviteO  s:   



	

r"  z/decline_invite/<token>c                 C   s   zt tjd j| ddd}W n   tdd ttd Y S tjj	| |d
 }|jd	kr:td
d ttdS d	|_tj  tdd ttdS )Nr  r  r  r  r  r   zmain.registerr  declinedz*This invitation has already been declined.z!You have declined the invitation.r   )r0   r   r   r  r	   r   r   r   rJ   r   r   r   r!   r   rV   )r	  rc   r  rX   rX   rY   decline_invitez  s   




r$  z/api/get_user_settingsc                  C   s^   t jjtjd } | r!| j| j| j| j	| j
| j| jd}t|S ddddddd	d}t|S )
Nr]   )theme_layoutpage_layoutsidebar_typelayoutdirection_layoutcolor_theme_layoutcard_layoutzlight-layoutzvertical-layoutzfull-sidebarzfull-layoutz
ltr-layoutzblue-theme-layoutzcard-without-border)r   rJ   r   r#   r   r   r%  r&  r'  r(  r)  r*  r+  r   )user_settingssettings_datarX   rX   rY   get_user_settings  s(   r.  /z/indexc               
   C   s  t jrt jnt } | jd urt jj}t|}t|}t|d d |d d< g }tddD ]2}||d | d t|d | d d |d | d d t	
|d | d	 d d d
d q-g }tdt|d dD ]2}||d | d t|d | d d |d | d d t	
|d | d	 d d d
d ql|d d }t||d d< t	
|d	 d d d
|d< td|||ddS tdddS )Nr<   tempr      listdt_txtcloudsrK   weatherzti ti-cloud)timer0  r4  icon   )dater0  r4  r7  winddegcardinalr7  z
index.htmlHome)weather_datatoday_forecastweekly_forecastr   )r   )r#   profiler   r   r+   r,   intrangerU   r.   r   lenr-   r
   )user_profiler   r>  forecast_datar?  ir@  wind_degrX   rX   rY   r     s6   


r   c                 C   s0   t tj}t ttj| }|jdv o|j|jkS )N)httphttps)r'   r   host_urlr(   schemenetloc)targetref_urltest_urlrX   rX   rY   is_safe_url  s   
rQ  z	/registerc            
   	   C   s  t jr	ttdS t } |  rt| jj| j	j| j
j| jjt| jjd}tj| tj  t|j| jj| jj| jj| jj| jj| jjd}tj| t|j| j
jd}tj| t|j| jj| jj| jj| j	jd}tj| t|jddd}tj| tj  | jjrtj t!j"d	|j d
}| jj#| |j d
|_tj  t$dd ttdS | j%& D ]\}}|D ]}	t$dt'| |j(j) d|	 d qqt*dd| dS )Nr   )ra   rb   rc   rd   r  )r^   r   r   r   phone_numberlocationcurrency)r^   notification_email)r^   business_namebusiness_addressra   rb   Freer   )r^   	plan_namesites_per_monthstatic/profile_picsz.jpgz/Congratulations, you are now a registered user!rE   r  r   r   dangerzregister.htmlRegisterr   rO   )+r#   is_authenticatedr   r   RegistrationFormrP   rI   ra   rR   rb   rc   rd   r   r  r!   r   rr   rV   r   r   r   r   r   rR  rS  rT  r   r   r   profile_pictureospathjoinr<   	root_pathsaver	   r   r   getattrlabeltextr
   )
rO   rQ   rA  r   billing_infosubscription_planpicture_pathr   r   r   rX   rX   rY   register  sn   

	


"rm  z/loginc                  C   sV  t jr	ttdS t } |  rtd tj	j
| jjd }|d u r4td tdd ttdS || jjsKtd tdd ttdS td	 t|| jjd
 | jjrutd tttd}|jd| jjdd |S tjd}|rt|std}td tdd t|S td tjd}|r|| j_tdd| dS )Nr   zForm validated successfullyr  zNo user found with that emailzInvalid email or passwordr\  r  zPassword check failedzLogging in user)rememberzSetting remember_me cookieremember_emaili ' )r  nextz%Redirecting to next page or dashboardzLogged in successfully.rE   zForm did not validatez
login.htmlzSign Inr^  )r#   r_  r   r   	LoginFormrP   loggingdebugrI   rJ   r   rc   rR   r   r	   check_passwordr  r$   remember_mer   
set_cookier   argsr   rQ  cookiesr
   )rO   rQ   resp	next_pageremembered_emailrX   rX   rY   login#  s@   









r|  z/login/googlec                  C   s8   t d} tddd}tt }|td< | j||dS )Nr=   zmain.google_callbackT)r
  nonce)r}  )r"   create_clientr   r   uuiduuid4r   authorize_redirect)r=   redirect_urir}  rX   rX   rY   login_googleM  s
   
r  z/auth/google/callbackc               
   C   s   t d} |  }tdd }|stdd ttdS | ||}|rt	j
j|d d }|sbt	t|d |d	 |d
 |d |d d}tj
jdd }|rW|j| tj| tj  zt| W n ty~ } z
t| W Y d }~nd }~ww ttdS tdd ttdS )Nr=   r}  z-Nonce not found. Please try logging in again.r   r  rc   r  sub
given_namefamily_namepicture)	google_idra   rb   rc   ra  rQ   r   r   z3User email not available or not verified by Google.)r"   r~  authorize_access_tokenr   popr	   r   r   parse_id_tokenrI   rJ   r   r   r   r  rT   rU   r!   rr   rV   r$   r   rN   )r=   r	  r}  userinforQ   default_roler   rX   rX   rY   google_callbackV  s>   




r  z/logoutc                   C   s   t   tdd ttdS )NzYou have been logged out.r   r  )r%   r	   r   r   rX   rX   rX   rY   logout  s   
r  z/api/save_settingsc                  C   s   t j} tjjtjd }|sttjd}| d|j	|_	| d|j
|_
| d|j|_| d|j|_| d|j|_| d|j|_| d|j|_tj| tj  td	d
dS )Nr]   r%  r&  r'  r(  r)  r*  r+  TzSettings saved successfully)rE   r   )r   jsonr   rJ   r   r#   r   r   r   r%  r&  r'  r(  r)  r*  r+  r!   r   rr   rV   r   )rR   r,  rX   rX   rY   save_settings  s   
r  z/load_settingsc               	   C   sR   t jjtjd } | r!t| j| j| j	| j
| j| j| jddfS tddidfS )Nr]   )r%  r)  r*  r&  r(  r'  r+     r   zNo settings foundi  )r   rJ   r   r#   r   r   r   r%  r)  r*  r&  r(  r'  r+  )settingsrX   rX   rY   load_settings  s   	r  z/profilec                  C   sH  t jd u r	t t _tt jd} t }t jd u rt t _tt d}t jd u r)t	 t _t
t d}t }tjdkr,dtjv r|  r| jjt _| jjt _| jjt _| jjt _| jjt j_| jjt j_| jjt j_| jjt j_| jjt j_| jjt j_tj  tdd tt dS dtjv r| rt !|j"jrt #|j$j tj  tdd tt dS td	d
 ndtjv r| r|j%jt j_%|j&jt j_&|j'jt j_'|j(jt j_(|j)jt j_)tj  tdd tt dS dtjv r+| r+|j*jt j_*|j+jt j_+|jjt j_|jjt j_|j,jt j_,|j-jt j_-tj  tdd tt dS nntjdkrt j| j_t j| j_t j| j_t jd urLt j| j_t jd urvt jj| j_t jj| j_t jj| j_t jj| j_t jj| j_t jj| j_t jd urt jj%|j%_t jj&|j&_t jj'|j'_t jj(|j(_t jj)|j)_t.d| ||||dS )Nr[   r@   update_profilezYour profile has been updated.rE   main.profilechange_passwordYour password has been updated.Current password is incorrect.r\  update_notificationsz+Notification preferences have been updated.update_billing_infoz%Billing information has been updated.r?   zprofile.htmlprofile_formchange_password_formnotification_formbilling_info_form
empty_form)/r#   rA  r   ProfileFormChangePasswordFormr   r   NotificationFormrj  r   BillingInfoForm	EmptyFormr   rM   rO   rP   ra   rR   rb   rc   rd   r   r   r   rR  rS  rT  r!   r   rV   r	   r   r   rt  current_passwordset_passwordnew_passwordrU  newsletter_notificationsinvoice_notificationsdelivery_notificationsemail_notificationsrV  rW  business_sectorr   r
   r  rX   rX   rY   rA    s   




















rA  z/change_passwordc                  C   sV   t  } |  r%t| jjr t| jj tj	
  tdd ntdd ttdS )Nr  rE   r  r\  r  )r  rP   r#   rt  r  rR   r  r  r!   r   rV   r	   r   r   )rO   rX   rX   rY   r    s   

r  z/upload_profile_picturec                  C   s   dt jvrtdd ttdS t jd } | jdkr%tdd ttdS | rQt| j}tj	t
jd|}| | tjd u rCt t_|tj_tj  tdd	 ttdS )
Nra  No file partr\  r   No selected filer[  z&Your profile picture has been updated!rE   )r   filesr	   r   r   filenamer/   rb  rc  rd  r<   re  rf  r#   rA  r   ra  r!   r   rV   )filer  rl  rX   rX   rY   upload_profile_picture  s"   









r  z/reset_profile_picturec                  C   s\   t jjr(tjtjdt jj} tj| rt	|  d t j_t
j  tdd ttdS )Nr[  z$Your profile picture has been reset!rE   r  )r#   rA  ra  rb  rc  rd  r<   re  existsremover!   r   rV   r	   r   r   )rl  rX   rX   rY   reset_profile_picture&  s   


r  c                  C   sh   t j } g }| D ](}|jd ur1|jd ur1|dd|j|jgd|j|jjtd|j	ddd q	|S )NFeaturePoint)typecoordinateszmain.layer_details)layer_id)rl   rm   link)r  geometry
properties)
r   rJ   rK   latitude	longituderU   rl   servicer   r   )layers
layer_datalayerrX   rX   rY   get_layer_data5  s    

r  z/get_layersc                  C   s   t  } td| dS )NFeatureCollection)r  features)r  r   )r  rX   rX   rY   
get_layersI  s   r  z/get_feature_layersc                  C   st   t j } g }| D ],}tj|j}tj|j}|r5|r5|j d|j	 d|j
 }|||j	|j	d q	t|S )N/rest/services//MapServer/)urlrl   rm   )r   rJ   rK   r   r   
service_idr   map_server_idr  rl   r   rU   r   )r  r  r  r  
map_server	layer_urlrX   rX   rY   get_feature_layersP  s   
r  zB/preview_layer/<int:map_server_id>/<int:service_id>/<int:layer_id>c           
      C   s  |d7 }t j| }|stddidfS tj|}|r!|j| kr)tddidfS tj|}|r6|j|kr>tddidfS |j d|j	 d|j
 d|jd  }t| d	}| }d
|vritddidfS |d
 }	tjd|  d| d|  tjd|  t||	dS )Nr   r   zInvalid map server  zInvalid servicezInvalid layerr  r/  ?f=pjsonextentzInvalid layer data from ArcGISz)Preview Layer called with map_server_id: z, service_id: z, layer_id: zPreview Layer url: )r  r  )r   rJ   r   r   r   r  r   r  r  rl   r  r   requestsr  r   r   r   )
r  r  r  r  r  r  r  r   rR   r  rX   rX   rY   preview_layerb  s,   &r  z/layersc                  C   s  t jd} t jdd}t jdd}t jdd}|r)|  d| d| d}n)|rB|r9|  d| d| d	}n|  d| d	}n|rM|  d| d}n|  d
}tjd|  t|}| }tjd|  tj	j
| d }|st| d}tj| tj  d|v r|d r|d D ]*}tj	j
||jd }	|	st||jd}
tj|
 tj  tjd|  qd|v rU|d rU|rtj	j
||jd }|d D ]9}tj	j
|d |jd }|st|d |d |jd}tj| tj  tjd|d  d|d   qn?|d D ]:}tj	j
|d |jd }|sCt|d |d |jd}tj| tj  tjd|d  d|d   qd|v rn|d rntd|d |dg | ddS d|v r|d rtd|d | ddS d|v r |d r tj	j
||jd }|std | d!|  d"g }|d D ]K}tj	j
|d |jd# }|st|\}}}}t|d |j||d$}tj| tj  tjd%|d   |j|d&< |j|d'< || qtd(|| |d)d*S td+d,| d-d.S )/N
arcgis_urlfolder_namer  service_namer  r  r/  r  z/MapServer?f=pjsonz/rest/services?f=pjsonzFetching URL: zData received from ArcGIS: )r  folders)rl   r  zProcessing folder: servicesrl   )rl   	folder_idr  )rl   r  r  zProcessing service: z	 of type )rl   r  r  zmapsearch.htmlzFolders & Services)r  r  r  r   zservices.htmlServices)r  r  r   r  z	Service 'z(' not found in database for map server '')rl   r  )rl   r  r  r  zProcessing layer: r  r  zlayers.htmlLayers)r  r  r  r   
error.htmlz#No results found for this endpoint.Error)r   r  r   )r   rw  r   r   r   r   r  r  r   rJ   r   r   r!   r   rr   rV   r   r   r   r
   
ValueErrorr   fetch_coordinatesrU   )r  r  r  r  r  r   rR   r  folderexisting_folder
new_folderparent_folderr  existing_servicenew_serviceparent_servicer  r  existing_layerlatlonr  spatial_reference	new_layerrX   rX   rY   r    s   





"
$


r  )TransformerCRSc              
   C   s   z\t | }| }|di }|di dd }d|v rZd|v rZd|v rZd|v rZ|rZtjd| d	d
d}|d |d  d }|d |d  d }|||\}}	|	|||fW S W dS  t jyy }
 ztj	d|
  W Y d }
~
dS d }
~
ww )N
fullExtentspatialReference
latestWkidxminyminxmaxymaxzepsg:z	epsg:4326T)	always_xy   )NNNNzError fetching coordinates: )
r  r   r  r  from_crs	transformRequestExceptionr   r   r   )service_urlr   rR   r  r  transformerx_centery_centerr  r  r   rX   rX   rY   r    s"   
$r  c                  C   s   t jd } tj| }|r@|jD ]/}|j d|j }t|\}}|d ur5|d ur5||_	||_
tj  qtjd|j  qttdS )Nr  r/  z&Could not fetch coordinates for layer zmain.viewmap)r   rO   r   rJ   r   r  r  r   r  r  r  r!   r   rV   r   r   rG   rl   r   r   )r  r  r  r  r  r  rX   rX   rY   	add_layer  s   

r  z/download_layer/<layer_name>c                 C   sX   t jd}t jd}|r|r| stddidfS tj||| gd}td|jidfS )	Nr  top_layer_namer   zMissing required parametersr  )rw  task_id   )r   rw  r   r   r)   apply_asyncr   )
layer_namer  r  taskrX   rX   rY   download_layer  s   r
  z /download_layer/status/<task_id>c                 C   s   t | }|jdkr|jdddd}t|S |jdkrB|j|jdd|jdd|jd	d
d}d|jv r>|jd |d< t|S |jddt|jd}t|S )NPENDINGr   r   z
Pending...)r   currentr   r   FAILUREr  r   r   r  result)r)   AsyncResultr   r   r   r   r   )r  r	  r   rX   rX   rY   download_layer_status'  s.   



r  z /download_layer/result/<task_id>c                 C   s@   t | }|jdkrtt|jd|  dddS tddidfS )	NSUCCESSlayer_z.zipT)r   r   r   zTask not completed or failedr  )r)   r  r   r   r   r  r   )r  r	  rX   rX   rY   download_layer_resultE  s   

r  z/layer_details/<layer_id>c                 C   s   t jdd}t jdd}tjd| d|  d|  | d| d|  d	}tjd
|  t|}| }tjd|  d|v r[tjd|d   d|d d  S t	d|||dS )Nr  r  r  z3Received request for layer details with arcgis_url=z, layer_id=z, top_layer_name=r  r  z?f=jsonz!Fetching layer details from URL: zLayer details received: r   zARCGIS Error: zError fetching layer details: r   zlayer_details.html)r  r  r  )
r   rw  r   r   r   r   r  r  r   r
   )r  r  r  r  r   rR   rX   rX   rY   layer_detailsO  s   
r  z/navigate_upc                  C   s>   t jdd} t jdd}t jdd}ttd| ||dS )Nr  r  r  r  zmain.layersr  r  r  )r   rw  r   r   r   r  rX   rX   rY   navigate_upf  s   r  z/addmapc                   C      t dS )Nzaddmap.htmlr
   rX   rX   rX   rY   addmapt     r  z/projectloadc                   C   r  )Nznewbulkupload.htmlr  rX   rX   rX   rY   projectloady  r  r  c                     s  t jd} t jd}t jd}t jdpd}| sdS tjtjdtj	dd	 tjt
  d
| j }| | i }d }|dkr_t|\}}|rS|s^tdd ttdS n|dkr%ddlm} dd l}|drx||n||}	d|	jv rt|	d jd nd}
d dD ]}| |
 v r|  nqdd l}tjtjtd}t|}| |}W d    n1 sw   Y  t! fdd|D d }|r|dd t jdpd|dd|dd|d}n%t jdd pt jd dt jddt jddt jdd|d}||\}}| |d!}nd"S tj"|\}}| d#}dd$l#m$} ||||| tj%|sOd%| d&fS t&fd'd(}tj%|sed%| d&fS t'|dd)S )*N	data_filecabinet_namecabinet_typeround0)zFile upload is requiredr  uploadsT)exist_ok_existingur   ❌ Could not find Ring Number or related Distribution WOs for this cabinet. Please double-check the cabinet name.r\  zmain.projectloadnewr   )r9   z.csvAttribute_complete_addressr  )PinellasHillsboroughPolkSarasotaManatee	CharlotteLeeCollierBayWaltonOkaloosaz
Santa RosaEscambiaHernandoCitrusSumterMarionOsceolaz	St. LuciezIndian RiverMartinz
Palm BeachBrowardz
Miami-DadeSeminoleVolusiaBrevardzmarket_orders.jsonc                 3   s$    | ]} | d g v r|V  qdS )countiesN)r   )r   m)county_namerX   rY   	<genexpr>  s   " z%handle_projectload.<locals>.<genexpr>market_order_nameUnknowndistribution_areaengineering_vendorconstruction_vendor)MOCountyDistribution_AreaEngineering_VendorConstruction_VendorRoundmocounty03d)z/Please select if the cabinet is NEW or EXISTINGr  z_output.xlsxr:   zOutput file not found: r   c              
      st   zt  D ]}t j |}t j|rt | qW | S  ty9 } ztj	d|  W Y d }~| S d }~ww )NzCleanup failed: )
rb  listdirrc  rd  isfiler  r   r   r   rG   )r   fnamefpathr   )upload_folderrX   rY   cleanup  s   
z#handle_projectload.<locals>.cleanup)r   )(r   r  r   rO   rb  rc  rd  r   re  makedirsr  r  r  rf  r8   r	   r   r   app.siteTrackerCallsr9   pandasendswithread_csv
read_excelcolumnsr   ilocr   r  dirname__file__openloadrp  splitextapp.bulkUploadGenr;   r  r   r   )r  r  r  round_value
input_pathproject_metanext_wo_numberr9   r   r   first_addressrM  r  	json_pathfmarket_datamarket_orderprefixbase_numbaseextoutput_pathr;   rT  rX   )r?  rS  rY   handle_projectload  s   


 







rq  z/viewmapc               
   C   s   z-t jtt jtjtj	tt jtj	
 } tjd|   td| dW S  tyP } ztjd|  tdt|dW  Y d }~S d }~ww )NzMap Servers: zviewmap.html)map_serverszError retrieving map servers: r  )r   )r   rJ   optionsr!   
joinedloadr  r   r  r   r  rK   r   r   r   r
   r   r   r   )rr  r   rX   rX   rY   viewmap  s   ru  z/gis_mapc                   C   r  )Nz	maps.htmlr  rX   rX   rX   rY   gis_map  r  rv  z/upload_filec                     s   t jdkrut jd} dt jvrtd tt jS t jd }|jdkr,td tt jS |rst	|j}t
jtjd |}|| dd	   fd
d}dd ldd ldd fdd}|||  td tj  ttdS d S tj }td|dS )Nr@   re   r  r  r  r  r>   c                 S   s   t | tr|   S | S N)
isinstancer   stripr   )valuerX   rX   rY   clean_header-     
z!upload_file.<locals>.clean_headerc                    s6   | d d   } d| d v od| d v od| d v S )N   manufacturer   modelr   dwg namer  )apply)row)r{  rX   rY   is_valid_header3  s   $z$upload_file.<locals>.is_valid_headerr   c                 S   s   t | tr|  d S d S )Nr   )rx  r   split)header_cellrX   rX   rY   "extract_equipment_type_from_header<  r|  z7upload_file.<locals>.extract_equipment_type_from_headerc                    s  t d|   | }g }|jD ]}t d|  j||d d}|js,|jd dkr4t d|  qz|jd }W n tyL   t d| d Y qw t d|j  d}|t	|d	 kr|||d	  
d
d }t d| d|d  d|j  d|jd v rd|jd v sd|jd v rd|jd v r || }	|	r|jdd ||d	 f }
g d|
_|	|
d< |
|
d  |
d dk@  }
|
jddidd t d| d| d|d  d|	 d|
 
 ||
 |d 7 }|t	|d	 ks_q|rIj|dd!}t d"|  | D ]4\}}tjj|d# |d |d$ |d |d% }|s<t|d# |d |d$ |d |d%}tj| q	tj  t d& d S t d' td())NzStarting to process file: zProcessing sheet: )r   headerr   zSkipping empty sheet: zSheet z' does not have enough rows. Skipping...z(Inspecting first row for table headers: r}  c                 S   s   t | tr	|  S d S rw  )rx  r   r   )xrX   rX   rY   <lambda>_  s    z7upload_file.<locals>.parse_and_insert.<locals>.<lambda>zChecking group in columns -r  r   r~  r  r   z
sub-folderr  )ManufacturerModel or Sub-FolderBlock DWG NamezEquipment Typer  r  ModelT)r[  inplacezExtracted table from sheet z
, columns z with equipment type z:
   )ignore_indexzCombined DataFrame:
r  r  )manufacturerr  block_dwg_nameequipment_typere   z-Data inserted successfully into the database.z+No valid tables found in the uploaded file.zNo valid tables found.)rN   	ExcelFilesheet_namesrZ  emptyshaper\  
IndexErrorvaluesrD  r  r[  notnarenamerU   concatiterrowsr   rJ   r   r   r!   r   rr   rV   r  )	file_pathre   xls
all_tablesr   r   	first_rowcolgroupr  tablecombined_dfr#  r  existing_record	new_entry)r  r   rX   rY   parse_and_insertA  s   

 
$
&
z%upload_file.<locals>.parse_and_insertz-File uploaded and data inserted successfully!zmain.upload_filezupload_blocks.htmlr   )r   rM   rO   r   r  r	   r   r  r  r/   rb  rc  rd  r   r   rf  rW  r!   r   rollbackr   r   rJ   rK   r
   )re   r  r  r  r  r  r   rX   )r{  r  r   rY   upload_file  s8   








d
  
r  z/search-blockc                  C   s   t jdkrGt jd} t jd}t jd}tjj||d }dd |D }t	| |}|rCtjj|d ||d	
 }td
|dS td tj }td|dS )Nr@   r  r  re   )r  re   c                 S   r   rX   )r  )r   entryrX   rX   rY   r     r   z search_block.<locals>.<listcomp>r   )r  r  re   zsearch_results.html)r  zNo match found.zblock_search.htmlr  )r   rM   rO   r   r   rJ   r   rK   r7   
extractOner   r
   r	   r   )search_queryr  re   
all_models
model_list
best_matchmatched_entryr   rX   rX   rY   search_block  s   

r  z/api/search_block_datac                  C   s   t jd} | stddidfS tj }g }|D ]2}t|j	
 | 
 }td|j	 d|  d|  |dkrK||j|j|j	|j|j|j|d	 qtd
|  t|S )Nr  r   zModel parameter is requiredr  zComparing 'z' with 'z': Similarity = F   )r   r  r  r  r  re   
similarityzMatching results: )r   rw  r   r   r   rJ   rK   r6   ratior  r   rN   rU   r   r  r  r  re   )query_modelall_datamatching_resultsr  r  rX   rX   rY   search_block_data  s*   
r  z/api/get_all_block_datac                  C   s    t j } dd | D }t|S )Nc              	   S   s*   g | ]}|j |j|j|j|j|jd qS )r   r  r  r  r  re   r  )r   r  rX   rX   rY   r     s    
z&get_all_block_data.<locals>.<listcomp>)r   rJ   rK   r   )r  rR   rX   rX   rY   get_all_block_data  s
   
	r  )r   rb  rer   flaskr   r   r   r   r   r   r	   r
   r   r   r   r   r   werkzeug.securityr   modelsr   r   r   r   r   r   r   r   r   r   r   r   r   r   forms
extensionsr!   r"   flask_loginr#   r$   r%   r&   urllib.parser'   r(   tasksr)   
decoratorsr*   rr  sysr5  r+   r,   r-   r.   r  werkzeug.utilsr/   r   rW  r   itsdangerousr0   rc   r1   appr2   r3   invoice_utilsr4   r5   
fuzzywuzzyr6   r7   siteTrackerCallsr8   r9   bulkUploadGenr;   	getLogger
addHandlerStreamHandlerstdout__name__r<   r~  r=   r>   r   rc  r  rU  routerZ   rg   rj   ru   ry   r   r   r   r   r   cachedr   r   r   r   r   r   r   r   r   r   r  r  r"  r$  r.  r   rQ  rm  r|  r  r  r  r  r  rA  r  r  r  r  r  r  r  r  pyprojr  r  r  r  r  r
  r  r  r  r  r  r  rq  ru  rv  	tracebackr  r  r  r  rX   rX   rX   rY   <module>   s   8@



/
>
	C;
*
"
%
A
)

(
T%bt	
 !

 