From b9d84ee39df0810bf59eba02c3486997fcdbc679 Mon Sep 17 00:00:00 2001 From: Anand Doshi Date: Tue, 22 Nov 2011 11:09:48 +0530 Subject: [PATCH] Changes in doclayer and doctype --- py/core/doctype/doclayer/doclayer.js | 5 +- py/core/doctype/doclayer/doclayer.py | 194 +++++++++++++++++++++++++-- py/webnotes/model/doctype.py | 64 +++++++-- 3 files changed, 244 insertions(+), 19 deletions(-) diff --git a/py/core/doctype/doclayer/doclayer.js b/py/core/doctype/doclayer/doclayer.js index ec97de2db8..f76d1fb157 100644 --- a/py/core/doctype/doclayer/doclayer.js +++ b/py/core/doctype/doclayer/doclayer.js @@ -1,13 +1,14 @@ cur_frm.cscript.doc_type = function(doc, dt, dn) { //console.log(doc); //console.log(doc_type); + $c_obj(make_doclist(dt, dn), 'get', '', function(r, rt) { cur_frm.refresh(); //console.log(arguments); }); } -cur_frm.cscript.onload_post_render = function(doc, dt, dn) { +cur_frm.cscript.refresh = function(doc, dt, dn) { cur_frm.frm_head.page_head.buttons.Save.hidden=1; cur_frm.page_layout.footer.hidden = 1; cur_frm.add_custom_button('Update', function() { @@ -16,5 +17,5 @@ cur_frm.cscript.onload_post_render = function(doc, dt, dn) { console.log(arguments); }); } - }); + },1); } diff --git a/py/core/doctype/doclayer/doclayer.py b/py/core/doctype/doclayer/doclayer.py index 1850a2a489..f6d9094b8d 100644 --- a/py/core/doctype/doclayer/doclayer.py +++ b/py/core/doctype/doclayer/doclayer.py @@ -2,6 +2,7 @@ DocLayer is a Single DocType used to mask the Property Setter Thus providing a better UI from user perspective """ +import webnotes class DocType: def __init__(self, doc, doclist=[]): @@ -20,6 +21,7 @@ class DocType: 'max_attachments' ] self.docfield_properties = [ + 'idx', 'label', 'fieldtype', 'fieldname', @@ -39,18 +41,17 @@ class DocType: 'name' ] + def get(self): """ Gets DocFields applied with Property Setter customizations via DocLayerField """ - from webnotes.model.doctype import get - from webnotes.model.doc import addchild - import webnotes - self.clear() if self.doc.doc_type: - for d in get(self.doc.doc_type): + from webnotes.model.doc import addchild + + for d in self.get_ref_doclist(): if d.doctype=='DocField': new = addchild(self.doc, 'fields', 'DocLayerField', 1, self.doclist) self.set( @@ -63,11 +64,20 @@ class DocType: elif d.doctype=='DocType': self.set({ 'list': self.doctype_properties, 'doc': d }) - def post(self): + + def get_ref_doclist(self): """ - Save diff between DocLayer DocList and DocType DocList as property setter entries + * Gets doclist of type self.doc.doc_type + * Applies property setter properties on the doclist + * returns the modified doclist """ - pass + from webnotes.model.doctype import _DocType + from webnotes.model.doc import get + + ref_doclist = get('DocType', self.doc.doc_type) + _DocType(self.doc.doc_type)._override_field_properties(ref_doclist) + + return ref_doclist def clear(self): @@ -101,6 +111,172 @@ class DocType: for f in args['list']: args['doc_to_set'].fields[f] = args['doc'].fields[f] else: - import webnotes webnotes.msgprint("Please specify args['list'] to set", raise_exception=1) + + def post(self): + """ + Save diff between DocLayer DocList and DocType DocList as property setter entries + """ + if self.doc.doc_type: + from webnotes.model import doc + from webnotes.model.doctype import get + + this_doclist = [self.doc] + self.doclist + ref_doclist = self.get_ref_doclist() + dt_doclist = doc.get('DocType', self.doc.doc_type) + + # get a list of property setter docs + diff_list = self.diff(this_doclist, ref_doclist, dt_doclist) + + webnotes.msgprint('this doc') + webnotes.msgprint([[d.name, d.idx, 'label' in d.fields and d.label or None] for d in this_doclist]) + webnotes.msgprint('ref doc') + webnotes.msgprint([[d.name, d.idx, 'label' in d.fields and d.label or None] for d in ref_doclist]) + webnotes.msgprint('def doc') + webnotes.msgprint([[d.name, d.idx, 'label' in d.fields and d.label or None] for d in dt_doclist]) + + self.set_properties(diff_list) + + webnotes.msgprint('End of Post') + webnotes.msgprint([[d.fields['property'], d.fields['value'], d.fields['doc_name'], d.fields['select_item'], 'delete' in d.fields and d.fields['delete'] or None] for d in diff_list]) + + + def diff(self, new_dl, ref_dl, dt_dl): + """ + Get difference between new_dl doclist and ref_dl doclist + then check how it differs from dt_dl i.e. default doclist + """ + import re + self.defaults = self.get_defaults() + diff_list = [] + for new_d in new_dl: + for ref_d in ref_dl: + if ref_d.doctype == 'DocField' and new_d.name == ref_d.name: + for prop in self.docfield_properties: + d = self.prepare_to_set(prop, new_d, ref_d, dt_dl) + if d: diff_list.append(d) + break + + elif ref_d.doctype == 'DocType' and new_d.doctype == 'DocLayer': + for prop in self.doctype_properties: + d = self.prepare_to_set(prop, new_d, ref_d, dt_dl) + if d: diff_list.append(d) + break + + return diff_list + + + def get_defaults(self): + """ + Get fieldtype and default value for properties of a field + """ + df_defaults = webnotes.conn.sql(""" + SELECT fieldname, fieldtype, `default`, label + FROM `tabDocField` + WHERE parent='DocField' or parent='DocType'""", as_dict=1) + + defaults = {} + for d in df_defaults: + fieldname = d['fieldname'] + del d['fieldname'] + defaults[fieldname] = d + defaults['idx'] = {'fieldtype' : 'Int', 'default' : 1, 'label' : 'idx'} + defaults['previous_field'] = {'fieldtype' : 'Data', 'default' : None, 'label' : 'Previous Field'} + return defaults + + + def prepare_to_set(self, prop, new_d, ref_d, dt_doclist, delete=0): + """ + Prepares docs of property setter + sets delete property if it is required to be deleted + """ + # Check if property has changed compared to when it was loaded + if new_d.fields[prop] != ref_d.fields[prop] \ + and not \ + ( \ + new_d.fields[prop] in [None, 0] \ + and ref_d.fields[prop] in [None, 0] \ + ) and not \ + ( \ + new_d.fields[prop] in [None, ''] \ + and ref_d.fields[prop] in [None, ''] \ + ): + # Check if the new property is same as that in original doctype + # If yes, we need to delete the property setter entry + for dt_d in dt_doclist: + if dt_d.name == ref_d.name \ + and (new_d.fields[prop] == dt_d.fields[prop] \ + or \ + ( \ + new_d.fields[prop] in [None, 0] \ + and dt_d.fields[prop] in [None, 0] \ + ) or \ + ( \ + new_d.fields[prop] in [None, ''] \ + and dt_d.fields[prop] in [None, ''] \ + )): + delete = 1 + break + + value = new_d.fields[prop] + + if prop == 'idx': + if value > 1: + for idoc in ([self.doc] + self.doclist): + if idoc.fields[prop] == (value - 1): + prop = 'previous_field' + value = idoc.name + break + elif value == 1: + prop = 'previous_field' + value = None + + # If the above conditions are fulfilled, + # create a property setter doc, but dont save it yet. + from webnotes.model.doc import Document + d = Document('Property Setter') + d.doctype_or_field = ref_d.doctype=='DocField' and 'DocField' or 'DocType' + d.doc_type = self.doc.doc_type + d.doc_name = ref_d.name + d.property = prop + d.value = value + d.property_type = self.defaults[prop]['fieldtype'] + d.default_value = self.defaults[prop]['default'] + d.select_doctype = self.doc.doc_type + d.select_item = ref_d.label and str(ref_d.idx) \ + + " - " + str(ref_d.label) \ + + " (" + str(ref_d.fieldtype) + ")" \ + or None + d.select_property = self.defaults[prop]['label'] + if delete: d.delete = 1 + + # return the property setter doc + return d + + + def set_properties(self, ps_doclist): + """ + * Delete a property setter entry + + if it already exists + + if marked for deletion + * Save the property setter doc in the list + """ + for d in ps_doclist: + # Check if the property setter doc already exists + res = webnotes.conn.sql(""" + SELECT * FROM `tabProperty Setter` + WHERE doc_type = %(doc_type)s + AND doc_name = %(doc_name)s + AND property = %(property)s""", d.fields) + + if res and res[0][0]: + webnotes.conn.sql(""" + DELETE FROM `tabProperty Setter` + WHERE doc_type = %(doc_type)s + AND doc_name = %(doc_name)s + AND property = %(property)s""", d.fields) + + # Save the property setter doc if not marked for deletion i.e. delete=0 + if not d.delete: + d.save(1) diff --git a/py/webnotes/model/doctype.py b/py/webnotes/model/doctype.py index 773d247095..fd3b43c571 100644 --- a/py/webnotes/model/doctype.py +++ b/py/webnotes/model/doctype.py @@ -206,9 +206,10 @@ class _DocType: dt = doclist[0].name try: for f in webnotes.conn.sql("select doc_name, property, property_type, value from `tabProperty Setter` where doc_type=%s", dt, as_dict=1): - if not f['doc_name'] in property_dict: - property_dict[f['doc_name']] = [] - property_dict[f['doc_name']].append(f) + #if not f['doc_name'] in property_dict: + # property_dict[f['doc_name']] = [] + #property_dict[f['doc_name']].append(f) + property_dict[f['doc_name']] = f except Exception, e: if e.args[0]==1146: # no override table @@ -216,14 +217,20 @@ class _DocType: else: raise e + # loop over fields and override property for d in doclist: if d.doctype=='DocField' and d.name in property_dict: - for p in property_dict[d.name]: - if p['property_type']=='Check': - d.fields[p['property']] = int(p['value']) - else: - d.fields[p['property']] = p['value'] + #for p in property_dict[d.name]: + p = property_dict[d.name] + if p['property_type']=='Check': + d.fields[p['property']] = int(p['value']) + elif p['property']=='previous_field': + continue + else: + d.fields[p['property']] = p['value'] + + self.change_doclist_idx(doclist, property_dict) # override properties in the main doctype if dt in property_dict: @@ -231,6 +238,47 @@ class _DocType: doclist[0].fields[p['property']] = p['value'] + def change_doclist_idx(self, doclist, property_dict): + """ + + """ + docfields = [] + sorted_doclist = sorted([dl for dl in doclist if dl.doctype=='DocField'], key=lambda dl: dl.idx) + old_order = [d.name for d in sorted_doclist] + property_list = [] + import webnotes + for p in property_dict.values(): + if p['property']=='previous_field': + property_list.append([p['value'], p['doc_name']]) + + nf = [p for p in property_list if p[0] is None] + + while(old_order): + if nf: + property_list.remove(nf[0]) + next_field = nf[0][1] + else: + for o in old_order: + if not (o in docfields): + next_field = o + old_order.remove(o) + break + else: + old_order.remove(o) + docfields.append(next_field) + nf = property_list and [p for p in property_list if p[0]==next_field] or None + + webnotes.msgprint(docfields) + + + for d in doclist: + if d.doctype == 'DocField': + d.idx = docfields.index(d.name) + 1 + + for d in sorted([dl for dl in doclist if dl.doctype=='DocField'], key=lambda dl: dl.idx): + webnotes.msgprint(str(d.idx) + " | " + str(d.label)) + + def make_doclist(self): """ returns the :term:`doclist` for consumption by the client