diff --git a/README.md b/README.md
index 9e9ef55..5d16fe3 100644
--- a/README.md
+++ b/README.md
@@ -1,63 +1,63 @@
-# Web Direct Print Module for Odoo 18
-
-This module enables direct printing of reports to local printers connected to the user's computer without downloading PDF files. It uses browser printing capabilities for a seamless printing experience.
-
-## Features
-
-- Direct print from web interface to local printer
-- Integration with existing report actions
-- Browser-based printing without downloads
-- Support for all standard Odoo reports
-- Direct print button in report dialogs
-
-## Installation
-
-1. Place the `web_direct_print` folder in your Odoo addons directory
-2. Update your Odoo configuration to include this directory in `addons_path`
-3. Restart your Odoo server
-4. Install the module from Apps menu (search for "Web Direct Print")
-
-## Usage
-
-Once installed, the module works automatically with existing reports:
-
-1. When viewing a document (Invoice, Sale Order, Purchase Order, etc.), click the print button
-2. Instead of downloading a PDF, you'll see options to print directly
-3. Select "Direct Print" to send the report directly to your default printer
-4. The browser's print dialog will appear, allowing you to select your printer and print settings
-
-## Technical Details
-
-The module works by:
-
-1. Intercepting report generation requests
-2. Converting reports to PDF in the backend
-3. Sending the PDF data to the browser as a blob
-4. Using JavaScript to create a temporary iframe with the PDF
-5. Calling the browser's print function on the iframe
-
-## Browser Compatibility
-
-This module relies on browser printing capabilities, which are available in all modern browsers (Chrome, Firefox, Safari, Edge). For best results, use the latest version of your preferred browser.
-
-## Troubleshooting
-
-### Browser Settings
-Make sure your browser allows popups from your Odoo instance, as some browsers may block the print dialog.
-
-### Printer Access
-The module sends print jobs to the browser's default printer. Users can change printer settings in the browser's print dialog.
-
-### Security Restrictions
-Some browsers may have security restrictions that prevent direct printing. If direct print doesn't work, the module will fall back to opening the report in a new tab where users can manually print using Ctrl+P.
-
-## Limitations
-
-- Requires user to have a local printer configured
-- Browser-dependent functionality
-- May not work in all network configurations
-- Users need to confirm print dialog (cannot print silently)
-
-## Security
-
+# Web Direct Print Module for Odoo 18
+
+This module enables direct printing of reports to local printers connected to the user's computer without downloading PDF files. It uses browser printing capabilities for a seamless printing experience.
+
+## Features
+
+- Direct print from web interface to local printer
+- Integration with existing report actions
+- Browser-based printing without downloads
+- Support for all standard Odoo reports
+- Direct print button in report dialogs
+
+## Installation
+
+1. Place the `web_direct_print` folder in your Odoo addons directory
+2. Update your Odoo configuration to include this directory in `addons_path`
+3. Restart your Odoo server
+4. Install the module from Apps menu (search for "Web Direct Print")
+
+## Usage
+
+Once installed, the module works automatically with existing reports:
+
+1. When viewing a document (Invoice, Sale Order, Purchase Order, etc.), click the print button
+2. Instead of downloading a PDF, you'll see options to print directly
+3. Select "Direct Print" to send the report directly to your default printer
+4. The browser's print dialog will appear, allowing you to select your printer and print settings
+
+## Technical Details
+
+The module works by:
+
+1. Intercepting report generation requests
+2. Converting reports to PDF in the backend
+3. Sending the PDF data to the browser as a blob
+4. Using JavaScript to create a temporary iframe with the PDF
+5. Calling the browser's print function on the iframe
+
+## Browser Compatibility
+
+This module relies on browser printing capabilities, which are available in all modern browsers (Chrome, Firefox, Safari, Edge). For best results, use the latest version of your preferred browser.
+
+## Troubleshooting
+
+### Browser Settings
+Make sure your browser allows popups from your Odoo instance, as some browsers may block the print dialog.
+
+### Printer Access
+The module sends print jobs to the browser's default printer. Users can change printer settings in the browser's print dialog.
+
+### Security Restrictions
+Some browsers may have security restrictions that prevent direct printing. If direct print doesn't work, the module will fall back to opening the report in a new tab where users can manually print using Ctrl+P.
+
+## Limitations
+
+- Requires user to have a local printer configured
+- Browser-dependent functionality
+- May not work in all network configurations
+- Users need to confirm print dialog (cannot print silently)
+
+## Security
+
The module follows Odoo's security model and only allows users to print documents they have access to.
\ No newline at end of file
diff --git a/__init__.py b/__init__.py
index 38718f0..af57e79 100644
--- a/__init__.py
+++ b/__init__.py
@@ -1,2 +1,2 @@
-from . import models
+from . import models
from . import controllers
\ No newline at end of file
diff --git a/__manifest__.py b/__manifest__.py
index 83fea89..5167361 100644
--- a/__manifest__.py
+++ b/__manifest__.py
@@ -1,58 +1,58 @@
-{
- 'name': 'Web Direct Print',
- 'version': '18.0.1.0.0',
- 'category': 'Extra Tools',
- 'summary': 'Enable direct printing from web browser to local printers',
- 'description': """
- This module enables direct printing of reports to local printers
- connected to the user's computer without downloading PDF files.
- Uses browser printing capabilities for seamless printing experience.
-
- Features:
- • Sales: Direct print quotations and sales orders
- • Purchase: Direct print purchase orders and vendor bills
- • Inventory: Direct print delivery slips, picking operations, internal transfers, receipts
- • Accounting: Direct print customer invoices, vendor bills, payment receipts, account statements
- • Stock Management: Direct print stock moves, inventory valuation, package contents
-
- Supported Reports:
- - Sales Orders & Quotations
- - Purchase Orders & RFQs
- - Customer Invoices & Credit Notes
- - Vendor Bills & Credit Notes
- - Delivery Orders & Picking Lists
- - Internal Transfers & Receipts
- - Payment Receipts & Statements
- - Stock Moves & Inventory Reports
- - Package & Lot Tracking Labels
- """,
- 'author': 'Suherdy Yacob',
- 'depends': [
- 'base',
- 'web',
- 'account',
- 'sale',
- 'purchase',
- 'stock',
- ],
- 'data': [
- 'data/ir_actions_server.xml',
- 'views/direct_print_templates.xml',
- 'views/sale_order_views.xml',
- 'views/sale_order_form_views.xml',
- 'views/purchase_order_views.xml',
- 'views/purchase_order_form_views.xml',
- 'views/stock_picking_views.xml',
- 'views/stock_picking_form_views.xml',
- 'views/account_move_views.xml',
- ],
- 'assets': {
- 'web.assets_backend': [
- 'web_direct_print/static/src/js/direct_print.js',
- 'web_direct_print/static/src/xml/direct_print.xml',
- ],
- },
- 'installable': True,
- 'auto_install': False,
- 'license': 'LGPL-3',
+{
+ 'name': 'Web Direct Print',
+ 'version': '18.0.1.0.0',
+ 'category': 'Extra Tools',
+ 'summary': 'Enable direct printing from web browser to local printers',
+ 'description': """
+ This module enables direct printing of reports to local printers
+ connected to the user's computer without downloading PDF files.
+ Uses browser printing capabilities for seamless printing experience.
+
+ Features:
+ • Sales: Direct print quotations and sales orders
+ • Purchase: Direct print purchase orders and vendor bills
+ • Inventory: Direct print delivery slips, picking operations, internal transfers, receipts
+ • Accounting: Direct print customer invoices, vendor bills, payment receipts, account statements
+ • Stock Management: Direct print stock moves, inventory valuation, package contents
+
+ Supported Reports:
+ - Sales Orders & Quotations
+ - Purchase Orders & RFQs
+ - Customer Invoices & Credit Notes
+ - Vendor Bills & Credit Notes
+ - Delivery Orders & Picking Lists
+ - Internal Transfers & Receipts
+ - Payment Receipts & Statements
+ - Stock Moves & Inventory Reports
+ - Package & Lot Tracking Labels
+ """,
+ 'author': 'Suherdy Yacob',
+ 'depends': [
+ 'base',
+ 'web',
+ 'account',
+ 'sale',
+ 'purchase',
+ 'stock',
+ ],
+ 'data': [
+ 'data/ir_actions_server.xml',
+ 'views/direct_print_templates.xml',
+ 'views/sale_order_views.xml',
+ 'views/sale_order_form_views.xml',
+ 'views/purchase_order_views.xml',
+ 'views/purchase_order_form_views.xml',
+ 'views/stock_picking_views.xml',
+ 'views/stock_picking_form_views.xml',
+ 'views/account_move_views.xml',
+ ],
+ 'assets': {
+ 'web.assets_backend': [
+ 'web_direct_print/static/src/js/direct_print.js',
+ 'web_direct_print/static/src/xml/direct_print.xml',
+ ],
+ },
+ 'installable': True,
+ 'auto_install': False,
+ 'license': 'LGPL-3',
}
\ No newline at end of file
diff --git a/__pycache__/__init__.cpython-310.pyc b/__pycache__/__init__.cpython-310.pyc
new file mode 100644
index 0000000..e1fb1db
Binary files /dev/null and b/__pycache__/__init__.cpython-310.pyc differ
diff --git a/controllers/__pycache__/__init__.cpython-310.pyc b/controllers/__pycache__/__init__.cpython-310.pyc
new file mode 100644
index 0000000..04a9dea
Binary files /dev/null and b/controllers/__pycache__/__init__.cpython-310.pyc differ
diff --git a/controllers/__pycache__/main.cpython-310.pyc b/controllers/__pycache__/main.cpython-310.pyc
new file mode 100644
index 0000000..551114e
Binary files /dev/null and b/controllers/__pycache__/main.cpython-310.pyc differ
diff --git a/controllers/main.py b/controllers/main.py
index 668804b..01b6140 100644
--- a/controllers/main.py
+++ b/controllers/main.py
@@ -1,90 +1,90 @@
-from odoo import http
-from odoo.http import request
-import json
-import base64
-
-
-class DirectPrintController(http.Controller):
-
- @http.route('/web/direct_print', type='json', auth='user')
- def direct_print(self, report_name, docids, data=None):
- """
- Controller method to handle direct print requests
- :param report_name: Name of the report to print
- :param docids: IDs of documents to print
- :param data: Additional data for the report
- :return: JSON response with print data
- """
- try:
- import logging
- _logger = logging.getLogger(__name__)
- _logger.info(f"Controller received: report_name={report_name} (type: {type(report_name)}), docids={docids} (type: {type(docids)}), data={data}")
-
- # Handle parameters that might come as different types
- if isinstance(report_name, list):
- report_name = report_name[0] if report_name else ''
-
- if isinstance(docids, str):
- try:
- # Try to convert string to list of integers
- if ',' in docids:
- docids = [int(x.strip()) for x in docids.split(',') if x.strip()]
- else:
- docids = [int(docids)]
- except ValueError:
- docids = []
- elif not isinstance(docids, list):
- docids = [docids] if docids else []
-
- _logger.info(f"Processed parameters: report_name={report_name}, docids={docids}")
-
- # Call the direct print model method with proper context
- result = request.env['web.direct.print'].sudo().direct_print_action(
- report_name, docids, data, context=request.context
- )
- return result
- except Exception as e:
- import logging
- _logger = logging.getLogger(__name__)
- _logger.error(f"Controller error: {str(e)}")
- _logger.exception("Full traceback:")
- return {
- 'success': False,
- 'error': str(e)
- }
-
- @http.route('/web/direct_print/get_reports', type='json', auth='user')
- def get_available_reports(self):
- """
- Controller method to get available reports for direct printing
- :return: JSON response with available reports
- """
- try:
- result = request.env['web.direct.print'].sudo().get_available_reports()
- return result
- except Exception as e:
- return {
- 'success': False,
- 'error': str(e)
- }
-
- @http.route('/web/direct_print/test', type='http', auth='user', website=True)
- def test_direct_print(self, **kwargs):
- """
- Test endpoint for direct printing functionality
- """
- # This could be used for testing purposes
- html_content = """
-
-
-
- Direct Print Test
-
-
-
Direct Print Test Page
-
This page demonstrates the direct print functionality.
-
-
-
- """
+from odoo import http
+from odoo.http import request
+import json
+import base64
+
+
+class DirectPrintController(http.Controller):
+
+ @http.route('/web/direct_print', type='json', auth='user')
+ def direct_print(self, report_name, docids, data=None):
+ """
+ Controller method to handle direct print requests
+ :param report_name: Name of the report to print
+ :param docids: IDs of documents to print
+ :param data: Additional data for the report
+ :return: JSON response with print data
+ """
+ try:
+ import logging
+ _logger = logging.getLogger(__name__)
+ _logger.info(f"Controller received: report_name={report_name} (type: {type(report_name)}), docids={docids} (type: {type(docids)}), data={data}")
+
+ # Handle parameters that might come as different types
+ if isinstance(report_name, list):
+ report_name = report_name[0] if report_name else ''
+
+ if isinstance(docids, str):
+ try:
+ # Try to convert string to list of integers
+ if ',' in docids:
+ docids = [int(x.strip()) for x in docids.split(',') if x.strip()]
+ else:
+ docids = [int(docids)]
+ except ValueError:
+ docids = []
+ elif not isinstance(docids, list):
+ docids = [docids] if docids else []
+
+ _logger.info(f"Processed parameters: report_name={report_name}, docids={docids}")
+
+ # Call the direct print model method with proper context
+ result = request.env['web.direct.print'].sudo().direct_print_action(
+ report_name, docids, data, context=request.context
+ )
+ return result
+ except Exception as e:
+ import logging
+ _logger = logging.getLogger(__name__)
+ _logger.error(f"Controller error: {str(e)}")
+ _logger.exception("Full traceback:")
+ return {
+ 'success': False,
+ 'error': str(e)
+ }
+
+ @http.route('/web/direct_print/get_reports', type='json', auth='user')
+ def get_available_reports(self):
+ """
+ Controller method to get available reports for direct printing
+ :return: JSON response with available reports
+ """
+ try:
+ result = request.env['web.direct.print'].sudo().get_available_reports()
+ return result
+ except Exception as e:
+ return {
+ 'success': False,
+ 'error': str(e)
+ }
+
+ @http.route('/web/direct_print/test', type='http', auth='user', website=True)
+ def test_direct_print(self, **kwargs):
+ """
+ Test endpoint for direct printing functionality
+ """
+ # This could be used for testing purposes
+ html_content = """
+
+
+
+ Direct Print Test
+
+
+
Direct Print Test Page
+
This page demonstrates the direct print functionality.
+
+
+
+ """
return html_content
\ No newline at end of file
diff --git a/data/ir_actions_server.xml b/data/ir_actions_server.xml
index 756d11a..eb37416 100644
--- a/data/ir_actions_server.xml
+++ b/data/ir_actions_server.xml
@@ -1,16 +1,16 @@
-
-
-
-
-
- Direct Print
-
- code
-
-if object:
- action = env['web.direct.print'].direct_print_action(object.report_name, env.context.get('active_ids', []), context=env.context)
-
-
-
-
+
+
+
+
+
+ Direct Print
+
+ code
+
+if object:
+ action = env['web.direct.print'].direct_print_action(object.report_name, env.context.get('active_ids', []), context=env.context)
+
+
+
+
\ No newline at end of file
diff --git a/models/__init__.py b/models/__init__.py
index bd0fadf..d50d46a 100644
--- a/models/__init__.py
+++ b/models/__init__.py
@@ -1,4 +1,4 @@
-from . import direct_print
-from . import stock_picking
-from . import sale_order
+from . import direct_print
+from . import stock_picking
+from . import sale_order
from . import purchase_order
\ No newline at end of file
diff --git a/models/__pycache__/__init__.cpython-310.pyc b/models/__pycache__/__init__.cpython-310.pyc
new file mode 100644
index 0000000..7d75823
Binary files /dev/null and b/models/__pycache__/__init__.cpython-310.pyc differ
diff --git a/models/__pycache__/direct_print.cpython-310.pyc b/models/__pycache__/direct_print.cpython-310.pyc
new file mode 100644
index 0000000..09955f4
Binary files /dev/null and b/models/__pycache__/direct_print.cpython-310.pyc differ
diff --git a/models/__pycache__/purchase_order.cpython-310.pyc b/models/__pycache__/purchase_order.cpython-310.pyc
new file mode 100644
index 0000000..6961c43
Binary files /dev/null and b/models/__pycache__/purchase_order.cpython-310.pyc differ
diff --git a/models/__pycache__/sale_order.cpython-310.pyc b/models/__pycache__/sale_order.cpython-310.pyc
new file mode 100644
index 0000000..f01ca14
Binary files /dev/null and b/models/__pycache__/sale_order.cpython-310.pyc differ
diff --git a/models/__pycache__/stock_picking.cpython-310.pyc b/models/__pycache__/stock_picking.cpython-310.pyc
new file mode 100644
index 0000000..e7d19d9
Binary files /dev/null and b/models/__pycache__/stock_picking.cpython-310.pyc differ
diff --git a/models/direct_print.py b/models/direct_print.py
index 0175913..6116a58 100644
--- a/models/direct_print.py
+++ b/models/direct_print.py
@@ -1,212 +1,212 @@
-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)
+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)
}
\ No newline at end of file
diff --git a/models/purchase_order.py b/models/purchase_order.py
index 7dc7b49..d8dde40 100644
--- a/models/purchase_order.py
+++ b/models/purchase_order.py
@@ -1,18 +1,18 @@
-from odoo import models, fields, api
-
-
-class PurchaseOrder(models.Model):
- _inherit = 'purchase.order'
-
- def action_direct_print_purchase_order(self):
- """
- Direct print action for purchase orders and RFQs
- """
- return {
- 'type': 'ir.actions.client',
- 'tag': 'direct_print',
- 'name': 'Direct Print Purchase Order',
- 'report_name': 'purchase.report_purchaseorder',
- 'docids': self.ids,
- 'context': self.env.context,
+from odoo import models, fields, api
+
+
+class PurchaseOrder(models.Model):
+ _inherit = 'purchase.order'
+
+ def action_direct_print_purchase_order(self):
+ """
+ Direct print action for purchase orders and RFQs
+ """
+ return {
+ 'type': 'ir.actions.client',
+ 'tag': 'direct_print',
+ 'name': 'Direct Print Purchase Order',
+ 'report_name': 'purchase.report_purchaseorder',
+ 'docids': self.ids,
+ 'context': self.env.context,
}
\ No newline at end of file
diff --git a/models/sale_order.py b/models/sale_order.py
index 8f98cf6..b84c398 100644
--- a/models/sale_order.py
+++ b/models/sale_order.py
@@ -1,18 +1,18 @@
-from odoo import models, fields, api
-
-
-class SaleOrder(models.Model):
- _inherit = 'sale.order'
-
- def action_direct_print_quotation(self):
- """
- Direct print action for sale orders and quotations
- """
- return {
- 'type': 'ir.actions.client',
- 'tag': 'direct_print',
- 'name': 'Direct Print Quotation/Order',
- 'report_name': 'sale.report_saleorder',
- 'docids': self.ids,
- 'context': self.env.context,
+from odoo import models, fields, api
+
+
+class SaleOrder(models.Model):
+ _inherit = 'sale.order'
+
+ def action_direct_print_quotation(self):
+ """
+ Direct print action for sale orders and quotations
+ """
+ return {
+ 'type': 'ir.actions.client',
+ 'tag': 'direct_print',
+ 'name': 'Direct Print Quotation/Order',
+ 'report_name': 'sale.report_saleorder',
+ 'docids': self.ids,
+ 'context': self.env.context,
}
\ No newline at end of file
diff --git a/models/stock_picking.py b/models/stock_picking.py
index febce5d..caee3f6 100644
--- a/models/stock_picking.py
+++ b/models/stock_picking.py
@@ -1,56 +1,56 @@
-from odoo import models, fields, api
-import json
-
-
-class StockPicking(models.Model):
- _inherit = 'stock.picking'
-
- def action_direct_print_receipt(self):
- """
- Direct print action for stock picking receipts
- """
- # Determine the appropriate report based on picking type
- if self.picking_type_id.code == 'incoming':
- report_name = 'stock.action_report_delivery'
- elif self.picking_type_id.code == 'outgoing':
- report_name = 'stock.action_report_delivery'
- elif self.picking_type_id.code == 'internal':
- report_name = 'stock.action_report_picking'
- else:
- report_name = 'stock.action_report_picking'
-
- # Return client action for direct printing
- return {
- 'type': 'ir.actions.client',
- 'tag': 'direct_print',
- 'name': 'Direct Print',
- 'report_name': report_name,
- 'docids': self.ids,
- 'context': self.env.context,
- }
-
- def action_direct_print_delivery(self):
- """
- Direct print delivery slip
- """
- return {
- 'type': 'ir.actions.client',
- 'tag': 'direct_print',
- 'name': 'Direct Print Delivery',
- 'report_name': 'stock.action_report_delivery',
- 'docids': self.ids,
- 'context': self.env.context,
- }
-
- def action_direct_print_picking_operations(self):
- """
- Direct print picking operations
- """
- return {
- 'type': 'ir.actions.client',
- 'tag': 'direct_print',
- 'name': 'Direct Print Operations',
- 'report_name': 'stock.action_report_picking',
- 'docids': self.ids,
- 'context': self.env.context,
+from odoo import models, fields, api
+import json
+
+
+class StockPicking(models.Model):
+ _inherit = 'stock.picking'
+
+ def action_direct_print_receipt(self):
+ """
+ Direct print action for stock picking receipts
+ """
+ # Determine the appropriate report based on picking type
+ if self.picking_type_id.code == 'incoming':
+ report_name = 'stock.action_report_delivery'
+ elif self.picking_type_id.code == 'outgoing':
+ report_name = 'stock.action_report_delivery'
+ elif self.picking_type_id.code == 'internal':
+ report_name = 'stock.action_report_picking'
+ else:
+ report_name = 'stock.action_report_picking'
+
+ # Return client action for direct printing
+ return {
+ 'type': 'ir.actions.client',
+ 'tag': 'direct_print',
+ 'name': 'Direct Print',
+ 'report_name': report_name,
+ 'docids': self.ids,
+ 'context': self.env.context,
+ }
+
+ def action_direct_print_delivery(self):
+ """
+ Direct print delivery slip
+ """
+ return {
+ 'type': 'ir.actions.client',
+ 'tag': 'direct_print',
+ 'name': 'Direct Print Delivery',
+ 'report_name': 'stock.action_report_delivery',
+ 'docids': self.ids,
+ 'context': self.env.context,
+ }
+
+ def action_direct_print_picking_operations(self):
+ """
+ Direct print picking operations
+ """
+ return {
+ 'type': 'ir.actions.client',
+ 'tag': 'direct_print',
+ 'name': 'Direct Print Operations',
+ 'report_name': 'stock.action_report_picking',
+ 'docids': self.ids,
+ 'context': self.env.context,
}
\ No newline at end of file
diff --git a/static/src/js/direct_print.js b/static/src/js/direct_print.js
index 1c30e35..22ae1ea 100644
--- a/static/src/js/direct_print.js
+++ b/static/src/js/direct_print.js
@@ -1,216 +1,216 @@
-/** @odoo-module **/
-
-import { rpc } from "@web/core/network/rpc";
-import { _t } from "@web/core/l10n/translation";
-import { registry } from "@web/core/registry";
-import { Component } from "@odoo/owl";
-
-const actionRegistry = registry.category("actions");
-
-// Direct Print Action Handler
-class DirectPrintAction extends Component {
- static template = "web_direct_print.DirectPrintAction";
-
- async setup() {
- // This action will handle direct print requests
- const action = this.props.action;
- console.log("DirectPrintAction received action:", action);
-
- const report_name = action.report_name || action.context?.report_name || '';
- const docids = action.docids || action.context?.active_ids || [];
- const data = action.data || {};
-
- console.log("Extracted params:", { report_name, docids, data });
- await this.directPrint(report_name, docids, data);
- }
-
- async directPrint(reportName, docIds, data) {
- try {
- // Call the controller endpoint to get report data
- const result = await rpc("/web/direct_print", {
- report_name: reportName,
- docids: docIds,
- data: data || {}
- });
-
- if (result.success) {
- this.printReport(result);
- } else {
- this.env.services.notification.add(
- _t("Error: ") + (result.error || _t("Unknown error occurred")),
- { type: "danger" }
- );
- }
- } catch (error) {
- console.error("Direct print error:", error);
- this.env.services.notification.add(
- _t("Error occurred while preparing print: ") + (error.message || error),
- { type: "danger" }
- );
- }
- }
-
- printReport(printData) {
- // Create a blob from the base64 content
- const binaryString = atob(printData.content);
- const bytes = new Uint8Array(binaryString.length);
- for (let i = 0; i < binaryString.length; i++) {
- bytes[i] = binaryString.charCodeAt(i);
- }
-
- const blob = new Blob([bytes], { type: printData.content_type });
- const url = URL.createObjectURL(blob);
-
- // Create a new window with HTML that embeds the PDF and has print functionality
- const printWindow = window.open('', '_blank', 'width=800,height=600');
- if (!printWindow) {
- // If popup is blocked, show download option
- const a = document.createElement('a');
- a.href = url;
- a.download = printData.report_name + '.pdf';
- a.click();
- URL.revokeObjectURL(url);
- return;
- }
-
- // Write HTML content that will embed the PDF and automatically trigger print
- var htmlContent = '' +
- '' +
- '' +
- 'Printing Document' +
- '' +
- '' +
- '' +
- '
' +
- '
' +
- '
-
-
- `);
- printWindow.document.close();
- }
-
- // Clean up
- setTimeout(() => URL.revokeObjectURL(url), 10000);
- }
- } catch (error) {
- console.error("Direct print error:", error);
- }
+/** @odoo-module **/
+
+import { rpc } from "@web/core/network/rpc";
+import { _t } from "@web/core/l10n/translation";
+import { registry } from "@web/core/registry";
+import { Component } from "@odoo/owl";
+
+const actionRegistry = registry.category("actions");
+
+// Direct Print Action Handler
+class DirectPrintAction extends Component {
+ static template = "web_direct_print.DirectPrintAction";
+
+ async setup() {
+ // This action will handle direct print requests
+ const action = this.props.action;
+ console.log("DirectPrintAction received action:", action);
+
+ const report_name = action.report_name || action.context?.report_name || '';
+ const docids = action.docids || action.context?.active_ids || [];
+ const data = action.data || {};
+
+ console.log("Extracted params:", { report_name, docids, data });
+ await this.directPrint(report_name, docids, data);
+ }
+
+ async directPrint(reportName, docIds, data) {
+ try {
+ // Call the controller endpoint to get report data
+ const result = await rpc("/web/direct_print", {
+ report_name: reportName,
+ docids: docIds,
+ data: data || {}
+ });
+
+ if (result.success) {
+ this.printReport(result);
+ } else {
+ this.env.services.notification.add(
+ _t("Error: ") + (result.error || _t("Unknown error occurred")),
+ { type: "danger" }
+ );
+ }
+ } catch (error) {
+ console.error("Direct print error:", error);
+ this.env.services.notification.add(
+ _t("Error occurred while preparing print: ") + (error.message || error),
+ { type: "danger" }
+ );
+ }
+ }
+
+ printReport(printData) {
+ // Create a blob from the base64 content
+ const binaryString = atob(printData.content);
+ const bytes = new Uint8Array(binaryString.length);
+ for (let i = 0; i < binaryString.length; i++) {
+ bytes[i] = binaryString.charCodeAt(i);
+ }
+
+ const blob = new Blob([bytes], { type: printData.content_type });
+ const url = URL.createObjectURL(blob);
+
+ // Create a new window with HTML that embeds the PDF and has print functionality
+ const printWindow = window.open('', '_blank', 'width=800,height=600');
+ if (!printWindow) {
+ // If popup is blocked, show download option
+ const a = document.createElement('a');
+ a.href = url;
+ a.download = printData.report_name + '.pdf';
+ a.click();
+ URL.revokeObjectURL(url);
+ return;
+ }
+
+ // Write HTML content that will embed the PDF and automatically trigger print
+ var htmlContent = '' +
+ '' +
+ '' +
+ 'Printing Document' +
+ '' +
+ '' +
+ '' +
+ '