This commit is contained in:
admin.suherdy 2025-11-27 10:11:39 +07:00
parent 7e5a51fa2d
commit e279e84501
29 changed files with 1140 additions and 1140 deletions

124
README.md
View File

@ -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.

View File

@ -1,2 +1,2 @@
from . import models
from . import models
from . import controllers

View File

@ -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',
}

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -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 = """
<!DOCTYPE html>
<html>
<head>
<title>Direct Print Test</title>
</head>
<body>
<h1>Direct Print Test Page</h1>
<p>This page demonstrates the direct print functionality.</p>
<button onclick="window.print()">Print this page</button>
</body>
</html>
"""
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 = """
<!DOCTYPE html>
<html>
<head>
<title>Direct Print Test</title>
</head>
<body>
<h1>Direct Print Test Page</h1>
<p>This page demonstrates the direct print functionality.</p>
<button onclick="window.print()">Print this page</button>
</body>
</html>
"""
return html_content

View File

@ -1,16 +1,16 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<data noupdate="1">
<!-- Server Action to trigger direct print -->
<record id="action_direct_print" model="ir.actions.server">
<field name="name">Direct Print</field>
<field name="model_id" ref="base.model_ir_actions_report"/>
<field name="state">code</field>
<field name="code">
if object:
action = env['web.direct.print'].direct_print_action(object.report_name, env.context.get('active_ids', []), context=env.context)
</field>
</record>
</data>
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<data noupdate="1">
<!-- Server Action to trigger direct print -->
<record id="action_direct_print" model="ir.actions.server">
<field name="name">Direct Print</field>
<field name="model_id" ref="base.model_ir_actions_report"/>
<field name="state">code</field>
<field name="code">
if object:
action = env['web.direct.print'].direct_print_action(object.report_name, env.context.get('active_ids', []), context=env.context)
</field>
</record>
</data>
</odoo>

View File

@ -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

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -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)
}

View File

@ -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,
}

View File

@ -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,
}

View File

@ -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,
}

View File

