[ADD] document_page_tag_print_control: restrict document printing based on tag configuration

This commit is contained in:
Juan Alberto Raja 2025-07-08 12:26:22 +02:00
parent 6bece12e6f
commit dccc140d32
19 changed files with 947 additions and 0 deletions

View File

@ -0,0 +1,108 @@
===============================
Document Page Tag Print Control
===============================
..
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! This file is generated by oca-gen-addon-readme !!
!! changes will be overwritten. !!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! source digest: sha256:c08c914a87dd77f1d5c07e7716f9f40c7341917cc62a95efe6c0035fce9a9eaf
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
.. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png
:target: https://odoo-community.org/page/development-status
:alt: Beta
.. |badge2| image:: https://img.shields.io/badge/licence-AGPL--3-blue.png
:target: http://www.gnu.org/licenses/agpl-3.0-standalone.html
:alt: License: AGPL-3
.. |badge3| image:: https://img.shields.io/badge/github-OCA%2Fknowledge-lightgray.png?logo=github
:target: https://github.com/OCA/knowledge/tree/16.0/document_page_tag_print_control
:alt: OCA/knowledge
.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png
:target: https://translation.odoo-community.org/projects/knowledge-16-0/knowledge-16-0-document_page_tag_print_control
:alt: Translate me on Weblate
.. |badge5| image:: https://img.shields.io/badge/runboat-Try%20me-875A7B.png
:target: https://runboat.odoo-community.org/builds?repo=OCA/knowledge&target_branch=16.0
:alt: Try me on Runboat
|badge1| |badge2| |badge3| |badge4| |badge5|
This module adds print control functionality to document pages based on
tags. It allows users to control which document pages cannot be printed
by configuring tags with a "Not Printable" attribute.
When a document page has one or more tags marked as not printable,
printing functionality will be disabled and a warning will be shown if
attempted.
Users with the "Manager" role in the "Document Knowledge" section (under
Settings > Users > Access Rights > Other) are exempt from these
restrictions and can print any document page regardless of its tags.
**Table of contents**
.. contents::
:local:
Usage
=====
To restrict the printing of document pages using tags:
1. Go to Document Management > Configuration > Tags.
2. Create or edit existing tags and use the "Not Printable" checkbox to
prevent printing.
3. Check "Not Printable" for tags that should block printing.
4. Assign these tags to document pages. If any tag on a page is marked
as not printable, the entire page will be blocked from printing.
5. If you attempt to print such pages, the system will raise a warning
and prevent the action.
6. All tags allow printing by default for compatibility.
Users with the **Manager** role in the "Document Knowledge" section
(Settings > Users > Access Rights > Other) are not affected by this
restriction. They can always print any document page.
Bug Tracker
===========
Bugs are tracked on `GitHub Issues <https://github.com/OCA/knowledge/issues>`_.
In case of trouble, please check there if your issue has already been reported.
If you spotted it first, help us to smash it by providing a detailed and welcomed
`feedback <https://github.com/OCA/knowledge/issues/new?body=module:%20document_page_tag_print_control%0Aversion:%2016.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**>`_.
Do not contact contributors directly about support or help with technical issues.
Credits
=======
Authors
-------
* Sygel
Contributors
------------
- `Sygel <https://www.sygel.es>`__
- Juan Alberto Raja
- Valentín Vinagre
Maintainers
-----------
This module is maintained by the OCA.
.. image:: https://odoo-community.org/logo.png
:alt: Odoo Community Association
:target: https://odoo-community.org
OCA, or the Odoo Community Association, is a nonprofit organization whose
mission is to support the collaborative development of Odoo features and
promote its widespread use.
This module is part of the `OCA/knowledge <https://github.com/OCA/knowledge/tree/16.0/document_page_tag_print_control>`_ project on GitHub.
You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.

View File

@ -0,0 +1,3 @@
# Copyright 2025 Juan Alberto Raja<juan.raja@sygel.es>
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
from . import models

View File

