
    E|jV6              
       N   U d dl Z d dlZd dlZd dlmZmZmZ d dl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 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'  e jP                  e)      Z*dZ+ee,d<   dZ-ee,d<   dZ.ee,d<    e       Z/ G d de      Z0 G d de      Z1 G d de      Z2 G d de      Z3 G d de      Z4 G d  d!e      Z5d"ed#ed$dfd%Z6e/jo                  d&ejp                  e4'       e	e       e	e      fd(e0d#ed)e9fd*       Z:e/jw                  d&e3+       ed,d-.       ed/d0.       e	e       e	e      fd1e<d2e<d#ed)e9fd3       Z=e/j}                  d4e5+       e	e       e	e      fd5ej~                  d(e1d#ed)e9fd6       Z@y)7    N)FinalOptionalList)	APIRouterDependsHTTPExceptionQuerystatus)AsyncSession)select)	BaseModelEmailStrfield_validator)get_dbget_current_staff)hash_pin)User)MstrDepartment)MstrRole)ActiveSession)PatientLock)error_codes)ADMIN_ROLE_KEYS   
PIN_LENGTHd   MAX_NAME_LENGTH   MAX_EMAIL_LENGTHc                       e Zd ZU eed<   eed<   eed<   eed<   eed<    ed      ed               Z ed      ed               Z	 ed      ed               Z
 ed      ed	               Zy
)CreateStaffRequestnameroleIdemailpindepartmentIdc                 b    	 t        j                  |       |S # t        $ r t        d      w xY wNz!departmentId must be a valid UUIDuuidUUID
ValueErrorclsvs     2/var/www/html/ai-nims-dev/backend/app/api/staff.pyvalidate_department_idz)CreateStaffRequest.validate_department_id'   s9    	BIIaL   	B@AA	B    .c                 b    	 t        j                  |       |S # t        $ r t        d      w xY wNzroleId must be a valid UUIDr)   r-   s     r0   validate_role_idz#CreateStaffRequest.validate_role_id0   s6    	<IIaL   	<:;;	<r2   c                     |j                         st        d      t        |      t        kD  rt        dt         d      |j                         S )NName cannot be emptyzName cannot exceed z characters)stripr,   lenr   r-   s     r0   name_not_emptyz!CreateStaffRequest.name_not_empty9   sG     wwy344q6O#2?2C;OPPwwy    c                 h    t        j                  dt         d|      st        dt         d      |S Nz^\d{z}$zPIN must be exactly z numeric digitsrematchr   r,   r-   s     r0   pin_must_be_6_digitsz'CreateStaffRequest.pin_must_be_6_digitsB   s5     xx5C0!43J<OPPr;   N)__name__
__module____qualname__str__annotations__r   r   classmethodr1   r5   r:   rA    r;   r0   r!   r!       s    
IKO	H^$  % X   V   U  r;   r!   c                   2   e Zd ZU dZee   ed<   dZee   ed<   dZee   ed<   dZ	ee
   ed<   dZee   ed<   dZee   ed<   dZee   ed<    ed      ed	               Z ed      ed
               Z ed      ed               Z ed      ed               Zy)UpdateStaffRequestNr"   r#   r&   r$   r%   isActiveunlockc                 d    ||j                         st        d      |r|j                         S |S )Nr7   )r8   r,   r-   s     r0   r:   z!UpdateStaffRequest.name_not_emptyS   s0     =344qwwy$1$r;   c                 j    |	 t        j                  |       |S |S # t        $ r t        d      w xY wr4   r)   r-   s     r0   r5   z#UpdateStaffRequest.validate_role_idZ   sD     =@		! q  @ !>??@    2c                 j    |	 t        j                  |       |S |S # t        $ r t        d      w xY wr(   r)   r-   s     r0   r1   z)UpdateStaffRequest.validate_department_idd   sD     =F		! q  F !DEEFrO   c                 l    |1t        j                  dt         d|      st        dt         d      |S r=   r>   r-   s     r0   rA   z'UpdateStaffRequest.pin_must_be_6_digitsn   s9     =U:,c*BA!F3J<OPPr;   )rB   rC   rD   r"   r   rE   rF   r#   r&   r$   r   r%   rK   boolrL   r   rG   r:   r5   r1   rA   rH   r;   r0   rJ   rJ   J   s    D(3- FHSM "&L(3-& $E8H$C##Hhtn#!FHTN!V%  %
 X   ^$  % U  r;   rJ   c                       e Zd ZU eed<   eed<   eed<   eed<   eed<   eed<   eed<   eed<   eed	<   d