@ -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 = '<!DOCTYPE html>' +
'<html>' +
'<head>' +
'<title>Printing Document</title>' +
'<style>' +
'body, html {' +
'margin: 0;' +
'padding: 0;' +
'height: 100%;' +
'overflow: hidden;' +
'}' +
'#pdfContainer {' +
'width: 100%;' +
'height: 100vh;' +
'border: none;' +
'}' +
'</style>' +
'</head>' +
'<body>' +
'<div id="pdfContainer">' +
'<embed id="pdfEmbed" src="' + url + '" type="application/pdf" width="100%" height="100%">' +
'</div>' +
'<script>' +
'var pdfEmbed = document.getElementById("pdfEmbed");' +
'var printWindow = window;' +
'' +
'// Wait for the PDF to load and then print' +
'function attemptPrint() {' +
'try {' +
'// Method 1: Try to print directly' +
'if (printWindow.print) {' +
'printWindow.print();' +
'}' +
'} catch (e) {' +
'console.log("Direct print failed:", e);' +
'' +
'// Method 2: Try to access the embedded PDF\'s print functionality' +
'try {' +
'if (pdfEmbed && pdfEmbed.print) {' +
'pdfEmbed.print();' +
'} else {' +
'// Method 3: Try to print using document.execCommand (older method)' +
'if (document.execCommand) {' +
'document.execCommand("print", false, null);' +
'}' +
'}' +
'} catch (e2) {' +
'console.log("Alternative print methods failed:", e2);' +
'// As a last resort, show user instructions' +
'printWindow.document.body.innerHTML = \'<div style="padding: 20px;"><p>PDF loaded. Press Ctrl+P to print.</p><embed src="' + url + '" type="application/pdf" width="100%" height="90%"></div>\';' +
'}' +
'}' +
'}' +
'' +
'// Try to print immediately and at intervals' +
'setTimeout(attemptPrint, 1000); // Wait 1 second then try to print' +
'setTimeout(attemptPrint, 3000); // Try again after 3 seconds' +
'setTimeout(attemptPrint, 5000); // Try again after 5 seconds' +
'' +
'// Also try to print when the window is focused' +
'printWindow.onfocus = function() {' +
'setTimeout(attemptPrint, 500);' +
'};' +
'' +
'// Listen for afterprint to close the window if possible' +
'if (window.matchMedia) {' +
'var mediaQueryList = window.matchMedia("print");' +
'mediaQueryList.onchange = function(mql) {' +
'if (!mql.matches) {' +
'// Print dialog was closed, close the window after a delay' +
'setTimeout(function() {' +
'window.close();' +
'}, 1000);' +
'}' +
'};' +
'}' +
'' +
'</scr' + 'ipt>' + // Split to avoid issues with closing script tag
'</body>' +
'</html>';
printWindow.document.write(htmlContent);
printWindow.document.close(); // Important: Close the document to finish loading
// Clean up the URL object after some time
setTimeout(() => {
URL.revokeObjectURL(url);
}, 5000);
}
}
// Register the action
actionRegistry.add("direct_print", DirectPrintAction);
// Global function for backward compatibility
window.directPrint = async function(reportName, docIds, data) {
try {
const result = await rpc("/web/direct_print", {
report_name: reportName,
docids: docIds,
data: data || {}
});
if (result.success) {
// Create a blob from the base64 content
const binaryString = atob(result.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: result.content_type });
const url = URL.createObjectURL(blob);
// Create a new window for printing
const printWindow = window.open('', '_blank', 'width=800,height=600');
if (printWindow) {
printWindow.document.write(`
<!DOCTYPE html>
<html>
<head><title>Print</title></head>
<body style="margin:0;">
<embed src="${url}" type="application/pdf" width="100%" height="100%">
<script>
setTimeout(() => { window.print(); }, 1000);
setTimeout(() => { window.close(); }, 5000);
</script>
</body>
</html>
`);
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 = '<!DOCTYPE html>' +
'<html>' +
'<head>' +
'<title>Printing Document</title>' +
'<style>' +
'body, html {' +
'margin: 0;' +
'padding: 0;' +
'height: 100%;' +
'overflow: hidden;' +
'}' +
'#pdfContainer {' +
'width: 100%;' +
'height: 100vh;' +
'border: none;' +
'}' +
'</style>' +
'</head>' +
'<body>' +
'<div id="pdfContainer">' +
'<embed id="pdfEmbed" src="' + url + '" type="application/pdf" width="100%" height="100%">' +
'</div>' +
'<script>' +
'var pdfEmbed = document.getElementById("pdfEmbed");' +
'var printWindow = window;' +
'' +
'// Wait for the PDF to load and then print' +
'function attemptPrint() {' +
'try {' +
'// Method 1: Try to print directly' +
'if (printWindow.print) {' +
'printWindow.print();' +
'}' +
'} catch (e) {' +
'console.log("Direct print failed:", e);' +
'' +
'// Method 2: Try to access the embedded PDF\'s print functionality' +
'try {' +
'if (pdfEmbed && pdfEmbed.print) {' +
'pdfEmbed.print();' +
'} else {' +
'// Method 3: Try to print using document.execCommand (older method)' +
'if (document.execCommand) {' +
'document.execCommand("print", false, null);' +
'}' +
'}' +
'} catch (e2) {' +
'console.log("Alternative print methods failed:", e2);' +
'// As a last resort, show user instructions' +
'printWindow.document.body.innerHTML = \'<div style="padding: 20px;"><p>PDF loaded. Press Ctrl+P to print.</p><embed src="' + url + '" type="application/pdf" width="100%" height="90%"></div>\';' +
'}' +
'}' +
'}' +
'' +
'// Try to print immediately and at intervals' +
'setTimeout(attemptPrint, 1000); // Wait 1 second then try to print' +
'setTimeout(attemptPrint, 3000); // Try again after 3 seconds' +
'setTimeout(attemptPrint, 5000); // Try again after 5 seconds' +
'' +
'// Also try to print when the window is focused' +
'printWindow.onfocus = function() {' +
'setTimeout(attemptPrint, 500);' +
'};' +
'' +
'// Listen for afterprint to close the window if possible' +
'if (window.matchMedia) {' +
'var mediaQueryList = window.matchMedia("print");' +
'mediaQueryList.onchange = function(mql) {' +
'if (!mql.matches) {' +
'// Print dialog was closed, close the window after a delay' +
'setTimeout(function() {' +
'window.close();' +
'}, 1000);' +
'}' +
'};' +
'}' +
'' +
'</scr' + 'ipt>' + // Split to avoid issues with closing script tag
'</body>' +
'</html>';
printWindow.document.write(htmlContent);
printWindow.document.close(); // Important: Close the document to finish loading
// Clean up the URL object after some time
setTimeout(() => {
URL.revokeObjectURL(url);
}, 5000);
}
}
// Register the action
actionRegistry.add("direct_print", DirectPrintAction);
// Global function for backward compatibility
window.directPrint = async function(reportName, docIds, data) {
try {
const result = await rpc("/web/direct_print", {
report_name: reportName,
docids: docIds,
data: data || {}
});
if (result.success) {
// Create a blob from the base64 content
const binaryString = atob(result.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: result.content_type });
const url = URL.createObjectURL(blob);
// Create a new window for printing
const printWindow = window.open('', '_blank', 'width=800,height=600');
if (printWindow) {
printWindow.document.write(`
<!DOCTYPE html>
<html>
<head><title>Print</title></head>
<body style="margin:0;">
<embed src="${url}" type="application/pdf" width="100%" height="100%">
<script>
setTimeout(() => { window.print(); }, 1000);
setTimeout(() => { window.close(); }, 5000);
</script>
</body>
</html>
`);
printWindow.document.close();
}
// Clean up
setTimeout(() => URL.revokeObjectURL(url), 10000);
}
} catch (error) {
console.error("Direct print error:", error);
}
};

