Publicidad

martes, 8 de abril de 2014

Introduccion en la Declaracion de Campos Odoo (OpenERP)

Los campos IntroducciĆ³n 


    Los objetos pueden contener diferentes tipos de campos. Esos tipos se pueden dividir en tres categorĆ­as: los tipos simples, tipos de relaciĆ³n y campos funcionales. Los tipos simples son enteros, reales, booleanos, cadenas, etc ... ; Los tipos de relaciĆ³n se utilizan para representar relaciones entre objetos (one2one, one2many, many2one). Campos funcionales son campos especiales porque no se almacenan en la base de datos pero calculan en tiempo real dado otros campos de la vista.

    AquĆ­ estĆ” la cabecera del mĆ©todo de inicializaciĆ³n de cualquier campo de la clase definida en Odoo (OpenERP) (como se puede ver en el server / bin / OSV / fields.py):
def __ init__ (self, char = "Unknow", required = False, readonly = False, domain = None, context = None, priority = 0, change_default = False, size = None, onDelete = "cascade", translate = False, selection = False, ** args):
Hay un conjunto comĆŗn de parĆ”metros opcionales que estĆ”n disponibles para la mayorĆ­a de los tipos de campos:

change_default: Ya sea o no el usuario puede definir valores por defecto en otros campos en funciĆ³n del valor de este campo. Estos valores por defecto deben ser definidos en la tabla ir.values.
help: Una descripciĆ³n de cĆ³mo se debe utilizar el campo: mĆ”s y mĆ”s descriptivo que char . AparecerĆ” en la informaciĆ³n sobre herramientas cuando se pasa el ratĆ³n sobre el campo.
ondelete: CĆ³mo manejar las eliminaciones  en un registro relacionado. Por default encontraremos el valor "ondelete".
priority: No se utiliza?
readonly: True si el usuario no puede editar este campo, de lo contrario False .
required: True si el campo debe tener un valor antes de que el objeto puede ser salvado, de lo contrario False .
size: El tamaƱo del campo en la base de datos: nĆŗmero de caracteres o dĆ­gitos. Para los campos de tipo Char.
states: Permite anular otros parĆ”metros para los estados especĆ­ficos de este objeto. Acepta un diccionario con los nombres de los estados como claves y una lista de nombres / valores tuplas como los valores. Por ejemplo: states = {'done': [('readonly', True)]}
char: El nombre del campo como debe aparecer en una etiqueta o encabezado de la columna. Cadenas que contienen caracteres no ASCII deben utilizar objetos unicode de Python. Por ejemplo: 'test': fields.boolean (u'TestĆ© ')
translate: True si el contenido de este campo debe ser traducido, de lo contrario False .

TambiƩn hay algunos parƔmetros opcionales que son especƭficos para algunos tipos de campos:



domain:
RestricciĆ³n de dominio en un campo relacional.
Valor por defecto: [].
Ejemplo: domain = [('campo', '=', valor)])
invisible:
Ocultar el valor del campo en los formularios. Por ejemplo, una contraseƱa.
on_change:
El valor por defecto para el on_change atributo en la vista. Esto abrirĆ” una funciĆ³n en el servidor cuando los cambios en el campo en el cliente. Por ejemplo, on_change = "onchange_shop_id (shop_id)" .
related:
Se utiliza cuando un campo es una referencia a otra tabla mediante su id. Este es el nombre de la tabla para buscar el valor del campo.  Por lo general se utiliza con los tipos de campos relacionados y funciĆ³n.
selection:
El valor por defecto para la selecciĆ³n de atributos en la vista. 1 significa bĆŗsqueda bĆ”sica y 2 medios de bĆŗsqueda avanzada.

Tipo de Campos 

Tipos bĆ”sicos 

booleano:
Un booleano (true, false).
Sintaxis:
fields.boolean ('Nombre de campo' [, ParƔmetros opcionales]),
integer:
Un entero.
Sintaxis:
fields.integer ('Nombre de campo' [, ParƔmetros opcionales]),
float:
Un nĆŗmero de punto flotante.
Sintaxis:
fields.float ('Nombre de campo' [, ParƔmetros opcionales]),

Nota

