o
    'h                     @   s,  d dl Z d dlmZmZmZ d dlmZ d dl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 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(m)Z)m*Z* ddl"m+Z+m,Z,m-Z-m.Z. d dl/m0Z0 d dl1m2Z2 e Z3d dl4m5Z5m6Z6m7Z7m8Z8m9Z9m:Z:m;Z; edd Z<ee8ddd Z=edd Z>edd  Z?ed!d" Z@ee9d#d$d%d& ZAeed'd( ZBeed)d* ZCee9dd+d,d- ZDee9d+d.d/d0 ZEee d1ge8d2d3d4 ZFee d1ge9d#d$d5d6 ZGee8d.d7d8 ZHee8d.d9d: ZIee8d.d;d< ZJee8d.d=d> ZKee d1ge8d.d?d@ ZLee8ddAdB ZMee8ddCdD ZNee d1ge8d.dEdF ZOee d1ge8d.dGdH ZPee d1ge9d#d$dIdJ ZQdS )K    N)datetime	timedeltadate)defaultdict)renderget_object_or_404redirect)login_required)LoginRequiredMixin)ListView
CreateView
UpdateView)messages)reverse_lazyget_user_model)PermissionDeniedJsonResponse)	Paginator)require_POSTrequire_http_methods)forms)timezone)Q   )TicketTicketCommentTicketAttachment)
TicketFormTicketUpdateFormTicketCommentFormTicketAttachmentForm)Customer)TicketNotificationService)can_assign_ticketsEmployeeRequiredMixinCustomerRequiredMixinpermission_requiredany_permission_requiredhas_permissionget_user_permissionsc              
   C   s  | j jr
tj }n)| j jrtj }ntjt| j dt| j dB t| j dr.t| j dnt B }|	ddd}| j
dd	 }| j
d
d	 }| j
dd	 }| j
dd }| j
dd	 }|rm|sm|}|dkrz|jddgd}n|dkr|jddgd}n|dkr|jdddgd}|rt|dt|dB }t|jdr|t|dO }|t|dO }|t|dO }|t|dO }|t|dO }|t|dO }|t|dO }|t|d O }||}d!}|rd"d#d$d%dd&d'd(}	||	v r|	| }
|d)krd*|
 }
