Merge pull request #16419 from rohitwaghchaure/project_update_status_code_and_design_refactoring
fix: Project update status feature's code and design refactored
This commit is contained in:
commit
9adfd2d7b4
@ -223,10 +223,15 @@ doc_events = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
scheduler_events = {
|
scheduler_events = {
|
||||||
|
"all": [
|
||||||
|
"erpnext.projects.doctype.project.project.project_status_update_reminder"
|
||||||
|
],
|
||||||
"hourly": [
|
"hourly": [
|
||||||
'erpnext.hr.doctype.daily_work_summary_group.daily_work_summary_group.trigger_emails',
|
'erpnext.hr.doctype.daily_work_summary_group.daily_work_summary_group.trigger_emails',
|
||||||
"erpnext.accounts.doctype.subscription.subscription.process_all",
|
"erpnext.accounts.doctype.subscription.subscription.process_all",
|
||||||
"erpnext.erpnext_integrations.doctype.amazon_mws_settings.amazon_mws_settings.schedule_get_order_details"
|
"erpnext.erpnext_integrations.doctype.amazon_mws_settings.amazon_mws_settings.schedule_get_order_details",
|
||||||
|
"erpnext.projects.doctype.project.project.hourly_reminder",
|
||||||
|
"erpnext.projects.doctype.project.project.collect_project_status"
|
||||||
],
|
],
|
||||||
"daily": [
|
"daily": [
|
||||||
"erpnext.stock.reorder_item.reorder_item",
|
"erpnext.stock.reorder_item.reorder_item",
|
||||||
@ -245,7 +250,8 @@ scheduler_events = {
|
|||||||
"erpnext.assets.doctype.asset.asset.update_maintenance_status",
|
"erpnext.assets.doctype.asset.asset.update_maintenance_status",
|
||||||
"erpnext.assets.doctype.asset.asset.make_post_gl_entry",
|
"erpnext.assets.doctype.asset.asset.make_post_gl_entry",
|
||||||
"erpnext.crm.doctype.contract.contract.update_status_for_contracts",
|
"erpnext.crm.doctype.contract.contract.update_status_for_contracts",
|
||||||
"erpnext.projects.doctype.project.project.update_project_sales_billing"
|
"erpnext.projects.doctype.project.project.update_project_sales_billing",
|
||||||
|
"erpnext.projects.doctype.project.project.send_project_status_email_to_users"
|
||||||
],
|
],
|
||||||
"daily_long": [
|
"daily_long": [
|
||||||
"erpnext.manufacturing.doctype.bom_update_tool.bom_update_tool.update_latest_price_in_all_boms"
|
"erpnext.manufacturing.doctype.bom_update_tool.bom_update_tool.update_latest_price_in_all_boms"
|
||||||
|
@ -112,6 +112,10 @@ def get_user_emails_from_group(group):
|
|||||||
if isinstance(group_doc, string_types):
|
if isinstance(group_doc, string_types):
|
||||||
group_doc = frappe.get_doc('Daily Work Summary Group', group)
|
group_doc = frappe.get_doc('Daily Work Summary Group', group)
|
||||||
|
|
||||||
emails = [d.email for d in group_doc.users if frappe.db.get_value("User", d.user, "enabled")]
|
emails = get_users_email(group_doc)
|
||||||
|
|
||||||
return emails
|
return emails
|
||||||
|
|
||||||
|
def get_users_email(doc):
|
||||||
|
return [d.email for d in doc.users
|
||||||
|
if frappe.db.get_value("User", d.user, "enabled")]
|
||||||
|
@ -581,3 +581,4 @@ erpnext.patches.v10_0.repost_gle_for_purchase_receipts_with_rejected_items
|
|||||||
erpnext.patches.v11_0.set_missing_gst_hsn_code
|
erpnext.patches.v11_0.set_missing_gst_hsn_code
|
||||||
erpnext.patches.v11_0.rename_bom_wo_fields
|
erpnext.patches.v11_0.rename_bom_wo_fields
|
||||||
erpnext.patches.v11_0.rename_additional_salary_component_additional_salary
|
erpnext.patches.v11_0.rename_additional_salary_component_additional_salary
|
||||||
|
erpnext.patches.v11_0.renamed_from_to_fields_in_project
|
13
erpnext/patches/v11_0/renamed_from_to_fields_in_project.py
Normal file
13
erpnext/patches/v11_0/renamed_from_to_fields_in_project.py
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
|
||||||
|
# License: GNU General Public License v3. See license.txt
|
||||||
|
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
import frappe
|
||||||
|
from frappe.model.utils.rename_field import rename_field
|
||||||
|
|
||||||
|
def execute():
|
||||||
|
frappe.reload_doc('projects', 'doctype', 'project')
|
||||||
|
|
||||||
|
if frappe.db.has_column('Project', 'from'):
|
||||||
|
rename_field('Project', 'from', 'from_time')
|
||||||
|
rename_field('Project', 'to', 'to_time')
|
@ -1,5 +1,6 @@
|
|||||||
{
|
{
|
||||||
"allow_copy": 0,
|
"allow_copy": 0,
|
||||||
|
"allow_events_in_timeline": 0,
|
||||||
"allow_guest_to_view": 0,
|
"allow_guest_to_view": 0,
|
||||||
"allow_import": 1,
|
"allow_import": 1,
|
||||||
"allow_rename": 1,
|
"allow_rename": 1,
|
||||||
@ -1486,6 +1487,40 @@
|
|||||||
"translatable": 0,
|
"translatable": 0,
|
||||||
"unique": 0
|
"unique": 0
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"allow_bulk_edit": 0,
|
||||||
|
"allow_in_quick_entry": 0,
|
||||||
|
"allow_on_submit": 0,
|
||||||
|
"bold": 0,
|
||||||
|
"collapsible": 0,
|
||||||
|
"columns": 0,
|
||||||
|
"depends_on": "collect_progress",
|
||||||
|
"fieldname": "holiday_list",
|
||||||
|
"fieldtype": "Link",
|
||||||
|
"hidden": 0,
|
||||||
|
"ignore_user_permissions": 0,
|
||||||
|
"ignore_xss_filter": 0,
|
||||||
|
"in_filter": 0,
|
||||||
|
"in_global_search": 0,
|
||||||
|
"in_list_view": 0,
|
||||||
|
"in_standard_filter": 0,
|
||||||
|
"label": "Holiday List",
|
||||||
|
"length": 0,
|
||||||
|
"no_copy": 0,
|
||||||
|
"options": "Holiday List",
|
||||||
|
"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,
|
||||||
|
"translatable": 0,
|
||||||
|
"unique": 0
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
"allow_bulk_edit": 0,
|
||||||
"allow_in_quick_entry": 0,
|
"allow_in_quick_entry": 0,
|
||||||
@ -1527,8 +1562,9 @@
|
|||||||
"bold": 0,
|
"bold": 0,
|
||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
"columns": 0,
|
"columns": 0,
|
||||||
"fieldname": "column_break_45",
|
"depends_on": "eval:(doc.frequency == \"Hourly\" && doc.collect_progress)",
|
||||||
"fieldtype": "Column Break",
|
"fieldname": "from_time",
|
||||||
|
"fieldtype": "Time",
|
||||||
"hidden": 0,
|
"hidden": 0,
|
||||||
"ignore_user_permissions": 0,
|
"ignore_user_permissions": 0,
|
||||||
"ignore_xss_filter": 0,
|
"ignore_xss_filter": 0,
|
||||||
@ -1536,6 +1572,7 @@
|
|||||||
"in_global_search": 0,
|
"in_global_search": 0,
|
||||||
"in_list_view": 0,
|
"in_list_view": 0,
|
||||||
"in_standard_filter": 0,
|
"in_standard_filter": 0,
|
||||||
|
"label": "From Time",
|
||||||
"length": 0,
|
"length": 0,
|
||||||
"no_copy": 0,
|
"no_copy": 0,
|
||||||
"permlevel": 0,
|
"permlevel": 0,
|
||||||
@ -1558,8 +1595,8 @@
|
|||||||
"bold": 0,
|
"bold": 0,
|
||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
"columns": 0,
|
"columns": 0,
|
||||||
"depends_on": "eval:(doc.frequency == \"Hourly\" && doc.collect_progress == true)",
|
"depends_on": "eval:(doc.frequency == \"Hourly\" && doc.collect_progress)",
|
||||||
"fieldname": "from",
|
"fieldname": "to_time",
|
||||||
"fieldtype": "Time",
|
"fieldtype": "Time",
|
||||||
"hidden": 0,
|
"hidden": 0,
|
||||||
"ignore_user_permissions": 0,
|
"ignore_user_permissions": 0,
|
||||||
@ -1568,40 +1605,7 @@
|
|||||||
"in_global_search": 0,
|
"in_global_search": 0,
|
||||||
"in_list_view": 0,
|
"in_list_view": 0,
|
||||||
"in_standard_filter": 0,
|
"in_standard_filter": 0,
|
||||||
"label": "From",
|
"label": "To Time",
|
||||||
"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,
|
|
||||||
"translatable": 0,
|
|
||||||
"unique": 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"allow_bulk_edit": 0,
|
|
||||||
"allow_in_quick_entry": 0,
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"columns": 0,
|
|
||||||
"depends_on": "eval:(doc.frequency == \"Hourly\" && doc.collect_progress == true)",
|
|
||||||
"fieldname": "to",
|
|
||||||
"fieldtype": "Time",
|
|
||||||
"hidden": 0,
|
|
||||||
"ignore_user_permissions": 0,
|
|
||||||
"ignore_xss_filter": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_global_search": 0,
|
|
||||||
"in_list_view": 0,
|
|
||||||
"in_standard_filter": 0,
|
|
||||||
"label": "To",
|
|
||||||
"length": 0,
|
"length": 0,
|
||||||
"no_copy": 0,
|
"no_copy": 0,
|
||||||
"permlevel": 0,
|
"permlevel": 0,
|
||||||
@ -1782,6 +1786,71 @@
|
|||||||
"set_only_once": 0,
|
"set_only_once": 0,
|
||||||
"translatable": 0,
|
"translatable": 0,
|
||||||
"unique": 0
|
"unique": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"allow_bulk_edit": 0,
|
||||||
|
"allow_in_quick_entry": 0,
|
||||||
|
"allow_on_submit": 0,
|
||||||
|
"bold": 0,
|
||||||
|
"collapsible": 0,
|
||||||
|
"columns": 0,
|
||||||
|
"fieldname": "column_break_45",
|
||||||
|
"fieldtype": "Column Break",
|
||||||
|
"hidden": 0,
|
||||||
|
"ignore_user_permissions": 0,
|
||||||
|
"ignore_xss_filter": 0,
|
||||||
|
"in_filter": 0,
|
||||||
|
"in_global_search": 0,
|
||||||
|
"in_list_view": 0,
|
||||||
|
"in_standard_filter": 0,
|
||||||
|
"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,
|
||||||
|
"translatable": 0,
|
||||||
|
"unique": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"allow_bulk_edit": 0,
|
||||||
|
"allow_in_quick_entry": 0,
|
||||||
|
"allow_on_submit": 0,
|
||||||
|
"bold": 0,
|
||||||
|
"collapsible": 0,
|
||||||
|
"columns": 0,
|
||||||
|
"depends_on": "collect_progress",
|
||||||
|
"description": "Message will sent to users to get their status on the project",
|
||||||
|
"fieldname": "message",
|
||||||
|
"fieldtype": "Text",
|
||||||
|
"hidden": 0,
|
||||||
|
"ignore_user_permissions": 0,
|
||||||
|
"ignore_xss_filter": 0,
|
||||||
|
"in_filter": 0,
|
||||||
|
"in_global_search": 0,
|
||||||
|
"in_list_view": 0,
|
||||||
|
"in_standard_filter": 0,
|
||||||
|
"label": "Message",
|
||||||
|
"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,
|
||||||
|
"translatable": 0,
|
||||||
|
"unique": 0
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"has_web_view": 0,
|
"has_web_view": 0,
|
||||||
@ -1795,7 +1864,7 @@
|
|||||||
"issingle": 0,
|
"issingle": 0,
|
||||||
"istable": 0,
|
"istable": 0,
|
||||||
"max_attachments": 4,
|
"max_attachments": 4,
|
||||||
"modified": "2018-08-30 00:12:09.649654",
|
"modified": "2019-01-16 23:26:57.376682",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Projects",
|
"module": "Projects",
|
||||||
"name": "Project",
|
"name": "Project",
|
||||||
|
@ -3,16 +3,16 @@
|
|||||||
|
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
import frappe
|
import frappe
|
||||||
|
|
||||||
from frappe.utils import flt, getdate, get_url, now
|
|
||||||
from frappe import _
|
from frappe import _
|
||||||
|
from six import iteritems
|
||||||
from frappe.model.document import Document
|
from email_reply_parser import EmailReplyParser
|
||||||
|
from frappe.utils import (flt, getdate, get_url, now,
|
||||||
|
nowtime, get_time, today, get_datetime, add_days)
|
||||||
from erpnext.controllers.queries import get_filters_cond
|
from erpnext.controllers.queries import get_filters_cond
|
||||||
from frappe.desk.reportview import get_match_cond
|
from frappe.desk.reportview import get_match_cond
|
||||||
import datetime
|
from erpnext.hr.doctype.daily_work_summary.daily_work_summary import get_users_email
|
||||||
|
from erpnext.hr.doctype.daily_work_summary_group.daily_work_summary_group import is_holiday_today
|
||||||
from six import iteritems
|
from frappe.model.document import Document
|
||||||
|
|
||||||
class Project(Document):
|
class Project(Document):
|
||||||
def get_feed(self):
|
def get_feed(self):
|
||||||
@ -406,56 +406,137 @@ def get_users_for_project(doctype, txt, searchfield, start, page_len, filters):
|
|||||||
def get_cost_center_name(project):
|
def get_cost_center_name(project):
|
||||||
return frappe.db.get_value("Project", project, "cost_center")
|
return frappe.db.get_value("Project", project, "cost_center")
|
||||||
|
|
||||||
@frappe.whitelist()
|
|
||||||
def hourly_reminder():
|
def hourly_reminder():
|
||||||
project = frappe.db.sql("""SELECT `tabProject`.name FROM `tabProject` WHERE `tabProject`.frequency = "Hourly" and (CURTIME() BETWEEN `tabProject`.from and `tabProject`.to) AND `tabProject`.collect_progress = 1 ORDER BY `tabProject`.name;""")
|
fields = ["from_time", "to_time"]
|
||||||
create_project_update(project)
|
projects = get_projects_for_collect_progress("Hourly", fields)
|
||||||
|
|
||||||
@frappe.whitelist()
|
for project in projects:
|
||||||
def twice_daily_reminder():
|
if (get_time(nowtime()) >= get_time(project.from_time) or
|
||||||
project = frappe.db.sql("""SELECT `tabProject User`.user FROM `tabProject User` INNER JOIN `tabProject` ON `tabProject`.project_name = `tabProject User`.parent WHERE (`tabProject`.frequency = "Twice Daily") AND ((`tabProject`.first_email BETWEEN DATE_ADD(curtime(), INTERVAL -15 MINUTE) AND DATE_ADD(curtime(), INTERVAL 15 MINUTE)) OR (`tabProject`.second_email BETWEEN DATE_ADD(curtime(), INTERVAL -15 MINUTE) AND DATE_ADD(curtime(), INTERVAL 15 MINUTE))) AND `tabProject`.collect_progress = 1;""")
|
get_time(nowtime()) <= get_time(project.to_time)):
|
||||||
create_project_update(project)
|
send_project_update_email_to_users(project.name)
|
||||||
|
|
||||||
|
def project_status_update_reminder():
|
||||||
|
daily_reminder()
|
||||||
|
twice_daily_reminder()
|
||||||
|
weekly_reminder()
|
||||||
|
|
||||||
@frappe.whitelist()
|
|
||||||
def daily_reminder():
|
def daily_reminder():
|
||||||
project = frappe.db.sql("""SELECT `tabProject User`.user FROM `tabProject User` INNER JOIN `tabProject` ON `tabProject`.project_name = `tabProject User`.parent WHERE (`tabProject`.frequency = "Daily") AND (`tabProject`.daily_time_to_send BETWEEN DATE_ADD(curtime(), INTERVAL -15 MINUTE) AND DATE_ADD(curtime(), INTERVAL 15 MINUTE)) AND `tabProject`.collect_progress = 1;""")
|
fields = ["daily_time_to_send"]
|
||||||
create_project_update(project)
|
projects = get_projects_for_collect_progress("Daily", fields)
|
||||||
|
|
||||||
@frappe.whitelist()
|
for project in projects:
|
||||||
def weekly():
|
if not check_project_update_exists(project.name, project.get("daily_time_to_send")):
|
||||||
today = datetime.datetime.now().strftime("%A")
|
send_project_update_email_to_users(project.name)
|
||||||
project = frappe.db.sql("""SELECT `tabProject User`.user FROM `tabProject User` INNER JOIN `tabProject` ON `tabProject`.project_name = `tabProject User`.parent WHERE (`tabProject`.frequency = "Weekly") AND (`tabProject`.day_to_send = %s) AND (`tabProject`.weekly_time_to_send BETWEEN DATE_ADD(curtime(), INTERVAL -15 MINUTE) AND DATE_ADD(curtime(), INTERVAL 15 MINUTE)) AND `tabProject`.collect_progress = 1""", today)
|
|
||||||
create_project_update(project)
|
|
||||||
|
|
||||||
#Call this function in order to generate the Project Update for a specific project
|
def twice_daily_reminder():
|
||||||
def create_project_update(project):
|
fields = ["first_email", "second_email"]
|
||||||
data = []
|
projects = get_projects_for_collect_progress("Twice Daily", fields)
|
||||||
date_today = datetime.date.today()
|
|
||||||
time_now = frappe.utils.now_datetime().strftime('%H:%M:%S')
|
for project in projects:
|
||||||
for projects in project:
|
for d in fields:
|
||||||
project_update_dict = {
|
if not check_project_update_exists(project.name, project.get(d)):
|
||||||
|
send_project_update_email_to_users(project.name)
|
||||||
|
|
||||||
|
def weekly_reminder():
|
||||||
|
fields = ["day_to_send", "weekly_time_to_send"]
|
||||||
|
projects = get_projects_for_collect_progress("Weekly", fields)
|
||||||
|
|
||||||
|
current_day = get_datetime().strftime("%A")
|
||||||
|
for project in projects:
|
||||||
|
if current_day != project.day_to_send:
|
||||||
|
continue
|
||||||
|
|
||||||
|
if not check_project_update_exists(project.name, project.get("weekly_time_to_send")):
|
||||||
|
send_project_update_email_to_users(project.name)
|
||||||
|
|
||||||
|
def check_project_update_exists(project, time):
|
||||||
|
data = frappe.db.sql(""" SELECT name from `tabProject Update`
|
||||||
|
WHERE project = %s and date = %s and time >= %s """, (project, today(), time))
|
||||||
|
|
||||||
|
return True if data and data[0][0] else False
|
||||||
|
|
||||||
|
def get_projects_for_collect_progress(frequency, fields):
|
||||||
|
fields.extend(["name"])
|
||||||
|
|
||||||
|
return frappe.get_all("Project", fields = fields,
|
||||||
|
filters = {'collect_progress': 1, 'frequency': frequency})
|
||||||
|
|
||||||
|
def send_project_update_email_to_users(project):
|
||||||
|
doc = frappe.get_doc('Project', project)
|
||||||
|
|
||||||
|
if is_holiday_today(doc.holiday_list) or not doc.users: return
|
||||||
|
|
||||||
|
project_update = frappe.get_doc({
|
||||||
"doctype" : "Project Update",
|
"doctype" : "Project Update",
|
||||||
"project" : projects[0],
|
"project" : project,
|
||||||
"date": date_today,
|
"sent": 0,
|
||||||
"time": time_now,
|
"date": today(),
|
||||||
"naming_series": "UPDATE-.project.-.YY.MM.DD.-"
|
"time": nowtime(),
|
||||||
}
|
"naming_series": "UPDATE-.project.-.YY.MM.DD.-",
|
||||||
project_update = frappe.get_doc(project_update_dict)
|
}).insert()
|
||||||
project_update.insert()
|
|
||||||
#you can edit your local_host
|
|
||||||
local_host = "http://localhost:8003"
|
|
||||||
project_update_url = "<a class = 'btn btn-primary' href=%s target='_blank'>" % (local_host +"/desk#Form/Project%20Update/" + (project_update.name)) + ("CREATE PROJECT UPDATE" + "</a>")
|
|
||||||
data.append(project_update_url)
|
|
||||||
|
|
||||||
email = frappe.db.sql("""SELECT user from `tabProject User` WHERE parent = %s;""", project[0])
|
subject = "For project %s, update your status" % (project)
|
||||||
for emails in email:
|
|
||||||
frappe.sendmail(
|
incoming_email_account = frappe.db.get_value('Email Account',
|
||||||
recipients=emails,
|
dict(enable_incoming=1, default_incoming=1), 'email_id')
|
||||||
subject=frappe._(projects[0]),
|
|
||||||
header=[frappe._("Please Update your Project Status"), 'blue'],
|
frappe.sendmail(recipients=get_users_email(doc),
|
||||||
message= project_update_url
|
message=doc.message,
|
||||||
|
subject=_(subject),
|
||||||
|
reference_doctype=project_update.doctype,
|
||||||
|
reference_name=project_update.name,
|
||||||
|
reply_to=incoming_email_account
|
||||||
)
|
)
|
||||||
return data
|
|
||||||
|
def collect_project_status():
|
||||||
|
for data in frappe.get_all("Project Update",
|
||||||
|
{'date': today(), 'sent': 0}):
|
||||||
|
replies = frappe.get_all('Communication',
|
||||||
|
fields=['content', 'text_content', 'sender'],
|
||||||
|
filters=dict(reference_doctype="Project Update",
|
||||||
|
reference_name=data.name,
|
||||||
|
communication_type='Communication',
|
||||||
|
sent_or_received='Received'),
|
||||||
|
order_by='creation asc')
|
||||||
|
|
||||||
|
for d in replies:
|
||||||
|
doc = frappe.get_doc("Project Update", data.name)
|
||||||
|
user_data = frappe.db.get_values("User", {"email": d.sender},
|
||||||
|
["full_name", "user_image", "name"], as_dict=True)[0]
|
||||||
|
|
||||||
|
doc.append("users", {
|
||||||
|
'user': user_data.name,
|
||||||
|
'full_name': user_data.full_name,
|
||||||
|
'image': user_data.user_image,
|
||||||
|
'project_status': frappe.utils.md_to_html(
|
||||||
|
EmailReplyParser.parse_reply(d.text_content) or d.content
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
doc.save(ignore_permissions=True)
|
||||||
|
|
||||||
|
def send_project_status_email_to_users():
|
||||||
|
yesterday = add_days(today(), -1)
|
||||||
|
|
||||||
|
for d in frappe.get_all("Project Update",
|
||||||
|
{'date': yesterday, 'sent': 0}):
|
||||||
|
doc = frappe.get_doc("Project Update", d.name)
|
||||||
|
|
||||||
|
project_doc = frappe.get_doc('Project', doc.project)
|
||||||
|
|
||||||
|
args = {
|
||||||
|
"users": doc.users,
|
||||||
|
"title": _("Project Summary for {0}").format(yesterday)
|
||||||
|
}
|
||||||
|
|
||||||
|
frappe.sendmail(recipients=get_users_email(project_doc),
|
||||||
|
template='daily_project_summary',
|
||||||
|
args=args,
|
||||||
|
subject=_("Daily Project Summary for {0}").format(d.name),
|
||||||
|
reference_doctype="Project Update",
|
||||||
|
reference_name=d.name)
|
||||||
|
|
||||||
|
doc.db_set('sent', 1)
|
||||||
|
|
||||||
def update_project_sales_billing():
|
def update_project_sales_billing():
|
||||||
sales_update_frequency = frappe.db.get_single_value("Selling Settings", "sales_update_frequency")
|
sales_update_frequency = frappe.db.get_single_value("Selling Settings", "sales_update_frequency")
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
{
|
{
|
||||||
"allow_copy": 0,
|
"allow_copy": 0,
|
||||||
|
"allow_events_in_timeline": 0,
|
||||||
"allow_guest_to_view": 0,
|
"allow_guest_to_view": 0,
|
||||||
"allow_import": 0,
|
"allow_import": 0,
|
||||||
"allow_rename": 0,
|
"allow_rename": 0,
|
||||||
@ -13,6 +14,40 @@
|
|||||||
"editable_grid": 1,
|
"editable_grid": 1,
|
||||||
"engine": "InnoDB",
|
"engine": "InnoDB",
|
||||||
"fields": [
|
"fields": [
|
||||||
|
{
|
||||||
|
"allow_bulk_edit": 0,
|
||||||
|
"allow_in_quick_entry": 0,
|
||||||
|
"allow_on_submit": 0,
|
||||||
|
"bold": 0,
|
||||||
|
"collapsible": 0,
|
||||||
|
"columns": 0,
|
||||||
|
"default": "",
|
||||||
|
"fieldname": "naming_series",
|
||||||
|
"fieldtype": "Data",
|
||||||
|
"hidden": 1,
|
||||||
|
"ignore_user_permissions": 0,
|
||||||
|
"ignore_xss_filter": 0,
|
||||||
|
"in_filter": 0,
|
||||||
|
"in_global_search": 0,
|
||||||
|
"in_list_view": 0,
|
||||||
|
"in_standard_filter": 0,
|
||||||
|
"label": "Series",
|
||||||
|
"length": 0,
|
||||||
|
"no_copy": 0,
|
||||||
|
"options": "PROJ-UPD-.YYYY.-",
|
||||||
|
"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,
|
||||||
|
"translatable": 0,
|
||||||
|
"unique": 0
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
"allow_bulk_edit": 0,
|
||||||
"allow_in_quick_entry": 0,
|
"allow_in_quick_entry": 0,
|
||||||
@ -46,6 +81,39 @@
|
|||||||
"translatable": 0,
|
"translatable": 0,
|
||||||
"unique": 0
|
"unique": 0
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"allow_bulk_edit": 0,
|
||||||
|
"allow_in_quick_entry": 0,
|
||||||
|
"allow_on_submit": 0,
|
||||||
|
"bold": 0,
|
||||||
|
"collapsible": 0,
|
||||||
|
"columns": 0,
|
||||||
|
"default": "0",
|
||||||
|
"fieldname": "sent",
|
||||||
|
"fieldtype": "Check",
|
||||||
|
"hidden": 0,
|
||||||
|
"ignore_user_permissions": 0,
|
||||||
|
"ignore_xss_filter": 0,
|
||||||
|
"in_filter": 0,
|
||||||
|
"in_global_search": 0,
|
||||||
|
"in_list_view": 0,
|
||||||
|
"in_standard_filter": 0,
|
||||||
|
"label": "Sent",
|
||||||
|
"length": 0,
|
||||||
|
"no_copy": 0,
|
||||||
|
"permlevel": 0,
|
||||||
|
"precision": "",
|
||||||
|
"print_hide": 0,
|
||||||
|
"print_hide_if_no_value": 0,
|
||||||
|
"read_only": 1,
|
||||||
|
"remember_last_selected_value": 0,
|
||||||
|
"report_hide": 0,
|
||||||
|
"reqd": 0,
|
||||||
|
"search_index": 0,
|
||||||
|
"set_only_once": 0,
|
||||||
|
"translatable": 0,
|
||||||
|
"unique": 0
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
"allow_bulk_edit": 0,
|
||||||
"allow_in_quick_entry": 0,
|
"allow_in_quick_entry": 0,
|
||||||
@ -172,39 +240,6 @@
|
|||||||
"translatable": 0,
|
"translatable": 0,
|
||||||
"unique": 0
|
"unique": 0
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"allow_bulk_edit": 0,
|
|
||||||
"allow_in_quick_entry": 0,
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"columns": 0,
|
|
||||||
"fieldname": "progress",
|
|
||||||
"fieldtype": "Select",
|
|
||||||
"hidden": 0,
|
|
||||||
"ignore_user_permissions": 0,
|
|
||||||
"ignore_xss_filter": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_global_search": 0,
|
|
||||||
"in_list_view": 0,
|
|
||||||
"in_standard_filter": 0,
|
|
||||||
"label": "How is the Project Progressing Right Now?",
|
|
||||||
"length": 0,
|
|
||||||
"no_copy": 0,
|
|
||||||
"options": "Not Updated\nGreat/Quickly\nGood/Steady\nChallenging/Slow\nProblematic/Stuck",
|
|
||||||
"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,
|
|
||||||
"translatable": 0,
|
|
||||||
"unique": 0
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
"allow_bulk_edit": 0,
|
||||||
"allow_in_quick_entry": 0,
|
"allow_in_quick_entry": 0,
|
||||||
@ -238,38 +273,6 @@
|
|||||||
"translatable": 0,
|
"translatable": 0,
|
||||||
"unique": 0
|
"unique": 0
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"allow_bulk_edit": 0,
|
|
||||||
"allow_in_quick_entry": 0,
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"columns": 0,
|
|
||||||
"fieldname": "progress_details",
|
|
||||||
"fieldtype": "Text Editor",
|
|
||||||
"hidden": 0,
|
|
||||||
"ignore_user_permissions": 0,
|
|
||||||
"ignore_xss_filter": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_global_search": 0,
|
|
||||||
"in_list_view": 0,
|
|
||||||
"in_standard_filter": 0,
|
|
||||||
"label": "Progress Details",
|
|
||||||
"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,
|
|
||||||
"translatable": 0,
|
|
||||||
"unique": 0
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
"allow_bulk_edit": 0,
|
||||||
"allow_in_quick_entry": 0,
|
"allow_in_quick_entry": 0,
|
||||||
@ -301,40 +304,6 @@
|
|||||||
"set_only_once": 0,
|
"set_only_once": 0,
|
||||||
"translatable": 0,
|
"translatable": 0,
|
||||||
"unique": 0
|
"unique": 0
|
||||||
},
|
|
||||||
{
|
|
||||||
"allow_bulk_edit": 0,
|
|
||||||
"allow_in_quick_entry": 0,
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"columns": 0,
|
|
||||||
"default": "",
|
|
||||||
"fieldname": "naming_series",
|
|
||||||
"fieldtype": "Data",
|
|
||||||
"hidden": 1,
|
|
||||||
"ignore_user_permissions": 0,
|
|
||||||
"ignore_xss_filter": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_global_search": 0,
|
|
||||||
"in_list_view": 0,
|
|
||||||
"in_standard_filter": 0,
|
|
||||||
"label": "Series",
|
|
||||||
"length": 0,
|
|
||||||
"no_copy": 0,
|
|
||||||
"options": "PROJ-UPD-.YYYY.-",
|
|
||||||
"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,
|
|
||||||
"translatable": 0,
|
|
||||||
"unique": 0
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"has_web_view": 0,
|
"has_web_view": 0,
|
||||||
@ -347,7 +316,7 @@
|
|||||||
"issingle": 0,
|
"issingle": 0,
|
||||||
"istable": 0,
|
"istable": 0,
|
||||||
"max_attachments": 0,
|
"max_attachments": 0,
|
||||||
"modified": "2018-08-21 14:44:21.287709",
|
"modified": "2019-01-16 19:31:05.210656",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Projects",
|
"module": "Projects",
|
||||||
"name": "Project Update",
|
"name": "Project Update",
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
{
|
{
|
||||||
"allow_copy": 0,
|
"allow_copy": 0,
|
||||||
|
"allow_events_in_timeline": 0,
|
||||||
"allow_guest_to_view": 0,
|
"allow_guest_to_view": 0,
|
||||||
"allow_import": 0,
|
"allow_import": 0,
|
||||||
"allow_rename": 0,
|
"allow_rename": 0,
|
||||||
@ -44,6 +45,136 @@
|
|||||||
"translatable": 0,
|
"translatable": 0,
|
||||||
"unique": 0
|
"unique": 0
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"allow_bulk_edit": 0,
|
||||||
|
"allow_in_quick_entry": 0,
|
||||||
|
"allow_on_submit": 0,
|
||||||
|
"bold": 0,
|
||||||
|
"collapsible": 0,
|
||||||
|
"columns": 0,
|
||||||
|
"fetch_from": "user.email",
|
||||||
|
"fieldname": "email",
|
||||||
|
"fieldtype": "Read Only",
|
||||||
|
"hidden": 0,
|
||||||
|
"ignore_user_permissions": 0,
|
||||||
|
"ignore_xss_filter": 0,
|
||||||
|
"in_filter": 0,
|
||||||
|
"in_global_search": 0,
|
||||||
|
"in_list_view": 0,
|
||||||
|
"in_standard_filter": 0,
|
||||||
|
"label": "Email",
|
||||||
|
"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,
|
||||||
|
"translatable": 0,
|
||||||
|
"unique": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"allow_bulk_edit": 0,
|
||||||
|
"allow_in_quick_entry": 0,
|
||||||
|
"allow_on_submit": 0,
|
||||||
|
"bold": 0,
|
||||||
|
"collapsible": 0,
|
||||||
|
"columns": 0,
|
||||||
|
"fetch_from": "user.user_image",
|
||||||
|
"fieldname": "image",
|
||||||
|
"fieldtype": "Read Only",
|
||||||
|
"hidden": 1,
|
||||||
|
"ignore_user_permissions": 0,
|
||||||
|
"ignore_xss_filter": 0,
|
||||||
|
"in_filter": 0,
|
||||||
|
"in_global_search": 1,
|
||||||
|
"in_list_view": 0,
|
||||||
|
"in_standard_filter": 0,
|
||||||
|
"label": "Image",
|
||||||
|
"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,
|
||||||
|
"translatable": 0,
|
||||||
|
"unique": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"allow_bulk_edit": 0,
|
||||||
|
"allow_in_quick_entry": 0,
|
||||||
|
"allow_on_submit": 0,
|
||||||
|
"bold": 0,
|
||||||
|
"collapsible": 0,
|
||||||
|
"columns": 0,
|
||||||
|
"fieldname": "column_break_2",
|
||||||
|
"fieldtype": "Column Break",
|
||||||
|
"hidden": 0,
|
||||||
|
"ignore_user_permissions": 0,
|
||||||
|
"ignore_xss_filter": 0,
|
||||||
|
"in_filter": 0,
|
||||||
|
"in_global_search": 0,
|
||||||
|
"in_list_view": 0,
|
||||||
|
"in_standard_filter": 0,
|
||||||
|
"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,
|
||||||
|
"translatable": 0,
|
||||||
|
"unique": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"allow_bulk_edit": 0,
|
||||||
|
"allow_in_quick_entry": 0,
|
||||||
|
"allow_on_submit": 0,
|
||||||
|
"bold": 0,
|
||||||
|
"collapsible": 0,
|
||||||
|
"columns": 0,
|
||||||
|
"default": "user.full_name",
|
||||||
|
"fieldname": "full_name",
|
||||||
|
"fieldtype": "Read Only",
|
||||||
|
"hidden": 0,
|
||||||
|
"ignore_user_permissions": 0,
|
||||||
|
"ignore_xss_filter": 0,
|
||||||
|
"in_filter": 0,
|
||||||
|
"in_global_search": 0,
|
||||||
|
"in_list_view": 0,
|
||||||
|
"in_standard_filter": 0,
|
||||||
|
"label": "Full Name",
|
||||||
|
"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,
|
||||||
|
"translatable": 0,
|
||||||
|
"unique": 0
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
"allow_bulk_edit": 0,
|
||||||
"allow_in_quick_entry": 0,
|
"allow_in_quick_entry": 0,
|
||||||
@ -107,6 +238,70 @@
|
|||||||
"set_only_once": 0,
|
"set_only_once": 0,
|
||||||
"translatable": 0,
|
"translatable": 0,
|
||||||
"unique": 0
|
"unique": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"allow_bulk_edit": 0,
|
||||||
|
"allow_in_quick_entry": 0,
|
||||||
|
"allow_on_submit": 0,
|
||||||
|
"bold": 0,
|
||||||
|
"collapsible": 0,
|
||||||
|
"columns": 0,
|
||||||
|
"fieldname": "section_break_5",
|
||||||
|
"fieldtype": "Section Break",
|
||||||
|
"hidden": 0,
|
||||||
|
"ignore_user_permissions": 0,
|
||||||
|
"ignore_xss_filter": 0,
|
||||||
|
"in_filter": 0,
|
||||||
|
"in_global_search": 0,
|
||||||
|
"in_list_view": 0,
|
||||||
|
"in_standard_filter": 0,
|
||||||
|
"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,
|
||||||
|
"translatable": 0,
|
||||||
|
"unique": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"allow_bulk_edit": 0,
|
||||||
|
"allow_in_quick_entry": 0,
|
||||||
|
"allow_on_submit": 0,
|
||||||
|
"bold": 0,
|
||||||
|
"collapsible": 0,
|
||||||
|
"columns": 0,
|
||||||
|
"depends_on": "eval:parent.doctype == 'Project Update'",
|
||||||
|
"fieldname": "project_status",
|
||||||
|
"fieldtype": "Text",
|
||||||
|
"hidden": 0,
|
||||||
|
"ignore_user_permissions": 0,
|
||||||
|
"ignore_xss_filter": 0,
|
||||||
|
"in_filter": 0,
|
||||||
|
"in_global_search": 0,
|
||||||
|
"in_list_view": 0,
|
||||||
|
"in_standard_filter": 0,
|
||||||
|
"label": "Project Status",
|
||||||
|
"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,
|
||||||
|
"translatable": 0,
|
||||||
|
"unique": 0
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"has_web_view": 0,
|
"has_web_view": 0,
|
||||||
@ -119,7 +314,7 @@
|
|||||||
"issingle": 0,
|
"issingle": 0,
|
||||||
"istable": 1,
|
"istable": 1,
|
||||||
"max_attachments": 0,
|
"max_attachments": 0,
|
||||||
"modified": "2018-09-09 12:39:38.376816",
|
"modified": "2019-01-17 17:10:05.339735",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Projects",
|
"module": "Projects",
|
||||||
"name": "Project User",
|
"name": "Project User",
|
||||||
|
46
erpnext/templates/emails/daily_project_summary.html
Normal file
46
erpnext/templates/emails/daily_project_summary.html
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
<table border="0" cellpadding="0" cellspacing="0" width="100%">
|
||||||
|
<tr>
|
||||||
|
<h3>{{ title }}</h3>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
{% for user in users %}
|
||||||
|
<table class="panel-header" border="0" cellpadding="0" cellspacing="0" width="100%">
|
||||||
|
<tr height="10"></tr>
|
||||||
|
<tr>
|
||||||
|
<td width="15"></td>
|
||||||
|
<td valign="top" width="24">
|
||||||
|
{% if user.image %}
|
||||||
|
<img class="sender-avatar" width="24" height="24" embed="{{ user.image }}"/>
|
||||||
|
{% else %}
|
||||||
|
<div class="sender-avatar-placeholder">
|
||||||
|
{{ user.full_name[0] }}
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
</td>
|
||||||
|
<td width="10"></td>
|
||||||
|
<td>
|
||||||
|
<div class="text-medium text-muted">
|
||||||
|
<span>{{ user.full_name }}</span>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td width="15"></td>
|
||||||
|
</tr>
|
||||||
|
<tr height="10"></tr>
|
||||||
|
</table>
|
||||||
|
<table class="panel-body" border="0" cellpadding="0" cellspacing="0" width="100%">
|
||||||
|
<tr height="10"></tr>
|
||||||
|
<tr>
|
||||||
|
<td width="15"></td>
|
||||||
|
<td>
|
||||||
|
<div>
|
||||||
|
{{ user.project_status }}
|
||||||
|
</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 %}
|
Loading…
Reference in New Issue
Block a user