changes
This commit is contained in:
@@ -26,6 +26,7 @@ class AuthorizerPortal(CustomerPortal):
|
||||
if hasattr(response, 'qcontext') and (partner.is_authorizer or partner.is_sales_rep_portal or partner.is_client_portal or partner.is_technician_portal):
|
||||
posting_info = self._get_adp_posting_info()
|
||||
response.qcontext.update(posting_info)
|
||||
response.qcontext.update(self._get_clock_status_data())
|
||||
|
||||
# Add signature count (documents to sign) - only if Sign module is installed
|
||||
sign_count = 0
|
||||
@@ -724,7 +725,7 @@ class AuthorizerPortal(CustomerPortal):
|
||||
'sale_type_filter': sale_type,
|
||||
'status_filter': status,
|
||||
}
|
||||
|
||||
values.update(self._get_clock_status_data())
|
||||
return request.render('fusion_authorizer_portal.portal_sales_dashboard', values)
|
||||
|
||||
@http.route(['/my/sales/cases', '/my/sales/cases/page/<int:page>'], type='http', auth='user', website=True)
|
||||
@@ -1090,14 +1091,60 @@ class AuthorizerPortal(CustomerPortal):
|
||||
_logger.error(f"Error downloading proof of delivery: {e}")
|
||||
return request.redirect('/my/funding-claims')
|
||||
|
||||
# ==================== CLOCK STATUS HELPER ====================
|
||||
|
||||
def _get_clock_status_data(self):
|
||||
"""Get clock in/out status for the current portal user."""
|
||||
try:
|
||||
user = request.env.user
|
||||
Employee = request.env['hr.employee'].sudo()
|
||||
employee = Employee.search([('user_id', '=', user.id)], limit=1)
|
||||
if not employee:
|
||||
employee = Employee.search([
|
||||
('name', '=', user.partner_id.name),
|
||||
('user_id', '=', False),
|
||||
], limit=1)
|
||||
if not employee or not getattr(employee, 'x_fclk_enable_clock', False):
|
||||
return {'clock_enabled': False}
|
||||
|
||||
is_checked_in = employee.attendance_state == 'checked_in'
|
||||
check_in_time = ''
|
||||
location_name = ''
|
||||
if is_checked_in:
|
||||
att = request.env['hr.attendance'].sudo().search([
|
||||
('employee_id', '=', employee.id),
|
||||
('check_out', '=', False),
|
||||
], limit=1)
|
||||
if att:
|
||||
check_in_time = att.check_in.isoformat() if att.check_in else ''
|
||||
location_name = att.x_fclk_location_id.name if att.x_fclk_location_id else ''
|
||||
|
||||
return {
|
||||
'clock_enabled': True,
|
||||
'clock_checked_in': is_checked_in,
|
||||
'clock_check_in_time': check_in_time,
|
||||
'clock_location_name': location_name,
|
||||
}
|
||||
except Exception as e:
|
||||
_logger.warning("Clock status check failed: %s", e)
|
||||
return {'clock_enabled': False}
|
||||
|
||||
# ==================== TECHNICIAN PORTAL ====================
|
||||
|
||||
def _check_technician_access(self):
|
||||
"""Check if current user is a technician portal user."""
|
||||
partner = request.env.user.partner_id
|
||||
if not partner.is_technician_portal:
|
||||
return False
|
||||
return True
|
||||
if partner.is_technician_portal:
|
||||
return True
|
||||
has_tasks = request.env['fusion.technician.task'].sudo().search_count([
|
||||
'|',
|
||||
('technician_id', '=', request.env.user.id),
|
||||
('additional_technician_ids', 'in', [request.env.user.id]),
|
||||
], limit=1)
|
||||
if has_tasks:
|
||||
partner.sudo().write({'is_technician_portal': True})
|
||||
return True
|
||||
return False
|
||||
|
||||
@http.route(['/my/technician', '/my/technician/dashboard'], type='http', auth='user', website=True)
|
||||
def technician_dashboard(self, **kw):
|
||||
@@ -1159,6 +1206,8 @@ class AuthorizerPortal(CustomerPortal):
|
||||
ICP = request.env['ir.config_parameter'].sudo()
|
||||
google_maps_api_key = ICP.get_param('fusion_claims.google_maps_api_key', '')
|
||||
|
||||
clock_data = self._get_clock_status_data()
|
||||
|
||||
values = {
|
||||
'today_tasks': today_tasks,
|
||||
'current_task': current_task,
|
||||
@@ -1174,6 +1223,7 @@ class AuthorizerPortal(CustomerPortal):
|
||||
'google_maps_api_key': google_maps_api_key,
|
||||
'page_name': 'technician_dashboard',
|
||||
}
|
||||
values.update(clock_data)
|
||||
return request.render('fusion_authorizer_portal.portal_technician_dashboard', values)
|
||||
|
||||
@http.route(['/my/technician/tasks', '/my/technician/tasks/page/<int:page>'], type='http', auth='user', website=True)
|
||||
@@ -1423,11 +1473,17 @@ class AuthorizerPortal(CustomerPortal):
|
||||
return {'success': False, 'error': str(e)}
|
||||
|
||||
@http.route('/my/technician/task/<int:task_id>/action', type='json', auth='user', website=True)
|
||||
def technician_task_action(self, task_id, action, **kw):
|
||||
"""Handle task status changes (start, complete, en_route, cancel)."""
|
||||
def technician_task_action(self, task_id, action, latitude=None, longitude=None, accuracy=None, **kw):
|
||||
"""Handle task status changes (start, complete, en_route, cancel).
|
||||
Location is mandatory -- the client must send GPS coordinates."""
|
||||
if not self._check_technician_access():
|
||||
return {'success': False, 'error': 'Access denied'}
|
||||
|
||||
if not latitude or not longitude:
|
||||
return {'success': False, 'error': 'Location is required. Please enable GPS and try again.'}
|
||||
if not (-90 <= latitude <= 90 and -180 <= longitude <= 180):
|
||||
return {'success': False, 'error': 'Invalid GPS coordinates.'}
|
||||
|
||||
user = request.env.user
|
||||
Task = request.env['fusion.technician.task'].sudo()
|
||||
|
||||
@@ -1439,21 +1495,32 @@ class AuthorizerPortal(CustomerPortal):
|
||||
):
|
||||
return {'success': False, 'error': 'Task not found or not assigned to you'}
|
||||
|
||||
request.env['fusion.technician.location'].sudo().log_location(
|
||||
latitude=latitude,
|
||||
longitude=longitude,
|
||||
accuracy=accuracy,
|
||||
)
|
||||
|
||||
location_ctx = {
|
||||
'action_latitude': latitude,
|
||||
'action_longitude': longitude,
|
||||
'action_accuracy': accuracy or 0,
|
||||
}
|
||||
|
||||
if action == 'en_route':
|
||||
task.action_start_en_route()
|
||||
task.with_context(**location_ctx).action_start_en_route()
|
||||
elif action == 'start':
|
||||
task.action_start_task()
|
||||
task.with_context(**location_ctx).action_start_task()
|
||||
elif action == 'complete':
|
||||
completion_notes = kw.get('completion_notes', '')
|
||||
if completion_notes:
|
||||
task.completion_notes = completion_notes
|
||||
task.action_complete_task()
|
||||
task.with_context(**location_ctx).action_complete_task()
|
||||
elif action == 'cancel':
|
||||
task.action_cancel_task()
|
||||
task.with_context(**location_ctx).action_cancel_task()
|
||||
else:
|
||||
return {'success': False, 'error': f'Unknown action: {action}'}
|
||||
|
||||
# For completion, also return next task info
|
||||
result = {
|
||||
'success': True,
|
||||
'status': task.status,
|
||||
@@ -1600,10 +1667,14 @@ class AuthorizerPortal(CustomerPortal):
|
||||
return {'success': False, 'error': str(e)}
|
||||
|
||||
@http.route('/my/technician/task/<int:task_id>/voice-complete', type='json', auth='user', website=True)
|
||||
def technician_voice_complete(self, task_id, transcription, **kw):
|
||||
def technician_voice_complete(self, task_id, transcription, latitude=None, longitude=None, accuracy=None, **kw):
|
||||
"""Format transcription with GPT and complete the task."""
|
||||
if not self._check_technician_access():
|
||||
return {'success': False, 'error': 'Access denied'}
|
||||
if not latitude or not longitude:
|
||||
return {'success': False, 'error': 'Location is required. Please enable GPS and try again.'}
|
||||
if not (-90 <= latitude <= 90 and -180 <= longitude <= 180):
|
||||
return {'success': False, 'error': 'Invalid GPS coordinates.'}
|
||||
|
||||
user = request.env.user
|
||||
Task = request.env['fusion.technician.task'].sudo()
|
||||
@@ -1675,7 +1746,18 @@ class AuthorizerPortal(CustomerPortal):
|
||||
'completion_notes': completion_html,
|
||||
'voice_note_transcription': transcription,
|
||||
})
|
||||
task.action_complete_task()
|
||||
|
||||
request.env['fusion.technician.location'].sudo().log_location(
|
||||
latitude=latitude,
|
||||
longitude=longitude,
|
||||
accuracy=accuracy,
|
||||
)
|
||||
location_ctx = {
|
||||
'action_latitude': latitude,
|
||||
'action_longitude': longitude,
|
||||
'action_accuracy': accuracy or 0,
|
||||
}
|
||||
task.with_context(**location_ctx).action_complete_task()
|
||||
|
||||
return {
|
||||
'success': True,
|
||||
|
||||
Reference in New Issue
Block a user