@@ -96,9 +96,9 @@ def init(site, sites_path=None): | |||
local.site_path = os.path.join(sites_path, site) | |||
local.message_log = [] | |||
local.debug_log = [] | |||
local.response = _dict({}) | |||
local.lang = "en" | |||
local.request_method = request.method if request else None | |||
local.response = _dict({"docs":[]}) | |||
local.conf = _dict(get_site_config()) | |||
local.initialised = True | |||
local.flags = _dict({}) | |||
@@ -115,6 +115,15 @@ def init(site, sites_path=None): | |||
setup_module_map() | |||
def connect(site=None, db_name=None): | |||
from database import Database | |||
if site: | |||
init(site) | |||
local.db = Database(user=db_name or local.conf.db_name) | |||
local.form_dict = _dict() | |||
local.session = _dict() | |||
set_user("Administrator") | |||
def get_site_config(sites_path=None, site_path=None): | |||
config = {} | |||
@@ -200,16 +209,6 @@ def throw(msg, exc=ValidationError): | |||
def create_folder(path): | |||
if not os.path.exists(path): os.makedirs(path) | |||
def connect(site=None, db_name=None): | |||
from database import Database | |||
if site: | |||
init(site) | |||
local.db = Database(user=db_name or local.conf.db_name) | |||
local.response = _dict() | |||
local.form_dict = _dict() | |||
local.session = _dict() | |||
set_user("Administrator") | |||
def set_user(username): | |||
from frappe.utils.user import User | |||
local.session["user"] = username | |||
@@ -65,9 +65,6 @@ def get_bootinfo(): | |||
for method in hooks.boot_session or []: | |||
frappe.get_attr(method)(bootinfo) | |||
from frappe.model.utils import compress | |||
bootinfo['docs'] = compress(bootinfo['docs']) | |||
if bootinfo.lang: | |||
bootinfo.lang = unicode(bootinfo.lang) | |||
@@ -138,10 +135,10 @@ def add_home_page(bootinfo, doclist): | |||
home_page = frappe.get_application_home_page(frappe.session.user) | |||
try: | |||
page_doclist = frappe.widgets.page.get(home_page) | |||
page = frappe.widgets.page.get(home_page) | |||
except (frappe.DoesNotExistError, frappe.PermissionError), e: | |||
page_doclist = frappe.widgets.page.get('desktop') | |||
bootinfo['home_page_html'] = page_doclist[0].content | |||
bootinfo['home_page'] = page_doclist[0].name | |||
doclist += page_doclist | |||
frappe.message_log.pop() | |||
page = frappe.widgets.page.get('desktop') | |||
bootinfo['home_page'] = page.name | |||
doclist.append(page) |
@@ -9,23 +9,20 @@ import os | |||
from frappe.utils import now, cint | |||
from frappe.model import no_value_fields | |||
from frappe.model.document import Document | |||
class DocType: | |||
def __init__(self, doc=None, doclist=[]): | |||
self.doc = doc | |||
self.doclist = doclist | |||
class DocType(Document): | |||
def validate(self): | |||
if not frappe.conf.get("developer_mode"): | |||
frappe.throw("Not in Developer Mode! Set in site_config.json") | |||
for c in [".", "/", "#", "&", "=", ":", "'", '"']: | |||
if c in self.doc.name: | |||
if c in self.name: | |||
frappe.msgprint(c + " not allowed in name", raise_exception=1) | |||
self.validate_series() | |||
self.scrub_field_names() | |||
self.validate_title_field() | |||
validate_fields(self.doclist.get({"doctype":"DocField"})) | |||
validate_permissions(self.doclist.get({"doctype":"DocPerm"})) | |||
validate_fields(self.get("fields")) | |||
validate_permissions(self.get("permissions")) | |||
self.make_amendable() | |||
self.check_link_replacement_error() | |||
@@ -33,14 +30,14 @@ class DocType: | |||
if frappe.flags.in_import: | |||
return | |||
parent_list = frappe.db.sql("""SELECT parent | |||
from tabDocField where fieldtype="Table" and options=%s""", self.doc.name) | |||
from tabDocField where fieldtype="Table" and options=%s""", self.name) | |||
for p in parent_list: | |||
frappe.db.sql('UPDATE tabDocType SET modified=%s WHERE `name`=%s', (now(), p[0])) | |||
def scrub_field_names(self): | |||
restricted = ('name','parent','idx','owner','creation','modified','modified_by', | |||
'parentfield','parenttype',"file_list") | |||
for d in self.doclist: | |||
for d in self.get("fields"): | |||
if d.parent and d.fieldtype: | |||
if (not d.fieldname): | |||
if d.label: | |||
@@ -52,16 +49,16 @@ class DocType: | |||
def validate_title_field(self): | |||
if self.doc.title_field and \ | |||
self.doc.title_field not in [d.fieldname for d in self.doclist.get({"doctype":"DocField"})]: | |||
if self.title_field and \ | |||
self.title_field not in [d.fieldname for d in self.get("fields")]: | |||
frappe.throw(_("Title field must be a valid fieldname")) | |||
def validate_series(self, autoname=None, name=None): | |||
if not autoname: autoname = self.doc.autoname | |||
if not name: name = self.doc.name | |||
if not autoname: autoname = self.autoname | |||
if not name: name = self.name | |||
if not autoname and self.doclist.get({"fieldname":"naming_series"}): | |||
self.doc.autoname = "naming_series:" | |||
if not autoname and self.get("fields", {"fieldname":"naming_series"}): | |||
self.autoname = "naming_series:" | |||
if autoname and (not autoname.startswith('field:')) and (not autoname.startswith('eval:')) \ | |||
and (not autoname=='Prompt') and (not autoname.startswith('naming_series:')): | |||
@@ -72,10 +69,10 @@ class DocType: | |||
def on_update(self): | |||
from frappe.model.db_schema import updatedb | |||
updatedb(self.doc.name) | |||
updatedb(self.name) | |||
self.change_modified_of_parent() | |||
make_module_and_roles(self.doclist) | |||
make_module_and_roles(self) | |||
from frappe import conf | |||
if (not frappe.flags.in_import) and conf.get('developer_mode') or 0: | |||
@@ -83,53 +80,53 @@ class DocType: | |||
self.make_controller_template() | |||
# update index | |||
if not self.doc.custom: | |||
if not self.custom: | |||
from frappe.model.code import load_doctype_module | |||
module = load_doctype_module( self.doc.name, self.doc.module) | |||
module = load_doctype_module( self.name, self.module) | |||
if hasattr(module, "on_doctype_update"): | |||
module.on_doctype_update() | |||
frappe.clear_cache(doctype=self.doc.name) | |||
frappe.clear_cache(doctype=self.name) | |||
def check_link_replacement_error(self): | |||
for d in self.doclist.get({"doctype":"DocField", "fieldtype":"Select"}): | |||
for d in self.get("fields", {"fieldtype":"Select"}): | |||
if (frappe.db.get_value("DocField", d.name, "options") or "").startswith("link:") \ | |||
and not d.options.startswith("link:"): | |||
frappe.msgprint("link: type Select fields are getting replaced. Please check for %s" % d.label, | |||
raise_exception=True) | |||
def on_trash(self): | |||
frappe.db.sql("delete from `tabCustom Field` where dt = %s", self.doc.name) | |||
frappe.db.sql("delete from `tabCustom Script` where dt = %s", self.doc.name) | |||
frappe.db.sql("delete from `tabProperty Setter` where doc_type = %s", self.doc.name) | |||
frappe.db.sql("delete from `tabReport` where ref_doctype=%s", self.doc.name) | |||
frappe.db.sql("delete from `tabCustom Field` where dt = %s", self.name) | |||
frappe.db.sql("delete from `tabCustom Script` where dt = %s", self.name) | |||
frappe.db.sql("delete from `tabProperty Setter` where doc_type = %s", self.name) | |||
frappe.db.sql("delete from `tabReport` where ref_doctype=%s", self.name) | |||
def before_rename(self, old, new, merge=False): | |||
if merge: | |||
frappe.throw(_("DocType can not be merged")) | |||
def after_rename(self, old, new, merge=False): | |||
if self.doc.issingle: | |||
if self.issingle: | |||
frappe.db.sql("""update tabSingles set doctype=%s where doctype=%s""", (new, old)) | |||
else: | |||
frappe.db.sql("rename table `tab%s` to `tab%s`" % (old, new)) | |||
def export_doc(self): | |||
from frappe.modules.export_file import export_to_files | |||
export_to_files(record_list=[['DocType', self.doc.name]]) | |||
export_to_files(record_list=[['DocType', self.name]]) | |||
def import_doc(self): | |||
from frappe.modules.import_module import import_from_files | |||
import_from_files(record_list=[[self.doc.module, 'doctype', self.doc.name]]) | |||
import_from_files(record_list=[[self.module, 'doctype', self.name]]) | |||
def make_controller_template(self): | |||
from frappe.modules import get_doc_path, get_module_path, scrub | |||
pypath = os.path.join(get_doc_path(self.doc.module, | |||
self.doc.doctype, self.doc.name), scrub(self.doc.name) + '.py') | |||
pypath = os.path.join(get_doc_path(self.module, | |||
self.doctype, self.name), scrub(self.name) + '.py') | |||
if not os.path.exists(pypath): | |||
# get app publisher for copyright | |||
app = frappe.local.module_app[frappe.scrub(self.doc.module)] | |||
app = frappe.local.module_app[frappe.scrub(self.module)] | |||
if not app: | |||
frappe.throw("App not found!") | |||
app_publisher = frappe.get_hooks(hook="app_publisher", app_name=app)[0] | |||
@@ -143,23 +140,22 @@ class DocType: | |||
""" | |||
if is_submittable is set, add amended_from docfields | |||
""" | |||
if self.doc.is_submittable: | |||
if self.is_submittable: | |||
if not frappe.db.sql("""select name from tabDocField | |||
where fieldname = 'amended_from' and parent = %s""", self.doc.name): | |||
new = self.doc.addchild('fields', 'DocField', self.doclist) | |||
new.label = 'Amended From' | |||
new.fieldtype = 'Link' | |||
new.fieldname = 'amended_from' | |||
new.options = self.doc.name | |||
new.permlevel = 0 | |||
new.read_only = 1 | |||
new.print_hide = 1 | |||
new.no_copy = 1 | |||
new.idx = self.get_max_idx() + 1 | |||
where fieldname = 'amended_from' and parent = %s""", self.name): | |||
self.append("fields", { | |||
"label": "Amended From", | |||
"fieldtype": "Link", | |||
"fieldname": "amended_from", | |||
"options": self.name, | |||
"read_only": 1, | |||
"print_hide": 1, | |||
"no_copy": 1 | |||
}) | |||
def get_max_idx(self): | |||
max_idx = frappe.db.sql("""select max(idx) from `tabDocField` where parent = %s""", | |||
self.doc.name) | |||
self.name) | |||
return max_idx and max_idx[0][0] or 0 | |||
def validate_fields_for_doctype(doctype): | |||
@@ -329,14 +325,14 @@ def validate_permissions(permissions, for_remove=False): | |||
check_level_zero_is_set(d) | |||
remove_rights_for_single(d) | |||
def make_module_and_roles(doclist, perm_doctype="DocPerm"): | |||
def make_module_and_roles(doc, perm_fieldname="permissions"): | |||
try: | |||
if not frappe.db.exists("Module Def", doclist[0].module): | |||
m = frappe.bean({"doctype": "Module Def", "module_name": doclist[0].module}) | |||
if not frappe.db.exists("Module Def", doc.module): | |||
m = frappe.bean({"doctype": "Module Def", "module_name": doc.module}) | |||
m.insert() | |||
default_roles = ["Administrator", "Guest", "All"] | |||
roles = [p.role for p in doclist.get({"doctype": perm_doctype})] + default_roles | |||
roles = [p.role for p in doc.get(permissions)] + default_roles | |||
for role in list(set(roles)): | |||
if not frappe.db.exists("Role", role): | |||
@@ -3,11 +3,9 @@ | |||
from __future__ import unicode_literals | |||
import frappe | |||
from frappe.model.document import Document | |||
class DocType: | |||
def __init__(self, d, dl): | |||
self.doc, self.doclist = d,dl | |||
class Page(Document): | |||
def autoname(self): | |||
""" | |||
Creates a url friendly name for this page. | |||
@@ -15,17 +13,17 @@ class DocType: | |||
it will add name-1, name-2 etc. | |||
""" | |||
from frappe.utils import cint | |||
if (self.doc.name and self.doc.name.startswith('New Page')) or not self.doc.name: | |||
self.doc.name = self.doc.page_name.lower().replace('"','').replace("'",'').\ | |||
if (self.name and self.name.startswith('New Page')) or not self.name: | |||
self.name = self.page_name.lower().replace('"','').replace("'",'').\ | |||
replace(' ', '-')[:20] | |||
if frappe.db.exists('Page',self.doc.name): | |||
if frappe.db.exists('Page',self.name): | |||
cnt = frappe.db.sql("""select name from tabPage | |||
where name like "%s-%%" order by name desc limit 1""" % self.doc.name) | |||
where name like "%s-%%" order by name desc limit 1""" % self.name) | |||
if cnt: | |||
cnt = cint(cnt[0][0].split('-')[-1]) + 1 | |||
else: | |||
cnt = 1 | |||
self.doc.name += '-' + str(cnt) | |||
self.name += '-' + str(cnt) | |||
# export | |||
def on_update(self): | |||
@@ -35,16 +33,16 @@ class DocType: | |||
""" | |||
from frappe import conf | |||
from frappe.core.doctype.doctype.doctype import make_module_and_roles | |||
make_module_and_roles(self.doclist, "Page Role") | |||
make_module_and_roles(self, "roles") | |||
if not frappe.flags.in_import and getattr(conf,'developer_mode', 0) and self.doc.standard=='Yes': | |||
if not frappe.flags.in_import and getattr(conf,'developer_mode', 0) and self.standard=='Yes': | |||
from frappe.modules.export_file import export_to_files | |||
from frappe.modules import get_module_path, scrub | |||
import os | |||
export_to_files(record_list=[['Page', self.doc.name]]) | |||
export_to_files(record_list=[['Page', self.name]]) | |||
# write files | |||
path = os.path.join(get_module_path(self.doc.module), 'page', scrub(self.doc.name), scrub(self.doc.name)) | |||
path = os.path.join(get_module_path(self.module), 'page', scrub(self.name), scrub(self.name)) | |||
# js | |||
if not os.path.exists(path + '.js'): | |||
@@ -55,35 +53,39 @@ class DocType: | |||
title: '%s', | |||
single_column: true | |||
}); | |||
}""" % (self.doc.name, self.doc.title)) | |||
}""" % (self.name, self.title)) | |||
def get_from_files(self): | |||
""" | |||
Loads page info from files in module | |||
""" | |||
def as_dict(self): | |||
d = super(Page, self).as_dict() | |||
for key in ("script", "style", "content"): | |||
d[key] = self.get(key) | |||
return d | |||
def load_assets(self): | |||
from frappe.modules import get_module_path, scrub | |||
import os | |||
path = os.path.join(get_module_path(self.doc.module), 'page', scrub(self.doc.name)) | |||
path = os.path.join(get_module_path(self.module), 'page', scrub(self.name)) | |||
# script | |||
fpath = os.path.join(path, scrub(self.doc.name) + '.js') | |||
fpath = os.path.join(path, scrub(self.name) + '.js') | |||
if os.path.exists(fpath): | |||
with open(fpath, 'r') as f: | |||
self.doc.script = f.read() | |||
self.script = f.read() | |||
# css | |||
fpath = os.path.join(path, scrub(self.doc.name) + '.css') | |||
fpath = os.path.join(path, scrub(self.name) + '.css') | |||
if os.path.exists(fpath): | |||
with open(fpath, 'r') as f: | |||
self.doc.style = f.read() | |||
self.style = f.read() | |||
# html | |||
fpath = os.path.join(path, scrub(self.doc.name) + '.html') | |||
fpath = os.path.join(path, scrub(self.name) + '.html') | |||
if os.path.exists(fpath): | |||
with open(fpath, 'r') as f: | |||
self.doc.content = f.read() | |||
self.content = f.read() | |||
if frappe.lang != 'en': | |||
from frappe.translate import get_lang_js | |||
self.doc.script += get_lang_js("page", self.doc.name) | |||
self.script += get_lang_js("page", self.name) | |||
@@ -151,8 +151,7 @@ frappe.RoleEditor = Class.extend({ | |||
.each(function(i, checkbox) { checkbox.checked = false; }); | |||
// set user roles as checked | |||
$.each(frappe.model.get("UserRole", {parent: cur_frm.doc.name, | |||
parentfield: "user_roles"}), function(i, user_role) { | |||
$.each((cur_frm.doc.user_roles || []), function(i, user_role) { | |||
var checkbox = $(me.wrapper) | |||
.find('[data-user-role="'+user_role.role+'"] input[type="checkbox"]').get(0); | |||
if(checkbox) checkbox.checked = true; | |||
@@ -163,8 +162,7 @@ frappe.RoleEditor = Class.extend({ | |||
var existing_roles_map = {}; | |||
var existing_roles_list = []; | |||
$.each(frappe.model.get("UserRole", {parent: cur_frm.doc.name, | |||
parentfield: "user_roles"}), function(i, user_role) { | |||
$.each((cur_frm.doc.user_roles || []), function(i, user_role) { | |||
existing_roles_map[user_role.role] = user_role.name; | |||
existing_roles_list.push(user_role.role); | |||
}); | |||
@@ -20,11 +20,9 @@ frappe.core.Workflow = frappe.ui.form.Controller.extend({ | |||
} | |||
}, | |||
update_field_options: function() { | |||
var fields = $.map(frappe.model.get("DocField", { | |||
parent: this.frm.doc.document_type, | |||
fieldtype: ["not in", frappe.model.no_value_type] | |||
}), | |||
function(d) { return d.fieldname; }); | |||
var fields = $.map(frappe.model.get_doc("DocType", this.frm.doc.document_type).fields, function(d) { | |||
return frappe.model.no_value_type.indexOf(d.fieldtype)===-1 ? d.fieldname : null; | |||
}) | |||
frappe.meta.get_docfield("Workflow Document State", "update_field", this.frm.doc.name).options | |||
= [""].concat(fields); | |||
} | |||
@@ -428,17 +428,15 @@ frappe.PermissionEngine = Class.extend({ | |||
}); | |||
}, | |||
get_user_fields: function(doctype) { | |||
var user_fields = frappe.model.get("DocField", {parent:doctype, | |||
fieldtype:"Link", options:"User"}); | |||
user_fields = user_fields.concat(frappe.model.get("DocField", {parent:doctype, | |||
fieldtype:"Select", link_doctype:"User"})) | |||
var user_fields = frappe.model.get_children("DocType", doctype, "fields", {fieldtype:"Link", options:"User"}) | |||
user_fields = user_fields.concat(frappe.model.get_children("DocType", doctype, "fields", | |||
{fieldtype:"Select", link_doctype:"User"})) | |||
return user_fields | |||
}, | |||
get_link_fields: function(doctype) { | |||
return link_fields = frappe.model.get("DocField", {parent:doctype, | |||
fieldtype:"Link", options:["not in", ["User", '[Select]']]}); | |||
return frappe.model.get_children("DocType", doctype, "fields", | |||
{fieldtype:"Link", options:["not in", ["User", '[Select]']]}); | |||
} | |||
}) | |||
@@ -65,7 +65,7 @@ def handle(): | |||
if cmd!='login': | |||
execute_cmd(cmd) | |||
return build_response("json") | |||
def execute_cmd(cmd): | |||
@@ -110,6 +110,16 @@ class BaseDocument(object): | |||
return self._valid_columns | |||
def as_dict(self): | |||
doc = self.get_valid_dict() | |||
doc["doctype"] = self.doctype | |||
for df in self.get_table_fields(): | |||
doc[df.fieldname] = [d.as_dict() for d in (self.get(df.fieldname) or [])] | |||
return doc | |||
def get_table_fields(self): | |||
return self.meta.get('fields', {"fieldtype":"Table"}) | |||
def get_table_field_doctype(self, fieldname): | |||
return self.meta.get("fields", {"fieldname":fieldname})[0].options | |||
@@ -41,6 +41,7 @@ def get_obj(dt = None, dn = None, doc=None, doclist=None, with_children = 0): | |||
def get_server_obj(doc, doclist = [], basedoctype = ''): | |||
# for test | |||
module = get_doctype_module(doc.doctype) | |||
classname = doc.doctype.replace(" ", "") | |||
return load_doctype_module(doc.doctype, module).DocType(doc, doclist) | |||
def run_server_obj(server_obj, method_name, arg=None): | |||
@@ -242,6 +242,8 @@ def clear_cache(doctype=None): | |||
def clear_single(dt): | |||
frappe.cache().delete_value(cache_name(dt, False)) | |||
frappe.cache().delete_value(cache_name(dt, True)) | |||
frappe.cache().delete_value("meta:" + dt) | |||
frappe.cache().delete_value("form_meta:" + dt) | |||
if doctype_cache and (dt in doctype_cache): | |||
del doctype_cache[dt] | |||
@@ -16,15 +16,20 @@ def get_doc(arg1, arg2=None): | |||
doctype = arg1 | |||
else: | |||
doctype = arg1.get("doctype") | |||
controller = get_controller(doctype) | |||
if controller: | |||
return controller(arg1, arg2) | |||
return Document(arg1, arg2) | |||
def get_controller(doctype): | |||
module = load_doctype_module(doctype) | |||
classname = doctype.replace(" ", "") | |||
if hasattr(module, classname): | |||
_class = getattr(module, classname) | |||
if issubclass(_class, Document): | |||
return getattr(module, classname)(arg1, arg2) | |||
return Document(arg1, arg2) | |||
return getattr(module, classname) | |||
class Document(BaseDocument): | |||
def __init__(self, arg1, arg2=None): | |||
@@ -59,6 +64,9 @@ class Document(BaseDocument): | |||
else: | |||
d = frappe.db.get_value(self.doctype, self.name, "*", as_dict=1) | |||
if not d: | |||
frappe.throw("{}: {}, {}".format(_("Not Found"), | |||
self.doctype, self.name), frappe.DoesNotExistError) | |||
self.update(d, valid_columns = d.keys()) | |||
for df in self.get_table_fields(): | |||
@@ -70,9 +78,6 @@ class Document(BaseDocument): | |||
else: | |||
self.set(df.fieldname, []) | |||
def get_table_fields(self): | |||
return self.meta.get('fields', {"fieldtype":"Table"}) | |||
def has_permission(self, permtype): | |||
if getattr(self, "_ignore_permissions", False): | |||
return True | |||
@@ -293,23 +298,10 @@ class Document(BaseDocument): | |||
def run_method(self, method, *args, **kwargs): | |||
"""run standard triggers, plus those in frappe""" | |||
def add_to_response(out, new_response): | |||
if isinstance(new_response, dict): | |||
out.update(new_response) | |||
if hasattr(self, method): | |||
add_to_response(frappe.local.response, | |||
getattr(self, method)(*args, **kwargs)) | |||
args = [self, method] + list(args or []) | |||
for handler in frappe.get_hooks("bean_event:" + self.doctype + ":" + method) \ | |||
+ frappe.get_hooks("bean_event:*:" + method): | |||
add_to_response(frappe.local.response, | |||
frappe.call(frappe.get_attr(handler), *args, **kwargs)) | |||
return frappe.local.response | |||
fn = lambda self, *args, **kwargs: getattr(self, method)(*args, **kwargs) | |||
return Document.hook(fn)(self, *args, **kwargs) | |||
def run_before_save_methods(self): | |||
if self._action=="save": | |||
self.run_method("validate") | |||
@@ -332,3 +324,31 @@ class Document(BaseDocument): | |||
self.run_method("on_cancel") | |||
elif self._action=="update_after_submit": | |||
self.run_method("on_update_after_submit") | |||
@staticmethod | |||
def hook(f): | |||
def add_to_response(new_response): | |||
if isinstance(new_response, dict): | |||
frappe.local.response.update(new_response) | |||
def compose(fn, *hooks): | |||
def runner(self, method, *args, **kwargs): | |||
add_to_response(fn(self, *args, **kwargs)) | |||
for f in hooks: | |||
add_to_response(f(self, method, *args, **kwargs)) | |||
return frappe.local.response | |||
return runner | |||
def composer(self, *args, **kwargs): | |||
hooks = [] | |||
method = f.__name__ | |||
for handler in frappe.get_hooks("bean_event:" + self.doctype + ":" + method) \ | |||
+ frappe.get_hooks("bean_event:*:" + method): | |||
hooks.append(frappe.getattr(handler)) | |||
composed = compose(f, *hooks) | |||
return composed(self, method, *args, **kwargs) | |||
return composer | |||
@@ -12,6 +12,8 @@ from frappe.model.document import Document | |||
###### | |||
def get_meta(doctype, cached=True): | |||
# TODO: cache to be cleared | |||
if cached: | |||
if doctype not in frappe.local.meta: | |||
frappe.local.meta[doctype] = frappe.cache().get_value("meta:" + doctype, lambda: Meta(doctype)) | |||
@@ -83,7 +83,6 @@ | |||
"public/js/frappe/model/model.js", | |||
"public/js/frappe/model/meta.js", | |||
"public/js/frappe/model/doclist.js", | |||
"public/js/frappe/model/sync.js", | |||
"public/js/frappe/model/create_new.js", | |||
"public/js/frappe/model/perm.js", | |||
@@ -135,6 +134,7 @@ | |||
"public/js/frappe/form/toolbar.js", | |||
"public/js/frappe/form/infobar.js", | |||
"public/js/frappe/form/dashboard.js", | |||
"public/js/frappe/form/save.js", | |||
"public/js/frappe/form/script_manager.js", | |||
"public/js/frappe/form/control.js", | |||
"public/js/frappe/form/link_selector.js", | |||
@@ -980,8 +980,9 @@ frappe.ui.form.ControlTable = frappe.ui.form.Control.extend({ | |||
this._super(); | |||
// add title if prev field is not column / section heading or html | |||
var prev_fieldtype = frappe.model.get("DocField", | |||
{parent: this.frm.doctype, idx: this.df.idx-1})[0].fieldtype; | |||
var prev_fieldtype = frappe.model.get_children("DocType", this.frm.doctype, "fields", | |||
{idx: this.df.idx-1}); | |||
prev_fieldtype = prev_fieldtype ? prev_fieldtype[0].fieldtype : ""; | |||
if(["Column Break", "Section Break", "HTML"].indexOf(prev_fieldtype)===-1) { | |||
$("<label>" + this.df.label + "<label>").appendTo(this.wrapper); | |||
@@ -98,7 +98,7 @@ frappe.form.formatters = { | |||
return "<pre>" + (value==null ? "" : $("<div>").text(value).html()) + "</pre>" | |||
}, | |||
WorkflowState: function(value) { | |||
workflow_state = frappe.model.get("Workflow State", value)[0]; | |||
workflow_state = frappe.model.get_doc("Workflow State", value); | |||
if(workflow_state) { | |||
return repl("<span class='label label-%(style)s' \ | |||
data-workflow-state='%(value)s'\ | |||
@@ -118,11 +118,7 @@ frappe.ui.form.Grid = Class.extend({ | |||
}); | |||
}, | |||
get_data: function() { | |||
var data = frappe.model.get(this.df.options, { | |||
"parenttype": this.frm.doctype, | |||
"parentfield": this.df.fieldname, | |||
"parent": this.frm.docname | |||
}); | |||
var data = this.frm.doc[this.df.fieldname] || []; | |||
data.sort(function(a, b) { return a.idx - b.idx}); | |||
return data; | |||
}, | |||
@@ -1,9 +1,7 @@ | |||
// Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors | |||
// MIT License. See license.txt | |||
// for license information please see license.txt | |||
frappe.provide("frappe.ui.form") | |||
frappe.provide("frappe.ui.form"); | |||
frappe.ui.form.LinkedWith = Class.extend({ | |||
init: function(opts) { | |||
@@ -1,45 +1,38 @@ | |||
// Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors | |||
// MIT License. See license.txt | |||
// MIT License. See license.txt | |||
frappe.provide("frappe.model"); | |||
frappe.model.DocList = Class.extend({ | |||
init: function(doctype, name) { | |||
this.doctype = doctype; this.name = name; | |||
this.doclist = frappe.model.get_doclist(this.doctype, this.name); | |||
this.doc = this.doclist[0]; | |||
}, | |||
save: function(action, callback, btn) { | |||
this.check_name(); | |||
if(this.check_mandatory()) { | |||
var me = this; | |||
this._call({ | |||
frappe.provide("frappe.ui.form"); | |||
frappe.ui.form.save = function(frm, action, callback, btn) { | |||
var save = function() { | |||
check_name(); | |||
if(check_mandatory()) { | |||
_call({ | |||
method: "frappe.widgets.form.save.savedocs", | |||
args: { docs: frappe.model.compress(this.doclist), action:action}, | |||
args: { docs: frm.doc, action:action}, | |||
callback: function(r) { | |||
$(document).trigger("save", me.doc); | |||
$(document).trigger("save", frm.doc); | |||
callback(r); | |||
}, | |||
btn: btn | |||
}); | |||
} | |||
}, | |||
}; | |||
cancel: function(callback, btn) { | |||
var me = this; | |||
this._call({ | |||
var cancel = function() { | |||
_call({ | |||
method: "frappe.widgets.form.save.cancel", | |||
args: { doctype: this.doctype, name: this.name }, | |||
args: { doctype: frm.doc.doctype, name: frm.doc.name }, | |||
callback: function(r) { | |||
$(document).trigger("save", frappe.model.get_doc(me.doctype, me.name)); | |||
$(document).trigger("save", frm.doc); | |||
callback(r); | |||
}, | |||
btn: btn | |||
}); | |||
}, | |||
}; | |||
check_name: function() { | |||
var doc = this.doclist[0]; | |||
var check_name = function() { | |||
var doc = frm.doc; | |||
var meta = locals.DocType[doc.doctype]; | |||
if(doc.__islocal && (meta && meta.autoname | |||
&& meta.autoname.toLowerCase()=='prompt')) { | |||
@@ -51,23 +44,22 @@ frappe.model.DocList = Class.extend({ | |||
throw "name required"; | |||
} | |||
} | |||
}, | |||
}; | |||
check_mandatory: function() { | |||
var me = this; | |||
var check_mandatory = function() { | |||
var has_errors = false; | |||
this.scroll_set = false; | |||
frm.scroll_set = false; | |||
if(this.doc.docstatus==2) return true; // don't check for cancel | |||
if(frm.doc.docstatus==2) return true; // don't check for cancel | |||
$.each(this.doclist, function(i, doc) { | |||
$.each(frm.model.get_all_docs(frm.doc), function(i, doc) { | |||
var error_fields = []; | |||
$.each(frappe.meta.docfield_list[doc.doctype] || [], function(i, docfield) { | |||
if(docfield.fieldname) { | |||
var df = frappe.meta.get_docfield(doc.doctype, | |||
docfield.fieldname, me.doclist[0].name); | |||
docfield.fieldname, frm.doc.name); | |||
if(df.reqd && !frappe.model.has_value(doc.doctype, doc.name, df.fieldname)) { | |||
has_errors = true; | |||
@@ -87,17 +79,17 @@ frappe.model.DocList = Class.extend({ | |||
}); | |||
return !has_errors; | |||
}, | |||
}; | |||
scroll_to: function(fieldname) { | |||
var scroll_to = function(fieldname) { | |||
var f = cur_frm.fields_dict[fieldname]; | |||
if(f) { | |||
$(document).scrollTop($(f.wrapper).offset().top - 100); | |||
} | |||
this.scroll_set = true; | |||
}, | |||
frm.scroll_set = true; | |||
}; | |||
_call: function(opts) { | |||
var _call = function(opts) { | |||
// opts = { | |||
// method: "some server method", | |||
// args: {args to be passed}, | |||
@@ -114,5 +106,11 @@ frappe.model.DocList = Class.extend({ | |||
opts.callback && opts.callback(r); | |||
} | |||
}) | |||
}, | |||
}); | |||
}; | |||
if(action==="cancel") { | |||
cancel(); | |||
} else { | |||
save(); | |||
} | |||
} |
@@ -109,7 +109,7 @@ frappe.ui.form.ScriptManager = Class.extend({ | |||
} | |||
}, | |||
copy_from_first_row: function(parentfield, current_row, fieldnames) { | |||
var doclist = frappe.model.get_doclist(this.frm.doc.doctype, this.frm.doc.name, {parentfield: parentfield}); | |||
var doclist = this.frm.doc[parentfield]; | |||
if(doclist.length===1 || doclist[0]===current_row) return; | |||
$.each(fieldnames, function(i, fieldname) { | |||
@@ -79,7 +79,7 @@ frappe.ui.form.States = Class.extend({ | |||
// show current state on the button | |||
this.workflow_button.find(".state-text").text(state); | |||
var state_doc = frappe.model.get("Workflow State", {name:state})[0]; | |||
var state_doc = frappe.model.get_doc("Workflow State", state); | |||
if (state_doc) { | |||
// set the icon | |||
@@ -109,7 +109,7 @@ frappe.ui.form.States = Class.extend({ | |||
$.each(frappe.workflow.get_transitions(this.frm.doctype, state), function(i, d) { | |||
if(in_list(user_roles, d.allowed)) { | |||
d.icon = frappe.model.get("Workflow State", {name:d.next_state})[0].icon; | |||
d.icon = frappe.model.get("Workflow State", d.next_state).icon; | |||
$(repl('<li><a href="#" data-action="%(action)s">\ | |||
<i class="icon icon-%(icon)s"></i> %(action)s</a></li>', d)) | |||
@@ -122,20 +122,36 @@ $.extend(frappe.model, { | |||
return d; | |||
}, | |||
copy_doc: function(dt, dn, from_amend) { | |||
copy_doc: function(doc, from_amend) { | |||
var no_copy_list = ['name','amended_from','amendment_date','cancel_reason']; | |||
var newdoc = frappe.model.get_new_doc(dt); | |||
var newdoc = frappe.model.get_new_doc(doc.doctype); | |||
for(var key in locals[dt][dn]) { | |||
for(var key in doc) { | |||
// dont copy name and blank fields | |||
var df = frappe.meta.get_docfield(dt, key); | |||
var df = frappe.meta.get_docfield(doc.doctype, key); | |||
if(key.substr(0,2)!='__' | |||
&& !in_list(no_copy_list, key) | |||
&& !(df && (!from_amend && cint(df.no_copy)==1))) { | |||
newdoc[key] = locals[dt][dn][key]; | |||
value = doc[key]; | |||
if(df.fieldtype==="Table") { | |||
newdoc[key] = []; | |||
$.each(value || [], function(i, d) { | |||
newdoc[key].push(frappe.model.copy_doc(d, from_amend)) | |||
}) | |||
} else { | |||
newdoc[key] = doc[key]; | |||
} | |||
} | |||
} | |||
newdoc.__islocal = 1; | |||
newdoc.docstatus = 0; | |||
newdoc.owner = user; | |||
newdoc.creation = ''; | |||
newdoc.modified_by = user; | |||
newdoc.modified = ''; | |||
return newdoc; | |||
}, | |||
@@ -167,7 +183,7 @@ $.extend(frappe.model, { | |||
method: opts.method, | |||
args: { | |||
"source_name": opts.source_name, | |||
"target_doclist": frappe.model.get_doclist(cur_frm.doc.doctype, cur_frm.doc.name) | |||
"target_doclist": cur_frm.doc | |||
}, | |||
callback: function(r) { | |||
if(!r.exc) { | |||
@@ -8,6 +8,13 @@ frappe.provide('frappe.meta.doctypes'); | |||
frappe.provide("frappe.meta.precision_map"); | |||
$.extend(frappe.meta, { | |||
sync: function(doc) { | |||
$.each(doc.fields, function(i, df) { | |||
frappe.meta.add_field(df); | |||
}) | |||
frappe.meta.sync_messages(doc); | |||
}, | |||
// build docfield_map and docfield_list | |||
add_field: function(df) { | |||
frappe.provide('frappe.meta.docfield_map.' + df.parent); | |||
@@ -84,8 +91,8 @@ $.extend(frappe.meta, { | |||
}, | |||
get_parentfield: function(parent_dt, child_dt) { | |||
var df = frappe.model.get("DocField", {parent:parent_dt, fieldtype:"Table", | |||
options:child_dt}) | |||
var df = (frappe.model.get_doc("DocType", parent_dt).fields || []).filter(function(d) | |||
{ return d.fieldtype==="Table" && options===child_dt }) | |||
if(!df.length) | |||
throw "parentfield not found for " + parent_dt + ", " + child_dt; | |||
return df[0].fieldname; | |||
@@ -46,8 +46,8 @@ $.extend(frappe.model, { | |||
} else { | |||
var cached_timestamp = null; | |||
if(localStorage["_doctype:" + doctype]) { | |||
var cached_doclist = JSON.parse(localStorage["_doctype:" + doctype]); | |||
cached_timestamp = cached_doclist[0].modified; | |||
var cached_doc = JSON.parse(localStorage["_doctype:" + doctype]); | |||
cached_timestamp = cached_doc.modified; | |||
} | |||
return frappe.call({ | |||
method:'frappe.widgets.form.load.getdoctype', | |||
@@ -64,7 +64,7 @@ $.extend(frappe.model, { | |||
return; | |||
} | |||
if(r.message=="use_cache") { | |||
frappe.model.sync(cached_doclist); | |||
frappe.model.sync(cached_doc); | |||
} else { | |||
localStorage["_doctype:" + doctype] = JSON.stringify(r.docs); | |||
} | |||
@@ -206,10 +206,10 @@ $.extend(frappe.model, { | |||
}, | |||
get: function(doctype, filters) { | |||
var src = locals[doctype] || locals[":" + doctype] || []; | |||
if($.isEmptyObject(src)) | |||
var docsdict = locals[doctype] || locals[":" + doctype] || []; | |||
if($.isEmptyObject(docsdict)) | |||
return []; | |||
return frappe.utils.filter_dict(src, filters); | |||
return frappe.utils.filter_dict(docsdict, filters); | |||
}, | |||
get_value: function(doctype, filters, fieldname) { | |||
@@ -277,55 +277,16 @@ $.extend(frappe.model, { | |||
return locals[doctype] ? locals[doctype][name] : null; | |||
}, | |||
get_doclist: function(doctype, name, filters) { | |||
var doclist = []; | |||
if(!locals[doctype]) | |||
return doclist; | |||
doclist[0] = locals[doctype][name]; | |||
$.each(frappe.model.get("DocField", {parent:doctype, fieldtype:"Table"}), | |||
function(i, table_field) { | |||
var child_doclist = frappe.model.get(table_field.options, { | |||
parent:name, parenttype: doctype, | |||
parentfield: table_field.fieldname}); | |||
if($.isArray(child_doclist)) { | |||
child_doclist.sort(function(a, b) { return a.idx - b.idx; }); | |||
doclist = doclist.concat(child_doclist); | |||
} | |||
} | |||
); | |||
if(filters) { | |||
doclist = frappe.utils.filter_dict(doclist, filters); | |||
} | |||
return doclist; | |||
}, | |||
get_children: function(doctype, parent, parentfield, parenttype) { | |||
if(parenttype) { | |||
var l = frappe.model.get(doctype, {parent:parent, | |||
parentfield:parentfield, parenttype:parenttype}); | |||
get_children: function(doctype, parent, parentfield, filters) { | |||
if($.isPlainObject(parentfield)) { | |||
var doc = doctype; | |||
var filters = parentfield; | |||
var parentfield = parent; | |||
return frappe.utils.filter_dict((doc[parentfield] || []), filters); | |||
} else { | |||
var l = frappe.model.get(doctype, {parent:parent, | |||
parentfield:parentfield}); | |||
return frappe.utils.filter_dict((frappe.model.get_doc(doctype, parent)[parentfield] || []), filters); | |||
} | |||
if(l.length) { | |||
l.sort(function(a,b) { return flt(a.idx) - flt(b.idx) }); | |||
// renumber | |||
$.each(l, function(i, v) { v.idx = i+1; }); // for chrome bugs ??? | |||
} | |||
return l; | |||
}, | |||
clear_doclist: function(doctype, name) { | |||
$.each(frappe.model.get_doclist(doctype, name), function(i, d) { | |||
if(d) frappe.model.clear_doc(d.doctype, d.name); | |||
}); | |||
}, | |||
clear_table: function(doctype, parenttype, parent, parentfield) { | |||
@@ -337,7 +298,7 @@ $.extend(frappe.model, { | |||
}, | |||
remove_from_locals: function(doctype, name) { | |||
this.clear_doclist(doctype, name); | |||
this.clear_doc(doctype, name); | |||
if(frappe.views.formview[doctype]) { | |||
delete frappe.views.formview[doctype].frm.opendocs[name]; | |||
} | |||
@@ -358,13 +319,14 @@ $.extend(frappe.model, { | |||
get_no_copy_list: function(doctype) { | |||
var no_copy_list = ['name','amended_from','amendment_date','cancel_reason']; | |||
$.each(frappe.model.get("DocField", {parent:doctype}), function(i, df) { | |||
$.each(frappe.model.get_doc("DocType", doctype).fields || [], function(i, df) { | |||
if(cint(df.no_copy)) no_copy_list.push(df.fieldname); | |||
}) | |||
return no_copy_list; | |||
}, | |||
// args: source (doclist), target (doctype), table_map, field_map, callback | |||
// args: source (doc), target (doc), table_map, field_map, callback | |||
map: function(args) { | |||
frappe.model.with_doctype(args.target, function() { | |||
var map_info = frappe.model.map_info[args.target] | |||
@@ -436,7 +398,7 @@ $.extend(frappe.model, { | |||
}, | |||
callback: function(r, rt) { | |||
if(!r.exc) { | |||
frappe.model.clear_doclist(doctype, docname); | |||
frappe.model.clear_doc(doctype, docname); | |||
if(frappe.ui.toolbar.recent) | |||
frappe.ui.toolbar.recent.remove(doctype, docname); | |||
if(callback) callback(r,rt); | |||
@@ -499,9 +461,20 @@ $.extend(frappe.model, { | |||
frappe.throw(frappe._("Please specify") + ": " + | |||
frappe._(frappe.meta.get_label(doc.doctype, fieldname, doc.parent || doc.name))); | |||
} | |||
}, | |||
get_all_docs: function(doc) { | |||
var all = [doc]; | |||
for(key in doc) { | |||
if($.isArray(doc[key])) { | |||
$.each(doc[key], function(i, d) { | |||
all.push(d); | |||
}); | |||
} | |||
} | |||
return all; | |||
} | |||
}); | |||
// legacy | |||
getchildren = frappe.model.get_children | |||
make_doclist = frappe.model.get_doclist |
@@ -38,17 +38,9 @@ $.extend(frappe.perm, { | |||
var perm = [{read: 0}]; | |||
var meta = frappe.model.get_doc("DocType", doctype); | |||
if(!meta) { | |||
return perm; | |||
} else if(meta.istable) { | |||
// if a child table, use permissions of parent form | |||
var parent_df = frappe.model.get("DocField", {fieldtype: "Table", options: doctype}); | |||
if(parent_df.length) { | |||
if(docname) { | |||
docname = frappe.model.get_doc(doctype, docname).parent; | |||
} | |||
doctype = parent_df[0].parent; | |||
} | |||
} | |||
if(user==="Administrator" || user_roles.indexOf("Administrator")!==-1) { | |||
@@ -60,7 +52,7 @@ $.extend(frappe.perm, { | |||
return perm; | |||
} | |||
var docperms = frappe.model.get("DocPerm", {parent: doctype}); | |||
var docperms = frappe.model.get_doc("DocType", doctype).permissions || []; | |||
$.each(docperms, function(i, p) { | |||
// if user has this role | |||
if(user_roles.indexOf(p.role)!==-1) { | |||
@@ -5,35 +5,21 @@ $.extend(frappe.model, { | |||
docinfo: {}, | |||
sync: function(r) { | |||
/* docs: | |||
extract doclist, docinfo (attachments, comments, assignments) | |||
extract docs, docinfo (attachments, comments, assignments) | |||
from incoming request and set in `locals` and `frappe.model.docinfo` | |||
*/ | |||
if(!r.docs && !r.docinfo) r = {docs:r}; | |||
if(r.docs) { | |||
var doclist = r.docs; | |||
if(doclist._kl) | |||
doclist = frappe.model.expand(doclist); | |||
if(doclist && doclist.length) | |||
frappe.model.clear_doclist(doclist[0].doctype, doclist[0].name) | |||
var last_parent_name = null; | |||
var dirty = []; | |||
$.each(doclist, function(i, d) { | |||
$.each(r.docs, function(i, d) { | |||
if(!d.name && d.__islocal) { // get name (local if required) | |||
frappe.model.clear_doc(d) | |||
d.name = frappe.model.get_new_name(d.doctype); | |||
frappe.provide("frappe.model.docinfo." + d.doctype + "." + d.name); | |||
if(!d.parenttype) | |||
last_parent_name = d.name; | |||
if(dirty.indexOf(d.parenttype || d.doctype)===-1) dirty.push(d.parenttype || d.doctype); | |||
} | |||
// set parent for subsequent orphans | |||
if(d.parenttype && !d.parent && d.__islocal) { | |||
d.parent = last_parent_name; | |||
} | |||
if(!locals[d.doctype]) | |||
@@ -41,14 +27,15 @@ $.extend(frappe.model, { | |||
locals[d.doctype][d.name] = d; | |||
d.__last_sync_on = new Date(); | |||
if(d.doctype==="DocType") { | |||
frappe.meta.sync(d); | |||
} | |||
if(cur_frm && cur_frm.doctype==d.doctype && cur_frm.docname==d.name) { | |||
cur_frm.doc = d; | |||
} | |||
if(d.doctype=='DocField') frappe.meta.add_field(d); | |||
if(d.doctype=='DocType') frappe.meta.sync_messages(d); | |||
if(d.localname) { | |||
frappe.model.new_names[d.localname] = d.name; | |||
$(document).trigger('rename', [d.doctype, d.localname, d.name]); | |||
@@ -66,10 +53,10 @@ $.extend(frappe.model, { | |||
} | |||
// set docinfo | |||
// set docinfo (comments, assign, attachments) | |||
if(r.docinfo) { | |||
if(doclist) { | |||
var doc = doclist[0]; | |||
if(r.docs) { | |||
var doc = r.docs[0]; | |||
} else { | |||
var doc = cur_frm.doc; | |||
} | |||
@@ -78,68 +65,7 @@ $.extend(frappe.model, { | |||
frappe.model.docinfo[doc.doctype][doc.name] = r.docinfo; | |||
} | |||
return doclist; | |||
return r.docs; | |||
}, | |||
expand: function(data) { | |||
function zip(k,v) { | |||
var obj = {}; | |||
for(var i=0;i<k.length;i++) { | |||
obj[k[i]] = v[i]; | |||
} | |||
return obj; | |||
} | |||
var l = []; | |||
for(var i=0;i<data._vl.length;i++) { | |||
l.push(zip(data._kl[data._vl[i][0]], data._vl[i])); | |||
} | |||
return l; | |||
}, | |||
compress: function(doclist) { | |||
var all_keys = {}; var values = []; | |||
function get_key_list(doctype) { | |||
// valid standard keys | |||
var key_list = ['doctype', 'name', 'docstatus', 'owner', 'parent', | |||
'parentfield', 'parenttype', 'idx', 'creation', 'modified', | |||
'modified_by', '__islocal', '__newname', '__modified', | |||
'_user_tags', '__temp', '_comments']; | |||
for(key in frappe.meta.docfield_map[doctype]) { // all other values | |||
if(!in_list(key_list, key) | |||
&& !in_list(frappe.model.no_value_type, frappe.meta.docfield_map[doctype][key].fieldtype) | |||
&& !frappe.meta.docfield_map[doctype][key].no_column) { | |||
key_list[key_list.length] = key | |||
} | |||
} | |||
return key_list; | |||
} | |||
for(var i=0; i<doclist.length;i++) { | |||
var doc = doclist[i]; | |||
// make keys | |||
if(!all_keys[doc.doctype]) { | |||
all_keys[doc.doctype] = get_key_list(doc.doctype); | |||
// doctype must be first | |||
} | |||
var row = [] | |||
var key_list = all_keys[doc.doctype]; | |||
// make data rows | |||
for(var j=0;j<key_list.length;j++) { | |||
row.push(doc[key_list[j]]); | |||
} | |||
values.push(row); | |||
} | |||
return JSON.stringify({'_vl':values, '_kl':all_keys}); | |||
} | |||
}); | |||
// legacy | |||
compress_doclist = frappe.model.compress; |
@@ -23,31 +23,19 @@ frappe.workflow = { | |||
}, | |||
get_default_state: function(doctype) { | |||
frappe.workflow.setup(doctype); | |||
return frappe.model.get("Workflow Document State", { | |||
parent: frappe.workflow.workflows[doctype].name, | |||
idx: 1 | |||
})[0].state; | |||
return frappe.workflow.workflows[doctype].workflow_document_states[0].state; | |||
}, | |||
get_transitions: function(doctype, state) { | |||
frappe.workflow.setup(doctype); | |||
return frappe.model.get("Workflow Transition", { | |||
parent: frappe.workflow.workflows[doctype].name, | |||
state: state | |||
}); | |||
return frappe.model.get_children(frappe.workflow.workflows[doctype], "workflow_transitions", {state:state}); | |||
}, | |||
get_document_state: function(doctype, state) { | |||
frappe.workflow.setup(doctype); | |||
return frappe.model.get("Workflow Document State", { | |||
parent: frappe.workflow.workflows[doctype].name, | |||
state: state | |||
})[0]; | |||
return frappe.model.get_children(frappe.workflow.workflows[doctype], "workflow_document_states", {state:state})[0]; | |||
}, | |||
get_next_state: function(doctype, state, action) { | |||
return frappe.model.get("Workflow Transition", { | |||
parent: frappe.workflow.workflows[doctype].name, | |||
state: state, | |||
action: action | |||
})[0].next_state; | |||
return frappe.model.get_children(frappe.workflow.workflows[doctype], "workflow_transitions", { | |||
state:state, action:action})[0].next_state; | |||
}, | |||
is_read_only: function(doctype, name) { | |||
var state_fieldname = frappe.workflow.get_state_fieldname(doctype); | |||
@@ -60,13 +48,7 @@ frappe.workflow = { | |||
var state = locals[doctype][name][state_fieldname] || | |||
frappe.workflow.get_default_state(doctype); | |||
var workflow_doc_state = frappe.model.get("Workflow Document State", | |||
{ | |||
parent: frappe.workflow.workflows[doctype].name, | |||
state: state | |||
}); | |||
var allow_edit = workflow_doc_state.length ? | |||
workflow_doc_state[0].allow_edit : null; | |||
var allow_edit = state ? frappe.workflow.get_document_state(doctype, state).allow_edit : null; | |||
if(user_roles.indexOf(allow_edit)==-1) { | |||
return true; | |||
@@ -75,8 +57,8 @@ frappe.workflow = { | |||
return false; | |||
}, | |||
get_update_fields: function(doctype) { | |||
var update_fields = $.unique($.map(frappe.model.get("Workflow Document State", | |||
{parent:frappe.workflow.workflows[doctype].name}), function(d) { | |||
var update_fields = $.unique($.map(frappe.workflow.workflows[doctype].workflow_document_states || [], | |||
function(d) { | |||
return d.update_field; | |||
})); | |||
return update_fields; | |||
@@ -16,8 +16,7 @@ frappe.call = function(opts) { | |||
} else if(opts.doc) { | |||
$.extend(args, { | |||
cmd: "runserverobj", | |||
docs: frappe.model.compress(frappe.model.get_doclist(opts.doc.doctype, | |||
opts.doc.name)), | |||
docs: frappe.model.get_doc(opts.doc.doctype, opts.doc.name), | |||
method: opts.method, | |||
args: opts.args, | |||
}); | |||
@@ -337,13 +337,13 @@ frappe.views.ReportView = frappe.ui.Listing.extend({ | |||
callback: function(r) { | |||
if(!r.exc) { | |||
d.hide(); | |||
var doclist = r.message; | |||
var doc = r.message; | |||
$.each(me.dataView.getItems(), function(i, item) { | |||
if (item.name === doclist[0].name) { | |||
var new_item = $.extend({}, item, doclist[0]); | |||
$.each(doclist, function(i, doc) { | |||
if(item[doc.doctype + ":name"]===doc.name) { | |||
$.each(doc, function(k, v) { | |||
if (item.name === doc.name) { | |||
var new_item = $.extend({}, item); | |||
$.each(frappe.model.get_all_docs(doc), function(i, d) { | |||
if(item[d.doctype + ":name"]===d.name) { | |||
$.each(d, function(k, v) { | |||
if(frappe.model.std_fields_list.indexOf(k)===-1) { | |||
new_item[k] = v; | |||
} | |||
@@ -4,10 +4,7 @@ | |||
get_server_fields = function(method, arg, table_field, doc, dt, dn, allow_edit, call_back) { | |||
frappe.dom.freeze(); | |||
return $c('runserverobj', | |||
args={'method':method, | |||
'docs':frappe.model.compress(make_doclist(doc.doctype, doc.name)), | |||
'arg':arg | |||
}, | |||
args={'method': method, 'docs': doc, 'arg': arg }, | |||
function(r, rt) { | |||
frappe.dom.unfreeze(); | |||
if (r.message) { | |||
@@ -125,10 +122,6 @@ _f.Frm.prototype.get_doc = function() { | |||
return locals[this.doctype][this.docname]; | |||
} | |||
_f.Frm.prototype.get_doclist = function(filters) { | |||
return frappe.model.get_doclist(this.doctype, this.docname, filters); | |||
} | |||
_f.Frm.prototype.field_map = function(fnames, fn) { | |||
if(typeof fnames==='string') { | |||
if(fnames == '*') { | |||
@@ -170,7 +163,7 @@ _f.Frm.prototype.toggle_display = function(fnames, show) { | |||
} | |||
_f.Frm.prototype.call_server = function(method, args, callback) { | |||
return $c_obj(cur_frm.get_doclist(), method, args, callback); | |||
return $c_obj(cur_frm.doc, method, args, callback); | |||
} | |||
_f.Frm.prototype.get_files = function() { | |||
@@ -548,13 +548,11 @@ _f.Frm.prototype.setnewdoc = function() { | |||
_f.Frm.prototype.runscript = function(scriptname, callingfield, onrefresh) { | |||
var me = this; | |||
if(this.docname) { | |||
// make doc list | |||
var doclist = frappe.model.compress(make_doclist(this.doctype, this.docname)); | |||
// send to run | |||
if(callingfield) | |||
$(callingfield.input).set_working(); | |||
return $c('runserverobj', {'docs':doclist, 'method':scriptname }, | |||
return $c('runserverobj', {'docs':this.doc, 'method':scriptname }, | |||
function(r, rtxt) { | |||
// run refresh | |||
if(onrefresh) | |||
@@ -577,45 +575,10 @@ _f.Frm.prototype.copy_doc = function(onload, from_amend) { | |||
return; | |||
} | |||
var dn = this.docname; | |||
// copy parent | |||
var newdoc = frappe.model.copy_doc(this.doctype, dn, from_amend); | |||
newdoc.idx = null; | |||
// copy chidren | |||
var dl = make_doclist(this.doctype, dn); | |||
// table fields dict - for no_copy check | |||
var tf_dict = {}; | |||
for(var d in dl) { | |||
d1 = dl[d]; | |||
// get tabel field | |||
if(d1.parentfield && !tf_dict[d1.parentfield]) { | |||
tf_dict[d1.parentfield] = frappe.meta.get_docfield(d1.parenttype, d1.parentfield); | |||
} | |||
if(d1.parent==dn && cint(tf_dict[d1.parentfield].no_copy)!=1) { | |||
var ch = frappe.model.copy_doc(d1.doctype, d1.name, from_amend); | |||
ch.parent = newdoc.name; | |||
ch.docstatus = 0; | |||
ch.owner = user; | |||
ch.creation = ''; | |||
ch.modified_by = user; | |||
ch.modified = ''; | |||
} | |||
} | |||
newdoc.__islocal = 1; | |||
newdoc.docstatus = 0; | |||
newdoc.owner = user; | |||
newdoc.creation = ''; | |||
newdoc.modified_by = user; | |||
newdoc.modified = ''; | |||
var newdoc = frappe.model.copy_doc(this.doc, from_amend); | |||
newdoc.idx = null; | |||
if(onload)onload(newdoc); | |||
loaddoc(newdoc.doctype, newdoc.name); | |||
} | |||
@@ -651,19 +614,15 @@ _f.Frm.prototype._save = function(save_action, callback, btn, on_error) { | |||
scroll(0, 0); | |||
// validate | |||
if(save_action!="Cancel") { | |||
validated = true; | |||
this.script_manager.trigger("validate"); | |||
if(!validated) { | |||
if(on_error) | |||
on_error(); | |||
return; | |||
} | |||
validated = true; | |||
this.script_manager.trigger("validate"); | |||
if(!validated) { | |||
if(on_error) | |||
on_error(); | |||
return; | |||
} | |||
var doclist = new frappe.model.DocList(this.doctype, this.docname); | |||
doclist.save(save_action || "Save", function(r) { | |||
var after_save = function(r) { | |||
if(!r.exc) { | |||
me.refresh(); | |||
} else { | |||
@@ -680,7 +639,9 @@ _f.Frm.prototype._save = function(save_action, callback, btn, on_error) { | |||
} | |||
frappe._from_link = null; | |||
} | |||
}, btn); | |||
} | |||
frappe.ui.form.save(this, save_action || "Save", after_save, btn); | |||
} | |||
@@ -713,14 +674,16 @@ _f.Frm.prototype.savecancel = function(btn, on_error) { | |||
on_error(); | |||
return; | |||
} | |||
var doclist = new frappe.model.DocList(me.doctype, me.docname); | |||
doclist.cancel(function(r) { | |||
var after_cancel = function(r) { | |||
if(!r.exc) { | |||
me.refresh(); | |||
me.script_manager.trigger("after_cancel"); | |||
} else { | |||
on_error(); | |||
} | |||
}, btn, on_error); | |||
} | |||
frappe.ui.form.save(this, "cancel", after_cancel, btn); | |||
}); | |||
} | |||
@@ -13,7 +13,7 @@ function $c(command, args, callback, error, no_spinner, freeze_msg, btn) { | |||
} | |||
// For calling an object | |||
function $c_obj(doclist, method, arg, callback, no_spinner, freeze_msg, btn) { | |||
function $c_obj(doc, method, arg, callback, no_spinner, freeze_msg, btn) { | |||
if(arg && typeof arg!='string') arg = JSON.stringify(arg); | |||
args = { | |||
@@ -22,10 +22,11 @@ function $c_obj(doclist, method, arg, callback, no_spinner, freeze_msg, btn) { | |||
method: method | |||
}; | |||
if(typeof doclist=='string') | |||
args.doctype = doclist; | |||
else | |||
args.docs = frappe.model.compress(doclist) | |||
if(typeof doc=='string') { | |||
args.doctype = doc; | |||
} else { | |||
args.docs = doc | |||
} | |||
return frappe.request.call({ | |||
args: args, | |||
@@ -53,7 +54,7 @@ function $c_page(module, page, method, arg, callback, no_spinner, freeze_msg, bt | |||
} | |||
// For calling an for output as csv | |||
function $c_obj_csv(doclist, method, arg) { | |||
function $c_obj_csv(doc, method, arg) { | |||
// single | |||
var args = {} | |||
@@ -62,10 +63,10 @@ function $c_obj_csv(doclist, method, arg) { | |||
args.method = method; | |||
args.arg = arg; | |||
if(doclist.substr) | |||
args.doctype = doclist; | |||
if(doc.substr) | |||
args.doctype = doc; | |||
else | |||
args.docs = frappe.model.compress(doclist); | |||
args.docs = doc; | |||
// open | |||
open_url_post(frappe.request.url, args); | |||
@@ -120,5 +120,6 @@ class TestDocument(unittest.TestCase): | |||
d.starts_on = "2014-01-01" | |||
d.ends_on = "2013-01-01" | |||
self.assertRaises(frappe.ValidationError, d.validate) | |||
self.assertRaises(frappe.ValidationError, d.run_method, "validate") | |||
self.assertRaises(frappe.ValidationError, d.save) | |||
@@ -0,0 +1,16 @@ | |||
# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors | |||
# MIT License. See license.txt | |||
import frappe, unittest | |||
from frappe.widgets.form.meta import get_meta | |||
from frappe.widgets.form.load import getdoctype, getdoc | |||
class TestFormLoad(unittest.TestCase): | |||
def test_load(self): | |||
getdoctype("DocType") | |||
self.assertEquals(frappe.response.docs[0].name, "DocType") | |||
self.assertTrue(frappe.response.docs[0].get("__js")) | |||
frappe.response.docs = [] | |||
d = getdoctype("Event") | |||
self.assertTrue(frappe.response.docs[0].get("__calendar_js")) |
@@ -9,7 +9,8 @@ import mimetypes | |||
import os | |||
import frappe | |||
from frappe import _ | |||
from frappe.model.doc import Document | |||
import frappe.model.doc | |||
import frappe.model.document | |||
import frappe.utils | |||
import frappe.sessions | |||
import frappe.model.utils | |||
@@ -28,6 +29,9 @@ def report_error(status_code): | |||
return response | |||
def build_response(response_type=None): | |||
if "docs" in frappe.local.response and not frappe.local.response.docs: | |||
del frappe.local.response["docs"] | |||
response_type_map = { | |||
'csv': as_csv, | |||
'download': as_raw, | |||
@@ -54,7 +58,6 @@ def as_raw(): | |||
def as_json(): | |||
make_logs() | |||
cleanup_docs() | |||
response = Response() | |||
response.headers["Content-Type"] = "application/json; charset: utf-8" | |||
response = gzip(json.dumps(frappe.local.response, default=json_handler, separators=(',',':')), | |||
@@ -68,14 +71,11 @@ def make_logs(): | |||
frappe.response['exc'] = json.dumps([frappe.utils.cstr(d) for d in frappe.local.error_log]) | |||
if frappe.local.message_log: | |||
frappe.response['_server_messages'] = json.dumps([frappe.utils.cstr(d) for d in frappe.local.message_log]) | |||
frappe.response['_server_messages'] = json.dumps([frappe.utils.cstr(d) for | |||
d in frappe.local.message_log]) | |||
if frappe.debug_log and frappe.conf.get("logging") or False: | |||
frappe.response['_debug_messages'] = json.dumps(frappe.local.debug_log) | |||
def cleanup_docs(): | |||
if frappe.response.get('docs') and type(frappe.response['docs'])!=dict: | |||
frappe.response['docs'] = frappe.model.utils.compress(frappe.response['docs']) | |||
def gzip(data, response): | |||
data = data.encode('utf-8') | |||
@@ -107,8 +107,10 @@ def json_handler(obj): | |||
return unicode(obj) | |||
elif isinstance(obj, LocalProxy): | |||
return unicode(obj) | |||
elif isinstance(obj, Document): | |||
elif isinstance(obj, frappe.model.doc.Document): | |||
return obj.fields | |||
elif isinstance(obj, frappe.model.document.Document): | |||
return obj.as_dict() | |||
else: | |||
raise TypeError, """Object of type %s with value of %s is not JSON serializable""" % \ | |||
(type(obj), repr(obj)) | |||
@@ -5,7 +5,7 @@ cur_frm.cscript.refresh = function(doc) { | |||
if(!doc.__islocal && doc.published) { | |||
if(!doc.email_sent) { | |||
cur_frm.add_custom_button('Email Subscribers', function() { | |||
$c_obj(make_doclist(doc.doctype, doc.name), 'send_emails', '', function(r) { | |||
$c_obj(doc, 'send_emails', '', function(r) { | |||
cur_frm.refresh(); | |||
}); | |||
}); | |||
@@ -5,6 +5,7 @@ from __future__ import unicode_literals | |||
import frappe, json | |||
import frappe.model.doc | |||
import frappe.utils | |||
import frappe.widgets.form.meta | |||
@frappe.whitelist() | |||
def getdoc(doctype, name, user=None): | |||
@@ -13,8 +14,6 @@ def getdoc(doctype, name, user=None): | |||
Requries "doctype", "name" as form variables. | |||
Will also call the "onload" method on the document. | |||
""" | |||
import frappe | |||
if not (doctype and name): | |||
raise Exception, 'doctype and name required!' | |||
@@ -26,14 +25,12 @@ def getdoc(doctype, name, user=None): | |||
return [] | |||
try: | |||
bean = frappe.bean(doctype, name) | |||
bean.run_method("onload") | |||
doc = frappe.get_doc(doctype, name) | |||
doc.run_method("onload") | |||
if not bean.has_read_perm(): | |||
if not doc.has_permission("read"): | |||
raise frappe.PermissionError | |||
doclist = bean.doclist | |||
# add file list | |||
get_docinfo(doctype, name) | |||
@@ -42,35 +39,38 @@ def getdoc(doctype, name, user=None): | |||
frappe.msgprint('Did not load.') | |||
raise | |||
if bean and not name.startswith('_'): | |||
if doc and not name.startswith('_'): | |||
frappe.user.update_recent(doctype, name) | |||
frappe.response['docs'] = doclist | |||
frappe.response.docs.append(doc) | |||
@frappe.whitelist() | |||
def getdoctype(doctype, with_parent=False, cached_timestamp=None): | |||
"""load doctype""" | |||
import frappe.model.doctype | |||
import frappe.model.meta | |||
doclist = [] | |||
docs = [] | |||
# with parent (called from report builder) | |||
if with_parent: | |||
parent_dt = frappe.model.meta.get_parent_dt(doctype) | |||
if parent_dt: | |||
doclist = frappe.model.doctype.get(parent_dt, processed=True) | |||
docs = get_meta_bundle(parent_dt) | |||
frappe.response['parent_dt'] = parent_dt | |||
if not doclist: | |||
doclist = frappe.model.doctype.get(doctype, processed=True) | |||
if not docs: | |||
docs = get_meta_bundle(doctype) | |||
frappe.response['restrictions'] = get_restrictions(doclist) | |||
frappe.response['restrictions'] = get_restrictions(docs[0]) | |||
if cached_timestamp and doclist[0].modified==cached_timestamp: | |||
if cached_timestamp and docs[0].modified==cached_timestamp: | |||
return "use_cache" | |||
frappe.response['docs'] = doclist | |||
frappe.response.docs.extend(docs) | |||
def get_meta_bundle(doctype): | |||
bundle = [frappe.widgets.form.meta.get_meta(doctype)] | |||
for df in bundle[0].get_table_fields(): | |||
bundle.append(frappe.widgets.form.meta.get_meta(df.options)) | |||
return bundle | |||
def get_docinfo(doctype, name): | |||
frappe.response["docinfo"] = { | |||
@@ -0,0 +1,157 @@ | |||
# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors | |||
# MIT License. See license.txt | |||
# metadata | |||
from __future__ import unicode_literals | |||
import frappe, os | |||
from frappe.utils import cstr, cint | |||
from frappe.model.meta import Meta | |||
from frappe.modules import scrub, get_module_path | |||
from frappe.model.workflow import get_workflow_name | |||
###### | |||
def get_meta(doctype, cached=True): | |||
if cached: | |||
meta = frappe.cache().get_value("form_meta:" + doctype, lambda: FormMeta(doctype)) | |||
else: | |||
meta = FormMeta(doctype) | |||
if frappe.local.lang != 'en': | |||
meta.set("__messages", frappe.get_lang_dict("doctype", doctype)) | |||
return meta | |||
class FormMeta(Meta): | |||
def __init__(self, doctype): | |||
super(FormMeta, self).__init__(doctype) | |||
self.load_assets() | |||
def load_assets(self): | |||
self.expand_selects() | |||
self.add_search_fields() | |||
if not self.istable: | |||
self.add_linked_with() | |||
self.add_code() | |||
self.load_print_formats() | |||
self.load_workflows() | |||
def as_dict(self): | |||
d = super(FormMeta, self).as_dict() | |||
for k in ("__js", "__css", "__list_js", "__calendar_js", "__map_js", "__linked_with", "__messages"): | |||
d[k] = self.get(k) | |||
for i, df in enumerate(d.get("fields")): | |||
for k in ("link_doctype", "search_fields"): | |||
df[k] = self.get("fields")[i].get(k) | |||
return d | |||
def add_code(self): | |||
path = os.path.join(get_module_path(self.module), 'doctype', scrub(self.name)) | |||
def _get_path(fname): | |||
return os.path.join(path, scrub(fname)) | |||
self._add_code(_get_path(self.name + '.js'), '__js') | |||
self._add_code(_get_path(self.name + '.css'), "__css") | |||
self._add_code(_get_path(self.name + '_list.js'), '__list_js') | |||
self._add_code(_get_path(self.name + '_calendar.js'), '__calendar_js') | |||
self._add_code(_get_path(self.name + '_map.js'), '__map_js') | |||
self.add_custom_script() | |||
self.add_code_via_hook("doctype_js", "__js") | |||
def _add_code(self, path, fieldname): | |||
js = frappe.read_file(path) | |||
if js: | |||
self.set(fieldname, (self.get(fieldname) or "") + "\n\n" + render_jinja(js)) | |||
def add_code_via_hook(self, hook, fieldname): | |||
hook = "{}:{}".format(hook, self.name) | |||
for app_name in frappe.get_installed_apps(): | |||
for file in frappe.get_hooks(hook, app_name=app_name): | |||
path = frappe.get_app_path(app_name, *file.strip("/").split("/")) | |||
self._add_code(path, fieldname) | |||
def add_custom_script(self): | |||
"""embed all require files""" | |||
# custom script | |||
custom = frappe.db.get_value("Custom Script", {"dt": self.name, | |||
"script_type": "Client"}, "script") or "" | |||
self.set("__js", (self.get('__js') or '') + "\n\n" + custom) | |||
def render_jinja(content): | |||
if "{% include" in content: | |||
content = frappe.get_jenv().from_string(content).render() | |||
return content | |||
def expand_selects(self): | |||
for df in self.get("fields", {"fieldtype": "Select"}): | |||
if df.options and df.options.startswith("link:"): | |||
df.link_doctype = df.options.split("\n")[0][5:] | |||
df.options = '\n'.join([''] + [o.name for o in frappe.db.sql("""select | |||
name from `tab%s` where docstatus<2 order by name asc""" % df.link_doctype, as_dict=1)]) | |||
def add_search_fields(self): | |||
"""add search fields found in the doctypes indicated by link fields' options""" | |||
for df in self.get("fields", {"fieldtype": "Link", "options":["!=", "[Select]"]}): | |||
if df.options: | |||
search_fields = frappe.get_meta(df.options).search_fields | |||
if search_fields: | |||
df.search_fields = map(lambda sf: sf.strip(), search_fields.split(",")) | |||
def add_linked_with(self): | |||
"""add list of doctypes this doctype is 'linked' with""" | |||
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) | |||
if not links: | |||
return {} | |||
ret = {} | |||
for dt in links: | |||
ret[dt] = { "fieldname": links[dt] } | |||
for grand_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[grand_parent] = {"child_doctype": options, "fieldname": links[options] } | |||
if options in ret: | |||
del ret[options] | |||
self.set("__linked_with", ret) | |||
def load_print_formats(self): | |||
frappe.response.docs.extend(frappe.db.sql("""select * FROM `tabPrint Format` | |||
WHERE doc_type=%s AND docstatus<2""", (self.name,), as_dict=1, update={"doctype":"Print Format"})) | |||
def load_workflows(self): | |||
# get active workflow | |||
workflow_name = get_workflow_name(self.name) | |||
if workflow_name and frappe.db.exists("Workflow", workflow_name): | |||
workflow = frappe.get_doc("Workflow", workflow_name) | |||
frappe.response.docs.append(workflow) | |||
for d in workflow.get("workflow_document_states"): | |||
frappe.response.docs.append(frappe.get_doc("Workflow State", d.state)) | |||
def render_jinja(content): | |||
if "{% include" in content: | |||
content = frappe.get_jenv().from_string(content).render() | |||
return content | |||
@@ -20,8 +20,6 @@ def runserverobj(): | |||
dt = frappe.form_dict.get('doctype') | |||
dn = frappe.form_dict.get('docname') | |||
frappe.response["docs"] = [] | |||
if dt: # not called from a doctype (from a page) | |||
if not dn: dn = dt # single | |||
so = frappe.model.code.get_obj(dt, dn) | |||
@@ -112,8 +112,6 @@ def get_linked_docs(doctype, name, metadata_loaded=None): | |||
results[dt] = ret | |||
if not dt in metadata_loaded: | |||
if not "docs" in frappe.local.response: | |||
frappe.local.response.docs = [] | |||
frappe.local.response.docs += linkmeta | |||
return results |
@@ -11,14 +11,14 @@ def get(name): | |||
""" | |||
Return the :term:`doclist` of the `Page` specified by `name` | |||
""" | |||
page = frappe.bean("Page", name) | |||
if has_permission(page.doclist): | |||
page.run_method("get_from_files") | |||
return page.doclist | |||
page = frappe.get_doc('Page', name) | |||
if has_permission(page): | |||
page.load_assets() | |||
return page | |||
else: | |||
frappe.response['403'] = 1 | |||
raise frappe.PermissionError, 'No read permission for Page %s' % \ | |||
(page.doclist[0].title or name,) | |||
(page.title or name) | |||
@frappe.whitelist(allow_guest=True) | |||
def getpage(): | |||
@@ -26,24 +26,19 @@ def getpage(): | |||
Load the page from `frappe.form` and send it via `frappe.response` | |||
""" | |||
page = frappe.form_dict.get('name') | |||
doclist = get(page) | |||
doc = get(page) | |||
if has_permission(doclist): | |||
# load translations | |||
if frappe.lang != "en": | |||
frappe.response["__messages"] = frappe.get_lang_dict("page", page) | |||
# load translations | |||
if frappe.lang != "en": | |||
frappe.response["__messages"] = frappe.get_lang_dict("page", page) | |||
frappe.response['docs'] = doclist | |||
else: | |||
frappe.response['403'] = 1 | |||
raise frappe.PermissionError, 'No read permission for Page %s' % \ | |||
(doclist[0].title or page, ) | |||
def has_permission(page_doclist): | |||
frappe.response.docs.append(doc) | |||
def has_permission(page): | |||
if frappe.user.name == "Administrator" or "System Manager" in frappe.user.get_roles(): | |||
return True | |||
page_roles = [d.role for d in page_doclist if d.fields.get("doctype")=="Page Role"] | |||
page_roles = [d.role for d in page.get("roles")] | |||
if page_roles: | |||
if frappe.session.user == "Guest" and "Guest" not in page_roles: | |||
return False | |||
@@ -51,7 +46,7 @@ def has_permission(page_doclist): | |||
# check if roles match | |||
return False | |||
if not frappe.has_permission("Page", ptype="read", refdoc=page_doclist[0].name): | |||
if not frappe.has_permission("Page", ptype="read", doc=page): | |||
# check if there are any restrictions | |||
return False | |||
else: | |||