Merge branch 'item-variants' into v5.0

Conflicts:
	frappe/api.py
	frappe/core/doctype/custom_field/custom_field.json
	frappe/core/doctype/customize_form_field/customize_form_field.json
This commit is contained in:
Rushabh Mehta 2014-09-29 12:33:28 +05:30
commit e7c4e4ef13
13 changed files with 149 additions and 87 deletions

View file

@ -90,7 +90,7 @@ def handle():
if frappe.local.form_dict.get('fields'):
frappe.local.form_dict['fields'] = json.loads(frappe.local.form_dict['fields'])
frappe.local.response.update({
"data": frappe.call(frappe.desk.reportview.execute,
"data": frappe.call(frappe.client.get_list,
doctype, **frappe.local.form_dict)})
if frappe.local.request.method=="POST":

View file

@ -8,6 +8,12 @@ import frappe.model
import frappe.utils
import json, os
@frappe.whitelist()
def get_list(doctype, fields=None, filters=None, order_by=None,
limit_start=None, limit_page_length=None):
return frappe.get_list(doctype, fields=fields, filters=filters, order_by=order_by,
limit_start=limit_start, limit_page_length=limit_page_length)
@frappe.whitelist()
def get(doctype, name=None, filters=None):
if filters and not name:

View file

@ -78,6 +78,13 @@
"search_index": 0,
"width": "50px"
},
{
"fieldname": "unique",
"fieldtype": "Check",
"label": "Unique",
"permlevel": 0,
"precision": ""
},
{
"fieldname": "in_list_view",
"fieldtype": "Check",
@ -314,7 +321,7 @@
"in_dialog": 1,
"issingle": 0,
"istable": 1,
"modified": "2014-09-05 07:41:05.956027",
"modified": "2014-09-26 05:03:44.822570",
"modified_by": "Administrator",
"module": "Core",
"name": "DocField",

View file

@ -145,6 +145,13 @@
"permlevel": 0,
"search_index": 0
},
{
"fieldname": "unique",
"fieldtype": "Check",
"label": "Unique",
"permlevel": 0,
"precision": ""
},
{
"fieldname": "read_only",
"fieldtype": "Check",
@ -267,7 +274,7 @@
],
"icon": "icon-glass",
"idx": 1,
"modified": "2014-09-05 07:41:13.076821",
"modified": "2014-09-26 05:04:49.148737",
"modified_by": "Administrator",
"module": "Custom",
"name": "Custom Field",

View file

@ -31,6 +31,7 @@ class CustomizeForm(Document):
'width': 'Data',
'print_width': 'Data',
'reqd': 'Check',
'unique': 'Check',
'ignore_user_permissions': 'Check',
'in_filter': 'Check',
'in_list_view': 'Check',

View file

