Jelajahi Sumber

Report mrp pdf y xls

Sebas 5 tahun lalu
melakukan
e2a9a2c486
14 mengubah file dengan 565 tambahan dan 0 penghapusan
  1. 78 0
      README.rst
  2. 24 0
      __init__.py
  3. TEMPAT SAMPAH
      __init__.pyc
  4. 32 0
      __openerp__.py
  5. 14 0
      i18n/report_xls.pot
  6. 29 0
      ir_report.py
  7. TEMPAT SAMPAH
      ir_report.pyc
  8. 255 0
      report_xls.py
  9. TEMPAT SAMPAH
      report_xls.pyc
  10. TEMPAT SAMPAH
      static/description/help.png
  11. TEMPAT SAMPAH
      static/description/icon.png
  12. 84 0
      static/description/index.html
  13. TEMPAT SAMPAH
      static/description/open_receivables.png
  14. 49 0
      utils.py

+ 78 - 0
README.rst

@@ -0,0 +1,78 @@
+.. image:: https://img.shields.io/badge/licence-AGPL--3-blue.svg
+   :target: http://www.gnu.org/licenses/agpl-3.0-standalone.html
+   :alt: License: AGPL-3
+
+===================
+Excel report engine
+===================
+
+This module adds Excel export capabilities to the standard odoo reporting
+engine.
+
+Usage
+=====
+
+In order to create an Excel report you can:
+
+- define a report of type 'xls'
+- pass ``{'xls_export': 1}`` via the context to the report create method
+
+The ``report_xls`` class contains a number of attributes and methods to
+facilitate the creation XLS reports in OpenERP.
+
+* cell types
+
+  Supported cell types : text, number, boolean, date.
+
+* cell styles
+
+  The predefined cell style definitions result in a consistent
+  look and feel of the OpenERP Excel reports.
+
+* cell formulas
+
+  Cell formulas can be easily added with the help of the ``rowcol_to_cell()``
+  function which you can import from the ``utils.py`` module.
+
+* Excel templates
+
+  It is possible to define Excel templates which can be adapted
+  by 'inherited' modules.
+  Download the ``account_move_line_report_xls`` module
+  from http://apps.odoo.com as example.
+
+* XLS with multiple sheets
+
+  Download the ``account_journal_report_xls`` module
+  from http://apps.odoo.com as example.
+
+Bug Tracker
+===========
+
+Bugs are tracked on `GitHub Issues
+<https://github.com/OCA/reporting-engine/issues>`_. In case of trouble, please
+check there if your issue has already been reported. If you spotted it first,
+help us smashing it by providing a detailed and welcomed feedback.
+
+Credits
+=======
+
+Contributors
+------------
+
+* Noviat
+
+Maintainer
+----------
+
+.. image:: https://odoo-community.org/logo.png
+   :alt: Odoo Community Association
+   :target: https://odoo-community.org
+
+This module is maintained by the OCA.
+
+OCA, or the Odoo Community Association, is a nonprofit organization whose
+mission is to support the collaborative development of Odoo features and
+promote its widespread use.
+
+To contribute to this module, please visit https://odoo-community.org.

+ 24 - 0
__init__.py

@@ -0,0 +1,24 @@
+# -*- coding: utf-8 -*-
+##############################################################################
+#
+#    OpenERP, Open Source Management Solution
+#
+#    Copyright (c) 2014 Noviat nv/sa (www.noviat.com). All rights reserved.
+#
+#    This program is free software: you can redistribute it and/or modify
+#    it under the terms of the GNU Affero General Public License as
+#    published by the Free Software Foundation, either version 3 of the
+#    License, or (at your option) any later version.
+#
+#    This program is distributed in the hope that it will be useful,
+#    but WITHOUT ANY WARRANTY; without even the implied warranty of
+#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+#    GNU Affero General Public License for more details.
+#
+#    You should have received a copy of the GNU Affero General Public License
+#    along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+##############################################################################
+
+from . import ir_report
+from . import report_xls

TEMPAT SAMPAH
__init__.pyc


+ 32 - 0
__openerp__.py

