diff --git a/hr_expense_report_merge_attachment/README.rst b/hr_expense_report_merge_attachment/README.rst new file mode 100644 index 0000000..8ee66eb --- /dev/null +++ b/hr_expense_report_merge_attachment/README.rst @@ -0,0 +1,47 @@ +============================== +hr_expense_report_merge_attachment +============================== + +Merge attachments in expense report. + +Managed attachment types : +* PDF +* Images + +Installation +============ + +Use Odoo normal module installation procedure to install +``hr_expense_report_merge_attachment``. + +Known issues / Roadmap +====================== + +None yet. +Bug Tracker +=========== + +Bugs are tracked on `our issues website `_. In case of +trouble, please check there if your issue has already been +reported. If you spotted it first, help us smashing it by providing a +detailed and welcomed feedback. + +Credits +======= + +Contributors +------------ + +* Clément Thomas + +Funders +------- + +The development of this module has been financially supported by: +* Elabore (https://elabore.coop) + + +Maintainer +---------- + +This module is maintained by Elabore. diff --git a/hr_expense_report_merge_attachment/__init__.py b/hr_expense_report_merge_attachment/__init__.py new file mode 100644 index 0000000..457bae2 --- /dev/null +++ b/hr_expense_report_merge_attachment/__init__.py @@ -0,0 +1,3 @@ +# -*- coding: utf-8 -*- + +from . import controllers \ No newline at end of file diff --git a/hr_expense_report_merge_attachment/__manifest__.py b/hr_expense_report_merge_attachment/__manifest__.py new file mode 100644 index 0000000..7a5cdc7 --- /dev/null +++ b/hr_expense_report_merge_attachment/__manifest__.py @@ -0,0 +1,34 @@ +# Copyright 2023 Stéphan Sainléger (Elabore) +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +{ + "name": "hr_effective_attendance_period", + "version": "14.0.0.0.0", + "author": "Elabore", + "website": "https://elabore.coop", + "maintainer": "Clément Thomas", + "license": "AGPL-3", + "category": "Tools", + "summary": "Merge attachments in expense report", + # any module necessary for this one to work correctly + "depends": [ + "hr_expense", + ], + "qweb": [ + ], + "external_dependencies": { + "python": [], + }, + # always loaded + "data": [ + ], + # only loaded in demonstration mode + "demo": [], + "js": [], + "css": [], + "installable": True, + # Install this module automatically if all dependency have been previously + # and independently installed. Used for synergetic or glue modules. + "auto_install": False, + "application": False, +} \ No newline at end of file diff --git a/hr_expense_report_merge_attachment/controllers/__init__.py b/hr_expense_report_merge_attachment/controllers/__init__.py new file mode 100644 index 0000000..6920e20 --- /dev/null +++ b/hr_expense_report_merge_attachment/controllers/__init__.py @@ -0,0 +1,3 @@ +# -*- coding: utf-8 -*- + +from . import main \ No newline at end of file diff --git a/hr_expense_report_merge_attachment/controllers/main.py b/hr_expense_report_merge_attachment/controllers/main.py new file mode 100644 index 0000000..89ecf0d --- /dev/null +++ b/hr_expense_report_merge_attachment/controllers/main.py @@ -0,0 +1,69 @@ +import odoo.addons.web.controllers.main as main +import ast +import base64 +import io +from odoo.tools.pdf import OdooPdfFileReader, OdooPdfFileWriter +import PyPDF2 +import logging +from odoo import http +from reportlab.pdfgen import canvas +from reportlab.lib.utils import ImageReader +from reportlab.lib.pagesizes import letter, A4 + +logger = logging.getLogger(__name__) + + +class Extension(main.ReportController): + + @http.route(['/report/download'], type='http', auth="user") + def report_download(self, data, token, context=None): + """ + In case of hr expense sheet report : merge PDF with other attachments + """ + + res = super(Extension,self).report_download(data, token, context) + + if "hr_expense.report_expense_sheet" in ast.literal_eval(data)[0]: #check if we are generating expense sheet report pdf + writer = OdooPdfFileWriter() #Open a file writer to create new PDF + + # Open main pdf and read it and write it page by page in new pdf + main_pdf_reader = OdooPdfFileReader(io.BytesIO(res.data), strict=False) + for n in range(main_pdf_reader.getNumPages()): + writer.addPage(main_pdf_reader.getPage(n)) + + # Parse data (last char after "/") to get id of current sheet + expense_sheet_id = int(ast.literal_eval(data)[0].split('/')[-1]) + + # Get ids of related expenses + expense_ids = [e.id for e in http.request.env['hr.expense.sheet'].browse(expense_sheet_id).expense_line_ids] + + # Get related attachments + attachments = http.request.env['ir.attachment'].search([('res_id','in',expense_ids),('res_model','=','hr.expense')]) + + # Open each attachments, and write it page by page in new pdf + for att in attachments: + if att.mimetype == "application/pdf": + try: + attachment_reader = OdooPdfFileReader(io.BytesIO(base64.b64decode(att.datas)), strict=False) + for n in range(attachment_reader.getNumPages()): + writer.addPage(attachment_reader.getPage(n)) + except PyPDF2.utils.PdfReadError: # Case of non-pdf attachments + logger.info('Attachment %s cannot be merged in expense report'%(att.name,)) + elif 'image/' in att.mimetype: + packet = io.BytesIO() + can = canvas.Canvas(packet) + img = ImageReader(io.BytesIO(base64.b64decode(att.datas))) + can.drawImage(img, 0, 0, A4[0]*0.9, A4[1]*0.9, preserveAspectRatio=True) + can.save() + packet.seek(0) + attachment_reader = OdooPdfFileReader(packet) + writer.addPage(attachment_reader.getPage(0)) + + # Write new pdf to res.data + buffer = io.BytesIO() + writer.write(buffer) + pdf_content = buffer.getvalue() + + res.data = pdf_content + + return res \ No newline at end of file