Zee   ed<   eed<   d
Z	ee   ed<   y
)	StaffItemidr"   r#   roleNameroleKeyr$   r&   rK   failedPinAttemptsNlockedAt	createdAt	updatedAt)
rB   rC   rD   rE   rF   rR   intrY   r   r[   rH   r;   r0   rT   rT   x   sR    G
IKMLJN"Hhsm"N#Ix}#r;   rT   c                       e Zd ZU ee   ed<   y)StaffListResponsestaffN)rB   rC   rD   r   rT   rF   rH   r;   r0   r^   r^      s    	?r;   r^   c                   h    e Zd ZU eed<   eed<   eed<   eed<   eed<   eed<   eed<   eed<   eed	<   y
)CreateStaffResponserU   r"   r#   rV   rW   r$   r&   rK   rZ   N)rB   rC   rD   rE   rF   rR   rH   r;   r0   ra   ra      s0    G
IKMLJNNr;   ra   c                       e Zd ZU eed<   eed<   eed<   eed<   eed<   eed<   eed<   eed<   eed	<   d
Zee   ed<   eed<   y
)UpdateStaffResponserU   r"   r#   rV   rW   r$   r&   rK   rX   NrY   rZ   )	rB   rC   rD   rE   rF   rR   r\   rY   r   rH   r;   r0   rc   rc      sD    G
IKMLJN"Hhsm"Nr;   rc   userdbreturnc                 *  K   |j                  t        t              j                  t        j                  | j
                  k(               d{   }|j                         }|r|j                  |       d{    |j                  t        t              j                  t        j                  | j
                  k(               d{   }|j                         j                         D ]  }|j                  |       d{     y7 7 7 E7 w)zFrees up a deactivated staff member's active session slot and any patient locks
    they're holding, so other staff aren't blocked by a now-inactive account.N)executer   r   wherestaff_idrU   scalar_one_or_nonedeleter   scalarsall)rd   re   active_resultactive_slotlock_resultlocks         r0    release_active_session_and_locksrs      s      **}##M$:$:dgg$EF M  224Kii$$$

{!!+"6"6$''"AB K ##%))+ iio
 	% 	sI   ADD*D9D:AD	D
9DDDDDD )status_coderesponse_modelrequestcurrent_staffc                   K   |j                  d      t        vr,t        t        j                  t
        j                  dd      |j                  t        t              j                  t        j                  t        j                  | j                        k(               d {   }|j                         }|s,t        t        j                   t
        j"                  dd      |j                  t        t$              j                  t$        j                  t        j                  | j&                        k(               d {   }|j                         }|s,t        t        j                   t
        j(                  dd      |j                  t        t*              j                  t*        j,                  | j,                  k(               d {   }|j                         }|r,t        t        j.                  t
        j0                  dd      t+        t        j2                         t        j                  | j                        | j4                  | j,                  t7        | j8                        |j                  dd	d 
	      }	|j;                  |	       |j=                          d {    |j?                  |	       d {    tA        tC        |	j                        |	j4                  tC        |j                        |j4                  |jD                  |	j,                  tC        |	jF                        |	jH                  |	jJ                  jM                         	      S 7 7 !7 7 7 w)NrolezOnly admins can create stafferrormessageru   detailDepartment not foundRole not found.A staff account with this email already existsTr   )	rU   department_idr"   r$   pin_hashrole_id	is_activefailed_pin_attempts	locked_at)	rU   r"   r#   rV   rW   r$   r&   rK   rZ   )'getr   r   r
   HTTP_403_FORBIDDENr   	FORBIDDENrh   r   r   ri   rU   r*   r+   r&   rk   HTTP_404_NOT_FOUNDDEPARTMENT_NOT_FOUNDr   r#   ROLE_NOT_FOUNDr   r$   HTTP_409_CONFLICTEMAIL_ALREADY_EXISTSuuid4r"   r   r%   addcommitrefreshra   rE   role_keyr   r   
