Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 8 additions & 16 deletions base_report_to_label_printer/tests/test_ir_actions_report.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
# Copyright (C) 2022 Raumschmiede GmbH - Christopher Hansen (<https://www.raumschmiede.de>)
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).

import logging

from odoo.addons.base.tests.common import BaseCommon

Expand All @@ -15,13 +14,11 @@ def setUpClass(cls):
cls.Model = cls.env["ir.actions.report"].with_context(
skip_printer_exception=True
)
cls.server = cls.env["printing.server"].create({})

def new_printer(self):
return self.env["printing.printer"].create(
{
"name": "Printer",
"server_id": self.server.id,
"system_name": "Sys Name",
"default": True,
"status": "unknown",
Expand All @@ -38,16 +35,11 @@ def test_print_behavior_user_label_printer(self):
report.label = True
self.env.user.printing_action = "client"
self.env.user.default_label_printer_id = self.new_printer()
with (
self.assertLogs(level=logging.WARNING) as logs,
):
self.assertEqual(
report.behaviour(),
{
"action": "client",
"printer": self.env.user.default_label_printer_id,
"tray": False,
},
)
self.assertEqual(len(logs.records), 1)
self.assertEqual(logs.records[0].levelno, logging.WARNING)
self.assertEqual(
report.behaviour(),
{
"action": "client",
"printer": self.env.user.default_label_printer_id,
"tray": False,
},
)
192 changes: 133 additions & 59 deletions base_report_to_printer/README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ Report to printer
!! This file is generated by oca-gen-addon-readme !!
!! changes will be overwritten. !!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! source digest: sha256:411351c67395d3219ea49f07addba2966080696f3b776d899712288e24f98fc2
!! source digest: sha256:e5af916528d668b5628606b5b2216ec40d3f05f183d01eb157311e01719dcb49
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

.. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png
Expand All @@ -32,33 +32,32 @@ Report to printer

|badge1| |badge2| |badge3| |badge4| |badge5|

This module allows users to send reports to a printer attached to the
server.
This module provides the core framework to send Odoo reports directly to
printers. It defines the base models, configuration options and printing
workflow, without depending on a specific printing protocol.

It adds an optional behaviour on reports to send it directly to a
printer.
The actual connection with printers is delegated to extension modules
(e.g. base_report_to_printer_cups), which implement support for a given
printing backend.

- Send to Client is the default behaviour providing you a downloadable
PDF
- Send to Printer prints the report on selected printer
Key features:

It detects trays on printers installation plus permits to select the
paper source on which you want to print directly.
Flexible report output behavior:

Report behaviour is defined by settings.
Send to Client (default): generates a downloadable PDF.

You will find this option on default user config, on default report
config and on specific config per user per report.
Send to Printer: sends the report directly to a configured printer (via
backend module).

This allows you to dedicate a specific paper source for example for
preprinted paper such as payment slip.
Support for user-level, report-level, and combined user/report printing
rules.

Settings can be configured:
Extensible design: new modules can add support for additional printing
systems or protocols.

- globally
- per user
- per report
- per user and report
This modular approach allows administrators to configure printing
globally, per user, per report, or per user/report combination, while
keeping the printing backend independent and replaceable.

**Table of contents**

Expand All @@ -68,64 +67,138 @@ Settings can be configured:
Installation
============

To install this module, you need to:

1. Install PyCups - https://pypi.python.org/pypi/pycups

.. code:: bash

sudo apt-get install cups
sudo apt-get install libcups2-dev
sudo apt-get install python3-dev
sudo pip install pycups

Configuration
=============

To configure this module, you need to:
Configuration Guide

To configure and start using the Base Report to Printer module, follow
these steps:

1. User Access Rights

Go to Settings → Users & Companies → Users.

Open the user form and in the Access Rights tab, enable:

Printing / Print User → grants access to the printing menu and
user-specific printing preferences.

2. Global Printing Settings

Navigate to Settings → Technical → Printing → Printing Settings.

Define the default printing behavior for reports:

Send to Client (default): generates a downloadable PDF.

Send to Printer: sends the report directly to a configured printer
(requires a backend module such as base_report_to_printer_cups).

3. User Preferences

Each user can configure their own printing behavior:

Go to Preferences (top-right menu, click on your name).

In the Printing section, choose:

Default action (Send to Client / Send to Printer).

Preferred printer (if a backend module is installed and printers are
detected).

4. Report-Specific Configuration

Go to Settings → Technical → Reports → Reports.

For each report, you can define:

1. Enable the "Printing / Print User" option under access rights to give
users the ability to view the print menu.
Default printing action.

The jobs will be sent to the printer with a name matching the
print_report_name of the report (truncated at 80 characters). By default
this will not be displayed by CUPS web interface or in Odoo. To see this
information, you need to change the configuration of your CUPS server
and set the JobPrivateValue directive to "none" (or some other list of
values which does not include "job-name") , and reload the server. See
cupsd.conf(5)
<`https://www.cups.org/doc/man-cupsd.conf.html\\> <https://www.cups.org/doc/man-cupsd.conf.html\>>`__
for details.
Default printer (if available).

These settings can be overridden at the user level.

5. Per User & Report Combination

Navigate to Settings → Technical → Printing → Report Configurations.

Here you can assign specific rules combining:

A user.

A report.

A printing action (Send to Client / Send to Printer).

A printer and tray (if supported by the backend).

6. Installing a Backend (e.g., CUPS)

The base module does not include any printing backend. To connect with
actual printers you must install an extension module, such as:

base_report_to_printer_cups → adds support for CUPS printers, trays, and
job management.

Once installed, printers from the backend will be available in the
configuration menus above.

Usage
=====

Guidelines for use:
Usage
=====

- To update the CUPS printers in *Settings > Printing > Update
Printers from CUPS*
- To print a report on a specific printer or tray, you can change
these in *Settings > Printing > Reports* to define default
behaviour.
- To print a report on a specific printer and/or tray for a user, you
can change these in *Settings > Printing > Reports* in *Specific
actions per user*
- Users may also select a default action, printer or tray in their
preferences.
Guidelines for use:

When no tray is configured for a report and a user, the default tray
setup on the CUPS server is used.
- To use a specific printing backend (e.g. CUPS), make sure the
corresponding module (such as ``base_report_to_printer_cups``) is
installed and configured.
- To print a report on a specific printer or tray, you can configure
defaults in *Settings > Printing > Reports*.
- To define user-specific behaviour, go to *Settings > Printing >
Reports* and configure *Specific actions per user*.
- Each user can also select a default action, printer or tray in their
*Preferences*.
- When no tray is configured for a report or a user, the default tray
defined by the printing backend (e.g. the CUPS server) will be used.

Notes
-----

- This module (``base_report_to_printer``) only provides the **base
framework**.
- To connect with a real print system, you must install an additional
backend module (e.g. ``base_report_to_printer_cups`` for CUPS).
- Other backend modules can be developed to support different print
protocols or environments.

Known issues / Roadmap
======================

- With threaded printing there's no download fallback when the issue
isn't detected by the CUPS Odoo backend. To able to do it, we would
need to notify the bus or use web_notify for it.


Changelog
=========

18.0.1.0.0 (2025-10-15)
-----------------------

- [REFAC] Extracted all CUPS-specific functionality into a dedicated
module: ``base_report_to_printer_cups``.
- [ADD] Introduced a base abstraction layer for report-to-printer, to
allow adding new backends (protocols) without modifying the core
module.
- [IMP] Improved configuration instructions (global, per-user,
per-report, and per user+report).
- [CLEAN] Updated documentation and module description to reflect new
architecture.
-

13.0.1.0.0 (2019-09-30)
-----------------------

Expand Down Expand Up @@ -180,12 +253,13 @@ Contributors
- Akim Juillerat <akim.juillerat@camptocamp.com>
- Jacques-Etienne Baudoux (BCIM) <je@bcim.be>
- Tris Doan <tridm@trobz.com>
- Miquel Alzanillas <mique.alzanillas@nagarro.com>

Other credits
-------------

The migration of this module from 17.0 to 18.0 was financially supported
by Camptocamp.
The migration of the original module (base_report_to_printer) from 17.0
to 18.0 was financially supported by Camptocamp.

Maintainers
-----------
Expand Down
6 changes: 1 addition & 5 deletions base_report_to_printer/__manifest__.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,12 @@
"data": [
"data/printing_data.xml",
"security/security.xml",
"security/ir.model.access.csv",
"views/printing_printer.xml",
"views/printing_server.xml",
"views/printing_job.xml",
"views/printing_report.xml",
"views/res_users.xml",
"views/ir_actions_report.xml",
"views/res_users.xml",
"wizards/print_attachment_report.xml",
"wizards/printing_printer_update_wizard_view.xml",
],
"assets": {
"web.assets_backend": [
Expand All @@ -35,5 +32,4 @@
},
"installable": True,
"application": False,
"external_dependencies": {"python": ["pycups"]},
}
1 change: 0 additions & 1 deletion base_report_to_printer/data/neutralize.sql
Original file line number Diff line number Diff line change
@@ -1,2 +1 @@
update printing_server set active=false;
update printing_printer set active=false;
10 changes: 0 additions & 10 deletions base_report_to_printer/data/printing_data.xml
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,6 @@
<field name="name">Send to Client</field>
<field name="action_type">client</field>
</record>
<record forcecreate="True" id="ir_cron_update_printers" model="ir.cron">
<field name="name">Update Printers Jobs</field>
<field name="active" eval="True" />
<field name="user_id" ref="base.user_root" />
<field name="interval_number">1</field>
<field name="interval_type">minutes</field>
<field name="model_id" ref="base_report_to_printer.model_printing_server" />
<field name="state">code</field>
<field name="code">model.action_update_jobs()</field>
</record>
<function
model="ir.default"
name="set"
Expand Down
1 change: 0 additions & 1 deletion base_report_to_printer/models/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
from . import printing_action
from . import printing_job
from . import printing_printer
from . import printing_server
from . import printing_report_xml_action
from . import printing_tray
from . import res_users
6 changes: 6 additions & 0 deletions base_report_to_printer/models/ir_actions_report.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,15 @@
# Copyright (C) 2013-2014 Camptocamp (<http://www.camptocamp.com>)
# Copyright 2024 Tecnativa - Sergio Teruel
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
import logging
import threading
from time import time

from odoo import _, api, exceptions, fields, models, registry
from odoo.tools.safe_eval import safe_eval

_logger = logging.getLogger(__name__)

REPORT_TYPES = {"qweb-pdf": "pdf", "qweb-text": "text"}


Expand Down Expand Up @@ -153,6 +156,9 @@ def print_document(self, record_ids, data=None):
"""Print a document, do not return the document file"""
report_type = REPORT_TYPES.get(self.report_type)
if not report_type:
_logger.warning(
"Report type %s not supported for direct printing", self.report_type
)
raise exceptions.UserError(
_("This report type (%s) is not supported by direct printing!")
% str(self.report_type)
Expand Down
Loading