I'm stuck.
My db is currently hosted with Odoo Online v17.1, and I need to print/download a large number of sales orders as separate PDFs. I have multiple batches of 50-100 quotes each.
I find that from the list view, selecting multiple quotes/orders and using any of the Print button/menu options concatenates all selected items into a single PDF. While useful for most other report types, that is extremely annoying for quotes, sales orders, invoices, proforma invoices, purchase orders, etc.
I chased multiple solutions, none of which will work with Odoo Online. I tried implementing a Server Action. Turns out 'safe_eval.py' is tight as hell. No 'import' statements, nor 'base64' or 'zipfile' built-ins. Then I tried writing my own module. Turns out custom python isn't even allowed Online, only on .sh or On-premise.
But I can't switch to either of those, because my db is already on 17.1, and I've just learned that downgrading is not an option, and Odoo.sh / On-Premise do not support intermediary versions.
I also find that people have been asking about this for the last 5+ years. What gives??? This is a simple as hell module. Why is something like this not already part of the code base?
from odoo import models, fields, api
import base64
import zipfile
import io
class SaleOrder(models.Model):
_inherit = 'sale.order'
@api.multi
def batch_print_pdfs(self):
report_template = 'sale.report_saleorder'
download_urls = []
for order in self:
pdf_content, _ = self.env.ref(report_template)._render_qweb_pdf([order.id])
attachment = self.env['ir.attachment'].create({
'name': f'SaleOrder_{order.name}.pdf',
'type': 'binary',
'datas': base64.b64encode(pdf_content),
'res_model': 'sale.order',
'res_id': order.id,
'mimetype': 'application/pdf'
})
download_urls.append(f'/web/content/{attachment.id}?download=true')
js_downloads = "".join([f"window.open('{url}');" for url in download_urls])
return {
'type': 'ir.actions.client',
'tag': 'action_warn',
'params': {
'title': 'Downloading...',
'message': 'Your files are being downloaded. Please check your browser\'s download manager.',
'sticky': False,
'next': {'type': 'ir.actions.client', 'tag': 'reload'}
},
'context': {'js': js_downloads},
}
@api.multi
def batch_print_pdfs_zipped(self):
report_template = 'sale.report_saleorder'
attachments = []
for order in self:
pdf_content, _ = self.env.ref(report_template)._render_qweb_pdf([order.id])
pdf_base64 = base64.b64encode(pdf_content)
attachment = self.env['ir.attachment'].create({
'name': f'SaleOrder_{order.name}.pdf',
'type': 'binary',
'datas': pdf_base64,
'res_model': 'sale.order',
'res_id': order.id,
'mimetype': 'application/pdf'
})
attachments.append(attachment)
zip_buffer = io.BytesIO()
with zipfile.ZipFile(zip_buffer, 'w', zipfile.ZIP_DEFLATED) as zip_file:
for attachment in attachments:
pdf_data = base64.b64decode(attachment.datas)
zip_file.writestr(attachment.name, pdf_data)
zip_buffer.seek(0)
zip_data = zip_buffer.read()
zip_base64 = base64.b64encode(zip_data)
zip_attachment = self.env['ir.attachment'].create({
'name': 'sale_orders.zip',
'type': 'binary',
'datas': zip_base64,
'res_model': 'sale.order',
'res_id': self[0].id,
'mimetype': 'application/zip'
})
return {
'type': 'ir.actions.act_url',
'url': f'/web/content/{zip_attachment.id}?download=true',
'target': 'self',
}
The only thing left to try would be via the API?