@ -0,0 +1,20 @@
# Copyright 2025 Juan Alberto Raja <juan.raja@sygel.es>
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
{
"name": "Document Page Tag Print Control",
"summary": "Restricts document page printing based on assigned tags",
"version": "16.0.1.0.0",
"license": "AGPL-3",
"author": "Sygel, Odoo Community Association (OCA)",
"website": "https://github.com/OCA/knowledge",
"category": "Knowledge",
"depends": [
"document_page_tag",
],
"data": [
"views/document_page_tag.xml",
],
"installable": True,
"application": False,
"auto_install": False,
}

View File

@ -0,0 +1,58 @@
# Translation of Odoo Server.
# * document_page_tag_print_control
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 16.0\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: \n"
"PO-Revision-Date: \n"
"Last-Translator: \n"
"Language-Team: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: \n"
"Language: ca\n"
"Plural-Forms: \n"
#. module: document_page_tag_print_control
#: code:addons/document_page_tag_print_control/models/report_document_page.py:0
#, python-format
msgid "None of the selected document pages can be printed due to their tags."
msgstr "Cap de les pàgines seleccionades es pot imprimir a causa de les seves etiquetes."
#. module: document_page_tag_print_control
#: code:addons/document_page_tag_print_control/models/report_document_page.py:0
#, python-format
msgid "Some pages cannot be printed due to their tags:\n"
msgstr "Algunes pàgines no es poden imprimir a causa de les seves etiquetes:\n"
#. module: document_page_tag_print_control
#: model:ir.model.fields,field_description:document_page_tag_print_control.field_document_page_tag__is_not_printable
msgid "Is Not Printable"
msgstr "No és imprimible"
#. module: document_page_tag_print_control
#: model:ir.model.fields,help:document_page_tag_print_control.field_document_page__is_not_printable
msgid "Indicates if the document cannot be printed based on its tags"
msgstr "Indica si el document no es pot imprimir basant-se en les seves etiquetes"
#. module: document_page_tag_print_control
#: model:ir.model.fields,help:document_page_tag_print_control.field_document_page_tag__is_not_printable
msgid "If checked, pages with this tag cannot be printed"
msgstr "Si està marcat, les pàgines amb aquesta etiqueta no es poden imprimir"
#. module: document_page_tag_print_control
#: model_terms:ir.ui.view,arch_db:document_page_tag_print_control.view_document_page_form_inherit_print
msgid "Print"
msgstr "Imprimir"
#. module: document_page_tag_print_control
#: model_terms:ir.ui.view,arch_db:document_page_tag_print_control.view_document_page_tag_search_extended
msgid "Printable Tags"
msgstr "Etiquetes imprimibles"
#. module: document_page_tag_print_control
#: model_terms:ir.ui.view,arch_db:document_page_tag_print_control.view_document_page_tag_search_extended
msgid "Non-Printable Tags"
msgstr "Etiquetes no imprimibles"

View File

