Views

Es werden zwei Arten von views unterschieden. Zum einen die Benutzeroberfläche und zum anderen der Report.
Beide werden über xml definiert.

Grundaufbau

Alle views haben folgende Struktur. Die angezeigten Daten werden von model bestimmt(Beispiel: sale.order.line). Nur die Felder in diesem Modell können angezeigt werden.

<record model="ir.ui.view" id="view_id">
    <field name="name">view.name</field>
    <field name="model">sale.order.line</field>
    <field name="priority" eval="16"/>
    <field name="arch" type="xml">
        <!-- view content: <form>, <tree>, <graph>, ... -->
    </field>
</record>


tree view

Zeigt Positionen in Listenform an.

<tree string="Idea list">
    <field name="name"/>
    <field name="inventor_id"/>
</tree>


form view

Definiert das Aussehen eines Formulars.

<form string="Course Form">
    <sheet>
        <group>
            <field name="name"/>
            <field name="description"/>
        </group>
    </sheet>
</form>      


menuitem

Menuitems sind immer mit einer action verbunden. Diese action zeigt auf eine tree oder from view. Unter dem Parameter parent wird angegeben an welchen Menüeintrag das neue Menuitem angehängt werden soll.

<menuitem action="eq_framework_agreement_action" id="eq_framework_agreement_menu" parent="sales_team.menu_sales" name="Framework Agreements" sequence="40"/>

Mit dem Attribut name definiert man mit welchem string das neue Menuitem in das Menü eingetragen wird. Mit sequence kann die Reihenfolge der Menüträge festgelegt werden, die Zahl gibt die Priorität an.

Die passende action hierzu sieht so aus:

<record id="eq_framework_agreement_action" model="ir.actions.act_window">
    <field name="name">Framework Agreements</field>
    <field name="res_model">eq_framework_agreement</field>
    <field name="view_type">form</field>
    <field name="view_mode">tree,form</field>
    <field name="help" type="html">
        <p class="oe_view_nocontent_create">Click on Create to create a Framework Agreement.</p>
    </field>
</record>


xpath

Auch bereits vorhanden views können erweitert werden. Hierzu wird ein Pfad zu einem Feld angegeben und code der beschreibt was zwischen diesem und dem nächsten Element passieren soll.

Das Attribut position kann folgendes Verhalten definieren:

replace

Das ausgewählte Feld wird durch den Inhalt von xpath ersetzt.

after

Alles wird hinter dem ausgewählten Feld angehängt.

before

Alles wird vor das ausgewählte Feld angehängt.

Beispiel für after:

<xpath expr="//field[@name='order_line']/form/group/group/field[@name='tax_id']" position="after">
   <field name="address_allotment_id"/>
</xpath>


Zustandekommen des Pfades:

Zuerst wird nach dem Feld 'order_line'gesucht. Von dort aus wird nacheinander form, group und einmal group gesucht. Nach dem letzten group tag wird dann nach 'tax_id' gesucht.