@@ -0,0 +1,32 @@
+# -*- coding: utf-8 -*-
+##############################################################################
+#
+#    OpenERP, Open Source Management Solution
+#
+#    Copyright (c) 2014 Noviat nv/sa (www.noviat.com). All rights reserved.
+#
+#    This program is free software: you can redistribute it and/or modify
+#    it under the terms of the GNU Affero General Public License as
+#    published by the Free Software Foundation, either version 3 of the
+#    License, or (at your option) any later version.
+#
+#    This program is distributed in the hope that it will be useful,
+#    but WITHOUT ANY WARRANTY; without even the implied warranty of
+#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+#    GNU Affero General Public License for more details.
+#
+#    You should have received a copy of the GNU Affero General Public License
+#    along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+##############################################################################
+{
+    'name': 'Excel report engine',
+    'version': '8.0.0.6.1',
+    'license': 'AGPL-3',
+    'author': "Noviat,Odoo Community Association (OCA)",
+    'website': 'http://www.noviat.com',
+    'category': 'Reporting',
+    'depends': ['base'],
+    'external_dependencies': {'python': ['xlwt']},
+    'installable': True,
+}

+ 14 - 0
i18n/report_xls.pot

@@ -0,0 +1,14 @@
+# Translation of Odoo Server.
+# This file contains the translation of the following modules:
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: Odoo Server 8.0\n"
+"Report-Msgid-Bugs-To: \n"
+"Last-Translator: <>\n"
+"Language-Team: \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: \n"
+"Plural-Forms: \n"
+

+ 29 - 0
ir_report.py

@@ -0,0 +1,29 @@
+# -*- coding: utf-8 -*-
+##############################################################################
+#
+#    OpenERP, Open Source Management Solution
+#
+#    Copyright (c) 2014 Noviat nv/sa (www.noviat.com). All rights reserved.
+#
+#    This program is free software: you can redistribute it and/or modify
+#    it under the terms of the GNU Affero General Public License as
+#    published by the Free Software Foundation, either version 3 of the
+#    License, or (at your option) any later version.
+#
+#    This program is distributed in the hope that it will be useful,
+#    but WITHOUT ANY WARRANTY; without even the implied warranty of
+#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+#    GNU Affero General Public License for more details.
+#
+#    You should have received a copy of the GNU Affero General Public License
+#    along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+##############################################################################
+
+from openerp import models, fields
+
+
+class IrActionsReportXml(models.Model):
+    _inherit = 'ir.actions.report.xml'
+
+    report_type = fields.Selection(selection_add=[('xls', 'XLS')])

TEMPAT SAMPAH
ir_report.pyc


+ 255 - 0
report_xls.py