@ -68,6 +68,13 @@
"search_index": 0,
"width": "50px"
},
{
"fieldname": "unique",
"fieldtype": "Check",
"label": "Unique",
"permlevel": 0,
"precision": ""
},
{
"fieldname": "in_list_view",
"fieldtype": "Check",
@ -278,7 +285,7 @@
"idx": 1,
"issingle": 0,
"istable": 1,
"modified": "2014-09-05 07:41:29.641455",
"modified": "2014-09-26 05:06:37.372435",
"modified_by": "Administrator",
"module": "Custom",
"name": "Customize Form Field",

View file

@ -30,6 +30,7 @@ CREATE TABLE `tabDocField` (
`print_hide` int(1) DEFAULT NULL,
`report_hide` int(1) DEFAULT NULL,
`reqd` int(1) DEFAULT NULL,
`unique` int(1) DEFAULT NULL,
`no_copy` int(1) DEFAULT NULL,
`allow_on_submit` int(1) DEFAULT NULL,
`trigger` varchar(255) DEFAULT NULL,

View file

@ -7,9 +7,13 @@ import frappe
import json
no_value_fields = ['Section Break', 'Column Break', 'HTML', 'Table', 'Button', 'Image', 'Fold']
default_fields = ['doctype','name','owner','creation','modified','modified_by','parent','parentfield','parenttype','idx','docstatus']
integer_docfield_properties = ["reqd", "search_index", "in_list_view", "permlevel", "hidden", "read_only", "ignore_user_permissions", "allow_on_submit", "report_hide", "in_filter", "no_copy", "print_hide"]
no_value_fields = ['Section Break', 'Column Break', 'HTML', 'Table', 'Button',
'Image', 'Fold']
default_fields = ['doctype','name','owner','creation','modified','modified_by',
'parent','parentfield','parenttype','idx','docstatus']
integer_docfield_properties = ["reqd", "search_index", "in_list_view", "permlevel",
"hidden", "read_only", "ignore_user_permissions", "allow_on_submit", "report_hide",
"in_filter", "no_copy", "print_hide", "unique"]
def insert(doclist):
if not isinstance(doclist, list):

View file

@ -217,11 +217,20 @@ class BaseDocument(object):
d = self.get_valid_dict()
columns = d.keys()
frappe.db.sql("""update `tab{doctype}`
set {values} where name=%s""".format(
doctype = self.doctype,
values = ", ".join(["`"+c+"`=%s" for c in columns])
), d.values() + [d.get("name")])
try:
frappe.db.sql("""update `tab{doctype}`
set {values} where name=%s""".format(
doctype = self.doctype,
values = ", ".join(["`"+c+"`=%s" for c in columns])
), d.values() + [d.get("name")])
except Exception, e:
if e.args[0]==1062:
type, value, traceback = sys.exc_info()
fieldname = str(e).split("'")[-2]
frappe.msgprint(_("{0} must be unique".format(self.meta.get_label(fieldname))))
raise frappe.ValidationError, (self.doctype, self.name, e), traceback
else:
raise
def db_set(self, fieldname, value):
self.set(fieldname, value)

View file

@ -223,10 +223,13 @@ class DatabaseQuery(object):
if not isinstance(f, (list, tuple)):
frappe.throw("Filter must be a tuple or list (in a list)")
if len(f) != 4:
if len(f) == 3:
f = (self.doctype, f[0], f[1], f[2])
elif len(f) != 4:
frappe.throw("Filter must have 4 values (doctype, fieldname, condition, value): " + str(f))
return f
return list(f)
def build_match_conditions(self, as_condition=True):
"""add match conditions if applicable"""

View file

@ -36,14 +36,27 @@ type_map = {
,'Attach': ('varchar', '255')
}
default_columns = ['name', 'creation', 'modified', 'modified_by', 'owner', 'docstatus', 'parent',\
'parentfield', 'parenttype', 'idx']
default_columns = ['name', 'creation', 'modified', 'modified_by', 'owner',
'docstatus', 'parent', 'parentfield', 'parenttype', 'idx']
default_shortcuts = ['_Login', '__user', '_Full Name', 'Today', '__today']
# -------------------------------------------------
# Class database table
# -------------------------------------------------
def updatedb(dt):
"""
Syncs a `DocType` to the table
* creates if required
* updates columns
* updates indices
"""
res = frappe.db.sql("select ifnull(issingle, 0) from tabDocType where name=%s", (dt,))
if not res:
raise Exception, 'Wrong doctype "%s" in updatedb' % dt
if not res[0][0]:
frappe.db.commit()
tab = DbTable(dt, 'tab')
tab.sync()
frappe.db.begin()
class DbTable:
def __init__(self, doctype, prefix = 'tab'):
@ -55,13 +68,21 @@ class DbTable:
# lists for change
self.add_column = []
self.change_type = []
self.add_index = []
self.drop_index = []
self.set_default = []
# load
self.get_columns_from_docfields()
def sync(self):
if not self.name in DbManager(frappe.db).get_tables_list(frappe.db.cur_db_name):
self.create()
else:
self.alter()
def create(self):
add_text = ''
@ -89,31 +110,6 @@ class DbTable:
ENGINE=InnoDB
CHARACTER SET=utf8""" % (self.name, add_text))
def get_columns_from_docfields(self):
"""
get columns from docfields and custom fields
"""
fl = frappe.db.sql("SELECT * FROM tabDocField WHERE parent = %s", self.doctype, as_dict = 1)
try:
custom_fl = frappe.db.sql("""\
SELECT * FROM `tabCustom Field`
WHERE dt = %s AND docstatus < 2""", (self.doctype,), as_dict=1)
if custom_fl: fl += custom_fl
except Exception, e:
if e.args[0]!=1146: # ignore no custom field
raise
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.get('options'))
def get_columns_from_db(self):
self.show_columns = frappe.db.sql("desc `%s`" % self.name)
for c in self.show_columns:
self.current_columns[c[0]] = {'name': c[0], 'type':c[1], 'index':c[3], 'default':c[4]}
def get_column_definitions(self):
column_list = [] + default_columns
ret = []
@ -133,6 +129,31 @@ class DbTable:
ret.append('index `' + key + '`(`' + key + '`)')
return ret
def get_columns_from_docfields(self):
"""
get columns from docfields and custom fields
"""
fl = frappe.db.sql("SELECT * FROM tabDocField WHERE parent = %s", self.doctype, as_dict = 1)
try:
custom_fl = frappe.db.sql("""\
SELECT * FROM `tabCustom Field`
WHERE dt = %s AND docstatus < 2""", (self.doctype,), as_dict=1)
if custom_fl: fl += custom_fl
except Exception, e:
if e.args[0]!=1146: # ignore no custom field
raise
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.get('options'), f.get('unique'))
def get_columns_from_db(self):
self.show_columns = frappe.db.sql("desc `%s`" % self.name)
for c in self.show_columns:
self.current_columns[c[0]] = {'name': c[0],
'type':c[1], 'index':c[3]=="MUL", 'default':c[4], "unique":c[3]=="UNI"}
# GET foreign keys
def get_foreign_keys(self):
@ -165,16 +186,10 @@ class DbTable:
frappe.db.sql("alter table `%s` drop foreign key `%s`" % (self.name, fk_dict[col.fieldname]))
frappe.db.sql("set foreign_key_checks=1")
def sync(self):
if not self.name in DbManager(frappe.db).get_tables_list(frappe.db.cur_db_name):
self.create()
else:
self.alter()
def alter(self):
self.get_columns_from_db()
for col in self.columns.values():
col.check(self.current_columns.get(col.fieldname, None))
col.build_for_alter_table(self.current_columns.get(col.fieldname, None))
query = []
@ -193,11 +208,12 @@ class DbTable:
for col in self.drop_index:
if col.fieldname != 'name': # primary key
# if index key exists
if frappe.db.sql("show index from `%s` where key_name = %s" %
(self.name, '%s'), col.fieldname):
if frappe.db.sql("""show index from `{0}`
where key_name=%s
and Non_unique=%s""".format(self.name), (col.fieldname, 1 if col.unique else 0)):
query.append("drop index `{}`".format(col.fieldname))
for col in list(set(self.set_default).difference(set(self.change_type))):
for col in self.set_default:
if col.fieldname=="name":
continue
@ -212,7 +228,8 @@ class DbTable:
frappe.db.sql("alter table `{}` {}".format(self.name, ", ".join(query)))
class DbColumn:
def __init__(self, table, fieldname, fieldtype, length, default, set_index, options):
def __init__(self, table, fieldname, fieldtype, length, default,
set_index, options, unique):
self.table = table
self.fieldname = fieldname
self.fieldtype = fieldtype
@ -220,18 +237,22 @@ class DbColumn:
self.set_index = set_index
self.default = default
self.options = options
self.unique = unique
def get_definition(self, with_default=1):
ret = get_definition(self.fieldtype)
def get_definition(self):
column_def = get_definition(self.fieldtype)
if with_default and self.default and (self.default not in default_shortcuts) \
and not self.default.startswith(":") and ret not in ['text', 'longtext']:
ret += ' default "' + self.default.replace('"', '\"') + '"'
if self.default and (self.default not in default_shortcuts) \
and not self.default.startswith(":") and column_def not in ['text', 'longtext']:
column_def += ' default "' + self.default.replace('"', '\"') + '"'
return ret
if self.unique:
column_def += ' unique'
def check(self, current_def):
column_def = self.get_definition(0)
return column_def
def build_for_alter_table(self, current_def):
column_def = get_definition(self.fieldtype)
# no columns
if not column_def:
@ -244,20 +265,27 @@ class DbColumn:
return
# type
if current_def['type'] != column_def:
if (current_def['type'] != column_def) or (self.unique and not current_def['unique']):
self.table.change_type.append(self)
# index
else:
# index
if (current_def['index'] and not self.set_index):
self.table.drop_index.append(self)
if (current_def['unique'] and not self.unique):
self.table.drop_index.append(self)
if (not current_def['index'] and self.set_index and not (column_def in ['text', 'longtext'])):
self.table.add_index.append(self)
# default
if (self.default_changed(current_def) and (self.default not in default_shortcuts) and not cstr(self.default).startswith(":") and not (column_def in ['text','longtext'])):
self.table.set_default.append(self)
# default
if (self.default_changed(current_def) \
and (self.default not in default_shortcuts) \
and not cstr(self.default).startswith(":") \
and not (column_def in ['text','longtext'])):
self.table.set_default.append(self)
def default_changed(self, current_def):
@ -373,22 +401,6 @@ def validate_column_name(n):
return n
def updatedb(dt):
"""
Syncs a `DocType` to the table
* creates if required
* updates columns
* updates indices
"""
res = frappe.db.sql("select ifnull(issingle, 0) from tabDocType where name=%s", (dt,))
if not res:
raise Exception, 'Wrong doctype "%s" in updatedb' % dt
if not res[0][0]:
frappe.db.commit()
tab = DbTable(dt, 'tab')
tab.sync()
frappe.db.begin()
def remove_all_foreign_keys():
frappe.db.sql("set foreign_key_checks = 0")
@ -417,8 +429,8 @@ def get_definition(fieldtype):
ret += '(' + d[1] + ')'
return ret
def add_column(doctype, column_name, fieldtype):
"""Add a column to the database"""
frappe.db.commit()
frappe.db.sql("alter table `tab%s` add column %s %s" % (doctype,
column_name, get_definition(fieldtype)))

View file

@ -190,7 +190,12 @@ frappe.ui.form.ControlInput = frappe.ui.form.Control.extend({
me.disp_area && $(me.disp_area).toggle(false);
$(me.input_area).toggle(true);
$(me.input_area).find("input").prop("disabled", false);
!me.has_input && me.make_input();
if(!me.has_input) {
me.make_input();
if(me.df.on_make) {
me.df.on_make(me);
}
};
if(me.doctype && me.docname)
me.set_input(me.value);
} else {

View file

@ -508,7 +508,7 @@ frappe.ui.form.GridRow = Class.extend({
<div class="panel-body">\
<div class="form-area"></div>\
<div class="toolbar footer-toolbar" style="margin-top: 15px">\
<span class="text-muted"><a href="#" class="shortcuts"><i class="icon-keyboard"></i>' + __("Shortcuts") + '</a></span>\
<span class="text-muted"><a href="#" class="shortcuts"> <i class="icon-keyboard"></i>' + __("Shortcuts") + '</a></span>\
<span class="text-success pull-right grid-toggle-row" \
title="'+__("Close")+'"\
style="margin-left: 7px; cursor: pointer;">\