diff --git a/migrations/5.0.25.5.0/post-0001_add_new_column.py b/migrations/5.0.25.5.0/post-0001_add_new_column.py new file mode 100644 index 0000000..dd60093 --- /dev/null +++ b/migrations/5.0.25.5.0/post-0001_add_new_column.py @@ -0,0 +1,18 @@ +from tools import config +import pooler + + +def up(cursor, installed_version): + if not installed_version or config.updating_all: + return + + pool = pooler.get_pool(cursor.dbname) + + pool.get("poweremail.templates")._auto_init(cursor, context={'module': 'poweremail'}) + + +def down(cursor, installed_version): + pass + + +migrate = up \ No newline at end of file diff --git a/poweremail_template.py b/poweremail_template.py index f7838d5..9165db3 100644 --- a/poweremail_template.py +++ b/poweremail_template.py @@ -396,6 +396,7 @@ def _get_model_data_name_search( 'report_template':fields.many2one( 'ir.actions.report.xml', 'Report to send'), + 'report_template_object_reference': fields.char('Reference of the report', size=300, required=False), #'report_template':fields.reference('Report to send',[('ir.actions.report.xml','Reports')],size=128), 'allowed_groups':fields.many2many( 'res.groups', @@ -905,6 +906,10 @@ def _generate_partner_events(self, return True def create_report(self, cursor, user, template, record_ids, context=None): + """" + Generate report to be attached and return it + If contain object_to_report_id in context, it will be used instead of record_ids + """ if context is None: context = {} report_obj = self.pool.get('ir.actions.report.xml') @@ -935,6 +940,7 @@ def _generate_attach_reports(self, cursor, user, template, record_ids, mail, con if context is None: context = {} lang = get_value(cursor, user, record_ids[0], template.lang, template, context=context) + record_reference_ids = record_ids ctx = context.copy() if lang: ctx['lang'] = lang @@ -949,14 +955,120 @@ def _generate_attach_reports(self, cursor, user, template, record_ids, mail, con return True + def _get_records_from_report_template_object_reference(self, cursor, user, template, record_ids, context=None): + """ + Evaluate the expression in report_template_object_reference field + to get the records to be used to generate the report. + + :param cursor: Database Cursor + :param user: ID of User + :param template: Browse record of template + :param record_ids: IDs of objects to be used to evaluate the expression + :param context: Context arguments + + :return: dict with model and record_ids keys evaluated from the expression + """ + res_ids = [] + expr = template.report_template_object_reference.replace('object', 'rec') + model = '' + for rec_obj in self.pool.get(template.object_name.model).simple_browse(cursor, user, record_ids, context=context): + try: + value = eval(expr, {}, {'rec': rec_obj}) + if not value: + continue + + if isinstance(value, (list, tuple)): + value = value[0] + + model = value._table_name + if hasattr(value, 'id'): + value = value.id + + res_ids.append(value) + except Exception as e: + LOGGER.notifyChannel( + _("Power Email"), + netsvc.LOG_DEBUG, + _("Error evaluating reference '%s' for record id %d: %s") % ( + template.report_template_object_reference, rec_obj.id, e) + ) + + return { + 'model': model, + 'record_ids': res_ids + } + + def create_report_from_report_template_object_reference_reference(self, cursor, user, template, record_ids, context=None): + """ + Generate report to be attached from the expression in report_template_object_reference field + and return it. + + :param cursor: Database Cursor + :param user: ID of User + :param template: Browse record of template + :param record_ids: IDs of template object + :param context: + :return: + """ + if 'object' not in template.report_template_object_reference: + LOGGER.notifyChannel( + _("Power Email"), + netsvc.LOG_ERROR, + _("Error evaluating reference: %s from record id %d. The expression must contain the 'object' variable.") % ( + template.report_template_object_reference, template.id) + ) + + refs = self._get_records_from_report_template_object_reference(cursor, + user, + template, + record_ids, + context=context) + if not refs.get('record_ids', []): + LOGGER.notifyChannel( + _("Power Email"), + netsvc.LOG_ERROR, + _("Error evaluating reference: %s from record id %d. The expression did not return any record.") % ( + template.report_template_object_reference, template.id) + ) + + return self.create_report(cursor, user, template, + refs.get('record_ids', []), + context=context) + def get_dynamic_attachment(self, cursor, user, template, record_ids, context=None): - res = {} - if template.report_template: - report_vals = self.create_report(cursor, user, template, record_ids, context=context) - res = { - 'file': base64.b64encode(report_vals[0]), - 'extension': report_vals[1] - } + """ + Generate report to be attached and return it. If contain a report_template_object_reference field, + it will generate the report from the records evaluated from the expression in that field. Ignoring + the record_ids parameter. + + :param cursor: Database Cursor + :param user: ID of User + :param template: Browse record of template + :param record_ids: IDs of template object + :param context: Context arguments + + :return: List of dicts with 'file' (base64 encoded) and 'extension' keys + """ + res = [] + if template.report_template_object_reference: + try: + report_vals = self.create_report_from_report_template_object_reference_reference( + cursor, user, template, record_ids, context=context + ) + except Exception as e: + LOGGER.notifyChannel( + _("Power Email"), + netsvc.LOG_ERROR, + _("Error evaluating reference: %s from record id %d. Error: %s") % (template.report_template_object_reference, template.id, e) + ) + else: + report_vals = self.create_report(cursor, user, template, record_ids, + context=context) + res.append({ + 'file': base64.b64encode(report_vals[0].encode()), + 'extension': report_vals[1] + }) + return res def set_dynamic_attachments(self, cursor, user, template, mail, record_ids, context=None): @@ -966,9 +1078,9 @@ def set_dynamic_attachments(self, cursor, user, template, mail, record_ids, cont mailbox_obj = self.pool.get('poweremail.mailbox') res = False - dynamic_attachment = self.get_dynamic_attachment(cursor, user, template, record_ids, context=context) + dynamic_attachments = self.get_dynamic_attachment(cursor, user, template, record_ids, context=context) - if dynamic_attachment: + for dynamic_attachment in dynamic_attachments: new_att_vals = { 'name': mail.pem_subject + ' (Email Attachment)', 'datas': dynamic_attachment['file'], diff --git a/poweremail_template_view.xml b/poweremail_template_view.xml index 3ff5ce6..75093dd 100644 --- a/poweremail_template_view.xml +++ b/poweremail_template_view.xml @@ -72,7 +72,7 @@