Browse Source
[12.0][IMP] excel_import_export, excel_import_export_demo
[12.0][IMP] excel_import_export, excel_import_export_demo
Add report action feature and new examples12.0
Kitti U
5 years ago
committed by
OCA-git-bot
26 changed files with 450 additions and 29 deletions
-
1excel_import_export/__init__.py
-
9excel_import_export/__manifest__.py
-
4excel_import_export/controllers/__init__.py
-
53excel_import_export/controllers/main.py
-
1excel_import_export/models/__init__.py
-
42excel_import_export/models/common.py
-
39excel_import_export/models/ir_report.py
-
5excel_import_export/readme/HISTORY.rst
-
20excel_import_export/readme/USAGE.rst
-
88excel_import_export/static/src/js/report/action_manager_report.js
-
11excel_import_export/views/webclient_templates.xml
-
1excel_import_export_demo/__init__.py
-
8excel_import_export_demo/__manifest__.py
-
2excel_import_export_demo/readme/DESCRIPTION.rst
-
5excel_import_export_demo/readme/HISTORY.rst
-
14excel_import_export_demo/readme/USAGE.rst
-
4excel_import_export_demo/report_action/__init__.py
-
4excel_import_export_demo/report_action/partner_list/__init__.py
-
BINexcel_import_export_demo/report_action/partner_list/partner_list.xlsx
-
10excel_import_export_demo/report_action/partner_list/report.xml
-
37excel_import_export_demo/report_action/partner_list/report_partner_list.py
-
43excel_import_export_demo/report_action/partner_list/report_partner_list.xml
-
29excel_import_export_demo/report_action/partner_list/templates.xml
-
13excel_import_export_demo/report_action/sale_order/report.xml
-
BINexcel_import_export_demo/report_action/sale_order/sale_order_form.xlsx
-
36excel_import_export_demo/report_action/sale_order/templates.xml
@ -0,0 +1,4 @@ |
|||
# Copyright 2019 Ecosoft Co., Ltd (http://ecosoft.co.th/) |
|||
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html) |
|||
|
|||
from . import main |
@ -0,0 +1,53 @@ |
|||
# Copyright 2019 Ecosoft Co., Ltd (http://ecosoft.co.th/) |
|||
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html) |
|||
|
|||
import json |
|||
import base64 |
|||
import time |
|||
from odoo.addons.web.controllers import main as report |
|||
from odoo.http import content_disposition, route, request |
|||
from odoo.tools.safe_eval import safe_eval |
|||
|
|||
|
|||
class ReportController(report.ReportController): |
|||
|
|||
@route() |
|||
def report_routes(self, reportname, docids=None, converter=None, **data): |
|||
if converter == 'excel': |
|||
report = request.env['ir.actions.report']._get_report_from_name( |
|||
reportname) |
|||
context = dict(request.env.context) |
|||
if docids: |
|||
docids = [int(i) for i in docids.split(',')] |
|||
if data.get('options'): |
|||
data.update(json.loads(data.pop('options'))) |
|||
if data.get('context'): |
|||
# Ignore 'lang' here, because the context in data is the one |
|||
# from the webclient *but* if the user explicitely wants to |
|||
# change the lang, this mechanism overwrites it. |
|||
data['context'] = json.loads(data['context']) |
|||
if data['context'].get('lang'): |
|||
del data['context']['lang'] |
|||
context.update(data['context']) |
|||
excel = report.with_context(context).render_excel( |
|||
docids, data=data |
|||
)[0] |
|||
excel = base64.decodestring(excel) |
|||
report_name = report.report_file |
|||
if report.print_report_name and not len(docids) > 1: |
|||
obj = request.env[report.model].browse(docids[0]) |
|||
report_name = safe_eval(report.print_report_name, |
|||
{'object': obj, 'time': time}) |
|||
excelhttpheaders = [ |
|||
('Content-Type', 'application/vnd.openxmlformats-' |
|||
'officedocument.spreadsheetml.sheet'), |
|||
('Content-Length', len(excel)), |
|||
( |
|||
'Content-Disposition', |
|||
content_disposition(report_name + '.xlsx') |
|||
) |
|||
] |
|||
return request.make_response(excel, headers=excelhttpheaders) |
|||
return super(ReportController, self).report_routes( |
|||
reportname, docids, converter, **data |
|||
) |
@ -0,0 +1,39 @@ |
|||
# Copyright 2019 Ecosoft Co., Ltd (http://ecosoft.co.th/) |
|||
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html) |
|||
|
|||
from odoo import api, fields, models, _ |
|||
from odoo.exceptions import UserError |
|||
|
|||
|
|||
class ReportAction(models.Model): |
|||
_inherit = "ir.actions.report" |
|||
|
|||
report_type = fields.Selection(selection_add=[("excel", "Excel")]) |
|||
|
|||
@api.model |
|||
def render_excel(self, docids, data): |
|||
if len(docids) != 1: |
|||
raise UserError( |
|||
_('Only one id is allowed for excel_import_export')) |
|||
xlsx_template = self.env['xlsx.template'].search( |
|||
[('fname', '=', self.report_name), ('res_model', '=', self.model)]) |
|||
if not xlsx_template or len(xlsx_template) != 1: |
|||
raise UserError( |
|||
_("Template %s on model %s is not unique!" % |
|||
(self.report_name, self.model))) |
|||
Export = self.env['xlsx.export'] |
|||
return Export.export_xlsx(xlsx_template, self.model, docids[0]) |
|||
|
|||
@api.model |
|||
def _get_report_from_name(self, report_name): |
|||
res = super(ReportAction, self)._get_report_from_name(report_name) |
|||
if res: |
|||
return res |
|||
report_obj = self.env['ir.actions.report'] |
|||
qwebtypes = ['excel'] |
|||
conditions = [ |
|||
('report_type', 'in', qwebtypes), |
|||
('report_name', '=', report_name), |
|||
] |
|||
context = self.env['res.users'].context_get() |
|||
return report_obj.with_context(context).search(conditions, limit=1) |
@ -0,0 +1,88 @@ |
|||
// Copyright 2019 Ecosoft Co., Ltd.
|
|||
// License AGPL-3.0 or later (https://www.gnuorg/licenses/agpl.html).
|
|||
odoo.define("excel_import_export.report", function (require) { |
|||
"use strict"; |
|||
|
|||
var core = require("web.core"); |
|||
var ActionManager = require("web.ActionManager"); |
|||
var crash_manager = require("web.crash_manager"); |
|||
var framework = require("web.framework"); |
|||
var session = require("web.session"); |
|||
var _t = core._t; |
|||
|
|||
ActionManager.include({ |
|||
|
|||
_downloadReportExcel: function (url, actions) { |
|||
framework.blockUI(); |
|||
var def = $.Deferred(); |
|||
var type = "excel"; |
|||
var cloned_action = _.clone(actions); |
|||
|
|||
if (_.isUndefined(cloned_action.data) || |
|||
_.isNull(cloned_action.data) || |
|||
(_.isObject(cloned_action.data) && _.isEmpty(cloned_action.data))) |
|||
{ |
|||
if (cloned_action.context.active_ids) { |
|||
url += "/" + cloned_action.context.active_ids.join(','); |
|||
} |
|||
} else { |
|||
url += "?options=" + encodeURIComponent(JSON.stringify(cloned_action.data)); |
|||
url += "&context=" + encodeURIComponent(JSON.stringify(cloned_action.context)); |
|||
} |
|||
|
|||
var blocked = !session.get_file({ |
|||
url: url, |
|||
data: { |
|||
data: JSON.stringify([url, type]), |
|||
}, |
|||
success: def.resolve.bind(def), |
|||
error: function () { |
|||
crash_manager.rpc_error.apply(crash_manager, arguments); |
|||
def.reject(); |
|||
}, |
|||
complete: framework.unblockUI, |
|||
}); |
|||
if (blocked) { |
|||
// AAB: this check should be done in get_file service directly,
|
|||
// should not be the concern of the caller (and that way, get_file
|
|||
// could return a deferred)
|
|||
var message = _t('A popup window with your report was blocked. You ' + |
|||
'may need to change your browser settings to allow ' + |
|||
'popup windows for this page.'); |
|||
this.do_warn(_t('Warning'), message, true); |
|||
} |
|||
return def; |
|||
}, |
|||
|
|||
_triggerDownload: function (action, options, type) { |
|||
var self = this; |
|||
var reportUrls = this._makeReportUrls(action); |
|||
if (type === "excel") { |
|||
return this._downloadReportExcel(reportUrls[type], action).then(function () { |
|||
if (action.close_on_report_download) { |
|||
var closeAction = {type: 'ir.actions.act_window_close'}; |
|||
return self.doAction(closeAction, _.pick(options, 'on_close')); |
|||
} else { |
|||
return options.on_close(); |
|||
} |
|||
}); |
|||
} |
|||
return this._super.apply(this, arguments); |
|||
}, |
|||
|
|||
_makeReportUrls: function (action) { |
|||
var reportUrls = this._super.apply(this, arguments); |
|||
reportUrls.excel = '/report/excel/' + action.report_name; |
|||
return reportUrls; |
|||
}, |
|||
|
|||
_executeReportAction: function (action, options) { |
|||
var self = this; |
|||
if (action.report_type === 'excel') { |
|||
return self._triggerDownload(action, options, 'excel'); |
|||
} |
|||
return this._super.apply(this, arguments); |
|||
} |
|||
}); |
|||
|
|||
}); |
@ -0,0 +1,11 @@ |
|||
<?xml version="1.0" encoding="UTF-8" ?> |
|||
<!-- |
|||
Copyright 2019 Ecosoft Co., Ltd. |
|||
License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html).--> |
|||
<odoo> |
|||
<template id="assets_backend" inherit_id="web.assets_backend"> |
|||
<xpath expr="." position="inside"> |
|||
<script type="text/javascript" src="/excel_import_export/static/src/js/report/action_manager_report.js"/> |
|||
</xpath> |
|||
</template> |
|||
</odoo> |
@ -1,3 +1,8 @@ |
|||
12.0.1.0.0 (2019-08-09) |
|||
~~~~~~~~~~~~~~~~~~~~~~~ |
|||
|
|||
* Add 2 new examples using report action, 1) sale_order 2) partner_list |
|||
|
|||
12.0.1.0.0 (2019-02-24) |
|||
~~~~~~~~~~~~~~~~~~~~~~~ |
|||
|
|||
|
@ -1,11 +1,19 @@ |
|||
**Use Case 1:** Export/Import Excel on existing document |
|||
**Example 1:** Export/Import Excel on existing document |
|||
|
|||
To test this use case, go to any Sales Order and use Export Excel or Import Excel in action menu. |
|||
|
|||
**Use Case 2:** Import Excel Files |
|||
**Example 2:** Import Excel Files |
|||
|
|||
To test this use case, go to Settings > Excel Import/Export > Sample Import Sales Order |
|||
|
|||
**Use Case 3:** Create Excel Report |
|||
**Example 3:** Create Excel Report |
|||
|
|||
To test this use case, go to Settings > Excel Import/Export > Sample Sales Report |
|||
|
|||
**Example 4:** Printout Excel on existing document, using report action |
|||
|
|||
To test this use case, go to any Sales Order and click print "Quotation / Order (.xlsx)". |
|||
|
|||
**Example 5:** Run Partner List Report, using report action |
|||
|
|||
To test this use case, go to menu Sales > Reporting > Partner List Report |
@ -0,0 +1,4 @@ |
|||
# Copyright 2019 Ecosoft Co., Ltd (http://ecosoft.co.th/) |
|||
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html) |
|||
|
|||
from . import partner_list |
@ -0,0 +1,4 @@ |
|||
# Copyright 2019 Ecosoft Co., Ltd (http://ecosoft.co.th/) |
|||
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html) |
|||
|
|||
from . import report_partner_list |
@ -0,0 +1,10 @@ |
|||
<?xml version="1.0" encoding="UTF-8" ?> |
|||
<odoo> |
|||
<report id='action_report_partner_excel' |
|||
string='Partner List (.xlsx)' |
|||
model='report.partner.list' |
|||
name='partner_list.xlsx' |
|||
file='partner_list' |
|||
report_type='excel' |
|||
/> |
|||
</odoo> |
@ -0,0 +1,37 @@ |
|||
# Copyright 2019 Ecosoft Co., Ltd (http://ecosoft.co.th/) |
|||
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html) |
|||
|
|||
from odoo import models, fields, api |
|||
|
|||
|
|||
class ReportPartnerList(models.TransientModel): |
|||
_name = 'report.partner.list' |
|||
_description = 'Wizard for report.partner.list' |
|||
|
|||
partner_ids = fields.Many2many( |
|||
comodel_name='res.partner', |
|||
) |
|||
supplier = fields.Boolean( |
|||
default=True, |
|||
) |
|||
customer = fields.Boolean( |
|||
default=True, |
|||
) |
|||
results = fields.Many2many( |
|||
'res.partner', |
|||
string='Results', |
|||
compute='_compute_results', |
|||
help='Use compute fields, so there is nothing store in database', |
|||
) |
|||
|
|||
@api.multi |
|||
def _compute_results(self): |
|||
""" On the wizard, result will be computed and added to results line |
|||
before export to excel by report_excel action |
|||
""" |
|||
self.ensure_one() |
|||
domain = ['|', ('supplier', '=', self.supplier), |
|||
('customer', '=', self.customer)] |
|||
if self.partner_ids: |
|||
domain.append(('id', 'in', self.partner_ids.ids)) |
|||
self.results = self.env['res.partner'].search(domain, order='id') |
@ -0,0 +1,43 @@ |
|||
<?xml version="1.0" encoding="UTF-8" ?> |
|||
<odoo> |
|||
|
|||
<record id="partner_list_wizard" model="ir.ui.view"> |
|||
<field name="name">partner.list.wizard</field> |
|||
<field name="model">report.partner.list</field> |
|||
<field name="arch" type="xml"> |
|||
<form> |
|||
<group> |
|||
<group> |
|||
<field name="partner_ids" widget="many2many_tags"/> |
|||
</group> |
|||
<group> |
|||
<field name="customer"/> |
|||
<field name="supplier"/> |
|||
</group> |
|||
</group> |
|||
<footer> |
|||
<button name='%(excel_import_export_demo.action_report_partner_excel)d' |
|||
type='action' string='Execute' |
|||
class='oe_highlight'/> |
|||
<button special='cancel' |
|||
string='Cancel'/> |
|||
</footer> |
|||
</form> |
|||
</field> |
|||
</record> |
|||
|
|||
<record id='action_report_partner_list' model='ir.actions.act_window'> |
|||
<field name='name'>Partner List Report</field> |
|||
<field name='res_model'>report.partner.list</field> |
|||
<field name='view_type'>form</field> |
|||
<field name='view_mode'>form</field> |
|||
<field name='target'>new</field> |
|||
</record> |
|||
|
|||
<menuitem id="menu_report_partner_list" |
|||
parent="sale.menu_sale_report" |
|||
action="action_report_partner_list" |
|||
name="Partner List Report" |
|||
/> |
|||
|
|||
</odoo> |
@ -0,0 +1,29 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
<odoo> |
|||
|
|||
<record id="partner_list_xlsx_template" model="xlsx.template"> |
|||
<field name="res_model">report.partner.list</field> |
|||
<field name="fname">partner_list.xlsx</field> |
|||
<field name="name">Partner List Report Template</field> |
|||
<field name="description">Sample Partner List Report Template for testing</field> |
|||
<field name="input_instruction"> |
|||
{ |
|||
'__EXPORT__': { |
|||
1: { |
|||
'results': { |
|||
'A4': 'id', |
|||
'B4': 'name${value or ""}#{style=text}', |
|||
'C4': 'phone${value or ""}#{style=text}', |
|||
'D4': 'email${value or ""}#{style=text}', |
|||
} |
|||
} |
|||
}, |
|||
} |
|||
</field> |
|||
</record> |
|||
|
|||
<function model="xlsx.template" name="load_xlsx_template"> |
|||
<value eval="[ref('partner_list_xlsx_template')]"/> |
|||
</function> |
|||
|
|||
</odoo> |
@ -0,0 +1,13 @@ |
|||
<?xml version="1.0" encoding="UTF-8" ?> |
|||
<odoo> |
|||
|
|||
<report id='action_report_saleorder_excel' |
|||
string='Quotation / Order (.xlsx)' |
|||
model='sale.order' |
|||
name='sale_order_form.xlsx' |
|||
file='sale_order' |
|||
print_report_name="(object.state in ('draft', 'sent') and 'Quotation - %s' % (object.name)) or 'Order - %s' % (object.name)" |
|||
report_type='excel' |
|||
/> |
|||
|
|||
</odoo> |
@ -0,0 +1,36 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
<odoo> |
|||
|
|||
<record id="sale_order_excel_template" model="xlsx.template"> |
|||
<field name="res_model">sale.order</field> |
|||
<field name="fname">sale_order_form.xlsx</field> |
|||
<field name="name">Sale Order Template</field> |
|||
<field name="description">Sample Sales Order Template for testing</field> |
|||
<field name="input_instruction"> |
|||
{ |
|||
'__EXPORT__': { |
|||
'sale_order': { |
|||
'_HEAD_': { |
|||
'B2': 'partner_id.display_name${value or ""}#{align=left;style=text}', |
|||
'B3': 'name${value or ""}#{align=left;style=text}', |
|||
}, |
|||
'order_line': { |
|||
'A6': 'product_id.display_name${value or ""}#{style=text}', |
|||
'B6': 'name${value or ""}#{style=text}', |
|||
'C6': 'product_uom_qty${value or 0}#{style=number}', |
|||
'D6': 'product_uom.name${value or ""}#{style=text}', |
|||
'E6': 'price_unit${value or 0}#{style=number}', |
|||
'F6': 'tax_id${value and ",".join([x.display_name for x in value]) or ""}', |
|||
'G6': 'price_subtotal${value or 0}#{style=number}@{sum}', |
|||
} |
|||
} |
|||
}, |
|||
} |
|||
</field> |
|||
</record> |
|||
|
|||
<function model="xlsx.template" name="load_xlsx_template"> |
|||
<value eval="[ref('sale_order_excel_template')]"/> |
|||
</function> |
|||
|
|||
</odoo> |
Write
Preview
Loading…
Cancel
Save
Reference in new issue