+
+ {% if user_limit %}
{% var users_percent = ((users / user_limit) * 100); %}
+
Users
+
+
@@ -23,6 +27,70 @@
+ {% endif %}
+
+
+
+ {% if expiry %}
+
Expiration
+ {% var days_remaining = total_days - used_days %}
+ {% var date_percent = (( used_days / total_days) * 100); %}
+
+
+
+
+
+
+ | Creation Date |
+ Expiry Date |
+ Days Remaining |
+
+
+
+
+ | {%= creation %} |
+ {%= expiry %} |
+ {%= days_remaining %} |
+
+
+
+
+ {% endif %}
+
+
+ {% if email_limit %}
+
Emails
+
+ {% var email_percent = (( bulk_count / email_limit ) * 100); %}
+ {% var emails_remaining = (email_limit - bulk_count) %}
+
+
+
+
+
+
+ | Emails Used |
+ Total Emails |
+ Emails Left |
+
+
+
+
+ | {%= bulk_count %} |
+ {%= email_limit %} |
+ {%= emails_remaining %} |
+
+
+
+
+ {% endif %}
+
Disk Space
{% var database_percent = ((database_size / max) * 100); %}
@@ -61,11 +129,15 @@
Total |
{%= total %} MB |
+ {% if max %}
| Available |
{%= flt(max - total, 2) %} MB |
+ {% endif %}
+
+
diff --git a/frappe/core/page/usage_info/usage_info.js b/frappe/core/page/usage_info/usage_info.js
index 689ee9a703..f72f8bfce4 100644
--- a/frappe/core/page/usage_info/usage_info.js
+++ b/frappe/core/page/usage_info/usage_info.js
@@ -6,18 +6,29 @@ frappe.pages['usage-info'].on_page_load = function(wrapper) {
});
frappe.call({
- method: "frappe.limits.get_limits",
- callback: function(doc) {
- doc = doc.message;
- if(!doc.database_size) doc.database_size = 26;
- if(!doc.files_size) doc.files_size = 1;
- if(!doc.backup_size) doc.backup_size = 1;
+ method: "frappe.limits.get_limits",
+ callback: function(r) {
+ var doc = r.message;
+ if(!doc.database_size) doc.database_size = 26;
+ if(!doc.files_size) doc.files_size = 1;
+ if(!doc.backup_size) doc.backup_size = 1;
- doc.max = flt(doc.space_limit * 1024);
- doc.total = (doc.database_size + doc.files_size + doc.backup_size);
- doc.users = keys(frappe.boot.user_info).length - 2;
+ doc.max = flt(doc.space_limit * 1024);
+ doc.total = (doc.database_size + doc.files_size + doc.backup_size);
+ doc.users = keys(frappe.boot.user_info).length - 2;
+ doc.today = frappe.datetime.get_today()
+ doc.total_days = frappe.datetime.get_day_diff(doc.expiry, doc.creation)
+ doc.used_days = frappe.datetime.get_day_diff(doc.today, doc.creation)
- $(frappe.render_template("usage_info", doc)).appendTo(page.main);
+ $(frappe.render_template("usage_info", doc)).appendTo(page.main);
+
+ var btn_text = doc.user_limit == 1 ? __("Upgrade") : __("Renew / Upgrade");
+
+ if(doc.limits_upgrade_link) {
+ page.set_primary_action(btn_text, function() {
+ frappe.set_route("upgrade");
+ });
+ }
}
});
diff --git a/frappe/desk/page/setup_wizard/setup_wizard.json b/frappe/desk/page/setup_wizard/setup_wizard.json
index a2bee8df20..2072d8f79f 100644
--- a/frappe/desk/page/setup_wizard/setup_wizard.json
+++ b/frappe/desk/page/setup_wizard/setup_wizard.json
@@ -1,15 +1,15 @@
{
- "content": null,
- "creation": "2013-10-04 13:49:33",
- "docstatus": 0,
- "doctype": "Page",
- "idx": 1,
- "modified": "2016-06-10 12:05:31.701566",
- "modified_by": "Administrator",
- "module": "Desk",
- "name": "setup-wizard",
- "owner": "Administrator",
- "page_name": "setup-wizard",
+ "content": null,
+ "creation": "2013-10-04 13:49:33",
+ "docstatus": 0,
+ "doctype": "Page",
+ "idx": 1,
+ "modified": "2016-06-15 13:07:32.651564",
+ "modified_by": "Administrator",
+ "module": "Desk",
+ "name": "setup-wizard",
+ "owner": "Administrator",
+ "page_name": "setup-wizard",
"roles": [
{
"role": "Administrator"
diff --git a/frappe/desk/page/setup_wizard/setup_wizard.py b/frappe/desk/page/setup_wizard/setup_wizard.py
old mode 100644
new mode 100755
index 71486d26fa..419648a0ef
--- a/frappe/desk/page/setup_wizard/setup_wizard.py
+++ b/frappe/desk/page/setup_wizard/setup_wizard.py
@@ -10,6 +10,7 @@ from frappe.translate import (set_default_language, get_dict,
from frappe.geo.country_info import get_country_info
from frappe.utils.file_manager import save_file
from frappe.utils.password import update_password
+from werkzeug.useragents import UserAgent
@frappe.whitelist()
def setup_complete(args):
@@ -146,3 +147,75 @@ def load_languages():
"default_language": get_language_from_code(frappe.local.lang),
"languages": sorted(get_lang_dict().keys())
}
+
+
+def prettify_args(args):
+ # remove attachments
+ for key, val in args.items():
+ if isinstance(val, basestring) and "data:image" in val:
+ filename = val.split("data:image", 1)[0].strip(", ")
+ size = round((len(val) * 3 / 4) / 1048576.0, 2)
+ args[key] = "Image Attached: '{0}' of size {1} MB".format(filename, size)
+
+ pretty_args = []
+ for key in sorted(args):
+ pretty_args.append("{} = {}".format(key, args[key]))
+ return pretty_args
+
+def email_setup_wizard_exception(traceback, args):
+ from frappe.limits import get_limits
+ frappe_limits = get_limits()
+
+ if not frappe_limits.get('setup_wizard_exception_email'):
+ return
+
+ pretty_args = prettify_args(args)
+
+ if frappe.local.request:
+ user_agent = UserAgent(frappe.local.request.headers.get('User-Agent', ''))
+
+ else:
+ user_agent = frappe._dict()
+
+ message = """
+#### Basic Information
+
+- **Site:** {site}
+- **User:** {user}
+- **Browser:** {user_agent.platform} {user_agent.browser} version: {user_agent.version} language: {user_agent.language}
+- **Browser Languages**: `{accept_languages}`
+
+---
+
+#### Traceback
+
+
{traceback}
+
+---
+
+#### Setup Wizard Arguments
+
+
{args}
+
+---
+
+#### Request Headers
+
+
{headers}""".format(
+ site=frappe.local.site,
+ traceback=traceback,
+ args="\n".join(pretty_args),
+ user=frappe.session.user,
+ user_agent=user_agent,
+ headers=frappe.local.request.headers,
+ accept_languages=", ".join(frappe.local.request.accept_languages.values()))
+
+ frappe.sendmail(recipients=frappe_limits.get('setup_wizard_exception_email'),
+ sender=frappe.session.user,
+ subject="Exception in Setup Wizard - {}".format(frappe.local.site),
+ message=message)
+
+
+def set_setup_complete(*args):
+ from frappe.limits import set_limits
+ set_limits({'setup_complete' : 1 , 'creation': frappe.utils.today()})
diff --git a/frappe/email/bulk.py b/frappe/email/bulk.py
old mode 100644
new mode 100755
index 5d8d411f86..48885237a4
--- a/frappe/email/bulk.py
+++ b/frappe/email/bulk.py
@@ -334,3 +334,8 @@ def clear_outbox():
"""Remove mails older than 31 days in Outbox. Called daily via scheduler."""
frappe.db.sql("""delete from `tabBulk Email` where
datediff(now(), creation) > 31""")
+
+def prevent_bulk_email_delete(doc, method):
+ from frappe.limits import get_limits
+ if frappe.session.user != 'Administrator' and get_limits().get('block_bulk_email_delete'):
+ frappe.throw(_('Only Administrator can delete Bulk Email'))
\ No newline at end of file
diff --git a/frappe/hooks.py b/frappe/hooks.py
index 197ad77395..cd300d813c 100755
--- a/frappe/hooks.py
+++ b/frappe/hooks.py
@@ -14,6 +14,11 @@ app_email = "info@frappe.io"
before_install = "frappe.utils.install.before_install"
after_install = "frappe.utils.install.after_install"
+extend_bootinfo = "frappe.limits.load_limits"
+
+page_js = {
+ "setup-wizard": "public/js/frappe/setup_wizard.js"
+}
# website
app_include_js = [
@@ -23,7 +28,8 @@ app_include_js = [
"assets/js/list.min.js",
"assets/js/form.min.js",
"assets/js/report.min.js",
- "assets/js/d3.min.js"
+ "assets/js/d3.min.js",
+ "assets/frappe/js/frappe/toolbar.js"
]
app_include_css = [
"assets/css/desk.min.css",
@@ -64,7 +70,7 @@ calendars = ["Event"]
on_session_creation = [
"frappe.core.doctype.communication.feed.login_feed",
"frappe.core.doctype.user.user.notifify_admin_access_to_system_manager",
- "frappe.limits.check_if_expired", #Unsure of where to move
+ "frappe.limits.check_if_expired",
"frappe.utils.scheduler.reset_enabled_scheduler_events",
]
@@ -93,6 +99,9 @@ doc_events = {
"User": {
"validate": "frappe.utils.user.validate_user_limit"
},
+ "Bulk Email": {
+ "on_trash": "frappe.email.bulk.prevent_bulk_email_delete"
+ },
"*": {
"after_insert": "frappe.email.doctype.email_alert.email_alert.trigger_email_alerts",
"validate": "frappe.email.doctype.email_alert.email_alert.trigger_email_alerts",
@@ -170,4 +179,6 @@ bot_parsers = [
'frappe.utils.bot.CountBot'
]
+setup_wizard_exception = "frappe.desk.page.setup_wizard.setup_wizard.email_setup_wizard_exception"
+setup_wizard_success = "frappe.desk.page.setup_wizard.setup_wizard.set_setup_complete"
before_write_file = "frappe.core.doctype.file.file.validate_space_limit"
diff --git a/frappe/limits.py b/frappe/limits.py
index 053bcac880..9f671902fa 100755
--- a/frappe/limits.py
+++ b/frappe/limits.py
@@ -1,25 +1,24 @@
from __future__ import unicode_literals
import frappe
-import subprocess, os
-from frappe.model.document import Document
-from frappe.core.doctype.user.user import get_total_users
-from frappe.utils import flt, cint, now_datetime, getdate, get_site_path
+from frappe.utils import now_datetime, getdate
from frappe.installer import update_site_config
-from frappe.utils.file_manager import MaxFileSizeReachedError
from frappe.utils.data import formatdate
from frappe import _
class SiteExpiredError(frappe.ValidationError):
pass
+EXPIRY_WARNING_DAYS = 10
+
+def load_limits(bootinfo):
+ bootinfo["frappe_limits"] = get_limits()
+ bootinfo["expiry_message"] = get_expiry_message()
+
def has_expired():
if frappe.session.user=="Administrator":
return False
- if not get_limits():
- return False
-
expires_on = get_limits().get("expiry")
if not expires_on:
return False
@@ -35,14 +34,46 @@ def check_if_expired():
return
# if expired, stop user from logging in
expires_on = formatdate(get_limits().get("expiry"))
+ support_email = get_limits().get("support_email") or _("your provider")
- frappe.throw("""Your subscription expired on
{}.
- To extend please drop a mail at
support@erpnext.com""".format(expires_on),
+ frappe.throw(_("""Your subscription expired on {0}.
+ To extend please send an email to {1}""").format(expires_on, support_email),
SiteExpiredError)
+def get_expiry_message():
+ if "System Manager" not in frappe.get_roles():
+ return ""
+
+ if not get_limits().get("expiry"):
+ return ""
+
+ expires_on = getdate(get_limits().get("expiry"))
+ today = now_datetime().date()
+
+ message = ""
+ if today > expires_on:
+ message = _("Your subscription has expired")
+ else:
+ days_to_expiry = (expires_on - today).days
+
+ if days_to_expiry == 0:
+ message = _("Your subscription will expire today")
+
+ elif days_to_expiry == 1:
+ message = _("Your subscription will expire tomorrow")
+
+ elif days_to_expiry <= EXPIRY_WARNING_DAYS:
+ message = _("Your subscription will expire on") + " " + formatdate(expires_on)
+
+ return message
+
+
@frappe.whitelist()
def get_limits():
- return frappe.get_conf().get("limits")
+ limits = frappe.get_conf().get("limits") or {}
+ day = frappe.utils.add_months(frappe.utils.today(), -1)
+ limits["bulk_count"] = frappe.db.count("Bulk Email", filters={'creation': ['>', day]})
+ return limits
def set_limits(limits):
@@ -55,7 +86,7 @@ def set_limits(limits):
def clear_limit(limit):
- frappe_limits = get_limits() or {}
+ frappe_limits = get_limits()
if limit in frappe_limits:
del frappe_limits[limit]
diff --git a/frappe/public/build.json b/frappe/public/build.json
old mode 100644
new mode 100755
diff --git a/frappe/public/js/frappe/setup_wizard.js b/frappe/public/js/frappe/setup_wizard.js
new file mode 100755
index 0000000000..66d6795c9b
--- /dev/null
+++ b/frappe/public/js/frappe/setup_wizard.js
@@ -0,0 +1,18 @@
+frappe.wiz.on("after_load", function() {
+ if (frappe.boot.frappe_limits.user_limit===1) {
+ // remove users slide
+ var users_slide;
+ for (var i in frappe.wiz.wizard.slides) {
+ var slide = frappe.wiz.wizard.slides[i];
+ if (slide.title === frappe.wiz.user.title) {
+ users_slide = i;
+ break;
+ }
+ }
+
+ if (users_slide >= 0) {
+ frappe.wiz.wizard.slides.splice(users_slide, 1);
+ }
+
+ }
+});
diff --git a/frappe/public/js/frappe/toolbar.js b/frappe/public/js/frappe/toolbar.js
new file mode 100755
index 0000000000..d034052563
--- /dev/null
+++ b/frappe/public/js/frappe/toolbar.js
@@ -0,0 +1,55 @@
+// Copyright (c) 2015, Frappe Technologies Pvt. Ltd.
+// For license information, please see license.txt
+
+$(document).on("toolbar_setup", function() {
+ var help_links = [];
+ var support_link = "#upgrade";
+ var chat_link = "#upgrade";
+ frappe_limits = frappe.boot.frappe_limits
+
+ if(frappe.boot.expiry_message) {
+ frappe.msgprint(frappe.boot.expiry_message)
+ }
+
+ if(frappe_limits.support_email || frappe_limits.support_chat) {
+ help_links.push('
');
+ }
+
+ if(frappe_limits.support_email) {
+ support_link = 'mailto:'+frappe.boot.frappe_limits.support_email;
+ help_links.push('
' + frappe._('Email Support') + '');
+ }
+
+ if(frappe_limits.support_chat) {
+ chat_link = frappe_limits.support_chat;
+ help_links.push('
' + frappe._('Chat Support') + '');
+ }
+
+
+ $(help_links.join("\n")).insertBefore($("#toolbar-user").find(".divider:last"));
+
+ if(frappe_limits.space_limit || frappe_limits.user_limit || frappe_limits.expiry || frappe_limits.email_limit)
+ {
+ help_links = [];
+ help_links.push('
' + frappe._('Usage Info') + '');
+ help_links.push('
');
+ }
+
+ $(help_links.join("\n")).insertBefore($("#toolbar-user").find("li:first"));
+});
+
+frappe.get_form_sidebar_extension = function() {
+ var fs = frappe.boot.frappe_limits;
+ if(!fs.sidebar_usage_html) {
+ fs.total_used = flt(fs.database_size + fs.backup_size + fs.files_size);
+ fs.total_used_percent = cint(fs.total_used / flt(fs.max_space * 1024) * 100);
+
+ var template = '';
+ fs.sidebar_usage_html = frappe.render(template, {fs:fs}, "form_sidebar_usage");
+ }
+
+ return fs.sidebar_usage_html;
+}