@ -0,0 +1,58 @@
# Translation of Odoo Server.
# * document_page_tag_print_control
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 16.0\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: \n"
"PO-Revision-Date: \n"
"Last-Translator: \n"
"Language-Team: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: \n"
"Language: es\n"
"Plural-Forms: \n"
#. module: document_page_tag_print_control
#: code:addons/document_page_tag_print_control/models/report_document_page.py:0
#, python-format
msgid "None of the selected document pages can be printed due to their tags."
msgstr "Ninguna de las páginas seleccionadas se puede imprimir debido a sus etiquetas."
#. module: document_page_tag_print_control
#: code:addons/document_page_tag_print_control/models/report_document_page.py:0
#, python-format
msgid "Some pages cannot be printed due to their tags:\n"
msgstr "Algunas páginas no se pueden imprimir debido a sus etiquetas:\n"
#. module: document_page_tag_print_control
#: model:ir.model.fields,field_description:document_page_tag_print_control.field_document_page_tag__is_not_printable
msgid "Is Not Printable"
msgstr "No es imprimible"
#. module: document_page_tag_print_control
#: model:ir.model.fields,help:document_page_tag_print_control.field_document_page__is_not_printable
msgid "Indicates if the document cannot be printed based on its tags"
msgstr "Indica si el documento no puede ser impreso basándose en sus etiquetas"
#. module: document_page_tag_print_control
#: model:ir.model.fields,help:document_page_tag_print_control.field_document_page_tag__is_not_printable
msgid "If checked, pages with this tag cannot be printed"
msgstr "Si está marcado, las páginas con esta etiqueta no se pueden imprimir"
#. module: document_page_tag_print_control
#: model_terms:ir.ui.view,arch_db:document_page_tag_print_control.view_document_page_form_inherit_print
msgid "Print"
msgstr "Imprimir"
#. module: document_page_tag_print_control
#: model_terms:ir.ui.view,arch_db:document_page_tag_print_control.view_document_page_tag_search_extended
msgid "Printable Tags"
msgstr "Etiquetas imprimibles"
#. module: document_page_tag_print_control
#: model_terms:ir.ui.view,arch_db:document_page_tag_print_control.view_document_page_tag_search_extended
msgid "Non-Printable Tags"
msgstr "Etiquetas no imprimibles"

View File

@ -0,0 +1,5 @@
# Copyright 2025 Juan Alberto Raja<juan.raja@sygel.es>
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
from . import document_page_tag
from . import document_page
from . import report_document_page

View File

@ -0,0 +1,20 @@
# Copyright 2025 Juan Alberto Raja<juan.raja@sygel.es>
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
from odoo import api, fields, models
class DocumentPage(models.Model):
_inherit = "document.page"
is_not_printable = fields.Boolean(
compute="_compute_is_not_printable",
store=True,
help="Indicates if the document cannot be printed based on its tags",
)
@api.depends("tag_ids", "tag_ids.is_not_printable")
def _compute_is_not_printable(self):
for record in self:
record.is_not_printable = any(
tag.is_not_printable for tag in record.tag_ids
)

View File

@ -0,0 +1,12 @@
# Copyright 2025 Juan Alberto Raja<juan.raja@sygel.es>
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
from odoo import fields, models
class DocumentPageTag(models.Model):
_inherit = "document.page.tag"
is_not_printable = fields.Boolean(
default=False,
help="If checked, pages with this tag cannot be printed",
)

View File

@ -0,0 +1,37 @@
# Copyright 2025 Juan Alberto Raja<juan.raja@sygel.es>
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
from odoo import _, api, models
from odoo.exceptions import UserError
class ReportDocumentPage(models.AbstractModel):
_name = "report.document_page.report_documentpage"
_description = "Document Page Report with Print Control"
@api.model
def _get_report_values(self, docids, data=None):
docs = self.env["document.page"].browse(docids).exists()
printable_docs = docs
if not self.env.user.has_group("document_page.group_document_manager"):
printable_docs = docs.filtered(lambda d: not d.is_not_printable)
if not printable_docs:
raise UserError(
_("None of the selected pages can be printed due to their tags.")
)
if len(printable_docs) < len(docs):
non_printable = docs - printable_docs
raise UserError(
_("Some pages cannot be printed due to their tags:\n")
+ "\n".join(f"- {doc.name}" for doc in non_printable)
)
report_values = {
"doc_ids": printable_docs.ids,
"doc_model": "document.page",
"docs": printable_docs,
}
return report_values

View File