created_at	isoformat)
rw   re   rx   dept_result
departmentrole_resultrz   email_resultexistingnew_users
             r0   create_staffr      s      711(22?]^
 	

 

~$$7+?+?!@@	
 K
 //1J11(==J`a
 	
 

xx{{dii.GGH K ))+D11(77DTU
 	
 t4::67 L ..0H00(==Jz{
 	
 ::<ii 4 45\\mm'++&
H FF8
))+
**X
x{{]]477|nn//0##%%//1
 
e. s^   B"M0$M#%B M0M&BM0M)CM0.M,/M0M.BM0&M0)M0,M0.M0)rv   rZ   z)^(name|department|role|status|createdAt)$)patterndescz^(asc|desc)$sort_byorderc                   K   |j                  d      t        vrt        dt        j                  dd      t        j                  |d         }|j                  t        t              j                  t        j                  |k(               d {   }t        |j                         j                               }|j                  t        t                     d {   }|j                         j                         D ci c]"  }t!        |j"                        |j$                  $ c}|j                  t        t&                     d {   }	|	j                         j                         D 
ci c]  }
t!        |
j"                        |
 c}
dt        dt         ffd	dt        dt(        fd
|dk(  }d fdfdfdd d}|j+                  ||    |       t-        |D cg c]  }t/        t!        |j"                        |j$                  t!        |j0                        t!        |j0                           j$                  t!        |j0                           j2                  |j4                  t!        |j                        |j6                  |j8                  |j:                  r|j:                  j=                         nd |j>                  j=                                c}      S 7 _7 c c}w 7 c c}
w c c}w w)Nrz   i  zOnly admins can view staff listr{   r~   r&   srf   c                 l    j                  t        | j                              }|r|j                  S dS Nrt   )r   rE   r   r"   )r   rz   role_maps     r0   	role_namezlist_staff.<locals>.role_name  s*    ||C		N+ tyy(b(r;   c                 <    | j                   y| j                  rdS dS )N   r      )r   r   r   s    r0   status_orderz list_staff.<locals>.status_order  s     ;;"KKq&Q&r;   r   c                 >    | j                   xs dj                         S r   )r"   lowerr   s    r0   <lambda>zlist_staff.<locals>.<lambda>&  s    2 4 4 6 r;   c                 j    j                  t        | j                        d      j                         S r   )r   rE   r   r   )r   dept_maps    r0   r   zlist_staff.<locals>.<lambda>'  s$    S-A2 F L L N r;   c                 0     |       j                         S N)r   )r   r   s    r0   r   zlist_staff.<locals>.<lambda>(  s    	! 2 2 4 r;   c                      |       S r   rH   )r   r   s    r0   r   zlist_staff.<locals>.<lambda>)  s    Q r;   c                     | j                   S r   )r   r   s    r0   r   zlist_staff.<locals>.<lambda>*  s
     r;   )r"   r   rz   r
   rZ   )keyreverserU   r"   r#   rV   rW   r$   r&   rK   rX   rY   rZ   )r_   ) r   r   r   r   r   r*   r+   rh   r   r   ri   r   listrm   rn   r   rE   rU   r"   r   r\   sortr^   rT   r   r   r$   r   r   r   r   r   )r   r   re   rx   admin_department_idresult