Los dĆ­gitos parĆ”metro opcional define la precisiĆ³n y la escala del nĆŗmero. La escala es el nĆŗmero de dĆ­gitos despuĆ©s del punto decimal, mientras que la precisiĆ³n es el nĆŗmero total de dĆ­gitos significativos en el nĆŗmero (antes y despuĆ©s del punto decimal). Si los dĆ­gitos parĆ”metro no estĆ” presente, el nĆŗmero serĆ” un nĆŗmero de punto flotante de doble precisiĆ³n. Advertencia: estos nĆŗmeros en coma flotante son inexactas (no cualquier valor puede ser convertido a su representaciĆ³n binaria) y esto puede dar lugar a errores de redondeo. Siempre se debe utilizar el parĆ”metro dĆ­gitos para cantidades monetarias.
Ejemplo:
«Nombre Campo »: fields.float (
    "Tasa cambio relativo",
    digits = (12,6) [,
    ParƔmetros opcionales]),

char:
Una cadena de longitud limitada. El parĆ”metro tamaƱo requerido determina su tamaƱo.
Sintaxis:
fields.char (
        'Nombre de campo',
        size = n [,
        ParĆ”metros opcionales]), donde #'' n'' es un nĆŗmero entero.
Ejemplo:
"Ciudad": fields.char ('Nombre de la ciudad', size = 30, required = True),
text:
Un campo de texto sin lĆ­mite de longitud.
Sintaxis:
fields.text ('Nombre de campo' [, ParƔmetros opcionales]),
date:
A la fecha.
Sintaxis:
fields.date ('Nombre de campo' [, ParƔmetros opcionales]),
datetime:
Permite almacenar la fecha y la hora del dĆ­a en el mismo campo.
Sintaxis:
fields.datetime ('Nombre de campo' [, ParƔmetros opcionales]),
binary:
Una cadena binaria
selection:
Un campo que permite al usuario hacer una selecciĆ³n entre varios valores predefinidos.
Sintaxis:
fields.selection ((('n', 'Sin confirmar'), ('c', 'Confirmado')),
                   'Nombre de campo' [, ParƔmetros opcionales]),
Nota
Formato del parĆ”metro de selecciĆ³n: tupla de tuplas de cadenas de la forma:
(( 'key_or_value' ,  'string_to_display' ),  ...  )
Nota
Usted puede especificar la funciĆ³n que devolverĆ” la tupla. Ejemplo
def  _get_selection ( auto ,  cr ,  uid ,  context = None ): 
    return  ( 
       ( 'choice1' ,  'Esta es la opciĆ³n 1' ), 
       ( 'choice2' ,  'Esta es la opciĆ³n 2' ))

_columns  =  { 
   'sel'  :  fields. selection ( 
       _get_selection , 
       '¿QuĆ© quieres? " ) 
}
Ejemplo
El uso de campos de relaciĆ³n many2one con la selecciĆ³n . En los campos de definiciones agregan:
...,
'Mi_elemento': fields.many2one (
        'modelo.relacion',
        'TĆ­tulo',
        selecciĆ³n = _sel_func),
...,
Y luego definir el _sel_func asĆ­ (pero antes de las definiciones campos):
def _sel_func(self, cr, uid, context=None):
    obj = self.pool.get('modulo.relacion')
    ids = obj.search(cr, uid, [])
    res = obj.read(cr, uid, ids, ['name', 'id'], context)
    res = [(r['id'], r['name']) for r in res]
    return res

Tipos relacionales 

one2one:
Un campo one2one expresa un uno: a: una relaciĆ³n entre dos objetos. Se ha quedado en desuso. Utilice many2one lugar.
Sintaxis:
fields.one2one ( 'other.object.name' ,  'Nombre de campo' )
many2one:
Associates este objeto a un objeto primario a travĆ©s de este campo. Por ejemplo, un empleado del Departamento pertenece harĆ­a muchos a uno. es decir, muchos empleados pertenecen a un departamento
Sintaxis:
fields.many2one (
        'other.object.name',
        'Nombre de campo',
        parƔmetros opcionales)
ParƔmetros opcionales:
  • onDelete: ¿QuĆ© debe suceder cuando el recurso de este campo se apunta a eliminar.
    • Valor predefinido: "cascade", "set default"

    • required: true
  • readonly: True
  • select: True - (crea un Ć­ndice en el campo de clave externa)
Ejemplo
"Comercial": fields.many2one (
        'res.users',
        "Comercial",
        onDelete = "cascade"),
one2many:
TODO
Sintaxis:
fields.one2many (
        'Other.object.name',
        'Campo IdentificaciĆ³n relaciĆ³n - campo_id ",
        'Nombre del campo',
        parƔmetro opcional)
ParƔmetros opcionales:
  • invisible: True / False
  • readonly: True / False
Ejemplo
'DirecciĆ³n': fields.one2many (
        'res.partner.address',
        'partner_id',
        "Contactos"),
many2many:
TODO
Sintaxis:
campos . many2many ( 'other.object.name' , 
                 'tabla_relacion_modelox_modeloy' , 
                 'actual.object.id' , 
                 'other.object.id' , 
                 'Nombre de campo' )
DĆ³nde:
  • other.object.name es el otro objeto que pertenece a la relaciĆ³n
  • objeto de relaciĆ³n es la mesa que hace que el enlace
  • actual.object.id y other.object.id son los nombres de los campos »utilizados en la tabla de relaciĆ³n
Ejemplo:
'Category_ids':
   fields.many2many (
    'res.partner.category',
    'res_partner_category_rel',
    'partner_id',
    'category_id',
    'CategorĆ­as'),
Para que sea bidireccional (= crear un campo en el otro objeto):
 
      
      
         
            
            objeto ' , 
            'actual.object.id' , 
            'other.object.id' , 
            'Other Nombre del campo' ), 
    } 