@@ -0,0 +1,255 @@
+# -*- coding: utf-8 -*-
+##############################################################################
+#
+#    OpenERP, Open Source Management Solution
+#
+#    Copyright (c) 2014 Noviat nv/sa (www.noviat.com). All rights reserved.
+#
+#    This program is free software: you can redistribute it and/or modify
+#    it under the terms of the GNU Affero General Public License as
+#    published by the Free Software Foundation, either version 3 of the
+#    License, or (at your option) any later version.
+#
+#    This program is distributed in the hope that it will be useful,
+#    but WITHOUT ANY WARRANTY; without even the implied warranty of
+#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+#    GNU Affero General Public License for more details.
+#
+#    You should have received a copy of the GNU Affero General Public License
+#    along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+##############################################################################
+
+import cStringIO
+from datetime import datetime
+from openerp.osv.fields import datetime as datetime_field
+from openerp.tools import DEFAULT_SERVER_DATETIME_FORMAT
+import inspect
+from types import CodeType
+from openerp.report.report_sxw import report_sxw
+from openerp.modules.registry import RegistryManager
+import logging
+
+_logger = logging.getLogger(__name__)
+
+xls_types_default = {
+    'bool': False,
+    'date': None,
+    'text': '',
+    'number': 0,
+}
+
+try:
+    import xlwt
+    from xlwt.Style import default_style
+
+    xls_types = {
+        'bool': xlwt.Row.set_cell_boolean,
+        'date': xlwt.Row.set_cell_date,
+        'text': xlwt.Row.set_cell_text,
+        'number': xlwt.Row.set_cell_number,
+    }
+except ImportError:  # pragma: no cover
+    _logger.debug("Cannot import xlwt. This module will not be functional.")
+    xls_types = xls_types_default
+    default_style = None
+
+
+class AttrDict(dict):
+    def __init__(self, *args, **kwargs):
+        super(AttrDict, self).__init__(*args, **kwargs)
+        self.__dict__ = self
+
+
+class report_xls(report_sxw):
+    # TO DO: move parameters infra to configurable data
+    # header/footer
+    hf_params = {
+        'font_size': 8,
+        'font_style': 'I',  # B: Bold, I:  Italic, U: Underline
+    }
+
+    # styles
+    _pfc = '26'  # default pattern fore_color
+    _bc = '22'   # borders color
+    decimal_format = '#,##0.00'
+    date_format = 'YYYY-MM-DD'
+    xls_styles = {
+        'xls_title': 'font: bold true, height 240;',
+        'bold': 'font: bold true;',
+        'underline': 'font: underline true;',
+        'italic': 'font: italic true;',
+        'fill': 'pattern: pattern solid, fore_color %s;' % _pfc,
+        'fill_blue': 'pattern: pattern solid, fore_color 27;',
+        'fill_grey': 'pattern: pattern solid, fore_color 22;',
+        'borders_all':
+            'borders: '
+            'left thin, right thin, top thin, bottom thin, '
+            'left_colour %s, right_colour %s, '
+            'top_colour %s, bottom_colour %s;'
+            % (_bc, _bc, _bc, _bc),
+        'left': 'align: horz left;',
+        'center': 'align: horz center;',
+        'right': 'align: horz right;',
+        'wrap': 'align: wrap true;',
+        'top': 'align: vert top;',
+        'bottom': 'align: vert bottom;',
+    }
+    # TO DO: move parameters supra to configurable data
+
+    def create(self, cr, uid, ids, data, context=None):
+        self.pool = RegistryManager.get(cr.dbname)
+        self.cr = cr
+        self.uid = uid
+        report_obj = self.pool.get('ir.actions.report.xml')
+        report_ids = report_obj.search(
+            cr, uid, [('report_name', '=', self.name[7:])], context=context)
+        if report_ids:
+            report_xml = report_obj.browse(
+                cr, uid, report_ids[0], context=context)
+            self.title = report_xml.name
+            if report_xml.report_type == 'xls':
+                return self.create_source_xls(cr, uid, ids, data, context)
+        elif context.get('xls_export'):
+            # use model from 'data' when no ir.actions.report.xml entry
+            self.table = data.get('model') or self.table
+            return self.create_source_xls(cr, uid, ids, data, context)
+        return super(report_xls, self).create(cr, uid, ids, data, context)
+
+    def create_source_xls(self, cr, uid, ids, data, context=None):
+        if not context:
+            context = {}
+        parser_instance = self.parser(cr, uid, self.name2, context)
+        self.parser_instance = parser_instance
+        self.context = context
+        objs = self.getObjects(cr, uid, ids, context)
+        parser_instance.set_context(objs, data, ids, 'xls')
+        objs = parser_instance.localcontext['objects']
+        n = cStringIO.StringIO()
+        # prevent style make error
+        # http://stackoverflow.com/questions/17130516/xlwt-set-style-making-error-more-than-4094-xfs-styles
+        wb = xlwt.Workbook(encoding='utf-8', style_compression=2)
+        _p = AttrDict(parser_instance.localcontext)
+        _xs = self.xls_styles
+        self.xls_headers = {
+            'standard': '',
+        }
+        report_date = datetime_field.context_timestamp(
+            cr, uid, datetime.now(), context)
+        report_date = report_date.strftime(DEFAULT_SERVER_DATETIME_FORMAT)
+        self.xls_footers = {
+            'standard': (
+                '&L&%(font_size)s&%(font_style)s' + report_date +
+                '&R&%(font_size)s&%(font_style)s&P / &N'
+                ) % self.hf_params,
+        }
+        self.generate_xls_report(_p, _xs, data, objs, wb)
+        wb.save(n)
+        n.seek(0)
+        return (n.read(), 'xls')
+
+    def render(self, wanted, col_specs, rowtype, render_space='empty'):
+        """
+        returns 'evaluated' col_specs
+
+        Input:
+        - wanted: element from the wanted_list
+        - col_specs : cf. specs[1:] documented in xls_row_template method
+        - rowtype : 'header' or 'data'
+        - render_space : type dict, (caller_space + localcontext)
+                         if not specified
+        """
+        if render_space == 'empty':
+            render_space = {}
+            caller_space = inspect.currentframe().f_back.f_back.f_locals
+            localcontext = self.parser_instance.localcontext
+            render_space.update(caller_space)
+            render_space.update(localcontext)
+        row = col_specs[wanted][rowtype][:]
+        for i in range(len(row)):
+            if isinstance(row[i], CodeType):
+                # TODO Use safe_eval or document why not and remove pylint hack
+                row[i] = eval(row[i], render_space)  # pylint: disable=W0123
+        row.insert(0, wanted)
+        return row
+
+    def generate_xls_report(self, parser, xls_styles, data, objects, wb):
+        """ override this method to create your excel file """
+        raise NotImplementedError()
+
+    def xls_row_template(self, specs, wanted_list):
+        """
+        Returns a row template.
+
+        Input :
+        - 'wanted_list': list of Columns that will be returned in the
+                         row_template
+        - 'specs': list with Column Characteristics
+            0: Column Name (from wanted_list)
+            1: Column Colspan
+            2: Column Size (unit = the width of the character ’0′
+                            as it appears in the sheet’s default font)
+            3: Column Type
+            4: Column Data
+            5: Column Formula (or 'None' for Data)
+            6: Column Style
+        """
+        r = []
+        col = 0
+        for w in wanted_list:
+            found = False
+            for s in specs:
+                if s[0] == w:
+                    found = True
+                    s_len = len(s)
+                    c = list(s[:5])
+                    # set write_cell_func or formula
+                    if s_len > 5 and s[5] is not None:
+                        c.append({'formula': s[5]})
+                    else:
+                        c.append({
+                            'write_cell_func': xls_types[c[3]]})
+                    # Set custom cell style
+                    if s_len > 6 and s[6] is not None:
+                        c.append(s[6])
+                    else:
+                        c.append(None)
+                    # Set cell formula
+                    if s_len > 7 and s[7] is not None:
+                        c.append(s[7])
+                    else:
+                        c.append(None)
+                    r.append((col, c[1], c))
+                    col += c[1]
+                    break
+            if not found:
+                _logger.warn("report_xls.xls_row_template, "
+                             "column '%s' not found in specs", w)
+        return r
+
+    def xls_write_row(self, ws, row_pos, row_data,
+                      row_style=default_style, set_column_size=False):
+        r = ws.row(row_pos)
+        for col, size, spec in row_data:
+            data = spec[4]
+            formula = spec[5].get('formula') and \
+                xlwt.Formula(spec[5]['formula']) or None
+            style = spec[6] and spec[6] or row_style
+            if not data:
+                # if no data, use default values
+                data = xls_types_default[spec[3]]
+            if size != 1:
+                if formula:
+                    ws.write_merge(
+                        row_pos, row_pos, col, col + size - 1, data, style)
+                else:
+                    ws.write_merge(
+                        row_pos, row_pos, col, col + size - 1, data, style)
+            else:
+                if formula:
+                    ws.write(row_pos, col, formula, style)
+                else:
+                    spec[5]['write_cell_func'](r, col, data, style)
+            if set_column_size:
+                ws.col(col).width = spec[2] * 256
+        return row_pos + 1

