212 lines
8.9 KiB
Python
212 lines
8.9 KiB
Python
from odoo import models, fields, api
|
|
import base64
|
|
import logging
|
|
|
|
_logger = logging.getLogger(__name__)
|
|
|
|
|
|
class DirectPrint(models.Model):
|
|
_name = 'web.direct.print'
|
|
_description = 'Web Direct Print'
|
|
|
|
@api.model
|
|
def get_report_data(self, report_name, docids, data=None):
|
|
"""
|
|
Generate report data for direct printing
|
|
:param report_name: Name of the report
|
|
:param docids: Document IDs to print
|
|
:param data: Additional report data
|
|
:return: Report content in base64
|
|
"""
|
|
try:
|
|
_logger.info(f"get_report_data called with report_name={report_name} (type: {type(report_name)}), docids={docids} (type: {type(docids)})")
|
|
|
|
# Handle report_name parameter - it could be a string, list, or ID
|
|
if isinstance(report_name, list):
|
|
if report_name and isinstance(report_name[0], int):
|
|
# It's a list of IDs, get the report by ID
|
|
report = self.env['ir.actions.report'].browse(report_name[0])
|
|
else:
|
|
# It's a list with string names
|
|
report_name_str = report_name[0] if report_name else ''
|
|
report = self.env['ir.actions.report'].search([('report_name', '=', report_name_str)], limit=1)
|
|
elif isinstance(report_name, int):
|
|
# It's an ID
|
|
report = self.env['ir.actions.report'].browse(report_name)
|
|
elif isinstance(report_name, str):
|
|
# It's a string name - try to find by report_name or use env.ref
|
|
if '.' in report_name:
|
|
# It looks like a module.xml_id format, try env.ref first
|
|
try:
|
|
ref_obj = self.env.ref(report_name)
|
|
# Check if the referenced object is actually a report
|
|
if hasattr(ref_obj, '_name') and ref_obj._name == 'ir.actions.report':
|
|
report = ref_obj
|
|
else:
|
|
# It's not a report (probably a view), search by report_name instead
|
|
report = self.env['ir.actions.report'].search([('report_name', '=', report_name)], limit=1)
|
|
except ValueError:
|
|
# If env.ref fails, try searching by report_name
|
|
report = self.env['ir.actions.report'].search([('report_name', '=', report_name)], limit=1)
|
|
else:
|
|
# Search by report_name
|
|
report = self.env['ir.actions.report'].search([('report_name', '=', report_name)], limit=1)
|
|
else:
|
|
report = None
|
|
|
|
# Generate the report content
|
|
if report:
|
|
# Generate the pdf content with proper context
|
|
current_context = self.env.context.copy()
|
|
|
|
# Handle docids parameter - ensure it's a list of integers
|
|
if isinstance(docids, str):
|
|
# If it's a string, try to convert to int
|
|
try:
|
|
docids = [int(docids)]
|
|
except ValueError:
|
|
# If it contains commas, split and convert
|
|
if ',' in docids:
|
|
docids = [int(d.strip()) for d in docids.split(',') if d.strip()]
|
|
else:
|
|
docids = [int(docids)]
|
|
elif isinstance(docids, int):
|
|
docids = [docids]
|
|
elif isinstance(docids, list):
|
|
# Ensure all elements are integers
|
|
processed_ids = []
|
|
for d in docids:
|
|
if isinstance(d, str):
|
|
try:
|
|
processed_ids.append(int(d))
|
|
except ValueError:
|
|
continue
|
|
elif isinstance(d, int):
|
|
processed_ids.append(d)
|
|
docids = processed_ids
|
|
else:
|
|
docids = []
|
|
|
|
_logger.info(f"Processed docids: {docids}")
|
|
|
|
if not docids:
|
|
return {
|
|
'success': False,
|
|
'error': 'No valid document IDs provided'
|
|
}
|
|
|
|
# Use the standard Odoo report rendering approach
|
|
# Ensure report_name is a string, not a list
|
|
report_name_str = str(report.report_name) if report.report_name else report.name
|
|
_logger.info(f"Using report_name_str: {report_name_str} (type: {type(report_name_str)})")
|
|
|
|
# Generate PDF using the standard method
|
|
pdf_content, report_format = self.env['ir.actions.report'].with_context(**current_context)._render_qweb_pdf(report_name_str, docids, data or {})
|
|
|
|
# Encode the content in base64 for transmission
|
|
encoded_content = base64.b64encode(pdf_content).decode('utf-8')
|
|
|
|
return {
|
|
'success': True,
|
|
'content': encoded_content,
|
|
'report_name': report_name,
|
|
'docids': docids,
|
|
'content_type': 'application/pdf'
|
|
}
|
|
else:
|
|
return {
|
|
'success': False,
|
|
'error': f'Report "{report_name}" not found'
|
|
}
|
|
except Exception as e:
|
|
_logger.error(f"Error generating report for direct print: {str(e)}")
|
|
_logger.exception("Full traceback:")
|
|
return {
|
|
'success': False,
|
|
'error': str(e)
|
|
}
|
|
|
|
@api.model
|
|
def prepare_print_data(self, report_name, docids, data=None):
|
|
"""
|
|
Prepare data for direct printing
|
|
:param report_name: Name of the report to print
|
|
:param docids: IDs of documents to print
|
|
:param data: Additional data for the report
|
|
:return: Dictionary with report data
|
|
"""
|
|
try:
|
|
result = self.get_report_data(report_name, docids, data)
|
|
return result
|
|
except Exception as e:
|
|
_logger.error(f"Error preparing print data: {str(e)}")
|
|
return {
|
|
'success': False,
|
|
'error': str(e)
|
|
}
|
|
|
|
@api.model
|
|
def get_available_reports(self):
|
|
"""
|
|
Get list of available reports for direct printing
|
|
:return: List of available reports
|
|
"""
|
|
try:
|
|
reports = self.env['ir.actions.report'].search([
|
|
('active', '=', True),
|
|
('report_type', 'in', ['qweb-pdf', 'qweb-html'])
|
|
])
|
|
|
|
report_list = []
|
|
for report in reports:
|
|
report_list.append({
|
|
'id': report.id,
|
|
'name': report.name,
|
|
'report_name': report.report_name,
|
|
'model': report.model,
|
|
})
|
|
|
|
return {
|
|
'success': True,
|
|
'reports': report_list
|
|
}
|
|
except Exception as e:
|
|
_logger.error(f"Error getting available reports: {str(e)}")
|
|
return {
|
|
'success': False,
|
|
'error': str(e)
|
|
}
|
|
|
|
@api.model
|
|
def direct_print_action(self, report_name, docids, data=None, context=None):
|
|
"""
|
|
Execute direct print action for a given report
|
|
:param report_name: Name of the report to print
|
|
:param docids: IDs of documents to print
|
|
:param data: Additional data for the report
|
|
:param context: Context data
|
|
:return: Result of the print action
|
|
"""
|
|
try:
|
|
# Update the environment context if provided
|
|
if context:
|
|
self = self.with_context(**context)
|
|
|
|
# Prepare the print data
|
|
print_data = self.prepare_print_data(report_name, docids, data)
|
|
|
|
if print_data['success']:
|
|
# In a real implementation, we might want to add additional
|
|
# processing here, such as tracking print jobs or handling
|
|
# special printer configurations
|
|
|
|
# Return the print data for client-side processing
|
|
return print_data
|
|
else:
|
|
return print_data
|
|
except Exception as e:
|
|
_logger.error(f"Error in direct print action: {str(e)}")
|
|
return {
|
|
'success': False,
|
|
'error': str(e)
|
|
} |