other_object_name2 ()
Ejemplo:
class res_partner_category2(osv.osv):
    _inherit = 'res.partner.category'
    _columns = {
        'partner_ids': fields.many2many(
            'res.partner',
            'res_partner_category_rel',
            'category_id',
            'partner_id',
            'Partners'),
    }
res_partner_category2()
related:
A veces es necesario hacer referencia a la relaciĆ³n de una relaciĆ³n. Por ejemplo, supongamos que usted tiene objetos: Ciudad -> Estado -> PaĆ­s, y tiene que referirse al paĆ­s de una ciudad, se puede definir un campo de la siguiente manera en el objeto City:
'Country_id': fields.related (
    'state_id',
    'country_id',
    type = "many2one",
    relation = "res.country",
    string = "PaĆ­s",
    store = False)
DĆ³nde:
  • El primer conjunto de parĆ”metros son de la cadena de campos de referencia a seguir, con el campo deseado en el extremo.
  • type es el tipo de campo que se desea.
  • Use relation si el campo deseado sigue siendo una especie de referencia. relaciĆ³n es la tabla para buscar esa referencia pulg

Los campos funcionales 

Un campo funcional es un campo cuyo valor se calcula por una funciĆ³n (en lugar de ser almacenado en la base de datos).
ParƔmetros:
fnct, arg = None, fnct_inv = None, fnct_inv_arg = None, type = "float",fnct_search = None, obj = None, method = False, store = False, multi = False
donde
  • fnct es la funciĆ³n o el mĆ©todo que va a calcular el valor del campo. Debe de haber sido declarada antes de declarar el Ć”mbito funcional.
  • fnct_inv es la funciĆ³n o mĆ©todo que le permitirĆ” escribir valores en ese campo.
  • tipo es el nombre del tipo de campo devuelto por la funciĆ³n. Puede ser cualquier nombre de tipo de campo, excepto la funciĆ³n.
  • fnct_search le permite definir el comportamiento de bĆŗsqueda en ese campo.
  • method si el campo se calcula mediante un mĆ©todo (de un objeto) o una funciĆ³n global
  • almacenar Si desea almacenar campo en la base de datos o no. El valor predeterminado es False.
  • multi es un nombre de grupo. Todos los campos con el mismo varios parĆ”metros se calculan en una sola llamada de funciĆ³n.

fnct parĆ”metro 

