Files
gsinghpal e56974d46f update
2026-03-16 08:14:56 -04:00

270 lines
11 KiB
Python

# -*- coding: utf-8 -*-
# Copyright 2024-2026 Nexa Systems Inc.
# License OPL-1 (Odoo Proprietary License v1.0)
from odoo import http
from odoo.http import request
import logging
_logger = logging.getLogger(__name__)
class LoanerPortalController(http.Controller):
@http.route('/my/loaner/categories', type='jsonrpc', auth='user', website=True)
def portal_loaner_categories(self, **kw):
parent = request.env.ref(
'fusion_loaners_management.product_category_loaner',
raise_if_not_found=False,
)
if not parent:
return []
categories = request.env['product.category'].sudo().search([
('parent_id', '=', parent.id),
], order='name')
return [{'id': c.id, 'name': c.name} for c in categories]
@http.route('/my/loaner/products', type='jsonrpc', auth='user', website=True)
def portal_loaner_products(self, **kw):
domain = [('x_fc_can_be_loaned', '=', True)]
category_id = kw.get('category_id')
if category_id:
domain.append(('categ_id', '=', int(category_id)))
products = request.env['product.product'].sudo().search(domain)
loaner_location = request.env.ref(
'fusion_loaners_management.stock_location_loaner',
raise_if_not_found=False,
)
result = []
for p in products:
lots = []
if loaner_location:
quants = request.env['stock.quant'].sudo().search([
('product_id', '=', p.id),
('location_id', '=', loaner_location.id),
('quantity', '>', 0),
])
for q in quants:
if q.lot_id:
lots.append({'id': q.lot_id.id, 'name': q.lot_id.name})
result.append({
'id': p.id,
'name': p.name,
'category_id': p.categ_id.id,
'period_days': p.product_tmpl_id.x_fc_loaner_period_days or 7,
'lots': lots,
})
return result
@http.route('/my/loaner/locations', type='jsonrpc', auth='user', website=True)
def portal_loaner_locations(self, **kw):
locations = request.env['stock.location'].sudo().search([
('usage', '=', 'internal'),
('company_id', '=', request.env.company.id),
])
return [{'id': loc.id, 'name': loc.complete_name} for loc in locations]
@http.route('/my/loaner/equipment-locations', type='jsonrpc', auth='user', website=True)
def portal_equipment_locations(self, **kw):
"""Return current location of all loaner equipment for the portal."""
partner = request.env.user.partner_id
if not (hasattr(partner, 'is_sales_rep_portal') and partner.is_sales_rep_portal) and \
not (hasattr(partner, 'is_authorizer') and partner.is_authorizer):
return {'error': 'Unauthorized'}
products = request.env['product.product'].sudo().search([
('x_fc_can_be_loaned', '=', True),
])
loaner_location = request.env.ref(
'fusion_loaners_management.stock_location_loaner',
raise_if_not_found=False,
)
result = []
for p in products:
quants = request.env['stock.quant'].sudo().search([
('product_id', '=', p.id),
('quantity', '>', 0),
])
for q in quants:
result.append({
'product_id': p.id,
'product_name': p.name,
'lot_id': q.lot_id.id if q.lot_id else False,
'serial_number': q.lot_id.name if q.lot_id else '',
'location_id': q.location_id.id,
'location_name': q.location_id.complete_name,
'quantity': q.quantity,
'is_loaner_stock': q.location_id.id == loaner_location.id if loaner_location else False,
})
return result
@http.route('/my/loaner/checkout', type='jsonrpc', auth='user', website=True)
def portal_loaner_checkout(self, **kw):
partner = request.env.user.partner_id
if not (hasattr(partner, 'is_sales_rep_portal') and partner.is_sales_rep_portal) and \
not (hasattr(partner, 'is_authorizer') and partner.is_authorizer):
return {'error': 'Unauthorized'}
product_id = int(kw.get('product_id', 0))
lot_id = int(kw.get('lot_id', 0)) if kw.get('lot_id') else False
sale_order_id = int(kw.get('sale_order_id', 0)) if kw.get('sale_order_id') else False
client_id = int(kw.get('client_id', 0)) if kw.get('client_id') else False
loaner_period = int(kw.get('loaner_period_days', 7))
condition = kw.get('checkout_condition', 'good')
notes = kw.get('checkout_notes', '')
if not product_id:
return {'error': 'Product is required'}
vals = {
'product_id': product_id,
'loaner_period_days': loaner_period,
'checkout_condition': condition,
'checkout_notes': notes,
'sales_rep_id': request.env.user.id,
}
if lot_id:
vals['lot_id'] = lot_id
if sale_order_id:
so = request.env['sale.order'].sudo().browse(sale_order_id)
if so.exists():
vals['sale_order_id'] = so.id
vals['partner_id'] = so.partner_id.id
if hasattr(so, 'x_fc_authorizer_id') and so.x_fc_authorizer_id:
vals['authorizer_id'] = so.x_fc_authorizer_id.id
vals['delivery_address'] = so.partner_shipping_id.contact_address if so.partner_shipping_id else ''
if client_id and not vals.get('partner_id'):
vals['partner_id'] = client_id
if not vals.get('partner_id'):
return {'error': 'Client is required'}
try:
checkout = request.env['fusion.loaner.checkout'].sudo().create(vals)
checkout.action_checkout()
return {
'success': True,
'checkout_id': checkout.id,
'name': checkout.name,
'message': f'Loaner {checkout.name} checked out successfully',
}
except Exception as e:
_logger.error(f"Loaner checkout error: {e}")
return {'error': str(e)}
@http.route('/my/loaner/create-product', type='jsonrpc', auth='user', website=True)
def portal_loaner_create_product(self, **kw):
partner = request.env.user.partner_id
if not (hasattr(partner, 'is_sales_rep_portal') and partner.is_sales_rep_portal) and \
not (hasattr(partner, 'is_authorizer') and partner.is_authorizer):
return {'error': 'Unauthorized'}
product_name = kw.get('product_name', '').strip()
serial_number = kw.get('serial_number', '').strip()
if not product_name:
return {'error': 'Product name is required'}
if not serial_number:
return {'error': 'Serial number is required'}
try:
category_id = kw.get('category_id')
category = None
if category_id:
category = request.env['product.category'].sudo().browse(int(category_id))
if not category.exists():
category = None
if not category:
category = request.env.ref(
'fusion_loaners_management.product_category_loaner',
raise_if_not_found=False,
)
if not category:
category = request.env['product.category'].sudo().search([
('name', '=', 'Loaner Equipment'),
], limit=1)
if not category:
category = request.env['product.category'].sudo().create({
'name': 'Loaner Equipment',
})
product_tmpl = request.env['product.template'].sudo().create({
'name': product_name,
'type': 'consu',
'tracking': 'serial',
'categ_id': category.id,
'x_fc_can_be_loaned': True,
'x_fc_loaner_period_days': 7,
'sale_ok': False,
'purchase_ok': False,
})
product = product_tmpl.product_variant_id
lot = request.env['stock.lot'].sudo().create({
'name': serial_number,
'product_id': product.id,
'company_id': request.env.company.id,
})
loaner_location = request.env.ref(
'fusion_loaners_management.stock_location_loaner',
raise_if_not_found=False,
)
if loaner_location:
request.env['stock.quant'].sudo().create({
'product_id': product.id,
'location_id': loaner_location.id,
'lot_id': lot.id,
'quantity': 1,
})
return {
'success': True,
'product_id': product.id,
'product_name': product.name,
'lot_id': lot.id,
'lot_name': lot.name,
}
except Exception as e:
_logger.error(f"Loaner product creation error: {e}")
return {'error': str(e)}
@http.route('/my/loaner/return', type='jsonrpc', auth='user', website=True)
def portal_loaner_return(self, **kw):
partner = request.env.user.partner_id
if not (hasattr(partner, 'is_sales_rep_portal') and partner.is_sales_rep_portal) and \
not (hasattr(partner, 'is_authorizer') and partner.is_authorizer):
return {'error': 'Unauthorized'}
checkout_id = int(kw.get('checkout_id', 0))
return_condition = kw.get('return_condition', 'good')
return_notes = kw.get('return_notes', '')
return_location_id = int(kw.get('return_location_id', 0)) if kw.get('return_location_id') else None
if not checkout_id:
return {'error': 'Checkout ID is required'}
try:
checkout = request.env['fusion.loaner.checkout'].sudo().browse(checkout_id)
if not checkout.exists():
return {'error': 'Checkout not found'}
if checkout.state not in ('checked_out', 'overdue', 'rental_pending'):
return {'error': 'This loaner is not currently checked out'}
checkout.action_process_return(
return_condition=return_condition,
return_notes=return_notes,
return_location_id=return_location_id,
)
return {
'success': True,
'message': f'Loaner {checkout.name} returned successfully',
}
except Exception as e:
_logger.error(f"Loaner return error: {e}")
return {'error': str(e)}