[IMP] sql_export_excel: black, isort, prettier
parent
0937bf7265
commit
3b578f7a4b
|
@ -2,23 +2,23 @@
|
|||
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html).
|
||||
|
||||
{
|
||||
'name': 'SQL Export Excel',
|
||||
'version': '12.0.1.1.0',
|
||||
'author': 'Akretion,Odoo Community Association (OCA)',
|
||||
'website': 'http://github/oca/server-tools',
|
||||
'license': 'AGPL-3',
|
||||
'category': 'Generic Modules/Others',
|
||||
'summary': 'Allow to export a sql query to an excel file.',
|
||||
'depends': [
|
||||
'sql_export',
|
||||
"name": "SQL Export Excel",
|
||||
"version": "12.0.1.1.0",
|
||||
"author": "Akretion,Odoo Community Association (OCA)",
|
||||
"website": "https://github.com/OCA/server-tools",
|
||||
"license": "AGPL-3",
|
||||
"category": "Generic Modules/Others",
|
||||
"summary": "Allow to export a sql query to an excel file.",
|
||||
"depends": [
|
||||
"sql_export",
|
||||
],
|
||||
'external_dependencies': {
|
||||
'python': [
|
||||
'openpyxl',
|
||||
"external_dependencies": {
|
||||
"python": [
|
||||
"openpyxl",
|
||||
],
|
||||
},
|
||||
'data': [
|
||||
'views/sql_export_view.xml',
|
||||
"data": [
|
||||
"views/sql_export_view.xml",
|
||||
],
|
||||
'installable': True,
|
||||
}
|
||||
"installable": True,
|
||||
}
|
||||
|
|
|
@ -1,71 +1,79 @@
|
|||
# Copyright 2019 Akretion
|
||||
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html).
|
||||
|
||||
from odoo import api, exceptions, fields, models, _
|
||||
from io import BytesIO
|
||||
import logging
|
||||
import base64
|
||||
import logging
|
||||
from io import BytesIO
|
||||
|
||||
from odoo import _, api, exceptions, fields, models
|
||||
|
||||
_logger = logging.getLogger(__name__)
|
||||
|
||||
try:
|
||||
import openpyxl
|
||||
except ImportError:
|
||||
_logger.debug('Can not import openpyxl')
|
||||
_logger.debug("Can not import openpyxl")
|
||||
|
||||
|
||||
class SqlExport(models.Model):
|
||||
_inherit = 'sql.export'
|
||||
_inherit = "sql.export"
|
||||
|
||||
file_format = fields.Selection(
|
||||
selection_add=[('excel', 'Excel')])
|
||||
file_format = fields.Selection(selection_add=[("excel", "Excel")])
|
||||
header = fields.Boolean(
|
||||
default=True,
|
||||
help="Indicate if the header should be exported to the file.")
|
||||
default=True, help="Indicate if the header should be exported to the file."
|
||||
)
|
||||
attachment_id = fields.Many2one(
|
||||
'ir.attachment', string='Excel Template',
|
||||
"ir.attachment",
|
||||
string="Excel Template",
|
||||
help="If you configure an excel file (in xlsx format) here, the "
|
||||
"result of the query will be injected in it.\nIt is usefull to "
|
||||
"feed data in a excel file pre-configured with calculation")
|
||||
"feed data in a excel file pre-configured with calculation",
|
||||
)
|
||||
sheet_position = fields.Integer(
|
||||
default=1,
|
||||
help="Indicate the sheet's position of the excel template where the "
|
||||
"result of the sql query should be injected.")
|
||||
"result of the sql query should be injected.",
|
||||
)
|
||||
row_position = fields.Integer(
|
||||
default=1,
|
||||
help="Indicate from which row the result of the query should be "
|
||||
"injected.")
|
||||
help="Indicate from which row the result of the query should be " "injected.",
|
||||
)
|
||||
col_position = fields.Integer(
|
||||
string="Column Position",
|
||||
default=1,
|
||||
help="Indicate from which column the result of the query should be "
|
||||
"injected.")
|
||||
"injected.",
|
||||
)
|
||||
|
||||
@api.constrains('sheet_position')
|
||||
@api.constrains("sheet_position")
|
||||
def check_sheet_position(self):
|
||||
for export in self:
|
||||
if export.sheet_position < 1:
|
||||
raise exceptions.ValidationError(
|
||||
_("The sheet position can't be less than 1."))
|
||||
_("The sheet position can't be less than 1.")
|
||||
)
|
||||
|
||||
@api.constrains('row_position')
|
||||
@api.constrains("row_position")
|
||||
def check_row_position(self):
|
||||
for export in self:
|
||||
if export.row_position < 1:
|
||||
raise exceptions.ValidationError(
|
||||
_("The row position can't be less than 1."))
|
||||
_("The row position can't be less than 1.")
|
||||
)
|
||||
|
||||
@api.constrains('col_position')
|
||||
@api.constrains("col_position")
|
||||
def check_column_position(self):
|
||||
for export in self:
|
||||
if export.col_position < 1:
|
||||
raise exceptions.ValidationError(
|
||||
_("The column position can't be less than 1."))
|
||||
_("The column position can't be less than 1.")
|
||||
)
|
||||
|
||||
@api.multi
|
||||
def _get_file_extension(self):
|
||||
self.ensure_one()
|
||||
if self.file_format == 'excel':
|
||||
return 'xlsx'
|
||||
if self.file_format == "excel":
|
||||
return "xlsx"
|
||||
else:
|
||||
return super()._get_file_extension()
|
||||
|
||||
|
@ -73,7 +81,8 @@ class SqlExport(models.Model):
|
|||
def excel_get_data_from_query(self, variable_dict):
|
||||
self.ensure_one()
|
||||
res = self._execute_sql_request(
|
||||
params=variable_dict, mode='fetchall', header=self.header)
|
||||
params=variable_dict, mode="fetchall", header=self.header
|
||||
)
|
||||
# Case we insert data in an existing excel file.
|
||||
if self.attachment_id:
|
||||
datas = self.attachment_id.datas
|
||||
|
@ -86,8 +95,11 @@ class SqlExport(models.Model):
|
|||
ws = sheets[self.sheet_position - 1]
|
||||
except IndexError:
|
||||
raise exceptions.ValidationError(
|
||||
_("The Excel Template file contains less than %s sheets "
|
||||
"Please, adjust the Sheet Position parameter."))
|
||||
_(
|
||||
"The Excel Template file contains less than %s sheets "
|
||||
"Please, adjust the Sheet Position parameter."
|
||||
)
|
||||
)
|
||||
row_position = self.row_position or 1
|
||||
col_position = self.col_position or 1
|
||||
# Case of excel file creation
|
||||
|
|
|
@ -2,24 +2,24 @@
|
|||
# @author: Florian da Costa
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
|
||||
|
||||
from odoo.tests.common import TransactionCase
|
||||
import base64
|
||||
from io import BytesIO
|
||||
import logging
|
||||
from io import BytesIO
|
||||
|
||||
from odoo.tests.common import TransactionCase
|
||||
|
||||
_logger = logging.getLogger(__name__)
|
||||
|
||||
try:
|
||||
import openpyxl
|
||||
except ImportError:
|
||||
_logger.debug('Can not import openpyxl')
|
||||
_logger.debug("Can not import openpyxl")
|
||||
|
||||
|
||||
class TestExportSqlQueryExcel(TransactionCase):
|
||||
|
||||
def setUp(self):
|
||||
super().setUp()
|
||||
self.wizard_obj = self.env['sql.file.wizard']
|
||||
self.wizard_obj = self.env["sql.file.wizard"]
|
||||
|
||||
def get_workbook_from_query(self, wizard):
|
||||
wizard.export_sql()
|
||||
|
@ -30,27 +30,29 @@ class TestExportSqlQueryExcel(TransactionCase):
|
|||
def test_excel_file_generation(self):
|
||||
test_query = "SELECT 'testcol1' as firstcol, 2 as second_col"
|
||||
query_vals = {
|
||||
'name': 'Test Query Excel',
|
||||
'query': test_query,
|
||||
'file_format': 'excel'
|
||||
"name": "Test Query Excel",
|
||||
"query": test_query,
|
||||
"file_format": "excel",
|
||||
}
|
||||
query = self.env['sql.export'].create(query_vals)
|
||||
query = self.env["sql.export"].create(query_vals)
|
||||
query.button_validate_sql_expression()
|
||||
wizard = self.wizard_obj.create({
|
||||
'sql_export_id': query.id,
|
||||
})
|
||||
wizard = self.wizard_obj.create(
|
||||
{
|
||||
"sql_export_id": query.id,
|
||||
}
|
||||
)
|
||||
workbook = self.get_workbook_from_query(wizard)
|
||||
ws = workbook.active
|
||||
# Check values, header should be here by default
|
||||
self.assertEqual(ws.cell(row=1, column=1).value, 'firstcol')
|
||||
self.assertEqual(ws.cell(row=2, column=1).value, 'testcol1')
|
||||
self.assertEqual(ws.cell(row=1, column=1).value, "firstcol")
|
||||
self.assertEqual(ws.cell(row=2, column=1).value, "testcol1")
|
||||
self.assertEqual(ws.cell(row=2, column=2).value, 2)
|
||||
|
||||
query.write({'header': False})
|
||||
query.write({"header": False})
|
||||
wb2 = self.get_workbook_from_query(wizard)
|
||||
ws2 = wb2.active
|
||||
# Check values, the header should not be present
|
||||
self.assertEqual(ws2.cell(row=1, column=1).value, 'testcol1')
|
||||
self.assertEqual(ws2.cell(row=1, column=1).value, "testcol1")
|
||||
self.assertEqual(ws2.cell(row=1, column=2).value, 2)
|
||||
|
||||
def test_excel_file_insert(self):
|
||||
|
@ -60,8 +62,8 @@ class TestExportSqlQueryExcel(TransactionCase):
|
|||
ws = wb.active
|
||||
ws.cell(row=1, column=1, value="My Test Value")
|
||||
ws2 = wb.create_sheet("data")
|
||||
ws2.cell(row=1, column=1, value='Partner Id')
|
||||
ws2.cell(row=1, column=2, value='Partner Name')
|
||||
ws2.cell(row=1, column=1, value="Partner Id")
|
||||
ws2.cell(row=1, column=2, value="Partner Name")
|
||||
output = BytesIO()
|
||||
wb.save(output)
|
||||
data = output.getvalue()
|
||||
|
@ -69,10 +71,10 @@ class TestExportSqlQueryExcel(TransactionCase):
|
|||
# Create attachment with the created xlsx file which will be used as
|
||||
# template in the sql query
|
||||
attachmnent_vals = {
|
||||
'name': 'template xlsx sql export Res Partner',
|
||||
'datas': base64.b64encode(data),
|
||||
"name": "template xlsx sql export Res Partner",
|
||||
"datas": base64.b64encode(data),
|
||||
}
|
||||
attachment = self.env['ir.attachment'].create(attachmnent_vals)
|
||||
attachment = self.env["ir.attachment"].create(attachmnent_vals)
|
||||
|
||||
# Create the query and configure it to insert the data in the second
|
||||
# sheet of the xlsx template file and start inserting data at the
|
||||
|
@ -80,19 +82,21 @@ class TestExportSqlQueryExcel(TransactionCase):
|
|||
# already contains a header)
|
||||
test_query = "SELECT id, name FROM res_partner"
|
||||
query_vals = {
|
||||
'name': 'Test Query Excel',
|
||||
'query': test_query,
|
||||
'file_format': 'excel',
|
||||
'attachment_id': attachment.id,
|
||||
'sheet_position': 2,
|
||||
'header': False,
|
||||
'row_position': 2,
|
||||
"name": "Test Query Excel",
|
||||
"query": test_query,
|
||||
"file_format": "excel",
|
||||
"attachment_id": attachment.id,
|
||||
"sheet_position": 2,
|
||||
"header": False,
|
||||
"row_position": 2,
|
||||
}
|
||||
query = self.env['sql.export'].create(query_vals)
|
||||
query = self.env["sql.export"].create(query_vals)
|
||||
query.button_validate_sql_expression()
|
||||
wizard = self.wizard_obj.create({
|
||||
'sql_export_id': query.id,
|
||||
})
|
||||
wizard = self.wizard_obj.create(
|
||||
{
|
||||
"sql_export_id": query.id,
|
||||
}
|
||||
)
|
||||
|
||||
# Check the generated excel file. The first sheet should still contain
|
||||
# the same data and the second sheet should have kept the header and
|
||||
|
@ -101,7 +105,7 @@ class TestExportSqlQueryExcel(TransactionCase):
|
|||
sheets = wb2.worksheets
|
||||
ws1 = sheets[0]
|
||||
# Check values, header should be here by default
|
||||
self.assertEqual(ws1.cell(row=1, column=1).value, 'My Test Value')
|
||||
self.assertEqual(ws1.cell(row=1, column=1).value, "My Test Value")
|
||||
ws2 = sheets[1]
|
||||
self.assertEqual(ws2.cell(row=1, column=1).value, 'Partner Id')
|
||||
self.assertEqual(ws2.cell(row=1, column=1).value, "Partner Id")
|
||||
self.assertTrue(ws2.cell(row=2, column=1).value)
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<openerp>
|
||||
<data>
|
||||
|
||||
|
@ -8,11 +8,26 @@
|
|||
<field name="inherit_id" ref="sql_export.sql_export_view_form" />
|
||||
<field name="arch" type="xml">
|
||||
<field name="file_format" position="after">
|
||||
<field name="header" attrs="{'invisible': [('file_format', '=', 'csv')]}"/>
|
||||
<field name="attachment_id" attrs="{'invisible': [('file_format', '!=', 'excel')]}"/>
|
||||
<field name="sheet_position" attrs="{'invisible': [('attachment_id', '=', False)]}"/>
|
||||
<field name="row_position" attrs="{'invisible': [('attachment_id', '=', False)]}"/>
|
||||
<field name="col_position" attrs="{'invisible': [('attachment_id', '=', False)]}"/>
|
||||
<field
|
||||
name="header"
|
||||
attrs="{'invisible': [('file_format', '=', 'csv')]}"
|
||||
/>
|
||||
<field
|
||||
name="attachment_id"
|
||||
attrs="{'invisible': [('file_format', '!=', 'excel')]}"
|
||||
/>
|
||||
<field
|
||||
name="sheet_position"
|
||||
attrs="{'invisible': [('attachment_id', '=', False)]}"
|
||||
/>
|
||||
<field
|
||||
name="row_position"
|
||||
attrs="{'invisible': [('attachment_id', '=', False)]}"
|
||||
/>
|
||||
<field
|
||||
name="col_position"
|
||||
attrs="{'invisible': [('attachment_id', '=', False)]}"
|
||||
/>
|
||||
</field>
|
||||
</field>
|
||||
</record>
|
||||
|
|
Loading…
Reference in New Issue