Si el method es cierto que la firma del mĆ©todo debe ser:
def fnct (self, cr, uid, ids, field_name, arg, context):
de lo contrario (si se trata de una funciĆ³n global), su firma debe ser:
def fnct (cr, table, ids, field_name, arg, context):
De cualquier manera, debe devolver un diccionario de valores de la forma {id'_1_ ': value'_1_', id'_2_ ': value'_2_', ...}.
Los valores del diccionario devuelto deben ser del tipo especificado por el argumento de tipo en la declaraciĆ³n del campo.
Si multi se ha establecido, field_name se sustituye por field_names : una lista de los nombres de los campos que deben ser calculados. Cada valor en el diccionario devuelto es tambiĆ©n un diccionario de nombre del campo de valor. Por ejemplo, si los campos "Nombre" y "edad" estĆ”n basados ​​en la vital_statistics funciĆ³n, el valor de retorno de vital_statistics podrĆ­a tener este aspecto cuando ids es [1, 2, 5] :
{
    1: {'nombre': 'Bob', "edad": 23},
    2: {"nombre": "Sally," edad ", 19},
    5: {"nombre": "Ed", "edad": 62}
}

parĆ”metro fnct_inv 

Si el mĆ©todo es cierto, la firma del mĆ©todo debe ser:
def fnct (self, cr, uid, ids, field_name, FIELD_VALUE, arg, context):
de lo contrario (si se trata de una funciĆ³n global), que debe ser:
def fnct (cr, table, ids, field_name, FIELD_VALUE, arg, context):

parĆ”metro fnct_search 

Si el method es True, la firma del mƩtodo debe ser:
def fnct (self, cr, uid, obj, name, args, contexto):
de lo contrario (si se trata de una funciĆ³n global), que debe ser:
def fnct (cr, uid, obj, name, args, contexto):
El valor de retorno es una lista que contiene las tuplas de 3 partes que se utilizan en funciĆ³n de la bĆŗsqueda:
return  [( 'id' , 'in' , [ 1 , 
3 , 5 ])]
obj es el mismo que 1 mismo , y el nombre recibe el nombre de campo. args es una lista de tuplas 3-parte que contiene criterios de bĆŗsqueda para este campo, a pesar de la funciĆ³n de bĆŗsqueda puede activarse por separado para cada tupla.

Ejemplo 

Supongamos que creamos un objeto de contrato, que es:
class hr_contract(osv.osv):
    _name = 'hr.contract'
    _description = 'Contract'
    _columns = {
        'name' : fields.char('Contract Name', size=30, required=True),
        'employee_id' : fields.many2one('hr.employee', 'Employee', required=True),
        'function' : fields.many2one('res.partner.function', 'Function'),
    }
hr_contract()
Si queremos aƱadir un campo que recupera la funciĆ³n de un empleado por mirar de su contrato actual, se utiliza un campo funcional. El hr_employee objeto se hereda de esta manera:
 
      
      
      
      
            
          
            
            
            
            
            FunciĆ³n ' ) 
    } 
hr_employee ()
Nota
tres puntos
  • tipe = 'many2one' se debe a que el campo de la funciĆ³n debe crear un campo many2one; funciĆ³n se declara como many2one en hr_contract tambiĆ©n.
  • obj = "res.partner.function" se utiliza para indicar que el objeto que se utilizarĆ” para el campo many2one es res.partner.function.
  • Llamamos a nuestro mĆ©todo _get_cur_function_id porque su funciĆ³n es devolver un diccionario cuyas claves son identificadores de los empleados, y cuyos valores correspondientes son los identificadores de la funciĆ³n de esos empleados. El cĆ³digo de este mĆ©todo es:
def  _get_cur_function_id ( auto ,  cr ,  uid ,  ids ,  field_name ,  arg ,  context ): 
    for  i  in  ids : 
        # obtener el identificador de la funciĆ³n actual del empleado del identificador "i" 
        sql_req =  "" " 
        SELECT f.id AS id_function
        FROM hr_contract  c
          LEFT JOIN res_partner_function f ON (f.id = c.function) 
        WHERE 
          (c.employee_id = % d ) 
        "" "  %  ( i ),

        cr . execute ( sql_req ) 
        sql_res  =  cr . dictfetchone ()

        if  sql_res :  # El empleado tiene un contrato asociado 
            res [ i ]  =  sql_res [ 'id_funciĆ³n' ] 
        else : 
            # res [i] se debe establecer en False y no a ninguna causa de XML: RPC 
            # "no se puede calcular las referencias Ninguno, salvo allow_none es permitido " 
            res [ i ]  =  False 
    retorno  res
