def doGenericFuntion(sQBE): """ Se define una tabla de funciones genericas q seran ejectua dinamicamente por pyton se ejectuan en el contexto actual, se deberia pasar algunas rutinas basicas en la medida q sean necesarias getModels Esta rutina servira tambien para desencadenar reglas de gestion sobre modelos y podria ser la base de la ejecucion del wKflow """ from utilsBase import explode # obtiene los parametros fCall = explode(sQBE[1:]) # obtiene la definicion de la funcion from models import PtFunction, getDjangoModel fBase = PtFunction.objects.get(code=fCall[0]) # Construyte las variables de entorno myVars = { 'model' : getDjangoModel(fBase.modelName) } arguments = fBase.arguments.split(',') params = fCall[1].split(',') for i in range(0 , len(arguments)): myVars[ arguments[i] ] = params[i] # ejecta y toma la base exec(fBase.functionBody, myVars) return myVars [ 'ret' ]
def doGenericFuntion(sQBE): """ Se define una tabla de funciones genericas q seran ejectua dinamicamente por pyton se ejectuan en el contexto actual, se deberia pasar algunas rutinas basicas en la medida q sean necesarias getModels Esta rutina servira tambien para desencadenar reglas de gestion sobre modelos y podria ser la base de la ejecucion del wKflow """ from utilsBase import explode # obtiene los parametros fCall = explode(sQBE[1:]) # obtiene la definicion de la funcion from models import PtFunction, getDjangoModel fBase = PtFunction.objects.get(code=fCall[0]) # Construyte las variables de entorno myVars = {'model': getDjangoModel(fBase.modelName)} arguments = fBase.arguments.split(',') params = fCall[1].split(',') for i in range(0, len(arguments)): myVars[arguments[i]] = params[i] # ejecta y toma la base exec(fBase.functionBody, myVars) return myVars['ret']
def getFieldIncrement(request): success = False fieldName = request.GET['fieldName'] viewEntity = request.GET['viewEntity'] try: model = getDjangoModel(viewEntity) except : return JsonError('model not found:' + viewEntity) fieldType = model._meta.get_field(fieldName).get_internal_type() increment = 0 if fieldType == 'IntegerField': maxid = model.objects.aggregate(Max('id')) if maxid['id__max']: increment = maxid['id__max'] + 1 else: increment = 1 else: return JsonError('Invalid field type') if increment > 0: success = True jsondict = { 'success': success, 'increment': increment } json_data = json.dumps(jsondict) return HttpResponse(json_data, content_type="application/json")
def protoGetFieldTree(request): """ return full field tree """ if request.method != 'POST': return JsonError('Invalid message') viewCode = request.POST.get('viewCode', '') viewEntity = getBaseModelName(viewCode) try: model = getDjangoModel(viewEntity) except Exception as e: return JsonError(getReadableError(e)) fieldList = [] if viewCode.startswith(PROTO_PREFIX) and viewCode != viewEntity : # --------------------------------------------------- Prototipos protoEntityId = request.POST.get('protoEntityId') if not protoEntityId >= 0: return JsonError('invalid idEntity') try: from prototype.actions.viewDefinition import GetProtoFieldsTree fieldList = GetProtoFieldsTree(protoEntityId) except: return JsonError('invalid idEntity') else: # ----------------------------------------------------------------------------------------------------- # Se crean los campos con base al modelo ( trae todos los campos del modelo # for field in model._meta._fields(): # only for django 1.4 for field in model._meta.fields: try: addFiedToList(fieldList, field , '') except Exception as e: traceback.print_exc() return JsonError(getReadableError(e)) # Add __str__ myField = { 'id' : '__str__' , 'text' : '__str__' , 'checked' : False, 'leaf' : True } # Defaults values setDefaultField(myField, model , viewCode) # FormLink redefinition to original view # myField['zoomModel'] = viewCode fieldList.append(myField) # Codifica el mssage json context = json.dumps(fieldList) return HttpResponse(context, content_type="application/json")
def getRowById(myModelName, myId): """ Retorna un registro dado un modelo y un id """ # Obtiene los datos model = getDjangoModel(myModelName) myList = model.objects.filter(pk=myId) if len(myList) > 0: return myList[0] else: return None
def readUdps(rowdict, regBase, cUDP, udpList, udpTypes): if cUDP.keyField: # si la creacion del detalle no es relacional, # se requiere hacer un verdadero Query sobre udpTable UdpModel = getDjangoModel(cUDP.udpTable) keyValue = rowdict.get(cUDP.keyField, '') if not keyValue: raise Exception('UdpError: Key not found ' + cUDP.keyField + ' in masterReg') keyValue = smart_str(keyValue) bAux = True Qs = UdpModel.objects Qs = addFilter(Qs, {cUDP.propertyRef: keyValue}) cllUDP = Qs.all() else: # Si no hay keyField, hace el query basado en el registro maestro try: bAux = eval('regBase.' + cUDP.udpTable.lower() + '_set.exists()') cllUDP = eval('regBase.' + cUDP.udpTable.lower() + '_set.all()') except: raise Exception('UdpError: related_name set not found ' + cUDP.udpTable.lower()) if bAux: for lUDP in cllUDP: udpName = cUDP.propertyPrefix + '__' + getattr( lUDP, cUDP.propertyName, '') if udpName in udpList: sAux = getattr(lUDP, cUDP.propertyValue, '') sAux = getTypedValue(sAux, udpTypes[udpName]) sAux = smart_str(sAux) if udpTypes[udpName] == 'html' and type( sAux).__name__ == 'string': sAux = sAux.replace('\n', '<br>').replace('\r', '<br>') sAux = sAux.replace('<br><br>', '<br>') sAux = sAux.replace('<td><br>', '<td>').replace('</td><br>', '</td>') sAux = sAux.replace('<th><br>', '<th>').replace('</th><br>', '</th>') sAux = sAux.replace('<tr><br>', '<tr>').replace('</tr><br>', '</tr>') sAux = sAux.replace('<br><td>', '<td>').replace('<br></td>', '</td>') sAux = sAux.replace('<br><th>', '<th>').replace('<br></th>', '</th>') sAux = sAux.replace('<br><tr>', '<tr>').replace('<br></tr>', '</tr>') rowdict[udpName] = sAux
def saveUDP(regBase, data, cUDP): try: UdpModel = getDjangoModel(cUDP.udpTable) except: raise Exception('UdpError: Invalid model ' + UdpModel) # si keyField no esta definido implica una relacion MD if not cUDP.keyField: try: Qs = eval('regBase.' + cUDP.udpTable.lower() + '_set.all()') except: raise Exception('UdpError: related_name set not found ' + cUDP.udpTable.lower()) else: keyValue = data.get(cUDP.keyField) keyValue = smart_str(keyValue) if not keyValue: raise Exception('UdpError: Key not found ' + cUDP.keyField + ' in masterReg') Qs = UdpModel.objects Qs = addFilter(Qs, {cUDP.propertyRef: keyValue}) for key in data: key = smart_str(key) if (not key.startswith(cUDP.propertyPrefix + '__')): continue UdpCode = key[len(cUDP.propertyPrefix) + 2:] QsUdp = addFilter(Qs, {cUDP.propertyName: UdpCode}) if QsUdp.exists(): rUdp = QsUdp[0] else: rUdp = UdpModel() if not cUDP.keyField: setattr(rUdp, cUDP.propertyRef, regBase) else: # Fix: deberia ser un parametro setattr(rUdp, cUDP.propertyRef + '_id', keyValue) setattr(rUdp, cUDP.propertyName, UdpCode) # Genera el ISO para la fecha y valores estandares para numeros y booleanos sAux = smart_str(data[key]) if sAux == 'None': sAux = '' setattr(rUdp, cUDP.propertyValue, sAux) rUdp.save()
def saveUDP(regBase, data, cUDP): try: UdpModel = getDjangoModel(cUDP.udpTable) except: raise Exception("UdpError: Invalid model " + UdpModel) # si keyField no esta definido implica una relacion MD if not cUDP.keyField: try: Qs = eval("regBase." + cUDP.udpTable.lower() + "_set.all()") except: raise Exception("UdpError: related_name set not found " + cUDP.udpTable.lower()) else: keyValue = data.get(cUDP.keyField) keyValue = smart_str(keyValue) if not keyValue: raise Exception("UdpError: Key not found " + cUDP.keyField + " in masterReg") Qs = UdpModel.objects Qs = addFilter(Qs, {cUDP.propertyRef: keyValue}) for key in data: key = smart_str(key) if not key.startswith(cUDP.propertyPrefix + "__"): continue UdpCode = key[len(cUDP.propertyPrefix) + 2 :] QsUdp = addFilter(Qs, {cUDP.propertyName: UdpCode}) if QsUdp.exists(): rUdp = QsUdp[0] else: rUdp = UdpModel() if not cUDP.keyField: setattr(rUdp, cUDP.propertyRef, regBase) else: # Fix: deberia ser un parametro setattr(rUdp, cUDP.propertyRef + "_id", keyValue) setattr(rUdp, cUDP.propertyName, UdpCode) # Genera el ISO para la fecha y valores estandares para numeros y booleanos sAux = smart_str(data[key]) if sAux == "None": sAux = "" setattr(rUdp, cUDP.propertyValue, sAux) rUdp.save()
def addDetailToList(detailList, detail, detailPath): """ return parcial detail tree ( Called from protoGetFieldTree ) detailList : Lista con los detalles detail : registro del detalle detailField : jerarquia vista desde el campo detailPath : jerarquia inversa vista desde el maestro """ if len(detailPath) > 0: detailPath += '/' detailPath += detail['menuText'] # Agrega el campo solicitado menuDetail = { "id": detailPath, "conceptDetail": detail['conceptDetail'], "detailField": detail['detailField'], "masterField": 'pk', "leaf": True } detailList.append(menuDetail) # Evita demasiada recursividad ( 5 niveles debe ser mas q suficiente ) # Si el mismo campo ya aparece en el camino seguramente es una autoreferencia detailField = detail['detailField'] if detailField.count('__') > 5 or detailField.count('__' + detail['detailName'] + '__') > 0: return else: detailChild = [] model = getDjangoModel(detail['conceptDetail']) modelDetails = getModelDetails(model) for sDetail in modelDetails: sDetail['detailField'] = sDetail['detailName'] + '__' + detail[ 'detailField'] addDetailToList(detailChild, sDetail, detailPath) # Si el modelo de base es el modelo de trabajo, no entro al loop if len(detailChild) > 0: menuDetail['leaf'] = False menuDetail['children'] = detailChild
def readUdps( rowdict, regBase , cUDP, udpList, udpTypes ): if cUDP.keyField: # si la creacion del detalle no es relacional, # se requiere hacer un verdadero Query sobre udpTable UdpModel = getDjangoModel( cUDP.udpTable ) keyValue = rowdict.get( cUDP.keyField , '' ) if not keyValue: raise Exception( 'UdpError: Key not found ' + cUDP.keyField + ' in masterReg') keyValue = smart_str( keyValue ) bAux = True Qs = UdpModel.objects Qs = addFilter( Qs, { cUDP.propertyRef : keyValue } ) cllUDP = Qs.all() else: # Si no hay keyField, hace el query basado en el registro maestro try: bAux = eval ( 'regBase.' + cUDP.udpTable.lower() + '_set.exists()' ) cllUDP = eval ( 'regBase.' + cUDP.udpTable.lower() + '_set.all()' ) except: raise Exception( 'UdpError: related_name set not found ' + cUDP.udpTable.lower() ) if bAux: for lUDP in cllUDP: udpName = cUDP.propertyPrefix + '__' + getattr( lUDP, cUDP.propertyName , '') if udpName in udpList: sAux = getattr( lUDP, cUDP.propertyValue, '' ) sAux = getTypedValue ( sAux , udpTypes[ udpName ]) sAux = smart_str( sAux ) if udpTypes[ udpName ] == 'html' and type( sAux ).__name__=='string' : sAux = sAux.replace( '\n', '<br>').replace( '\r', '<br>') sAux = sAux.replace( '<br><br>', '<br>') sAux = sAux.replace( '<td><br>', '<td>').replace( '</td><br>', '</td>') sAux = sAux.replace( '<th><br>', '<th>').replace( '</th><br>', '</th>') sAux = sAux.replace( '<tr><br>', '<tr>').replace( '</tr><br>', '</tr>') sAux = sAux.replace( '<br><td>', '<td>').replace( '<br></td>', '</td>') sAux = sAux.replace( '<br><th>', '<th>').replace( '<br></th>', '</th>') sAux = sAux.replace( '<br><tr>', '<tr>').replace( '<br></tr>', '</tr>') rowdict[ udpName ] = sAux
def readUdps(rowdict, regBase, cUDP, udpList, udpTypes): if cUDP.keyField: # si la creacion del detalle no es relacional, # se requiere hacer un verdadero Query sobre udpTable UdpModel = getDjangoModel(cUDP.udpTable) keyValue = rowdict.get(cUDP.keyField, "") if not keyValue: raise Exception("UdpError: Key not found " + cUDP.keyField + " in masterReg") keyValue = smart_str(keyValue) bAux = True Qs = UdpModel.objects Qs = addFilter(Qs, {cUDP.propertyRef: keyValue}) cllUDP = Qs.all() else: # Si no hay keyField, hace el query basado en el registro maestro try: bAux = eval("regBase." + cUDP.udpTable.lower() + "_set.exists()") cllUDP = eval("regBase." + cUDP.udpTable.lower() + "_set.all()") except: raise Exception("UdpError: related_name set not found " + cUDP.udpTable.lower()) if bAux: for lUDP in cllUDP: udpName = cUDP.propertyPrefix + "__" + getattr(lUDP, cUDP.propertyName, "") if udpName in udpList: sAux = getattr(lUDP, cUDP.propertyValue, "") sAux = getTypedValue(sAux, udpTypes[udpName]) sAux = smart_str(sAux) if udpTypes[udpName] == "html" and type(sAux).__name__ == "string": sAux = sAux.replace("\n", "<br>").replace("\r", "<br>") sAux = sAux.replace("<br><br>", "<br>") sAux = sAux.replace("<td><br>", "<td>").replace("</td><br>", "</td>") sAux = sAux.replace("<th><br>", "<th>").replace("</th><br>", "</th>") sAux = sAux.replace("<tr><br>", "<tr>").replace("</tr><br>", "</tr>") sAux = sAux.replace("<br><td>", "<td>").replace("<br></td>", "</td>") sAux = sAux.replace("<br><th>", "<th>").replace("<br></th>", "</th>") sAux = sAux.replace("<br><tr>", "<tr>").replace("<br></tr>", "</tr>") rowdict[udpName] = sAux
def addDetailToList( detailList , detail, detailPath ): """ return parcial detail tree ( Called from protoGetFieldTree ) detailList : Lista con los detalles detail : registro del detalle detailField : jerarquia vista desde el campo detailPath : jerarquia inversa vista desde el maestro """ if len( detailPath ) > 0: detailPath += '/' detailPath += detail[ 'menuText' ] # Agrega el campo solicitado menuDetail = { "id" : detailPath , "conceptDetail" : detail[ 'conceptDetail' ] , "detailField" : detail[ 'detailField' ] , "masterField" : 'pk', "leaf" : True } detailList.append( menuDetail ) # Evita demasiada recursividad ( 5 niveles debe ser mas q suficiente ) # Si el mismo campo ya aparece en el camino seguramente es una autoreferencia detailField = detail[ 'detailField' ] if detailField.count( '__') > 5 or detailField.count( '__' + detail[ 'detailName' ] + '__' ) > 0: return else: detailChild= [] model = getDjangoModel( detail[ 'conceptDetail' ] ) modelDetails = getModelDetails( model ) for sDetail in modelDetails: sDetail[ 'detailField' ] = sDetail[ 'detailName' ] + '__' + detail[ 'detailField' ] addDetailToList( detailChild, sDetail , detailPath ) # Si el modelo de base es el modelo de trabajo, no entro al loop if len( detailChild ) > 0: menuDetail['leaf'] = False menuDetail['children'] = detailChild
def protoGetDetailsTree(request): """ return full field tree """ if not request.user.is_authenticated(): return JsonError('readOnly User') if request.method != 'POST': return JsonError('invalid message') viewCode = request.POST.get('viewCode', '') viewEntity = getBaseModelName(viewCode) try: model = getDjangoModel(viewEntity) except Exception, e: jsondict = {'success': False, 'message': getReadableError(e)} context = json.dumps(jsondict) return HttpResponse(context, content_type="application/json")
def protoGetDetailsTree(request): """ return full field tree """ if not request.user.is_authenticated(): return JsonError('readOnly User') if request.method != 'POST': return JsonError( 'invalid message' ) viewCode = request.POST.get('viewCode', '') viewEntity = getBaseModelName( viewCode ) try: model = getDjangoModel(viewEntity) except Exception, e: jsondict = { 'success':False, 'message': getReadableError( e ) } context = json.dumps( jsondict) return HttpResponse(context, content_type="application/json")
def getReportBase( viewCode ): viewEntity = getBaseModelName( viewCode ) # Obtiene el modelo try: model = getDjangoModel(viewEntity) except Exception as e : pass # Obtiene la definicion try: protoDef = ProtoDefinition.objects.get (code = viewCode ) protoMeta = json.loads( protoDef.metaDefinition ) except Exception as e : pass # hace el QSet de los registros seleccionados Qs = model.objects.select_related() return protoMeta, Qs
def getReportBase( viewCode ): viewEntity = getBaseModelName( viewCode ) # Obtiene el modelo try: model = getDjangoModel(viewEntity) except Exception as e: pass # Obtiene la definicion try: protoDef = ProtoDefinition.objects.get (code = viewCode ) protoMeta = json.loads( protoDef.metaDefinition ) except Exception as e: pass # hace el QSet de los registros seleccionados Qs = model.objects.select_related(depth=1) return protoMeta, Qs
def protoExecuteAction(request): """ Ejecuta una opcion """ def doWfAction(model, selectedKeys, parameters, actionDef, viewEntity, pUser): userProfile = getUserProfile(pUser, 'wflow', viewEntity) try: changeSt = actionDef.get('change', []) stInitial = changeSt[0] stFinal = changeSt[1] Qs = model.objects.filter(pk__in=selectedKeys) Qs = Qs.filter(smWflowStatus=stInitial) # TODO transaction??? if actionDef.get('notifyOwner', False): for wfRow in Qs: if len(parameters) > 0: strMsg = parameters[0].get('value') else: strMsg = actionDef.get('message', '') UserReponse = WflowUserReponse() UserReponse.viewEntity = viewEntity UserReponse.strKey = wfRow.__str__() UserReponse.wfAction = actionDef.get('name') UserReponse.adminMsg = strMsg try: setattr(UserReponse, 'smOwningUser', wfRow.smOwningUser) setattr(UserReponse, 'smOwningTeam', wfRow.smOwningTeam) setattr(UserReponse, 'smCreatedBy', userProfile.user) setattr(UserReponse, 'smRegStatus', '0') setattr(UserReponse, 'smCreatedOn', datetime.now()) except: pass UserReponse.save() if actionDef.get('emailNotification', False): user = User.objects.get( username=wfRow.smOwningUser.username) if user.email: try: subject = actionDef.get('emailSubject', '') message = actionDef.get('emailTemplate', '') variableFormat = { 'sk': wfRow.__str__(), 'concept': viewEntity, 'admmessage': strMsg, 'admin': userProfile.user.username.title(), 'date': strftime('%d/%m/%Y', wfRow.smCreatedOn.timetuple()), 'User': wfRow.smOwningUser.username.title() } message = message.format(**variableFormat) user.email_user(subject, message) except: pass if actionDef.get('setOwner', False): Qs.update(smWflowStatus=stFinal, smOwningTeam=userProfile.userTeam) else: Qs.update(smWflowStatus=stFinal) return doReturn({'success': True, 'message': 'WfAction Ok'}) except Exception as e: return doReturn({'success': False, 'message': str(e)}) # ---------------------------------------- def doAdminAction(model, selectedKeys, parameters, actionDef, modelAdmin): for action in modelAdmin.actions: if action.__name__ == actionName: break if not action: return doReturn({'success': False, 'message': 'Action notFound'}) Qs = model.objects.select_related() Qs = Qs.filter(pk__in=selectedKeys) try: returnObj = action(modelAdmin, request, Qs, parameters) return doReturn(returnObj) except Exception as e: return doReturn({'success': False, 'message': str(e)}) # ---------------------------------------- def doAdminDetailAction(model, selectedKeys, detKeys, parameters, actionDef, modelAdmin): for action in modelAdmin.actions: if action.__name__ == actionName: break if not action: return doReturn({'success': False, 'message': 'Action notFound'}) try: returnObj = action(modelAdmin, request, selectedKeys, detKeys, parameters) return doReturn(returnObj) except Exception as e: return doReturn({'success': False, 'message': str(e)}) # ---------------------------------------- if not request.user.is_authenticated(): return doReturn({'success': False, 'message': 'readOnly User'}) if request.method != 'POST': return doReturn({'success': False, 'message': 'PostAction required'}) actionName = request.POST.get('actionName', '') viewCode = request.POST.get('viewCode', '') viewEntity = getBaseModelName(viewCode) selectedKeys = request.POST.get('selectedKeys', []) selectedKeys = json.loads(selectedKeys) parameters = request.POST.get('parameters', []) parameters = json.loads(parameters) actionDef = request.POST.get('actionDef', {}) actionDef = json.loads(actionDef) # hace el QSet de los registros seleccionados if actionDef.get('selectionMode', '') != 'none' and selectedKeys.__len__() == 0: return doReturn({'success': False, 'message': 'No record selected'}) # Obtiene el modelo try: model = getDjangoModel(viewEntity) modelAdmin = site._registry.get(model) except: return doReturn({'success': False, 'message': 'Model notFound'}) # details if actionDef.get('selectionMode', '') == 'details': detKeys = request.POST.get('detKeys', {}) detKeys = json.loads(detKeys) return doAdminDetailAction(model, selectedKeys, detKeys, parameters, actionDef, modelAdmin) elif actionDef.get('actionType', '') == 'wflow': return doWfAction(model, selectedKeys, parameters, actionDef, viewEntity, request.user) elif hasattr(modelAdmin, 'actions'): return doAdminAction(model, selectedKeys, parameters, actionDef, modelAdmin) else: return doReturn({'success': False, 'message': 'Action notFound'}) # ----------------------------------------
def protoGetPCI(request): """ return full metadata (columns, renderers, totalcount...) """ if not request.user.is_authenticated(): return JsonError('readOnly User') if request.method != 'POST': return JsonError( 'invalid message' ) viewCode = request.POST.get('viewCode', '') viewEntity = getBaseModelName( viewCode ) try: model = getDjangoModel(viewEntity) except : return JsonError( 'model not found:' + viewEntity ) # userProfile = getUserProfile( request.user, 'getPci', viewEntity ) # PROTOTIPOS if viewCode.startswith( PROTO_PREFIX ) and viewCode != viewEntity : try: prototypeView = viewCode.replace( PROTO_PREFIX, '') protoDef = Prototype.objects.get(code = prototypeView, smOwningTeam = userProfile.userTeam ) created = False except: jsondict = { 'success':False, 'message': viewCode + ' notFound' } return HttpResponse( json.dumps( jsondict), mimetype="application/json") else: # created : El objeto es nuevo # protoDef : PCI leida de la DB protoDef, created = ProtoDefinition.objects.get_or_create(code = viewCode ) # Verifica si es una version vieja if created: protoDef.overWrite = True # else: # protoMeta = json.loads( protoDef.metaDefinition ) # version = protoMeta.get( 'metaVersion' ) # if ( version is None ) or ( version < PROTOVERSION ): # created = True # active solo viene de protoDefinition try: active = protoDef.active except: active = True # Si es nuevo o no esta activo lee Django if created or ( not active ) : model_admin, protoMeta = getProtoAdmin( model ) version = protoMeta.get( 'metaVersion' ) # La version determina q es una carga completa de la meta y no es necesario reconstruirla # solo en caso de q la definicion no este en la Db if ( version is None ) or ( version < PROTOVERSION ): # Verifica si existe una propiedad ProtoMeta es la copia de la meta cargada a la Db, grid = protoGrid.ProtoGridFactory( model, viewCode, model_admin, protoMeta ) protoMeta = createProtoMeta( model, grid, viewEntity, viewCode ) # Guarda la Meta si es nuevo o si se especifica overWrite if created or protoDef.overWrite: protoDef.metaDefinition = json.dumps( protoMeta ) protoDef.description = protoMeta['description'] protoDef.save() else: protoMeta = json.loads( protoDef.metaDefinition ) protoMeta['viewCode'] = viewCode # La definicion del arbol es fija, pues las cols deben ser siempre uniformes sin importar el tipo de modelo. # pStyle = protoMeta.get( 'pciStyle', '') # if pStyle == 'tree': setTreeDefinition() customCode = '_custom.' + viewCode try: custom = CustomDefinition.objects.get(code = customCode, smOwningTeam = userProfile.userTeam ) custom = json.loads( custom.metaDefinition ) protoMeta['custom'] = custom['custom'] except: pass # WorkFlow if hasattr( model , '_WorkFlow' ) : wflowControl = getattr( model, '_WorkFlow', {} ) if request.user.is_superuser or getModelPermissions( request.user , model, 'wfadmin' ) : protoMeta['WFlowActions'] = wflowControl.get( 'transitions', [] ) wfFilterSet = wflowControl.get( 'wfFilters', [] ) if len( wfFilterSet ) > 0: protoMeta['gridSets'] = protoMeta.get('gridSets', {}) protoMeta['gridSets']['filtersSet'] = wfFilterSet for lFilter in wfFilterSet: lFilter['customFilter'] = [{ "property": "smWflowStatus", "filterStmt": lFilter[ 'wfStatus'] }] jsondict = { 'success':True, 'message': '', 'metaData':{ # The name of the property which contains the Array of row objects. ... 'root': 'rows', #Name of the property within a row object that contains a record identifier value. ... 'idProperty': protoMeta['idProperty'], #Name of the property from which to retrieve the total number of records in t 'totalProperty':'totalCount', #Name of the property from which to retrieve the success attribute. ... 'successProperty':'success', #The name of the property which contains a response message. (optional) 'messageProperty': 'message', }, 'protoMeta': protoMeta, 'permissions': getModelPermissions( request.user, model ), 'rows':[], 'totalCount': 0, } # Codifica el mssage json context = json.dumps( jsondict) return HttpResponse(context, mimetype="application/json")
def _protoEdit(request, myAction): if not request.user.is_authenticated(): return doReturn({'success': False, 'message': 'readOnly User'}) if request.method != 'POST': return doReturn({'success': False, 'message': 'invalid message'}) message = '' # Carga el modelo protoMeta = request.POST.get('protoMeta', '') protoMeta = json.loads(protoMeta) viewEntity = protoMeta.get('viewEntity', '') model = getDjangoModel(viewEntity) # Autentica if not getModelPermissions(request.user, model, myAction): return doReturn({ 'success': False, 'message': 'No ' + myAction + 'permission' }) # Obtiene el profile para saber el teamhierarchi userProfile = getUserProfile(request.user, 'edit', viewEntity) # Verfica si es un protoModel ( maneja TeamHierarchy ) isProtoModel = hasattr(model, '_protoObj') # Verifica si hay registros que son solo de referencia userNodes = [] refAllow = False if myAction in ['DEL', 'UPD' ] and isProtoModel and not request.user.is_superuser: refAllow = getModelPermissions(request.user, model, 'refallow') if refAllow: userNodes = getUserNodes(request.user, viewEntity) # WorkFlow hasWFlow = hasattr(model, '_WorkFlow') and isProtoModel if hasWFlow: wfadmin = getModelPermissions(request.user, model, 'wfadmin') WFlowControl = getattr(model, '_WorkFlow', {}) initialWfStatus = WFlowControl.get('initialStatus', '0') # Decodifica los eltos rows = request.POST.get('rows', []) rows = json.loads(rows) # LogInfo logEvent(viewEntity, rows, request.user, userProfile.userTeam, '', myAction) # Fields fieldsDict = list2dict(protoMeta['fields'], 'name') # JsonField jsonField = protoMeta.get('jsonField', '') if not isinstance(jsonField, (str, unicode)): jsonField = '' # TOOD: Log # activityLog ( myAction, request.user , viewEntity, { 'protoMeta' : protoMeta , 'rows' : rows }) # Genera la clase UDP pUDP = protoMeta.get('usrDefProps', {}) cUDP = verifyUdpDefinition(pUDP) # Verifica q sea una lista de registros, (no deberia pasar, ya desde Extjs se controla ) if type(rows).__name__ == 'dict': rows = [rows] pList = [] for data in rows: data['_ptStatus'] = '' if myAction == 'INS': rec = model() else: try: rec = model.objects.get(pk=data['id']) except: data['_ptStatus'] = data['_ptStatus'] + ERR_NOEXIST + '<br>' pList.append(data) continue # refAllow verifica si corresponde a los registros modificables ( solo es true en myAction in ['DEL', 'UPD'] ) if refAllow and isProtoModel: if not (str(rec.smOwningTeam_id) in userNodes): data['_ptStatus'] = ERR_REFONLY + '<br>' pList.append(data) continue if not (myAction == 'DEL'): # Upd, Ins for key in data: key = smart_str(key) if key in ['id', '_ptStatus', '_ptId', '__str__']: continue vFld = fieldsDict[key] if vFld.get('crudType') in ["screenOnly", "linked"]: continue # Los campos de seguridad se manejan a nivel registro if isProtoModel: if key in [ 'smOwningUser', 'smOwningTeam', 'smOwningUser_id', 'smOwningTeam_id', 'smCreatedBy', 'smModifiedBy', 'smCreatedBy_id', 'smModifiedBy_id', 'smCreatedOn', 'smModifiedOn', 'smWflowStatus', 'smRegStatus', 'smUUID' ]: continue # Udps if (cUDP.udpTable and key.startswith(cUDP.propertyPrefix + '__')): continue # JsonField if key == jsonField: continue if key.startswith(jsonField + '__'): continue try: setRegister(model, rec, key, data) except Exception as e: data['_ptStatus'] = data['_ptStatus'] + getReadableError(e) if isProtoModel: setSecurityInfo(rec, data, userProfile, (myAction == 'INS')) if len(jsonField) > 0: jsonInfo = {} for key in data: if not key.startswith(jsonField + '__'): continue jKey = key[len(jsonField) + 2:] jsonInfo[jKey] = data[key] setattr(rec, jsonField, jsonInfo) # Inicializa el estado del WF if hasWFlow: setattr(rec, 'smWflowStatus', initialWfStatus) # Guarda el idInterno para concatenar registros nuevos en la grilla try: _ptId = data['_ptId'] except: _ptId = '' try: rec.save() # Guardar las Udps if cUDP.udpTable: try: saveUDP(rec, data, cUDP) except Exception as e: raise Exception('UdpError: saveActiob') # -- Los tipos complejos ie. date, generan un error, es necesario hacerlo detalladamente # Convierte el registro en una lista y luego toma solo el primer elto de la lista resultado. data = Q2Dict(protoMeta, [rec], False)[0] data['_ptId'] = _ptId except Exception as e: data['_ptStatus'] = data['_ptStatus'] + getReadableError(e) data['_ptId'] = _ptId # traceback.print_exc() # return doReturn ({'success':False ,'message' : str( e )}) else: # Action Delete try: rec.delete() except Exception, e: data['_ptStatus'] = data['_ptStatus'] + getReadableError(e) pList.append(data) if data.get('_ptStatus', ''): message += data['_ptStatus'] + ';'
def protoSaveProtoObj(request): """ Save full metadata * objetos del tipo _XXX se guardan siempre en CustomDefinition * objetos del tipo prototype.protoTable se guardan siempre en Prototype * Solo los adminstradores tienen el derecho de guardar pcls custom : Los objetos de tipo custom, manejan la siguiente llave _ColSet.[viewCode] listDisplaySet _QrySet.[viewCode] filterSet _menu Para manejar el modelo en las generacion de protoPci's se usa : prototype.protoTable.[protoModel-viewCode] --> al leer la pcl se leera prototype.protoTable.[protoModel-viewCode] """ if request.method != 'POST': return JsonError('invalid message') custom = False prototype = False create = False viewCode = request.POST.get('viewCode', '') userProfile = getUserProfile(request.user, 'saveObjs', viewCode) # Reglas para definir q se guarda if viewCode.find('_') == 0 : custom = True if viewCode.startswith(PROTO_PREFIX) : prototype = True # Carga la meta sMeta = request.POST.get('protoMeta', '') # Es customProperty if custom: try: protoDef, create = CustomDefinition.objects.get_or_create(code=viewCode, smOwningTeam=userProfile.userTeam) except Exception as e: return JsonError(getReadableError(e)) # Es prototype elif prototype: try: # debe existir previamente protoCode = viewCode.replace(PROTO_PREFIX, '') protoMeta = json.loads(sMeta) entityId = protoMeta['protoEntityId'] entityObj = Entity.objects.get(id=entityId) protoDef, create = Prototype.objects.get_or_create(code=protoCode, entity=entityObj, smOwningTeam=userProfile.userTeam) except Exception as e: return JsonError(getReadableError(e)) else: # Verifica los permisos viewEntity = getBaseModelName(viewCode) model = getDjangoModel(viewEntity) if not getModelPermissions(request.user, model, 'config') : return JsonError('permission denied') try: protoDef = ProtoDefinition.objects.get_or_create(code=viewCode)[0] except Exception as e: return JsonError(getReadableError(e)) protoDef.active = True protoDef.overWrite = False # borra el custom por q confunde haecer modif en un lado y otro try: CustomDefinition.objects.filter(code='_custom.' + viewCode, smOwningTeam=userProfile.userTeam).delete() except: pass if custom or prototype: setSecurityInfo(protoDef, {}, userProfile, create) protoDef.metaDefinition = sMeta protoDef.save() return JsonSuccess({ 'message': 'Ok' })
def protoGetPCI(request): """ return full metadata (columns, renderers, totalcount...) """ if not request.user.is_authenticated(): return JsonError('readOnly User') if request.method != 'POST': return JsonError('invalid message') viewCode = request.POST.get('viewCode', '') viewEntity = getBaseModelName(viewCode) try: model = getDjangoModel(viewEntity) except : return JsonError('model not found: {0}'.format( viewEntity)) # userProfile = getUserProfile(request.user, 'getPci', viewEntity) # PROTOTIPOS isPrototype = False if viewCode.startswith(PROTO_PREFIX) and viewCode != viewEntity : try: prototypeView = viewCode.replace(PROTO_PREFIX, '') protoDef = Prototype.objects.get(code=prototypeView, smOwningTeam=userProfile.userTeam) created = False isPrototype = True except: return JsonError('prototype not found: {0}'.format( viewCode )) else: # protoDef : PCI leida de la DB ; created : El objeto es nuevo protoDef, created = ProtoDefinition.objects.get_or_create(code=viewCode) if ( not isPrototype ) : # if ( not protoDef.active) : # return JsonError('Inactive definition : {0}'.format( viewCode )) if protoDef.overWrite : # Si la directiva es reescribirlo es como si fuera nuevo cada vez created = True # Si es nuevo lee Django if created : model_admin, protoMeta = getProtoAdmin(model) # Genera la definicion de la vista grid = protoGrid.ProtoGridFactory(model, viewCode, model_admin, protoMeta) if not createProtoMeta(model, grid, viewEntity, viewCode) : return JsonError('Document type required: {0}.???'.format( viewCode )) # Guarda o refresca la Meta y mantiene la directiva overWrite protoDef.metaDefinition = json.dumps(grid.protoMeta) protoDef.description = protoMeta['description'] protoDef.save() else: protoMeta = json.loads(protoDef.metaDefinition) protoMeta['viewCode'] = viewCode # La definicion del arbol es fija, pues las cols deben ser siempre uniformes sin importar el tipo de modelo. # pStyle = protoMeta.get( 'pciStyle', '') # if pStyle == 'tree': setTreeDefinition() customCode = '_custom.' + viewCode try: custom = CustomDefinition.objects.get(code=customCode, smOwningTeam=userProfile.userTeam) custom = json.loads(custom.metaDefinition) protoMeta['custom'] = custom['custom'] except: pass # TODO: Verificacion de la metadata # try: # protoMeta = verifyMeta(protoMeta, 'pcl') # except Exception, e: # traceback.print_exc() # message = getReadableError(e) # WorkFlow if hasattr(model , '_WorkFlow') : wflowControl = getattr(model, '_WorkFlow', {}) if request.user.is_superuser or getModelPermissions(request.user , model, 'wfadmin') : protoMeta['WFlowActions'] = wflowControl.get('transitions', []) wfFilterSet = wflowControl.get('wfFilters', []) if len(wfFilterSet) > 0: protoMeta['gridSets'] = protoMeta.get('gridSets', {}) protoMeta['gridSets']['filtersSet'] = wfFilterSet for lFilter in wfFilterSet: lFilter['customFilter'] = [{ "property": "smWflowStatus", "filterStmt": lFilter[ 'wfStatus'] }] jsondict = { 'success':True, 'message': '', 'metaData':{ # The name of the property which contains the Array of row objects. ... 'root': 'rows', # Name of the property within a row object that contains a record identifier value. ... 'idProperty': protoMeta['idProperty'], # Name of the property from which to retrieve the total number of records in t 'totalProperty':'totalCount', # Name of the property from which to retrieve the success attribute. ... 'successProperty':'success', # The name of the property which contains a response message. (optional) 'messageProperty': 'message', }, 'protoMeta': protoMeta, 'permissions': getModelPermissions(request.user, model), 'rows':[], 'totalCount': 0, } # Codifica el mssage json context = json.dumps(jsondict) return HttpResponse(context, content_type="application/json")
def getQSet(protoMeta, protoFilter, baseFilter, sort, pUser): # Decodifica los eltos viewEntity = protoMeta.get('viewEntity', '') model = getDjangoModel(viewEntity) # Autentica ' if not getModelPermissions(pUser, model, 'list'): return model.objects.none(), [], False, False # modelo Administrado isProtoModel = hasattr(model, '_protoObj') if isProtoModel: userNodes = getUserNodes(pUser, viewEntity) # WorkFlow Model hasWFlow = hasattr(model, '_WorkFlow') if hasWFlow: WFlowControl = getattr(model, '_WorkFlow', {}) OkStatus = WFlowControl.get('OkStatus', 'Ok') # JsonField JsonField = protoMeta.get('jsonField', '') if not isinstance(JsonField, (str, unicode)): JsonField = '' # QSEt # Qs = model.objects.select_related(depth=1) Qs = model.objects # Permite la lectura de todos los registros refAllow = getModelPermissions(pUser, model, 'refallow') # Solamenete valida si es if isProtoModel and not pUser.is_superuser: # Si no tiene wflow y tampoco permiso de referencia, se limita a los nodos de su equipo if not refAllow: Qs = Qs.filter(smOwningTeam__in=userNodes) # Si tiene permiso de referencia y ademas WF, trae todos los propios o los demas en estado valido elif hasWFlow: Qs = Qs.filter( Q(smOwningTeam__in=userNodes) | Q(~Q(smOwningTeam__in=userNodes), Q(smWflowStatus=OkStatus))) # TODO: Agregar solomente los campos definidos en el safeMeta ( only, o defer ) # Qs.query.select_fields = [f1, f2, .... ] # Le pega la meta al modelo para tomar por ejemplo searchFields model.protoMeta = protoMeta # El filtro base viene en la configuracion MD try: Qs = addQbeFilter(baseFilter, model, Qs, JsonField) except Exception as e: traceback.print_exc() getReadableError(e) # Order by localSort = protoMeta.get('localSort', False) orderBy = [] if not localSort: sort = verifyList(sort) for sField in sort: # Verificar que el campo de sort haga parte de los campos del modelo # blacklist = [f.name for f in instance._meta.fields] + ['id', 'user'] # Unicode sort if sField['property'] == '__str__': try: unicodeSort = getUnicodeFields(model) for sAux in unicodeSort: if sField['direction'] == 'DESC': sAux = '-' + sAux orderBy.append(sAux) except Exception as e: pass else: if sField['direction'] == 'DESC': sField['property'] = '-' + sField['property'] orderBy.append(sField['property']) orderBy = tuple(orderBy) try: Qs = addQbeFilter(protoFilter, model, Qs, JsonField) except Exception as e: traceback.print_exc() getReadableError(e) # DbFirst en caso de q no exista una llave primaria fakeId = hasattr(model, '_fakeId') # Solo retorna refAllow si este es valido para la tabla ( no es un super usuario y es un modelo manejado por sm ) refAllow = refAllow and isProtoModel and not pUser.is_superuser return Qs, orderBy, fakeId, refAllow
from models import getDjangoModel model = getDjangoModel( 'prototype.entity') entityId = 20 pEntity = model.objects.get( pk = entityId ) ret = pEntity.model.project_id ret = projectId
def getQSet(protoMeta, protoFilter, baseFilter , sort , pUser): # Decodifica los eltos viewEntity = protoMeta.get('viewEntity', '') model = getDjangoModel(viewEntity) # Autentica ' if not getModelPermissions(pUser, model, 'list'): return model.objects.none(), [], False, False # modelo Administrado isProtoModel = hasattr(model , '_protoObj') if isProtoModel: userNodes = getUserNodes(pUser, viewEntity) # WorkFlow Model hasWFlow = hasattr(model , '_WorkFlow') if hasWFlow: WFlowControl = getattr(model, '_WorkFlow', {}) OkStatus = WFlowControl.get('OkStatus', 'Ok') # JsonField JsonField = protoMeta.get('jsonField', '') if not isinstance(JsonField, (str, unicode)): JsonField = '' # QSEt # Qs = model.objects.select_related(depth=1) Qs = model.objects # Permite la lectura de todos los registros refAllow = getModelPermissions(pUser, model, 'refallow') # Solamenete valida si es if isProtoModel and not pUser.is_superuser : # Si no tiene wflow y tampoco permiso de referencia, se limita a los nodos de su equipo if not refAllow : Qs = Qs.filter(smOwningTeam__in=userNodes) # Si tiene permiso de referencia y ademas WF, trae todos los propios o los demas en estado valido elif hasWFlow: Qs = Qs.filter(Q(smOwningTeam__in=userNodes) | Q(~Q(smOwningTeam__in=userNodes) , Q(smWflowStatus=OkStatus))) # TODO: Agregar solomente los campos definidos en el safeMeta ( only, o defer ) # Qs.query.select_fields = [f1, f2, .... ] # Le pega la meta al modelo para tomar por ejemplo searchFields model.protoMeta = protoMeta # El filtro base viene en la configuracion MD try: Qs = addQbeFilter(baseFilter, model, Qs , JsonField) except Exception as e: traceback.print_exc() getReadableError(e) # Order by localSort = protoMeta.get('localSort', False) orderBy = [] if not localSort : sort = verifyList(sort) for sField in sort: # Verificar que el campo de sort haga parte de los campos del modelo # blacklist = [f.name for f in instance._meta.fields] + ['id', 'user'] # Unicode sort if sField['property'] == '__str__' : try: unicodeSort = getUnicodeFields(model) for sAux in unicodeSort: if sField['direction'] == 'DESC': sAux = '-' + sAux orderBy.append(sAux) except Exception as e: pass else: if sField['direction'] == 'DESC': sField['property'] = '-' + sField['property'] orderBy.append(sField['property']) orderBy = tuple(orderBy) try: Qs = addQbeFilter(protoFilter, model, Qs, JsonField) except Exception as e: traceback.print_exc() getReadableError(e) # DbFirst en caso de q no exista una llave primaria fakeId = hasattr(model , '_fakeId') # Solo retorna refAllow si este es valido para la tabla ( no es un super usuario y es un modelo manejado por sm ) refAllow = refAllow and isProtoModel and not pUser.is_superuser return Qs, orderBy, fakeId, refAllow
def protoGetPCI(request): """ return full metadata (columns, renderers, totalcount...) """ if not request.user.is_authenticated(): return JsonError('readOnly User') if request.method != 'POST': return JsonError('invalid message') viewCode = request.POST.get('viewCode', '') viewEntity = getBaseModelName(viewCode) try: model = getDjangoModel(viewEntity) except : return JsonError('model not found:' + viewEntity) # userProfile = getUserProfile(request.user, 'getPci', viewEntity) # PROTOTIPOS if viewCode.startswith(PROTO_PREFIX) and viewCode != viewEntity : try: prototypeView = viewCode.replace(PROTO_PREFIX, '') protoDef = Prototype.objects.get(code=prototypeView, smOwningTeam=userProfile.userTeam) created = False except: jsondict = { 'success':False, 'message': viewCode + ' notFound' } return HttpResponse(json.dumps(jsondict), content_type="application/json") else: # created : El objeto es nuevo # protoDef : PCI leida de la DB protoDef, created = ProtoDefinition.objects.get_or_create(code=viewCode) # Verifica si es una version vieja if created: protoDef.overWrite = True # active solo viene de protoDefinition try: active = protoDef.active except: active = True # Si es nuevo o no esta activo lee Django if created or (not active) : model_admin, protoMeta = getProtoAdmin(model) version = protoMeta.get('metaVersion') # La version determina q es una carga completa de la meta y no es necesario reconstruirla # solo en caso de q la definicion no este en la Db if (version is None) or (version < PROTOVERSION): # Verifica si existe una propiedad ProtoMeta es la copia de la meta cargada a la Db, grid = protoGrid.ProtoGridFactory(model, viewCode, model_admin, protoMeta) protoMeta = createProtoMeta(model, grid, viewEntity, viewCode) # Guarda la Meta si es nuevo o si se especifica overWrite if created or protoDef.overWrite: protoDef.metaDefinition = json.dumps(protoMeta) protoDef.description = protoMeta['description'] protoDef.save() else: protoMeta = json.loads(protoDef.metaDefinition) protoMeta['viewCode'] = viewCode # La definicion del arbol es fija, pues las cols deben ser siempre uniformes sin importar el tipo de modelo. # pStyle = protoMeta.get( 'pciStyle', '') # if pStyle == 'tree': setTreeDefinition() customCode = '_custom.' + viewCode try: custom = CustomDefinition.objects.get(code=customCode, smOwningTeam=userProfile.userTeam) custom = json.loads(custom.metaDefinition) protoMeta['custom'] = custom['custom'] except: pass # TODO: Verificacion de la metadata # try: # protoMeta = verifyMeta(protoMeta, 'pcl') # except Exception, e: # traceback.print_exc() # message = getReadableError(e) # WorkFlow if hasattr(model , '_WorkFlow') : wflowControl = getattr(model, '_WorkFlow', {}) if request.user.is_superuser or getModelPermissions(request.user , model, 'wfadmin') : protoMeta['WFlowActions'] = wflowControl.get('transitions', []) wfFilterSet = wflowControl.get('wfFilters', []) if len(wfFilterSet) > 0: protoMeta['gridSets'] = protoMeta.get('gridSets', {}) protoMeta['gridSets']['filtersSet'] = wfFilterSet for lFilter in wfFilterSet: lFilter['customFilter'] = [{ "property": "smWflowStatus", "filterStmt": lFilter[ 'wfStatus'] }] jsondict = { 'success':True, 'message': '', 'metaData':{ # The name of the property which contains the Array of row objects. ... 'root': 'rows', # Name of the property within a row object that contains a record identifier value. ... 'idProperty': protoMeta['idProperty'], # Name of the property from which to retrieve the total number of records in t 'totalProperty':'totalCount', # Name of the property from which to retrieve the success attribute. ... 'successProperty':'success', # The name of the property which contains a response message. (optional) 'messageProperty': 'message', }, 'protoMeta': protoMeta, 'permissions': getModelPermissions(request.user, model), 'rows':[], 'totalCount': 0, } # Codifica el mssage json context = json.dumps(jsondict) return HttpResponse(context, content_type="application/json")
def protoExecuteAction(request): """ Ejecuta una opcion """ def doWfAction(model, selectedKeys, parameters, actionDef, viewEntity, pUser): userProfile = getUserProfile(pUser, 'wflow', viewEntity) try: changeSt = actionDef.get('change', []) stInitial = changeSt[0] stFinal = changeSt[1] Qs = model.objects.filter(pk__in=selectedKeys) Qs = Qs.filter(smWflowStatus=stInitial) # TODO transaction??? if actionDef.get('notifyOwner', False) : for wfRow in Qs : if len (parameters) > 0: strMsg = parameters[0].get('value') else : strMsg = actionDef.get('message', '') UserReponse = WflowUserReponse() UserReponse.viewEntity = viewEntity UserReponse.strKey = wfRow.__str__() UserReponse.wfAction = actionDef.get('name') UserReponse.adminMsg = strMsg try: setattr(UserReponse, 'smOwningUser', wfRow.smOwningUser ) setattr(UserReponse, 'smOwningTeam', wfRow.smOwningTeam ) setattr(UserReponse, 'smCreatedBy', userProfile.user) setattr(UserReponse, 'smRegStatus', '0') setattr(UserReponse, 'smCreatedOn', datetime.now()) except : pass UserReponse.save() if actionDef.get('setOwner', False) : Qs.update(smWflowStatus=stFinal, smOwningTeam=userProfile.userTeam) else : Qs.update(smWflowStatus=stFinal) return doReturn ({'success':True, 'message' : 'WfAction Ok'}) except Exception as e: return doReturn ({'success':False, 'message' : str(e) }) # ---------------------------------------- def doAdminAction(model, selectedKeys, parameters, actionDef, modelAdmin): for action in modelAdmin.actions: if action.__name__ == actionName: break; if not action: return doReturn ({'success':False, 'message' : 'Action notFound'}) Qs = model.objects.select_related(depth=1) Qs = Qs.filter(pk__in=selectedKeys) try: returnObj = action(modelAdmin, request, Qs , parameters) return doReturn (returnObj) except Exception as e: return doReturn ({'success':False, 'message' : str(e) }) # ---------------------------------------- if not request.user.is_authenticated(): return doReturn ({'success':False , 'message' : 'readOnly User'}) if request.method != 'POST': return doReturn ({'success':False , 'message' : 'PostAction required'}) actionName = request.POST.get('actionName', '') viewCode = request.POST.get('viewCode', '') viewEntity = getBaseModelName(viewCode) selectedKeys = request.POST.get('selectedKeys', []) selectedKeys = json.loads(selectedKeys) parameters = request.POST.get('parameters', []) parameters = json.loads(parameters) actionDef = request.POST.get('actionDef', {}) actionDef = json.loads(actionDef) # hace el QSet de los registros seleccionados if actionDef.get('selectionMode', '') != 'none' and selectedKeys.__len__() == 0: return doReturn ({'success':False, 'message' : 'No record selected'}) # Obtiene el modelo try: model = getDjangoModel(viewEntity) modelAdmin = site._registry.get(model) except : return doReturn ({'success':False, 'message' : 'Model notFound'}) if actionDef.get('actionType', '') == 'wflow': return doWfAction(model, selectedKeys, parameters, actionDef, viewEntity, request.user) elif hasattr(modelAdmin, 'actions'): return doAdminAction (model, selectedKeys, parameters, actionDef, modelAdmin) else: return doReturn ({'success':False, 'message' : 'Action notFound'})
def _protoEdit(request, myAction ): if not request.user.is_authenticated(): return doReturn ({'success':False ,'message' : 'readOnly User'}) if request.method != 'POST': return doReturn ({'success':False, 'message' : 'invalid message'}) message = '' # Carga el modelo protoMeta = request.POST.get('protoMeta', '') protoMeta = json.loads( protoMeta ) viewEntity = protoMeta.get('viewEntity', '') model = getDjangoModel(viewEntity) # Autentica if not getModelPermissions( request.user, model, myAction ): return doReturn ({'success':False ,'message' : 'No ' + myAction + 'permission'}) # Obtiene el profile para saber el teamhierarchi userProfile = getUserProfile( request.user, 'edit', viewEntity ) # Verfica si es un protoModel ( maneja TeamHierarchy ) isProtoModel = hasattr( model , '_protoObj' ) # Verifica si hay registros que son solo de referencia userNodes = [] refAllow = False if myAction in ['delete', 'change'] and isProtoModel and not request.user.is_superuser : refAllow = getModelPermissions( request.user, model, 'refallow' ) if refAllow: userNodes = getUserNodes( request.user, viewEntity ) # WorkFlow hasWFlow = hasattr( model , '_WorkFlow' ) and isProtoModel if hasWFlow: wfadmin = getModelPermissions( request.user , model, 'wfadmin' ) WFlowControl = getattr( model, '_WorkFlow', {} ) initialWfStatus = WFlowControl.get( 'initialStatus', '0') # Decodifica los eltos rows = request.POST.get('rows', []) rows = json.loads( rows ) fieldsDict = list2dict( protoMeta[ 'fields' ], 'name') # JsonField jsonField = protoMeta.get('jsonField', '') if not isinstance( jsonField, (str, unicode) ): jsonField = '' # TOOD: Log # activityLog ( myAction, request.user , viewEntity, { 'protoMeta' : protoMeta , 'rows' : rows }) # Genera la clase UDP pUDP = protoMeta.get('usrDefProps', {}) cUDP = verifyUdpDefinition( pUDP ) # Verifica q sea una lista de registros, (no deberia pasar, ya desde Extjs se controla ) if type(rows).__name__=='dict': rows = [rows] pList = [] for data in rows: data['_ptStatus'] = '' if myAction == 'add': rec = model() else: try: rec = model.objects.get( pk = data['id'] ) except: data['_ptStatus'] = data['_ptStatus'] + ERR_NOEXIST + '<br>' pList.append( data ) continue # refAllow verifica si corresponde a los registros modificables ( solo es true en myAction in ['delete', 'change'] ) if refAllow and isProtoModel : if not ( str( rec.smOwningTeam_id ) in userNodes ) : data['_ptStatus'] = ERR_REFONLY + '<br>' pList.append( data ) continue if not ( myAction == 'delete' ): # Upd, Ins for key in data: key = smart_str( key ) if key in ['id', '_ptStatus', '_ptId', '__str__']: continue vFld = fieldsDict[key] if vFld.get( 'crudType' ) in ["screenOnly", "linked" ]: continue # Los campos de seguridad se manejan a nivel registro if isProtoModel: if key in ['smOwningUser','smOwningTeam','smCreatedBy','smModifiedBy', 'smWflowStatus','smRegStatus','smCreatedOn','smModifiedOn', 'smOwningUser_id','smOwningTeam_id','smCreatedBy_id','smModifiedBy_id']: continue # Udps if (cUDP.udpTable and key.startswith( cUDP.propertyPrefix + '__')): continue # JsonField if key == jsonField: continue if key.startswith( jsonField + '__'): continue try: setRegister( model, rec, key, data ) except Exception as e: data['_ptStatus'] = data['_ptStatus'] + getReadableError( e ) if isProtoModel: setSecurityInfo( rec, data, userProfile, ( myAction == 'add' ) ) if len( jsonField ) > 0: jsonInfo = {} for key in data: if not key.startswith( jsonField + '__'): continue jKey = key[ len(jsonField) + 2 : ] jsonInfo[ jKey ] = data[ key ] setattr( rec, jsonField , jsonInfo ) # Inicializa el estado del WF if hasWFlow: setattr( rec, 'smWflowStatus' , initialWfStatus ) # Guarda el idInterno para concatenar registros nuevos en la grilla try: _ptId = data['_ptId'] except: _ptId = '' try: rec.save() # Guardar las Udps if cUDP.udpTable: try: saveUDP( rec, data, cUDP ) except Exception as e: raise Exception( 'UdpError: saveActiob') # -- Los tipos complejos ie. date, generan un error, es necesario hacerlo detalladamente # Convierte el registro en una lista y luego toma solo el primer elto de la lista resultado. data = Q2Dict(protoMeta , [rec], False )[0] data['_ptId'] = _ptId except Exception as e: data['_ptStatus'] = data['_ptStatus'] + getReadableError( e ) data['_ptId'] = _ptId #traceback.print_exc() #return doReturn ({'success':False ,'message' : str( e )}) else: # Action Delete try: rec.delete() except Exception, e: data['_ptStatus'] = data['_ptStatus'] + getReadableError( e ) pass pList.append( data ) if data.get('_ptStatus', ''): message += data['_ptStatus'] + ';'