View File

@ -1,12 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<templates id="template" xml:space="preserve">
<t t-name="web_direct_print.DirectPrintAction">
<div class="o_direct_print_action">
<!-- This template is minimal as the printing happens in setup() -->
<div class="text-center">
<i class="fa fa-spinner fa-spin fa-2x"/>
<div class="mt-2">Preparing print...</div>
</div>
</div>
</t>
<?xml version="1.0" encoding="UTF-8"?>
<templates id="template" xml:space="preserve">
<t t-name="web_direct_print.DirectPrintAction">
<div class="o_direct_print_action">
<!-- This template is minimal as the printing happens in setup() -->
<div class="text-center">
<i class="fa fa-spinner fa-spin fa-2x"/>
<div class="mt-2">Preparing print...</div>
</div>
</div>
</t>
</templates>

View File

@ -1,115 +1,115 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<data>
<!-- Customer Invoice Direct Print -->
<record id="action_direct_print_customer_invoice" model="ir.actions.server">
<field name="name">Direct Print Customer Invoice</field>
<field name="model_id" ref="account.model_account_move"/>
<field name="binding_model_id" ref="account.model_account_move"/>
<field name="binding_view_types">list,form</field>
<field name="state">code</field>
<field name="code">
if records:
# Filter for customer invoices
invoices = records.filtered(lambda r: r.move_type in ['out_invoice', 'out_refund'])
if invoices:
action = {
'type': 'ir.actions.client',
'tag': 'direct_print',
'report_name': 'account.report_invoice',
'docids': invoices.ids,
'context': env.context,
}
</field>
</record>
<!-- Vendor Bill Direct Print -->
<record id="action_direct_print_vendor_bill" model="ir.actions.server">
<field name="name">Direct Print Vendor Bill</field>
<field name="model_id" ref="account.model_account_move"/>
<field name="binding_model_id" ref="account.model_account_move"/>
<field name="binding_view_types">list,form</field>
<field name="state">code</field>
<field name="code">
if records:
# Filter for vendor bills
bills = records.filtered(lambda r: r.move_type in ['in_invoice', 'in_refund'])
if bills:
action = {
'type': 'ir.actions.client',
'tag': 'direct_print',
'report_name': 'account.report_invoice',
'docids': bills.ids,
'context': env.context,
}
</field>
</record>
<!-- Invoice with Payment Receipt Direct Print -->
<record id="action_direct_print_invoice_with_payments" model="ir.actions.server">
<field name="name">Direct Print Invoice with Payments</field>
<field name="model_id" ref="account.model_account_move"/>
<field name="binding_model_id" ref="account.model_account_move"/>
<field name="binding_view_types">list,form</field>
<field name="state">code</field>
<field name="code">
if records:
# Filter for customer invoices
invoices = records.filtered(lambda r: r.move_type in ['out_invoice'])
if invoices:
action = {
'type': 'ir.actions.client',
'tag': 'direct_print',
'report_name': 'account.report_invoice_with_payments',
'docids': invoices.ids,
'context': env.context,
}
</field>
</record>
<!-- Payment Receipt Direct Print -->
<record id="action_direct_print_payment_receipt" model="ir.actions.server">
<field name="name">Direct Print Payment Receipt</field>
<field name="model_id" ref="account.model_account_payment"/>
<field name="binding_model_id" ref="account.model_account_payment"/>
<field name="binding_view_types">list,form</field>
<field name="state">code</field>
<field name="code">
if records:
# Filter for payments
payments = records.filtered(lambda r: r.state == 'posted')
if payments:
action = {
'type': 'ir.actions.client',
'tag': 'direct_print',
'report_name': 'account.action_report_payment_receipt',
'docids': payments.ids,
'context': env.context,
}
</field>
</record>
<!-- Account Statement Direct Print -->
<record id="action_direct_print_account_statement" model="ir.actions.server">
<field name="name">Direct Print Account Statement</field>
<field name="model_id" ref="base.model_res_partner"/>
<field name="binding_model_id" ref="base.model_res_partner"/>
<field name="binding_view_types">list,form</field>
<field name="state">code</field>
<field name="code">
if records:
# Filter for partners with accounting entries
partners = records.filtered(lambda r: r.customer_rank > 0 or r.supplier_rank > 0)
if partners:
action = {
'type': 'ir.actions.client',
'tag': 'direct_print',
'report_name': 'account.report_partnerledger',
'docids': partners.ids,
'context': env.context,
}
</field>
</record>
</data>
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<data>
<!-- Customer Invoice Direct Print -->
<record id="action_direct_print_customer_invoice" model="ir.actions.server">
<field name="name">Direct Print Customer Invoice</field>
<field name="model_id" ref="account.model_account_move"/>
<field name="binding_model_id" ref="account.model_account_move"/>
<field name="binding_view_types">list,form</field>
<field name="state">code</field>
<field name="code">
if records:
# Filter for customer invoices
invoices = records.filtered(lambda r: r.move_type in ['out_invoice', 'out_refund'])
if invoices:
action = {
'type': 'ir.actions.client',
'tag': 'direct_print',
'report_name': 'account.report_invoice',
'docids': invoices.ids,
'context': env.context,
}
</field>
</record>
<!-- Vendor Bill Direct Print -->
<record id="action_direct_print_vendor_bill" model="ir.actions.server">
<field name="name">Direct Print Vendor Bill</field>
<field name="model_id" ref="account.model_account_move"/>
<field name="binding_model_id" ref="account.model_account_move"/>
<field name="binding_view_types">list,form</field>
<field name="state">code</field>
<field name="code">
if records:
# Filter for vendor bills
bills = records.filtered(lambda r: r.move_type in ['in_invoice', 'in_refund'])
if bills:
action = {
'type': 'ir.actions.client',
'tag': 'direct_print',
'report_name': 'account.report_invoice',
'docids': bills.ids,
'context': env.context,
}
</field>
</record>
<!-- Invoice with Payment Receipt Direct Print -->
<record id="action_direct_print_invoice_with_payments" model="ir.actions.server">
<field name="name">Direct Print Invoice with Payments</field>
<field name="model_id" ref="account.model_account_move"/>
<field name="binding_model_id" ref="account.model_account_move"/>
<field name="binding_view_types">list,form</field>
<field name="state">code</field>
<field name="code">
if records:
# Filter for customer invoices
invoices = records.filtered(lambda r: r.move_type in ['out_invoice'])
if invoices:
action = {
'type': 'ir.actions.client',
'tag': 'direct_print',
'report_name': 'account.report_invoice_with_payments',
'docids': invoices.ids,
'context': env.context,
}
</field>
</record>
<!-- Payment Receipt Direct Print -->
<record id="action_direct_print_payment_receipt" model="ir.actions.server">
<field name="name">Direct Print Payment Receipt</field>
<field name="model_id" ref="account.model_account_payment"/>
<field name="binding_model_id" ref="account.model_account_payment"/>
<field name="binding_view_types">list,form</field>
<field name="state">code</field>
<field name="code">
if records:
# Filter for payments
payments = records.filtered(lambda r: r.state == 'posted')
if payments:
action = {
'type': 'ir.actions.client',
'tag': 'direct_print',
'report_name': 'account.action_report_payment_receipt',
'docids': payments.ids,
'context': env.context,
}
</field>
</record>
<!-- Account Statement Direct Print -->
<record id="action_direct_print_account_statement" model="ir.actions.server">
<field name="name">Direct Print Account Statement</field>
<field name="model_id" ref="base.model_res_partner"/>
<field name="binding_model_id" ref="base.model_res_partner"/>
<field name="binding_view_types">list,form</field>
<field name="state">code</field>
<field name="code">
if records:
# Filter for partners with accounting entries
partners = records.filtered(lambda r: r.customer_rank > 0 or r.supplier_rank > 0)
if partners:
action = {
'type': 'ir.actions.client',
'tag': 'direct_print',
'report_name': 'account.report_partnerledger',
'docids': partners.ids,
'context': env.context,
}
</field>
</record>
</data>
</odoo>