El identificador de la funciĆ³n se recupera mediante una consulta SQL. Tenga en cuenta que si la consulta no devuelve ningĆŗn resultado, el valor de sql_res ['id_funciĆ³n'] serĆ” Ninguno. Nos forzamos el valor False en este caso, ya que el valor XML: RPC (comunicaciĆ³n entre el servidor y el cliente) no permite transmitir este valor.

ParĆ”metro Store 

Se calcularĆ” el campo y almacenar el resultado en la tabla. El campo se vuelve a calcular cuando ciertos campos se cambian en otros objetos. Se utiliza la siguiente sintaxis:
store  =  { 
    'object_name' :  ( 
            nombre_funcion , 
            [ 'field_name1' ,  'field_name2' ], 
            priority ) 
}
Se llamarĆ” a la funciĆ³n nombre_funcion cuando los cambios se escriben en los campos en la lista ['campo1', 'campo2'] en 'object_name' objeto.La funciĆ³n debe tener la siguiente firma:
def nombre_funcion (self, cr, uid, ids, context = None):
Cuando identificadores serĆ”n los identificadores de registros de la tabla del otro objeto que han cambiado los valores en los campos observados.La funciĆ³n debe devolver una lista de los identificadores de los registros de su propia tabla que debe tener el campo vuelve a calcular. Dicha lista se enviarĆ” como un parĆ”metro para la funciĆ³n principal del campo.
He aquĆ­ un ejemplo del mĆ³dulo de afiliaciĆ³n:
'membership_state' : 
    fields.function( 
        _membership_state , 
        method = True , 
        string = 'ComposiciĆ³n actual'),
        
        
        
               
              
             
                      
                
                
        

Campos Property (Propiedad) 

Declarar una propiedad

Una propiedad es un campo especial: fields.property.
{
 "Lista de precios " ,method = True , view_load = True , 
 group_name = "propiedades Lista de Precios" ) 
    }
Entonces usted tiene que crear el valor por defecto en un archivo XML para esta propiedad.:
<record model="ir.property" id="property_product_pricelist">
    <field name="name">property_product_pricelist</field>
    <field name="fields_id" search="[('model','=','res.partner'),
      ('name','=','property_product_pricelist')]"/>
    <field name="value" eval="'product.pricelist,'+str(list0)"/>
</record>


Si el valor por defecto apunta a un recurso de otro mĆ³dulo, puede usar la funciĆ³n de Ć”rbitro de esta manera:
<field name="value" eval="'product.pricelist,'+str(ref('module.data_id'))"/>

Property en Vistas Form.

Para agregar propiedades en las formas, sĆ³lo hay que poner la etiqueta <properties/> en su formulario. Esto agregarĆ” automĆ”ticamente todos los campos de propiedades que estĆ”n relacionados con este objeto. El sistema agregarĆ” propiedades en funciĆ³n de sus derechos. (Algunas personas serĆ”n capaces de cambiar una propiedad especĆ­fica, otros no).
Las propiedades se muestran en la secciĆ³n, dependiendo del atributo nombre_grupo. (Se representa en el cliente como una etiqueta separador).

¿CĆ³mo funciona esto?

La clase fields.property hereda de fields.function y reemplaza el mĆ©todo de lectura y escritura. El tipo de este campo es many2one, por lo que en la forma de una propiedad se representa como una funciĆ³n many2one.
Pero el valor de una propiedad se almacena en la clase ir.property / table como un registro completo. El valor almacenado es un campo de referencia de tipo (no many2one), ya que cada establecimiento puede apuntar a un objeto diferente. Si modifica los valores de las propiedades (en el menĆŗ de administraciĆ³n), se representan como un campo de referencia de tipo.
Cuando se lee una propiedad, el programa le da la propiedad asociado con la instancia de objeto que estĆ” leyendo. Si este objeto no tiene valor, el sistema le darĆ” la propiedad predeterminada.
La definiciĆ³n de una propiedad se almacena en la clase ir.model.fields como cualquier otro campo. En la definiciĆ³n de la propiedad, puede agregar grupos que tienen permiso para cambiar a la propiedad.

