Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
17 commits
Select commit Hold shift + click to select a range
e7bbc17
feat: get ids from the new columns to attach
gpozo-gisce Feb 19, 2025
125d7dc
feat: add column necessary to make the attachments
gpozo-gisce Feb 20, 2025
1218edb
test: add test to check if the attachments is created with the conten…
gpozo-gisce Feb 20, 2025
92d1373
refactor: requested changes
gpozo-gisce Feb 28, 2025
fbcb7b7
Merge branch 'v5_backport' into 69731_add_attach_into_mails
gpozo-gisce Feb 28, 2025
2b881e9
test: check attaches for specifics report attach values
gpozo-gisce Feb 28, 2025
767a9d6
fix: create new function to evalute the new column conditions
gpozo-gisce Mar 3, 2025
481a175
fix: change the function for wizard preview to generate_mail_sync()
gpozo-gisce Mar 3, 2025
ae9b0a0
Merge branch 'v5_backport' into 69731_add_attach_into_mails
gpozo-gisce Mar 5, 2025
caba41e
Merge branch 'main' into 69731_add_attach_into_mails
gpozo-gisce Jul 11, 2025
2df1d93
Merge branch 'main' into 69731_add_attach_into_mails
gpozo-gisce Jul 24, 2025
3752ade
refactor: simplify report template object reference handling
gpozo-gisce Sep 12, 2025
8373544
Merge branch 'main' into 69731_add_attach_into_mails
gpozo-gisce Sep 12, 2025
b490307
Merge branch 'main' into 69731_add_attach_into_mails
gpozo-gisce Sep 24, 2025
a57adbe
refactor: enhance report generation to support object references
gpozo-gisce Oct 9, 2025
a1db1d8
refactor: update test cases for attachment generation and object refe…
gpozo-gisce Oct 9, 2025
4dbee03
refactor: streamline report generation logic and improve error handling
gpozo-gisce Oct 13, 2025
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
18 changes: 18 additions & 0 deletions migrations/5.0.25.5.0/post-0001_add_new_column.py
Original file line number Diff line number Diff line change
@@ -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
130 changes: 121 additions & 9 deletions poweremail_template.py
Original file line number Diff line number Diff line change
Expand Up @@ -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',
Expand Down Expand Up @@ -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')
Expand Down Expand Up @@ -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
Expand All @@ -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]
Comment on lines +980 to +981
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no hauria de ser sempre un unic valor?


model = value._table_name
if hasattr(value, 'id'):
value = value.id
Comment on lines +983 to +985
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

per evitar-nos aquesta comprovació, jo afegiria al help que l'avaluació del camp ha de retornar un id. P.e.: object.invoice_id.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):
Expand All @@ -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'],
Expand Down
4 changes: 3 additions & 1 deletion poweremail_template_view.xml
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@
<!--
I dont advice using the html widget
because tinymce is interfering too
much with the html generated
much with the html generated

Sunday,30 May 2010:Enabling HTML as
community votes for it
Expand Down Expand Up @@ -142,6 +142,8 @@
<field name="save_to_drafts" colspan="4"/>
<field name="inline" colspan="4"/>
</group>
<separator string="Attachments (Report to attach)" colspan="4" />
<field name="report_template_object_reference" colspan="2"/>
<group>
<separator colspan="4" string="Allowed User Groups" />
<field name="allowed_groups" string="Allowed User Groups" nolabel="1" colspan="4"/>
Expand Down
1 change: 1 addition & 0 deletions tests/__init__.py
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
from .test_poweremail_mailbox import *
from .test_poweremail_templates import *
from .test_attach_other_models import *
Loading
Loading