<record id="view_order_form" model="ir.ui.view">
    <field name="name">sale.order.form</field>
    <field name="model">sale.order</field>
    <field name="arch" type="xml">
        <form string="Sales Order" class="o_sale_order">
        <header>
            <button name="%(action_view_sale_advance_payment_inv)d" string="Create Invoice"
                type="action" class="btn-primary"
                attrs="{'invisible': [('invoice_status', '!=', 'to invoice')]}"/>
            <button name="%(action_view_sale_advance_payment_inv)d" string="Create Invoice"
                type="action" context="{'default_advance_payment_method': 'percentage'}"
                attrs="{'invisible': ['|',('invoice_status', '!=', 'no'), ('state', '!=', 'sale')]}"/>
            <button name="action_quotation_send" string="Send by Email" type="object" states="draft" class="btn-primary"/>
            <button name="print_quotation" string="Print" type="object" states="draft" class="btn-primary"/>
            <button name="action_confirm" states="sent" string="Confirm Sale" class="btn-primary o_sale_confirm" type="object" />
            <button name="action_confirm" states="draft" string="Confirm Sale" class="o_sale_confirm" type="object" />
            <button name="print_quotation" string="Print" type="object" states="sent,sale"/>
            <button name="action_quotation_send" string="Send by Email" type="object" states="sent,sale"/>
            <button name="action_cancel" states="draft,sent,sale" type="object" string="Cancel"/>
            <button name="action_draft" states="cancel" type="object" string="Set to Quotation"/>
            <button name="action_done" type="object" string="Lock" states="sale"
                help="If the sale is locked, you can not modify it anymore. However, you will still be able to invoice or deliver."/>
            <field name="state" widget="statusbar" statusbar_visible="draft,sent,sale"/>
        </header>
        <sheet>
            <div class="oe_button_box" name="button_box">
                <button name="action_view_invoice"
                    type="object"
                    class="oe_stat_button"
                    icon="fa-pencil-square-o"
                    attrs="{'invisible': [('invoice_count', '=', 0)]}">
                    <field name="invoice_count" widget="statinfo" string="Invoices"/>
                </button>
            </div>
            <div class="oe_title">
                <h1>
                    <field name="name" readonly="1"/>
                </h1>
            </div>
            <group>
                <group>
                    <field name="partner_id" domain="[('customer','=',True)]" context="{'search_default_customer':1, 'show_address': 1}" options='{"always_reload": True}'/>
                    <field name="partner_invoice_id" groups="sale.group_delivery_invoice_address" context="{'default_type':'invoice'}"/>
                    <field name="partner_shipping_id" groups="sale.group_delivery_invoice_address" context="{'default_type':'delivery'}"/>
                </group>
                <group>
                    <field name="date_order" attrs="{'invisible': [('state', 'in', ['sale', 'done', 'cancel'])]}"/>
                    <field name="validity_date" attrs="{'invisible': [('state', 'in', ['sale', 'done'])]}"/>
                    <field name="confirmation_date" attrs="{'invisible': [('state', 'in', ['draft', 'sent', 'cancel'])]}"/>
                    <field name="pricelist_id" groups="product.group_sale_pricelist"/>
                    <field name="currency_id" invisible="1"/>
                    <field name="payment_term_id" options="{'no_create': True}"/>
                </group>
            </group>
            <notebook>
                <page string="Order Lines">
                    <field name="order_line" mode="tree,kanban"
                        attrs="{'readonly': [('state', 'in', ('done','cancel'))]}">
                        <form string="Sales Order Lines">
                            <group>
                                <group>
                                    <field name="product_id"
                                        context="{'partner_id':parent.partner_id, 'quantity':product_uom_qty, 'pricelist':parent.pricelist_id, 'uom':product_uom, 'company_id': parent.company_id}"
                                        attrs="{'readonly': ['|', ('qty_invoiced', '&gt;', 0), ('procurement_ids', '!=', [])]}"
                                       />
                                    <field name="layout_category_id" groups="sale.group_sale_layout"/>
                                    <field name="invoice_status" invisible="1"/>
                                    <field name="qty_to_invoice" invisible="1"/>
                                    <field name="qty_delivered_updateable" invisible="1"/>
                                    <field name="procurement_ids" invisible="1"/>
                                    <field name="price_subtotal" invisible="1"/>
                                    <label for="product_uom_qty" string="Ordered Quantity"/>
                                    <div>
                                        <field
                                            context="{'partner_id':parent.partner_id, 'quantity':product_uom_qty, 'pricelist':parent.pricelist_id, 'uom':product_uom, 'uom_qty_change':True, 'company_id': parent.company_id}"
                                            name="product_uom_qty" class="oe_inline"/>
                                        <field name="product_uom" groups="product.group_uom" class="oe_inline oe_no_button"
                                            attrs="{'readonly': [('state', 'in', ('sale','done', 'cancel'))]}"/>
                                    </div>
                                    <label for="qty_delivered" string="Delivered Quantity" invisible="context.get('hide_sale')"/>
                                    <div invisible="context.get('hide_sale')">
                                        <field name="qty_delivered" attrs="{'readonly': [('qty_delivered_updateable', '=', False)]}"/>
                                    </div>
                                    <label for="qty_invoiced" string="Invoiced Quantity" invisible="context.get('hide_sale')"/>
                                    <div invisible="context.get('hide_sale')">
                                        <field name="qty_invoiced" invisible="context.get('hide_sale')"/>
                                    </div>
                                    <field name="price_unit"/>
                                    <label for="discount" groups="sale.group_discount_per_so_line"/>
                                    <div name="discount" groups="sale.group_discount_per_so_line">
                                        <field name="discount" class="oe_inline"/> %%
                                    </div>
                                </group>
                                <group>
                                    <field name="tax_id" widget="many2many_tags" domain="[('type_tax_use','=','sale'),('company_id','=',parent.company_id)]"
                                        attrs="{'readonly': [('qty_invoiced', '&gt;', 0)]}"/>
                                    <label for="customer_lead"/>
                                    <div>
                                        <field name="customer_lead" class="oe_inline"/> days
                                    </div>
                                    <label for="analytic_tag_ids"/>
                                    <div>
                                        <field name="analytic_tag_ids" widget="many2many_tags"/>
                                    </div>
                                </group>
                            </group>
                            <label for="name"/>
                            <field name="name"/>
                            <div groups="base.group_no_one">
                                <label for="invoice_lines"/>
                                <field name="invoice_lines"/>
                            </div>
                            <field name="state" invisible="1"/>
                        </form>
                        <tree string="Sales Order Lines" editable="bottom" decoration-info="invoice_status=='to invoice'">
                            <field name="sequence" widget="handle"/>
                            <field name="product_id"
                                attrs="{'readonly': ['|', ('qty_invoiced', '&gt;', 0), ('procurement_ids', '!=', [])]}"
                                context="{'partner_id':parent.partner_id, 'quantity':product_uom_qty, 'pricelist':parent.pricelist_id, 'uom':product_uom, 'company_id': parent.company_id}"
                               />
                            <field name="layout_category_id" groups="sale.group_sale_layout"/>
                            <field name="name"/>
                            <field name="product_uom_qty"
                                string="Ordered Qty"
                                context="{'partner_id':parent.partner_id, 'quantity':product_uom_qty, 'pricelist':parent.pricelist_id, 'uom':product_uom, 'company_id': parent.company_id}"
                            />
                            <field name="qty_delivered" invisible="context.get('hide_sale')"
                                attrs="{'readonly': [('qty_delivered_updateable', '=', False)]}"/>
                            <field name="qty_invoiced"
                                invisible="context.get('hide_sale')"/>
                            <field name="qty_to_invoice" invisible="1"/>
                            <field name="product_uom"
                                attrs="{'readonly': [('state', 'in', ('sale','done', 'cancel'))]}"
                                context="{'company_id': parent.company_id}"
                                groups="product.group_uom" options='{"no_open": True}'/>
                            <field name="analytic_tag_ids" groups="analytic.group_analytic_accounting" widget="many2many_tags"/>
                            <field name="price_unit"
                                attrs="{'readonly': [('qty_invoiced', '&gt;', 0)]}"/>
                            <field name="tax_id" widget="many2many_tags" domain="[('type_tax_use','=','sale'),('company_id','=',parent.company_id)]"
                                attrs="{'readonly': [('qty_invoiced', '&gt;', 0)]}"/>
                            <field name="discount" groups="sale.group_discount_per_so_line"/>
                            <field name="price_subtotal" widget="monetary" groups="sale.group_show_price_subtotal"/>
                            <field name="price_total" widget="monetary" groups="sale.group_show_price_total"/>
                            <field name="qty_delivered_updateable" invisible="1"/>
                            <field name="procurement_ids" invisible="1"/>
                            <field name="state" invisible="1"/>
                            <field name="invoice_status" invisible="1"/>
                            <field name="customer_lead" invisible="1"/>
                            <field name="currency_id" invisible="1"/>
                        </tree>
                        <kanban class="o_kanban_mobile">
                            <field name="product_id"/>
                            <field name="product_uom_qty"/>
                            <field name="product_uom" groups="product.group_uom"/>
                            <field name="price_subtotal"/>
                            <templates>
                                <t t-name="kanban-box">
                                    <div t-attf-class="oe_kanban_card oe_kanban_global_click">
                                        <div class="row">
                                            <div class="col-xs-12">
                                                <strong><span><t t-esc="record.product_id.value"/></span></strong>
                                            </div>
                                        </div>
                                        <div class="row">
                                            <div class="col-xs-8 text-muted">
                                                <span><t t-esc="record.product_uom_qty.value"/> <t t-esc="record.product_uom.value"/></span>
                                            </div>
                                            <div class="col-xs-4 text-muted">
                                                <span class="pull-right text-right"><t t-esc="record.price_subtotal.value"/></span>
                                            </div>
                                        </div>
                                    </div>
                                </t>
                            </templates>
                        </kanban>
                    </field>
                    <group class="oe_subtotal_footer oe_right" colspan="2" name="sale_total">
                        <field name="amount_untaxed" widget='monetary' options="{'currency_field': 'currency_id'}"/>
                        <field name="amount_tax" widget='monetary' options="{'currency_field': 'currency_id'}"/>
                        <div class="oe_subtotal_footer_separator oe_inline o_td_label">
                            <label for="amount_total" />
                            <button name="button_dummy"
                                states="draft,sent" string="(update)" type="object" class="oe_edit_only oe_link"/>
                        </div>
                        <field name="amount_total" nolabel="1" class="oe_subtotal_footer_separator" widget='monetary' options="{'currency_field': 'currency_id'}"/>
                    </group>
                    <field name="note" class="oe_inline" placeholder="Setup default terms and conditions in your company settings."/>
                    <div class="oe_clear"/>
                </page>
                <page string="Other Information">
                    <group>
                        <group string="Sales Information" name="sales_person">
                            <field name="user_id"/>
                            <field name="team_id" options="{'no_create': True}"/>
                            <field name="client_order_ref"/>
                            <field name="company_id" options="{'no_create': True}" groups="base.group_multi_company"/>
                            <field name="project_id" attrs="{'invisible':[('state','=','sale')]}" context="{'default_partner_id':partner_invoice_id, 'default_name':name}" groups="analytic.group_analytic_accounting"/>
                            <field name="related_project_id"
                                   attrs="{'readonly': ['|',('project_id','!=',False),('invoice_count','!=',0),('state','=','sale')],'invisible':[('state','!=','sale')]}"
                                   context="{'default_partner_id':partner_invoice_id, 'default_name':name}"
                                   groups="analytic.group_analytic_accounting"/>
                        </group>
                        <group name="sale_pay" string="Invoicing">
                            <field name="fiscal_position_id" options="{'no_create': True}"/>
                            <field name="invoice_status"
                                attrs="{'invisible': [('state', 'not in', ('sale','done'))]}"/>
                        </group>
                        <group string="Reporting" name="technical" groups="base.group_no_one">
                            <field groups="base.group_no_one" name="origin"/>
                        </group>
                    </group>
                </page>
            </notebook>
        </sheet>
        <div class="oe_chatter">
            <field name="message_follower_ids" widget="mail_followers"/>
            <field name="message_ids" widget="mail_thread"/>
        </div>
        </form>
    </field>