View File

@ -1,3 +1,3 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<?xml version="1.0" encoding="utf-8"?>
<odoo>
</odoo>

View File

@ -1,10 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<!-- Template for direct print button that can be added to forms -->
<template id="direct_print_button" name="Direct Print Button">
<button type="button" class="btn btn-primary o_direct_print_btn"
title="Print directly to local printer">
<i class="fa fa-print"/> Direct Print
</button>
</template>
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<!-- Template for direct print button that can be added to forms -->
<template id="direct_print_button" name="Direct Print Button">
<button type="button" class="btn btn-primary o_direct_print_btn"
title="Print directly to local printer">
<i class="fa fa-print"/> Direct Print
</button>
</template>
</odoo>

View File

@ -1,21 +1,21 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<data>
<!-- Add Direct Print button to Purchase Order form view -->
<record id="purchase_order_form_direct_print" model="ir.ui.view">
<field name="name">purchase.order.form.direct.print</field>
<field name="model">purchase.order</field>
<field name="inherit_id" ref="purchase.purchase_order_form"/>
<field name="arch" type="xml">
<xpath expr="//header" position="inside">
<button name="action_direct_print_purchase_order"
type="object"
string="Direct Print"
class="btn-primary"
invisible="state == 'cancel'"
groups="purchase.group_purchase_user"/>
</xpath>
</field>
</record>
</data>
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<data>
<!-- Add Direct Print button to Purchase Order form view -->
<record id="purchase_order_form_direct_print" model="ir.ui.view">
<field name="name">purchase.order.form.direct.print</field>
<field name="model">purchase.order</field>
<field name="inherit_id" ref="purchase.purchase_order_form"/>
<field name="arch" type="xml">
<xpath expr="//header" position="inside">
<button name="action_direct_print_purchase_order"
type="object"
string="Direct Print"
class="btn-primary"
invisible="state == 'cancel'"
groups="purchase.group_purchase_user"/>
</xpath>
</field>
</record>
</data>
</odoo>

