diff --git a/frappe/__init__.py b/frappe/__init__.py index 536e721048..9e176e6077 100644 --- a/frappe/__init__.py +++ b/frappe/__init__.py @@ -310,7 +310,7 @@ def sendmail(recipients=(), sender="", subject="No Subject", message="No Message as_markdown=False, bulk=False, reference_doctype=None, reference_name=None, unsubscribe_method=None, unsubscribe_params=None, unsubscribe_message=None, attachments=None, content=None, doctype=None, name=None, reply_to=None, - cc=(), message_id=None, as_bulk=False, send_after=None, expose_recipients=False, + cc=(), show_as_cc=(), message_id=None, as_bulk=False, send_after=None, expose_recipients=False, bulk_priority=1): """Send email using user's default **Email Account** or global default **Email Account**. @@ -339,7 +339,7 @@ def sendmail(recipients=(), sender="", subject="No Subject", message="No Message subject=subject, message=content or message, reference_doctype = doctype or reference_doctype, reference_name = name or reference_name, unsubscribe_method=unsubscribe_method, unsubscribe_params=unsubscribe_params, unsubscribe_message=unsubscribe_message, - attachments=attachments, reply_to=reply_to, cc=cc, message_id=message_id, send_after=send_after, + attachments=attachments, reply_to=reply_to, cc=cc, show_as_cc=show_as_cc, message_id=message_id, send_after=send_after, expose_recipients=expose_recipients, bulk_priority=bulk_priority) else: import frappe.email @@ -469,11 +469,14 @@ def get_precision(doctype, fieldname, currency=None, doc=None): from frappe.model.meta import get_field_precision return get_field_precision(get_meta(doctype).get_field(fieldname), doc, currency) -def generate_hash(txt=None): +def generate_hash(txt=None, length=None): """Generates random hash for given text + current timestamp + random string.""" import hashlib, time from .utils import random_string - return hashlib.sha224((txt or "") + repr(time.time()) + repr(random_string(8))).hexdigest() + digest = hashlib.sha224((txt or "") + repr(time.time()) + repr(random_string(8))).hexdigest() + if length: + digest = digest[:length] + return digest def reset_metadata_version(): """Reset `metadata_version` (Client (Javascript) build ID) hash.""" @@ -735,6 +738,9 @@ def get_file_json(path): def read_file(path, raise_not_found=False): """Open a file and return its content as Unicode.""" from frappe.utils import cstr + if isinstance(path, unicode): + path = path.encode("utf-8") + if os.path.exists(path): with open(path, "r") as f: return cstr(f.read()) diff --git a/frappe/__version__.py b/frappe/__version__.py index a38fe1d5b2..895d82fee6 100644 --- a/frappe/__version__.py +++ b/frappe/__version__.py @@ -1,2 +1,2 @@ from __future__ import unicode_literals -__version__ = "6.4.9" +__version__ = "6.5.0" diff --git a/frappe/change_log/v6/v6_5_0.md b/frappe/change_log/v6/v6_5_0.md new file mode 100644 index 0000000000..62afbd34c3 --- /dev/null +++ b/frappe/change_log/v6/v6_5_0.md @@ -0,0 +1,2 @@ +- **Linked With** will now show links from Dynamic Links +- **Data** field-type size truncated to 140 characters from 255 (by default). Can be changed by setting the **length** property from **Customize Form View** diff --git a/frappe/commands.py b/frappe/commands.py index c96ccaa40d..632d128402 100644 --- a/frappe/commands.py +++ b/frappe/commands.py @@ -383,15 +383,28 @@ def reset_perms(context): @click.command('execute') @click.argument('method') +@click.option('--args') +@click.option('--kwargs') @pass_context -def execute(context, method): +def execute(context, method, args=None, kwargs=None): "execute a function" for site in context.sites: try: frappe.init(site=site) frappe.connect() print frappe.local.site - ret = frappe.get_attr(method)() + + if args: + args = eval(args) + else: + args = () + + if kwargs: + kwargs = eval(args) + else: + kwargs = {} + + ret = frappe.get_attr(method)(*args, **kwargs) if frappe.db: frappe.db.commit() @@ -862,7 +875,9 @@ def drop_site(site, root_login='root', root_password=None): def get_version(context): frappe.init(site=context.sites[0]) for m in sorted(frappe.local.app_modules.keys()): - print "{0} {1}".format(m, frappe.get_module(m).__version__) + module = frappe.get_module(m) + if hasattr(module, "__version__"): + print "{0} {1}".format(m, module.__version__) # commands = [ # new_site, diff --git a/frappe/core/doctype/async_task/async_task.json b/frappe/core/doctype/async_task/async_task.json index 330596ccd2..0e63df9957 100644 --- a/frappe/core/doctype/async_task/async_task.json +++ b/frappe/core/doctype/async_task/async_task.json @@ -19,7 +19,7 @@ "ignore_user_permissions": 0, "in_filter": 0, "in_list_view": 0, - "label": "Status", + "label": "Status", "no_copy": 0, "options": "\nQueued\nRunning\nSucceeded\nFailed\n", "permlevel": 0, @@ -195,7 +195,7 @@ "is_submittable": 0, "issingle": 0, "istable": 0, - "modified": "2015-09-07 08:08:22.193911", + "modified": "2015-10-02 07:38:38.658939", "modified_by": "Administrator", "module": "Core", "name": "Async Task", diff --git a/frappe/core/doctype/block_module/block_module.json b/frappe/core/doctype/block_module/block_module.json index af1648a2b5..3473e6fe88 100644 --- a/frappe/core/doctype/block_module/block_module.json +++ b/frappe/core/doctype/block_module/block_module.json @@ -39,7 +39,7 @@ "is_submittable": 0, "issingle": 0, "istable": 1, - "modified": "2015-03-24 16:03:52.359042", + "modified": "2015-10-02 07:38:39.485971", "modified_by": "Administrator", "module": "Core", "name": "Block Module", diff --git a/frappe/core/doctype/comment/comment.json b/frappe/core/doctype/comment/comment.json index d928532acd..f03c3cec89 100644 --- a/frappe/core/doctype/comment/comment.json +++ b/frappe/core/doctype/comment/comment.json @@ -292,7 +292,7 @@ "is_submittable": 0, "issingle": 0, "istable": 0, - "modified": "2015-06-08 12:31:15.122312", + "modified": "2015-10-02 07:38:41.308408", "modified_by": "Administrator", "module": "Core", "name": "Comment", diff --git a/frappe/core/doctype/comment/comment.py b/frappe/core/doctype/comment/comment.py index 6d798de258..43e68cab33 100644 --- a/frappe/core/doctype/comment/comment.py +++ b/frappe/core/doctype/comment/comment.py @@ -9,6 +9,8 @@ from frappe.model.document import Document from frappe.model.db_schema import add_column from frappe.utils import get_fullname +exclude_from_linked_with = True + class Comment(Document): """Comments are added to Documents via forms or views like blogs etc.""" no_feed_on_delete = True diff --git a/frappe/core/doctype/communication/communication.json b/frappe/core/doctype/communication/communication.json index 77ddb28d51..5bd167c3fc 100644 --- a/frappe/core/doctype/communication/communication.json +++ b/frappe/core/doctype/communication/communication.json @@ -21,7 +21,7 @@ "ignore_user_permissions": 0, "in_filter": 0, "in_list_view": 0, - "label": "Series", + "label": "Series", "no_copy": 0, "options": "COMM-", "permlevel": 0, @@ -44,7 +44,7 @@ "ignore_user_permissions": 0, "in_filter": 0, "in_list_view": 0, - "label": "Communication Medium", + "label": "Communication Medium", "no_copy": 0, "options": "\nChat\nPhone\nEmail\nSMS\nVisit\nOther", "permlevel": 0, @@ -153,7 +153,7 @@ "ignore_user_permissions": 0, "in_filter": 0, "in_list_view": 1, - "label": "Status", + "label": "Status", "no_copy": 0, "options": "Open\nReplied\nClosed\nLinked", "permlevel": 0, @@ -176,7 +176,7 @@ "ignore_user_permissions": 0, "in_filter": 0, "in_list_view": 1, - "label": "Sent or Received", + "label": "Sent or Received", "no_copy": 0, "options": "Sent\nReceived", "permlevel": 0, @@ -199,7 +199,7 @@ "ignore_user_permissions": 0, "in_filter": 0, "in_list_view": 0, - "label": "Delivery Status", + "label": "Delivery Status", "no_copy": 0, "options": "\nSent\nBounced\nOpened\nMarked As Spam\nRejected\nDelayed\nSoft-Bounced\nClicked\nRecipient Unsubscribed", "permlevel": 0, @@ -573,7 +573,7 @@ "is_submittable": 0, "issingle": 0, "istable": 0, - "modified": "2015-09-24 02:27:43.536919", + "modified": "2015-10-02 07:38:41.472917", "modified_by": "Administrator", "module": "Core", "name": "Communication", diff --git a/frappe/core/doctype/communication/communication.py b/frappe/core/doctype/communication/communication.py index e56b69c9df..6d372dd8b7 100644 --- a/frappe/core/doctype/communication/communication.py +++ b/frappe/core/doctype/communication/communication.py @@ -5,7 +5,7 @@ from __future__ import unicode_literals, absolute_import import frappe import json from email.utils import formataddr, parseaddr -from frappe.utils import get_url, get_formatted_email, cstr, cint, validate_email_add, split_emails +from frappe.utils import get_url, get_formatted_email, cint, validate_email_add, split_emails from frappe.utils.file_manager import get_file import frappe.email.smtp from frappe import _ @@ -106,7 +106,7 @@ class Communication(Document): from frappe.tasks import sendmail sendmail.delay(frappe.local.site, self.name, print_html=print_html, print_format=print_format, attachments=attachments, - recipients=recipients, cc=cc) + recipients=recipients, cc=cc, lang=frappe.local.lang) def _notify(self, print_html=None, print_format=None, attachments=None, recipients=None, cc=None): @@ -115,6 +115,7 @@ class Communication(Document): frappe.sendmail( recipients=(recipients or []) + (cc or []), + show_as_cc=(cc or []), expose_recipients=True, sender=self.sender, reply_to=self.incoming_email_account, @@ -230,8 +231,8 @@ class Communication(Document): cc = split_emails(self.cc) if self.reference_doctype and self.reference_name: - if not cc or fetched_from_email_account: - # if CC is not mentioned from the UI or is a fetched email, add follows to CC + if fetched_from_email_account: + # if it is a fetched email, add follows to CC cc.append(self.get_owner_email()) cc += self.get_assignees() cc += self.get_starrers() @@ -261,7 +262,7 @@ class Communication(Document): exclude += [d[0] for d in frappe.db.get_all("Email Unsubscribe", ["email"], {"reference_doctype": self.reference_doctype, "reference_name": self.reference_name}, as_list=True)] - cc = self.filter_email_list(cc, exclude) + cc = self.filter_email_list(cc, exclude, is_cc=True) if getattr(self, "send_me_a_copy", False) and self.sender not in cc: self.all_email_addresses.append(self.sender) @@ -269,7 +270,7 @@ class Communication(Document): return cc - def filter_email_list(self, email_list, exclude): + def filter_email_list(self, email_list, exclude, is_cc=False): # temp variables filtered = [] email_address_list = [] @@ -285,6 +286,12 @@ class Communication(Document): if email_address in exclude: continue + if is_cc: + is_user_enabled = frappe.db.get_value("User", email_address, "enabled") + if is_user_enabled==0: + # don't send to disabled users + continue + # make sure of case-insensitive uniqueness of email address if email_address not in email_address_list: # append the full email i.e. "Human " diff --git a/frappe/core/doctype/defaultvalue/defaultvalue.json b/frappe/core/doctype/defaultvalue/defaultvalue.json index e6c4c66998..5bf6b116d0 100644 --- a/frappe/core/doctype/defaultvalue/defaultvalue.json +++ b/frappe/core/doctype/defaultvalue/defaultvalue.json @@ -67,7 +67,7 @@ "is_submittable": 0, "issingle": 0, "istable": 1, - "modified": "2015-02-19 01:06:59.622792", + "modified": "2015-10-02 07:38:44.346115", "modified_by": "Administrator", "module": "Core", "name": "DefaultValue", diff --git a/frappe/core/doctype/docfield/docfield.json b/frappe/core/doctype/docfield/docfield.json index c88952f5f0..462083224b 100644 --- a/frappe/core/doctype/docfield/docfield.json +++ b/frappe/core/doctype/docfield/docfield.json @@ -1,839 +1,864 @@ { - "allow_copy": 0, - "allow_import": 0, - "allow_rename": 0, - "autoname": "hash", - "creation": "2013-02-22 01:27:33", - "custom": 0, - "docstatus": 0, - "doctype": "DocType", + "allow_copy": 0, + "allow_import": 0, + "allow_rename": 0, + "autoname": "hash", + "creation": "2013-02-22 01:27:33", + "custom": 0, + "docstatus": 0, + "doctype": "DocType", "fields": [ { - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "fieldname": "label_and_type", - "fieldtype": "Section Break", - "hidden": 0, - "ignore_user_permissions": 0, - "in_filter": 0, - "in_list_view": 0, - "label": "", - "no_copy": 0, - "permlevel": 0, - "print_hide": 0, - "read_only": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "fieldname": "label_and_type", + "fieldtype": "Section Break", + "hidden": 0, + "ignore_user_permissions": 0, + "in_filter": 0, + "in_list_view": 0, + "label": "", + "no_copy": 0, + "permlevel": 0, + "print_hide": 0, + "read_only": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, "unique": 0 - }, + }, { - "allow_on_submit": 0, - "bold": 1, - "collapsible": 0, - "fieldname": "label", - "fieldtype": "Data", - "hidden": 0, - "ignore_user_permissions": 0, - "in_filter": 0, - "in_list_view": 1, - "label": "Label", - "no_copy": 0, - "oldfieldname": "label", - "oldfieldtype": "Data", - "permlevel": 0, - "print_hide": 0, - "print_width": "163", - "read_only": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 1, - "set_only_once": 0, - "unique": 0, + "allow_on_submit": 0, + "bold": 1, + "collapsible": 0, + "fieldname": "label", + "fieldtype": "Data", + "hidden": 0, + "ignore_user_permissions": 0, + "in_filter": 0, + "in_list_view": 1, + "label": "Label", + "no_copy": 0, + "oldfieldname": "label", + "oldfieldtype": "Data", + "permlevel": 0, + "print_hide": 0, + "print_width": "163", + "read_only": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 1, + "set_only_once": 0, + "unique": 0, "width": "163" - }, + }, { - "allow_on_submit": 0, - "bold": 1, - "collapsible": 0, - "default": "Data", - "fieldname": "fieldtype", - "fieldtype": "Select", - "hidden": 0, - "ignore_user_permissions": 0, - "in_filter": 0, - "in_list_view": 1, - "label": "Type", - "no_copy": 0, - "oldfieldname": "fieldtype", - "oldfieldtype": "Select", - "options": "Attach\nAttach Image\nButton\nCheck\nCode\nColumn Break\nCurrency\nData\nDate\nDatetime\nDynamic Link\nFloat\nFold\nHeading\nHTML\nImage\nInt\nLink\nLong Text\nPassword\nPercent\nRead Only\nSection Break\nSelect\nSmall Text\nTable\nText\nText Editor\nTime", - "permlevel": 0, - "print_hide": 0, - "read_only": 0, - "report_hide": 0, - "reqd": 1, - "search_index": 1, - "set_only_once": 0, + "allow_on_submit": 0, + "bold": 1, + "collapsible": 0, + "default": "Data", + "fieldname": "fieldtype", + "fieldtype": "Select", + "hidden": 0, + "ignore_user_permissions": 0, + "in_filter": 0, + "in_list_view": 1, + "label": "Type", + "no_copy": 0, + "oldfieldname": "fieldtype", + "oldfieldtype": "Select", + "options": "Attach\nAttach Image\nButton\nCheck\nCode\nColumn Break\nCurrency\nData\nDate\nDatetime\nDynamic Link\nFloat\nFold\nHeading\nHTML\nImage\nInt\nLink\nLong Text\nPassword\nPercent\nRead Only\nSection Break\nSelect\nSmall Text\nTable\nText\nText Editor\nTime", + "permlevel": 0, + "print_hide": 0, + "read_only": 0, + "report_hide": 0, + "reqd": 1, + "search_index": 1, + "set_only_once": 0, "unique": 0 - }, + }, { - "allow_on_submit": 0, - "bold": 1, - "collapsible": 0, - "fieldname": "fieldname", - "fieldtype": "Data", - "hidden": 0, - "ignore_user_permissions": 0, - "in_filter": 0, - "in_list_view": 1, - "label": "Name", - "no_copy": 0, - "oldfieldname": "fieldname", - "oldfieldtype": "Data", - "permlevel": 0, - "print_hide": 0, - "read_only": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 1, - "set_only_once": 0, + "allow_on_submit": 0, + "bold": 1, + "collapsible": 0, + "fieldname": "fieldname", + "fieldtype": "Data", + "hidden": 0, + "ignore_user_permissions": 0, + "in_filter": 0, + "in_list_view": 1, + "label": "Name", + "no_copy": 0, + "oldfieldname": "fieldname", + "oldfieldtype": "Data", + "permlevel": 0, + "print_hide": 0, + "read_only": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 1, + "set_only_once": 0, "unique": 0 - }, + }, { - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "fieldname": "reqd", - "fieldtype": "Check", - "hidden": 0, - "ignore_user_permissions": 0, - "in_filter": 0, - "in_list_view": 1, - "label": "Mandatory", - "no_copy": 0, - "oldfieldname": "reqd", - "oldfieldtype": "Check", - "permlevel": 0, - "print_hide": 0, - "print_width": "50px", - "read_only": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "unique": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "fieldname": "reqd", + "fieldtype": "Check", + "hidden": 0, + "ignore_user_permissions": 0, + "in_filter": 0, + "in_list_view": 1, + "label": "Mandatory", + "no_copy": 0, + "oldfieldname": "reqd", + "oldfieldtype": "Check", + "permlevel": 0, + "print_hide": 0, + "print_width": "50px", + "read_only": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "unique": 0, "width": "50px" - }, + }, { - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "depends_on": "eval:in_list([\"Float\", \"Currency\", \"Percent\"], doc.fieldtype)", - "description": "Set non-standard precision for a Float or Currency field", - "fieldname": "precision", - "fieldtype": "Select", - "hidden": 0, - "ignore_user_permissions": 0, - "in_filter": 0, - "in_list_view": 0, - "label": "Precision", - "no_copy": 0, - "options": "\n1\n2\n3\n4\n5\n6\n7\n8\n9", - "permlevel": 0, - "print_hide": 1, - "read_only": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "depends_on": "eval:in_list([\"Float\", \"Currency\", \"Percent\"], doc.fieldtype)", + "description": "Set non-standard precision for a Float or Currency field", + "fieldname": "precision", + "fieldtype": "Select", + "hidden": 0, + "ignore_user_permissions": 0, + "in_filter": 0, + "in_list_view": 0, + "label": "Precision", + "no_copy": 0, + "options": "\n1\n2\n3\n4\n5\n6\n7\n8\n9", + "permlevel": 0, + "print_hide": 1, + "read_only": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, "unique": 0 - }, + }, { - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "fieldname": "search_index", - "fieldtype": "Check", - "hidden": 0, - "ignore_user_permissions": 0, - "in_filter": 0, - "in_list_view": 0, - "label": "Index", - "no_copy": 0, - "oldfieldname": "search_index", - "oldfieldtype": "Check", - "permlevel": 0, - "print_hide": 0, - "print_width": "50px", - "read_only": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "unique": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "depends_on": "eval:in_list(['Data', 'Link', 'Dynamic Link', 'Password', 'Select', 'Read Only', 'Attach', 'Attach Image'], doc.fieldtype)", + "fieldname": "length", + "fieldtype": "Int", + "hidden": 0, + "ignore_user_permissions": 0, + "in_filter": 0, + "in_list_view": 0, + "label": "Length", + "no_copy": 0, + "permlevel": 0, + "precision": "", + "print_hide": 0, + "read_only": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "unique": 0 + }, + { + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "fieldname": "search_index", + "fieldtype": "Check", + "hidden": 0, + "ignore_user_permissions": 0, + "in_filter": 0, + "in_list_view": 0, + "label": "Index", + "no_copy": 0, + "oldfieldname": "search_index", + "oldfieldtype": "Check", + "permlevel": 0, + "print_hide": 0, + "print_width": "50px", + "read_only": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "unique": 0, "width": "50px" - }, + }, { - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "fieldname": "in_list_view", - "fieldtype": "Check", - "hidden": 0, - "ignore_user_permissions": 0, - "in_filter": 0, - "in_list_view": 0, - "label": "In List View", - "no_copy": 0, - "permlevel": 0, - "print_hide": 0, - "print_width": "70px", - "read_only": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "unique": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "fieldname": "in_list_view", + "fieldtype": "Check", + "hidden": 0, + "ignore_user_permissions": 0, + "in_filter": 0, + "in_list_view": 0, + "label": "In List View", + "no_copy": 0, + "permlevel": 0, + "print_hide": 0, + "print_width": "70px", + "read_only": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "unique": 0, "width": "70px" - }, + }, { - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "fieldname": "bold", - "fieldtype": "Check", - "hidden": 0, - "ignore_user_permissions": 0, - "in_filter": 0, - "in_list_view": 0, - "label": "Bold", - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "read_only": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "fieldname": "bold", + "fieldtype": "Check", + "hidden": 0, + "ignore_user_permissions": 0, + "in_filter": 0, + "in_list_view": 0, + "label": "Bold", + "no_copy": 0, + "permlevel": 0, + "precision": "", + "print_hide": 0, + "read_only": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, "unique": 0 - }, + }, { - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "depends_on": "eval:doc.fieldtype===\"Section Break\"", - "fieldname": "collapsible", - "fieldtype": "Check", - "hidden": 0, - "ignore_user_permissions": 0, - "in_filter": 0, - "in_list_view": 0, - "label": "Collapsible", - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "read_only": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "depends_on": "eval:doc.fieldtype===\"Section Break\"", + "fieldname": "collapsible", + "fieldtype": "Check", + "hidden": 0, + "ignore_user_permissions": 0, + "in_filter": 0, + "in_list_view": 0, + "label": "Collapsible", + "length": 255, + "no_copy": 0, + "permlevel": 0, + "precision": "", + "print_hide": 0, + "read_only": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, "unique": 0 - }, + }, { - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "depends_on": "eval:doc.fieldtype==\"Section Break\"", - "fieldname": "collapsible_depends_on", - "fieldtype": "Data", - "hidden": 0, - "ignore_user_permissions": 0, - "in_filter": 0, - "in_list_view": 0, - "label": "Collapsible Depends On", - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "read_only": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "depends_on": "eval:doc.fieldtype==\"Section Break\"", + "fieldname": "collapsible_depends_on", + "fieldtype": "Small Text", + "hidden": 0, + "ignore_user_permissions": 0, + "in_filter": 0, + "in_list_view": 0, + "label": "Collapsible Depends On", + "no_copy": 0, + "permlevel": 0, + "precision": "", + "print_hide": 0, + "read_only": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, "unique": 0 - }, + }, { - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "fieldname": "column_break_6", - "fieldtype": "Column Break", - "hidden": 0, - "ignore_user_permissions": 0, - "in_filter": 0, - "in_list_view": 0, - "no_copy": 0, - "permlevel": 0, - "print_hide": 0, - "read_only": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "fieldname": "column_break_6", + "fieldtype": "Column Break", + "hidden": 0, + "ignore_user_permissions": 0, + "in_filter": 0, + "in_list_view": 0, + "no_copy": 0, + "permlevel": 0, + "print_hide": 0, + "read_only": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, "unique": 0 - }, + }, { - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "description": "For Links, enter the DocType as range.\nFor Select, enter list of Options, each on a new line.", - "fieldname": "options", - "fieldtype": "Text", - "hidden": 0, - "ignore_user_permissions": 0, - "in_filter": 0, - "in_list_view": 1, - "label": "Options", - "no_copy": 0, - "oldfieldname": "options", - "oldfieldtype": "Text", - "permlevel": 0, - "print_hide": 0, - "read_only": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "description": "For Links, enter the DocType as range.\nFor Select, enter list of Options, each on a new line.", + "fieldname": "options", + "fieldtype": "Text", + "hidden": 0, + "ignore_user_permissions": 0, + "in_filter": 0, + "in_list_view": 1, + "label": "Options", + "no_copy": 0, + "oldfieldname": "options", + "oldfieldtype": "Text", + "permlevel": 0, + "print_hide": 0, + "read_only": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, "unique": 0 - }, + }, { - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "fieldname": "default", - "fieldtype": "Small Text", - "hidden": 0, - "ignore_user_permissions": 0, - "in_filter": 0, - "in_list_view": 0, - "label": "Default", - "no_copy": 0, - "oldfieldname": "default", - "oldfieldtype": "Text", - "permlevel": 0, - "print_hide": 0, - "read_only": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "fieldname": "default", + "fieldtype": "Small Text", + "hidden": 0, + "ignore_user_permissions": 0, + "in_filter": 0, + "in_list_view": 0, + "label": "Default", + "no_copy": 0, + "oldfieldname": "default", + "oldfieldtype": "Text", + "permlevel": 0, + "print_hide": 0, + "read_only": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, "unique": 0 - }, + }, { - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "fieldname": "permissions", - "fieldtype": "Section Break", - "hidden": 0, - "ignore_user_permissions": 0, - "in_filter": 0, - "in_list_view": 0, - "label": "Permissions", - "no_copy": 0, - "permlevel": 0, - "print_hide": 0, - "read_only": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "fieldname": "permissions", + "fieldtype": "Section Break", + "hidden": 0, + "ignore_user_permissions": 0, + "in_filter": 0, + "in_list_view": 0, + "label": "Permissions", + "no_copy": 0, + "permlevel": 0, + "print_hide": 0, + "read_only": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, "unique": 0 - }, + }, { - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "fieldname": "depends_on", - "fieldtype": "Data", - "hidden": 0, - "ignore_user_permissions": 0, - "in_filter": 0, - "in_list_view": 0, - "label": "Depends On", - "no_copy": 0, - "oldfieldname": "depends_on", - "oldfieldtype": "Data", - "permlevel": 0, - "print_hide": 0, - "read_only": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "fieldname": "depends_on", + "fieldtype": "Small Text", + "hidden": 0, + "ignore_user_permissions": 0, + "in_filter": 0, + "in_list_view": 0, + "label": "Depends On", + "length": 255, + "no_copy": 0, + "oldfieldname": "depends_on", + "oldfieldtype": "Data", + "permlevel": 0, + "print_hide": 0, + "read_only": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, "unique": 0 - }, + }, { - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "fieldname": "hidden", - "fieldtype": "Check", - "hidden": 0, - "ignore_user_permissions": 0, - "in_filter": 0, - "in_list_view": 0, - "label": "Hidden", - "no_copy": 0, - "oldfieldname": "hidden", - "oldfieldtype": "Check", - "permlevel": 0, - "print_hide": 0, - "print_width": "50px", - "read_only": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "unique": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "fieldname": "hidden", + "fieldtype": "Check", + "hidden": 0, + "ignore_user_permissions": 0, + "in_filter": 0, + "in_list_view": 0, + "label": "Hidden", + "no_copy": 0, + "oldfieldname": "hidden", + "oldfieldtype": "Check", + "permlevel": 0, + "print_hide": 0, + "print_width": "50px", + "read_only": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "unique": 0, "width": "50px" - }, + }, { - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "fieldname": "read_only", - "fieldtype": "Check", - "hidden": 0, - "ignore_user_permissions": 0, - "in_filter": 0, - "in_list_view": 0, - "label": "Read Only", - "no_copy": 0, - "permlevel": 0, - "print_hide": 0, - "print_width": "50px", - "read_only": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "unique": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "fieldname": "read_only", + "fieldtype": "Check", + "hidden": 0, + "ignore_user_permissions": 0, + "in_filter": 0, + "in_list_view": 0, + "label": "Read Only", + "no_copy": 0, + "permlevel": 0, + "print_hide": 0, + "print_width": "50px", + "read_only": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "unique": 0, "width": "50px" - }, + }, { - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "fieldname": "unique", - "fieldtype": "Check", - "hidden": 0, - "ignore_user_permissions": 0, - "in_filter": 0, - "in_list_view": 0, - "label": "Unique", - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "read_only": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "fieldname": "unique", + "fieldtype": "Check", + "hidden": 0, + "ignore_user_permissions": 0, + "in_filter": 0, + "in_list_view": 0, + "label": "Unique", + "no_copy": 0, + "permlevel": 0, + "precision": "", + "print_hide": 0, + "read_only": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, "unique": 0 - }, + }, { - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "description": "Do not allow user to change after set the first time", - "fieldname": "set_only_once", - "fieldtype": "Check", - "hidden": 0, - "ignore_user_permissions": 0, - "in_filter": 0, - "in_list_view": 0, - "label": "Set Only Once", - "no_copy": 0, - "permlevel": 0, - "print_hide": 0, - "read_only": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "description": "Do not allow user to change after set the first time", + "fieldname": "set_only_once", + "fieldtype": "Check", + "hidden": 0, + "ignore_user_permissions": 0, + "in_filter": 0, + "in_list_view": 0, + "label": "Set Only Once", + "no_copy": 0, + "permlevel": 0, + "print_hide": 0, + "read_only": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, "unique": 0 - }, + }, { - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "fieldname": "column_break_13", - "fieldtype": "Column Break", - "hidden": 0, - "ignore_user_permissions": 0, - "in_filter": 0, - "in_list_view": 0, - "no_copy": 0, - "permlevel": 0, - "print_hide": 0, - "read_only": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "fieldname": "column_break_13", + "fieldtype": "Column Break", + "hidden": 0, + "ignore_user_permissions": 0, + "in_filter": 0, + "in_list_view": 0, + "no_copy": 0, + "permlevel": 0, + "print_hide": 0, + "read_only": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, "unique": 0 - }, + }, { - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "default": "0", - "fieldname": "permlevel", - "fieldtype": "Int", - "hidden": 0, - "ignore_user_permissions": 0, - "in_filter": 0, - "in_list_view": 0, - "label": "Perm Level", - "no_copy": 0, - "oldfieldname": "permlevel", - "oldfieldtype": "Int", - "permlevel": 0, - "print_hide": 0, - "print_width": "50px", - "read_only": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "unique": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "default": "0", + "fieldname": "permlevel", + "fieldtype": "Int", + "hidden": 0, + "ignore_user_permissions": 0, + "in_filter": 0, + "in_list_view": 0, + "label": "Perm Level", + "no_copy": 0, + "oldfieldname": "permlevel", + "oldfieldtype": "Int", + "permlevel": 0, + "print_hide": 0, + "print_width": "50px", + "read_only": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "unique": 0, "width": "50px" - }, + }, { - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "description": "User permissions should not apply for this Link", - "fieldname": "ignore_user_permissions", - "fieldtype": "Check", - "hidden": 0, - "ignore_user_permissions": 0, - "in_filter": 0, - "in_list_view": 0, - "label": "Ignore User Permissions", - "no_copy": 0, - "permlevel": 0, - "print_hide": 0, - "read_only": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "description": "User permissions should not apply for this Link", + "fieldname": "ignore_user_permissions", + "fieldtype": "Check", + "hidden": 0, + "ignore_user_permissions": 0, + "in_filter": 0, + "in_list_view": 0, + "label": "Ignore User Permissions", + "no_copy": 0, + "permlevel": 0, + "print_hide": 0, + "read_only": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, "unique": 0 - }, + }, { - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "fieldname": "allow_on_submit", - "fieldtype": "Check", - "hidden": 0, - "ignore_user_permissions": 0, - "in_filter": 0, - "in_list_view": 0, - "label": "Allow on Submit", - "no_copy": 0, - "oldfieldname": "allow_on_submit", - "oldfieldtype": "Check", - "permlevel": 0, - "print_hide": 0, - "print_width": "50px", - "read_only": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "unique": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "fieldname": "allow_on_submit", + "fieldtype": "Check", + "hidden": 0, + "ignore_user_permissions": 0, + "in_filter": 0, + "in_list_view": 0, + "label": "Allow on Submit", + "no_copy": 0, + "oldfieldname": "allow_on_submit", + "oldfieldtype": "Check", + "permlevel": 0, + "print_hide": 0, + "print_width": "50px", + "read_only": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "unique": 0, "width": "50px" - }, + }, { - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "fieldname": "report_hide", - "fieldtype": "Check", - "hidden": 0, - "ignore_user_permissions": 0, - "in_filter": 0, - "in_list_view": 0, - "label": "Report Hide", - "no_copy": 0, - "oldfieldname": "report_hide", - "oldfieldtype": "Check", - "permlevel": 0, - "print_hide": 0, - "print_width": "50px", - "read_only": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "unique": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "fieldname": "report_hide", + "fieldtype": "Check", + "hidden": 0, + "ignore_user_permissions": 0, + "in_filter": 0, + "in_list_view": 0, + "label": "Report Hide", + "no_copy": 0, + "oldfieldname": "report_hide", + "oldfieldtype": "Check", + "permlevel": 0, + "print_hide": 0, + "print_width": "50px", + "read_only": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "unique": 0, "width": "50px" - }, + }, { - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "fieldname": "display", - "fieldtype": "Section Break", - "hidden": 0, - "ignore_user_permissions": 0, - "in_filter": 0, - "in_list_view": 0, - "label": "Display", - "no_copy": 0, - "permlevel": 0, - "print_hide": 0, - "read_only": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "fieldname": "display", + "fieldtype": "Section Break", + "hidden": 0, + "ignore_user_permissions": 0, + "in_filter": 0, + "in_list_view": 0, + "label": "Display", + "no_copy": 0, + "permlevel": 0, + "print_hide": 0, + "read_only": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, "unique": 0 - }, + }, { - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "fieldname": "in_filter", - "fieldtype": "Check", - "hidden": 0, - "ignore_user_permissions": 0, - "in_filter": 0, - "in_list_view": 0, - "label": "In Filter", - "no_copy": 0, - "oldfieldname": "in_filter", - "oldfieldtype": "Check", - "permlevel": 0, - "print_hide": 0, - "print_width": "50px", - "read_only": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "unique": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "fieldname": "in_filter", + "fieldtype": "Check", + "hidden": 0, + "ignore_user_permissions": 0, + "in_filter": 0, + "in_list_view": 0, + "label": "In Filter", + "no_copy": 0, + "oldfieldname": "in_filter", + "oldfieldtype": "Check", + "permlevel": 0, + "print_hide": 0, + "print_width": "50px", + "read_only": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "unique": 0, "width": "50px" - }, + }, { - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "fieldname": "no_copy", - "fieldtype": "Check", - "hidden": 0, - "ignore_user_permissions": 0, - "in_filter": 0, - "in_list_view": 0, - "label": "No Copy", - "no_copy": 0, - "oldfieldname": "no_copy", - "oldfieldtype": "Check", - "permlevel": 0, - "print_hide": 0, - "print_width": "50px", - "read_only": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "unique": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "fieldname": "no_copy", + "fieldtype": "Check", + "hidden": 0, + "ignore_user_permissions": 0, + "in_filter": 0, + "in_list_view": 0, + "label": "No Copy", + "no_copy": 0, + "oldfieldname": "no_copy", + "oldfieldtype": "Check", + "permlevel": 0, + "print_hide": 0, + "print_width": "50px", + "read_only": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "unique": 0, "width": "50px" - }, + }, { - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "fieldname": "print_hide", - "fieldtype": "Check", - "hidden": 0, - "ignore_user_permissions": 0, - "in_filter": 0, - "in_list_view": 0, - "label": "Print Hide", - "no_copy": 0, - "oldfieldname": "print_hide", - "oldfieldtype": "Check", - "permlevel": 0, - "print_hide": 0, - "print_width": "50px", - "read_only": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "unique": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "fieldname": "print_hide", + "fieldtype": "Check", + "hidden": 0, + "ignore_user_permissions": 0, + "in_filter": 0, + "in_list_view": 0, + "label": "Print Hide", + "no_copy": 0, + "oldfieldname": "print_hide", + "oldfieldtype": "Check", + "permlevel": 0, + "print_hide": 0, + "print_width": "50px", + "read_only": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "unique": 0, "width": "50px" - }, + }, { - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "fieldname": "print_width", - "fieldtype": "Data", - "hidden": 0, - "ignore_user_permissions": 0, - "in_filter": 0, - "in_list_view": 0, - "label": "Print Width", - "no_copy": 0, - "permlevel": 0, - "print_hide": 0, - "read_only": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "fieldname": "print_width", + "fieldtype": "Data", + "hidden": 0, + "ignore_user_permissions": 0, + "in_filter": 0, + "in_list_view": 0, + "label": "Print Width", + "no_copy": 0, + "permlevel": 0, + "print_hide": 0, + "read_only": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, "unique": 0 - }, + }, { - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "fieldname": "width", - "fieldtype": "Data", - "hidden": 0, - "ignore_user_permissions": 0, - "in_filter": 0, - "in_list_view": 0, - "label": "Width", - "no_copy": 0, - "oldfieldname": "width", - "oldfieldtype": "Data", - "permlevel": 0, - "print_hide": 0, - "print_width": "50px", - "read_only": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "unique": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "fieldname": "width", + "fieldtype": "Data", + "hidden": 0, + "ignore_user_permissions": 0, + "in_filter": 0, + "in_list_view": 0, + "label": "Width", + "no_copy": 0, + "oldfieldname": "width", + "oldfieldtype": "Data", + "permlevel": 0, + "print_hide": 0, + "print_width": "50px", + "read_only": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "unique": 0, "width": "50px" - }, + }, { - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "fieldname": "column_break_22", - "fieldtype": "Column Break", - "hidden": 0, - "ignore_user_permissions": 0, - "in_filter": 0, - "in_list_view": 0, - "no_copy": 0, - "permlevel": 0, - "print_hide": 0, - "read_only": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "fieldname": "column_break_22", + "fieldtype": "Column Break", + "hidden": 0, + "ignore_user_permissions": 0, + "in_filter": 0, + "in_list_view": 0, + "no_copy": 0, + "permlevel": 0, + "print_hide": 0, + "read_only": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, "unique": 0 - }, + }, { - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "fieldname": "description", - "fieldtype": "Small Text", - "hidden": 0, - "ignore_user_permissions": 0, - "in_filter": 0, - "in_list_view": 1, - "label": "Description", - "no_copy": 0, - "oldfieldname": "description", - "oldfieldtype": "Text", - "permlevel": 0, - "print_hide": 0, - "print_width": "300px", - "read_only": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "unique": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "fieldname": "description", + "fieldtype": "Small Text", + "hidden": 0, + "ignore_user_permissions": 0, + "in_filter": 0, + "in_list_view": 1, + "label": "Description", + "no_copy": 0, + "oldfieldname": "description", + "oldfieldtype": "Text", + "permlevel": 0, + "print_hide": 0, + "print_width": "300px", + "read_only": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "unique": 0, "width": "300px" - }, + }, { - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "fieldname": "oldfieldname", - "fieldtype": "Data", - "hidden": 1, - "ignore_user_permissions": 0, - "in_filter": 0, - "in_list_view": 0, - "no_copy": 0, - "oldfieldname": "oldfieldname", - "oldfieldtype": "Data", - "permlevel": 0, - "print_hide": 0, - "read_only": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "fieldname": "oldfieldname", + "fieldtype": "Data", + "hidden": 1, + "ignore_user_permissions": 0, + "in_filter": 0, + "in_list_view": 0, + "no_copy": 0, + "oldfieldname": "oldfieldname", + "oldfieldtype": "Data", + "permlevel": 0, + "print_hide": 0, + "read_only": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, "unique": 0 - }, + }, { - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "fieldname": "oldfieldtype", - "fieldtype": "Data", - "hidden": 1, - "ignore_user_permissions": 0, - "in_filter": 0, - "in_list_view": 0, - "no_copy": 0, - "oldfieldname": "oldfieldtype", - "oldfieldtype": "Data", - "permlevel": 0, - "print_hide": 0, - "read_only": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "fieldname": "oldfieldtype", + "fieldtype": "Data", + "hidden": 1, + "ignore_user_permissions": 0, + "in_filter": 0, + "in_list_view": 0, + "no_copy": 0, + "oldfieldname": "oldfieldtype", + "oldfieldtype": "Data", + "permlevel": 0, + "print_hide": 0, + "read_only": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, "unique": 0 } - ], - "hide_heading": 0, - "hide_toolbar": 0, - "idx": 1, - "in_create": 0, - "in_dialog": 1, - "is_submittable": 0, - "issingle": 0, - "istable": 1, - "modified": "2015-08-20 16:05:15.274200", - "modified_by": "Administrator", - "module": "Core", - "name": "DocField", - "owner": "Administrator", - "permissions": [], - "read_only": 0, + ], + "hide_heading": 0, + "hide_toolbar": 0, + "idx": 1, + "in_create": 0, + "in_dialog": 1, + "is_submittable": 0, + "issingle": 0, + "istable": 1, + "modified": "2015-10-02 07:38:45.729933", + "modified_by": "Administrator", + "module": "Core", + "name": "DocField", + "owner": "Administrator", + "permissions": [], + "read_only": 0, "read_only_onload": 0 -} \ No newline at end of file +} diff --git a/frappe/core/doctype/docperm/docperm.json b/frappe/core/doctype/docperm/docperm.json index d21abfaaa8..dbb9e4d53c 100644 --- a/frappe/core/doctype/docperm/docperm.json +++ b/frappe/core/doctype/docperm/docperm.json @@ -591,7 +591,7 @@ "is_submittable": 0, "issingle": 0, "istable": 1, - "modified": "2015-07-22 07:39:40.471092", + "modified": "2015-10-02 07:38:46.740536", "modified_by": "Administrator", "module": "Core", "name": "DocPerm", diff --git a/frappe/core/doctype/docshare/docshare.json b/frappe/core/doctype/docshare/docshare.json index 3a7846cce1..f06857213d 100644 --- a/frappe/core/doctype/docshare/docshare.json +++ b/frappe/core/doctype/docshare/docshare.json @@ -178,7 +178,7 @@ "is_submittable": 0, "issingle": 0, "istable": 0, - "modified": "2015-07-17 07:02:10.632582", + "modified": "2015-10-02 07:38:47.029636", "modified_by": "Administrator", "module": "Core", "name": "DocShare", diff --git a/frappe/core/doctype/docshare/docshare.py b/frappe/core/doctype/docshare/docshare.py index 5f2b3ae1bd..bbe31f9e84 100644 --- a/frappe/core/doctype/docshare/docshare.py +++ b/frappe/core/doctype/docshare/docshare.py @@ -7,6 +7,8 @@ from frappe.model.document import Document from frappe import _ from frappe.utils import get_fullname +exclude_from_linked_with = True + class DocShare(Document): no_feed_on_delete = True diff --git a/frappe/core/doctype/doctype/doctype.json b/frappe/core/doctype/doctype/doctype.json index 620e4234d6..dd5e0bc13d 100644 --- a/frappe/core/doctype/doctype/doctype.json +++ b/frappe/core/doctype/doctype/doctype.json @@ -134,7 +134,7 @@ "ignore_user_permissions": 0, "in_filter": 0, "in_list_view": 0, - "label": "Document Type", + "label": "Document Type", "no_copy": 0, "oldfieldname": "document_type", "oldfieldtype": "Select", @@ -312,7 +312,7 @@ "ignore_user_permissions": 0, "in_filter": 0, "in_list_view": 0, - "label": "Name Case", + "label": "Name Case", "no_copy": 0, "oldfieldname": "name_case", "oldfieldtype": "Select", @@ -448,7 +448,7 @@ "ignore_user_permissions": 0, "in_filter": 0, "in_list_view": 0, - "label": "Sort Order", + "label": "Sort Order", "no_copy": 0, "options": "ASC\nDESC", "permlevel": 0, @@ -851,7 +851,7 @@ "is_submittable": 0, "issingle": 0, "istable": 0, - "modified": "2015-07-28 16:18:11.925264", + "modified": "2015-10-02 07:38:47.199387", "modified_by": "Administrator", "module": "Core", "name": "DocType", diff --git a/frappe/core/doctype/doctype/test_doctype.py b/frappe/core/doctype/doctype/test_doctype.py new file mode 100644 index 0000000000..2419f0c7d1 --- /dev/null +++ b/frappe/core/doctype/doctype/test_doctype.py @@ -0,0 +1,12 @@ +# -*- coding: utf-8 -*- +# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors +# See license.txt +from __future__ import unicode_literals + +import frappe +import unittest + +# test_records = frappe.get_test_records('DocType') + +class TestDocType(unittest.TestCase): + pass diff --git a/frappe/core/doctype/file/file.json b/frappe/core/doctype/file/file.json index c9ff215cb9..dbc77702c1 100644 --- a/frappe/core/doctype/file/file.json +++ b/frappe/core/doctype/file/file.json @@ -2,7 +2,7 @@ "allow_copy": 0, "allow_import": 1, "allow_rename": 0, - "autoname": "hash", + "autoname": "", "creation": "2012-12-12 11:19:22", "custom": 0, "docstatus": 0, @@ -189,7 +189,7 @@ "collapsible": 0, "depends_on": "eval:!doc.is_folder", "fieldname": "file_url", - "fieldtype": "Data", + "fieldtype": "Small Text", "hidden": 0, "ignore_user_permissions": 0, "in_filter": 0, @@ -205,6 +205,28 @@ "set_only_once": 0, "unique": 0 }, + { + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "fieldname": "thumbnail_url", + "fieldtype": "Small Text", + "hidden": 0, + "ignore_user_permissions": 0, + "in_filter": 0, + "in_list_view": 0, + "label": "Thumbnail URL", + "no_copy": 0, + "permlevel": 0, + "precision": "", + "print_hide": 0, + "read_only": 1, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "unique": 0 + }, { "allow_on_submit": 0, "bold": 0, @@ -433,7 +455,7 @@ "is_submittable": 0, "issingle": 0, "istable": 0, - "modified": "2015-09-18 06:22:10.902847", + "modified": "2015-10-19 02:13:43.935641", "modified_by": "Administrator", "module": "Core", "name": "File", diff --git a/frappe/core/doctype/file/file.py b/frappe/core/doctype/file/file.py index ccfaa3a0b4..11bf3e1b0e 100644 --- a/frappe/core/doctype/file/file.py +++ b/frappe/core/doctype/file/file.py @@ -13,10 +13,14 @@ from frappe.utils.file_manager import delete_file_data_content from frappe import _ from frappe.utils.nestedset import NestedSet +from frappe.utils import strip import json +import urllib class FolderNotEmpty(frappe.ValidationError): pass +exclude_from_linked_with = True + class File(NestedSet): nsm_parent_field = 'folder' no_feed_on_delete = True @@ -40,7 +44,7 @@ class File(NestedSet): # home self.name = self.file_name else: - self.name = self.file_url + self.name = frappe.generate_hash("", 10) def after_insert(self): self.update_parent_folder_size() @@ -53,7 +57,8 @@ class File(NestedSet): return frappe.db.sql_list("select name from tabFile where folder='%s'"%self.name) or [] def validate(self): - self.validate_duplicate_entry() + if self.is_new(): + self.validate_duplicate_entry() self.validate_folder() self.set_folder_size() @@ -92,6 +97,8 @@ class File(NestedSet): def validate_duplicate_entry(self): if not self.flags.ignore_duplicate_entry_error and not self.is_folder: + # check duplicate name + # check duplicate assignement n_records = frappe.db.sql("""select name from `tabFile` where content_hash=%s @@ -111,12 +118,55 @@ class File(NestedSet): super(File, self).on_trash() self.delete_file() + def make_thumbnail(self): + from PIL import Image, ImageOps + import os + + if self.file_url: + if self.file_url.startswith("/files"): + try: + image = Image.open(frappe.get_site_path("public", self.file_url)) + filename, extn = self.file_url.rsplit(".", 1) + except IOError: + frappe.msgprint("Unable to read file format for {0}".format(self.file_url)) + + else: + # downlaod + import requests, StringIO + file_url = frappe.utils.get_url(self.file_url) + r = requests.get(file_url, stream=True) + r.raise_for_status() + image = Image.open(StringIO.StringIO(r.content)) + filename, extn = self.file_url.rsplit("/", 1)[1].rsplit(".", 1) + filename = "/files/" + strip(urllib.unquote(filename)) + + thumbnail = ImageOps.fit( + image, + (300, 300), + Image.ANTIALIAS + ) + + thumbnail_url = filename + "_small." + extn + + path = os.path.abspath(frappe.get_site_path("public", thumbnail_url.lstrip("/"))) + + try: + thumbnail.save(path) + self.db_set("thumbnail_url", thumbnail_url) + except IOError: + frappe.msgprint("Unable to write file format for {0}".format(path)) + + return thumbnail_url + + def after_delete(self): self.update_parent_folder_size() def check_folder_is_empty(self): """Throw exception if folder is not empty""" - if self.is_folder and frappe.get_all("File", filters={"folder": self.name}): + files = frappe.get_all("File", filters={"folder": self.name}, fields=("name", "file_name")) + + if self.is_folder and files: frappe.throw(_("Folder {0} is not empty").format(self.name), FolderNotEmpty) def check_reference_doc_permission(self): @@ -138,6 +188,9 @@ class File(NestedSet): {"content_hash": self.content_hash, "name": ["!=", self.name]})): delete_file_data_content(self) + elif self.file_url: + delete_file_data_content(self, only_thumbnail=True) + def on_rollback(self): self.on_trash() @@ -178,7 +231,10 @@ def create_new_folder(file_name, folder): @frappe.whitelist() def move_file(file_list, new_parent, old_parent): - for file_obj in json.loads(file_list): + if isinstance(file_list, basestring): + file_list = json.loads(file_list) + + for file_obj in file_list: setup_folder_path(file_obj.get("name"), new_parent) # recalculate sizes diff --git a/frappe/core/doctype/file/test_file.py b/frappe/core/doctype/file/test_file.py index 824ab454fd..a73349d9c3 100644 --- a/frappe/core/doctype/file/test_file.py +++ b/frappe/core/doctype/file/test_file.py @@ -5,37 +5,26 @@ from __future__ import unicode_literals import frappe import unittest -from frappe.utils.file_manager import save_file, get_file, get_files_path +from frappe.utils.file_manager import save_file, get_files_path from frappe import _ from frappe.core.doctype.file.file import move_file -import json # test_records = frappe.get_test_records('File') class TestFile(unittest.TestCase): def setUp(self): self.delete_test_data() self.upload_file() - - def delete_test_data(self): - for file_name in ["folder_copy.txt", "file_copy.txt", "Test Folder 2"]: - file_name = frappe.db.get_value("File", {"file_name": file_name}, "name") - if file_name: - file = frappe.get_doc("File", file_name) - ancestors = file.get_ancestors() - file.delete() - self.delete_ancestors(ancestors) - def delete_ancestors(self, ancestors): - for folder in ancestors: - if folder != "Home": - folder = frappe.get_doc("File", folder) - folder.delete() + def delete_test_data(self): + for f in frappe.db.sql('''select name, file_name from tabFile where + is_home_folder = 0 and is_attachments_folder = 0 order by rgt-lft asc'''): + frappe.delete_doc("File", f[0]) def upload_file(self): self.saved_file = save_file('file_copy.txt', "Testing file copy example.",\ "", "", self.get_folder("Test Folder 1", "Home").name) self.saved_filename = get_files_path(self.saved_file.file_name) - + def get_folder(self, folder_name, parent_folder="Home"): return frappe.get_doc({ "doctype": "File", @@ -46,61 +35,57 @@ class TestFile(unittest.TestCase): def tests_after_upload(self): self.assertEqual(self.saved_file.folder, _("Home/Test Folder 1")) - + folder_size = frappe.db.get_value("File", _("Home/Test Folder 1"), "file_size") saved_file_size = frappe.db.get_value("File", self.saved_file.name, "file_size") - + self.assertEqual(folder_size, saved_file_size) - + def test_file_copy(self): folder = self.get_folder("Test Folder 2", "Home") - - file = frappe.get_doc("File", "/files/file_copy.txt") - - file_dict = [{"name": file.name}] - - move_file(json.dumps(file_dict), folder.name, file.folder) - - file = frappe.get_doc("File", "/files/file_copy.txt") - + + file = frappe.get_doc("File", {"file_name":"file_copy.txt"}) + move_file([{"name": file.name}], folder.name, file.folder) + file = frappe.get_doc("File", {"file_name":"file_copy.txt"}) + self.assertEqual(_("Home/Test Folder 2"), file.folder) self.assertEqual(frappe.db.get_value("File", _("Home/Test Folder 2"), "file_size"), file.file_size) self.assertEqual(frappe.db.get_value("File", _("Home/Test Folder 1"), "file_size"), None) - + def test_folder_copy(self): folder = self.get_folder("Test Folder 2", "Home") folder = self.get_folder("Test Folder 3", "Home/Test Folder 2") - + self.saved_file = save_file('folder_copy.txt', "Testing folder copy example.", "", "", folder.name) - - file_dict = [{"name": folder.name}] - - move_file(json.dumps(file_dict), 'Home/Test Folder 1', folder.folder) - - file = frappe.get_doc("File", "/files/folder_copy.txt") - + + move_file([{"name": folder.name}], 'Home/Test Folder 1', folder.folder) + + file = frappe.get_doc("File", {"file_name":"folder_copy.txt"}) + file_copy_txt = frappe.get_value("File", {"file_name":"file_copy.txt"}) + if file_copy_txt: + frappe.get_doc("File", file_copy_txt).delete() + self.assertEqual(_("Home/Test Folder 1/Test Folder 3"), file.folder) self.assertEqual(frappe.db.get_value("File", _("Home/Test Folder 1"), "file_size"), file.file_size) self.assertEqual(frappe.db.get_value("File", _("Home/Test Folder 2"), "file_size"), None) - + def test_non_parent_folder(self): d = frappe.get_doc({ "doctype": "File", "file_name": _("Test_Folder"), "is_folder": 1 }) - + self.assertRaises(frappe.ValidationError, d.save) - + def test_on_delete(self): - file = frappe.get_doc("File", "/files/file_copy.txt") + file = frappe.get_doc("File", {"file_name":"file_copy.txt"}) file.delete() - + self.assertEqual(frappe.db.get_value("File", _("Home/Test Folder 1"), "file_size"), None) - + folder = self.get_folder("Test Folder 3", "Home/Test Folder 1") self.saved_file = save_file('folder_copy.txt', "Testing folder copy example.", "", "", folder.name) folder = frappe.get_doc("File", "Home/Test Folder 1/Test Folder 3") self.assertRaises(frappe.ValidationError, folder.delete) - \ No newline at end of file diff --git a/frappe/core/doctype/module_def/module_def.json b/frappe/core/doctype/module_def/module_def.json index 464b966280..a74ccc1241 100644 --- a/frappe/core/doctype/module_def/module_def.json +++ b/frappe/core/doctype/module_def/module_def.json @@ -62,7 +62,7 @@ "is_submittable": 0, "issingle": 0, "istable": 0, - "modified": "2015-02-05 05:11:41.388856", + "modified": "2015-10-02 07:38:57.452736", "modified_by": "Administrator", "module": "Core", "name": "Module Def", diff --git a/frappe/core/doctype/module_def/test_module_def.py b/frappe/core/doctype/module_def/test_module_def.py new file mode 100644 index 0000000000..1f9bea4768 --- /dev/null +++ b/frappe/core/doctype/module_def/test_module_def.py @@ -0,0 +1,12 @@ +# -*- coding: utf-8 -*- +# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors +# See license.txt +from __future__ import unicode_literals + +import frappe +import unittest + +# test_records = frappe.get_test_records('Module Def') + +class TestModuleDef(unittest.TestCase): + pass diff --git a/frappe/core/doctype/page/page.json b/frappe/core/doctype/page/page.json index 67aa6e62a4..2156cc1435 100644 --- a/frappe/core/doctype/page/page.json +++ b/frappe/core/doctype/page/page.json @@ -149,7 +149,7 @@ "ignore_user_permissions": 0, "in_filter": 0, "in_list_view": 0, - "label": "Standard", + "label": "Standard", "no_copy": 0, "oldfieldname": "standard", "oldfieldtype": "Select", @@ -217,7 +217,7 @@ "is_submittable": 0, "issingle": 0, "istable": 0, - "modified": "2015-09-11 12:19:55.121822", + "modified": "2015-10-02 07:38:59.403028", "modified_by": "Administrator", "module": "Core", "name": "Page", diff --git a/frappe/core/doctype/page_role/page_role.json b/frappe/core/doctype/page_role/page_role.json index 3e9375deb5..270d0ae2f5 100644 --- a/frappe/core/doctype/page_role/page_role.json +++ b/frappe/core/doctype/page_role/page_role.json @@ -41,7 +41,7 @@ "is_submittable": 0, "issingle": 0, "istable": 1, - "modified": "2015-02-19 01:07:00.897854", + "modified": "2015-10-02 07:38:59.530013", "modified_by": "Administrator", "module": "Core", "name": "Page Role", diff --git a/frappe/core/doctype/patch_log/patch_log.json b/frappe/core/doctype/patch_log/patch_log.json index af0cff107f..9ae4e9f40e 100644 --- a/frappe/core/doctype/patch_log/patch_log.json +++ b/frappe/core/doctype/patch_log/patch_log.json @@ -15,7 +15,7 @@ "bold": 0, "collapsible": 0, "fieldname": "patch", - "fieldtype": "Data", + "fieldtype": "Small Text", "hidden": 0, "ignore_user_permissions": 0, "in_filter": 0, @@ -41,7 +41,7 @@ "is_submittable": 0, "issingle": 0, "istable": 0, - "modified": "2013-12-20 19:24:15", + "modified": "2015-10-02 07:38:59.666628", "modified_by": "Administrator", "module": "Core", "name": "Patch Log", diff --git a/frappe/core/doctype/patch_log/test_patch_log.py b/frappe/core/doctype/patch_log/test_patch_log.py new file mode 100644 index 0000000000..0a7f22a78b --- /dev/null +++ b/frappe/core/doctype/patch_log/test_patch_log.py @@ -0,0 +1,12 @@ +# -*- coding: utf-8 -*- +# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors +# See license.txt +from __future__ import unicode_literals + +import frappe +import unittest + +# test_records = frappe.get_test_records('Patch Log') + +class TestPatchLog(unittest.TestCase): + pass diff --git a/frappe/core/doctype/report/report.json b/frappe/core/doctype/report/report.json index 562cdba6e4..8bd82b6047 100644 --- a/frappe/core/doctype/report/report.json +++ b/frappe/core/doctype/report/report.json @@ -62,7 +62,7 @@ "ignore_user_permissions": 0, "in_filter": 0, "in_list_view": 1, - "label": "Is Standard", + "label": "Is Standard", "no_copy": 0, "options": "No\nYes", "permlevel": 0, @@ -147,7 +147,7 @@ "ignore_user_permissions": 0, "in_filter": 0, "in_list_view": 0, - "label": "Report Type", + "label": "Report Type", "no_copy": 0, "options": "Report Builder\nQuery Report\nScript Report", "permlevel": 0, @@ -300,7 +300,7 @@ "is_submittable": 0, "issingle": 0, "istable": 0, - "modified": "2015-09-07 15:51:26", + "modified": "2015-10-02 07:39:07.933259", "modified_by": "Administrator", "module": "Core", "name": "Report", diff --git a/frappe/core/doctype/role/role.json b/frappe/core/doctype/role/role.json index fb4b299077..bc14d18aa1 100644 --- a/frappe/core/doctype/role/role.json +++ b/frappe/core/doctype/role/role.json @@ -41,7 +41,7 @@ "is_submittable": 0, "issingle": 0, "istable": 0, - "modified": "2015-09-07 15:51:26", + "modified": "2015-10-02 07:39:08.074305", "modified_by": "Administrator", "module": "Core", "name": "Role", diff --git a/frappe/core/doctype/role/role.py b/frappe/core/doctype/role/role.py index 8401328169..da156d137c 100644 --- a/frappe/core/doctype/role/role.py +++ b/frappe/core/doctype/role/role.py @@ -10,4 +10,6 @@ class Role(Document): def after_insert(self): # Add role to Administrator if frappe.flags.in_install != "frappe": - frappe.get_doc("User", "Administrator").add_roles(self.name) + user = frappe.get_doc("User", "Administrator") + user.flags.ignore_permissions = True + user.add_roles(self.name) diff --git a/frappe/core/doctype/scheduler_log/scheduler_log.json b/frappe/core/doctype/scheduler_log/scheduler_log.json index 3056d93b9e..86a900ba37 100644 --- a/frappe/core/doctype/scheduler_log/scheduler_log.json +++ b/frappe/core/doctype/scheduler_log/scheduler_log.json @@ -85,7 +85,7 @@ "is_submittable": 0, "issingle": 0, "istable": 0, - "modified": "2015-05-28 02:49:12.819934", + "modified": "2015-10-02 07:39:12.348067", "modified_by": "Administrator", "module": "Core", "name": "Scheduler Log", diff --git a/frappe/core/doctype/user/user.json b/frappe/core/doctype/user/user.json index 1e631b288b..7436fa5397 100644 --- a/frappe/core/doctype/user/user.json +++ b/frappe/core/doctype/user/user.json @@ -1263,7 +1263,7 @@ "issingle": 0, "istable": 0, "max_attachments": 5, - "modified": "2015-08-18 11:58:00.000691", + "modified": "2015-10-19 03:04:48.829054", "modified_by": "Administrator", "module": "Core", "name": "User", diff --git a/frappe/core/doctype/userrole/userrole.json b/frappe/core/doctype/userrole/userrole.json index f7d0442721..1bf512f135 100644 --- a/frappe/core/doctype/userrole/userrole.json +++ b/frappe/core/doctype/userrole/userrole.json @@ -43,7 +43,7 @@ "is_submittable": 0, "issingle": 0, "istable": 1, - "modified": "2015-02-19 01:07:02.561834", + "modified": "2015-10-02 07:39:18.179539", "modified_by": "Administrator", "module": "Core", "name": "UserRole", diff --git a/frappe/core/doctype/version/version.json b/frappe/core/doctype/version/version.json index d4df6c8d2c..608c4db77b 100644 --- a/frappe/core/doctype/version/version.json +++ b/frappe/core/doctype/version/version.json @@ -83,7 +83,7 @@ "is_submittable": 0, "issingle": 0, "istable": 0, - "modified": "2015-07-28 16:18:12.706419", + "modified": "2015-10-02 07:39:18.235343", "modified_by": "Administrator", "module": "Core", "name": "Version", diff --git a/frappe/custom/doctype/custom_field/custom_field.json b/frappe/custom/doctype/custom_field/custom_field.json index 1e0ac687d1..a08ef06568 100644 --- a/frappe/custom/doctype/custom_field/custom_field.json +++ b/frappe/custom/doctype/custom_field/custom_field.json @@ -1,709 +1,710 @@ { - "allow_copy": 0, - "allow_import": 1, - "allow_rename": 0, - "creation": "2013-01-10 16:34:01", - "custom": 0, - "description": "Adds a custom field to a DocType", - "docstatus": 0, - "doctype": "DocType", + "allow_copy": 0, + "allow_import": 1, + "allow_rename": 0, + "creation": "2013-01-10 16:34:01", + "custom": 0, + "description": "Adds a custom field to a DocType", + "docstatus": 0, + "doctype": "DocType", "fields": [ { - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "fieldname": "dt", - "fieldtype": "Link", - "hidden": 0, - "ignore_user_permissions": 0, - "in_filter": 1, - "in_list_view": 1, - "label": "Document", - "no_copy": 0, - "oldfieldname": "dt", - "oldfieldtype": "Link", - "options": "DocType", - "permlevel": 0, - "print_hide": 0, - "read_only": 0, - "report_hide": 0, - "reqd": 1, - "search_index": 1, - "set_only_once": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "fieldname": "dt", + "fieldtype": "Link", + "hidden": 0, + "ignore_user_permissions": 0, + "in_filter": 1, + "in_list_view": 1, + "label": "Document", + "no_copy": 0, + "oldfieldname": "dt", + "oldfieldtype": "Link", + "options": "DocType", + "permlevel": 0, + "print_hide": 0, + "read_only": 0, + "report_hide": 0, + "reqd": 1, + "search_index": 1, + "set_only_once": 0, "unique": 0 - }, + }, { - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "fieldname": "label", - "fieldtype": "Data", - "hidden": 0, - "ignore_user_permissions": 0, - "in_filter": 1, - "in_list_view": 0, - "label": "Label", - "no_copy": 1, - "oldfieldname": "label", - "oldfieldtype": "Data", - "permlevel": 0, - "print_hide": 0, - "read_only": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "fieldname": "label", + "fieldtype": "Data", + "hidden": 0, + "ignore_user_permissions": 0, + "in_filter": 1, + "in_list_view": 0, + "label": "Label", + "no_copy": 1, + "oldfieldname": "label", + "oldfieldtype": "Data", + "permlevel": 0, + "print_hide": 0, + "read_only": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, "unique": 0 - }, + }, { - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "fieldname": "label_help", - "fieldtype": "HTML", - "hidden": 0, - "ignore_user_permissions": 0, - "in_filter": 0, - "in_list_view": 0, - "label": "Label Help", - "no_copy": 0, - "oldfieldtype": "HTML", - "permlevel": 0, - "print_hide": 0, - "read_only": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "fieldname": "label_help", + "fieldtype": "HTML", + "hidden": 0, + "ignore_user_permissions": 0, + "in_filter": 0, + "in_list_view": 0, + "label": "Label Help", + "no_copy": 0, + "oldfieldtype": "HTML", + "permlevel": 0, + "print_hide": 0, + "read_only": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, "unique": 0 - }, + }, { - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "description": "Select the label after which you want to insert new field.", - "fieldname": "insert_after", - "fieldtype": "Select", - "hidden": 0, - "ignore_user_permissions": 0, - "in_filter": 0, - "in_list_view": 0, - "label": "Insert After", - "no_copy": 1, - "oldfieldname": "insert_after", - "oldfieldtype": "Select", - "permlevel": 0, - "print_hide": 0, - "read_only": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "description": "Select the label after which you want to insert new field.", + "fieldname": "insert_after", + "fieldtype": "Select", + "hidden": 0, + "ignore_user_permissions": 0, + "in_filter": 0, + "in_list_view": 0, + "label": "Insert After", + "no_copy": 1, + "oldfieldname": "insert_after", + "oldfieldtype": "Select", + "permlevel": 0, + "print_hide": 0, + "read_only": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, "unique": 0 - }, + }, { - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "default": "Data", - "fieldname": "fieldtype", - "fieldtype": "Select", - "hidden": 0, - "ignore_user_permissions": 0, - "in_filter": 1, - "in_list_view": 1, - "label": "Field Type", - "no_copy": 0, - "oldfieldname": "fieldtype", - "oldfieldtype": "Select", - "options": "Attach\nButton\nCheck\nCode\nColumn Break\nCurrency\nData\nDate\nDatetime\nDynamic Link\nFloat\nHTML\nImage\nInt\nLink\nLong Text\nPassword\nPercent\nRead Only\nSection Break\nSelect\nSmall Text\nTable\nText\nText Editor\nTime", - "permlevel": 0, - "print_hide": 0, - "read_only": 0, - "report_hide": 0, - "reqd": 1, - "search_index": 0, - "set_only_once": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "default": "Data", + "fieldname": "fieldtype", + "fieldtype": "Select", + "hidden": 0, + "ignore_user_permissions": 0, + "in_filter": 1, + "in_list_view": 1, + "label": "Field Type", + "no_copy": 0, + "oldfieldname": "fieldtype", + "oldfieldtype": "Select", + "options": "Attach\nButton\nCheck\nCode\nColumn Break\nCurrency\nData\nDate\nDatetime\nDynamic Link\nFloat\nHTML\nImage\nInt\nLink\nLong Text\nPassword\nPercent\nRead Only\nSection Break\nSelect\nSmall Text\nTable\nText\nText Editor\nTime", + "permlevel": 0, + "print_hide": 0, + "read_only": 0, + "report_hide": 0, + "reqd": 1, + "search_index": 0, + "set_only_once": 0, "unique": 0 - }, + }, { - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "depends_on": "eval:in_list([\"Float\", \"Currency\", \"Percent\"], doc.fieldtype)", - "description": "Set non-standard precision for a Float or Currency field", - "fieldname": "precision", - "fieldtype": "Select", - "hidden": 0, - "ignore_user_permissions": 0, - "in_filter": 0, - "in_list_view": 0, - "label": "Precision", - "no_copy": 0, - "options": "\n1\n2\n3\n4\n5\n6\n7\n8\n9", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "read_only": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "depends_on": "eval:in_list([\"Float\", \"Currency\", \"Percent\"], doc.fieldtype)", + "description": "Set non-standard precision for a Float or Currency field", + "fieldname": "precision", + "fieldtype": "Select", + "hidden": 0, + "ignore_user_permissions": 0, + "in_filter": 0, + "in_list_view": 0, + "label": "Precision", + "no_copy": 0, + "options": "\n1\n2\n3\n4\n5\n6\n7\n8\n9", + "permlevel": 0, + "precision": "", + "print_hide": 0, + "read_only": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, "unique": 0 - }, + }, { - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "fieldname": "options_help", - "fieldtype": "HTML", - "hidden": 0, - "ignore_user_permissions": 0, - "in_filter": 0, - "in_list_view": 0, - "label": "Options Help", - "no_copy": 0, - "oldfieldtype": "HTML", - "permlevel": 0, - "print_hide": 0, - "read_only": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "fieldname": "options_help", + "fieldtype": "HTML", + "hidden": 0, + "ignore_user_permissions": 0, + "in_filter": 0, + "in_list_view": 0, + "label": "Options Help", + "no_copy": 0, + "oldfieldtype": "HTML", + "permlevel": 0, + "print_hide": 0, + "read_only": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, "unique": 0 - }, + }, { - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "fieldname": "options", - "fieldtype": "Text", - "hidden": 0, - "ignore_user_permissions": 0, - "in_filter": 0, - "in_list_view": 1, - "label": "Options", - "no_copy": 0, - "oldfieldname": "options", - "oldfieldtype": "Text", - "permlevel": 0, - "print_hide": 0, - "read_only": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "fieldname": "options", + "fieldtype": "Text", + "hidden": 0, + "ignore_user_permissions": 0, + "in_filter": 0, + "in_list_view": 1, + "label": "Options", + "no_copy": 0, + "oldfieldname": "options", + "oldfieldtype": "Text", + "permlevel": 0, + "print_hide": 0, + "read_only": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, "unique": 0 - }, + }, { - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "fieldname": "description", - "fieldtype": "Text", - "hidden": 0, - "ignore_user_permissions": 0, - "in_filter": 0, - "in_list_view": 0, - "label": "Field Description", - "no_copy": 0, - "oldfieldname": "description", - "oldfieldtype": "Text", - "permlevel": 0, - "print_hide": 0, - "print_width": "300px", - "read_only": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "unique": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "fieldname": "description", + "fieldtype": "Text", + "hidden": 0, + "ignore_user_permissions": 0, + "in_filter": 0, + "in_list_view": 0, + "label": "Field Description", + "no_copy": 0, + "oldfieldname": "description", + "oldfieldtype": "Text", + "permlevel": 0, + "print_hide": 0, + "print_width": "300px", + "read_only": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "unique": 0, "width": "300px" - }, + }, { - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "fieldname": "fieldname", - "fieldtype": "Data", - "hidden": 0, - "ignore_user_permissions": 0, - "in_filter": 0, - "in_list_view": 1, - "label": "Fieldname", - "no_copy": 1, - "oldfieldname": "fieldname", - "oldfieldtype": "Data", - "permlevel": 0, - "print_hide": 0, - "read_only": 1, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "fieldname": "fieldname", + "fieldtype": "Data", + "hidden": 0, + "ignore_user_permissions": 0, + "in_filter": 0, + "in_list_view": 1, + "label": "Fieldname", + "no_copy": 1, + "oldfieldname": "fieldname", + "oldfieldtype": "Data", + "permlevel": 0, + "print_hide": 0, + "read_only": 1, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, "unique": 0 - }, + }, { - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "fieldname": "properties", - "fieldtype": "Column Break", - "hidden": 0, - "ignore_user_permissions": 0, - "in_filter": 0, - "in_list_view": 0, - "label": "Properties", - "no_copy": 0, - "oldfieldtype": "Column Break", - "permlevel": 0, - "print_hide": 0, - "print_width": "50%", - "read_only": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "unique": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "fieldname": "properties", + "fieldtype": "Column Break", + "hidden": 0, + "ignore_user_permissions": 0, + "in_filter": 0, + "in_list_view": 0, + "label": "Properties", + "no_copy": 0, + "oldfieldtype": "Column Break", + "permlevel": 0, + "print_hide": 0, + "print_width": "50%", + "read_only": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "unique": 0, "width": "50%" - }, + }, { - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "default": "0", - "fieldname": "permlevel", - "fieldtype": "Int", - "hidden": 0, - "ignore_user_permissions": 0, - "in_filter": 0, - "in_list_view": 0, - "label": "Permission Level", - "no_copy": 0, - "oldfieldname": "permlevel", - "oldfieldtype": "Int", - "permlevel": 0, - "print_hide": 0, - "read_only": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "default": "0", + "fieldname": "permlevel", + "fieldtype": "Int", + "hidden": 0, + "ignore_user_permissions": 0, + "in_filter": 0, + "in_list_view": 0, + "label": "Permission Level", + "no_copy": 0, + "oldfieldname": "permlevel", + "oldfieldtype": "Int", + "permlevel": 0, + "print_hide": 0, + "read_only": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, "unique": 0 - }, + }, { - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "fieldname": "reqd", - "fieldtype": "Check", - "hidden": 0, - "ignore_user_permissions": 0, - "in_filter": 0, - "in_list_view": 1, - "label": "Is Mandatory Field", - "no_copy": 0, - "oldfieldname": "reqd", - "oldfieldtype": "Check", - "permlevel": 0, - "print_hide": 0, - "read_only": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "fieldname": "reqd", + "fieldtype": "Check", + "hidden": 0, + "ignore_user_permissions": 0, + "in_filter": 0, + "in_list_view": 1, + "label": "Is Mandatory Field", + "no_copy": 0, + "oldfieldname": "reqd", + "oldfieldtype": "Check", + "permlevel": 0, + "print_hide": 0, + "read_only": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, "unique": 0 - }, + }, { - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "fieldname": "unique", - "fieldtype": "Check", - "hidden": 0, - "ignore_user_permissions": 0, - "in_filter": 0, - "in_list_view": 0, - "label": "Unique", - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "read_only": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "fieldname": "unique", + "fieldtype": "Check", + "hidden": 0, + "ignore_user_permissions": 0, + "in_filter": 0, + "in_list_view": 0, + "label": "Unique", + "no_copy": 0, + "permlevel": 0, + "precision": "", + "print_hide": 0, + "read_only": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, "unique": 0 - }, + }, { - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "fieldname": "read_only", - "fieldtype": "Check", - "hidden": 0, - "ignore_user_permissions": 0, - "in_filter": 0, - "in_list_view": 0, - "label": "Read Only", - "no_copy": 0, - "permlevel": 0, - "print_hide": 0, - "read_only": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "fieldname": "read_only", + "fieldtype": "Check", + "hidden": 0, + "ignore_user_permissions": 0, + "in_filter": 0, + "in_list_view": 0, + "label": "Read Only", + "no_copy": 0, + "permlevel": 0, + "print_hide": 0, + "read_only": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, "unique": 0 - }, + }, { - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "depends_on": "eval:doc.fieldtype===\"Link\"", - "fieldname": "ignore_user_permissions", - "fieldtype": "Check", - "hidden": 0, - "ignore_user_permissions": 0, - "in_filter": 0, - "in_list_view": 0, - "label": "Ignore User Permissions", - "no_copy": 0, - "permlevel": 0, - "print_hide": 0, - "read_only": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "depends_on": "eval:doc.fieldtype===\"Link\"", + "fieldname": "ignore_user_permissions", + "fieldtype": "Check", + "hidden": 0, + "ignore_user_permissions": 0, + "in_filter": 0, + "in_list_view": 0, + "label": "Ignore User Permissions", + "no_copy": 0, + "permlevel": 0, + "print_hide": 0, + "read_only": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, "unique": 0 - }, + }, { - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "fieldname": "width", - "fieldtype": "Data", - "hidden": 0, - "ignore_user_permissions": 0, - "in_filter": 0, - "in_list_view": 0, - "label": "Width", - "no_copy": 0, - "oldfieldname": "width", - "oldfieldtype": "Data", - "permlevel": 0, - "print_hide": 0, - "read_only": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "fieldname": "width", + "fieldtype": "Data", + "hidden": 0, + "ignore_user_permissions": 0, + "in_filter": 0, + "in_list_view": 0, + "label": "Width", + "no_copy": 0, + "oldfieldname": "width", + "oldfieldtype": "Data", + "permlevel": 0, + "print_hide": 0, + "read_only": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, "unique": 0 - }, + }, { - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "fieldname": "default", - "fieldtype": "Text", - "hidden": 0, - "ignore_user_permissions": 0, - "in_filter": 0, - "in_list_view": 0, - "label": "Default Value", - "no_copy": 0, - "oldfieldname": "default", - "oldfieldtype": "Text", - "permlevel": 0, - "print_hide": 0, - "read_only": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "fieldname": "default", + "fieldtype": "Text", + "hidden": 0, + "ignore_user_permissions": 0, + "in_filter": 0, + "in_list_view": 0, + "label": "Default Value", + "no_copy": 0, + "oldfieldname": "default", + "oldfieldtype": "Text", + "permlevel": 0, + "print_hide": 0, + "read_only": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, "unique": 0 - }, + }, { - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "fieldname": "hidden", - "fieldtype": "Check", - "hidden": 0, - "ignore_user_permissions": 0, - "in_filter": 0, - "in_list_view": 0, - "label": "Hidden", - "no_copy": 0, - "permlevel": 0, - "print_hide": 0, - "read_only": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "fieldname": "hidden", + "fieldtype": "Check", + "hidden": 0, + "ignore_user_permissions": 0, + "in_filter": 0, + "in_list_view": 0, + "label": "Hidden", + "no_copy": 0, + "permlevel": 0, + "print_hide": 0, + "read_only": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, "unique": 0 - }, + }, { - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "fieldname": "depends_on", - "fieldtype": "Data", - "hidden": 0, - "ignore_user_permissions": 0, - "in_filter": 0, - "in_list_view": 0, - "label": "Depends On", - "no_copy": 0, - "permlevel": 0, - "print_hide": 0, - "read_only": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "fieldname": "depends_on", + "fieldtype": "Small Text", + "hidden": 0, + "ignore_user_permissions": 0, + "in_filter": 0, + "in_list_view": 0, + "label": "Depends On", + "length": 255, + "no_copy": 0, + "permlevel": 0, + "print_hide": 0, + "read_only": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, "unique": 0 - }, + }, { - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "fieldname": "print_hide", - "fieldtype": "Check", - "hidden": 0, - "ignore_user_permissions": 0, - "in_filter": 0, - "in_list_view": 0, - "label": "Print Hide", - "no_copy": 0, - "oldfieldname": "print_hide", - "oldfieldtype": "Check", - "permlevel": 0, - "print_hide": 0, - "read_only": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "fieldname": "print_hide", + "fieldtype": "Check", + "hidden": 0, + "ignore_user_permissions": 0, + "in_filter": 0, + "in_list_view": 0, + "label": "Print Hide", + "no_copy": 0, + "oldfieldname": "print_hide", + "oldfieldtype": "Check", + "permlevel": 0, + "print_hide": 0, + "read_only": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, "unique": 0 - }, + }, { - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "fieldname": "print_width", - "fieldtype": "Data", - "hidden": 1, - "ignore_user_permissions": 0, - "in_filter": 0, - "in_list_view": 0, - "label": "Print Width", - "no_copy": 1, - "permlevel": 0, - "print_hide": 1, - "read_only": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "fieldname": "print_width", + "fieldtype": "Data", + "hidden": 1, + "ignore_user_permissions": 0, + "in_filter": 0, + "in_list_view": 0, + "label": "Print Width", + "no_copy": 1, + "permlevel": 0, + "print_hide": 1, + "read_only": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, "unique": 0 - }, + }, { - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "fieldname": "no_copy", - "fieldtype": "Check", - "hidden": 0, - "ignore_user_permissions": 0, - "in_filter": 0, - "in_list_view": 0, - "label": "No Copy", - "no_copy": 0, - "oldfieldname": "no_copy", - "oldfieldtype": "Check", - "permlevel": 0, - "print_hide": 0, - "read_only": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "fieldname": "no_copy", + "fieldtype": "Check", + "hidden": 0, + "ignore_user_permissions": 0, + "in_filter": 0, + "in_list_view": 0, + "label": "No Copy", + "no_copy": 0, + "oldfieldname": "no_copy", + "oldfieldtype": "Check", + "permlevel": 0, + "print_hide": 0, + "read_only": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, "unique": 0 - }, + }, { - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "fieldname": "allow_on_submit", - "fieldtype": "Check", - "hidden": 0, - "ignore_user_permissions": 0, - "in_filter": 0, - "in_list_view": 0, - "label": "Allow on Submit", - "no_copy": 0, - "oldfieldname": "allow_on_submit", - "oldfieldtype": "Check", - "permlevel": 0, - "print_hide": 0, - "read_only": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "fieldname": "allow_on_submit", + "fieldtype": "Check", + "hidden": 0, + "ignore_user_permissions": 0, + "in_filter": 0, + "in_list_view": 0, + "label": "Allow on Submit", + "no_copy": 0, + "oldfieldname": "allow_on_submit", + "oldfieldtype": "Check", + "permlevel": 0, + "print_hide": 0, + "read_only": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, "unique": 0 - }, + }, { - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "fieldname": "in_filter", - "fieldtype": "Check", - "hidden": 0, - "ignore_user_permissions": 0, - "in_filter": 0, - "in_list_view": 0, - "label": "In Report Filter", - "no_copy": 0, - "oldfieldname": "in_filter", - "oldfieldtype": "Check", - "permlevel": 0, - "print_hide": 0, - "read_only": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "fieldname": "in_filter", + "fieldtype": "Check", + "hidden": 0, + "ignore_user_permissions": 0, + "in_filter": 0, + "in_list_view": 0, + "label": "In Report Filter", + "no_copy": 0, + "oldfieldname": "in_filter", + "oldfieldtype": "Check", + "permlevel": 0, + "print_hide": 0, + "read_only": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, "unique": 0 - }, + }, { - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "fieldname": "in_list_view", - "fieldtype": "Check", - "hidden": 0, - "ignore_user_permissions": 0, - "in_filter": 0, - "in_list_view": 0, - "label": "In List View", - "no_copy": 0, - "permlevel": 0, - "print_hide": 0, - "read_only": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "fieldname": "in_list_view", + "fieldtype": "Check", + "hidden": 0, + "ignore_user_permissions": 0, + "in_filter": 0, + "in_list_view": 0, + "label": "In List View", + "no_copy": 0, + "permlevel": 0, + "print_hide": 0, + "read_only": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, "unique": 0 - }, + }, { - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "fieldname": "report_hide", - "fieldtype": "Check", - "hidden": 0, - "ignore_user_permissions": 0, - "in_filter": 0, - "in_list_view": 0, - "label": "Report Hide", - "no_copy": 0, - "oldfieldname": "report_hide", - "oldfieldtype": "Check", - "permlevel": 0, - "print_hide": 0, - "read_only": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "fieldname": "report_hide", + "fieldtype": "Check", + "hidden": 0, + "ignore_user_permissions": 0, + "in_filter": 0, + "in_list_view": 0, + "label": "Report Hide", + "no_copy": 0, + "oldfieldname": "report_hide", + "oldfieldtype": "Check", + "permlevel": 0, + "print_hide": 0, + "read_only": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, "unique": 0 - }, + }, { - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "fieldname": "search_index", - "fieldtype": "Check", - "hidden": 1, - "ignore_user_permissions": 0, - "in_filter": 0, - "in_list_view": 0, - "label": "Index", - "no_copy": 1, - "permlevel": 0, - "print_hide": 1, - "read_only": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "fieldname": "search_index", + "fieldtype": "Check", + "hidden": 1, + "ignore_user_permissions": 0, + "in_filter": 0, + "in_list_view": 0, + "label": "Index", + "no_copy": 1, + "permlevel": 0, + "print_hide": 1, + "read_only": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, "unique": 0 } - ], - "hide_heading": 0, - "hide_toolbar": 0, - "icon": "icon-glass", - "idx": 1, - "in_create": 0, - "in_dialog": 0, - "is_submittable": 0, - "issingle": 0, - "istable": 0, - "modified": "2015-02-25 03:39:23.573928", - "modified_by": "Administrator", - "module": "Custom", - "name": "Custom Field", - "owner": "Administrator", + ], + "hide_heading": 0, + "hide_toolbar": 0, + "icon": "icon-glass", + "idx": 1, + "in_create": 0, + "in_dialog": 0, + "is_submittable": 0, + "issingle": 0, + "istable": 0, + "modified": "2015-10-02 07:38:43.093031", + "modified_by": "Administrator", + "module": "Custom", + "name": "Custom Field", + "owner": "Administrator", "permissions": [ { - "amend": 0, - "apply_user_permissions": 0, - "cancel": 0, - "create": 1, - "delete": 1, - "email": 1, - "export": 0, - "if_owner": 0, - "import": 0, - "permlevel": 0, - "print": 1, - "read": 1, - "report": 1, - "role": "Administrator", - "set_user_permissions": 0, - "share": 1, - "submit": 0, + "amend": 0, + "apply_user_permissions": 0, + "cancel": 0, + "create": 1, + "delete": 1, + "email": 1, + "export": 0, + "if_owner": 0, + "import": 0, + "permlevel": 0, + "print": 1, + "read": 1, + "report": 1, + "role": "Administrator", + "set_user_permissions": 0, + "share": 1, + "submit": 0, "write": 1 - }, + }, { - "amend": 0, - "apply_user_permissions": 0, - "cancel": 0, - "create": 1, - "delete": 1, - "email": 1, - "export": 0, - "if_owner": 0, - "import": 0, - "permlevel": 0, - "print": 1, - "read": 1, - "report": 1, - "role": "System Manager", - "set_user_permissions": 0, - "share": 1, - "submit": 0, + "amend": 0, + "apply_user_permissions": 0, + "cancel": 0, + "create": 1, + "delete": 1, + "email": 1, + "export": 0, + "if_owner": 0, + "import": 0, + "permlevel": 0, + "print": 1, + "read": 1, + "report": 1, + "role": "System Manager", + "set_user_permissions": 0, + "share": 1, + "submit": 0, "write": 1 } - ], - "read_only": 0, - "read_only_onload": 0, + ], + "read_only": 0, + "read_only_onload": 0, "search_fields": "dt,label,fieldtype,options" -} \ No newline at end of file +} diff --git a/frappe/custom/doctype/custom_script/custom_script.json b/frappe/custom/doctype/custom_script/custom_script.json index 3b6b2438e7..58fd66c0c2 100644 --- a/frappe/custom/doctype/custom_script/custom_script.json +++ b/frappe/custom/doctype/custom_script/custom_script.json @@ -44,7 +44,7 @@ "ignore_user_permissions": 0, "in_filter": 0, "in_list_view": 1, - "label": "Script Type", + "label": "Script Type", "no_copy": 0, "oldfieldname": "script_type", "oldfieldtype": "Select", @@ -114,7 +114,7 @@ "is_submittable": 0, "issingle": 0, "istable": 0, - "modified": "2015-08-27 06:36:20.439949", + "modified": "2015-10-02 07:38:43.345211", "modified_by": "Administrator", "module": "Custom", "name": "Custom Script", diff --git a/frappe/custom/doctype/custom_script/test_custom_script.py b/frappe/custom/doctype/custom_script/test_custom_script.py new file mode 100644 index 0000000000..6947e6060d --- /dev/null +++ b/frappe/custom/doctype/custom_script/test_custom_script.py @@ -0,0 +1,12 @@ +# -*- coding: utf-8 -*- +# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors +# See license.txt +from __future__ import unicode_literals + +import frappe +import unittest + +# test_records = frappe.get_test_records('Custom Script') + +class TestCustomScript(unittest.TestCase): + pass diff --git a/frappe/custom/doctype/customize_form/customize_form.json b/frappe/custom/doctype/customize_form/customize_form.json index ced2f73f64..cb7b38efea 100644 --- a/frappe/custom/doctype/customize_form/customize_form.json +++ b/frappe/custom/doctype/customize_form/customize_form.json @@ -234,7 +234,7 @@ "ignore_user_permissions": 0, "in_filter": 0, "in_list_view": 0, - "label": "Sort Order", + "label": "Sort Order", "no_copy": 0, "options": "ASC\nDESC", "permlevel": 0, @@ -301,7 +301,7 @@ "is_submittable": 0, "issingle": 1, "istable": 0, - "modified": "2015-07-27 01:00:32.901851", + "modified": "2015-10-02 07:17:18.939161", "modified_by": "Administrator", "module": "Custom", "name": "Customize Form", diff --git a/frappe/custom/doctype/customize_form/customize_form.py b/frappe/custom/doctype/customize_form/customize_form.py index 72e5c34bc6..4a2427cf68 100644 --- a/frappe/custom/doctype/customize_form/customize_form.py +++ b/frappe/custom/doctype/customize_form/customize_form.py @@ -47,7 +47,8 @@ class CustomizeForm(Document): 'description': 'Text', 'default': 'Text', 'precision': 'Select', - 'read_only': 'Check' + 'read_only': 'Check', + 'length': 'Int' } allowed_fieldtype_change = (('Currency', 'Float', 'Percent'), ('Small Text', 'Data'), diff --git a/frappe/custom/doctype/customize_form_field/customize_form_field.json b/frappe/custom/doctype/customize_form_field/customize_form_field.json index 60cd527a24..96c82fa7a9 100644 --- a/frappe/custom/doctype/customize_form_field/customize_form_field.json +++ b/frappe/custom/doctype/customize_form_field/customize_form_field.json @@ -64,11 +64,11 @@ "ignore_user_permissions": 0, "in_filter": 0, "in_list_view": 1, - "label": "Type", + "label": "Type", "no_copy": 0, "oldfieldname": "fieldtype", "oldfieldtype": "Select", - "options": "Attach\nButton\nCheck\nCode\nColumn Break\nCurrency\nData\nDate\nDatetime\nDynamic Link\nFloat\nFold\nHTML\nImage\nInt\nLink\nLong Text\nPassword\nPercent\nRead Only\nSection Break\nSelect\nSmall Text\nTable\nText\nText Editor\nTime", + "options": "Attach\nAttach Image\nButton\nCheck\nCode\nColumn Break\nCurrency\nData\nDate\nDatetime\nDynamic Link\nFloat\nFold\nHeading\nHTML\nImage\nInt\nLink\nLong Text\nPassword\nPercent\nRead Only\nSection Break\nSelect\nSmall Text\nTable\nText\nText Editor\nTime", "permlevel": 0, "print_hide": 0, "read_only": 0, @@ -202,7 +202,7 @@ "ignore_user_permissions": 0, "in_filter": 0, "in_list_view": 0, - "label": "Precision", + "label": "Precision", "no_copy": 0, "options": "\n1\n2\n3\n4\n5\n6\n7\n8\n9", "permlevel": 0, @@ -215,6 +215,29 @@ "set_only_once": 0, "unique": 0 }, + { + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "depends_on": "eval:in_list(['Data', 'Link', 'Dynamic Link', 'Password', 'Select', 'Read Only', 'Attach', 'Attach Image'], doc.fieldtype)", + "fieldname": "length", + "fieldtype": "Int", + "hidden": 0, + "ignore_user_permissions": 0, + "in_filter": 0, + "in_list_view": 0, + "label": "Length", + "no_copy": 0, + "permlevel": 0, + "precision": "", + "print_hide": 0, + "read_only": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "unique": 0 + }, { "allow_on_submit": 0, "bold": 0, @@ -709,7 +732,7 @@ "is_submittable": 0, "issingle": 0, "istable": 1, - "modified": "2015-10-01 07:59:15.490247", + "modified": "2015-10-03 07:38:44.026280", "modified_by": "Administrator", "module": "Custom", "name": "Customize Form Field", diff --git a/frappe/custom/doctype/property_setter/property_setter.json b/frappe/custom/doctype/property_setter/property_setter.json index 6fa56076af..b9aa3be264 100644 --- a/frappe/custom/doctype/property_setter/property_setter.json +++ b/frappe/custom/doctype/property_setter/property_setter.json @@ -61,7 +61,7 @@ "ignore_user_permissions": 0, "in_filter": 0, "in_list_view": 1, - "label": "DocType or Field", + "label": "DocType or Field", "no_copy": 0, "options": "\nDocField\nDocType", "permlevel": 0, @@ -233,7 +233,7 @@ "is_submittable": 0, "issingle": 0, "istable": 0, - "modified": "2015-02-05 05:11:43.216164", + "modified": "2015-10-02 07:39:02.618929", "modified_by": "Administrator", "module": "Custom", "name": "Property Setter", diff --git a/frappe/custom/doctype/property_setter/test_property_setter.py b/frappe/custom/doctype/property_setter/test_property_setter.py new file mode 100644 index 0000000000..33e7d288a4 --- /dev/null +++ b/frappe/custom/doctype/property_setter/test_property_setter.py @@ -0,0 +1,12 @@ +# -*- coding: utf-8 -*- +# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors +# See license.txt +from __future__ import unicode_literals + +import frappe +import unittest + +# test_records = frappe.get_test_records('Property Setter') + +class TestPropertySetter(unittest.TestCase): + pass diff --git a/frappe/data/Framework.sql b/frappe/data/Framework.sql index 624bea642d..988e2c8e5e 100644 --- a/frappe/data/Framework.sql +++ b/frappe/data/Framework.sql @@ -36,8 +36,8 @@ CREATE TABLE `tabDocField` ( `no_copy` int(1) NOT NULL DEFAULT 0, `allow_on_submit` int(1) NOT NULL DEFAULT 0, `trigger` varchar(255) DEFAULT NULL, - `collapsible_depends_on` varchar(255) DEFAULT NULL, - `depends_on` varchar(255) DEFAULT NULL, + `collapsible_depends_on` text, + `depends_on` text, `permlevel` int(11) DEFAULT '0', `ignore_user_permissions` int(1) NOT NULL DEFAULT 0, `width` varchar(255) DEFAULT NULL, @@ -48,6 +48,7 @@ CREATE TABLE `tabDocField` ( `in_list_view` int(1) NOT NULL DEFAULT 0, `read_only` int(1) NOT NULL DEFAULT 0, `precision` varchar(255) DEFAULT NULL, + `length` int(11) DEFAULT NULL, PRIMARY KEY (`name`), KEY `parent` (`parent`), KEY `label` (`label`), diff --git a/frappe/data/languages.txt b/frappe/data/languages.txt index 216b5b1036..18c6645192 100644 --- a/frappe/data/languages.txt +++ b/frappe/data/languages.txt @@ -2,7 +2,7 @@ ar العربية bg bǎlgarski bo ལྷ་སའི་སྐད་ bs bosanski -bn বাঙালি +bn বাংলা ca català cs česky da dansk @@ -36,9 +36,8 @@ pt português pt-BR português brasileiro ro român ru русский -si slovenščina +sk slovenčina sv svenska -sk slovenčina sq shqiptar sr српски ta தமிழ் diff --git a/frappe/desk/doctype/event/event.json b/frappe/desk/doctype/event/event.json index 33adad16c2..9b694ce139 100644 --- a/frappe/desk/doctype/event/event.json +++ b/frappe/desk/doctype/event/event.json @@ -61,7 +61,7 @@ "ignore_user_permissions": 0, "in_filter": 0, "in_list_view": 1, - "label": "Event Type", + "label": "Event Type", "no_copy": 0, "oldfieldname": "event_type", "oldfieldtype": "Select", @@ -253,7 +253,7 @@ "ignore_user_permissions": 0, "in_filter": 0, "in_list_view": 0, - "label": "Repeat On", + "label": "Repeat On", "no_copy": 0, "options": "\nEvery Day\nEvery Week\nEvery Month\nEvery Year", "permlevel": 0, @@ -635,7 +635,7 @@ "is_submittable": 0, "issingle": 0, "istable": 0, - "modified": "2015-09-07 15:51:26", + "modified": "2015-10-02 07:38:49.897665", "modified_by": "Administrator", "module": "Desk", "name": "Event", diff --git a/frappe/desk/doctype/event_role/event_role.json b/frappe/desk/doctype/event_role/event_role.json index e8a7613935..fe8f6ec94f 100644 --- a/frappe/desk/doctype/event_role/event_role.json +++ b/frappe/desk/doctype/event_role/event_role.json @@ -43,7 +43,7 @@ "is_submittable": 0, "issingle": 0, "istable": 1, - "modified": "2015-02-19 01:07:00.166770", + "modified": "2015-10-02 07:38:50.115057", "modified_by": "Administrator", "module": "Desk", "name": "Event Role", diff --git a/frappe/desk/doctype/feed/feed.json b/frappe/desk/doctype/feed/feed.json index 47f0c873a1..227faf8525 100644 --- a/frappe/desk/doctype/feed/feed.json +++ b/frappe/desk/doctype/feed/feed.json @@ -18,7 +18,7 @@ "ignore_user_permissions": 0, "in_filter": 0, "in_list_view": 1, - "label": "Feed Type", + "label": "Feed Type", "no_copy": 0, "options": "\nComment\nLogin\nLabel\nInfo", "permlevel": 0, @@ -77,7 +77,7 @@ "bold": 0, "collapsible": 0, "fieldname": "subject", - "fieldtype": "Data", + "fieldtype": "Small Text", "hidden": 0, "ignore_user_permissions": 0, "in_filter": 0, @@ -145,7 +145,7 @@ "is_submittable": 0, "issingle": 0, "istable": 0, - "modified": "2015-09-07 15:51:26", + "modified": "2015-10-02 07:38:50.611929", "modified_by": "Administrator", "module": "Desk", "name": "Feed", diff --git a/frappe/desk/doctype/feed/feed.py b/frappe/desk/doctype/feed/feed.py index 6538d46468..c9a8ee02fc 100644 --- a/frappe/desk/doctype/feed/feed.py +++ b/frappe/desk/doctype/feed/feed.py @@ -9,6 +9,8 @@ from frappe.model.document import Document from frappe.utils import get_fullname from frappe import _ +exclude_from_linked_with = True + class Feed(Document): pass diff --git a/frappe/desk/doctype/feed/test_feed.py b/frappe/desk/doctype/feed/test_feed.py new file mode 100644 index 0000000000..36adfa377c --- /dev/null +++ b/frappe/desk/doctype/feed/test_feed.py @@ -0,0 +1,12 @@ +# -*- coding: utf-8 -*- +# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors +# See license.txt +from __future__ import unicode_literals + +import frappe +import unittest + +# test_records = frappe.get_test_records('Feed') + +class TestFeed(unittest.TestCase): + pass diff --git a/frappe/desk/doctype/note/note.json b/frappe/desk/doctype/note/note.json index 11121a2434..6e62b9d432 100644 --- a/frappe/desk/doctype/note/note.json +++ b/frappe/desk/doctype/note/note.json @@ -84,7 +84,7 @@ "is_submittable": 0, "issingle": 0, "istable": 0, - "modified": "2015-09-11 12:20:04.912891", + "modified": "2015-10-02 07:38:57.968895", "modified_by": "Administrator", "module": "Desk", "name": "Note", diff --git a/frappe/desk/doctype/todo/todo.js b/frappe/desk/doctype/todo/todo.js index be16bdf0d8..3a204408f7 100644 --- a/frappe/desk/doctype/todo/todo.js +++ b/frappe/desk/doctype/todo/todo.js @@ -32,6 +32,9 @@ frappe.ui.form.on("ToDo", { frm.save(); }, null, "btn-default"); } + frm.add_custom_button(__("New"), function() { + newdoc("ToDo") + }, null, "btn-default"); } } }); diff --git a/frappe/desk/doctype/todo/todo.json b/frappe/desk/doctype/todo/todo.json index 144a4d1165..5f80d78bff 100644 --- a/frappe/desk/doctype/todo/todo.json +++ b/frappe/desk/doctype/todo/todo.json @@ -85,7 +85,7 @@ "ignore_user_permissions": 0, "in_filter": 0, "in_list_view": 1, - "label": "Status", + "label": "Status", "no_copy": 0, "options": "Open\nClosed", "permlevel": 0, @@ -108,7 +108,7 @@ "ignore_user_permissions": 0, "in_filter": 0, "in_list_view": 0, - "label": "Priority", + "label": "Priority", "no_copy": 0, "oldfieldname": "priority", "oldfieldtype": "Data", @@ -335,7 +335,7 @@ "issingle": 0, "istable": 0, "max_attachments": 0, - "modified": "2015-09-07 15:51:26", + "modified": "2015-10-02 07:39:17.248993", "modified_by": "Administrator", "module": "Desk", "name": "ToDo", diff --git a/frappe/desk/doctype/todo/todo.py b/frappe/desk/doctype/todo/todo.py index f3c6647988..b93cd9d28c 100644 --- a/frappe/desk/doctype/todo/todo.py +++ b/frappe/desk/doctype/todo/todo.py @@ -10,6 +10,7 @@ from frappe.utils import get_fullname subject_field = "description" sender_field = "sender" +exclude_from_linked_with = True class ToDo(Document): def validate(self): diff --git a/frappe/desk/form/assign_to.py b/frappe/desk/form/assign_to.py index b8e08c858d..996fa6be28 100644 --- a/frappe/desk/form/assign_to.py +++ b/frappe/desk/form/assign_to.py @@ -103,8 +103,8 @@ def notify_assignment(assigned_by, owner, doc_type, doc_name, action='CLOSE', user_info = get_fullnames() # Search for email address in description -- i.e. assignee - from frappe.utils import get_url_to_form - assignment = get_url_to_form(doc_type, doc_name, label="%s: %s" % (doc_type, doc_name)) + from frappe.utils import get_link_to_form + assignment = get_link_to_form(doc_type, doc_name, label="%s: %s" % (doc_type, doc_name)) owner_name = user_info.get(owner, {}).get('fullname') user_name = user_info.get(frappe.session.get('user'), {}).get('fullname') if action=='CLOSE': diff --git a/frappe/desk/form/linked_with.py b/frappe/desk/form/linked_with.py new file mode 100644 index 0000000000..4c7220f797 --- /dev/null +++ b/frappe/desk/form/linked_with.py @@ -0,0 +1,177 @@ +# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors +# MIT License. See license.txt +from __future__ import unicode_literals + +import frappe, json +from frappe.model.meta import is_single +from frappe.modules import load_doctype_module +import frappe.desk.form.meta +import frappe.desk.form.load + +@frappe.whitelist() +def get_linked_docs(doctype, name, linkinfo=None): + results = frappe.cache().get_value("linked_with:{doctype}:{name}".format(doctype=doctype, name=name)) + if results: + return results + + meta = frappe.desk.form.meta.get_meta(doctype) + results = {} + + if isinstance(linkinfo, basestring): + # additional fields are added in linkinfo + linkinfo = json.loads(linkinfo) + + if not linkinfo: + return results + + me = frappe.db.get_value(doctype, name, ["parenttype", "parent"], as_dict=True) + for dt, link in linkinfo.items(): + link["doctype"] = dt + link_meta_bundle = frappe.desk.form.load.get_meta_bundle(dt) + linkmeta = link_meta_bundle[0] + if not linkmeta.get("issingle"): + fields = [d.fieldname for d in linkmeta.get("fields", {"in_list_view":1, + "fieldtype": ["not in", ["Image", "HTML", "Button", "Table"]]})] \ + + ["name", "modified", "docstatus"] + + if link.get("add_fields"): + fields += link["add_fields"] + + fields = ["`tab{dt}`.`{fn}`".format(dt=dt, fn=sf.strip()) for sf in fields if sf + and "`tab" not in sf] + + try: + if link.get("get_parent"): + if me and me.parent and me.parenttype == dt: + ret = frappe.get_list(doctype=dt, fields=fields, + filters=[[dt, "name", '=', me.parent]]) + else: + ret = None + + elif link.get("child_doctype"): + filters = [[link.get('child_doctype'), link.get("fieldname"), '=', name]] + + # dynamic link + if link.get("doctype_fieldname"): + filters.append([link.get('child_doctype'), link.get("doctype_fieldname"), "=", doctype]) + + ret = frappe.get_list(doctype=dt, fields=fields, filters=filters) + + else: + filters = [[dt, link.get("fieldname"), '=', name]] + + # dynamic link + if link.get("doctype_fieldname"): + filters.append([dt, link.get("doctype_fieldname"), "=", doctype]) + + ret = frappe.get_list(doctype=dt, fields=fields, filters=filters) + + except frappe.PermissionError: + if frappe.local.message_log: + frappe.local.message_log.pop() + + continue + + if ret: + results[dt] = ret + + frappe.cache().set_value("linked_with:{doctype}:{name}".format(doctype=doctype, name=name), results, user=True) + + return results + +@frappe.whitelist() +def get_linked_doctypes(doctype): + """add list of doctypes this doctype is 'linked' with. + + Example, for Customer: + + {"Address": {"fieldname": "customer"}..} + """ + return frappe.cache().hget("linked_doctypes", doctype, lambda: _get_linked_doctypes(doctype)) + +def _get_linked_doctypes(doctype): + ret = {} + + # find fields where this doctype is linked + ret.update(get_linked_fields(doctype)) + + ret.update(get_dynamic_linked_fields(doctype)) + + # find links of parents + links = frappe.db.sql("""select dt from `tabCustom Field` + where (fieldtype="Table" and options=%s)""", (doctype)) + links += frappe.db.sql("""select parent from tabDocField + where (fieldtype="Table" and options=%s)""", (doctype)) + + for dt, in links: + if not dt in ret: + ret[dt] = {"get_parent": True} + + for dt in ret.keys(): + doctype_module = load_doctype_module(dt) + + if getattr(doctype_module, "exclude_from_linked_with", False): + del ret[dt] + + return ret + +def get_linked_fields(doctype): + links = frappe.db.sql("""select parent, fieldname from tabDocField + where (fieldtype="Link" and options=%s) + or (fieldtype="Select" and options=%s)""", (doctype, "link:"+ doctype)) + links += frappe.db.sql("""select dt as parent, fieldname from `tabCustom Field` + where (fieldtype="Link" and options=%s) + or (fieldtype="Select" and options=%s)""", (doctype, "link:"+ doctype)) + + links = dict(links) + + ret = {} + + if links: + for dt in links: + ret[dt] = { "fieldname": links[dt] } + + # find out if linked in a child table + for parent, options in frappe.db.sql("""select parent, options from tabDocField + where fieldtype="Table" + and options in (select name from tabDocType + where istable=1 and name in (%s))""" % ", ".join(["%s"] * len(links)) ,tuple(links)): + + ret[parent] = {"child_doctype": options, "fieldname": links[options] } + if options in ret: + del ret[options] + + return ret + +def get_dynamic_linked_fields(doctype): + ret = {} + + links = frappe.db.sql("""select parent as doctype, fieldname, options as doctype_fieldname + from `tabDocField` where fieldtype='Dynamic Link'""", as_dict=True) + links += frappe.db.sql("""select dt as doctype, fieldname, options as doctype_fieldname + from `tabCustom Field` where fieldtype='Dynamic Link'""", as_dict=True) + + for df in links: + if is_single(df.doctype): + continue + + # optimized to get both link exists and parenttype + possible_link = frappe.db.sql("""select distinct `{doctype_fieldname}`, parenttype + from `tab{doctype}` where `{doctype_fieldname}`=%s""".format(**df), doctype, as_dict=True) + if possible_link: + for d in possible_link: + # is child + if d.parenttype: + ret[d.parenttype] = { + "child_doctype": df.doctype, + "fieldname": df.fieldname, + "doctype_fieldname": df.doctype_fieldname + } + + else: + ret[df.doctype] = { + "fieldname": df.fieldname, + "doctype_fieldname": df.doctype_fieldname + } + + return ret diff --git a/frappe/desk/form/meta.py b/frappe/desk/form/meta.py index 7d526ceb28..64b1b45e04 100644 --- a/frappe/desk/form/meta.py +++ b/frappe/desk/form/meta.py @@ -36,7 +36,6 @@ class FormMeta(Meta): self.add_linked_document_type() if not self.istable: - self.add_linked_with() self.add_code() self.load_print_formats() self.load_workflows() @@ -130,52 +129,6 @@ class FormMeta(Meta): # edge case where options="[Select]" pass - def add_linked_with(self): - """add list of doctypes this doctype is 'linked' with. - - Example, for Customer: - - {"Address": {"fieldname": "customer"}..} - """ - - # find fields where this doctype is linked - links = frappe.db.sql("""select parent, fieldname from tabDocField - where (fieldtype="Link" and options=%s) - or (fieldtype="Select" and options=%s)""", (self.name, "link:"+ self.name)) - links += frappe.db.sql("""select dt as parent, fieldname from `tabCustom Field` - where (fieldtype="Link" and options=%s) - or (fieldtype="Select" and options=%s)""", (self.name, "link:"+ self.name)) - - links = dict(links) - - ret = {} - - for dt in links: - ret[dt] = { "fieldname": links[dt] } - - if links: - # find out if linked in a child table - for parent, options in frappe.db.sql("""select parent, options from tabDocField - where fieldtype="Table" - and options in (select name from tabDocType - where istable=1 and name in (%s))""" % ", ".join(["%s"] * len(links)) ,tuple(links)): - - ret[parent] = {"child_doctype": options, "fieldname": links[options] } - if options in ret: - del ret[options] - - # find links of parents - links = frappe.db.sql("""select dt from `tabCustom Field` - where (fieldtype="Table" and options=%s)""", (self.name)) - links += frappe.db.sql("""select parent from tabDocField - where (fieldtype="Table" and options=%s)""", (self.name)) - - for dt, in links: - if not dt in ret: - ret[dt] = {"get_parent": True} - - self.set("__linked_with", ret, as_value=True) - def load_print_formats(self): print_formats = frappe.db.sql("""select * FROM `tabPrint Format` WHERE doc_type=%s AND docstatus<2 and ifnull(disabled, 0)=0""", (self.name,), as_dict=1, diff --git a/frappe/desk/form/test_form.py b/frappe/desk/form/test_form.py index af907ba2fb..ff0343b6e0 100644 --- a/frappe/desk/form/test_form.py +++ b/frappe/desk/form/test_form.py @@ -1,17 +1,17 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors -# MIT License. See license.txt +# MIT License. See license.txt from __future__ import unicode_literals import frappe, unittest -from frappe.desk.form.utils import get_linked_docs +from frappe.desk.form.linked_with import get_linked_docs, get_linked_doctypes class TestForm(unittest.TestCase): def test_linked_with(self): - results = get_linked_docs("Role", "System Manager") + results = get_linked_docs("Role", "System Manager", linkinfo=get_linked_doctypes("Role")) self.assertTrue("User" in results) self.assertTrue("DocType" in results) - + if __name__=="__main__": frappe.connect() unittest.main() diff --git a/frappe/desk/form/utils.py b/frappe/desk/form/utils.py index 83ede1c57c..a6ca8173d8 100644 --- a/frappe/desk/form/utils.py +++ b/frappe/desk/form/utils.py @@ -105,54 +105,3 @@ def get_next(doctype, value, prev, filters=None, order_by="modified desc"): else: return res[0][0] -@frappe.whitelist() -def get_linked_docs(doctype, name, metadata_loaded=None, no_metadata=False): - if not metadata_loaded: metadata_loaded = [] - meta = frappe.desk.form.meta.get_meta(doctype) - linkinfo = meta.get("__linked_with") - results = {} - - if not linkinfo: - return results - - me = frappe.db.get_value(doctype, name, ["parenttype", "parent"], as_dict=True) - for dt, link in linkinfo.items(): - link["doctype"] = dt - link_meta_bundle = frappe.desk.form.load.get_meta_bundle(dt) - linkmeta = link_meta_bundle[0] - if not linkmeta.get("issingle"): - fields = [d.fieldname for d in linkmeta.get("fields", {"in_list_view":1, - "fieldtype": ["not in", ["Image", "HTML", "Button", "Table"]]})] \ - + ["name", "modified", "docstatus"] - - fields = ["`tab{dt}`.`{fn}`".format(dt=dt, fn=sf.strip()) for sf in fields if sf] - - try: - if link.get("get_parent"): - if me and me.parent and me.parenttype == dt: - ret = frappe.get_list(doctype=dt, fields=fields, - filters=[[dt, "name", '=', me.parent]]) - else: - ret = None - - elif link.get("child_doctype"): - ret = frappe.get_list(doctype=dt, fields=fields, - filters=[[link.get('child_doctype'), link.get("fieldname"), '=', name]]) - - else: - ret = frappe.get_list(doctype=dt, fields=fields, - filters=[[dt, link.get("fieldname"), '=', name]]) - - except frappe.PermissionError: - if frappe.local.message_log: - frappe.local.message_log.pop() - - continue - - if ret: - results[dt] = ret - - if not no_metadata and not dt in metadata_loaded: - frappe.local.response.docs.extend(link_meta_bundle) - - return results diff --git a/frappe/email/bulk.py b/frappe/email/bulk.py index 9b69458526..023a7e36ff 100644 --- a/frappe/email/bulk.py +++ b/frappe/email/bulk.py @@ -16,7 +16,7 @@ class BulkLimitCrossedError(frappe.ValidationError): pass def send(recipients=None, sender=None, subject=None, message=None, reference_doctype=None, reference_name=None, unsubscribe_method=None, unsubscribe_params=None, unsubscribe_message=None, - attachments=None, reply_to=None, cc=(), message_id=None, send_after=None, + attachments=None, reply_to=None, cc=(), show_as_cc=(), message_id=None, send_after=None, expose_recipients=False, bulk_priority=1): """Add email to sending queue (Bulk Email) @@ -89,6 +89,14 @@ def send(recipients=None, sender=None, subject=None, message=None, reference_doc email_content = email_content.replace("", unsubscribe_link.html) email_text_context += unsubscribe_link.text + # show as cc + cc_message = "" + if email in show_as_cc: + cc_message = _("This email was sent to you as CC") + + email_content = email_content.replace("", cc_message) + email_text_context = cc_message + "\n" + email_text_context + # add to queue add(email, sender, subject, email_content, email_text_context, reference_doctype, reference_name, attachments, reply_to, cc, message_id, send_after, bulk_priority) @@ -230,7 +238,7 @@ def flush(from_test=False): frappe.db.sql("""update `tabBulk Email` set status='Expired' where datediff(curdate(), creation) > 3""", auto_commit=auto_commit) - for i in xrange(100): + for i in xrange(500): email = frappe.db.sql("""select * from `tabBulk Email` where status='Not Sent' and ifnull(send_after, "2000-01-01 00:00:00") < %s order by priority desc, creation asc limit 1 for update""", now_datetime(), as_dict=1) diff --git a/frappe/email/doctype/bulk_email/bulk_email.json b/frappe/email/doctype/bulk_email/bulk_email.json index 99d2b01a82..cebdd99424 100644 --- a/frappe/email/doctype/bulk_email/bulk_email.json +++ b/frappe/email/doctype/bulk_email/bulk_email.json @@ -84,7 +84,7 @@ "ignore_user_permissions": 0, "in_filter": 0, "in_list_view": 1, - "label": "Status", + "label": "Status", "no_copy": 0, "options": "\nNot Sent\nSending\nSent\nError", "permlevel": 0, @@ -215,7 +215,7 @@ "is_submittable": 0, "issingle": 0, "istable": 0, - "modified": "2015-09-29 05:16:31.857121", + "modified": "2015-10-02 07:38:40.795371", "modified_by": "Administrator", "module": "Email", "name": "Bulk Email", diff --git a/frappe/email/doctype/email_account/email_account.json b/frappe/email/doctype/email_account/email_account.json index 753bee092b..0e08a31780 100644 --- a/frappe/email/doctype/email_account/email_account.json +++ b/frappe/email/doctype/email_account/email_account.json @@ -41,7 +41,7 @@ "ignore_user_permissions": 0, "in_filter": 0, "in_list_view": 0, - "label": "Service", + "label": "Service", "no_copy": 0, "options": "\nGMail\nYahoo Mail\nOutlook.com", "permlevel": 0, @@ -780,7 +780,7 @@ "is_submittable": 0, "issingle": 0, "istable": 0, - "modified": "2015-09-18 01:34:31.784444", + "modified": "2015-10-02 07:38:47.651995", "modified_by": "Administrator", "module": "Email", "name": "Email Account", diff --git a/frappe/email/doctype/email_alert/email_alert.json b/frappe/email/doctype/email_alert/email_alert.json index b4496355c5..d4189a0de5 100644 --- a/frappe/email/doctype/email_alert/email_alert.json +++ b/frappe/email/doctype/email_alert/email_alert.json @@ -56,6 +56,7 @@ "allow_on_submit": 0, "bold": 0, "collapsible": 0, + "description": "To add dynamic subject, use jinja tags like\n\n
{{ doc.name }} Delivered
", "fieldname": "subject", "fieldtype": "Data", "hidden": 0, @@ -411,7 +412,7 @@ "is_submittable": 0, "issingle": 0, "istable": 0, - "modified": "2015-07-09 00:27:00.169741", + "modified": "2015-10-16 01:35:51.254775", "modified_by": "Administrator", "module": "Email", "name": "Email Alert", diff --git a/frappe/email/doctype/email_alert/email_alert.py b/frappe/email/doctype/email_alert/email_alert.py index 4b4065791f..2366652de3 100644 --- a/frappe/email/doctype/email_alert/email_alert.py +++ b/frappe/email/doctype/email_alert/email_alert.py @@ -94,7 +94,11 @@ def evaluate_alert(doc, alert, event): if not recipients: return - frappe.sendmail(recipients=recipients, subject=alert.subject, + subject = alert.subject + if "{" in subject: + subject = frappe.render_template(alert.subject, {"doc": doc, "alert": alert}) + + frappe.sendmail(recipients=recipients, subject=subject, message= frappe.render_template(alert.message, {"doc": doc, "alert":alert}), bulk=True, reference_doctype = doc.doctype, reference_name = doc.name, attachments = [frappe.attach_print(doc.doctype, doc.name)] if alert.attach_print else None) diff --git a/frappe/email/doctype/email_alert_recipient/email_alert_recipient.json b/frappe/email/doctype/email_alert_recipient/email_alert_recipient.json index 29c90a1e8d..9ed1d1fcad 100644 --- a/frappe/email/doctype/email_alert_recipient/email_alert_recipient.json +++ b/frappe/email/doctype/email_alert_recipient/email_alert_recipient.json @@ -82,7 +82,7 @@ "is_submittable": 0, "issingle": 0, "istable": 1, - "modified": "2014-07-11 17:54:53.298536", + "modified": "2015-10-02 07:38:48.185785", "modified_by": "Administrator", "module": "Email", "name": "Email Alert Recipient", diff --git a/frappe/email/doctype/email_unsubscribe/email_unsubscribe.json b/frappe/email/doctype/email_unsubscribe/email_unsubscribe.json index c4210ee009..f93379d5c3 100644 --- a/frappe/email/doctype/email_unsubscribe/email_unsubscribe.json +++ b/frappe/email/doctype/email_unsubscribe/email_unsubscribe.json @@ -106,7 +106,7 @@ "is_submittable": 0, "issingle": 0, "istable": 0, - "modified": "2015-08-05 06:02:12.805282", + "modified": "2015-10-02 07:38:48.744583", "modified_by": "Administrator", "module": "Email", "name": "Email Unsubscribe", diff --git a/frappe/email/doctype/standard_reply/standard_reply.json b/frappe/email/doctype/standard_reply/standard_reply.json index 049c724a9e..314f8bdb81 100644 --- a/frappe/email/doctype/standard_reply/standard_reply.json +++ b/frappe/email/doctype/standard_reply/standard_reply.json @@ -83,7 +83,7 @@ "is_submittable": 0, "issingle": 0, "istable": 0, - "modified": "2015-09-07 15:51:26", + "modified": "2015-10-02 07:39:13.407883", "modified_by": "Administrator", "module": "Email", "name": "Standard Reply", diff --git a/frappe/email/doctype/standard_reply/test_standard_reply.py b/frappe/email/doctype/standard_reply/test_standard_reply.py new file mode 100644 index 0000000000..9255716b12 --- /dev/null +++ b/frappe/email/doctype/standard_reply/test_standard_reply.py @@ -0,0 +1,12 @@ +# -*- coding: utf-8 -*- +# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors +# See license.txt +from __future__ import unicode_literals + +import frappe +import unittest + +# test_records = frappe.get_test_records('Standard Reply') + +class TestStandardReply(unittest.TestCase): + pass diff --git a/frappe/email/smtp.py b/frappe/email/smtp.py index c24ea82807..189369a699 100644 --- a/frappe/email/smtp.py +++ b/frappe/email/smtp.py @@ -77,6 +77,7 @@ def get_default_outgoing_email_account(raise_exception_not_set=True): "sender": frappe.conf.get("auto_email_id", "notifications@example.com") }) email_account.from_site_config = True + email_account.name = frappe.conf.get("email_sender_name") or "Frappe" if not email_account and not raise_exception_not_set: return None diff --git a/frappe/exceptions.py b/frappe/exceptions.py index 17c12d2c36..49e1515c0b 100644 --- a/frappe/exceptions.py +++ b/frappe/exceptions.py @@ -47,6 +47,7 @@ class MandatoryError(ValidationError): pass class InvalidSignatureError(ValidationError): pass class RateLimitExceededError(ValidationError): pass class CannotChangeConstantError(ValidationError): pass +class CharacterLengthExceededError(ValidationError): pass class UpdateAfterSubmitError(ValidationError): pass class LinkValidationError(ValidationError): pass class CancelledLinkError(LinkValidationError): pass diff --git a/frappe/geo/doctype/country/country.json b/frappe/geo/doctype/country/country.json index 165695d7f5..04e111f0aa 100644 --- a/frappe/geo/doctype/country/country.json +++ b/frappe/geo/doctype/country/country.json @@ -105,7 +105,7 @@ "is_submittable": 0, "issingle": 0, "istable": 0, - "modified": "2015-09-07 15:51:26", + "modified": "2015-10-02 07:38:42.770807", "modified_by": "Administrator", "module": "Geo", "name": "Country", diff --git a/frappe/geo/doctype/currency/currency.json b/frappe/geo/doctype/currency/currency.json index b42a53da67..8eedef0082 100644 --- a/frappe/geo/doctype/currency/currency.json +++ b/frappe/geo/doctype/currency/currency.json @@ -131,7 +131,7 @@ "ignore_user_permissions": 0, "in_filter": 0, "in_list_view": 1, - "label": "Number Format", + "label": "Number Format", "no_copy": 0, "options": "\n#,###.##\n#.###,##\n# ###.##\n# ###,##\n#'###.##\n#, ###.##\n#,##,###.##\n#,###.###\n#.###\n#,###", "permlevel": 0, @@ -153,7 +153,7 @@ "is_submittable": 0, "issingle": 0, "istable": 0, - "modified": "2015-09-14 03:17:04.837607", + "modified": "2015-10-02 07:38:42.863135", "modified_by": "Administrator", "module": "Geo", "name": "Currency", diff --git a/frappe/hooks.py b/frappe/hooks.py index c8d7972b76..202095de7e 100644 --- a/frappe/hooks.py +++ b/frappe/hooks.py @@ -26,7 +26,7 @@ to ERPNext. """ app_icon = "octicon octicon-circuit-board" -app_version = "6.4.9" +app_version = "6.5.0" app_color = "orange" github_link = "https://github.com/frappe/frappe" diff --git a/frappe/model/base_document.py b/frappe/model/base_document.py index a4ad9e35db..22b75a0596 100644 --- a/frappe/model/base_document.py +++ b/frappe/model/base_document.py @@ -9,6 +9,7 @@ from frappe.model import default_fields from frappe.model.naming import set_new_name from frappe.modules import load_doctype_module from frappe.model import display_fieldtypes +from frappe.model.db_schema import type_map, varchar_len _classes = {} @@ -444,6 +445,25 @@ class BaseDocument(object): frappe.throw(_("Value cannot be changed for {0}").format(self.meta.get_label(fieldname)), frappe.CannotChangeConstantError) + def _validate_length(self): + if frappe.flags.in_install: + return + + for fieldname, value in self.get_valid_dict().iteritems(): + df = self.meta.get_field(fieldname) + if df and df.fieldtype in type_map and type_map[df.fieldtype][0]=="varchar": + max_length = cint(df.get("length")) or cint(varchar_len) + + if len(cstr(value)) > max_length: + if self.parentfield and self.idx: + reference = _("{0}, Row {1}").format(_(self.doctype), self.idx) + + else: + reference = "{0} {1}".format(_(self.doctype), self.name) + + frappe.throw(_("{0}: '{1}' will get truncated, as max characters allowed is {2}")\ + .format(reference, _(df.label), max_length), frappe.CharacterLengthExceededError) + def _validate_update_after_submit(self): # get the full doc with children db_values = frappe.get_doc(self.doctype, self.name).as_dict() diff --git a/frappe/model/db_schema.py b/frappe/model/db_schema.py index deb27d7eda..3a3e15cd22 100644 --- a/frappe/model/db_schema.py +++ b/frappe/model/db_schema.py @@ -13,9 +13,13 @@ import os import frappe from frappe import _ from frappe.utils import cstr, cint +import MySQLdb class InvalidColumnName(frappe.ValidationError): pass +varchar_len = '140' +standard_varchar_columns = ('name', 'owner', 'modified_by', 'parent', 'parentfield', 'parenttype') + type_map = { 'Currency': ('decimal', '18,6') ,'Int': ('int', '11') @@ -30,14 +34,14 @@ type_map = { ,'Datetime': ('datetime', '6') ,'Time': ('time', '6') ,'Text': ('text', '') - ,'Data': ('varchar', '255') - ,'Link': ('varchar', '255') - ,'Dynamic Link':('varchar', '255') - ,'Password': ('varchar', '255') - ,'Select': ('varchar', '255') - ,'Read Only': ('varchar', '255') - ,'Attach': ('varchar', '255') - ,'Attach Image':('varchar', '255') + ,'Data': ('varchar', varchar_len) + ,'Link': ('varchar', varchar_len) + ,'Dynamic Link':('varchar', varchar_len) + ,'Password': ('varchar', varchar_len) + ,'Select': ('varchar', varchar_len) + ,'Read Only': ('varchar', varchar_len) + ,'Attach': ('text', '') + ,'Attach Image':('text', '') } default_columns = ['name', 'creation', 'modified', 'modified_by', 'owner', @@ -57,8 +61,10 @@ def updatedb(dt): raise Exception, 'Wrong doctype "%s" in updatedb' % dt if not res[0][0]: - frappe.db.commit() tab = DbTable(dt, 'tab') + tab.validate() + + frappe.db.commit() tab.sync() frappe.db.begin() @@ -80,12 +86,57 @@ class DbTable: # load self.get_columns_from_docfields() + def validate(self): + """Check if change in varchar length isn't truncating the columns""" + if self.is_new(): + return + + self.get_columns_from_db() + + columns = [frappe._dict({"fieldname": f, "fieldtype": "Data"}) for f in standard_varchar_columns] + columns += self.columns.values() + + for col in columns: + if col.fieldtype in type_map and type_map[col.fieldtype][0]=="varchar": + + # validate length range + new_length = cint(col.length) or cint(varchar_len) + if not (1 <= new_length <= 255): + frappe.throw(_("Length of {0} should be between 1 and 255").format(col.fieldname)) + + try: + # check for truncation + max_length = frappe.db.sql("""select max(length(`{fieldname}`)) from `tab{doctype}`"""\ + .format(fieldname=col.fieldname, doctype=self.doctype)) + + except MySQLdb.OperationalError, e: + if e.args[0]==1054: + # Unknown column 'column_name' in 'field list' + continue + + else: + raise + + if max_length and max_length[0][0] > new_length: + current_type = self.current_columns[col.fieldname]["type"] + current_length = re.findall('varchar\(([\d]+)\)', current_type)[0] + + if col.fieldname in self.columns: + self.columns[col.fieldname].length = current_length + + frappe.msgprint(_("Reverting length to {0} for '{1}' in '{2}'; Setting the length as {3} will cause truncation of data.")\ + .format(current_length, col.fieldname, self.doctype, new_length)) + + def sync(self): - if not self.name in DbManager(frappe.db).get_tables_list(frappe.db.cur_db_name): + if self.is_new(): self.create() else: self.alter() + def is_new(self): + return self.name not in DbManager(frappe.db).get_tables_list(frappe.db.cur_db_name) + def create(self): add_text = '' @@ -99,21 +150,21 @@ class DbTable: # create table frappe.db.sql("""create table `%s` ( - name varchar(255) not null primary key, + name varchar({varchar_len}) not null primary key, creation datetime(6), modified datetime(6), - modified_by varchar(255), - owner varchar(255), + modified_by varchar({varchar_len}), + owner varchar({varchar_len}), docstatus int(1) default '0', - parent varchar(255), - parentfield varchar(255), - parenttype varchar(255), + parent varchar({varchar_len}), + parentfield varchar({varchar_len}), + parenttype varchar({varchar_len}), idx int(8), %sindex parent(parent)) ENGINE=InnoDB ROW_FORMAT=COMPRESSED CHARACTER SET=utf8mb4 - COLLATE=utf8mb4_unicode_ci""" % (self.name, add_text)) + COLLATE=utf8mb4_unicode_ci""".format(varchar_len=varchar_len) % (self.name, add_text)) def get_column_definitions(self): column_list = [] + default_columns @@ -139,6 +190,7 @@ class DbTable: get columns from docfields and custom fields """ fl = frappe.db.sql("SELECT * FROM tabDocField WHERE parent = %s", self.doctype, as_dict = 1) + lengths = {} precisions = {} uniques = {} @@ -148,19 +200,26 @@ class DbTable: WHERE dt = %s AND docstatus < 2""", (self.doctype,), as_dict=1) if custom_fl: fl += custom_fl - # get precision from property setters - for ps in frappe.get_all("Property Setter", fields=["field_name", "value"], - filters={"doc_type": self.doctype, "doctype_or_field": "DocField", "property": "precision"}): - precisions[ps.field_name] = ps.value + # apply length, precision and unique from property setters + for ps in frappe.get_all("Property Setter", fields=["field_name", "property", "value"], + filters={ + "doc_type": self.doctype, + "doctype_or_field": "DocField", + "property": ["in", ["precision", "length", "unique"]] + }): - # apply unique from property setters - for ps in frappe.get_all("Property Setter", fields=["field_name", "value"], - filters={"doc_type": self.doctype, "doctype_or_field": "DocField", "property": "unique"}): + if ps.property=="length": + lengths[ps.field_name] = cint(ps.value) + + elif ps.property=="precision": + precisions[ps.field_name] = cint(ps.value) + + elif ps.property=="unique": uniques[ps.field_name] = cint(ps.value) for f in fl: self.columns[f['fieldname']] = DbColumn(self, f['fieldname'], - f['fieldtype'], f.get('length'), f.get('default'), f.get('search_index'), + f['fieldtype'], lengths.get(f["fieldname"]) or f.get('length'), f.get('default'), f.get('search_index'), f.get('options'), uniques.get(f["fieldname"], f.get('unique')), precisions.get(f['fieldname']) or f.get('precision')) def get_columns_from_db(self): @@ -201,7 +260,6 @@ class DbTable: frappe.db.sql("set foreign_key_checks=1") def alter(self): - self.get_columns_from_db() for col in self.columns.values(): col.build_for_alter_table(self.current_columns.get(col.fieldname, None)) @@ -268,7 +326,7 @@ class DbColumn: self.precision = precision def get_definition(self, with_default=1): - column_def = get_definition(self.fieldtype, self.precision) + column_def = get_definition(self.fieldtype, precision=self.precision, length=self.length) if not column_def: return column_def @@ -287,7 +345,7 @@ class DbColumn: return column_def def build_for_alter_table(self, current_def): - column_def = get_definition(self.fieldtype) + column_def = get_definition(self.fieldtype, self.precision, self.length) # no columns if not column_def: @@ -471,20 +529,28 @@ def remove_all_foreign_keys(): for f in fklist: frappe.db.sql("alter table `tab%s` drop foreign key `%s`" % (t[0], f[1])) -def get_definition(fieldtype, precision=None): +def get_definition(fieldtype, precision=None, length=None): d = type_map.get(fieldtype) if not d: return - ret = d[0] + coltype = d[0] + size = None if d[1]: - length = d[1] - if fieldtype in ["Float", "Currency", "Percent"] and cint(precision) > 6: - length = '18,9' - ret += '(' + length + ')' + size = d[1] - return ret + if size: + if fieldtype in ["Float", "Currency", "Percent"] and cint(precision) > 6: + size = '18,9' + + if coltype == "varchar" and length: + size = length + + if size is not None: + coltype = "{coltype}({size})".format(coltype=coltype, size=size) + + return coltype def add_column(doctype, column_name, fieldtype, precision=None): frappe.db.commit() diff --git a/frappe/model/document.py b/frappe/model/document.py index f2d965cc2d..3c308f1b8a 100644 --- a/frappe/model/document.py +++ b/frappe/model/document.py @@ -337,11 +337,13 @@ class Document(BaseDocument): self._validate_links() self._validate_selects() self._validate_constants() + self._validate_length() children = self.get_all_children() for d in children: d._validate_selects() d._validate_constants() + d._validate_length() # extract images after validations to save processing if some validation error is raised self._extract_images_from_text_editor() @@ -616,11 +618,34 @@ class Document(BaseDocument): elif self._action=="update_after_submit": self.run_method("on_update_after_submit") - frappe.cache().hdel("last_modified", self.doctype) + self.clear_cache() self.notify_update() self.latest = None + def clear_cache(self): + frappe.cache().hdel("last_modified", self.doctype) + self.clear_linked_with_cache() + + def clear_linked_with_cache(self): + cache = frappe.cache() + def _clear_cache(d): + for df in (d.meta.get_link_fields() + d.meta.get_dynamic_link_fields()): + if d.get(df.fieldname): + doctype = df.options if df.fieldtype=="Link" else d.get(df.options) + name = d.get(df.fieldname) + + if df.fieldtype=="Dynamic Link": + # clear linked doctypes list + cache.hdel("linked_doctypes", doctype) + + # delete linked with cache for all users + cache.delete_value("user:*:linked_with:{doctype}:{name}".format(doctype=doctype, name=name)) + + _clear_cache(self) + for d in self.get_all_children(): + _clear_cache(d) + def notify_update(self): """Publish realtime that the current document is modified""" frappe.publish_realtime("doc_update", {"modified": self.modified, "doctype": self.doctype, "name": self.name}, diff --git a/frappe/model/meta.py b/frappe/model/meta.py index 4999b4fdc7..83ace81270 100644 --- a/frappe/model/meta.py +++ b/frappe/model/meta.py @@ -60,6 +60,9 @@ class Meta(Document): def get_link_fields(self): return self.get("fields", {"fieldtype": "Link", "options":["!=", "[Select]"]}) + def get_dynamic_link_fields(self): + return self.get("fields", {"fieldtype": "Dynamic Link"}) + def get_select_fields(self): return self.get("fields", {"fieldtype": "Select", "options":["not in", ["[Select]", "Loading..."]]}) @@ -329,14 +332,19 @@ def trim_tables(): frappe.db.sql_ddl(query) def clear_cache(doctype=None): - frappe.cache().delete_value("is_table") - frappe.cache().delete_value("doctype_modules") + cache = frappe.cache() - groups = ["meta", "form_meta", "table_columns", "last_modified"] + cache.delete_value("is_table") + cache.delete_value("doctype_modules") + + groups = ["meta", "form_meta", "table_columns", "last_modified", "linked_doctypes"] def clear_single(dt): for name in groups: - frappe.cache().hdel(name, dt) + cache.hdel(name, dt) + + # also clear linked_with list cache + cache.delete_keys("user:*:linked_with:{doctype}:".format(doctype=doctype)) if doctype: clear_single(doctype) @@ -353,5 +361,5 @@ def clear_cache(doctype=None): else: # clear all for name in groups: - frappe.cache().delete_value(name) + cache.delete_value(name) diff --git a/frappe/model/naming.py b/frappe/model/naming.py index c23bd3d633..292e80ce9b 100644 --- a/frappe/model/naming.py +++ b/frappe/model/naming.py @@ -82,7 +82,7 @@ def make_autoname(key, doctype=''): DE/09/01/0001 where 09 is the year, 01 is the month and 0001 is the series """ if key=="hash": - return frappe.generate_hash(doctype)[:10] + return frappe.generate_hash(doctype, 10) if not "#" in key: key = key + ".#####" diff --git a/frappe/patches.txt b/frappe/patches.txt index c9dbc01117..f25f0ac91d 100644 --- a/frappe/patches.txt +++ b/frappe/patches.txt @@ -2,8 +2,9 @@ execute:frappe.db.sql("""update `tabPatch Log` set patch=replace(patch, '.4_0.', frappe.patches.v5_0.convert_to_barracuda_and_utf8mb4 frappe.patches.v6_1.rename_file_data execute:frappe.reload_doc('core', 'doctype', 'doctype', force=True) #2014-01-24 -execute:frappe.reload_doc('core', 'doctype', 'docfield', force=True) #2015-08-20 +execute:frappe.reload_doc('core', 'doctype', 'docfield', force=True) #2015-10-16 execute:frappe.reload_doc('core', 'doctype', 'docperm') #2014-06-24 +execute:frappe.reload_doc('custom', 'doctype', 'custom_field') #2015-10-19 execute:frappe.reload_doc('core', 'doctype', 'page') #2013-13-26 execute:frappe.reload_doc('core', 'doctype', 'report') #2014-06-03 execute:frappe.reload_doc('core', 'doctype', 'version') #2014-02-21 @@ -94,3 +95,5 @@ frappe.patches.v6_2.ignore_user_permissions_if_missing execute:frappe.db.sql("delete from tabSessions where user is null") frappe.patches.v6_2.rename_backup_manager execute:frappe.delete_doc("DocType", "Backup Manager") +frappe.patches.v6_4.reduce_varchar_length +frappe.patches.v6_4.rename_bengali_language \ No newline at end of file diff --git a/frappe/patches/v5_3/rename_chinese_languages.py b/frappe/patches/v5_3/rename_chinese_languages.py index f70783d2cc..8bc954c04c 100644 --- a/frappe/patches/v5_3/rename_chinese_languages.py +++ b/frappe/patches/v5_3/rename_chinese_languages.py @@ -1,6 +1,7 @@ # -*- coding: utf-8 -*- from __future__ import unicode_literals import frappe +from frappe.translate import rename_language def execute(): language_map = { @@ -8,11 +9,5 @@ def execute(): "中國(繁體)": "正體中文" } - language_in_system_settings = frappe.db.get_single_value("System Settings", "language") - if language_in_system_settings in language_map: - new_language_name = language_map[language_in_system_settings] - frappe.db.set_value("System Settings", "System Settings", "language", new_language_name) - for old_name, new_name in language_map.items(): - frappe.db.sql("""update `tabUser` set language=%(new_name)s where language=%(old_name)s""", - { "old_name": old_name, "new_name": new_name }) + rename_language(old_name, new_name) diff --git a/frappe/patches/v6_4/__init__.py b/frappe/patches/v6_4/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/frappe/patches/v6_4/reduce_varchar_length.py b/frappe/patches/v6_4/reduce_varchar_length.py new file mode 100644 index 0000000000..45229769cc --- /dev/null +++ b/frappe/patches/v6_4/reduce_varchar_length.py @@ -0,0 +1,33 @@ +from __future__ import unicode_literals +import frappe + +def execute(): + for doctype in frappe.get_all("DocType", filters={"issingle": 0}): + doctype = doctype.name + + for column in frappe.db.sql("desc `tab{doctype}`".format(doctype=doctype), as_dict=True): + fieldname = column["Field"] + column_type = column["Type"] + + if not column_type.startswith("varchar"): + continue + + max_length = frappe.db.sql("""select max(length(`{fieldname}`)) from `tab{doctype}`"""\ + .format(fieldname=fieldname, doctype=doctype)) + + max_length = max_length[0][0] if max_length else None + + if max_length and max_length > 140: + print "setting length of '{fieldname}' in '{doctype}' as {length}".format( + fieldname=fieldname, doctype=doctype, length=max_length) + + # create property setter for length + frappe.make_property_setter({ + "doctype": doctype, + "fieldname": fieldname, + "property": "length", + "value": max_length, + "property_type": "Int" + }) + + frappe.clear_cache(doctype=doctype) diff --git a/frappe/patches/v6_4/rename_bengali_language.py b/frappe/patches/v6_4/rename_bengali_language.py new file mode 100644 index 0000000000..dbbcb62f8d --- /dev/null +++ b/frappe/patches/v6_4/rename_bengali_language.py @@ -0,0 +1,7 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals +import frappe +from frappe.translate import rename_language + +def execute(): + rename_language("বাঙালি", "বাংলা") \ No newline at end of file diff --git a/frappe/print/doctype/letter_head/letter_head.json b/frappe/print/doctype/letter_head/letter_head.json index b70dd49587..81e3f9132e 100644 --- a/frappe/print/doctype/letter_head/letter_head.json +++ b/frappe/print/doctype/letter_head/letter_head.json @@ -116,7 +116,7 @@ "issingle": 0, "istable": 0, "max_attachments": 3, - "modified": "2015-09-07 15:51:26", + "modified": "2015-10-02 07:38:56.001216", "modified_by": "Administrator", "module": "Print", "name": "Letter Head", diff --git a/frappe/print/doctype/print_format/print_format.json b/frappe/print/doctype/print_format/print_format.json index 019091a016..84c40b22fb 100644 --- a/frappe/print/doctype/print_format/print_format.json +++ b/frappe/print/doctype/print_format/print_format.json @@ -83,7 +83,7 @@ "ignore_user_permissions": 0, "in_filter": 1, "in_list_view": 0, - "label": "Standard", + "label": "Standard", "no_copy": 1, "oldfieldname": "standard", "oldfieldtype": "Select", @@ -153,7 +153,7 @@ "ignore_user_permissions": 0, "in_filter": 0, "in_list_view": 0, - "label": "Print Format Type", + "label": "Print Format Type", "no_copy": 0, "options": "Server\nClient", "permlevel": 0, @@ -268,7 +268,7 @@ "ignore_user_permissions": 0, "in_filter": 0, "in_list_view": 0, - "label": "Font", + "label": "Font", "no_copy": 0, "options": "Default\nArial\nHelvetica\nVerdana\nMonospace", "permlevel": 0, @@ -447,7 +447,7 @@ "issingle": 0, "istable": 0, "max_attachments": 0, - "modified": "2015-09-09 05:46:11.025962", + "modified": "2015-10-02 07:39:00.918464", "modified_by": "Administrator", "module": "Print", "name": "Print Format", diff --git a/frappe/public/js/frappe/form/control.js b/frappe/public/js/frappe/form/control.js index 011d854fed..39a90e914e 100644 --- a/frappe/public/js/frappe/form/control.js +++ b/frappe/public/js/frappe/form/control.js @@ -353,6 +353,11 @@ frappe.ui.form.ControlData = frappe.ui.form.ControlInput.extend({ .addClass("input-with-feedback form-control") .prependTo(this.input_area) + if (in_list(['Data', 'Link', 'Dynamic Link', 'Password', 'Select', 'Read Only', 'Attach', 'Attach Image'], + this.df.fieldtype)) { + this.$input.attr("maxlength", this.df.length || 140); + } + this.set_input_attributes(); this.input = this.$input.get(0); this.has_input = true; diff --git a/frappe/public/js/frappe/form/linked_with.js b/frappe/public/js/frappe/form/linked_with.js index 09c0df4871..5c777001ba 100644 --- a/frappe/public/js/frappe/form/linked_with.js +++ b/frappe/public/js/frappe/form/linked_with.js @@ -12,20 +12,13 @@ frappe.ui.form.LinkedWith = Class.extend({ if(!this.dialog) this.make_dialog(); + this.dialog.fields_dict.list.$wrapper.html('
' + + __("Loading") + '...
'); + this.dialog.show(); }, make_dialog: function() { var me = this; - this.linked_with = this.frm.meta.__linked_with; - - var links = []; - $.each(this.linked_with, function(doctype, tmp) { - if(frappe.model.can_get_report(doctype)) { - links.push({label: __(doctype), value: doctype}); - } - }); - - links = frappe.utils.sort(links, "label"); this.dialog = new frappe.ui.Dialog({ hide_on_page_refresh: true, @@ -37,49 +30,116 @@ frappe.ui.form.LinkedWith = Class.extend({ this.dialog.$wrapper.find(".modal-dialog").addClass("linked-with-dialog"); - if(!links) { - this.dialog.fields_dict.list.$wrapper.html("
" - + this.frm.doctype + ": " - + (this.linked_with ? __("Not Linked to any record.") : __("Not enough permission to see links.")) - + "
") - return; - } - this.dialog.on_page_show = function() { - me.dialog.fields_dict.list.$wrapper.html('
' - + __("Loading") + '...
'); - - frappe.call({ - method:"frappe.desk.form.utils.get_linked_docs", - args: { - doctype: me.frm.doctype, - name: me.frm.docname, - metadata_loaded: keys(locals.DocType) - }, - callback: function(r) { - var parent = me.dialog.fields_dict.list.$wrapper.empty(); - - if(keys(r.message || {}).length) { - $.each(keys(r.message).sort(), function(i, doctype) { - var listview = frappe.views.get_listview(doctype, me); - listview.no_delete = true; - - var wrapper = $('
').appendTo(parent); - $('
').html(__(doctype).bold()).appendTo(wrapper); - var body = $('
').appendTo(wrapper); - - $.each(r.message[doctype], function(i, d) { - d.doctype = doctype; - listview.render($('
') - .appendTo(body), d, me); - }) - }) - } else { - parent.html(__("Not Linked to any record.")); + // execute ajax calls sequentially + // 1. get linked doctypes + // 2. load all doctypes + // 3. load linked docs + $.when(me.get_linked_doctypes()) + .then(function() { return me.load_doctypes() }) + .then(function() { + if (me.links_not_permitted_or_missing()) { + return; } - } - }) + + return me.get_linked_docs(); + }); } }, + + load_doctypes: function() { + var me = this; + var already_loaded = Object.keys(locals.DocType); + var doctypes_to_load = []; + $.each(Object.keys(me.frm.__linked_doctypes), function(i, v) { + if (already_loaded.indexOf(v)===-1) { + doctypes_to_load.push(v); + } + }); + + // load all doctypes sequentially using with_doctype + return $.when.apply($, $.map(doctypes_to_load, function(dt) { + return frappe.model.with_doctype(dt, function() { + if (frappe.listview_settings[dt]) { + // add additional fields to __linked_doctypes + me.frm.__linked_doctypes[dt].add_fields = frappe.listview_settings[dt].add_fields; + } + }); + })); + }, + + links_not_permitted_or_missing: function() { + var me = this; + var links = []; + $.each(me.frm.__linked_doctypes, function(doctype, tmp) { + if(frappe.model.can_get_report(doctype)) { + links.push({label: __(doctype), value: doctype}); + } + }); + + links = frappe.utils.sort(links, "label"); + + if(!links) { + me.dialog.fields_dict.list.$wrapper.html("
" + + me.frm.doctype + ": " + + (me.frm.__linked_doctypes ? __("Not Linked to any record.") : __("Not enough permission to see links.")) + + "
") + return true; + } + + return false; + }, + + get_linked_doctypes: function() { + var me = this; + if (this.frm.__linked_doctypes) { + return; + } + + return frappe.call({ + method: "frappe.desk.form.linked_with.get_linked_doctypes", + args: { + doctype: this.frm.doctype + }, + callback: function(r) { + me.frm.__linked_doctypes = r.message; + } + }); + }, + + get_linked_docs: function() { + var me = this; + + return frappe.call({ + method:"frappe.desk.form.linked_with.get_linked_docs", + args: { + doctype: me.frm.doctype, + name: me.frm.docname, + linkinfo: me.frm.__linked_doctypes + }, + callback: function(r) { + var parent = me.dialog.fields_dict.list.$wrapper.empty(); + + if(keys(r.message || {}).length) { + $.each(keys(r.message).sort(), function(i, doctype) { + var listview = frappe.views.get_listview(doctype, me); + listview.no_delete = true; + + var wrapper = $('
').appendTo(parent); + $('
').html(__(doctype).bold()).appendTo(wrapper); + var body = $('
').appendTo(wrapper); + + $.each(r.message[doctype], function(i, d) { + d.doctype = doctype; + listview.render($('
') + .appendTo(body), d, me); + }) + }) + } else { + parent.html(__("Not Linked to any record.")); + } + } + }); + } }); diff --git a/frappe/public/js/frappe/model/model.js b/frappe/public/js/frappe/model/model.js index ac4d72f3e0..b4e0dad4f7 100644 --- a/frappe/public/js/frappe/model/model.js +++ b/frappe/public/js/frappe/model/model.js @@ -83,7 +83,7 @@ $.extend(frappe.model, { with_doctype: function(doctype, callback) { if(locals.DocType[doctype]) { - callback(); + callback && callback(); } else { var cached_timestamp = null; if(localStorage["_doctype:" + doctype]) { @@ -112,7 +112,7 @@ $.extend(frappe.model, { } frappe.model.init_doctype(doctype); frappe.defaults.set_user_permissions(r.user_permissions); - callback(r); + callback && callback(r); } }); } diff --git a/frappe/public/js/frappe/ui/filters/filters.js b/frappe/public/js/frappe/ui/filters/filters.js index 8688d26b77..f56689582b 100644 --- a/frappe/public/js/frappe/ui/filters/filters.js +++ b/frappe/public/js/frappe/ui/filters/filters.js @@ -57,7 +57,7 @@ frappe.ui.FilterList = Class.extend({ var filter = new frappe.ui.Filter({ flist: this, - doctype: doctype, + _doctype: doctype, fieldname: fieldname, condition: condition, value: value, @@ -168,7 +168,7 @@ frappe.ui.Filter = Class.extend({ // set the field if(me.fieldname) { // pre-sets given (could be via tags!) - this.set_values(me.doctype, me.fieldname, me.condition, me.value); + this.set_values(me._doctype, me.fieldname, me.condition, me.value); } else { me.set_field(me.doctype, 'name'); } diff --git a/frappe/public/js/frappe/ui/toolbar/awesome_bar.js b/frappe/public/js/frappe/ui/toolbar/awesome_bar.js index 721b8cefc9..8e448e0054 100644 --- a/frappe/public/js/frappe/ui/toolbar/awesome_bar.js +++ b/frappe/public/js/frappe/ui/toolbar/awesome_bar.js @@ -190,6 +190,11 @@ frappe.search.verbs = [ // doctype list function(txt) { + if (txt.toLowerCase().indexOf(" list")) { + // remove list keyword + txt = txt.replace(/ list/ig, "").trim(); + } + frappe.search.find(frappe.boot.user.can_read, txt, function(match) { if(in_list(frappe.boot.single_types, match)) { return { diff --git a/frappe/public/js/frappe/views/communication.js b/frappe/public/js/frappe/views/communication.js index 3db2d32bb0..33ddca2422 100644 --- a/frappe/public/js/frappe/views/communication.js +++ b/frappe/public/js/frappe/views/communication.js @@ -435,7 +435,7 @@ frappe.views.CommunicationComposer = Class.extend({ callback: function(r) { if(!r.exc) { if(form_values.send_email && r.message["emails_not_sent_to"]) { - msgprint( __("Email not sent to {0}", + msgprint( __("Email not sent to {0} (unsubscribed / disabled)", [ frappe.utils.escape_html(r.message["emails_not_sent_to"]) ]) ); } diff --git a/frappe/public/js/frappe/views/ganttview.js b/frappe/public/js/frappe/views/ganttview.js index 62f2b240fd..360806159f 100644 --- a/frappe/public/js/frappe/views/ganttview.js +++ b/frappe/public/js/frappe/views/ganttview.js @@ -82,7 +82,7 @@ frappe.views.Gantt = frappe.views.CalendarBase.extend({ gantt_area.gantt({ source: me.get_source(r), navigate: "scroll", - scale: "days", + scale: me.gantt_scale || "days", minScale: "hours", maxScale: "months", itemsPerPage: 20, diff --git a/frappe/sessions.py b/frappe/sessions.py index a9ca0ce447..85786cd0a2 100644 --- a/frappe/sessions.py +++ b/frappe/sessions.py @@ -32,7 +32,7 @@ def clear_cache(user=None): cache = frappe.cache() groups = ("bootinfo", "user_recent", "user_roles", "user_doc", "lang", - "defaults", "user_permissions", "roles", "home_page") + "defaults", "user_permissions", "roles", "home_page", "linked_with") if user: for name in groups: diff --git a/frappe/tasks.py b/frappe/tasks.py index ada78f7b08..dfbc607a2c 100644 --- a/frappe/tasks.py +++ b/frappe/tasks.py @@ -186,10 +186,13 @@ def run_async_task(self, site=None, user=None, cmd=None, form_dict=None, hijack_ @celery_task() def sendmail(site, communication_name, print_html=None, print_format=None, attachments=None, - recipients=None, cc=None): + recipients=None, cc=None, lang=None): try: frappe.connect(site=site) + if lang: + frappe.local.lang = lang + # upto 3 retries for i in xrange(3): try: diff --git a/frappe/templates/emails/standard.html b/frappe/templates/emails/standard.html index fa8981a37b..4a9cf795bb 100644 --- a/frappe/templates/emails/standard.html +++ b/frappe/templates/emails/standard.html @@ -8,6 +8,7 @@
+ {{ content }} {{ signature }}
diff --git a/frappe/tests/test_document.py b/frappe/tests/test_document.py index 7a33026e4a..995103376a 100644 --- a/frappe/tests/test_document.py +++ b/frappe/tests/test_document.py @@ -150,3 +150,9 @@ class TestDocument(unittest.TestCase): d.load_from_db() d.starts_on = "2014-01-01" d.validate_update_after_submit() + + def test_varchar_length(self): + d = self.test_insert() + d.subject = "abcde"*100 + self.assertRaises(frappe.CharacterLengthExceededError, d.save) + diff --git a/frappe/translate.py b/frappe/translate.py index 89a257382c..8e8ec88a44 100644 --- a/frappe/translate.py +++ b/frappe/translate.py @@ -529,3 +529,11 @@ def deduplicate_messages(messages): def get_bench_dir(): return os.path.join(frappe.__file__, '..', '..', '..', '..') + +def rename_language(old_name, new_name): + language_in_system_settings = frappe.db.get_single_value("System Settings", "language") + if language_in_system_settings == old_name: + frappe.db.set_value("System Settings", "System Settings", "language", new_name) + + frappe.db.sql("""update `tabUser` set language=%(new_name)s where language=%(old_name)s""", + { "old_name": old_name, "new_name": new_name }) \ No newline at end of file diff --git a/frappe/utils/data.py b/frappe/utils/data.py index 07a032908e..9ad4afdfc7 100644 --- a/frappe/utils/data.py +++ b/frappe/utils/data.py @@ -513,6 +513,9 @@ def get_url(uri=None, full_address=False): """get app url from request""" host_name = frappe.local.conf.host_name + if uri and (uri.startswith("http://") or uri.startswith("https://")): + return uri + if not host_name: if hasattr(frappe.local, "request") and frappe.local.request and frappe.local.request.host: protocol = 'https' == frappe.get_request_header('X-Forwarded-Proto', "") and 'https://' or 'http://' @@ -538,10 +541,16 @@ def get_url(uri=None, full_address=False): def get_host_name(): return get_url().rsplit("//", 1)[-1] -def get_url_to_form(doctype, name, label=None): +def get_link_to_form(doctype, name, label=None): if not label: label = name - return """%(label)s""" % locals() + return """{1}""".format(get_url_to_form(doctype, name), label) + +def get_url_to_form(doctype, name): + return get_url(uri = "desk/#Form/{0}/{1}".format(doctype, name)) + +def get_url_to_list(doctype): + return get_url(uri = "desk/#List/{0}".format(doctype)) operator_map = { # startswith diff --git a/frappe/utils/file_manager.py b/frappe/utils/file_manager.py index 6b62b0bd54..68c93f5f56 100644 --- a/frappe/utils/file_manager.py +++ b/frappe/utils/file_manager.py @@ -10,6 +10,7 @@ from frappe.utils import get_site_path, get_hook_method, get_files_path, random_ from frappe import _ from frappe import conf from copy import copy +import urllib class MaxFileSizeReachedError(frappe.ValidationError): pass @@ -59,6 +60,8 @@ def save_url(file_url, dt, dn, folder): # frappe.msgprint("URL must start with 'http://' or 'https://'") # return None, None + file_url = urllib.unquote(file_url) + f = frappe.get_doc({ "doctype": "File", "file_url": file_url, @@ -241,22 +244,30 @@ def remove_file(fid, attached_to_doctype=None, attached_to_name=None): return comment -def delete_file_data_content(doc): +def delete_file_data_content(doc, only_thumbnail=False): method = get_hook_method('delete_file_data_content', fallback=delete_file_from_filesystem) - method(doc) + method(doc, only_thumbnail=only_thumbnail) -def delete_file_from_filesystem(doc): - path = doc.file_name - - if path.startswith("files/"): - path = frappe.utils.get_site_path("public", doc.file_name) +def delete_file_from_filesystem(doc, only_thumbnail=False): + """Delete file, thumbnail from File document""" + if only_thumbnail: + delete_file(doc.thumbnail_url) else: - path = frappe.utils.get_site_path("public", "files", doc.file_name) + delete_file(doc.file_url) + delete_file(doc.thumbnail_url) - path = encode(path) +def delete_file(path): + """Delete file from `public folder`""" + if path and path.startswith("/files/"): + parts = os.path.split(path) + path = frappe.utils.get_site_path("public", "files", parts[-1]) - if os.path.exists(path): - os.remove(path) + if "/../" in path: + frappe.msgprint(_("It is risky to delete this file: {0}. Please contact your System Manager.").format(path)) + + path = encode(path) + if os.path.exists(path): + os.remove(path) def get_file(fname): f = frappe.db.sql("""select file_name from `tabFile` diff --git a/frappe/utils/redis_wrapper.py b/frappe/utils/redis_wrapper.py index 7d5cd9ed0c..bcaeae1289 100644 --- a/frappe/utils/redis_wrapper.py +++ b/frappe/utils/redis_wrapper.py @@ -147,4 +147,3 @@ class RedisWrapper(redis.Redis): return super(redis.Redis, self).hkeys(self.make_key(name)) except redis.exceptions.ConnectionError: return [] - diff --git a/frappe/website/doctype/about_us_team_member/about_us_team_member.json b/frappe/website/doctype/about_us_team_member/about_us_team_member.json index f1bc781c7e..bc3da3a3db 100644 --- a/frappe/website/doctype/about_us_team_member/about_us_team_member.json +++ b/frappe/website/doctype/about_us_team_member/about_us_team_member.json @@ -83,7 +83,7 @@ "is_submittable": 0, "issingle": 0, "istable": 1, - "modified": "2015-02-19 09:29:46.804175", + "modified": "2015-10-19 03:04:52.537466", "modified_by": "Administrator", "module": "Website", "name": "About Us Team Member", diff --git a/frappe/website/doctype/blog_category/blog_category.json b/frappe/website/doctype/blog_category/blog_category.json index 5d442ec67b..06c51c2945 100644 --- a/frappe/website/doctype/blog_category/blog_category.json +++ b/frappe/website/doctype/blog_category/blog_category.json @@ -126,7 +126,7 @@ "is_submittable": 0, "issingle": 0, "istable": 0, - "modified": "2015-09-11 12:20:05.555186", + "modified": "2015-10-02 07:38:39.540340", "modified_by": "Administrator", "module": "Website", "name": "Blog Category", diff --git a/frappe/website/doctype/blog_post/blog_post.json b/frappe/website/doctype/blog_post/blog_post.json index f166fc076f..b409d68141 100644 --- a/frappe/website/doctype/blog_post/blog_post.json +++ b/frappe/website/doctype/blog_post/blog_post.json @@ -272,7 +272,7 @@ "issingle": 0, "istable": 0, "max_attachments": 5, - "modified": "2015-09-11 12:19:54.226902", + "modified": "2015-10-02 07:38:39.632512", "modified_by": "Administrator", "module": "Website", "name": "Blog Post", diff --git a/frappe/website/doctype/blogger/blogger.json b/frappe/website/doctype/blogger/blogger.json index a862f754e6..ca98bc7690 100644 --- a/frappe/website/doctype/blogger/blogger.json +++ b/frappe/website/doctype/blogger/blogger.json @@ -171,7 +171,7 @@ "issingle": 0, "istable": 0, "max_attachments": 1, - "modified": "2015-09-07 15:51:26", + "modified": "2015-10-19 03:04:50.241951", "modified_by": "Administrator", "module": "Website", "name": "Blogger", diff --git a/frappe/website/doctype/company_history/company_history.json b/frappe/website/doctype/company_history/company_history.json index f93ababa76..210801bd63 100644 --- a/frappe/website/doctype/company_history/company_history.json +++ b/frappe/website/doctype/company_history/company_history.json @@ -60,7 +60,7 @@ "is_submittable": 0, "issingle": 0, "istable": 1, - "modified": "2013-12-20 19:23:01", + "modified": "2015-10-02 07:38:42.281395", "modified_by": "Administrator", "module": "Website", "name": "Company History", diff --git a/frappe/website/doctype/top_bar_item/top_bar_item.json b/frappe/website/doctype/top_bar_item/top_bar_item.json index 6a2b4828a9..c4a6d581ff 100644 --- a/frappe/website/doctype/top_bar_item/top_bar_item.json +++ b/frappe/website/doctype/top_bar_item/top_bar_item.json @@ -87,7 +87,7 @@ "ignore_user_permissions": 0, "in_filter": 0, "in_list_view": 0, - "label": "Target", + "label": "Target", "no_copy": 0, "options": "\ntarget = \"_blank\"", "permlevel": 0, @@ -130,7 +130,7 @@ "is_submittable": 0, "issingle": 0, "istable": 1, - "modified": "2015-07-07 07:06:26.632888", + "modified": "2015-10-02 07:39:17.448972", "modified_by": "Administrator", "module": "Website", "name": "Top Bar Item", diff --git a/frappe/website/doctype/web_form/web_form.json b/frappe/website/doctype/web_form/web_form.json index 1735313293..2b1d8f4727 100644 --- a/frappe/website/doctype/web_form/web_form.json +++ b/frappe/website/doctype/web_form/web_form.json @@ -431,7 +431,7 @@ "is_submittable": 0, "issingle": 0, "istable": 0, - "modified": "2015-09-11 12:20:17.264419", + "modified": "2015-10-02 07:39:18.834336", "modified_by": "Administrator", "module": "Website", "name": "Web Form", diff --git a/frappe/website/doctype/web_form_field/web_form_field.json b/frappe/website/doctype/web_form_field/web_form_field.json index dcf14d258c..8178a987f9 100644 --- a/frappe/website/doctype/web_form_field/web_form_field.json +++ b/frappe/website/doctype/web_form_field/web_form_field.json @@ -39,7 +39,7 @@ "ignore_user_permissions": 0, "in_filter": 0, "in_list_view": 1, - "label": "Fieldtype", + "label": "Fieldtype", "no_copy": 0, "options": "Attach\nCheck\nData\nDate\nDatetime\nHTML\nSelect\nText\nSection Break\nColumn Break", "permlevel": 0, @@ -266,7 +266,7 @@ "is_submittable": 0, "issingle": 0, "istable": 1, - "modified": "2015-06-03 06:45:30.240450", + "modified": "2015-10-02 07:39:19.006591", "modified_by": "Administrator", "module": "Website", "name": "Web Form Field", diff --git a/frappe/website/doctype/web_page/web_page.json b/frappe/website/doctype/web_page/web_page.json index 17ea6333fd..b13fa917f9 100644 --- a/frappe/website/doctype/web_page/web_page.json +++ b/frappe/website/doctype/web_page/web_page.json @@ -410,7 +410,7 @@ "ignore_user_permissions": 0, "in_filter": 0, "in_list_view": 0, - "label": "Text Align", + "label": "Text Align", "no_copy": 0, "options": "Left\nCenter\nRight", "permlevel": 0, @@ -608,7 +608,7 @@ "issingle": 0, "istable": 0, "max_attachments": 20, - "modified": "2015-09-11 12:19:37.342904", + "modified": "2015-10-02 07:39:19.171402", "modified_by": "Administrator", "module": "Website", "name": "Web Page", diff --git a/frappe/website/doctype/website_settings/website_settings.json b/frappe/website/doctype/website_settings/website_settings.json index 0db94fe630..3ef204feb6 100644 --- a/frappe/website/doctype/website_settings/website_settings.json +++ b/frappe/website/doctype/website_settings/website_settings.json @@ -867,7 +867,7 @@ "issingle": 1, "istable": 0, "max_attachments": 10, - "modified": "2015-08-27 03:40:44.227153", + "modified": "2015-10-19 03:04:48.520048", "modified_by": "Administrator", "module": "Website", "name": "Website Settings", diff --git a/frappe/website/doctype/website_slideshow/test_website_slideshow.py b/frappe/website/doctype/website_slideshow/test_website_slideshow.py new file mode 100644 index 0000000000..9eccc71ad3 --- /dev/null +++ b/frappe/website/doctype/website_slideshow/test_website_slideshow.py @@ -0,0 +1,12 @@ +# -*- coding: utf-8 -*- +# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors +# See license.txt +from __future__ import unicode_literals + +import frappe +import unittest + +# test_records = frappe.get_test_records('Website Slideshow') + +class TestWebsiteSlideshow(unittest.TestCase): + pass diff --git a/frappe/website/doctype/website_slideshow/website_slideshow.json b/frappe/website/doctype/website_slideshow/website_slideshow.json index 47fca929ca..67c9048b9d 100644 --- a/frappe/website/doctype/website_slideshow/website_slideshow.json +++ b/frappe/website/doctype/website_slideshow/website_slideshow.json @@ -111,7 +111,7 @@ "issingle": 0, "istable": 0, "max_attachments": 10, - "modified": "2015-07-28 16:18:13.013029", + "modified": "2015-10-02 07:39:19.477260", "modified_by": "Administrator", "module": "Website", "name": "Website Slideshow", diff --git a/frappe/website/doctype/website_slideshow_item/website_slideshow_item.json b/frappe/website/doctype/website_slideshow_item/website_slideshow_item.json index ac3714bb8d..d9f4554994 100644 --- a/frappe/website/doctype/website_slideshow_item/website_slideshow_item.json +++ b/frappe/website/doctype/website_slideshow_item/website_slideshow_item.json @@ -85,7 +85,7 @@ "issingle": 0, "istable": 1, "max_attachments": 10, - "modified": "2015-02-19 09:27:05.003437", + "modified": "2015-10-19 03:04:52.486465", "modified_by": "Administrator", "module": "Website", "name": "Website Slideshow Item", diff --git a/frappe/website/doctype/website_theme/website_theme.json b/frappe/website/doctype/website_theme/website_theme.json index f84e20972e..e1de23fc0b 100644 --- a/frappe/website/doctype/website_theme/website_theme.json +++ b/frappe/website/doctype/website_theme/website_theme.json @@ -643,7 +643,7 @@ "is_submittable": 0, "issingle": 0, "istable": 0, - "modified": "2015-09-14 02:56:01.143058", + "modified": "2015-10-19 03:04:48.248634", "modified_by": "Administrator", "module": "Website", "name": "Website Theme", diff --git a/frappe/workflow/doctype/workflow/workflow.json b/frappe/workflow/doctype/workflow/workflow.json index 52f53ca4fd..e3c9198750 100644 --- a/frappe/workflow/doctype/workflow/workflow.json +++ b/frappe/workflow/doctype/workflow/workflow.json @@ -199,7 +199,7 @@ "is_submittable": 0, "issingle": 0, "istable": 0, - "modified": "2015-09-14 02:56:01.362929", + "modified": "2015-10-02 07:39:19.926848", "modified_by": "Administrator", "module": "Workflow", "name": "Workflow", diff --git a/frappe/workflow/doctype/workflow_action/test_workflow_action.py b/frappe/workflow/doctype/workflow_action/test_workflow_action.py new file mode 100644 index 0000000000..d70ee9151b --- /dev/null +++ b/frappe/workflow/doctype/workflow_action/test_workflow_action.py @@ -0,0 +1,12 @@ +# -*- coding: utf-8 -*- +# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors +# See license.txt +from __future__ import unicode_literals + +import frappe +import unittest + +# test_records = frappe.get_test_records('Workflow Action') + +class TestWorkflowAction(unittest.TestCase): + pass diff --git a/frappe/workflow/doctype/workflow_action/workflow_action.json b/frappe/workflow/doctype/workflow_action/workflow_action.json index c6509435c2..6463bd4a9e 100644 --- a/frappe/workflow/doctype/workflow_action/workflow_action.json +++ b/frappe/workflow/doctype/workflow_action/workflow_action.json @@ -40,7 +40,7 @@ "is_submittable": 0, "issingle": 0, "istable": 0, - "modified": "2015-02-05 05:12:45.535606", + "modified": "2015-10-02 07:39:20.028302", "modified_by": "Administrator", "module": "Workflow", "name": "Workflow Action", diff --git a/frappe/workflow/doctype/workflow_document_state/workflow_document_state.json b/frappe/workflow/doctype/workflow_document_state/workflow_document_state.json index c9ca6a3cd5..c2762b0985 100644 --- a/frappe/workflow/doctype/workflow_document_state/workflow_document_state.json +++ b/frappe/workflow/doctype/workflow_document_state/workflow_document_state.json @@ -44,7 +44,7 @@ "ignore_user_permissions": 0, "in_filter": 0, "in_list_view": 1, - "label": "Doc Status", + "label": "Doc Status", "no_copy": 0, "options": "0\n1\n2", "permlevel": 0, @@ -156,7 +156,7 @@ "is_submittable": 0, "issingle": 0, "istable": 1, - "modified": "2015-07-28 16:18:13.257862", + "modified": "2015-10-02 07:39:20.102069", "modified_by": "Administrator", "module": "Workflow", "name": "Workflow Document State", diff --git a/frappe/workflow/doctype/workflow_state/workflow_state.json b/frappe/workflow/doctype/workflow_state/workflow_state.json index a464da250b..c756f029f1 100644 --- a/frappe/workflow/doctype/workflow_state/workflow_state.json +++ b/frappe/workflow/doctype/workflow_state/workflow_state.json @@ -42,7 +42,7 @@ "ignore_user_permissions": 0, "in_filter": 0, "in_list_view": 0, - "label": "Icon", + "label": "Icon", "no_copy": 0, "options": "\nglass\nmusic\nsearch\nenvelope\nheart\nstar\nstar-empty\nuser\nfilm\nth-large\nth\nth-list\nok\nremove\nzoom-in\nzoom-out\noff\nsignal\ncog\ntrash\nhome\nfile\ntime\nroad\ndownload-alt\ndownload\nupload\ninbox\nplay-circle\nrepeat\nrefresh\nlist-alt\nlock\nflag\nheadphones\nvolume-off\nvolume-down\nvolume-up\nqrcode\nbarcode\ntag\ntags\nbook\nbookmark\nprint\ncamera\nfont\nbold\nitalic\ntext-height\ntext-width\nalign-left\nalign-center\nalign-right\nalign-justify\nlist\nindent-left\nindent-right\nfacetime-video\npicture\npencil\nmap-marker\nadjust\ntint\nedit\nshare\ncheck\nmove\nstep-backward\nfast-backward\nbackward\nplay\npause\nstop\nforward\nfast-forward\nstep-forward\neject\nchevron-left\nchevron-right\nplus-sign\nminus-sign\nremove-sign\nok-sign\nquestion-sign\ninfo-sign\nscreenshot\nremove-circle\nok-circle\nban-circle\narrow-left\narrow-right\narrow-up\narrow-down\nshare-alt\nresize-full\nresize-small\nplus\nminus\nasterisk\nexclamation-sign\ngift\nleaf\nfire\neye-open\neye-close\nwarning-sign\nplane\ncalendar\nrandom\ncomment\nmagnet\nchevron-up\nchevron-down\nretweet\nshopping-cart\nfolder-close\nfolder-open\nresize-vertical\nresize-horizontal\nhdd\nbullhorn\nbell\ncertificate\nthumbs-up\nthumbs-down\nhand-right\nhand-left\nhand-up\nhand-down\ncircle-arrow-right\ncircle-arrow-left\ncircle-arrow-up\ncircle-arrow-down\nglobe\nwrench\ntasks\nfilter\nbriefcase\nfullscreen", "permlevel": 0, @@ -65,7 +65,7 @@ "ignore_user_permissions": 0, "in_filter": 0, "in_list_view": 0, - "label": "Style", + "label": "Style", "no_copy": 0, "options": "\nPrimary\nInfo\nSuccess\nWarning\nDanger\nInverse", "permlevel": 0, @@ -87,7 +87,7 @@ "is_submittable": 0, "issingle": 0, "istable": 0, - "modified": "2015-07-28 16:18:13.320514", + "modified": "2015-10-02 07:39:20.222387", "modified_by": "Administrator", "module": "Workflow", "name": "Workflow State", diff --git a/frappe/workflow/doctype/workflow_transition/workflow_transition.json b/frappe/workflow/doctype/workflow_transition/workflow_transition.json index bcbce218b1..bd694ec74e 100644 --- a/frappe/workflow/doctype/workflow_transition/workflow_transition.json +++ b/frappe/workflow/doctype/workflow_transition/workflow_transition.json @@ -113,7 +113,7 @@ "is_submittable": 0, "issingle": 0, "istable": 1, - "modified": "2013-12-20 19:21:55.000001", + "modified": "2015-10-02 07:39:20.308052", "modified_by": "Administrator", "module": "Workflow", "name": "Workflow Transition", diff --git a/requirements.txt b/requirements.txt index 1777583ba0..41bbfb8b6a 100644 --- a/requirements.txt +++ b/requirements.txt @@ -30,3 +30,4 @@ click num2words watchdog==0.8.0 bleach +Pillow diff --git a/setup.py b/setup.py index 78bbcbe458..f50925a4ae 100644 --- a/setup.py +++ b/setup.py @@ -1,6 +1,6 @@ from setuptools import setup, find_packages -version = "6.4.9" +version = "6.5.0" with open("requirements.txt", "r") as f: install_requires = f.readlines()