def protoList(request):
#   Vista simple para cargar la informacion,

    PAGESIZE = 50
    message = ''

    if not request.user or not request.user.is_authenticated():
        return doReturn ({'success':False , 'message' : 'readOnly User'})

    if request.method != 'POST':
        return doReturn ({'success':False, 'message' : 'invalid message'})

#   Los objetos vienen textoJson y hay q hacer el load para construirlos como objetos.
    protoMeta = request.POST.get('protoMeta', '')
    protoMeta = json.loads(protoMeta)

#
    protoFilter = request.POST.get('protoFilter', '')
    baseFilter = request.POST.get('baseFilter', '')
    sort = request.POST.get('sort', '')

    start = int(request.POST.get('start', 0))
    page = int(request.POST.get('page', 1))
    limit = int(request.POST.get('limit', PAGESIZE))


#   Obtiene las filas del modelo
    Qs, orderBy, fakeId, refAllow = getQSet(protoMeta, protoFilter, baseFilter , sort , request.user)
    pRowsCount = Qs.count()


#   Fix: Cuando esta en la pagina el filtro continua en la pagina 2 y no muestra nada.
#   if ( ( page -1 ) *limit >= pRowsCount ): page = 1

#   En el sitio en produccion, el pRows pasaba sin asignar; no entiendo el porq?
    if orderBy:
        try:
            pRows = Qs.order_by(*orderBy)[ start: page * limit ]
        except:
            pRows = Qs.all()[ start: page * limit ]
    else: 
        pRows = Qs.all()[ start: page * limit ]


    # Verifica los nodos validos 
    if refAllow: 
        userNodes = getUserNodes(request.user, protoMeta.get('viewEntity', ''))
    else: 
        userNodes = []

#   Prepara las cols del Query
    try:
        # TODO: improve performance
        pList = Q2Dict(protoMeta , pRows, fakeId, userNodes)
        bResult = True
    except Exception, e:
        traceback.print_exc()
        message = getReadableError(e)
        bResult = False
        pList = []
Exemple #2
0
def protoList(request):
    #   Vista simple para cargar la informacion,

    PAGESIZE = 50
    message = ''

    if not request.user or not request.user.is_authenticated():
        return doReturn({'success': False, 'message': 'readOnly User'})

    if request.method != 'POST':
        return doReturn({'success': False, 'message': 'invalid message'})

#   Los objetos vienen textoJson y hay q hacer el load para construirlos como objetos.
    protoMeta = request.POST.get('protoMeta', '')
    protoMeta = json.loads(protoMeta)

    #
    protoFilter = request.POST.get('protoFilter', '')
    baseFilter = request.POST.get('baseFilter', '')
    sort = request.POST.get('sort', '')

    start = int(request.POST.get('start', 0))
    page = int(request.POST.get('page', 1))
    limit = int(request.POST.get('limit', PAGESIZE))

    #   Obtiene las filas del modelo
    Qs, orderBy, fakeId, refAllow = getQSet(protoMeta, protoFilter, baseFilter,
                                            sort, request.user)
    pRowsCount = Qs.count()

    #   Fix: Cuando esta en la pagina el filtro continua en la pagina 2 y no muestra nada.
    #   if ( ( page -1 ) *limit >= pRowsCount ): page = 1

    #   En el sitio en produccion, el pRows pasaba sin asignar; no entiendo el porq?
    if orderBy:
        try:
            pRows = Qs.order_by(*orderBy)[start:page * limit]
        except:
            pRows = Qs.all()[start:page * limit]
    else:
        pRows = Qs.all()[start:page * limit]

    # Verifica los nodos validos
    if refAllow:
        userNodes = getUserNodes(request.user, protoMeta.get('viewEntity', ''))
    else:
        userNodes = []

#   Prepara las cols del Query
    try:
        # TODO: improve performance
        pList = Q2Dict(protoMeta, pRows, fakeId, userNodes)
        bResult = True
    except Exception, e:
        traceback.print_exc()
        message = getReadableError(e)
        bResult = False
        pList = []
    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) })
Exemple #4
0
    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)})
Exemple #5
0
    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) })
Exemple #6
0
    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)})
Exemple #7
0
    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) })
Exemple #8
0
    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)})
Exemple #9
0
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'})


#   ----------------------------------------
Exemple #10
0
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']  + ';'
Exemple #11
0
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 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 _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'] + ';'