View File

@ -1,22 +1,22 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<data>
<record id="action_direct_print_purchase_order" model="ir.actions.server">
<field name="name">Direct Print Request for Quotation / Order</field>
<field name="model_id" ref="purchase.model_purchase_order"/>
<field name="binding_model_id" ref="purchase.model_purchase_order"/>
<field name="binding_view_types">list,form</field>
<field name="state">code</field>
<field name="code">
if records:
action = {
'type': 'ir.actions.client',
'tag': 'direct_print',
'report_name': 'purchase.report_purchaseorder',
'docids': records.ids,
'context': env.context,
}
</field>
</record>
</data>
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<data>
<record id="action_direct_print_purchase_order" model="ir.actions.server">
<field name="name">Direct Print Request for Quotation / Order</field>
<field name="model_id" ref="purchase.model_purchase_order"/>
<field name="binding_model_id" ref="purchase.model_purchase_order"/>
<field name="binding_view_types">list,form</field>
<field name="state">code</field>
<field name="code">
if records:
action = {
'type': 'ir.actions.client',
'tag': 'direct_print',
'report_name': 'purchase.report_purchaseorder',
'docids': records.ids,
'context': env.context,
}
</field>
</record>
</data>
</odoo>

View File

@ -1,21 +1,21 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<data>
<!-- Add Direct Print button to Sale Order form view -->
<record id="view_order_form_direct_print" model="ir.ui.view">
<field name="name">sale.order.form.direct.print</field>
<field name="model">sale.order</field>
<field name="inherit_id" ref="sale.view_order_form"/>
<field name="arch" type="xml">
<xpath expr="//header" position="inside">
<button name="action_direct_print_quotation"
type="object"
string="Direct Print"
class="btn-primary"
invisible="state == 'cancel'"
groups="sales_team.group_sale_salesman"/>
</xpath>
</field>
</record>
</data>
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<data>
<!-- Add Direct Print button to Sale Order form view -->
<record id="view_order_form_direct_print" model="ir.ui.view">
<field name="name">sale.order.form.direct.print</field>
<field name="model">sale.order</field>
<field name="inherit_id" ref="sale.view_order_form"/>
<field name="arch" type="xml">
<xpath expr="//header" position="inside">
<button name="action_direct_print_quotation"
type="object"
string="Direct Print"
class="btn-primary"
invisible="state == 'cancel'"
groups="sales_team.group_sale_salesman"/>
</xpath>
</field>
</record>
</data>
</odoo>

