264 lines
11 KiB
Python
264 lines
11 KiB
Python
# -*- coding: utf-8 -*-
|
|
import base64
|
|
import logging
|
|
from datetime import datetime
|
|
from odoo import http, fields, _, exceptions
|
|
from odoo.http import request
|
|
from odoo.addons.portal.controllers.portal import CustomerPortal, pager as portal_pager
|
|
|
|
_logger = logging.getLogger(__name__)
|
|
|
|
def parse_html_datetime(dt_str):
|
|
if not dt_str:
|
|
return None
|
|
for fmt in (
|
|
"%Y-%m-%dT%H:%M", "%Y-%m-%dT%H:%M:%S",
|
|
"%Y-%m-%d %H:%M:%S", "%Y-%m-%d %H:%M", "%Y-%m-%d",
|
|
"%m/%d/%Y %I:%M %p", "%d/%m/%Y %I:%M %p",
|
|
"%m/%d/%Y %H:%M", "%d/%m/%Y %H:%M",
|
|
"%m/%d/%Y", "%d/%m/%Y"
|
|
):
|
|
try:
|
|
return datetime.strptime(dt_str.strip(), fmt)
|
|
except ValueError:
|
|
continue
|
|
try:
|
|
return fields.Datetime.to_datetime(dt_str)
|
|
except Exception:
|
|
return None
|
|
|
|
class EventRentalController(http.Controller):
|
|
|
|
@http.route('/rentals', type='http', auth='public', website=True)
|
|
def rental_catalog(self, search='', category=None, **post):
|
|
domain = [('is_rental', '=', True)]
|
|
if search:
|
|
domain.append(('name', 'ilike', search))
|
|
|
|
# Fetch products matching domain
|
|
products = request.env['product.template'].sudo().search(domain)
|
|
|
|
# Extract categories represented by these products to display in the filter sidebar
|
|
categories = products.mapped('categ_id')
|
|
|
|
if category:
|
|
domain.append(('categ_id', '=', int(category)))
|
|
products = request.env['product.template'].sudo().search(domain)
|
|
|
|
values = {
|
|
'products': products,
|
|
'categories': categories,
|
|
'search': search,
|
|
'current_category': int(category) if category else None,
|
|
}
|
|
return request.render('event_rental.rental_catalog_template', values)
|
|
|
|
@http.route('/rentals/<string:product_slug>', type='http', auth='public', website=True)
|
|
def rental_product_detail(self, product_slug, **post):
|
|
try:
|
|
if '-' in product_slug:
|
|
product_id = int(product_slug.split('-')[-1])
|
|
else:
|
|
product_id = int(product_slug)
|
|
except (ValueError, IndexError):
|
|
return request.not_found()
|
|
|
|
product = request.env['product.template'].sudo().browse(product_id)
|
|
if not product or not product.exists() or not product.is_rental:
|
|
return request.not_found()
|
|
|
|
return request.render('event_rental.rental_product_detail_template', {'product': product})
|
|
|
|
@http.route('/rental/request', type='http', auth='public', website=True, methods=['GET', 'POST'])
|
|
def rental_request(self, product_id=None, **post):
|
|
if request.httprequest.method == 'GET':
|
|
selected_product = None
|
|
if product_id:
|
|
# Browse product product variant
|
|
product_tmpl = request.env['product.template'].sudo().browse(int(product_id))
|
|
selected_product = product_tmpl.product_variant_id
|
|
all_products = request.env['product.product'].sudo().search([('is_rental', '=', True)])
|
|
return request.render('event_rental.rental_request_form_template', {
|
|
'all_products': all_products,
|
|
'selected_product': selected_product,
|
|
'error_message': None,
|
|
'post': post
|
|
})
|
|
|
|
# Process POST request
|
|
try:
|
|
_logger.info("RENTAL REQUEST POST PARAMS (product_id=%s): %s", product_id, post)
|
|
customer_name = post.get('customer_name')
|
|
customer_email = post.get('customer_email')
|
|
customer_phone = post.get('customer_phone')
|
|
company_name = post.get('company_name')
|
|
customer_address = post.get('customer_address')
|
|
|
|
start_date_str = post.get('start_date')
|
|
end_date_str = post.get('end_date')
|
|
location = post.get('location')
|
|
event_type = post.get('event_type')
|
|
|
|
req_product_id = int(product_id or post.get('product_id') or 0)
|
|
quantity = float(post.get('quantity') or 1.0)
|
|
doc_type = post.get('doc_type', 'aadhaar')
|
|
id_proof_file = request.httprequest.files.get('id_proof')
|
|
|
|
# Simple UI checks
|
|
if not customer_name or not customer_email or not customer_phone or not start_date_str or not end_date_str or not location or not req_product_id:
|
|
raise ValueError(_("All required fields must be filled."))
|
|
|
|
if not id_proof_file or id_proof_file.filename == '':
|
|
raise ValueError(_("Please upload a valid Government ID Proof document."))
|
|
|
|
start_date = parse_html_datetime(start_date_str)
|
|
end_date = parse_html_datetime(end_date_str)
|
|
|
|
if not start_date or not end_date:
|
|
raise ValueError(_("Invalid start or end date format."))
|
|
|
|
if start_date >= end_date:
|
|
raise ValueError(_("Event Start Date must be earlier than End Date."))
|
|
|
|
product = request.env['product.product'].sudo().browse(req_product_id)
|
|
if not product:
|
|
raise ValueError(_("Invalid rental product selected."))
|
|
|
|
# Availability checking bypassed per request
|
|
# dummy_request = request.env['event.rental.request'].sudo()
|
|
# available_qty = dummy_request.check_availability(start_date, end_date, product)
|
|
#
|
|
# if available_qty < quantity:
|
|
# raise ValueError(_("Product '%s' is not available in the quantity requested (%s) for the selected dates. Only %s units are currently available.") % (
|
|
# product.name, quantity, available_qty
|
|
# ))
|
|
|
|
# Find or create partner
|
|
partner = request.env['res.partner'].sudo().search([('email', '=', customer_email)], limit=1)
|
|
if not partner:
|
|
partner = request.env['res.partner'].sudo().create({
|
|
'name': customer_name,
|
|
'email': customer_email,
|
|
'phone': customer_phone,
|
|
'company_name': company_name,
|
|
'street': customer_address,
|
|
})
|
|
|
|
# Create rental request record
|
|
rental_request = request.env['event.rental.request'].sudo().create({
|
|
'partner_id': partner.id,
|
|
'customer_name': customer_name,
|
|
'customer_email': customer_email,
|
|
'customer_phone': customer_phone,
|
|
'company_name': company_name,
|
|
'customer_address': customer_address,
|
|
'start_date': start_date,
|
|
'end_date': end_date,
|
|
'location': location,
|
|
'event_type': event_type,
|
|
'status': 'under_review',
|
|
})
|
|
|
|
# Create request line
|
|
request.env['event.rental.line'].sudo().create({
|
|
'request_id': rental_request.id,
|
|
'product_id': product.id,
|
|
'quantity': quantity,
|
|
})
|
|
|
|
# Store ID proof attachment
|
|
file_content = id_proof_file.read()
|
|
file_base64 = base64.b64encode(file_content)
|
|
attachment = request.env['ir.attachment'].sudo().create({
|
|
'name': id_proof_file.filename,
|
|
'type': 'binary',
|
|
'datas': file_base64,
|
|
'res_model': 'event.rental.request',
|
|
'res_id': rental_request.id,
|
|
})
|
|
|
|
# Create document record
|
|
request.env['event.document'].sudo().create({
|
|
'request_id': rental_request.id,
|
|
'partner_id': partner.id,
|
|
'doc_type': doc_type,
|
|
'attachment_id': attachment.id,
|
|
'verification_status': 'pending',
|
|
})
|
|
|
|
# Post submission trace
|
|
rental_request.message_post(body=_("Rental request submitted successfully from public website."))
|
|
|
|
return request.redirect(f'/rental/request/success?name={rental_request.name}')
|
|
|
|
except Exception as e:
|
|
selected_product = None
|
|
if post.get('product_id'):
|
|
selected_product = request.env['product.product'].sudo().browse(int(post.get('product_id')))
|
|
all_products = request.env['product.product'].sudo().search([('is_rental', '=', True)])
|
|
return request.render('event_rental.rental_request_form_template', {
|
|
'all_products': all_products,
|
|
'selected_product': selected_product,
|
|
'error_message': str(e),
|
|
'post': post
|
|
})
|
|
|
|
@http.route('/rental/request/success', type='http', auth='public', website=True)
|
|
def rental_request_success(self, name, **post):
|
|
return request.render('event_rental.rental_request_success_template', {'name': name})
|
|
|
|
|
|
class CustomerPortalRental(CustomerPortal):
|
|
|
|
def _prepare_home_portal_values(self, counters):
|
|
values = super()._prepare_home_portal_values(counters)
|
|
if 'rental_count' in counters:
|
|
partner = request.env.user.partner_id
|
|
rental_count = request.env['event.rental.request'].search_count([
|
|
('partner_id', '=', partner.id)
|
|
])
|
|
values['rental_count'] = rental_count
|
|
return values
|
|
|
|
@http.route(['/my/rentals', '/my/rentals/page/<int:page>'], type='http', auth="user", website=True)
|
|
def portal_my_rentals(self, page=1, date_begin=None, date_end=None, sortby=None, **kw):
|
|
values = self._prepare_portal_layout_values()
|
|
partner = request.env.user.partner_id
|
|
RentalRequest = request.env['event.rental.request']
|
|
domain = [('partner_id', '=', partner.id)]
|
|
|
|
# Count for pagination
|
|
rental_count = RentalRequest.search_count(domain)
|
|
pager = portal_pager(
|
|
url="/my/rentals",
|
|
total=rental_count,
|
|
page=page,
|
|
step=10
|
|
)
|
|
|
|
requests = RentalRequest.search(domain, limit=10, offset=pager['offset'])
|
|
|
|
values.update({
|
|
'requests': requests,
|
|
'page_name': 'rental_requests',
|
|
'pager': pager,
|
|
'default_url': '/my/rentals',
|
|
})
|
|
return request.render("event_rental.portal_my_rental_requests", values)
|
|
|
|
@http.route(['/my/rentals/<int:request_id>'], type='http', auth="user", website=True)
|
|
def portal_rental_request_detail(self, request_id, **kw):
|
|
rental_request = request.env['event.rental.request'].browse(request_id)
|
|
try:
|
|
# Enforce native record rules / access rights
|
|
rental_request.check_access_rights('read')
|
|
rental_request.check_access_rule('read')
|
|
except exceptions.AccessError:
|
|
return request.redirect('/my')
|
|
|
|
values = {
|
|
'rental_request': rental_request,
|
|
'page_name': 'rental_request_detail',
|
|
}
|
|
return request.render("event_rental.portal_rental_request_detail_template", values)
|