staff_listr   dr   rr   sort_key_mapr   r   r   r   r   s                 @@@@r0   
list_staffr     s\      7(22?`a
 	
 ))M.$AB::fTl001C1CGZ1Z[\\Ffnn&**,-J

6.#9::K;F;N;N;P;T;T;VWaADD	166 1WH

6(#344K;F;N;N;P;T;T;V$WaSY\$WH)T )c )' ' '
 voG6N4/,L OOW-wO?  
  qtt9VV199~!#aii.166 QYY099gg 1"#"7"745KK..0T,,002
 9 ] ;W4$W,
sc   BLK4AL"K7#$L'K:.$LK?$L7LAL0C<L,	L7L:L
Lz/{staff_id}rj   c                 :  K   |j                  d      t        vr,t        t        j                  t
        j                  dd      |j                  t        t              j                  t        j                  | k(               d {   }|j                         }|s,t        t        j                  t
        j                  dd      |j                  |j                  |_        |j                   |j                  t        t              j                  t        j                   |j                   k(  t        j                  | k7               d {   }|j                         r,t        t        j"                  t
        j$                  dd      |j                   |_        |j&                  |j                  t        t(              j                  t(        j                  t+        j,                  |j&                        k(               d {   }|j                         s,t        t        j                  t
        j.                  dd      t+        j,                  |j&                        |_        |j2                  |j                  t        t4              j                  t4        j                  t+        j,                  |j2                        k(               d {   }|j                         s,t        t        j                  t
        j6                  dd      t+        j,                  |j2                        |_        |j:                  :t=        |j:                        |_        t@        jC                  d	|j                          |jD                  \|jD                  |_#        t@        jC                  d
|j                   |jD                         |jD                  stI        ||       d {    |jJ                  du r.d |_&        d|_'        t@        jC                  d|j                          |jQ                          d {    |jS                  |       d {    |j                  t        t(              j                  t(        j                  |j0                  k(               d {   }|jU                         }	tW        tY        |j                        |j                  tY        |	j                        |	j                  |	jZ                  |j                   tY        |j8                        |jF                  |jN                  |jL                  r|jL                  j]                         nd |j^                  j]                               S 7 7 77 ~7 7 7 V7 @7 w)Nrz   z%Only admins can update staff accountsr{   r~   zStaff account not foundr   r   r   zPIN reset for %szStaff %s isActive set to %sTr   zAccount unlocked for %sr   )0r   r   r   r
   r   r   r   rh   r   r   ri   rU   rk   r   STAFF_NOT_FOUNDr"   r$   r   r   r#   r   r*   r+   r   r   r&   r   r   r   r%   r   r   loggerinforK   r   rs   rL   r   r   r   r   
scalar_onerc   rE   r   r   r   )
rj   rw   re   rx   r   rd   r   r   r   rz   s
             r0   update_staffr   B  s%      711(22?fg
 	

 ::t477h./ F $$&D11(88E^_
 	

 ||LL	}} ZZ4LtzzW]]:DGGx<OP
 
 **,"44!,!A!AN~  ]]
~~!JJ8""8;;$))GNN2K#KL
 
 --/"55!,!;!;HXY  yy0'JJ>"(():):diiH\H\>])]^
 
 --/"55!,!A!ANde  "YYw';';<{{ -&

3# ))14::w?O?OP 24<<<~~#$ -tzz:
))+
**T


6(#3#9#9(++:U#VWWK!!#Dtww<YY477|jj++,22/3~~))+4//++- M


( = Ws   BVVCVVB;VV
CVVDV)V*AV=V>VVAV&V'CVV
VVVVVV)Aloggingr*   r?   typingr   r   r   fastapir   r   r   r	   r
   sqlalchemy.ext.asyncior   
sqlalchemyr   pydanticr   r   r   app.core.depsr   r   app.core.authr   app.models.userr   app.models.mstr_departmentr   app.models.mstr_roler   app.models.active_sessionr   app.models.patient_lockr   app.constantsr   app.constants.role_keysr   	getLoggerrB   r   r   rF   r   r   routerr!   rJ   rT   r^   ra   rc   rs   postHTTP_201_CREATEDdictr   r   rE   r   patchr+   r   rH   r;   r0   <module>r      s	     	 ( ( D D /  9 9 3 "   5 ) 3 / % 3			8	$
E   % 	
' 'T) )\$	 $	 	) 	)   < D & RV44EXY v!"34GGG G ZGT B01.YZv~6v!"34	999 	9 	9 29x m,?@ v!"34	^ii^^ 	^ 	^ A^r;   