View File

@ -1,22 +1,22 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<data>
<record id="action_direct_print_sale_order" model="ir.actions.server">
<field name="name">Direct Print Quotation / Order</field>
<field name="model_id" ref="sale.model_sale_order"/>
<field name="binding_model_id" ref="sale.model_sale_order"/>
<field name="binding_view_types">list,form</field>
<field name="state">code</field>
<field name="code">
if records:
action = {
'type': 'ir.actions.client',
'tag': 'direct_print',
'report_name': 'sale.report_saleorder',
'docids': records.ids,
'context': env.context,
}
</field>
</record>
</data>
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<data>
<record id="action_direct_print_sale_order" model="ir.actions.server">
<field name="name">Direct Print Quotation / Order</field>
<field name="model_id" ref="sale.model_sale_order"/>
<field name="binding_model_id" ref="sale.model_sale_order"/>
<field name="binding_view_types">list,form</field>
<field name="state">code</field>
<field name="code">
if records:
action = {
'type': 'ir.actions.client',
'tag': 'direct_print',
'report_name': 'sale.report_saleorder',
'docids': records.ids,
'context': env.context,
}
</field>
</record>
</data>
</odoo>

View File

@ -1,22 +1,22 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<data>
<!-- Add Direct Print button to Stock Picking form view -->
<record id="view_picking_form_direct_print" model="ir.ui.view">
<field name="name">stock.picking.form.direct.print</field>
<field name="model">stock.picking</field>
<field name="inherit_id" ref="stock.view_picking_form"/>
<field name="arch" type="xml">
<xpath expr="//header" position="inside">
<button name="action_direct_print_receipt"
type="object"
string="Direct Print"
class="btn-primary"
invisible="state not in ['done', 'assigned']"
groups="stock.group_stock_user"/>
</xpath>
</field>
</record>
</data>
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<data>
<!-- Add Direct Print button to Stock Picking form view -->
<record id="view_picking_form_direct_print" model="ir.ui.view">
<field name="name">stock.picking.form.direct.print</field>
<field name="model">stock.picking</field>
<field name="inherit_id" ref="stock.view_picking_form"/>
<field name="arch" type="xml">
<xpath expr="//header" position="inside">
<button name="action_direct_print_receipt"
type="object"
string="Direct Print"
class="btn-primary"
invisible="state not in ['done', 'assigned']"
groups="stock.group_stock_user"/>
</xpath>
</field>
</record>
</data>
</odoo>

View File