TEMPAT SAMPAH
report_xls.pyc


TEMPAT SAMPAH
static/description/help.png


TEMPAT SAMPAH
static/description/icon.png


+ 84 - 0
static/description/index.html

@@ -0,0 +1,84 @@
+<section class="oe_container">
+    <div class="oe_row oe_spaced">
+        <div class="oe_span12">
+            <h2 class="oe_slogan">Excel report engine</h2>
+        </div>
+        <div class="oe_span6">
+            <div class="oe_demo oe_picture oe_screenshot">
+                <img src="open_receivables.png">
+            </div>
+        </div>
+        <div class="oe_span6">
+            <p class="oe_mt32">
+              <br><br>This module adds Excel export capabilities to the standard odoo reporting engine.
+            </p>
+        </div>
+    </div>
+</section>
+
+<section class="oe_spaced oe_container oe_dark">
+    <div class="oe_row">
+        <h2 class="oe_slogan">Report development</h2>
+        <p class="oe_mt32">
+          In order to create an Excel report you can
+          <ul>
+            <li>define a report of type 'xls'</li>
+            <li>pass <code>{'xls_export': 1}</code> via the context to the report create method</li>
+          </ul>
+        </p>
+        <p class="oe_mt32">
+           The <code>report_xls</code> class contains a number of attributes and methods to facilitate the creation XLS reports in odoo.
+          <ul>
+            <li>
+              cell types
+              <br>Supported cell types : text, number, boolean, date.
+            </li>
+          </ul>
+          <ul>
+            <li>
+              cell styles
+              <br>The predefined cell style definitions result in a consistent look and feel of the odoo Excel reports.
+            </li>
+          </ul>
+          <ul>
+            <li>
+              cell formulas
+              <br>Cell formulas can be easily added with the help of the <code>rowcol_to_cell()</code> function which you can import from the <code>utils.py</code> module.
+            </li>
+          </ul>
+          <ul>
+            <li>
+              Excel templates
+              <br>It is possible to define Excel templates which can be adapted by 'inherited' modules.
+              <br>Download the <b>account_move_line_report_xls</b> module from <a href="http://apps.odoo.com">http://apps.odoo.com</a> as example.
+            </li>
+          </ul>
+          <ul>
+            <li>
+              XLS with multiple sheets
+              <br>Download the <b>account_journal_report_xls</b> module from <a href="http://apps.odoo.com">http://apps.odoo.com</a> as example.
+            </li>
+          </ul>
+        </p>
+    </div>
+</section>
+
+<section class="oe_container">
+    <div class="oe_row oe_spaced">
+        <div class="oe_span12">
+            <h2 class="oe_slogan">Development assistance</h2>
+        </div>
+        <div class="oe_span6">
+            <br>
+            <div class="oe_picture">
+                <center><img src="help.png" height="150"></center>
+            </div>
+        </div>
+        <div class="oe_span6">
+            <p class="oe_mt32">
+              <br><br>Contact <a href="mailto:info@noviat.com">info@noviat.com</a> for help with the development of Excel reports in odoo.
+            </p>
+        </div>
+    </div>
+</section>
+