UtilizaciĆ³n de las propiedades o campos normales

Si desea aƱadir una nueva caracterĆ­stica, tendrĆ” que optar por aplicar como una propiedad o terreno normal. Utilice un campo normal cuando se hereda de un objeto y quiere extender este objeto. Utilice una propiedad cuando la nueva funciĆ³n no estĆ” relacionada con el objeto, sino a un concepto externo.
AquĆ­ hay algunos consejos para ayudarle a elegir entre un campo normal o una propiedad:
Campos normales ampliar el objeto, la adiciĆ³n de mĆ”s caracterĆ­sticas o datos.
Una propiedad es un concepto que se adjunta a un objeto y tienen caracterĆ­sticas especiales:
  • Valor diferente para la misma propiedad en funciĆ³n de la empresa
  • La gestiĆ³n de derechos por campo
  • Es un vĆ­nculo entre los recursos (many2one)
Ejemplo 1: Cuentas por cobrar

La "Cuenta por cobrar" por defecto de pareja se implementa como una propiedad porque:
  • Este es un concepto relacionado con la tabla de cuenta y no a la pareja, por lo que es una propiedad de cuenta de que es visible en una forma pareja. Derechos tienen que ser manejados en este campo para los contables, estos no son los mismos derechos que se aplican a los objetos asociados. AsĆ­ que usted tiene derechos especĆ­ficos sĆ³lo para este campo de forma pareja: sĆ³lo los contadores pueden cambiar la cuenta por cobrar de un socio.
  • Este es un campo multi-empresa: la misma pareja puede tener diferentes valores de cuentas por cobrar en funciĆ³n de la empresa que pertenece el usuario. En un sistema multi-empresa, hay una carta cuenta por la empresa. La cuenta por cobrar de una pareja depende de la empresa que realizĆ³ el pedido de venta.
  • La cuenta por cobrar por defecto es el mismo para todos los socios y se configura desde el menĆŗ general de la propiedad (en la administraciĆ³n).

Nota

Una cosa interesante es que las propiedades evitan cĆ³digo "spaghetti". El mĆ³dulo cuenta depende del mĆ³dulo pareja (base). Pero se puede instalar el mĆ³dulo pareja (base) sin el mĆ³dulo de contabilidad. Si agrega un campo que apunta a una cuenta en el objeto de pareja, ambos objetos dependerĆ”n de los demĆ”s. Es mucho mĆ”s difĆ­cil de mantener y cĆ³digo (por ejemplo, tratar de eliminar una tabla cuando ambas tablas estĆ”n apuntando a los demĆ”s.)

Ejemplo 2: Tiempos de productos

El mĆ³dulo de caducidad del producto implementa todas las demoras relacionadas con los productos: Fecha de retiro, usetime producto, ... Este mĆ³dulo es muy Ćŗtil para las industrias de alimentos.
En este mĆ³dulo se hereda del objeto product.product y aƱade nuevos campos a la misma:

clase  product_product ( OSV . OSV ):

    _inherit  =  'product.product' 
    _name  =  'product.product' 
    _columns  =  {

        'Life_time' :  fields.integer ( 'Tiempo de vida del producto' ), 
        'use_time' :  fields.integer ( 'usetime producto' ), 
        'removal_time' :  fields.integer ( "tiempo de retirada del producto ' ), 
        'alert_time' :  fields.integer ( 'tiempo de alerta del producto' ), 
        }

product_product ()
Este mĆ³dulo agrega campos simples al objeto product.product. No usamos las propiedades debido a que:
  • Extendemos un producto, el campo life_time es un concepto relacionado con un producto, no a otro objeto.
  • No necesitamos una gestiĆ³n correcta por campo, los diferentes retardos son gestionados por las mismas personas que manejan todos los productos.

1 comentario:

  1. GermƔn, cuidadƭn al traducir de forma automƔtica!!
    Como pongas "cataratas" en lugar de "cascade" al definir un campo, ya verƔs que tortazo.
    ParƔmetro "tienda", otra mƔs. Es "store" y punto.
    Los campos de tipo propiedad no existen, son de tipo "property".
    En fin, hay que darle un repaso :-)
    Un saludo,
    Juan

    ResponderBorrar