feat: hide authorizer for rental orders, auto-set sale type

Rental orders no longer show the "Authorizer Required?" question or
the Authorizer field. The sale type is automatically set to 'Rentals'
when creating or confirming a rental order. Validation logic also
skips authorizer checks for rental sale type.

Made-with: Cursor
This commit is contained in:
gsinghpal
2026-02-25 23:33:23 -05:00
parent 3c8f83b8e6
commit 14fe9ab716
51 changed files with 4192 additions and 822 deletions

View File

@@ -1111,9 +1111,11 @@ class AuthorizerPortal(CustomerPortal):
SaleOrder = request.env['sale.order'].sudo()
today = fields.Date.context_today(request.env['fusion.technician.task'])
# Today's tasks
# Today's tasks (lead or additional technician)
today_tasks = Task.search([
'|',
('technician_id', '=', user.id),
('additional_technician_ids', 'in', [user.id]),
('scheduled_date', '=', today),
('status', '!=', 'cancelled'),
], order='sequence, time_start, id')
@@ -1143,7 +1145,9 @@ class AuthorizerPortal(CustomerPortal):
from datetime import timedelta
tomorrow = today + timedelta(days=1)
tomorrow_count = Task.search_count([
'|',
('technician_id', '=', user.id),
('additional_technician_ids', 'in', [user.id]),
('scheduled_date', '=', tomorrow),
('status', '!=', 'cancelled'),
])
@@ -1181,7 +1185,7 @@ class AuthorizerPortal(CustomerPortal):
user = request.env.user
Task = request.env['fusion.technician.task'].sudo()
domain = [('technician_id', '=', user.id)]
domain = ['|', ('technician_id', '=', user.id), ('additional_technician_ids', 'in', [user.id])]
if filter_status == 'scheduled':
domain.append(('status', '=', 'scheduled'))
@@ -1237,14 +1241,19 @@ class AuthorizerPortal(CustomerPortal):
try:
task = Task.browse(task_id)
if not task.exists() or task.technician_id.id != user.id:
if not task.exists() or (
task.technician_id.id != user.id
and user.id not in task.additional_technician_ids.ids
):
raise AccessError(_('You do not have access to this task.'))
except (AccessError, MissingError):
return request.redirect('/my/technician/tasks')
# Check for earlier uncompleted tasks (sequential enforcement)
earlier_incomplete = Task.search([
'|',
('technician_id', '=', user.id),
('additional_technician_ids', 'in', [user.id]),
('scheduled_date', '=', task.scheduled_date),
('time_start', '<', task.time_start),
('status', 'not in', ['completed', 'cancelled']),
@@ -1284,7 +1293,10 @@ class AuthorizerPortal(CustomerPortal):
Attachment = request.env['ir.attachment'].sudo()
try:
task = Task.browse(task_id)
if not task.exists() or task.technician_id.id != user.id:
if not task.exists() or (
task.technician_id.id != user.id
and user.id not in task.additional_technician_ids.ids
):
return {'success': False, 'error': 'Task not found'}
from markupsafe import Markup, escape
@@ -1421,7 +1433,10 @@ class AuthorizerPortal(CustomerPortal):
try:
task = Task.browse(task_id)
if not task.exists() or task.technician_id.id != user.id:
if not task.exists() or (
task.technician_id.id != user.id
and user.id not in task.additional_technician_ids.ids
):
return {'success': False, 'error': 'Task not found or not assigned to you'}
if action == 'en_route':
@@ -1470,7 +1485,10 @@ class AuthorizerPortal(CustomerPortal):
ICP = request.env['ir.config_parameter'].sudo()
task = Task.browse(task_id)
if not task.exists() or task.technician_id.id != user.id:
if not task.exists() or (
task.technician_id.id != user.id
and user.id not in task.additional_technician_ids.ids
):
return {'success': False, 'error': 'Task not found'}
api_key = ICP.get_param('fusion_notes.openai_api_key') or ICP.get_param('fusion_claims.ai_api_key', '')
@@ -1532,7 +1550,10 @@ class AuthorizerPortal(CustomerPortal):
ICP = request.env['ir.config_parameter'].sudo()
task = Task.browse(task_id)
if not task.exists() or task.technician_id.id != user.id:
if not task.exists() or (
task.technician_id.id != user.id
and user.id not in task.additional_technician_ids.ids
):
return {'success': False, 'error': 'Task not found'}
api_key = ICP.get_param('fusion_notes.openai_api_key') or ICP.get_param('fusion_claims.ai_api_key', '')
@@ -1589,7 +1610,10 @@ class AuthorizerPortal(CustomerPortal):
ICP = request.env['ir.config_parameter'].sudo()
task = Task.browse(task_id)
if not task.exists() or task.technician_id.id != user.id:
if not task.exists() or (
task.technician_id.id != user.id
and user.id not in task.additional_technician_ids.ids
):
return {'success': False, 'error': 'Task not found'}
api_key = ICP.get_param('fusion_notes.openai_api_key') or ICP.get_param('fusion_claims.ai_api_key', '')
@@ -1672,7 +1696,9 @@ class AuthorizerPortal(CustomerPortal):
tomorrow = today + timedelta(days=1)
tomorrow_tasks = Task.search([
'|',
('technician_id', '=', user.id),
('additional_technician_ids', 'in', [user.id]),
('scheduled_date', '=', tomorrow),
('status', '!=', 'cancelled'),
], order='sequence, time_start, id')
@@ -1711,7 +1737,9 @@ class AuthorizerPortal(CustomerPortal):
return request.redirect('/my/technician')
tasks = Task.search([
'|',
('technician_id', '=', user.id),
('additional_technician_ids', 'in', [user.id]),
('scheduled_date', '=', schedule_date),
('status', '!=', 'cancelled'),
], order='sequence, time_start, id')
@@ -1835,7 +1863,9 @@ class AuthorizerPortal(CustomerPortal):
if not has_access and partner.is_technician_portal:
task_count = request.env['fusion.technician.task'].sudo().search_count([
('sale_order_id', '=', order.id),
'|',
('technician_id', '=', user.id),
('additional_technician_ids', 'in', [user.id]),
])
if task_count:
has_access = True
@@ -2490,7 +2520,8 @@ class AuthorizerPortal(CustomerPortal):
if (
not task.exists()
or task.technician_id.id != user.id
or (task.technician_id.id != user.id
and user.id not in task.additional_technician_ids.ids)
or task.task_type != 'pickup'
):
return request.redirect('/my')
@@ -2515,7 +2546,8 @@ class AuthorizerPortal(CustomerPortal):
if (
not task.exists()
or task.technician_id.id != user.id
or (task.technician_id.id != user.id
and user.id not in task.additional_technician_ids.ids)
or task.task_type != 'pickup'
):
return {'success': False, 'error': 'Access denied.'}