odoo報表

* odoo8 採用是Qweb報表,廢棄了7.0中的RML報表
        
* 創建業務報表
    報表是通過Qweb的技術來建立的
    #一般報表結構如下:
     purchase
       ├ views
       │  ├ report_purchaseorder.xml (報表模板)
       │  ├ report_purchasequotaion.xml
       ├ purchase_report.xml (模塊中報表定義 模塊名_report.xml)    
       
     當要建立報表時,就按這樣的結構來創建,    
     
    #注意,報表,用到了wkhtmltopdf依賴
      http://wkhtmltopdf.org/downloads.html   wkhtmltopdf-0.12.1 版本
      $ sudo apt-get remove --purge wkhtmltopdf
      $ cd /tmp
      $ wget http://downloads.sourceforge.net/project/wkhtmltopdf/archive/0.12.1/
              wkhtmltox-0.12.1_linux-trusty-adm64.deb
              
      $ sudo dpkg -i wkhtmltox-0.12.1_linux-trusty-amd64.deb
  
    #報表定義purchase_report.xml:(註冊報表)
      <?xml version="1.0" encoding="utf-8"?>
        <openerp>
            <data>
                <report 
                    string="Purchase Order" 
                    id="action_report_purchase_order" 
                    model="purchase.order" 
                    report_type="qweb-pdf"
                    name="purchase.report_purchaseorder" 
                    file="purchase.report_purchaseorder" 
                />

                <report 
                    string="Request for Quotation" 
                    id="report_purchase_quotation" 
                    model="purchase.order" 
                    report_type="qweb-pdf"
                    name="purchase.report_purchasequotation" 
                    file="purchase.report_purchasequotation"
                />
            </data>
        </openerp>
        @string: 在打印按鈕那裏的顯示名稱 
        @id:外id標識
        @name: 完整主模板名稱 模塊名.主板模名稱  用於管理和調用
        @file: 完整模板文件名 模塊名.模板文件名  用於更好地關聯模板
        @model:相關的模型顯示在那個模塊進行打印報表 通常在各視圖中的打印那裏會出現
         上面表示在採購訂單相關視圖時,會出現“打印-詢價單/採購訂單”
        @report_type: 報表類型 是 qweb-pdf 或 qweb-html
        @report_name: 打印出來的文件名
        @groups_id:指定權限
        --------
        attachment_use="True"
        attachment="(object.state in ('open','paid')) and
        ('INV'+(object.number or '').replace('/','')+'.pdf')"
        @attachment_use:使用附件,這樣不會一直查數據庫,只能當數據變化時纔會查數據庫
        @attachment:附件的名稱,當我們下載下來的文件名
        ------
              
        <report> 是 ir.actions.report.xml 模型的快捷方式
        
    
        <record id="action_report_purchase_order" model="ir.actions.report.xml">
                <field name="name">Purchase Order</field>
                <field name="model">purchase.order</field>
                <field name="report_type">qweb-pdf</field>
                <field name="template_name">
                    purchase.report_purchaseorder
                </field>
                <field name="paper_format_id" ref="report.paperformat_euro"/> 
                #指定的紙張 可以到 addons/report/data/report_paperformat.xml 查看可用紙張規格
        </record>
        報表可以在 設置->技術->報表 可以查到
         t-call 調用的標準報告架構,這個很重要
         report.external_layout 包含頭部和尾部 ,也可以只用 report.internal_layout 只用
         基礎架構的頭部,其它部分自己寫
         
    # 報表模板 report_purchaseorder.xml
        # /addons/purchase/views/report_purchase.xml:
        <?xml version="1.0" encoding="utf-8"?>
            <openerp>
            <data>
            <template id="report_purchaseorder_document">
                <t t-call="report.external_layout"> <!--套上頭尾的模板佈局-->
                    <div class="page">
                        <div class="oe_structure"/>    
                         <div class="row">
                            <div class="col-xs-6"> <!--bootstrap佈局方式-->
                                <strong>Shipping address:</strong>
                                <div t-if="o.dest_address_id">
                                    <div t-field="o.dest_address_id"
                                        t-field-options='{"widget": "contact", "fields": ["address", "name", "phone", "fax"], "no_marker": true}'/>
                                </div>

                                <div t-if="not o.dest_address_id and o.picking_type_id and o.picking_type_id.warehouse_id">
                                    <span t-field="o.picking_type_id.warehouse_id.name"/>
                                    <div t-field="o.picking_type_id.warehouse_id.partner_id"
                                        t-field-options='{"widget": "contact", "fields": ["address", "phone", "fax"], "no_marker": true}'/>
                                </div>
                            </div>
                            <div class="col-xs-5 col-xs-offset-1">
                                <div t-field="o.partner_id"
                                    t-field-options='{"widget": "contact", "fields": ["address", "name", "phone", "fax"], "no_marker": true}'/>
                                    <p t-if="o.partner_id.vat">VAT: <span t-field="o.partner_id.vat"/></p>
                            </div>
                        </div>                        
                         ...
                        <div class="oe_structure"/>
                    </div>
                </t>
            </template>

            <template id="report_purchaseorder">
                <t t-call="report.html_container">
                    <t t-foreach="doc_ids" t-as="doc_id">
                        <!--採用合作伙伴設定的語言來翻譯報表-->
                        <t t-raw="translate_doc(doc_id, doc_model, 'partner_id.lang', 'purchase.report_purchaseorder_document')"/>
                    </t>
                </t>
            </template>
            </data>
            </openerp>
            
            來一段沒有翻譯的模板
            <template id="report_invoice">
                <t t-call="report.html_container">
                    <t t-foreach="docs" t-as="o">
                        <t t-call="report.external_layout">
                            <div class="page">
                                <h2>Report title</h2>
                                <p>This object's name is <span t-field="o.name"/></p>
                            </div>
                        </t>
                    </t>
                </t>
            </template>
            
        @docs 當前報表記錄集
        @doc_ids 報表記錄集的ids列表
        @doc_model 報表錄集對應的模型
        @translate_doc 翻譯報表
        <t t-foreach="doc_ids" t-as="doc_id">
          <t t-raw="translate_doc(doc_id, doc_model, 'partner_id.lang', account.report_invoice_document')"/>
        </t>
        @user 打印報表的人
        @res_company 當前用戶的公司
            
         @調用了report.external_layout 模板 所在的佈局文件在 /addons/report/views/layouts.xml
         @注意translate_doc 中的 purchase.report_purchaseorder_document ,這個要報表視圖id前加模塊名
          這個名稱和模板的id名稱要一致
         @模板名稱 report_purchaseorder_documen  和模板名稱 report_purchaseorder
          這樣在報表定義時 purchase.report_purchaseorder 就可以關聯到定義的模板
         @ 大家可能注意到了o 對於o是代表當前報表模型數據 在/addons/report/models/report.xml
           translate_doc 這個方法
           def translate_doc(self, cr, uid, doc_id, model, lang_field, template, values, context=None):
                ctx = context.copy()
                doc = self.pool[model].browse(cr, uid, doc_id, context=ctx)
                qcontext = values.copy()
                # Do not force-translate if we chose to display the report in a specific lang
                if ctx.get('translatable') is True:
                    qcontext['o'] = doc
                else:
                    # Reach the lang we want to translate the doc into
                    ctx['lang'] = eval('doc.%s' % lang_field, {'doc': doc})
                    qcontext['o'] = self.pool[model].browse(cr, uid, doc_id, context=ctx)
                return self.pool['ir.ui.view'].render(cr, uid, template, qcontext, context=ctx)
            看到o就是報表中的的對象,若選擇多個就是objects ,單個用o
            報表中除了html的佈局,剩下的就是用qweb語言來寫的,和python類似。            
        

    #在報表中呈現數據    
    可用的變量:
      docs 循環打印出一個記錄集
      doc_ids 一個記錄集的ids列表打印出來
      doc_model 調用哪個模型來處理
      time 時間
      user 本次執行報告的用戶
      res_company  當前用戶所在的公司
     
      
      字段值用 t-field 屬性 還可以用其補充屬性 t-field-options
      上一道菜:
       <h2 t-field="o.name"/>
            <p t-field="o.user_id.name"/>
            <ul>
            <t t-foreach="o.message_follower_ids" t-as="f">
                <li>
                    <img t-if="f.image_small"
                         t-att-src="'data:image/png;base64,%s' % f.image_small"
                         style="max-height: 45px;"/>
                    <span t-field="f.name"/>
                </li>
            </t>
        </ul>
        有貨幣字段:
         <span t-field="o.amount"
            t-field-options='{
            "widget": "monetary",
            "display_currency": "o.pricelist_id.currency_id"}'/>

         <div t-field="res_company.partner_id"
            t-field-options='{
            "widget": "contact",
            "fields": ["address", "name", "phone", "fax"],
            "no_marker": true}' />
            
         支持語言翻譯
         <template id="report_todo_task_template">
            <t t-call="report.html_container">
                <t t-foreach="doc_ids" t-as="doc_id">
                <t t-raw="translate_doc(doc_id, doc_model,
                    'user_id.partner_id.lang',
                    'todo_kanban.report_todo_task_doc')"/>
                </t>
            </t>
         </template>
         translate_doc
         
          
            注:col-xs-N  N代表多少列 像bootstrap寫法,一行劃成12列
                <t t-if="f_last"> 循環到了最後
                
                
         #紙張格式

            <record id="report_todo_task_action" model="ir.actions.report.xml">
                <field name="name">To-do Tasks</field>
                <field name="model">todo.task</field>
                <field name="report_type">qweb-html</field>
                <field name="template_name">
                    todo_kanban.report_todo_task_template
                </field>
                <field name="paper_format_id" ref="report.paperformat_euro"/>
            </record>         
            paper_format_id 引用了 report.paperformat_euro 這個格式,這個值,可以在
            設置->技術->報告->紙張格式
            
            定義紙張格式
            <record id="paperformat_frenchcheck" model="report.paperformat">
                <field name="name">French Bank Check</field>
                <field name="default" eval="True"/>
                <field name="format">custom</field>
                <field name="page_height">80</field>
                <field name="page_width">175</field>
                <field name="orientation">Portrait</field>
                <field name="margin_top">3</field>
                <field name="margin_bottom">3</field>
                <field name="margin_left">3</field>
                <field name="margin_right">3</field>
                <field name="header_line" eval="False"/>
                <field name="header_spacing">3</field>
                <field name="dpi">80</field>
            </record>
            
            
            
        #模板加入模塊中(__openerp__.py)
       'data': [
        
        'views/report_purchaseorder.xml',
        'views/report_purchasequotation.xml',
        ],   

        #加入條件碼:
        <img t-att-src="'/report/barcode/QR/%s' % 'My text in qr code'"/>
        <img t-att-src="'/report/barcode/?
            type=%s&value=%s&width=%s&height=%s'%('QR', 'text', 200, 200)"/>
            
        # 報表加入css
        <template id="report_saleorder_style" inherit_id="report.layout">
          <xpath expr="//style" position="after">
            <style type="text/css">
              .example-css-class {
                background-color: red;
              }
            </style>
          </xpath>
        </template>
        
    #自定義報表
      默認有 get_html方法來調用報表傳遞數據,這時,我們只要定義模型時,重寫這個方法就
      可以完成自定義報表輸出
        from openerp import api, models

      class ParticularReport(models.AbstractModel):
        _name = 'report.module.report_name'
        @api.multi
        def render_html(self, data=None):
            report_obj = self.env['report']
            report = report_obj._get_report_from_name('module.report_name')
            docargs = {
                'doc_ids': self._ids,
                'doc_model': report.model,
                'docs': self,
            }
            return report_obj.render('module.report_name', docargs)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章