# -*- coding: utf-8 -*- # Copyright 2024-2026 Nexa Systems Inc. # License OPL-1 (Odoo Proprietary License v1.0) """Client maintenance booking portal. The maintenance reminder email contains a tokenized URL: /repairs/maintenance/book/ Clicking it lands the client on a single-page form where they can confirm a preferred date. On submit, a repair.order is spawned via the same intake service (source='client_portal') and the contract's next reminder band is locked so we don't keep nagging them. """ import logging from odoo import _, fields, http from odoo.http import request _logger = logging.getLogger(__name__) class MaintenanceBookingPortal(http.Controller): def _resolve_contract(self, token): if not token: return None Contract = request.env['fusion.repair.maintenance.contract'].sudo() contract = Contract.search([('booking_token', '=', token)], limit=1) if not contract or contract.state != 'active': return None return contract @http.route('/repairs/maintenance/book/', type='http', auth='public', website=True, sitemap=False) def maintenance_book_get(self, token, **kw): contract = self._resolve_contract(token) if not contract: return request.render('fusion_repairs.portal_maintenance_invalid_token', {}) already = bool(contract.booking_repair_id) return request.render('fusion_repairs.portal_maintenance_book', { 'contract': contract, 'already_booked': already, 'default_date': fields.Date.context_today(request.env.user).isoformat(), }) @http.route('/repairs/maintenance/book//confirm', type='http', auth='public', methods=['POST'], csrf=True, website=True) def maintenance_book_post(self, token, **post): contract = self._resolve_contract(token) if not contract: return request.render('fusion_repairs.portal_maintenance_invalid_token', {}) if contract.booking_repair_id: return request.redirect(f'/repairs/maintenance/book/{token}?ok=already') preferred_date = (post.get('preferred_date') or '').strip() scheduled = False if preferred_date: try: scheduled = fields.Date.from_string(preferred_date) except ValueError: scheduled = False repair = contract.create_repair_from_booking(scheduled_date=scheduled) return request.render('fusion_repairs.portal_maintenance_thanks', { 'contract': contract, 'repair': repair, })