[wip] daily work summary

This commit is contained in:
Rushabh Mehta 2016-11-14 10:52:01 +05:30
parent fe816c3852
commit c10d2a0025
9 changed files with 88 additions and 139 deletions

View File

@ -22,7 +22,7 @@
"ignore_user_permissions": 0, "ignore_user_permissions": 0,
"ignore_xss_filter": 0, "ignore_xss_filter": 0,
"in_filter": 0, "in_filter": 0,
"in_list_view": 0, "in_list_view": 1,
"in_standard_filter": 0, "in_standard_filter": 0,
"label": "Company", "label": "Company",
"length": 0, "length": 0,
@ -32,7 +32,7 @@
"precision": "", "precision": "",
"print_hide": 0, "print_hide": 0,
"print_hide_if_no_value": 0, "print_hide_if_no_value": 0,
"read_only": 0, "read_only": 1,
"remember_last_selected_value": 0, "remember_last_selected_value": 0,
"report_hide": 0, "report_hide": 0,
"reqd": 0, "reqd": 0,
@ -45,23 +45,24 @@
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"fieldname": "responses", "default": "Open",
"fieldtype": "Table", "fieldname": "status",
"fieldtype": "Select",
"hidden": 0, "hidden": 0,
"ignore_user_permissions": 0, "ignore_user_permissions": 0,
"ignore_xss_filter": 0, "ignore_xss_filter": 0,
"in_filter": 0, "in_filter": 0,
"in_list_view": 0, "in_list_view": 1,
"in_standard_filter": 0, "in_standard_filter": 0,
"label": "Responses", "label": "Status",
"length": 0, "length": 0,
"no_copy": 0, "no_copy": 0,
"options": "Daily Work Summary Response", "options": "Open\nSummary Sent",
"permlevel": 0, "permlevel": 0,
"precision": "", "precision": "",
"print_hide": 0, "print_hide": 0,
"print_hide_if_no_value": 0, "print_hide_if_no_value": 0,
"read_only": 0, "read_only": 1,
"remember_last_selected_value": 0, "remember_last_selected_value": 0,
"report_hide": 0, "report_hide": 0,
"reqd": 0, "reqd": 0,
@ -80,7 +81,7 @@
"issingle": 0, "issingle": 0,
"istable": 0, "istable": 0,
"max_attachments": 0, "max_attachments": 0,
"modified": "2016-11-08 06:03:21.121442", "modified": "2016-11-10 16:09:11.619822",
"modified_by": "Administrator", "modified_by": "Administrator",
"module": "HR", "module": "HR",
"name": "Daily Work Summary", "name": "Daily Work Summary",

View File