TEMPAT SAMPAH
static/description/open_receivables.png


+ 49 - 0
utils.py

@@ -0,0 +1,49 @@
+# -*- coding: utf-8 -*-
+##############################################################################
+#
+#    OpenERP, Open Source Management Solution
+#
+#    Copyright (c) 2014 Noviat nv/sa (www.noviat.com). All rights reserved.
+#
+#    This program is free software: you can redistribute it and/or modify
+#    it under the terms of the GNU Affero General Public License as
+#    published by the Free Software Foundation, either version 3 of the
+#    License, or (at your option) any later version.
+#
+#    This program is distributed in the hope that it will be useful,
+#    but WITHOUT ANY WARRANTY; without even the implied warranty of
+#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+#    GNU Affero General Public License for more details.
+#
+#    You should have received a copy of the GNU Affero General Public License
+#    along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+##############################################################################
+
+
+def _render(code):
+    return compile(code, '<string>', 'eval')
+
+
+def rowcol_to_cell(row, col, row_abs=False, col_abs=False):
+    # Code based upon utils from xlwt distribution
+    """
+    Convert numeric row/col notation to an Excel cell
+    reference string in A1 notation.
+    """
+    d = col // 26
+    m = col % 26
+    chr1 = ""    # Most significant character in AA1
+    if row_abs:
+        row_abs = '$'
+    else:
+        row_abs = ''
+    if col_abs:
+        col_abs = '$'
+    else:
+        col_abs = ''
+    if d > 0:
+        chr1 = chr(ord('A') + d - 1)
+    chr2 = chr(ord('A') + m)
+    # Zero index to 1-index
+    return col_abs + chr1 + chr2 + row_abs + str(row + 1)