This is needed for ordering in display of links as it keeps track of the clicks on a particular link itemversion-14
@@ -241,7 +241,7 @@ def address_query(doctype, txt, searchfield, start, page_len, filters): | |||||
{mcond} {condition} | {mcond} {condition} | ||||
order by | order by | ||||
if(locate(%(_txt)s, `tabAddress`.name), locate(%(_txt)s, `tabAddress`.name), 99999), | if(locate(%(_txt)s, `tabAddress`.name), locate(%(_txt)s, `tabAddress`.name), 99999), | ||||
`tabAddress`.name | |||||
`tabAddress`.idx desc, `tabAddress`.name | |||||
limit %(start)s, %(page_len)s """.format( | limit %(start)s, %(page_len)s """.format( | ||||
mcond=get_match_cond(doctype), | mcond=get_match_cond(doctype), | ||||
key=searchfield, | key=searchfield, | ||||
@@ -215,7 +215,7 @@ def contact_query(doctype, txt, searchfield, start, page_len, filters): | |||||
{mcond} | {mcond} | ||||
order by | order by | ||||
if(locate(%(_txt)s, `tabContact`.name), locate(%(_txt)s, `tabContact`.name), 99999), | if(locate(%(_txt)s, `tabContact`.name), locate(%(_txt)s, `tabContact`.name), 99999), | ||||
`tabContact`.name | |||||
`tabContact`.idx desc, `tabContact`.name | |||||
limit %(start)s, %(page_len)s """.format(mcond=get_match_cond(doctype), key=searchfield), { | limit %(start)s, %(page_len)s """.format(mcond=get_match_cond(doctype), key=searchfield), { | ||||
'txt': '%' + txt + '%', | 'txt': '%' + txt + '%', | ||||
'_txt': txt.replace("%", ""), | '_txt': txt.replace("%", ""), | ||||
@@ -707,7 +707,6 @@ class DocType(Document): | |||||
add_column(self.name, "parent", "Data") | add_column(self.name, "parent", "Data") | ||||
add_column(self.name, "parenttype", "Data") | add_column(self.name, "parenttype", "Data") | ||||
add_column(self.name, "parentfield", "Data") | add_column(self.name, "parentfield", "Data") | ||||
add_column(self.name, "idx", "Int", length=8, not_null=True, default="0") | |||||
def get_max_idx(self): | def get_max_idx(self): | ||||
"""Returns the highest `idx`""" | """Returns the highest `idx`""" | ||||
@@ -193,7 +193,7 @@ def get_user_linked_doctypes(doctype, txt, searchfield, start, page_len, filters | |||||
['DocType', 'read_only', '=', 0], ['DocType', 'name', 'like', '%{0}%'.format(txt)]] | ['DocType', 'read_only', '=', 0], ['DocType', 'name', 'like', '%{0}%'.format(txt)]] | ||||
doctypes = frappe.get_all('DocType', fields = ['`tabDocType`.`name`'], filters=filters, | doctypes = frappe.get_all('DocType', fields = ['`tabDocType`.`name`'], filters=filters, | ||||
limit_start=start, limit_page_length=page_len, as_list=1) | |||||
order_by='`tabDocType`.`idx` desc', limit_start=start, limit_page_length=page_len, as_list=1) | |||||
custom_dt_filters = [['Custom Field', 'dt', 'like', '%{0}%'.format(txt)], | custom_dt_filters = [['Custom Field', 'dt', 'like', '%{0}%'.format(txt)], | ||||
['Custom Field', 'options', '=', 'User'], ['Custom Field', 'fieldtype', '=', 'Link']] | ['Custom Field', 'options', '=', 'User'], ['Custom Field', 'fieldtype', '=', 'Link']] | ||||
@@ -38,8 +38,8 @@ class Database(object): | |||||
OPTIONAL_COLUMNS = ["_user_tags", "_comments", "_assign", "_liked_by"] | OPTIONAL_COLUMNS = ["_user_tags", "_comments", "_assign", "_liked_by"] | ||||
DEFAULT_SHORTCUTS = ['_Login', '__user', '_Full Name', 'Today', '__today', "now", "Now"] | DEFAULT_SHORTCUTS = ['_Login', '__user', '_Full Name', 'Today', '__today', "now", "Now"] | ||||
STANDARD_VARCHAR_COLUMNS = ('name', 'owner', 'modified_by') | STANDARD_VARCHAR_COLUMNS = ('name', 'owner', 'modified_by') | ||||
DEFAULT_COLUMNS = ['name', 'creation', 'modified', 'modified_by', 'owner', 'docstatus'] | |||||
CHILD_TABLE_COLUMNS = ('parent', 'parenttype', 'parentfield', 'idx') | |||||
DEFAULT_COLUMNS = ['name', 'creation', 'modified', 'modified_by', 'owner', 'docstatus', 'idx'] | |||||
CHILD_TABLE_COLUMNS = ('parent', 'parenttype', 'parentfield') | |||||
MAX_WRITES_PER_TRANSACTION = 200_000 | MAX_WRITES_PER_TRANSACTION = 200_000 | ||||
class InvalidColumnName(frappe.ValidationError): pass | class InvalidColumnName(frappe.ValidationError): pass | ||||
@@ -171,6 +171,7 @@ CREATE TABLE `tabDocType` ( | |||||
`modified_by` varchar(255) DEFAULT NULL, | `modified_by` varchar(255) DEFAULT NULL, | ||||
`owner` varchar(255) DEFAULT NULL, | `owner` varchar(255) DEFAULT NULL, | ||||
`docstatus` int(1) NOT NULL DEFAULT 0, | `docstatus` int(1) NOT NULL DEFAULT 0, | ||||
`idx` int(8) NOT NULL DEFAULT 0, | |||||
`search_fields` varchar(255) DEFAULT NULL, | `search_fields` varchar(255) DEFAULT NULL, | ||||
`issingle` int(1) NOT NULL DEFAULT 0, | `issingle` int(1) NOT NULL DEFAULT 0, | ||||
`is_tree` int(1) NOT NULL DEFAULT 0, | `is_tree` int(1) NOT NULL DEFAULT 0, | ||||
@@ -24,8 +24,7 @@ class MariaDBTable(DBTable): | |||||
( | ( | ||||
f"parent varchar({varchar_len})", | f"parent varchar({varchar_len})", | ||||
f"parentfield varchar({varchar_len})", | f"parentfield varchar({varchar_len})", | ||||
f"parenttype varchar({varchar_len})", | |||||
"idx int(8) not null default '0'" | |||||
f"parenttype varchar({varchar_len})" | |||||
) | ) | ||||
) + ',\n' | ) + ',\n' | ||||
@@ -37,6 +36,7 @@ class MariaDBTable(DBTable): | |||||
modified_by varchar({varchar_len}), | modified_by varchar({varchar_len}), | ||||
owner varchar({varchar_len}), | owner varchar({varchar_len}), | ||||
docstatus int(1) not null default '0', | docstatus int(1) not null default '0', | ||||
idx int(8) not null default '0', | |||||
{additional_definitions} | {additional_definitions} | ||||
index modified(modified)) | index modified(modified)) | ||||
ENGINE={engine} | ENGINE={engine} | ||||
@@ -176,6 +176,7 @@ CREATE TABLE "tabDocType" ( | |||||
"modified_by" varchar(255) DEFAULT NULL, | "modified_by" varchar(255) DEFAULT NULL, | ||||
"owner" varchar(255) DEFAULT NULL, | "owner" varchar(255) DEFAULT NULL, | ||||
"docstatus" smallint NOT NULL DEFAULT 0, | "docstatus" smallint NOT NULL DEFAULT 0, | ||||
"idx" bigint NOT NULL DEFAULT 0, | |||||
"search_fields" varchar(255) DEFAULT NULL, | "search_fields" varchar(255) DEFAULT NULL, | ||||
"issingle" smallint NOT NULL DEFAULT 0, | "issingle" smallint NOT NULL DEFAULT 0, | ||||
"is_tree" smallint NOT NULL DEFAULT 0, | "is_tree" smallint NOT NULL DEFAULT 0, | ||||
@@ -21,8 +21,7 @@ class PostgresTable(DBTable): | |||||
( | ( | ||||
"parent varchar({varchar_len})", | "parent varchar({varchar_len})", | ||||
"parentfield varchar({varchar_len})", | "parentfield varchar({varchar_len})", | ||||
"parenttype varchar({varchar_len})", | |||||
"idx bigint not null default '0'" | |||||
"parenttype varchar({varchar_len})" | |||||
) | ) | ||||
) | ) | ||||
@@ -35,6 +34,7 @@ class PostgresTable(DBTable): | |||||
modified_by varchar({varchar_len}), | modified_by varchar({varchar_len}), | ||||
owner varchar({varchar_len}), | owner varchar({varchar_len}), | ||||
docstatus smallint not null default '0', | docstatus smallint not null default '0', | ||||
idx bigint not null default '0', | |||||
%s)""" % (self.table_name, add_text)).format(varchar_len=frappe.db.VARCHAR_LEN)) | %s)""" % (self.table_name, add_text)).format(varchar_len=frappe.db.VARCHAR_LEN)) | ||||
self.create_indexes() | self.create_indexes() | ||||
@@ -108,7 +108,7 @@ class DBTable: | |||||
frappe.db.STANDARD_VARCHAR_COLUMNS] | frappe.db.STANDARD_VARCHAR_COLUMNS] | ||||
if self.meta.get("istable"): | if self.meta.get("istable"): | ||||
columns += [frappe._dict({"fieldname": f, "fieldtype": "Data"}) for f in | columns += [frappe._dict({"fieldname": f, "fieldtype": "Data"}) for f in | ||||
frappe.db.CHILD_TABLE_COLUMNS if f != "idx"] | |||||
frappe.db.CHILD_TABLE_COLUMNS] | |||||
columns += self.columns.values() | columns += self.columns.values() | ||||
for col in columns: | for col in columns: | ||||
@@ -147,7 +147,7 @@ def search_widget(doctype, txt, query=None, searchfield=None, start=0, | |||||
from frappe.model.db_query import get_order_by | from frappe.model.db_query import get_order_by | ||||
order_by_based_on_meta = get_order_by(doctype, meta) | order_by_based_on_meta = get_order_by(doctype, meta) | ||||
# 2 is the index of _relevance column | # 2 is the index of _relevance column | ||||
order_by = "_relevance, {0}".format(order_by_based_on_meta) | |||||
order_by = "_relevance, {0}, `tab{1}`.idx desc".format(order_by_based_on_meta, doctype) | |||||
ptype = 'select' if frappe.only_has_select_perm(doctype) else 'read' | ptype = 'select' if frappe.only_has_select_perm(doctype) else 'read' | ||||
ignore_permissions = True if doctype == "DocType" else (cint(ignore_user_permissions) and has_permission(doctype, ptype=ptype)) | ignore_permissions = True if doctype == "DocType" else (cint(ignore_user_permissions) and has_permission(doctype, ptype=ptype)) | ||||
@@ -90,14 +90,14 @@ default_fields = ( | |||||
'creation', | 'creation', | ||||
'modified', | 'modified', | ||||
'modified_by', | 'modified_by', | ||||
'docstatus' | |||||
'docstatus', | |||||
'idx' | |||||
) | ) | ||||
child_table_fields = ( | child_table_fields = ( | ||||
'parent', | 'parent', | ||||
'parentfield', | 'parentfield', | ||||
'parenttype', | |||||
'idx' | |||||
'parenttype' | |||||
) | ) | ||||
optional_fields = ( | optional_fields = ( | ||||
@@ -292,16 +292,16 @@ class BaseDocument(object): | |||||
if key not in self.__dict__: | if key not in self.__dict__: | ||||
self.__dict__[key] = None | self.__dict__[key] = None | ||||
if key == "docstatus" and self.__dict__[key] is None: | |||||
self.__dict__[key] = DocStatus.draft() | |||||
if self.__dict__[key] is None: | |||||
if key == "docstatus": | |||||
self.docstatus = DocStatus.draft() | |||||
elif key == "idx": | |||||
self.__dict__[key] = 0 | |||||
for key in self.get_valid_columns(): | for key in self.get_valid_columns(): | ||||
if key not in self.__dict__: | if key not in self.__dict__: | ||||
self.__dict__[key] = None | self.__dict__[key] = None | ||||
if key == "idx" and self.__dict__[key] is None: | |||||
self.__dict__[key] = 0 | |||||
def get_valid_columns(self): | def get_valid_columns(self): | ||||
if self.doctype not in frappe.local.valid_columns: | if self.doctype not in frappe.local.valid_columns: | ||||
if self.doctype in DOCTYPES_FOR_DOCTYPE: | if self.doctype in DOCTYPES_FOR_DOCTYPE: | ||||
@@ -232,7 +232,6 @@ def check_if_doc_is_linked(doc, method="Delete"): | |||||
if frappe.get_meta(link_dt).istable: | if frappe.get_meta(link_dt).istable: | ||||
fields.extend(["parent", "parenttype"]) | fields.extend(["parent", "parenttype"]) | ||||
# NOTE: scenario: parent doc <-(linked to) child table doc <-(linked to) doc | |||||
for item in frappe.db.get_values(link_dt, {link_field:doc.name}, fields , as_dict=True): | for item in frappe.db.get_values(link_dt, {link_field:doc.name}, fields , as_dict=True): | ||||
# available only in child table cases | # available only in child table cases | ||||
item_parent = getattr(item, "parent", None) | item_parent = getattr(item, "parent", None) | ||||
@@ -184,7 +184,7 @@ def map_fields(source_doc, target_doc, table_map, source_parent): | |||||
target_doc.set(fmap[1], val) | target_doc.set(fmap[1], val) | ||||
# map idx | # map idx | ||||
if source_doc.get("idx"): | |||||
if source_doc.idx: | |||||
target_doc.idx = source_doc.idx | target_doc.idx = source_doc.idx | ||||
# add fetch | # add fetch | ||||
@@ -10,7 +10,7 @@ $.extend(frappe.model, { | |||||
layout_fields: ['Section Break', 'Column Break', 'Tab Break', 'Fold'], | layout_fields: ['Section Break', 'Column Break', 'Tab Break', 'Fold'], | ||||
std_fields_list: ['name', 'owner', 'creation', 'modified', 'modified_by', | std_fields_list: ['name', 'owner', 'creation', 'modified', 'modified_by', | ||||
'_user_tags', '_comments', '_assign', '_liked_by', 'docstatus'], | |||||
'_user_tags', '_comments', '_assign', '_liked_by', 'docstatus', 'idx'], | |||||
core_doctypes_list: ['DocType', 'DocField', 'DocPerm', 'User', 'Role', 'Has Role', | core_doctypes_list: ['DocType', 'DocField', 'DocPerm', 'User', 'Role', 'Has Role', | ||||
'Page', 'Module Def', 'Print Format', 'Report', 'Customize Form', | 'Page', 'Module Def', 'Print Format', 'Report', 'Customize Form', | ||||
@@ -19,6 +19,7 @@ $.extend(frappe.model, { | |||||
std_fields: [ | std_fields: [ | ||||
{fieldname:'name', fieldtype:'Link', label:__('ID')}, | {fieldname:'name', fieldtype:'Link', label:__('ID')}, | ||||
{fieldname:'owner', fieldtype:'Link', label:__('Created By'), options: 'User'}, | {fieldname:'owner', fieldtype:'Link', label:__('Created By'), options: 'User'}, | ||||
{fieldname:'idx', fieldtype:'Int', label:__('Index')}, | |||||
{fieldname:'creation', fieldtype:'Date', label:__('Created On')}, | {fieldname:'creation', fieldtype:'Date', label:__('Created On')}, | ||||
{fieldname:'modified', fieldtype:'Date', label:__('Last Updated On')}, | {fieldname:'modified', fieldtype:'Date', label:__('Last Updated On')}, | ||||
{fieldname:'modified_by', fieldtype:'Data', label:__('Last Updated By')}, | {fieldname:'modified_by', fieldtype:'Data', label:__('Last Updated By')}, | ||||
@@ -106,6 +106,7 @@ def get_other_fields_meta(meta): | |||||
'modified_by': ('Data', 0), | 'modified_by': ('Data', 0), | ||||
'creation': ('Datetime', 0), | 'creation': ('Datetime', 0), | ||||
'modified': ('Datetime', 0), | 'modified': ('Datetime', 0), | ||||
'idx': ('Int', 8), | |||||
'docstatus': ('Check', 0) | 'docstatus': ('Check', 0) | ||||
} | } | ||||
@@ -115,8 +116,7 @@ def get_other_fields_meta(meta): | |||||
child_table_fields_map = {} | child_table_fields_map = {} | ||||
if meta.istable: | if meta.istable: | ||||
child_table_fields_map.update({field: ('Data', 0) for field in frappe.db.CHILD_TABLE_COLUMNS if field != 'idx'}) | |||||
child_table_fields_map.update({'idx': ('Int', 8)}) | |||||
child_table_fields_map.update({field: ('Data', 0) for field in frappe.db.CHILD_TABLE_COLUMNS}) | |||||
optional_fields_map = {field: ('Text', 0) for field in optional_fields} | optional_fields_map = {field: ('Text', 0) for field in optional_fields} | ||||
fields = dict(default_fields_map, **optional_fields_map, **child_table_fields_map) | fields = dict(default_fields_map, **optional_fields_map, **child_table_fields_map) | ||||
@@ -118,6 +118,7 @@ class WebsiteGenerator(Document): | |||||
"doc": self, | "doc": self, | ||||
"page_or_generator": "Generator", | "page_or_generator": "Generator", | ||||
"ref_doctype":self.doctype, | "ref_doctype":self.doctype, | ||||
"idx": self.idx, | |||||
"docname": self.name, | "docname": self.name, | ||||
"controller": get_module_name(self.doctype, self.meta.module), | "controller": get_module_name(self.doctype, self.meta.module), | ||||
}) | }) | ||||