@ -0,0 +1,3 @@
- [Sygel](https://www.sygel.es)
- Juan Alberto Raja
- Valentín Vinagre

View File

@ -0,0 +1,5 @@
This module adds print control functionality to document pages based on tags. It allows users to control which document pages cannot be printed by configuring tags with a "Not Printable" attribute.
When a document page has one or more tags marked as not printable, printing functionality will be disabled and a warning will be shown if attempted.
Users with the "Manager" role in the "Document Knowledge" section (under Settings > Users > Access Rights > Other) are exempt from these restrictions and can print any document page regardless of its tags.

View File

@ -0,0 +1,11 @@
To restrict the printing of document pages using tags:
1. Go to Document Management > Configuration > Tags.
2. Create or edit existing tags and use the "Not Printable" checkbox to prevent printing.
3. Check "Not Printable" for tags that should block printing.
4. Assign these tags to document pages. If any tag on a page is marked as not printable, the entire page will be blocked from printing.
5. If you attempt to print such pages, the system will raise a warning and prevent the action.
6. All tags allow printing by default for compatibility.
Users with the **Manager** role in the "Document Knowledge" section (Settings > Users > Access Rights > Other) are not affected by this restriction. They can always print any document page.

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.2 KiB

View File

@ -0,0 +1,454 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="generator" content="Docutils: https://docutils.sourceforge.io/" />
<title>Document Page Tag Print Control</title>
<style type="text/css">
/*
:Author: David Goodger (goodger@python.org)
:Id: $Id: html4css1.css 9511 2024-01-13 09:50:07Z milde $
:Copyright: This stylesheet has been placed in the public domain.
Default cascading style sheet for the HTML output of Docutils.
Despite the name, some widely supported CSS2 features are used.
See https://docutils.sourceforge.io/docs/howto/html-stylesheets.html for how to
customize this style sheet.
*/
/* used to remove borders from tables and images */
.borderless, table.borderless td, table.borderless th {
border: 0 }
table.borderless td, table.borderless th {
/* Override padding for "table.docutils td" with "! important".
The right padding separates the table cells. */
padding: 0 0.5em 0 0 ! important }
.first {
/* Override more specific margin styles with "! important". */
margin-top: 0 ! important }
.last, .with-subtitle {
margin-bottom: 0 ! important }
.hidden {
display: none }
.subscript {
vertical-align: sub;
font-size: smaller }
.superscript {
vertical-align: super;
font-size: smaller }
a.toc-backref {
text-decoration: none ;
color: black }
blockquote.epigraph {
margin: 2em 5em ; }
dl.docutils dd {
margin-bottom: 0.5em }
object[type="image/svg+xml"], object[type="application/x-shockwave-flash"] {
overflow: hidden;
}
/* Uncomment (and remove this text!) to get bold-faced definition list terms
dl.docutils dt {
font-weight: bold }
*/
div.abstract {
margin: 2em 5em }
div.abstract p.topic-title {
font-weight: bold ;
text-align: center }
div.admonition, div.attention, div.caution, div.danger, div.error,
div.hint, div.important, div.note, div.tip, div.warning {
margin: 2em ;
border: medium outset ;
padding: 1em }
div.admonition p.admonition-title, div.hint p.admonition-title,
div.important p.admonition-title, div.note p.admonition-title,
div.tip p.admonition-title {
font-weight: bold ;
font-family: sans-serif }
div.attention p.admonition-title, div.caution p.admonition-title,
div.danger p.admonition-title, div.error p.admonition-title,
div.warning p.admonition-title, .code .error {
color: red ;
font-weight: bold ;
font-family: sans-serif }
/* Uncomment (and remove this text!) to get reduced vertical space in
compound paragraphs.
div.compound .compound-first, div.compound .compound-middle {
margin-bottom: 0.5em }
div.compound .compound-last, div.compound .compound-middle {
margin-top: 0.5em }
*/
div.dedication {
margin: 2em 5em ;
text-align: center ;
font-style: italic }
div.dedication p.topic-title {
font-weight: bold ;
font-style: normal }
div.figure {
margin-left: 2em ;
margin-right: 2em }
div.footer, div.header {
clear: both;
font-size: smaller }
div.line-block {
display: block ;
margin-top: 1em ;
margin-bottom: 1em }
div.line-block div.line-block {
margin-top: 0 ;
margin-bottom: 0 ;
margin-left: 1.5em }
div.sidebar {
margin: 0 0 0.5em 1em ;
border: medium outset ;
padding: 1em ;
background-color: #ffffee ;
width: 40% ;
float: right ;
clear: right }
div.sidebar p.rubric {
font-family: sans-serif ;
font-size: medium }
div.system-messages {
margin: 5em }
div.system-messages h1 {
color: red }
div.system-message {
border: medium outset ;
padding: 1em }
div.system-message p.system-message-title {
color: red ;
font-weight: bold }
div.topic {
margin: 2em }
h1.section-subtitle, h2.section-subtitle, h3.section-subtitle,
h4.section-subtitle, h5.section-subtitle, h6.section-subtitle {
margin-top: 0.4em }
h1.title {
text-align: center }
h2.subtitle {
text-align: center }
hr.docutils {
width: 75% }
img.align-left, .figure.align-left, object.align-left, table.align-left {
clear: left ;
float: left ;
margin-right: 1em }
img.align-right, .figure.align-right, object.align-right, table.align-right {
clear: right ;
float: right ;
margin-left: 1em }
img.align-center, .figure.align-center, object.align-center {
display: block;
margin-left: auto;
margin-right: auto;
}
table.align-center {
margin-left: auto;
margin-right: auto;
}
.align-left {
text-align: left }
.align-center {
clear: both ;
text-align: center }
.align-right {
text-align: right }
/* reset inner alignment in figures */
div.align-right {
text-align: inherit }
/* div.align-center * { */
/* text-align: left } */
.align-top {
vertical-align: top }
.align-middle {
vertical-align: middle }
.align-bottom {
vertical-align: bottom }
ol.simple, ul.simple {
margin-bottom: 1em }
ol.arabic {
list-style: decimal }
ol.loweralpha {
list-style: lower-alpha }
ol.upperalpha {
list-style: upper-alpha }
ol.lowerroman {
list-style: lower-roman }
ol.upperroman {
list-style: upper-roman }
p.attribution {
text-align: right ;
margin-left: 50% }
p.caption {
font-style: italic }
p.credits {
font-style: italic ;
font-size: smaller }
p.label {
white-space: nowrap }
p.rubric {
font-weight: bold ;
font-size: larger ;
color: maroon ;
text-align: center }
p.sidebar-title {
font-family: sans-serif ;
font-weight: bold ;
font-size: larger }
p.sidebar-subtitle {
font-family: sans-serif ;
font-weight: bold }
p.topic-title {
font-weight: bold }
pre.address {
margin-bottom: 0 ;
margin-top: 0 ;
font: inherit }
pre.literal-block, pre.doctest-block, pre.math, pre.code {
margin-left: 2em ;
margin-right: 2em }
pre.code .ln { color: gray; } /* line numbers */
pre.code, code { background-color: #eeeeee }
pre.code .comment, code .comment { color: #5C6576 }
pre.code .keyword, code .keyword { color: #3B0D06; font-weight: bold }
pre.code .literal.string, code .literal.string { color: #0C5404 }
pre.code .name.builtin, code .name.builtin { color: #352B84 }
pre.code .deleted, code .deleted { background-color: #DEB0A1}
pre.code .inserted, code .inserted { background-color: #A3D289}
span.classifier {
font-family: sans-serif ;
font-style: oblique }
span.classifier-delimiter {
font-family: sans-serif ;
font-weight: bold }
span.interpreted {
font-family: sans-serif }
span.option {
white-space: nowrap }
span.pre {
white-space: pre }
span.problematic, pre.problematic {
color: red }
span.section-subtitle {
/* font-size relative to parent (h1..h6 element) */
font-size: 80% }
table.citation {
border-left: solid 1px gray;
margin-left: 1px }
table.docinfo {
margin: 2em 4em }
table.docutils {
margin-top: 0.5em ;
margin-bottom: 0.5em }
table.footnote {
border-left: solid 1px black;
margin-left: 1px }
table.docutils td, table.docutils th,
table.docinfo td, table.docinfo th {
padding-left: 0.5em ;
padding-right: 0.5em ;
vertical-align: top }
table.docutils th.field-name, table.docinfo th.docinfo-name {
font-weight: bold ;
text-align: left ;
white-space: nowrap ;
padding-left: 0 }
/* "booktabs" style (no vertical lines) */
table.docutils.booktabs {
border: 0px;
border-top: 2px solid;
border-bottom: 2px solid;
border-collapse: collapse;
}
table.docutils.booktabs * {
border: 0px;
}
table.docutils.booktabs th {
border-bottom: thin solid;
text-align: left;
}
h1 tt.docutils, h2 tt.docutils, h3 tt.docutils,
h4 tt.docutils, h5 tt.docutils, h6 tt.docutils {
font-size: 100% }
ul.auto-toc {
list-style-type: none }
</style>
</head>
<body>
<div class="document" id="document-page-tag-print-control">
<h1 class="title">Document Page Tag Print Control</h1>
<!-- !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! This file is generated by oca-gen-addon-readme !!
!! changes will be overwritten. !!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! source digest: sha256:c08c914a87dd77f1d5c07e7716f9f40c7341917cc62a95efe6c0035fce9a9eaf
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -->
<p><a class="reference external image-reference" href="https://odoo-community.org/page/development-status"><img alt="Beta" src="https://img.shields.io/badge/maturity-Beta-yellow.png" /></a> <a class="reference external image-reference" href="http://www.gnu.org/licenses/agpl-3.0-standalone.html"><img alt="License: AGPL-3" src="https://img.shields.io/badge/licence-AGPL--3-blue.png" /></a> <a class="reference external image-reference" href="https://github.com/OCA/knowledge/tree/16.0/document_page_tag_print_control"><img alt="OCA/knowledge" src="https://img.shields.io/badge/github-OCA%2Fknowledge-lightgray.png?logo=github" /></a> <a class="reference external image-reference" href="https://translation.odoo-community.org/projects/knowledge-16-0/knowledge-16-0-document_page_tag_print_control"><img alt="Translate me on Weblate" src="https://img.shields.io/badge/weblate-Translate%20me-F47D42.png" /></a> <a class="reference external image-reference" href="https://runboat.odoo-community.org/builds?repo=OCA/knowledge&amp;target_branch=16.0"><img alt="Try me on Runboat" src="https://img.shields.io/badge/runboat-Try%20me-875A7B.png" /></a></p>
<p>This module adds print control functionality to document pages based on
tags. It allows users to control which document pages cannot be printed
by configuring tags with a “Not Printable” attribute.</p>
<p>When a document page has one or more tags marked as not printable,
printing functionality will be disabled and a warning will be shown if
attempted.</p>
<p>Users with the “Manager” role in the “Document Knowledge” section (under
Settings &gt; Users &gt; Access Rights &gt; Other) are exempt from these
restrictions and can print any document page regardless of its tags.</p>
<p><strong>Table of contents</strong></p>
<div class="contents local topic" id="contents">
<ul class="simple">
<li><a class="reference internal" href="#usage" id="toc-entry-1">Usage</a></li>
<li><a class="reference internal" href="#bug-tracker" id="toc-entry-2">Bug Tracker</a></li>
<li><a class="reference internal" href="#credits" id="toc-entry-3">Credits</a><ul>
<li><a class="reference internal" href="#authors" id="toc-entry-4">Authors</a></li>
<li><a class="reference internal" href="#contributors" id="toc-entry-5">Contributors</a></li>
<li><a class="reference internal" href="#maintainers" id="toc-entry-6">Maintainers</a></li>
</ul>
</li>
</ul>
</div>
<div class="section" id="usage">
<h1><a class="toc-backref" href="#toc-entry-1">Usage</a></h1>
<p>To restrict the printing of document pages using tags:</p>
<ol class="arabic simple">
<li>Go to Document Management &gt; Configuration &gt; Tags.</li>
<li>Create or edit existing tags and use the “Not Printable” checkbox to
prevent printing.</li>
<li>Check “Not Printable” for tags that should block printing.</li>
<li>Assign these tags to document pages. If any tag on a page is marked
as not printable, the entire page will be blocked from printing.</li>
<li>If you attempt to print such pages, the system will raise a warning
and prevent the action.</li>
<li>All tags allow printing by default for compatibility.</li>
</ol>
<p>Users with the <strong>Manager</strong> role in the “Document Knowledge” section
(Settings &gt; Users &gt; Access Rights &gt; Other) are not affected by this
restriction. They can always print any document page.</p>
</div>
<div class="section" id="bug-tracker">
<h1><a class="toc-backref" href="#toc-entry-2">Bug Tracker</a></h1>
<p>Bugs are tracked on <a class="reference external" href="https://github.com/OCA/knowledge/issues">GitHub Issues</a>.
In case of trouble, please check there if your issue has already been reported.
If you spotted it first, help us to smash it by providing a detailed and welcomed
<a class="reference external" href="https://github.com/OCA/knowledge/issues/new?body=module:%20document_page_tag_print_control%0Aversion:%2016.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**">feedback</a>.</p>
<p>Do not contact contributors directly about support or help with technical issues.</p>
</div>
<div class="section" id="credits">
<h1><a class="toc-backref" href="#toc-entry-3">Credits</a></h1>
<div class="section" id="authors">
<h2><a class="toc-backref" href="#toc-entry-4">Authors</a></h2>
<ul class="simple">
<li>Sygel</li>
</ul>
</div>
<div class="section" id="contributors">
<h2><a class="toc-backref" href="#toc-entry-5">Contributors</a></h2>
<ul class="simple">
<li><a class="reference external" href="https://www.sygel.es">Sygel</a><ul>
<li>Juan Alberto Raja</li>
<li>Valentín Vinagre</li>
</ul>
</li>
</ul>
</div>
<div class="section" id="maintainers">
<h2><a class="toc-backref" href="#toc-entry-6">Maintainers</a></h2>
<p>This module is maintained by the OCA.</p>
<a class="reference external image-reference" href="https://odoo-community.org">
<img alt="Odoo Community Association" src="https://odoo-community.org/logo.png" />
</a>
<p>OCA, or the Odoo Community Association, is a nonprofit organization whose
mission is to support the collaborative development of Odoo features and
promote its widespread use.</p>
<p>This module is part of the <a class="reference external" href="https://github.com/OCA/knowledge/tree/16.0/document_page_tag_print_control">OCA/knowledge</a> project on GitHub.</p>
<p>You are welcome to contribute. To learn how please visit <a class="reference external" href="https://odoo-community.org/page/Contribute">https://odoo-community.org/page/Contribute</a>.</p>
</div>
</div>
</div>
</body>
</html>

View File

@ -0,0 +1,3 @@
# Copyright 2025 Juan Alberto Raja <juan.raja@sygel.es>
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
from . import test_document_page_tag_print_control

View File

@ -0,0 +1,90 @@
from odoo.exceptions import UserError
from odoo.tests import tagged
from odoo.tests.common import TransactionCase
@tagged("post_install", "-at_install")
class TestDocumentPrintControl(TransactionCase):
@classmethod
def setUpClass(cls):
super().setUpClass()
cls.printable_tag = cls.env["document.page.tag"].create(
{"name": "Printable", "is_not_printable": False}
)
cls.non_printable_tag = cls.env["document.page.tag"].create(
{"name": "Non-Printable", "is_not_printable": True}
)
cls.doc_without_tags = cls.env["document.page"].create(
{"name": "Document Without Tags", "content": "Content"}
)
cls.doc_printable = cls.env["document.page"].create(
{
"name": "Printable Document",
"content": "Content",
"tag_ids": [(4, cls.printable_tag.id)],
}
)
cls.doc_non_printable = cls.env["document.page"].create(
{
"name": "Non-Printable Document",
"content": "Content",
"tag_ids": [(4, cls.non_printable_tag.id)],
}
)
cls.doc_mixed_tags = cls.env["document.page"].create(
{
"name": "Mixed Tags Document",
"content": "Content",
"tag_ids": [(4, cls.printable_tag.id), (4, cls.non_printable_tag.id)],
}
)
def test_document_without_tags_is_printable(self):
"""Document without tags is printable."""
self.assertFalse(self.doc_without_tags.is_not_printable)
def test_document_with_printable_tag(self):
"""Document with printable tag is printable."""
self.assertFalse(self.doc_printable.is_not_printable)
def test_document_with_non_printable_tag(self):
"""Document with non-printable tag is not printable."""
self.assertTrue(self.doc_non_printable.is_not_printable)
def test_document_with_mixed_tags(self):
"""Document with mixed tags is not printable."""
self.assertTrue(self.doc_mixed_tags.is_not_printable)
def test_report_non_printable_raises_error(self):
"""Report fails if all documents are non-printable."""
with self.assertRaises(UserError) as ctx:
self.env["report.document_page.report_documentpage"]._get_report_values(
[self.doc_non_printable.id]
)
self.assertIn("None of the selected pages can be printed", str(ctx.exception))
def test_report_mixed_docs_raises_error(self):
"""Report fails if some documents are non-printable."""
with self.assertRaises(UserError) as ctx:
self.env["report.document_page.report_documentpage"]._get_report_values(
[self.doc_printable.id, self.doc_non_printable.id]
)
self.assertIn("Some pages cannot be printed", str(ctx.exception))
self.assertIn(self.doc_non_printable.name, str(ctx.exception))
def test_report_printable_docs(self):
"""Report returns correct values for printable documents."""
values = self.env[
"report.document_page.report_documentpage"
]._get_report_values([self.doc_printable.id])
self.assertEqual(values["doc_ids"], [self.doc_printable.id])
self.assertEqual(values["doc_model"], "document.page")
self.assertEqual(values["docs"].ids, [self.doc_printable.id])
def test_manager_bypasses_print_restrictions(self):
"""Manager can print any document."""
self.env.user.groups_id |= self.env.ref("document_page.group_document_manager")
values = self.env[
"report.document_page.report_documentpage"
]._get_report_values([self.doc_non_printable.id])
self.assertEqual(values["doc_ids"], [self.doc_non_printable.id])

View File

@ -0,0 +1,53 @@
<?xml version="1.0" encoding="utf-8" ?>
<!-- Copyright 2025 Juan Alberto Raja <juan.raja@sygel.es>
License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). -->
<odoo>
<record id="view_document_page_tag_form_extended" model="ir.ui.view">
<field name="name">document.page.tag.form.extended</field>
<field name="model">document.page.tag</field>
<field name="inherit_id" ref="document_page_tag.view_document_page_tag_form" />
<field name="arch" type="xml">
<field name="color" position="before">
<field name="is_not_printable" />
</field>
</field>
</record>
<record id="view_document_page_tag_tree_extended" model="ir.ui.view">
<field name="name">document.page.tag.tree.extended</field>
<field name="model">document.page.tag</field>
<field name="inherit_id" ref="document_page_tag.view_document_page_tag_tree" />
<field name="arch" type="xml">
<field name="color" position="after">
<field name="is_not_printable" />
</field>
</field>
</record>
<record id="view_document_page_tag_search_extended" model="ir.ui.view">
<field name="name">document.page.tag.search.extended</field>
<field name="model">document.page.tag</field>
<field
name="inherit_id"
ref="document_page_tag.view_document_page_tag_search"
/>
<field name="arch" type="xml">
<field name="name" position="after">
<field name="is_not_printable" />
</field>
<xpath expr="//filter[@name='inactive']" position="after">
<separator />
<filter
name="printable_tags"
string="Non-Printable Tags"
domain="[('is_not_printable', '=', True)]"
/>
<filter
name="non_printable_tags"
string="Printable Tags"
domain="[('is_not_printable', '=', False)]"
/>
</xpath>
</field>
</record>
</odoo>

View File

@ -0,0 +1 @@
../../../../document_page_tag_print_control

View File

@ -0,0 +1,6 @@
import setuptools
setuptools.setup(
setup_requires=['setuptools-odoo'],
odoo_addon=True,
)