
    Xj]                         d dl Z d dlmZmZmZ d dlmZ  G d dej                        Z G d dej                        Z	 G d d	ej                        Z
y)
    N)_fieldsmodels)	UserErrorc                   >   e Zd ZdZdZdZ ej                  d      Z ej                  dd      Z
 ej                  dd      Z ej                  ddd	d
      Z ej                  d      Z ej                         Z ej$                  dd      Zed        Zd Zy)XenoAttendanceLocationxeno.attendance.locationzIAllowed GPS check-in location (geofence), mirrors XENHR's locations tablenameT)required)
      )digitsr   zRadius (meters)d   z,Allowed distance from this point, in meters.)stringr   defaulthelp)r   zCHECK(radius > 0)zRadius must be greater than 0.c                    d}t        j                  || z
        }t        j                  ||z
        }t        j                  |dz        dz  t        j                  t        j                  |             t        j                  t        j                  |            z  t        j                  |dz        dz  z  z   }dt        j                  t        j
                  |      t        j
                  d|z
              z  }||z  S )zrDistance in meters between two GPS points -- same formula as
        XENHR's AttendanceService::haversineDistance.i6a       )mathradianssincosatan2sqrt)	lat1lon1lat2lon2earth_radiusd_latd_lonacs	            J/home/susu/odoo-hr-migration/xeno_attendance/models/attendance_geofence.py_xeno_haversinez&XenoAttendanceLocation._xeno_haversine   s     TD[)TD[)XXeai A%xxT*+dhht||D7I.JJTXXV[^_V_M`deMeef

499Q<1q5)9::a    c                     d}| D ]H  }| j                  |||j                  |j                        }|||k  r|}||j                  k  sD||fc S  | j	                         |xs dfS )a  Among these (active) locations, return (matched_location, min_distance)
        -- matched_location is the closest one the point falls within, or an
        empty recordset if none match (min_distance is still the closest
        distance found, for a useful error message).Ng        )r&   latitude	longituderadiusbrowse)selfr)   r*   min_distancelocationdistances         r%   _xeno_matchz"XenoAttendanceLocation._xeno_match%   s|    
  	*H++HiARART\TfTfgH#x,'>'8??*))	* {{}|2s33r'   N)__name__
__module____qualname___name_description_orderr   Charr
   Floatr)   r*   Integerr+   Booleanactiveremarkr   
Constraint_radius_positivestaticmethodr&   r1    r'   r%   r   r      s    &E^LF6;;%Dv||7T:HGd;IV^^ 4;=F V^^D)FV[[]F(v((= 	  	 4r'   r   c                   <    e Zd ZdZ ej
                  dddd      Zy)HrAttendancezhr.attendancer	   zMatched LocationTz8Which configured geofence this check-in matched, if any.)r   readonlyr   N)r2   r3   r4   _inheritr   Many2onexeno_location_idrA   r'   r%   rC   rC   4   s$    H&v"+=GIr'   rC   c                   $     e Zd ZdZd fd	Z xZS )
HrEmployeezhr.employeec                    | j                   dk7  }d}|r|xs i j                  d      dk7  r| j                  d   j                         j	                  dg      }|rx|xs i j                  d      }|xs i j                  d      }|r|st        t        d	            |j                  ||      \  }}|st        t        d
t        |                  t        	| )  |      }|r|j                  |j                         _        |S )a  Geofence GPS check-ins against xeno.attendance.location, mirroring
        XENHR's AttendanceService::checkIn/validateGpsLocation exactly: if no
        active locations are configured, no restriction (today's behavior,
        unchanged); otherwise GPS coordinates are required and must fall
        within at least one location's radius, or the check-in is rejected
        with the closest distance reported -- same as XENHR's
        OutsideLocationException. Only applies to check-IN (XENHR never
        geofences check-out either).

        Only applies to 'systray' check-ins (an employee's own device) --
        never to 'kiosk' (a shared, physically-controlled terminal at a
        fixed office location, where core sets geo_information['mode'] to
        'kiosk'). A kiosk's own physical presence already proves the
        workplace; requiring browser GPS from it as well is both pointless
        and often impossible in practice (geolocation is blocked by
        browsers on non-HTTPS origins, and GeoIP can't resolve a private
        LAN address), so enforcing it here would just lock out the kiosk
        entirely once any geofence location is configured.
        
checked_inNmodekioskr	   )r<   =Tr)   r*   zhGPS coordinates are required to check in at this workplace. Please enable location access and try again.z{You are not within any designated check-in area (closest is %(distance)s m away). Please check your location and try again.)r0   )geo_information)attendance_stategetenvsudosearchr   r   r1   intsuper_attendance_action_changeidrG   )
r-   rO   is_checking_inmatched	locationsr)   r*   r.   
attendance	__class__s
            r%   rW   z$HrEmployee._attendance_action_change?   s   ( ..,>4"99&AWL!;<AACJJLaKbcI+1r66zB,277D	y#A!%" # # )2(=(=h	(R%#A2 "%\!2	%4 5 5
 W66W
18JOO.r'   )N)r2   r3   r4   rE   rW   __classcell__)r]   s   @r%   rI   rI   <   s    H* *r'   rI   )r   odoor   r   r   odoo.exceptionsr   Modelr   rC   rI   rA   r'   r%   <module>rb      sD     " " %*4V\\ *4ZI6<< I- -r'   