New design for daily work summary (#9844)
* New design for daily work summary * Update tests
This commit is contained in:
parent
8e2531e2bb
commit
2c5b3e83f5
@ -193,6 +193,8 @@ scheduler_events = {
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
email_brand_image = "assets/erpnext/images/erpnext-logo.jpg"
|
||||||
|
|
||||||
default_mail_footer = """<div style="text-align: center;">
|
default_mail_footer = """<div style="text-align: center;">
|
||||||
<a href="https://erpnext.com?source=via_email_footer" target="_blank" style="color: #8d99a6;">
|
<a href="https://erpnext.com?source=via_email_footer" target="_blank" style="color: #8d99a6;">
|
||||||
Sent via ERPNext
|
Sent via ERPNext
|
||||||
|
@ -8,7 +8,7 @@ from frappe.model.document import Document
|
|||||||
from frappe import _
|
from frappe import _
|
||||||
from email_reply_parser import EmailReplyParser
|
from email_reply_parser import EmailReplyParser
|
||||||
from erpnext.hr.doctype.employee.employee import is_holiday
|
from erpnext.hr.doctype.employee.employee import is_holiday
|
||||||
from frappe.utils import formatdate
|
from frappe.utils import global_date_format
|
||||||
from markdown2 import markdown
|
from markdown2 import markdown
|
||||||
|
|
||||||
class DailyWorkSummary(Document):
|
class DailyWorkSummary(Document):
|
||||||
@ -24,17 +24,18 @@ class DailyWorkSummary(Document):
|
|||||||
|
|
||||||
def send_summary(self):
|
def send_summary(self):
|
||||||
'''Send summary of all replies. Called at midnight'''
|
'''Send summary of all replies. Called at midnight'''
|
||||||
message = self.get_summary_message()
|
args = self.get_message_details()
|
||||||
|
|
||||||
frappe.sendmail(recipients = get_employee_emails(self.company, False),
|
frappe.sendmail(recipients = get_employee_emails(self.company, False),
|
||||||
message = message,
|
template='daily_work_summary',
|
||||||
|
args=args,
|
||||||
subject = _('Daily Work Summary for {0}').format(self.company),
|
subject = _('Daily Work Summary for {0}').format(self.company),
|
||||||
reference_doctype=self.doctype, reference_name=self.name)
|
reference_doctype=self.doctype, reference_name=self.name)
|
||||||
|
|
||||||
self.db_set('status', 'Sent')
|
self.db_set('status', 'Sent')
|
||||||
|
|
||||||
def get_summary_message(self):
|
def get_message_details(self):
|
||||||
'''Return summary of replies as HTML'''
|
'''Return args for template'''
|
||||||
settings = frappe.get_doc('Daily Work Summary Settings')
|
settings = frappe.get_doc('Daily Work Summary Settings')
|
||||||
|
|
||||||
replies = frappe.get_all('Communication', fields=['content', 'text_content', 'sender'],
|
replies = frappe.get_all('Communication', fields=['content', 'text_content', 'sender'],
|
||||||
@ -45,8 +46,12 @@ class DailyWorkSummary(Document):
|
|||||||
did_not_reply = self.email_sent_to.split()
|
did_not_reply = self.email_sent_to.split()
|
||||||
|
|
||||||
for d in replies:
|
for d in replies:
|
||||||
d.sender_name = frappe.db.get_value("Employee", {"user_id": d.sender},
|
emp = frappe.db.get_values("Employee", {"user_id": d.sender},
|
||||||
"employee_name") or d.sender
|
["employee_name", "image"], as_dict=True)
|
||||||
|
|
||||||
|
d.sender_name = emp[0].employee_name if emp else d.sender
|
||||||
|
d.image = emp[0].image if emp and emp[0].image else None
|
||||||
|
|
||||||
if d.sender in did_not_reply:
|
if d.sender in did_not_reply:
|
||||||
did_not_reply.remove(d.sender)
|
did_not_reply.remove(d.sender)
|
||||||
if d.text_content:
|
if d.text_content:
|
||||||
@ -56,30 +61,12 @@ class DailyWorkSummary(Document):
|
|||||||
did_not_reply = [(frappe.db.get_value("Employee", {"user_id": email}, "employee_name") or email)
|
did_not_reply = [(frappe.db.get_value("Employee", {"user_id": email}, "employee_name") or email)
|
||||||
for email in did_not_reply]
|
for email in did_not_reply]
|
||||||
|
|
||||||
return frappe.render_template(self.get_summary_template(),
|
return dict(replies=replies,
|
||||||
dict(replies=replies,
|
|
||||||
original_message=settings.message,
|
original_message=settings.message,
|
||||||
title=_('Daily Work Summary for {0}'.format(formatdate(self.creation))),
|
title=_('Daily Work Summary for {0}'.format(global_date_format(self.creation))),
|
||||||
did_not_reply= ', '.join(did_not_reply) or '',
|
did_not_reply= ', '.join(did_not_reply) or '',
|
||||||
did_not_reply_title = _('No replies from')))
|
did_not_reply_title = _('No replies from'))
|
||||||
|
|
||||||
def get_summary_template(self):
|
|
||||||
return '''
|
|
||||||
<h3>{{ title }}</h3>
|
|
||||||
|
|
||||||
{% for reply in replies %}
|
|
||||||
<h4>{{ reply.sender_name }}</h4>
|
|
||||||
<p style="padding-bottom: 20px">
|
|
||||||
{{ reply.content }}
|
|
||||||
</p>
|
|
||||||
<hr>
|
|
||||||
{% endfor %}
|
|
||||||
|
|
||||||
{% if did_not_reply %}
|
|
||||||
<p>{{ did_not_reply_title }}: {{ did_not_reply }}</p>
|
|
||||||
{% endif %}
|
|
||||||
|
|
||||||
'''
|
|
||||||
|
|
||||||
def get_employee_emails(company, only_working=True):
|
def get_employee_emails(company, only_working=True):
|
||||||
'''Returns list of Employee user ids for the given company who are working today
|
'''Returns list of Employee user ids for the given company who are working today
|
||||||
|
@ -46,9 +46,9 @@ class TestDailyWorkSummary(unittest.TestCase):
|
|||||||
daily_work_summary = frappe.get_doc('Daily Work Summary',
|
daily_work_summary = frappe.get_doc('Daily Work Summary',
|
||||||
frappe.get_all('Daily Work Summary')[0].name)
|
frappe.get_all('Daily Work Summary')[0].name)
|
||||||
|
|
||||||
summary = daily_work_summary.get_summary_message()
|
args = daily_work_summary.get_message_details()
|
||||||
|
|
||||||
self.assertTrue('I built Daily Work Summary!' in summary)
|
self.assertTrue('I built Daily Work Summary!' in args.get('replies')[0].content)
|
||||||
|
|
||||||
def setup_and_prepare_test(self, hour=None):
|
def setup_and_prepare_test(self, hour=None):
|
||||||
frappe.db.sql('delete from `tabDaily Work Summary`')
|
frappe.db.sql('delete from `tabDaily Work Summary`')
|
||||||
|
59
erpnext/templates/emails/daily_work_summary.html
Normal file
59
erpnext/templates/emails/daily_work_summary.html
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
<table border="0" cellpadding="0" cellspacing="0" width="100%">
|
||||||
|
<tr>
|
||||||
|
<div style="color: #333; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif; word-wrap: break-word; overflow-wrap: break-word;">
|
||||||
|
<h3>{{ title }}</h3>
|
||||||
|
</div>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
{% for reply in replies %}
|
||||||
|
<table border="0" cellpadding="0" cellspacing="0" width="100%"
|
||||||
|
style="background-color: #fafbfc; border: 1px solid #d1d8dd; border-radius: 3px 3px 0 0">
|
||||||
|
<tr height="10"></tr>
|
||||||
|
<tr>
|
||||||
|
<td width="15"></td>
|
||||||
|
<td valign="top" width="24">
|
||||||
|
{% if reply.image %}
|
||||||
|
<img width="24" height="24" embed="{{ reply.image }}" style="border-radius: 3px; vertical-align: middle;" />
|
||||||
|
{% else %}
|
||||||
|
<div style="width: 24px; height: 24px; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif;background: #fff; border-radius: 3px; border: 1px solid #d1d8dd; text-align: center; line-height: 24px; color: #d1d8dd;">
|
||||||
|
{{ reply.sender_name[0] }}
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
</td>
|
||||||
|
<td width="10"></td>
|
||||||
|
<td>
|
||||||
|
<div style="font-size: 12px; color: #8D99A6; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif; word-wrap: break-word; line-height: 22px; overflow-wrap: break-word; text-decoration: none;">
|
||||||
|
<span>{{ reply.sender_name }}</span>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td width="15"></td>
|
||||||
|
</tr>
|
||||||
|
<tr height="10"></tr>
|
||||||
|
</table>
|
||||||
|
<table border="0" cellpadding="0" cellspacing="0" width="100%"
|
||||||
|
style="background-color: #fff; border: 1px solid #d1d8dd; border-top: none; border-radius: 0 0 3px 3px">
|
||||||
|
<tr height="10"></tr>
|
||||||
|
<tr>
|
||||||
|
<td width="15"></td>
|
||||||
|
<td>
|
||||||
|
<div style="font-size: 14px; color: #333; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif; word-wrap: break-word; line-height: 22px; overflow-wrap: break-word; text-decoration: none;">
|
||||||
|
{{ reply.content }}
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td width="15"></td>
|
||||||
|
</tr>
|
||||||
|
<tr height="10"></tr>
|
||||||
|
</table>
|
||||||
|
<table border="0" cellpadding="0" cellspacing="0" width="100%">
|
||||||
|
<tr height="20"></tr>
|
||||||
|
</table>
|
||||||
|
{% endfor %}
|
||||||
|
{% if did_not_reply %}
|
||||||
|
<table border="0" cellpadding="0" cellspacing="0" width="100%">
|
||||||
|
<tr>
|
||||||
|
<div style="font-size: 14px; color: #8D99A6; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif; word-wrap: break-word; line-height: 22px; overflow-wrap: break-word; text-decoration: none;">
|
||||||
|
<p>{{ did_not_reply_title }}: {{ did_not_reply }}</p>
|
||||||
|
</div>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
{% endif %}
|
11
erpnext/templates/emails/daily_work_summary.txt
Normal file
11
erpnext/templates/emails/daily_work_summary.txt
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
{{ title }}
|
||||||
|
|
||||||
|
{% for reply in replies %}
|
||||||
|
{{ reply.sender_name }}:
|
||||||
|
{{ reply.content }}
|
||||||
|
|
||||||
|
|
||||||
|
{% endfor %}
|
||||||
|
{% if did_not_reply %}
|
||||||
|
{{ did_not_reply_title }}: {{ did_not_reply }}
|
||||||
|
{% endif %}
|
Loading…
x
Reference in New Issue
Block a user