Site Tools


Hotfix release available: 2025-05-14a "Librarian". upgrade now! [56.1] (what's this?)
New release available: 2025-05-14 "Librarian". upgrade now! [56] (what's this?)
Hotfix release available: 2024-02-06b "Kaos". upgrade now! [55.2] (what's this?)
Hotfix release available: 2024-02-06a "Kaos". upgrade now! [55.1] (what's this?)
New release available: 2024-02-06 "Kaos". upgrade now! [55] (what's this?)
Hotfix release available: 2023-04-04b "Jack Jackrum". upgrade now! [54.2] (what's this?)
Hotfix release available: 2023-04-04a "Jack Jackrum". upgrade now! [54.1] (what's this?)
New release available: 2023-04-04 "Jack Jackrum". upgrade now! [54] (what's this?)
Hotfix release available: 2022-07-31b "Igor". upgrade now! [53.1] (what's this?)
Hotfix release available: 2022-07-31a "Igor". upgrade now! [53] (what's this?)
New release available: 2022-07-31 "Igor". upgrade now! [52.2] (what's this?)
New release candidate 2 available: rc2022-06-26 "Igor". upgrade now! [52.1] (what's this?)
New release candidate available: 2022-06-26 "Igor". upgrade now! [52] (what's this?)
Hotfix release available: 2020-07-29a "Hogfather". upgrade now! [51.4] (what's this?)
old revision restored (2025/06/24 08:33)
it:openerp:general

OpenERP

zu klärende Fragen zum Einstieg

  • wie werden gelöschte Datensätze behandelt? (aus Tabelle gelöscht und wohin?)
  • Anbindung an OpenOffice
  • Zuordnung Users zu partners
    • res.partner's Feld 'user_id' welches auf den Salesman verweist scheint hierfür genutzt zu werden.

OpenERP Entwicklung

Standardmäßig extended view für admin setzen

<!-- Set Extended View for Administrator -->
    <record model="res.users" id="base.user_root">
      <field name="view">extended</field>
    </record>

Felder anhand von Status sperren

'reference': fields.char('Reference', size=128, required=1, states={'done': [('readonly', True)]}),

Spalten Create_Date und Write_Date einblenden:

_columns = {
   'create_date': fields.datetime('Creation Date' , readonly=True),
   'write_date': fields.datetime('Write Date' , readonly=True),
}

Encoding

Unbedingt alle Python Dateien mit UTF-8 explizit kodieren, um ASCII-Konvertierungsfehler zu vermeiden.

# -*- coding: utf-8 -*-

Domain Filter auf one2many Spalte

Active Spalte

Legt man eine Bool-Spalte namens “active” an, wird dieses standardmäßig in Domains abgefragt.

Message an ui

from tools.translate import _
raise osv.except_osv(
                        _('Could not cancel purchase order !'),
                        _('You must first cancel all picking attached to this purchase order.'))

Übersetzung der message

In der .po Datei

#. module: purchase
#: code:addons/purchase/purchase.py:721
#, python-format
msgid ""
"You have to select a product UOM in the same category than the purchase UOM "
"of the product"
msgstr ""
"Sie müssen eine Mengeneinheit auswählen, die sich in derselben Kategorie wie "
"die Produktmengeneinheit (ME) des Einkaufs befindet"

einen String übersetzen

from tools.translate import _
 
 
result = _('text zu übersetzen')

summmen von float fields im tree

<field name="residual" sum="Residual Amount"/>

ein browse-objekt per xml-id holen

print pool.get("ir.model.data").get_object(cr, uid, "cp_crm", "salutation_1").title

kontextsensitive Suchformulare

 _columns={
        'partner_id': fields.many2one('res.partner', string='Partner'),
        'company_id': fields.many2one('res.company', string='Company'),
        'account_receivable': fields.many2one('account.account', domain="[('type', '=', 'receivable'), ('company_id', '=', company_id)]", string="Account Receivable"),
        'account_payable': fields.many2one('account.account', domain="[('type', '=', 'payable'), ('company_id', '=', company_id)]", string="Account Payable"),
        'company_name': fields.related('company_id', 'name', type='char', string='Company name'),
        'partner_name': fields.related('partner_id', 'name', type='char', string='Partner name'),

Durch ('company_id', '=', company_id) nimmt die Domäne aus dem aktuellen Kontext den Wert company_id.

Weiterhin kann auf ein Ändern eines Feldes aus dem Kontext reagiert werden, um die Domäne abzudaten.

<field name="company_id" widget="selection" width="150" on_change="on_change_company_id(company_id)"/>
<field name="account_payable" width="150"/>
<field name="account_receivable" width="150"/>
    def on_change_company_id(self, cr, uid, ids, company_id):
        d={}
        if company_id!=False:
            d['account_receivable']=[('company_id', '=', company_id)]
        return{'domain':d}

Context => auf übergeordnete Felder zugreifen

<field name="product_id" colspan="4" context="partner_id=parent.partner_id,quantity=product_qty,pricelist=parent.pricelist_id,uom=product_uom,warehouse=parent.warehouse_id"/>
   <field name="levels"/> <!-- one2many Verknüpfung -->
   <field name="units" nolabel="1" mode="tree,form" context="{'levels': map(lambda x: x[1], levels)}"> <!-- neue context variable levels = liste aus ids aus levels -->
     <tree string="Units">
       <field name="name" />
       <field name="level_id" />
     </tree>
     <form string="Unit">
       <field name="name"/>
       <field name="level_id" domain="[('id', 'in', context['levels'])]"/> <!-- many2one nur auf levels die im übergeordneten levels stehen -->
     </form>
   </field>

Spezifischen View in Field durch context verwenden

#zur Verfügung stehen search_view_ref, form_view_ref und tree_view_ref
<field name="test" context="{'search_view_ref':'modul.xml_id'}"/>

Filter durch Context setzen

#filter im such view
<filter string="Das ist ein Test Filter" name="test_filter" domain="[('id','>',0)]/>"
 
#filter setzen im field das auf andere Entität geht
<field name="test_field" context="{'search_default_test_filter':1}"
# 1 = filter an, 0 = filter aus

SQL Constraints

Im Modul res.groups habe folgende Anweisung entdeckt:

_sqlconstraints = [
  ('name_uniq', 'unique (name)', 'The name of the group must be unique!')
]

Man kann also super leicht contraints definieren…z.B. praktisch für NLV: maximal ein gültiger Standort zu einem Zeitpunkt und nicht zwei.

xml_id in id umwandeln

<record id="server_action_assign_task" model="ir.actions.server">
			<field name="name">Assign task to me</field>
			<field name="type">ir.actions.server</field>
			<field name="model_id" search="[('model', '=', 'project.task')]" />
      		<field name="state">code</field>
      		<field name="code">obj.assign_task_to_me()</field>
		</record>
		<record id="ir_value_assign_task" model="ir.values">
			<field name="name">Assign task to me</field>
			<field name="key">action</field>
			<field name="key2">client_action_multi</field>
			<field name="model">project.task</field>
			<field name="value" eval="'ir.actions.server,%d'%server_action_assign_task"/>
			<field name="object" eval="True"/>
		</record>

domain in action window mit xml_id

<field name="domain" eval="[('user_id','=',ref('base.user_root'))]"/>

lambda Ausdrücke in defaults columns

    _defaults = {
         'name':lambda self, cursor, user, context:self.pool.get(
                                                'res.users'
                                                ).read(
                                                        cursor,
                                                        user,
                                                        user,
                                                        ['name'],
                                                        context
                                                        )['name'],
         'state':lambda * a:'draft',
         'smtpport':lambda *a:25,
         'smtpserver':lambda *a:'localhost',
         'company':lambda *a:'yes',
         'user':lambda self, cursor, user, context:user,
         'send_pref':lambda *a: 'html',
         'smtptls':lambda *a:True,
     }

defaults überschreiben

Hiermit wird der default Wert des Feldes date überschrieben.

<field name="works" colspan="4" nolabel="1" mode="tree,form" context="{'default_date': date_current + time.strftime(' %%H:%%M:%%S')}">

Praktische Parameter der openerp_server.py

Um nur ein spezifisches Modul beim start neu zu laden:

openerp_server.py -d <dbname> --update=<modulname>

-----------------

Model Ebene

Felder

Wenn das Feld related auf ein one2many Feld zeigt, dann wird dort das erste Element verwendet unter Beachtund der Sortierung (_order).

Erweitern von Standard Selection Fields

Beispielsweise gibt es bei res.partner ein Auswahlfeld für den Adresstyp. Um diesen zu erweitern, muss im init.py der eigenen Klasse per Programmcode die neuen Selections hinzugefügt werden. Geht so:

def __init__(self, pool, cr):
        #TIP extend selection
        super(osv.osv, self).__init__(pool, cr)
        pool = pooler.get_pool(cr.dbname)
        partner_object = pool.get("res.partner.address")
        partner_object._columns['type'].selection.append(('house', 'House Address'))
Readonly nur bei bestimmten Status True
'company_id': fields.many2one('res.company', 'Company', required=True, readonly=True, states={'draft':[('readonly',False)]}),

ähnlich im XML:

<group attrs="{'readonly': [('field_name', '=', 'value')]}">

Many2Many Felder Füllen

        Note: The type of field values to pass in vals for relationship fields is specific:

                *

                  For a many2many field, a list of tuples is expected. Here is the list of tuple that are accepted, with the corresponding semantics

                  (0, 0,  { values })    link to a new record that needs to be created with the given values dictionary
                  (1, ID, { values })    update the linked record with id = ID (write *values* on it)
                  (2, ID)                remove and delete the linked record with id = ID (calls unlink on ID, that will delete the object completely, and the link to it as well)
                  (3, ID)                cut the link to the linked record with id = ID (delete the relationship between the two objects but does not delete the target object itself)
                  (4, ID)                link to existing record with id = ID (adds a relationship)
                  (5)                    unlink all (like using (3,ID) for all linked records)
                  (6, 0, [IDs])          replace the list of linked IDs (like using (5) then (4,ID) for each ID in the list of IDs)

                  Example:
                     [(6, 0, [8, 5, 6, 4])] sets the many2many to ids [8, 5, 6, 4]

                *

                  For a one2many field, a lits of tuples is expected. Here is the list of tuple that are accepted, with the corresponding semantics

                  (0, 0,  { values })    link to a new record that needs to be created with the given values dictionary
                  (1, ID, { values })    update the linked record with id = ID (write *values* on it)
                  (2, ID)                remove and delete the linked record with id = ID (calls unlink on ID, that will delete the object completely, and the link to it as well)

                  Example:
                     [(0, 0, {'field_name':field_value_record1, ...}), (0, 0, {'field_name':field_value_record2, ...})]

                *

                  For a many2one field, simply use the ID of target record, which must already exist, or False to remove the link.
                *

                  For a reference field, use a string with the model name, a comma, and the target object id (example: 'product.product, 5')

Mittels eineer Funktion lässt sich dies folgendermassen erledigen:

# Felddeklaration:
        'move_lines':fields.function(_get_lines, method=True, type='many2many', relation='account.move.line', string='Entry Lin
# Funktionsdefinition
   # Give Journal Items related to the payment reconciled to this invoice
    # Return ids of partial and total payments related to the selected invoices
    def _get_lines(self, cr, uid, ids, name, arg, context=None):
        res = {}
        for invoice in self.browse(cr, uid, ids, context=context):
            id = invoice.id
            res[id] = []
            if not invoice.move_id:
                continue
            data_lines = [x for x in invoice.move_id.line_id if x.account_id.id == invoice.account_id.id]
            partial_ids = []
            for line in data_lines:
                ids_line = []
                if line.reconcile_id:
                    ids_line = line.reconcile_id.line_id
                elif line.reconcile_partial_id:
                    ids_line = line.reconcile_partial_id.line_partial_ids
                l = map(lambda x: x.id, ids_line)
                partial_ids.append(line.id)
                res[id] =[x for x in l if x <> line.id and x not in partial_ids]
        return res

View Ebene

View öffnen

Aus einem Tree oder From View einen anderen View öffnen

#wizard erstellen
class open_ref_wizard(wizard.interface):
 
    def open_ref(self, cr, uid, data, context):
 
        return {
            'name': 'test',
            'view_type': 'form',
            'view_mode': 'form,tree',
            'res_model': model,
            'res_id': int(id),
            'view_id': False,
            'type': 'ir.actions.act_window',
            'target': 'new',
        }
 
    states = {
        'init': {
            'actions': [],
            'result': {
                'type': 'action',
                'action': open_ref,
                'state':'end',
            }
        }
    }
open_ref_wizard('cp_cash.open_ref')
<!-- wizard definieren -->
<wizard string="Open Ref" model="cp_cash.liquidity.source" name="cp_cash.open_ref" id="open_ref" />
 
<!-- button in tree oder form einbinden -->
<button string="Open Ref" name="%(open_ref)d" type="action" icon="gtk-open" />

Message an UI

raise osv.osv.except_osv("Message", Values_For_Message, exc_Type)
Events

Felder in Views haben ein “onchange” event Attribut: http://doc.openerp.com/v6.0/developer/2_6_views_events/events/events.html#on-change Format:

MethodenName(Parameter)

Die Methode muss folgende Signatur haben:

MethodenName(self, cursor, userid, selectierteElementeIds, parameter)

Um den View über die Änderungen zu informieren, wird eine collection Zurückgegeben:

{'values':{'KlassenAttribut':Wert}}

Schnittstellen

Agenda

Offene Posten
it/openerp/general.txt · Last modified: 2025/08/04 04:13 by 216.73.216.198