</record>


function

Es können beliebige Methoden aufgerufen werden. Dies geschieht immer bei der installation des Moduls.

<function model="eq_install_func" name="_load_translation"/>


Reports

Reports verhalten sich ähnlich wie views. Sie sind jedoch dazu gedacht auf Papier ausgedruckt zu werden.

Vereinfachtes Beispiel:

<odoo>
<data>
    <report
        id="report_session"
        model="openacademy.session"
        string="Session Report"
        name="openacademy.report_session_view"
        file="openacademy.report_session"
        report_type="qweb-pdf" />

    <template id="report_session_view">
        <t t-call="report.html_container">
            <t t-foreach="docs" t-as="doc">
                <t t-call="report.external_layout">
                    <div class="page">
                        <h2 t-field="doc.name"/>
                        <p>From <span t-field="doc.start_date"/> to <span t-field="doc.end_date"/></p>
                        <h3>Attendees:</h3>
                        <ul>
                            <t t-foreach="doc.attendee_ids" t-as="attendee">
                                <li><span t-field="attendee.name"/></li>
                            </t>
                        </ul>
                    </div>
                </t>
            </t>
        </t>
    </template>
</data>
</odoo>


render_html Methode

Möchte man dem report noch ein zweites oder n-tes Modell übergeben so kann die render_html Methode überschrieben werden.

@api.multi
def render_html(self, data=None):
    req = self.env['eq_requirement'].search([('id', '=', self.id)])
    line = self.env['eq_requirement.line'].search([('eq_requirement', '=', self.id)])
    report_obj = self.env['report']
    report = report_obj._get_report_from_name('eq_rmanager.report_session_view_full')

    docargs = {
        'doc_ids': req._ids,
        'doc_model': report.model,
        'docs': req,
        'line': line,
    }
    return report_obj.render('eq_rmanager.report_session_view_full', docargs)

Im obigen Beispiel wird zusätzlich zu 'eq_requirement' noch das Modell 'eq_requirement.line' übergeben. Im XML können dessen Felder dann mit line.<Feldname> abgerufen werden.