mirror of
https://github.com/OCA/knowledge.git
synced 2025-07-16 04:02:56 -06:00
[ADD] document_print_control: restrict document printing based on tag configuration
This commit is contained in:
parent
62ebf2ba86
commit
32e5cbbce5
3
document_print_control/__init__.py
Normal file
3
document_print_control/__init__.py
Normal 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
|
22
document_print_control/__manifest__.py
Normal file
22
document_print_control/__manifest__.py
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
# Copyright 2025 Juan Alberto Raja <juan.raja@sygel.es>
|
||||||
|
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
|
||||||
|
{
|
||||||
|
"name": "Document 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",
|
||||||
|
"document_page_tag",
|
||||||
|
],
|
||||||
|
"data": [
|
||||||
|
"views/document_page_tag.xml",
|
||||||
|
"views/document_page.xml",
|
||||||
|
],
|
||||||
|
"installable": True,
|
||||||
|
"application": False,
|
||||||
|
"auto_install": False,
|
||||||
|
}
|
46
document_print_control/i18n/ca_ES.po
Normal file
46
document_print_control/i18n/ca_ES.po
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
# Translation of Odoo Server.
|
||||||
|
# * document_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_print_control
|
||||||
|
#: model:ir.model.fields,field_description:document_print_control.field_document_page_tag__is_printable
|
||||||
|
msgid "Is Printable"
|
||||||
|
msgstr "És imprimible"
|
||||||
|
|
||||||
|
#. module: document_print_control
|
||||||
|
#: model:ir.model.fields,help:document_print_control.field_document_page__is_printable
|
||||||
|
msgid "Indicates if the document can be printed based on its tags"
|
||||||
|
msgstr "Indica si el document es pot imprimir basant-se en les seves etiquetes"
|
||||||
|
|
||||||
|
#. module: document_print_control
|
||||||
|
#: model:ir.model.fields,help:document_print_control.field_document_page_tag__is_printable
|
||||||
|
msgid "If unchecked, pages with this tag cannot be printed"
|
||||||
|
msgstr "Si està desmarcat, les pàgines amb aquesta etiqueta no es poden imprimir"
|
||||||
|
|
||||||
|
#. module: document_print_control
|
||||||
|
#: model_terms:ir.ui.view,arch_db:document_print_control.view_document_page_form_inherit_print
|
||||||
|
msgid "Print"
|
||||||
|
msgstr "Imprimir"
|
||||||
|
|
||||||
|
#. module: document_print_control
|
||||||
|
#: model_terms:ir.ui.view,arch_db:document_print_control.view_document_page_tag_search_extended
|
||||||
|
msgid "Printable Tags"
|
||||||
|
msgstr "Etiquetes imprimibles"
|
||||||
|
|
||||||
|
#. module: document_print_control
|
||||||
|
#: model_terms:ir.ui.view,arch_db:document_print_control.view_document_page_tag_search_extended
|
||||||
|
msgid "Non-Printable Tags"
|
||||||
|
msgstr "Etiquetes no imprimibles"
|
46
document_print_control/i18n/es.po
Normal file
46
document_print_control/i18n/es.po
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
# Translation of Odoo Server.
|
||||||
|
# * document_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_print_control
|
||||||
|
#: model:ir.model.fields,field_description:document_print_control.field_document_page_tag__is_printable
|
||||||
|
msgid "Is Printable"
|
||||||
|
msgstr "Es imprimible"
|
||||||
|
|
||||||
|
#. module: document_print_control
|
||||||
|
#: model:ir.model.fields,help:documents_print_control.field_document_page__is_printable
|
||||||
|
msgid "Indicates if the document can be printed based on its tags"
|
||||||
|
msgstr "Indica si el documento puede ser impreso basándose en sus etiquetas"
|
||||||
|
|
||||||
|
#. module: document_print_control
|
||||||
|
#: model:ir.model.fields,help:documents_print_control.field_document_page_tag__is_printable
|
||||||
|
msgid "If unchecked, pages with this tag cannot be printed"
|
||||||
|
msgstr "Si está desmarcado, las páginas con esta etiqueta no se pueden imprimir"
|
||||||
|
|
||||||
|
#. module: document_print_control
|
||||||
|
#: model_terms:ir.ui.view,arch_db:document_print_control.view_document_page_form_inherit_print
|
||||||
|
msgid "Print"
|
||||||
|
msgstr "Imprimir"
|
||||||
|
|
||||||
|
#. module: document_print_control
|
||||||
|
#: model_terms:ir.ui.view,arch_db:document_print_control.view_document_page_tag_search_extended
|
||||||
|
msgid "Printable Tags"
|
||||||
|
msgstr "Etiquetas imprimibles"
|
||||||
|
|
||||||
|
#. module: document_print_control
|
||||||
|
#: model_terms:ir.ui.view,arch_db:document_print_control.view_document_page_tag_search_extended
|
||||||
|
msgid "Non-Printable Tags"
|
||||||
|
msgstr "Etiquetas no imprimibles"
|
4
document_print_control/models/__init__.py
Normal file
4
document_print_control/models/__init__.py
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
# 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
|
25
document_print_control/models/document_page.py
Normal file
25
document_print_control/models/document_page.py
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
from odoo import api, fields, models
|
||||||
|
|
||||||
|
|
||||||
|
class DocumentPage(models.Model):
|
||||||
|
_inherit = "document.page"
|
||||||
|
|
||||||
|
is_printable = fields.Boolean(
|
||||||
|
compute="_compute_is_printable",
|
||||||
|
store=True,
|
||||||
|
help="Indicates if the document can be printed based on its tags",
|
||||||
|
)
|
||||||
|
|
||||||
|
@api.depends("tag_ids", "tag_ids.is_printable")
|
||||||
|
def _compute_is_printable(self):
|
||||||
|
for record in self:
|
||||||
|
if not record.tag_ids:
|
||||||
|
record.is_printable = True
|
||||||
|
else:
|
||||||
|
record.is_printable = all(tag.is_printable for tag in record.tag_ids)
|
||||||
|
|
||||||
|
def action_print_document_page(self):
|
||||||
|
for record in self:
|
||||||
|
if not record.is_printable:
|
||||||
|
return None
|
||||||
|
return self.env.ref("document_page.report_document_page").report_action(self)
|
18
document_print_control/models/document_page_tag.py
Normal file
18
document_print_control/models/document_page_tag.py
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
# 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 DocumentPageTag(models.Model):
|
||||||
|
_inherit = "document.page.tag"
|
||||||
|
|
||||||
|
is_printable = fields.Boolean(
|
||||||
|
default=True,
|
||||||
|
help="If unchecked, pages with this tag cannot be printed",
|
||||||
|
)
|
||||||
|
|
||||||
|
@api.model
|
||||||
|
def create(self, vals):
|
||||||
|
if "is_printable" not in vals:
|
||||||
|
vals["is_printable"] = True
|
||||||
|
return super().create(vals)
|
5
document_print_control/readme/CONTRIBUTORS.md
Normal file
5
document_print_control/readme/CONTRIBUTORS.md
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
|
||||||
|
> - [Sygel](https://www.sygel.es):
|
||||||
|
>
|
||||||
|
> > - Juan Alberto Raja Martinez\<<juan.raja@sygel.es>\>
|
||||||
|
> > - Valentín Vinagre Urteaga\<<valentin.vinagre@sygel.es>\>
|
1
document_print_control/readme/DESCRIPTION.md
Normal file
1
document_print_control/readme/DESCRIPTION.md
Normal file
@ -0,0 +1 @@
|
|||||||
|
This module adds print control functionality to document pages based on tags. It allows users to control which document pages can be printed by configuring tags with a "printable" attribute. When a document page has tags marked as non-printable, the print button will be hidden and the printing functionality will be disabled for that document.
|
8
document_print_control/readme/USAGE.md
Normal file
8
document_print_control/readme/USAGE.md
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
If you want to control the printing of document pages using tags:
|
||||||
|
|
||||||
|
1. Go to Document Management, then to Configuration, and open Tags.
|
||||||
|
2. Create or edit existing tags and use the "Is Printable" checkbox to control printing permissions.
|
||||||
|
3. Uncheck "Is Printable" for tags that should prevent document printing.
|
||||||
|
4. Assign these tags to document pages - if any tag on a document page is marked as non-printable, the entire document becomes non-printable.
|
||||||
|
5. The print button will automatically hide for non-printable documents, and printing functionality will be disabled.
|
||||||
|
6. All tags are printable by default to maintain backward compatibility.
|
BIN
document_print_control/static/description/icon.png
Normal file
BIN
document_print_control/static/description/icon.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 9.2 KiB |
3
document_print_control/tests/__init__.py
Normal file
3
document_print_control/tests/__init__.py
Normal 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_print_control
|
90
document_print_control/tests/test_document_print_control.py
Normal file
90
document_print_control/tests/test_document_print_control.py
Normal file
@ -0,0 +1,90 @@
|
|||||||
|
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 Tag",
|
||||||
|
"is_printable": True,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
cls.non_printable_tag = cls.env["document.page.tag"].create(
|
||||||
|
{
|
||||||
|
"name": "Non-Printable Tag",
|
||||||
|
"is_printable": False,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
cls.doc_without_tags = cls.env["document.page"].create(
|
||||||
|
{
|
||||||
|
"name": "Document without tags",
|
||||||
|
"content": "Test content without tags",
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
cls.doc_with_printable_tag = cls.env["document.page"].create(
|
||||||
|
{
|
||||||
|
"name": "Document with printable tag",
|
||||||
|
"content": "Test content with printable tag",
|
||||||
|
"tag_ids": [(4, cls.printable_tag.id)],
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
cls.doc_with_non_printable_tag = cls.env["document.page"].create(
|
||||||
|
{
|
||||||
|
"name": "Document with non-printable tag",
|
||||||
|
"content": "Test content with non-printable tag",
|
||||||
|
"tag_ids": [(4, cls.non_printable_tag.id)],
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
cls.doc_with_mixed_tags = cls.env["document.page"].create(
|
||||||
|
{
|
||||||
|
"name": "Document with mixed tags",
|
||||||
|
"content": "Test content with mixed tags",
|
||||||
|
"tag_ids": [(4, cls.printable_tag.id), (4, cls.non_printable_tag.id)],
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_printable_without_tags(self):
|
||||||
|
"""Documents without tags should be printable by default"""
|
||||||
|
self.assertTrue(self.doc_without_tags.is_printable)
|
||||||
|
|
||||||
|
def test_printable_with_allowed_tags(self):
|
||||||
|
"""Documents with only printable tags should be printable"""
|
||||||
|
self.assertTrue(self.doc_with_printable_tag.is_printable)
|
||||||
|
|
||||||
|
def test_not_printable_with_restricted_tags(self):
|
||||||
|
"""Documents with non-printable tags should not be printable"""
|
||||||
|
self.assertFalse(self.doc_with_non_printable_tag.is_printable)
|
||||||
|
|
||||||
|
def test_not_printable_with_mixed_tags(self):
|
||||||
|
"""Documents with mixed tags should not be printable"""
|
||||||
|
self.assertFalse(self.doc_with_mixed_tags.is_printable)
|
||||||
|
|
||||||
|
def test_print_action_allowed_documents(self):
|
||||||
|
"""Print action should return report for printable documents"""
|
||||||
|
result = self.doc_with_printable_tag.action_print_document_page()
|
||||||
|
self.assertIsNotNone(result)
|
||||||
|
self.assertIn("context", result)
|
||||||
|
self.assertIn("report_action", result["context"])
|
||||||
|
self.assertIn("report_name", result["context"]["report_action"])
|
||||||
|
|
||||||
|
def test_print_action_restricted_documents(self):
|
||||||
|
"""Print action should return None for non-printable documents"""
|
||||||
|
result = self.doc_with_non_printable_tag.action_print_document_page()
|
||||||
|
self.assertIsNone(result)
|
||||||
|
|
||||||
|
def test_tag_default_is_printable(self):
|
||||||
|
"""Tags created without is_printable should default to True"""
|
||||||
|
tag = self.env["document.page.tag"].create(
|
||||||
|
{"name": "Test Tag Without is_printable"}
|
||||||
|
)
|
||||||
|
self.assertTrue(tag.is_printable)
|
33
document_print_control/views/document_page.xml
Normal file
33
document_print_control/views/document_page.xml
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
<?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="document_page.report_document_page" model="ir.actions.report">
|
||||||
|
<field name="binding_type">action</field>
|
||||||
|
<field name="binding_view_types" eval="False" />
|
||||||
|
</record>
|
||||||
|
|
||||||
|
<record id="view_document_page_form_inherit_print" model="ir.ui.view">
|
||||||
|
<field name="name">document.page.form.inherit.print</field>
|
||||||
|
<field name="model">document.page</field>
|
||||||
|
<field name="inherit_id" ref="document_page.view_wiki_form" />
|
||||||
|
<field name="arch" type="xml">
|
||||||
|
<xpath expr="//form" position="inside">
|
||||||
|
<field name="is_printable" invisible="0" />
|
||||||
|
</xpath>
|
||||||
|
|
||||||
|
<xpath expr="//sheet" position="before">
|
||||||
|
<header>
|
||||||
|
<button
|
||||||
|
name="action_print_document_page"
|
||||||
|
type="object"
|
||||||
|
string="Print"
|
||||||
|
icon="fa-print"
|
||||||
|
class="oe_highlight"
|
||||||
|
attrs="{'invisible': [('is_printable', '=', False)]}"
|
||||||
|
/>
|
||||||
|
</header>
|
||||||
|
</xpath>
|
||||||
|
</field>
|
||||||
|
</record>
|
||||||
|
</odoo>
|
53
document_print_control/views/document_page_tag.xml
Normal file
53
document_print_control/views/document_page_tag.xml
Normal 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_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_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_printable" />
|
||||||
|
</field>
|
||||||
|
<xpath expr="//filter[@name='inactive']" position="after">
|
||||||
|
<separator />
|
||||||
|
<filter
|
||||||
|
name="printable_tags"
|
||||||
|
string="Printable Tags"
|
||||||
|
domain="[('is_printable', '=', True)]"
|
||||||
|
/>
|
||||||
|
<filter
|
||||||
|
name="non_printable_tags"
|
||||||
|
string="Non-Printable Tags"
|
||||||
|
domain="[('is_printable', '=', False)]"
|
||||||
|
/>
|
||||||
|
</xpath>
|
||||||
|
</field>
|
||||||
|
</record>
|
||||||
|
</odoo>
|
Loading…
Reference in New Issue
Block a user