|
}||}t|d+}| j
d,}||}d-d.lm} d-d/lm} | }|jjdd0d1}|jjd2d2d3d4}| }|jddgd }|jdd5 }|jdddgd }|||||||||d6	}t| d7|S )8zList all tickets with filters)
created_byassigned_toemployee_profile)assigned_employee__usercustomerr.   assigned_employeefilter searchsortorderascstatusactiveopenin_progress
status__inresolvedclosedurgent)priorityr>   )title__icontains)ticket_id__icontains)customer__full_name__icontains)customer__phone__icontains) customer__customer_id__icontains) assigned_to__username__icontains)"assigned_to__first_name__icontains)!assigned_to__last_name__icontains)'assigned_employee__full_name__icontains))assigned_employee__employee_id__icontains-created_at	ticket_idcustomer__full_nametitlerB   assigned_employee__full_name
created_at)rN   r1   rP   rB   r9   r.   rR   desc-   pager   Employeer   employment_statusemployee_idT)is_staff	is_activeusernamer9   )	page_objstatus_filtersearch_querysort_column
sort_ordertotal_ticketsopen_ticketsresolved_ticketsurgent_ticketsztickets/ticket_list.html)useris_superuserr   objectsallr\   r3   r   hasattrselect_relatedGETgetstripmodelorder_byr   get_page	hr.modelsrX   django.contrib.authr   countr   )requestticketsfilter_typerb   rc   rd   ra   search_q
sort_fieldsort_fieldsfield	paginatorpage_numberr`   rX   r   User	employeesusersre   rf   rg   rh   context r   -/var/www/html/optinet_system/tickets/views.pyticket_list&   s   








r   view_calendarc                 C   s$  t jjdddd}| jd}| jd}| jd}|r9zt|d }|j|d	}W n	 t	y8   Y nw |rUzt|d }|j|d
}W n	 t	yT   Y nw |ro|
dri|dd }|j|d}n|j|d}ddlm} |jjdd}	tjjdd}
||	|
|||d}t| d|S )z'View for staff to see scheduled ticketsTF)is_scheduledscheduled_date__isnullscheduled_date	date_fromdate_tor.   %Y-%m-%dscheduled_date__date__gtescheduled_date__date__lteemp_   Nassigned_employee__employee_idassigned_to__usernamer   rW   r:   rY   r\   )scheduled_ticketsr   r   r   r   assigned_filterztickets/scheduled_tickets.html)r   rk   r3   rs   ro   rp   r   strptimer   
ValueError
startswithru   rX   r   r   )rx   r   r   r   r   date_from_parseddate_to_parsedemp_idrX   r   r   r   r   r   r   r      sN   
r   c                 C   sl   t | jdst| d tdS tjj| jjd	d}t
|d}| jd}||}d|i}t| d	|S )
z)View for clients to see their own ticketscustomer_profilez"You don't have a customer profile.	dashboard)r1   rM   rU   rV   r`   ztickets/my_tickets.html)rm   ri   r   errorr   r   rk   r3   r   rs   r   ro   rp   rt   r   )rx   ry   r   r   r`   r   r   r   r   
my_tickets   s   

r   c              
   C   s   | j dkr[t| j}| rZ| }|js|jrHzt }||}|s)t	
| d W n tyG } zt	
| dt|  W Y d}~nd}~ww t	| d|j d td|jdS nt }t| jd	rt| jj|jd
 _t |jd
 _d|i}t| d|S )zCreate a new ticketPOSTz.Ticket created but notification failed to sendz'Ticket created but notification error: NTicket z created successfully!tickets:ticket_detailticket_numberr   r1   formztickets/create_ticket.html)methodr   r   is_validsaver2   r.   r$   !send_ticket_assigned_notificationr   warning	ExceptionstrsuccessrN   r   rm   ri   r   fieldsinitialr   HiddenInputwidgetr   )rx   r   ticketnotification_servicer   er   r   r   r   create_ticket   s2   


"r   c                 C   s   t t|d}| jjs!t| jdr|j| jjkr!t| d t	dS |j
 d}|j d}| jjs;|jdd}t }t }|||||d	}t| d
|S )zView ticket detailsrN   r   z.You don't have permission to view this ticket.tickets:my_ticketsrR   z-uploaded_atF)is_internal)r   commentsattachmentscomment_formattachment_formztickets/ticket_detail.html)r   r   ri   r\   rm   r1   r   r   r   r   r   rl   rs   r   r3   r!   r"   r   )rx   r   r   r   r   r   r   r   r   r   r   ticket_detail  s$   r   change_ticketsmanage_ticketsc              
   C   s  t t|d}|j}|j}|j}| jdkrt| j|d}| r|	 }t
 }|j}	|j}
||	ks4||
kr]|	s8|
r]z|| W n ty\ } zt| dt|  W Y d}~nd}~ww ||jkr|jrz%|jdkrq|| n|jdkr||| n|jdkr|jr|| W n ty } zt| d	t|  W Y d}~nd}~ww t| d
|j d td|jdS nt|d}||d}t| d|S )zEdit ticket (staff only)r   r   )instancez(Ticket updated but notification failed: Nr?   r<   	scheduledz1Ticket updated but customer notification failed: r   z updated successfully!r   r   )r   r   ztickets/ticket_edit.html)r   r   r9   r2   r.   r   r    r   r   r   r$   r   r   r   r   r   r1   #send_service_completed_notification%send_technician_arriving_notificationr   send_appointment_reminderr   rN   r   r   )rx   r   r   
old_statusold_assigned_employeeold_assigned_tor   updated_ticketr   new_assigned_employeenew_assigned_tor   r   r   r   r   ticket_edit%  sN   
"


"
r   c                 C   s   t t|d}|j}| jjs$t| jdr|j| jjkr$t	| d t
dS t| j}| rL|jdd}||_| j|_| jjsAd|_|  t| d nt	| d t
d	|jd
S )zAdd comment to ticketr   r   z4You don't have permission to comment on this ticket.r   FcommitzComment added successfully!z.Error adding comment. Please check your input.r   r   )r   r   idri   r\   rm   r1   r   r   r   r   r!   r   r   r   r   r   r   rN   )rx   r   r   rN   r   commentr   r   r   add_commentX  s"   
r   c           	      C   s   t t|d}|j}| jjs$t| jdr|j| jjkr$t	| d t
dS t| j| j}| rG|jdd}||_| j|_|  t| d n|j D ]\}}|D ]}t	| | d|  qRqLt
d	|jd
S )zAdd attachment to ticketr   r   z<You don't have permission to add attachments to this ticket.r   Fr   z!Attachment uploaded successfully!: r   r   )r   r   r   ri   r\   rm   r1   r   r   r   r   r"   r   FILESr   r   r   uploaded_byr   errorsitemsrN   )	rx   r   r   rN   r   
attachmentr~   r   r   r   r   r   add_attachmentw  s$   r   view_ticketsc                 C   s  | j d}| j d}| j d}|r|s!t }|j}|j}nt|}t|}t||d}|dkrAt|d ddtdd }nt||d dtdd }tj	j
d||dd	}|rt|d
rn|dd }|j
|d}n|j
|d}ddlm}	 |	j	j
dd}
tj	j
dd}tt}|D ]7}|j }|| |j|j|j|j|jd|jr|jdnd|jrt|jnd|j|j|j|jd qddl }|!||}t"|||||j#| ||
||dkr|d nd|dkr|n|d |dk r|d nd|dk r|n|d d}t$| d|S )z,Display calendar view with scheduled tickets
technicianmonthyearr      )daysT)r   r   r   r   r   r   Nr   r   r   rW   r:   rY   r   z%H:%MzNot set)r   rN   rP   r1   scheduled_timeend_timedurationassigned_personrB   r9   category)calendar_datacalendar_structurecurrent_monthcurrent_year
month_nametechnician_filterr   r   
prev_month	prev_year
next_month	next_yearztickets/calendar_view.html)%ro   rp   r   todayr   r   intr   r   rk   r3   rs   r   ru   rX   r   r   listr   appendr   rN   rP   customer_namestrftimescheduled_end_timeestimated_durationr   r   rB   r9   r   calendarmonthcalendardictr   r   )rx   r   r   r   r   
start_dateend_datery   r   rX   r   r   r   r   ticket_dater   calr   r   r   r   calendar_view  sx   



r  manage_schedulesc           	      C   s   d}t | jdr| jj}t| jd}|r|t|dO }tjj|ddg ddd	}| j	d
}| j	d}|rRzt
|d }|j|d}W n	 tyQ   Y nw |rnzt
|d }|j|d}W n	 tym   Y nw ||||d}t| d|S )z.View for technicians to see their own scheduleNr/   r-   )r2   TF)r;   r<   r   )r   r   r>   r   r   r   r   r   r   )ry   employeer   r   ztickets/my_schedule.html)rm   ri   r/   r   r   rk   r3   rs   ro   rp   r   r   r   r   r   )	rx   r  
base_queryry   r   r   r   r   r   r   r   r   my_schedule  sH   r  r   assign_ticketsc              
   C   st  t t|d}| jd}|stdddS z|dr;ddlm} |d	d
 }|jj|d}||_	|j
r7|j
nd
|_ntjj|d}||_t|dd
|_	|  zt }||}	|	sctd|j  W n ty }
 ztd|j dt|
  W Y d
}
~
nd
}
~
ww tjj|| j
d|j dd tdd|j dW S  ty }
 ztdt|
dW  Y d
}
~
S d
}
~
ww )z'Reassign ticket to different technicianr   new_assigneeFzNo assignee selectedr   r   r   r   rW   r   Nr[   r^   r/   z'Failed to send notification for ticket z&Error sending notification for ticket r   zTicket reassigned to Tr   ri   r   r   r   message)r   r   r   rp   r   r   ru   rX   rk   r2   ri   r.   r   getattrr   r$   r   printrN   r   r   r   creater   )rx   rN   r   r	  rX   r   r  ri   r   r   r   r   r   r   reassign_ticket  sP   




r  c              
   C   sn  t t|d}| jd}z|dkr<t |_d|_d}|jr;z
t	 }|
| W n\ ty: } zW Y d}~nOd}~ww nI|dkr}|jsHt |_t |_d|_|jrZ|j|j |_d	}|jr|z
t	 }|| W n ty{ } zW Y d}~nd}~ww ntd
ddW S |  tjj|| j|dd td|dW S  ty } ztd
t|dW  Y d}~S d}~ww )z$Update ticket actual start/end timesr  actionstartr<   zWork startedNcompleter?   zWork completedFzInvalid actionr
  Tr  r  )r   r   r   rp   r   nowwork_started_atr9   r1   r$   r   r   completed_atactual_durationr   r   r   r   rk   r  ri   r   )rx   rN   r   r  r  r   r   r   r   r   update_ticket_timeP  s\   


r  c                 C   s   g }d|i}t | d|S )zList all schedule templates	templatesz#tickets/schedule_template_list.html)r   )rx   r  r   r   r   r   schedule_template_list  s   r  c                 C      t | d tdS )zCreate a new schedule templatez2Schedule template creation is not yet implemented.tickets:schedule_template_listr   infor   )rx   r   r   r   create_schedule_template     r"  c                 C   r  )z"Edit an existing schedule templatez1Schedule template editing is not yet implemented.r  r   rx   template_idr   r   r   edit_schedule_template  r#  r&  c                 C   r  )z)Use a schedule template to create ticketsz/Schedule template usage is not yet implemented.r  r   r$  r   r   r   use_schedule_template  r#  r'  c                 C   s   t dddS )zDelete a schedule templateFz1Schedule template deletion is not yet implementedr
  r   r$  r   r   r   delete_schedule_template  s   r(  c                 C   sl  | j d}| j d}|stddiddS z
t|d }W n ty1   tddidd Y S w tjj	d	|d

d}|rW|drQ|dd }|j	|d}n|j	|d}i }|D ]T}|jj}t|d}	|	|vrpg ||	< d}
|jrt|j }|d }|d d }|dkr| d| d}
n| d}
||	 |j|j|j|j|j|j|
|jd q[td|iS )z$Get timeline data for a specific dayr   r   r   zDate parameter requiredi  r_   r   zInvalid date formatT)r   scheduled_date__dater   r   r   Nr   r      r4   i  <   r   zh m)r   rN   rP   r   rB   r9   r   r1   timeline)ro   rp   r   r   r   r   r   r   rk   r3   rs   r   r   hourr   zfillr   r   total_secondsr   r   rN   rP   r   rB   r9   r   )rx   date_strr   date_objry   r   timeline_datar   r.  hour_keyduration_strr0  hoursminutesr   r   r   day_timeline  sZ   


r8  c              
   C   sh   t jjtddtddB ddgdd}g }|D ]}||j|j|j|j	|j
|jd	 qtd
|iS )zGet list of unscheduled ticketsF)r   T)r   r;   r<   r=   rM   )r   rN   rP   r1   rB   r9   ry   )r   rk   r3   r   rs   r   r   rN   rP   r   rB   r9   r   )rx   ry   ticket_datar   r   r   r   unscheduled_tickets  s"   
	r:  c              
   C   sF  | j d}| j d}| j d}| j d}t|||gs&tdddS ztjj|d}|j}|j}t	|d	}||_
d
|_d|_|rOt|}	t|	d|_|drtddlm}
 |dd }|
jj|d}||_|jrp|jnd|_ntjj|d}||_t|dd|_|  z0t }||jks||jkr||}|std|j  |jr||}|std|j  W n ty } ztd|j dt|  W Y d}~nd}~ww tjj || jd|!d d|j" d
d td
ddW S  tj#y   tddd Y S  ty" } ztdt|dW  Y d}~S d}~ww ) zSchedule an existing ticketrN   r   assigned_technicianr   FzMissing required fieldsr
  r  %Y-%m-%dT%H:%MTr   )r6  r   r   rW   r   Nr  r  r/   z2Failed to send technician notification for ticket z0Failed to send customer notification for ticket z'Error sending notifications for ticket r   zTicket scheduled for %Y-%m-%d %H:%Mz and assigned to r  zTicket scheduled successfullyr  Ticket not found)$r   rp   rl   r   r   rk   r2   r.   r   r   r   r   r9   floatr   r   r   ru   rX   ri   r   r  r   r$   r   r  rN   r1   send_appointment_confirmationr   r   r   r  r   r   DoesNotExist)rx   rN   r   r;  r   r   r   r   scheduled_datetimeduration_hoursrX   r   r  ri   r   r   r   r   r   r   schedule_existing_ticket  sp   


rD  c           	   
   C   s0  | j d}|stdddS zEtjj|d}t|d}|j}||_d|_|	  |r1|
dnd	}|
d}tjj|| jd
| d| dd tdd| |dW S  tjye   tddd Y S  ty} } ztdddW  Y d}~S d}~w ty } ztdt|dW  Y d}~S d}~ww )z+Reschedule an existing ticket to a new timenew_datetimeFzNew datetime is requiredr
  r  r<  Tr=  UnscheduledzTicket rescheduled from  to r  zTicket rescheduled to )r   r  rE  r>  zInvalid datetime formatN)r   rp   r   r   rk   r   r   r   r   r   r   r   r  ri   rA  r   r   r   )	rx   rN   new_datetime_strr   rE  old_datetimeold_time_strnew_time_strr   r   r   r   reschedule_ticketf  s@   

rL  c              
   C   s  ddl }z|| j}|d}|stdddW S dd tjD }||vr.tdd	dW S tjj|d
}|j}||_|dkri|dkrit	
 |_|jrhz
t }|| W nC tyg }	 zW Y d}	~	n6d}	~	ww n0|dkr|dkr|jsyt	
 |_|jrz
t }|| W n ty }	 zW Y d}	~	nd}	~	ww |  ttj||}
ttj||}tjj|| jd| d|
 dd tdd|
 |dW S  tjy   tddd Y S  |jy   tddd Y S  ty }	 ztdt|	dW  Y d}	~	S d}	~	ww )zChange ticket status via AJAXr   Nr9   FzStatus is requiredr
  c                 S   s   g | ]}|d  qS )r   r   ).0choicer   r   r   
<listcomp>  s    z(change_ticket_status.<locals>.<listcomp>zInvalid statusr   r?   r<   zStatus changed from rG  Tr  zTicket status changed to )r   r  
new_statusr>  zInvalid JSON data)jsonloadsbodyrp   r   r   STATUS_CHOICESrk   r9   r   r  resolved_atr1   r$   r   r   r  r   r   r   r   r  ri   rA  JSONDecodeErrorr   )rx   r   rQ  datarP  valid_statusesr   r   r   r   status_displayold_status_displayr   r   r   change_ticket_status  sp   



r[  )RrQ  r   r   r   collectionsr   django.shortcutsr   r   r   django.contrib.auth.decoratorsr	   django.contrib.auth.mixinsr
   django.views.genericr   r   r   django.contribr   django.urlsr   rv   r   django.core.exceptionsr   django.httpr   django.core.paginatorr   django.views.decorators.httpr   r   djangor   django.utilsr   django.db.modelsr   modelsr   r   r   r   r    r!   r"   customers.modelsr#   "notifications.ticket_notificationsr$   r   accounts.permissionsr%   r&   r'   r(   r)   r*   r+   r   r   r   r   r   r   r   r   r  r  r  r  r  r"  r&  r'  r(  r8  r:  rD  rL  r[  r   r   r   r   <module>   s    $
t3

 
1S/4;<O.