Skip to content
Open
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
2 changes: 2 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,8 @@ jobs:
- uses: actions/checkout@v4
with:
persist-credentials: false
- name: Install Ghostscript
run: apt-get update && apt-get install -y ghostscript
- name: Install addons and dependencies
run: oca_install_addons
- name: Check licenses
Expand Down
141 changes: 141 additions & 0 deletions attachment_pdfa/README.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
================
Attachment PDF/A
================

..
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! This file is generated by oca-gen-addon-readme !!
!! changes will be overwritten. !!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! source digest: sha256:607a7dc56a5708440b64968c78229b78bc02b715336989ba87460c94bd98e2fb
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

.. |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-LGPL--3-blue.png
:target: http://www.gnu.org/licenses/lgpl-3.0-standalone.html
:alt: License: LGPL-3
.. |badge3| image:: https://img.shields.io/badge/github-OCA%2Fstorage-lightgray.png?logo=github
:target: https://github.com/OCA/storage/tree/18.0/attachment_pdfa
:alt: OCA/storage
.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png
:target: https://translation.odoo-community.org/projects/storage-18-0/storage-18-0-attachment_pdfa
: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/storage&target_branch=18.0
:alt: Try me on Runboat

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

This module extends Odoo's attachment system to support automatic
conversion of PDF files to the **PDF/A-3** format.

**Table of contents**

.. contents::
:local:

Use Cases / Context
===================

In many legal frameworks and corporate archiving policies, business
documents must be stored in a compliant, long-term preservation format
like **PDF/A-3**.

This module provides a flexible framework to automate PDF to PDF/A-3
conversion upon attachment creation:

- **Opt-in via Mixin**: Rather than blindly converting all system PDFs,
models must opt-in by inheriting ``attachment.pdfa.mixin`` and
defining conditional rules.
- **Pluggable Engine**: Offers conversion via **Ghostscript** or
**Odoo**.
- **Chatter Integration**: Non-blocking conversion pipeline — if the
conversion generates warnings or errors during conversion, details are
posted directly as internal notes in the record's Chatter.

Installation
============

To install and use Ghostscript conversion (default engine):

1. Ensure Ghostscript is installed on your Odoo server host system.
2. Ensure the ``gs`` binary is available in the system execution PATH of
the user running Odoo.

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

To configure this module:

1. Go to **Settings** > **General Settings**.

2. Scroll down to the **PDF/A Conversion** section under *Document
Settings*.

3. Select your preferred conversion method:

- **Ghostscript** (default).
- **Odoo**.
- **Disable**: Disables automatic conversion globally.

4. Click **Save**.

Usage
=====

To use this module:

1. Create or generate a PDF attachment on a record whose model
implements ``attachment.pdfa.mixin`` (and where
``_attachment_must_be_pdfa()`` evaluates to ``True``).
2. The created PDF is automatically converted to PDF/A-3.
3. If the conversion encounters any non-fatal warnings or fails to
convert the file, a log note is automatically posted to the record's
**Chatter**, allowing administrators and users to review the
conversion output.

Bug Tracker
===========

Bugs are tracked on `GitHub Issues <https://github.com/OCA/storage/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/storage/issues/new?body=module:%20attachment_pdfa%0Aversion:%2018.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
-------

* ACSONE SA/NV

Contributors
------------

- Zina Rasoamanana zina.rasoamanana@acsone.eu
(`Acsone <https://acsone.eu>`__)
- Benoit Aimont benoit.aimont@acsone.eu (`Acsone <https://acsone.eu>`__)
- Stéphane Bidoul stephane.bidoul@acsone.eu
(`Acsone <https://acsone.eu>`__)

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/storage <https://github.com/OCA/storage/tree/18.0/attachment_pdfa>`_ project on GitHub.

You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.
1 change: 1 addition & 0 deletions attachment_pdfa/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
from . import models
26 changes: 26 additions & 0 deletions attachment_pdfa/__manifest__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# Copyright 2026 ACSONE SA/NV
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl).

{
"name": "Attachment PDF/A",
"summary": """Convert PDF attachments to PDF/A""",
"version": "18.0.1.0.0",
"category": "Storage",
"license": "LGPL-3",
"author": "ACSONE SA/NV, Odoo Community Association (OCA)",
"website": "https://github.com/OCA/storage",
"depends": [
"mail",
],
"data": [
"data/config_parameter.xml",
"data/pdfa3_metadata.xml",
"views/res_config_settings.xml",
],
"external_dependencies": {
"bin": [
"gs",
],
},
"installable": True,
}
9 changes: 9 additions & 0 deletions attachment_pdfa/data/config_parameter.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8" ?>
<!-- Copyright 2026 ACSONE SA/NV
License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl). -->
<odoo noupdate="1">
<record id="function_convert_pdfa" model="ir.config_parameter">
<field name="key">attachment_pdfa.method</field>
<field name="value">ghostscript</field>
</record>
</odoo>
Binary file added attachment_pdfa/data/iccprofiles_default_rgb.icc
Binary file not shown.
46 changes: 46 additions & 0 deletions attachment_pdfa/data/pdfa3_metadata.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
<?xml version="1.0" encoding="UTF-8" ?>
<odoo>
<template id="pdfa3_metadata">
<x:xmpmeta xmlns:x="adobe:ns:meta/">
<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
<rdf:Description
xmlns:pdfaid="http://www.aiim.org/pdfa/ns/id/"
rdf:about=""
>
<pdfaid:part>3</pdfaid:part>
<pdfaid:conformance>B</pdfaid:conformance>
</rdf:Description>
<rdf:Description
xmlns:dc="http://purl.org/dc/elements/1.1/"
rdf:about=""
>
<dc:title>
<rdf:Alt>
<rdf:li t-att="{'xml:lang': 'x-default'}" t-out="title" />
</rdf:Alt>
</dc:title>
<dc:creator>
<rdf:Seq>
<rdf:li>Odoo</rdf:li>
</rdf:Seq>
</dc:creator>
<dc:description>
<rdf:Alt>
<rdf:li
t-att="{'xml:lang': 'x-default'}"
>PDF/A3 generated by Odoo</rdf:li>
</rdf:Alt>
</dc:description>
</rdf:Description>
<rdf:Description xmlns:pdf="http://ns.adobe.com/pdf/1.3/" rdf:about="">
<pdf:Producer>Odoo</pdf:Producer>
</rdf:Description>
<rdf:Description xmlns:xmp="http://ns.adobe.com/xap/1.0/" rdf:about="">
<xmp:CreatorTool>Odoo</xmp:CreatorTool>
<xmp:CreateDate t-out="date" />
<xmp:ModifyDate t-out="date" />
</rdf:Description>
</rdf:RDF>
</x:xmpmeta>
</template>
</odoo>
Binary file added attachment_pdfa/data/pdfa_def.ps
Binary file not shown.
3 changes: 3 additions & 0 deletions attachment_pdfa/models/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
from . import attachment_pdfa_mixin
from . import res_config_settings
from . import ir_attachment
12 changes: 12 additions & 0 deletions attachment_pdfa/models/attachment_pdfa_mixin.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# Copyright 2026 ACSONE SA/NV
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl).

from odoo import models


class AttachmentPdfaMixin(models.AbstractModel):
_name = "attachment.pdfa.mixin"
_description = "Attachment PDF/A Mixin"

def _attachment_must_be_pdfa(self):
return False
Loading
Loading