This commit is contained in:
gsinghpal
2026-02-27 14:32:32 -05:00
parent b649246e81
commit b925766966
80 changed files with 7831 additions and 1041 deletions

View File

@@ -2,6 +2,7 @@
# Copyright 2026 Nexa Systems Inc.
# License OPL-1 (Odoo Proprietary License v1.0)
import ipaddress
import json
import logging
import requests
@@ -54,6 +55,19 @@ class FusionClockLocation(models.Model):
default=lambda self: self.env.user.tz or 'UTC',
)
# IP whitelist fallback
ip_whitelist = fields.Text(
string='IP Whitelist',
help="One IP address or CIDR per line. Used as fallback when GPS is unavailable.",
)
# Photo verification
require_photo = fields.Boolean(
string='Require Photo on Clock-In',
default=False,
help="If enabled, employees must take a selfie when clocking in at this location.",
)
# Computed
attendance_count = fields.Integer(
string='Total Attendances',
@@ -89,6 +103,28 @@ class FusionClockLocation(models.Model):
('x_fclk_location_id', '=', rec.id),
])
def check_ip_whitelist(self, client_ip):
"""Check if a client IP matches this location's whitelist.
Returns True if matched, False otherwise.
"""
if not self.ip_whitelist or not client_ip:
return False
try:
client = ipaddress.ip_address(client_ip)
for line in self.ip_whitelist.strip().split('\n'):
line = line.strip()
if not line or line.startswith('#'):
continue
try:
network = ipaddress.ip_network(line, strict=False)
if client in network:
return True
except ValueError:
continue
except ValueError:
return False
return False
def action_geocode_address(self):
"""Geocode the address to get lat/lng using Google Geocoding API.
Falls back to Nominatim (OpenStreetMap) if Google fails.
@@ -97,7 +133,6 @@ class FusionClockLocation(models.Model):
if not self.address:
raise UserError(_("Please enter an address first."))
# Try Google first
api_key = self.env['ir.config_parameter'].sudo().get_param('fusion_clock.google_maps_api_key', '')
if api_key:
try:
@@ -126,13 +161,12 @@ class FusionClockLocation(models.Model):
},
}
elif data.get('status') == 'REQUEST_DENIED':
_logger.warning("Google Geocoding API denied. Enable the Geocoding API in Google Cloud Console. Falling back to Nominatim.")
_logger.warning("Google Geocoding API denied. Falling back to Nominatim.")
else:
_logger.warning("Google geocoding returned: %s. Trying Nominatim fallback.", data.get('status'))
_logger.warning("Google geocoding returned: %s. Trying Nominatim.", data.get('status'))
except requests.exceptions.RequestException as e:
_logger.warning("Google geocoding network error: %s. Trying Nominatim fallback.", e)
_logger.warning("Google geocoding network error: %s. Trying Nominatim.", e)
# Fallback: Nominatim (OpenStreetMap) - free, no API key needed
try:
url = 'https://nominatim.openstreetmap.org/search'
params = {
@@ -165,7 +199,7 @@ class FusionClockLocation(models.Model):
},
}
else:
raise UserError(_("Could not geocode address. No results found. Try a more specific address."))
raise UserError(_("Could not geocode address. No results found."))
except requests.exceptions.RequestException as e:
raise UserError(_("Network error during geocoding: %s") % str(e))