@ -6,40 +6,69 @@ from __future__ import unicode_literals
import frappe import frappe
from frappe.model.document import Document from frappe.model.document import Document
from frappe import _ from frappe import _
from email_reply_parser import EmailReplyParser
from erpnext.hr.doctype.employee.employee import is_holiday
class DailyWorkSummary(Document): class DailyWorkSummary(Document):
def send_mails(self, settings): def send_mails(self, settings, emails):
'''Send emails to get daily work summary to all employees''' '''Send emails to get daily work summary to all employees'''
frappe.sendmail(recipients = self.get_employee_emails(), message = settings.message, incoming_email_account = frappe.db.get_value('Email Account',
subject = settings.subject, reference_doctype=self.doctype, reference_name=self.name) dict(enable_incoming=1, default_incoming=1), 'email_id')
frappe.sendmail(recipients = emails, message = settings.message,
subject = settings.subject, reference_doctype=self.doctype,
reference_name=self.name, reply_to = incoming_email_account)
def send_summary(self): def send_summary(self):
'''Send summary of all replies''' '''Send summary of all replies'''
settings = frappe.get_doc('Daily Work Summary Settings') message = self.get_summary_message()
replies = frappe.get_doc('Communication', fields=['content', 'sender'], frappe.sendmail(recipients = get_employee_emails(self.company, False), message = message,
filters=dict(reference_doctype=self.doctype, reference_name=self.name,
communication_type='Email', sent_or_received='Received'))
message = frappe.render_template(template, dict(replies=replies,
original_message=settings.message))
frappe.sendmail(recipients = self.get_employee_emails(), message = message,
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)
def get_employee_emails(self): def get_summary_message(self):
return filter(None, [d.user_id for d in '''Return summary of replies as HTML'''
frappe.get_all('Employee', fields=['user_id'], settings = frappe.get_doc('Daily Work Summary Settings')
filters={'status': 'Active', 'company': self.company})])
replies = frappe.get_all('Communication', fields=['content', 'text_content', 'sender'],
filters=dict(reference_doctype=self.doctype, reference_name=self.name,
communication_type='Communication', sent_or_received='Received'))
if not replies:
return None
for d in replies:
if d.text_content:
d.content = EmailReplyParser.parse_reply(d.text_content)
return frappe.render_template(template, dict(replies=replies,
original_message=settings.message))
def get_employee_emails(company, only_working=True):
'''Returns list of Employee user ids for the given company who are working today
:param company: Company `name`'''
employee_list = frappe.get_all('Employee', fields=['name', 'user_id'],
filters={'status': 'Active', 'company': company})
out = []
for e in employee_list:
if e.user_id:
if only_working and is_holiday(e.name):
# don't add if holiday
pass
out.append(e.user_id)
return out
template = ''' template = '''
<p>Summary of replies:</p> <p>Summary of replies:</p>
{% for reply in replies %} {% for reply in replies %}
<h5>{{ frappe.db.get_value("Employee", reply.sender, "full_name") }}<h5> <h5>{{ frappe.db.get_value("Employee", {"user_id": reply.sender}, "employee_name") or reply.sender }}<h5>
<div style="padding-bottom: 20px"> <div style="padding-bottom: 20px">
{{ reply.content.split(original_message)[0].strip() }} {{ reply.content }}
</div> </div>
{% endfor %} {% endfor %}
''' '''

View File

@ -30,6 +30,9 @@ class TestDailyWorkSummary(unittest.TestCase):
self.assertFalse(d.user_id in [d.recipient for d in emails self.assertFalse(d.user_id in [d.recipient for d in emails
if settings.subject in d.message]) if settings.subject in d.message])
def test_summary(self):
pass
def setup_and_prepare_test(self, hour): def setup_and_prepare_test(self, hour):
frappe.db.sql('delete from `tabEmail Queue`') frappe.db.sql('delete from `tabEmail Queue`')

View File

@ -1,95 +0,0 @@
{
"allow_copy": 0,
"allow_import": 0,
"allow_rename": 0,
"beta": 0,
"creation": "2016-11-08 04:56:39.588230",
"custom": 0,
"docstatus": 0,
"doctype": "DocType",
"document_type": "Document",
"editable_grid": 1,
"engine": "InnoDB",
"fields": [
{
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "employee",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 1,
"in_standard_filter": 0,
"label": "Employee",
"length": 0,
"no_copy": 0,
"options": "Employee",
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "response",
"fieldtype": "Text",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 1,
"in_standard_filter": 0,
"label": "Response",
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
}
],
"hide_heading": 0,
"hide_toolbar": 0,
"idx": 0,
"image_view": 0,
"in_create": 0,
"in_dialog": 0,
"is_submittable": 0,
"issingle": 0,
"istable": 1,
"max_attachments": 0,
"modified": "2016-11-08 04:56:39.588230",
"modified_by": "Administrator",
"module": "HR",
"name": "Daily Work Summary Response",
"name_case": "",
"owner": "Administrator",
"permissions": [],
"quick_entry": 1,
"read_only": 0,
"read_only_onload": 0,
"sort_field": "modified",
"sort_order": "DESC",
"track_seen": 0
}

View File

@ -1,10 +0,0 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and contributors
# For license information, please see license.txt
from __future__ import unicode_literals
import frappe
from frappe.model.document import Document
class DailyWorkSummaryResponse(Document):
pass

View File

@ -2,6 +2,9 @@
// For license information, please see license.txt // For license information, please see license.txt
frappe.ui.form.on('Daily Work Summary Settings', { frappe.ui.form.on('Daily Work Summary Settings', {
onload: function(frm) { refresh: function(frm) {
frm.add_custom_button(__('Daily Work Summary'), function() {
frappe.set_route('List', 'Daily Work Summary');
});
} }
}); });

View File

@ -6,15 +6,22 @@ from __future__ import unicode_literals
import frappe import frappe
from frappe.model.document import Document from frappe.model.document import Document
import frappe.utils import frappe.utils
from frappe import _
from erpnext.hr.doctype.daily_work_summary.daily_work_summary import get_employee_emails
class DailyWorkSummarySettings(Document): class DailyWorkSummarySettings(Document):
pass def validate(self):
if self.companies:
if not frappe.db.get_value('Email Account', dict(enable_incoming=1, default_incoming=1)):
frappe.throw(_('There must be a default incoming Email Account enabled for this to work. Please setup a default incoming Email Account (POP/IMAP) and try again.'))
def trigger_emails(): def trigger_emails():
settings = frappe.get_doc('Daily Work Summary Settings') settings = frappe.get_doc('Daily Work Summary Settings')
for d in settings.companies: for d in settings.companies:
# if current hour # if current hour
if frappe.utils.nowtime().split(':')[0] == d.send_emails_at.split(':')[0]: if frappe.utils.nowtime().split(':')[0] == d.send_emails_at.split(':')[0]:
work_summary = frappe.get_doc(dict(doctype='Daily Work Summary', emails = get_employee_emails(d.company)
company=d.company)).insert() if emails:
work_summary.send_mails(settings) work_summary = frappe.get_doc(dict(doctype='Daily Work Summary',
company=d.company)).insert()
work_summary.send_mails(settings, emails)

View File

@ -9,7 +9,6 @@ from frappe.model.naming import make_autoname
from frappe import throw, _ from frappe import throw, _
import frappe.permissions import frappe.permissions
from frappe.model.document import Document from frappe.model.document import Document
from frappe.model.mapper import get_mapped_doc
from erpnext.utilities.transaction_base import delete_events from erpnext.utilities.transaction_base import delete_events
@ -164,7 +163,6 @@ def get_timeline_data(doctype, name):
@frappe.whitelist() @frappe.whitelist()
def get_retirement_date(date_of_birth=None): def get_retirement_date(date_of_birth=None):
import datetime
ret = {} ret = {}
if date_of_birth: if date_of_birth:
try: try:
@ -233,3 +231,16 @@ def get_holiday_list_for_employee(employee, raise_exception=True):
return holiday_list return holiday_list
def is_holiday(employee, date=None):
'''Returns True if given Employee has an holiday on the given date
:param employee: Employee `name`
:param date: Date to check. Will check for today if None'''
holiday_list = get_holiday_list_for_employee(employee)
if not date:
date = today()
if holiday_list:
return frappe.get_all('Holiday List', dict(name=holiday_list, holiday_date=date)) and True or False