@ -1,160 +1,160 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<data>
<record id="action_direct_print_delivery_slip" model="ir.actions.server">
<field name="name">Direct Print Delivery Slip</field>
<field name="model_id" ref="stock.model_stock_picking"/>
<field name="binding_model_id" ref="stock.model_stock_picking"/>
<field name="binding_view_types">list,form</field>
<field name="state">code</field>
<field name="code">
if records:
action = {
'type': 'ir.actions.client',
'tag': 'direct_print',
'report_name': 'stock.action_report_delivery',
'docids': records.ids,
'context': env.context,
}
</field>
</record>
<record id="action_direct_print_picking_operations" model="ir.actions.server">
<field name="name">Direct Print Picking Operations</field>
<field name="model_id" ref="stock.model_stock_picking"/>
<field name="binding_model_id" ref="stock.model_stock_picking"/>
<field name="binding_view_types">list,form</field>
<field name="state">code</field>
<field name="code">
if records:
action = {
'type': 'ir.actions.client',
'tag': 'direct_print',
'report_name': 'stock.action_report_picking',
'docids': records.ids,
'context': env.context,
}
</field>
</record>
<!-- Internal Transfer Direct Print -->
<record id="action_direct_print_internal_transfer" model="ir.actions.server">
<field name="name">Direct Print Internal Transfer</field>
<field name="model_id" ref="stock.model_stock_picking"/>
<field name="binding_model_id" ref="stock.model_stock_picking"/>
<field name="binding_view_types">list,form</field>
<field name="state">code</field>
<field name="code">
if records:
# Filter for internal transfers
internal_transfers = records.filtered(lambda r: r.picking_type_id.code == 'internal')
if internal_transfers:
action = {
'type': 'ir.actions.client',
'tag': 'direct_print',
'report_name': 'stock.action_report_picking',
'docids': internal_transfers.ids,
'context': env.context,
}
else:
# All records if none are internal transfers
action = {
'type': 'ir.actions.client',
'tag': 'direct_print',
'report_name': 'stock.action_report_picking',
'docids': records.ids,
'context': env.context,
}
</field>
</record>
<!-- Receipt/Incoming Shipment Direct Print -->
<record id="action_direct_print_receipt" model="ir.actions.server">
<field name="name">Direct Print Receipt</field>
<field name="model_id" ref="stock.model_stock_picking"/>
<field name="binding_model_id" ref="stock.model_stock_picking"/>
<field name="binding_view_types">list,form</field>
<field name="state">code</field>
<field name="code">
if records:
# Filter for incoming/receipt operations
receipts = records.filtered(lambda r: r.picking_type_id.code == 'incoming')
if receipts:
action = {
'type': 'ir.actions.client',
'tag': 'direct_print',
'report_name': 'stock.action_report_picking',
'docids': receipts.ids,
'context': env.context,
}
else:
# All records if none are receipts
action = {
'type': 'ir.actions.client',
'tag': 'direct_print',
'report_name': 'stock.action_report_picking',
'docids': records.ids,
'context': env.context,
}
</field>
</record>
<!-- Stock Move Direct Print -->
<record id="action_direct_print_stock_move" model="ir.actions.server">
<field name="name">Direct Print Stock Move</field>
<field name="model_id" ref="stock.model_stock_move"/>
<field name="binding_model_id" ref="stock.model_stock_move"/>
<field name="binding_view_types">list,form</field>
<field name="state">code</field>
<field name="code">
if records:
action = {
'type': 'ir.actions.client',
'tag': 'direct_print',
'report_name': 'stock.report_stock_move',
'docids': records.ids,
'context': env.context,
}
</field>
</record>
<!-- Inventory Valuation Direct Print -->
<record id="action_direct_print_inventory_valuation" model="ir.actions.server">
<field name="name">Direct Print Inventory Valuation</field>
<field name="model_id" ref="stock.model_stock_quant"/>
<field name="binding_model_id" ref="stock.model_stock_quant"/>
<field name="binding_view_types">list</field>
<field name="state">code</field>
<field name="code">
if records:
action = {
'type': 'ir.actions.client',
'tag': 'direct_print',
'report_name': 'stock.action_report_inventory',
'docids': records.ids,
'context': env.context,
}
</field>
</record>
<!-- Package/Lot Tracking Direct Print -->
<record id="action_direct_print_package_content" model="ir.actions.server">
<field name="name">Direct Print Package Content</field>
<field name="model_id" ref="stock.model_stock_quant_package"/>
<field name="binding_model_id" ref="stock.model_stock_quant_package"/>
<field name="binding_view_types">list,form</field>
<field name="state">code</field>
<field name="code">
if records:
action = {
'type': 'ir.actions.client',
'tag': 'direct_print',
'report_name': 'stock.action_report_quant_package_barcode',
'docids': records.ids,
'context': env.context,
}
</field>
</record>
</data>
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<data>
<record id="action_direct_print_delivery_slip" model="ir.actions.server">
<field name="name">Direct Print Delivery Slip</field>
<field name="model_id" ref="stock.model_stock_picking"/>
<field name="binding_model_id" ref="stock.model_stock_picking"/>
<field name="binding_view_types">list,form</field>
<field name="state">code</field>
<field name="code">
if records:
action = {
'type': 'ir.actions.client',
'tag': 'direct_print',
'report_name': 'stock.action_report_delivery',
'docids': records.ids,
'context': env.context,
}
</field>
</record>
<record id="action_direct_print_picking_operations" model="ir.actions.server">
<field name="name">Direct Print Picking Operations</field>
<field name="model_id" ref="stock.model_stock_picking"/>
<field name="binding_model_id" ref="stock.model_stock_picking"/>
<field name="binding_view_types">list,form</field>
<field name="state">code</field>
<field name="code">
if records:
action = {
'type': 'ir.actions.client',
'tag': 'direct_print',
'report_name': 'stock.action_report_picking',
'docids': records.ids,
'context': env.context,
}
</field>
</record>
<!-- Internal Transfer Direct Print -->
<record id="action_direct_print_internal_transfer" model="ir.actions.server">
<field name="name">Direct Print Internal Transfer</field>
<field name="model_id" ref="stock.model_stock_picking"/>
<field name="binding_model_id" ref="stock.model_stock_picking"/>
<field name="binding_view_types">list,form</field>
<field name="state">code</field>
<field name="code">
if records:
# Filter for internal transfers
internal_transfers = records.filtered(lambda r: r.picking_type_id.code == 'internal')
if internal_transfers:
action = {
'type': 'ir.actions.client',
'tag': 'direct_print',
'report_name': 'stock.action_report_picking',
'docids': internal_transfers.ids,
'context': env.context,
}
else:
# All records if none are internal transfers
action = {
'type': 'ir.actions.client',
'tag': 'direct_print',
'report_name': 'stock.action_report_picking',
'docids': records.ids,
'context': env.context,
}
</field>
</record>
<!-- Receipt/Incoming Shipment Direct Print -->
<record id="action_direct_print_receipt" model="ir.actions.server">
<field name="name">Direct Print Receipt</field>
<field name="model_id" ref="stock.model_stock_picking"/>
<field name="binding_model_id" ref="stock.model_stock_picking"/>
<field name="binding_view_types">list,form</field>
<field name="state">code</field>
<field name="code">
if records:
# Filter for incoming/receipt operations
receipts = records.filtered(lambda r: r.picking_type_id.code == 'incoming')
if receipts:
action = {
'type': 'ir.actions.client',
'tag': 'direct_print',
'report_name': 'stock.action_report_picking',
'docids': receipts.ids,
'context': env.context,
}
else:
# All records if none are receipts
action = {
'type': 'ir.actions.client',
'tag': 'direct_print',
'report_name': 'stock.action_report_picking',
'docids': records.ids,
'context': env.context,
}
</field>
</record>
<!-- Stock Move Direct Print -->
<record id="action_direct_print_stock_move" model="ir.actions.server">
<field name="name">Direct Print Stock Move</field>
<field name="model_id" ref="stock.model_stock_move"/>
<field name="binding_model_id" ref="stock.model_stock_move"/>
<field name="binding_view_types">list,form</field>
<field name="state">code</field>
<field name="code">
if records:
action = {
'type': 'ir.actions.client',
'tag': 'direct_print',
'report_name': 'stock.report_stock_move',
'docids': records.ids,
'context': env.context,
}
</field>
</record>
<!-- Inventory Valuation Direct Print -->
<record id="action_direct_print_inventory_valuation" model="ir.actions.server">
<field name="name">Direct Print Inventory Valuation</field>
<field name="model_id" ref="stock.model_stock_quant"/>
<field name="binding_model_id" ref="stock.model_stock_quant"/>
<field name="binding_view_types">list</field>
<field name="state">code</field>
<field name="code">
if records:
action = {
'type': 'ir.actions.client',
'tag': 'direct_print',
'report_name': 'stock.action_report_inventory',
'docids': records.ids,
'context': env.context,
}
</field>
</record>
<!-- Package/Lot Tracking Direct Print -->
<record id="action_direct_print_package_content" model="ir.actions.server">
<field name="name">Direct Print Package Content</field>
<field name="model_id" ref="stock.model_stock_quant_package"/>
<field name="binding_model_id" ref="stock.model_stock_quant_package"/>
<field name="binding_view_types">list,form</field>
<field name="state">code</field>
<field name="code">
if records:
action = {
'type': 'ir.actions.client',
'tag': 'direct_print',
'report_name': 'stock.action_report_quant_package_barcode',
'docids': records.ids,
'context': env.context,
}
</field>
</record>
</data>
</odoo>