odoo pdf 打印任务后台运行,pdf保存在附件中, 借助queue_job模块实现后台打印

发布时间 2023-08-18 15:16:19作者: 那时一个人

用户故事:

在打印大批量pdf 文件时会有较长事件的等待, 而且容易中断

原因

中断原因, 有内存及超时限制,wkhtmltopdf工具比较吃内存

解决方案:

内存限制的问题可以分批处理,比如每次只处理50条记录

代码示例,使用按钮触发的打印功能:

# model: res.partner
  
    @api.model
    def save_attachment(self, datas,report_name, file_name,res_id=None, res_model='queue.job'):
        """
        <record id="documents_vendor_bill_extract_azure_interior" model="ir.attachment">
            <field name="name">Invoice Azure Interior</field>
            <field name="datas_fname">invoice_azure_interior.pdf</field>
            <field name="datas" type="base64" file="documents/demo/files/invoice_azure_interior.pdf"/>
            <field name="folder_id" ref="documents_finance_folder"/>
        </record>
        pdf文件保存在附件中,并绑定queque_job 记录
        """
        attach = self.env['ir.attachment']
        var = dict(name=report_name,
                   datas_fname=file_name,
                   datas=base64.b64encode(datas).decode('utf-8'),
                   folder_id=self.env.ref('documents.documents_finance_folder').id,
                   res_model=res_model,
                   res_id=res_id
                   )
        attach.create([var])

    def do_button_print_statement(self):

        _logger.info('do_button_print_statement_context:{}'.format(self._context))
        report_info = self.env.ref('account_statement.report_customert_print').report_action(self)
        if self._context.get('is_backend'):
            # 用户可以选择是否后台运行打印任务
            self.save_in_attachment(report_info)
            return None
        return report_info

    @api.model
    def save_in_attachment(self, report_info):
        """
        将打印的文件保存在附件中,odoo 服务器中,不直接下载, 针对打印的pdf 数量太多的情况
        """
        report_name = report_info.get('report_name')
        name = report_info.get('name')
        report_type = report_info.get('report_type')
        report = self.env['ir.actions.report']._get_report_from_name(report_name)
        context = report_info.get('context')
        context.update(date_end = str(context.get('date_end')))

        list_pdf_bytes = []
        for list_id in list_split(self.ids, 50):
            pdf_bytes = report.with_context(context).render_qweb_pdf(list_id, data=context)[0]
            list_pdf_bytes.append(pdf_bytes)
        sum_pdf = merge_pdf(list_pdf_bytes)
        job_uid = context.get('job_uuid')
        queue = self.env['queue.job'].search([('uuid','=',job_uid)])
        self.save_attachment(sum_pdf, name, '{}.pdf'.format(name), queue.id)
        queue.message_subscribe(partner_ids=queue.user_id.partner_id.ids)
        queue.sudo().message_post(body='Report generate success!', message_type='notification', subtype='queue_job.mt_job_failed')

效果展示

  1. 后台任务完成后会发送完成提示
    image
    image

  2. 附件可以在queue_job 记录中获取
    image

  3. 附件可以在document 模块中中获取
    image

  4. 前端界面:
    image