diff --git a/report_relatorio/README.rst b/report_relatorio/README.rst new file mode 100644 index 0000000..215ef82 --- /dev/null +++ b/report_relatorio/README.rst @@ -0,0 +1,89 @@ +.. 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 + +================ +Base report xlsx +================ + +This module provides a basic report class to generate xlsx report. + +Installation +============ + +Make sure you have ``xlsxwriter`` Python module installed:: + +$ pip install xlsxwriter + +Usage +===== + +An example of XLSX report for partners: + +A python class :: + + from openerp.addons.report_xlsx.report.report_xlsx import ReportXlsx + + class partner_xlsx(ReportXlsx): + + def generate_xlsx_report(self, workbook, data, partners): + for obj in partners: + report_name = obj.name + # One sheet by partner + sheet = workbook.add_worksheet(report_name[:31]) + bold = workbook.add_format({'bold': True}) + sheet.write(0, 0, obj.name, bold) + + + partner_xlsx('report.res.partner.xlsx', + 'res.partner') + +To manipulate the ``workbook`` and ``sheet`` objects, refer to the +`documentation `_ of ``xlsxwriter``. + +A report XML record :: + + + +.. image:: https://odoo-community.org/website/image/ir.attachment/5784_f2813bd/datas + :alt: Try me on Runbot + :target: https://runbot.odoo-community.org/runbot/143/8.0 + +Bug Tracker +=========== + +Bugs are tracked on `GitHub 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 +`here `_. + +Credits +======= + +* Icon taken from http://www.icons101.com/icon/id_67712/setid_2096/Boxed_Metal_by_Martin/xlsx. + +Contributors +------------ + +* Adrien Peiffer + +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. diff --git a/report_relatorio/__init__.py b/report_relatorio/__init__.py new file mode 100644 index 0000000..6db3fc7 --- /dev/null +++ b/report_relatorio/__init__.py @@ -0,0 +1,19 @@ +# -*- coding: utf-8 -*- + +# Copyright 2016 Fabien Bourgeois +# +# 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 . + +from . import models +from . import report diff --git a/report_relatorio/models/__init__.py b/report_relatorio/models/__init__.py new file mode 100644 index 0000000..1a293ad --- /dev/null +++ b/report_relatorio/models/__init__.py @@ -0,0 +1,18 @@ +# -*- coding: utf-8 -*- + +# Copyright 2016 Fabien Bourgeois +# +# 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 . + +from . import ir_report diff --git a/report_relatorio/models/ir_report.py b/report_relatorio/models/ir_report.py new file mode 100644 index 0000000..23f370e --- /dev/null +++ b/report_relatorio/models/ir_report.py @@ -0,0 +1,24 @@ +# -*- coding: utf-8 -*- + +# Copyright 2016 Fabien Bourgeois +# +# 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 . + +from openerp import fields, models + + +class IrActionsReportRelatorio(models.Model): + _inherit = 'ir.actions.report.xml' + + report_type = fields.Selection(selection_add=[("xlsx", "xlsx")]) diff --git a/report_relatorio/openerp.tmp.py b/report_relatorio/openerp.tmp.py new file mode 100644 index 0000000..d061330 --- /dev/null +++ b/report_relatorio/openerp.tmp.py @@ -0,0 +1,30 @@ +# -*- coding: utf-8 -*- + +# Copyright 2016 Fabien Bourgeois +# +# 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 . + +{ + 'name': 'Relatorio reporting', + 'summary': 'Adds simple reporting engine based on relatorio', + 'version': '0.1', + 'category': 'Reporting', + 'author': 'Fabien Bourgeois', + 'website': 'http://www.yaltik.com', + 'license': 'AGPL-3', + 'application': True, + 'installable': True, + 'external_dependencies': {'python': ['relatorio']}, + 'depends': ['base'] +} diff --git a/report_relatorio/report/__init__.py b/report_relatorio/report/__init__.py new file mode 100644 index 0000000..637f86d --- /dev/null +++ b/report_relatorio/report/__init__.py @@ -0,0 +1,18 @@ +# -*- coding: utf-8 -*- + +# Copyright 2016 Fabien Bourgeois +# +# 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 . + +from . import report_relatorio diff --git a/report_relatorio/report/report_xlsx.py b/report_relatorio/report/report_xlsx.py new file mode 100644 index 0000000..285c97b --- /dev/null +++ b/report_relatorio/report/report_xlsx.py @@ -0,0 +1,45 @@ +# -*- coding: utf-8 -*- +# Copyright 2015 ACSONE SA/NV () +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +from cStringIO import StringIO + +from openerp.report.report_sxw import report_sxw +from openerp.api import Environment + +import logging +_logger = logging.getLogger(__name__) + +try: + import xlsxwriter +except ImportError: + _logger.debug('Can not import xlsxwriter`.') + + +class ReportXlsx(report_sxw): + + def create(self, cr, uid, ids, data, context=None): + self.env = Environment(cr, uid, context) + report_obj = self.env['ir.actions.report.xml'] + report = report_obj.search([('report_name', '=', self.name[7:])]) + if report.ids: + self.title = report.name + if report.report_type == 'xlsx': + return self.create_xlsx_report(ids, data, report) + return super(ReportXlsx, self).create(cr, uid, ids, data, context) + + def create_xlsx_report(self, ids, data, report): + self.parser_instance = self.parser( + self.env.cr, self.env.uid, self.name2, self.env.context) + objs = self.getObjects( + self.env.cr, self.env.uid, ids, self.env.context) + self.parser_instance.set_context(objs, data, ids, 'xlsx') + file_data = StringIO() + workbook = xlsxwriter.Workbook(file_data) + self.generate_xlsx_report(workbook, data, objs) + workbook.close() + file_data.seek(0) + return (file_data.read(), 'xlsx') + + def generate_xlsx_report(self, workbook, data, objs): + raise NotImplementedError() diff --git a/report_relatorio/static/description/icon.png b/report_relatorio/static/description/icon.png new file mode 100644 index 0000000..baab9a4 Binary files /dev/null and b/report_relatorio/static/description/icon.png differ diff --git a/web_image_uploader/__init__.py b/web_image_uploader/__init__.py new file mode 100644 index 0000000..643d893 --- /dev/null +++ b/web_image_uploader/__init__.py @@ -0,0 +1,16 @@ +# -*- coding: utf-8 -*- + +# Copyright 2016 Fabien Bourgeois +# +# 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 . diff --git a/web_image_uploader/__openerp__.py b/web_image_uploader/__openerp__.py new file mode 100644 index 0000000..8ce79fa --- /dev/null +++ b/web_image_uploader/__openerp__.py @@ -0,0 +1,30 @@ +# -*- coding: utf-8 -*- + +# Copyright 2016 Fabien Bourgeois +# +# 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 . + +{ + 'name': 'Web Image Uploader', + 'summary': 'Web Widget : Image Uploader', + 'description': 'Web Widget : Image Uploader', + 'version': '0.1', + 'category': 'Usability', + 'author': 'Fabien Bourgeois', + 'license': 'AGPL-3', + 'application': False, + 'installable': True, + 'depends': ['web'], + 'data': ['views/web_image_uploader.xml'] +} diff --git a/web_image_uploader/static/src/js/dmuploader.js b/web_image_uploader/static/src/js/dmuploader.js new file mode 100644 index 0000000..746ddbd --- /dev/null +++ b/web_image_uploader/static/src/js/dmuploader.js @@ -0,0 +1,289 @@ +/* + * dmuploader.js - Jquery File Uploader - 0.1 + * http://www.daniel.com.uy/projects/jquery-file-uploader/ + * + * Copyright (c) 2013 Daniel Morales + * Dual licensed under the MIT and GPL licenses. + * http://www.daniel.com.uy/doc/license/ + */ + +(function($) { + var pluginName = 'dmUploader'; + + // These are the plugin defaults values + var defaults = { + url: document.URL, + method: 'POST', + extraData: {}, + maxFileSize: 0, + maxFiles: 0, + allowedTypes: '*', + extFilter: null, + dataType: null, + fileName: 'file', + onInit: function(){}, + onFallbackMode: function(message) {}, + onNewFile: function(id, file){}, + onBeforeUpload: function(id){}, + onComplete: function(){}, + onUploadProgress: function(id, percent){}, + onUploadSuccess: function(id, data){}, + onUploadError: function(id, message){}, + onFileTypeError: function(file){}, + onFileSizeError: function(file){}, + onFileExtError: function(file){}, + onFilesMaxError: function(file){} + }; + + var DmUploader = function(element, options) + { + this.element = $(element); + + this.settings = $.extend({}, defaults, options); + + if(!this.checkBrowser()){ + return false; + } + + this.init(); + + return true; + }; + + DmUploader.prototype.checkBrowser = function() + { + if(window.FormData === undefined){ + this.settings.onFallbackMode.call(this.element, 'Browser doesn\'t support Form API'); + + return false; + } + + if(this.element.find('input[type=file]').length > 0){ + return true; + } + + if (!this.checkEvent('drop', this.element) || !this.checkEvent('dragstart', this.element)){ + this.settings.onFallbackMode.call(this.element, 'Browser doesn\'t support Ajax Drag and Drop'); + + return false; + } + + return true; + }; + + DmUploader.prototype.checkEvent = function(eventName, element) + { + var element = element || document.createElement('div'); + var eventName = 'on' + eventName; + + var isSupported = eventName in element; + + if(!isSupported){ + if(!element.setAttribute){ + element = document.createElement('div'); + } + if(element.setAttribute && element.removeAttribute){ + element.setAttribute(eventName, ''); + isSupported = typeof element[eventName] == 'function'; + + if(typeof element[eventName] != 'undefined'){ + element[eventName] = undefined; + } + element.removeAttribute(eventName); + } + } + + element = null; + return isSupported; + }; + + DmUploader.prototype.init = function() + { + var widget = this; + + widget.queue = new Array(); + widget.queuePos = -1; + widget.queueRunning = false; + + // -- Drag and drop event + widget.element.on('drop', function (evt){ + evt.preventDefault(); + var files = evt.originalEvent.dataTransfer.files; + + widget.queueFiles(files); + }); + + //-- Optional File input to make a clickable area + widget.element.find('input[type=file]').on('change', function(evt){ + var files = evt.target.files; + + widget.queueFiles(files); + + $(this).val(''); + }); + + this.settings.onInit.call(this.element); + }; + + DmUploader.prototype.queueFiles = function(files) + { + var j = this.queue.length; + + for (var i= 0; i < files.length; i++) + { + var file = files[i]; + + // Check file size + if((this.settings.maxFileSize > 0) && + (file.size > this.settings.maxFileSize)){ + + this.settings.onFileSizeError.call(this.element, file); + + continue; + } + + // Check file type + if((this.settings.allowedTypes != '*') && + !file.type.match(this.settings.allowedTypes)){ + + this.settings.onFileTypeError.call(this.element, file); + + continue; + } + + // Check file extension + if(this.settings.extFilter != null){ + var extList = this.settings.extFilter.toLowerCase().split(';'); + + var ext = file.name.toLowerCase().split('.').pop(); + + if($.inArray(ext, extList) < 0){ + this.settings.onFileExtError.call(this.element, file); + + continue; + } + } + + // Check max files + if(this.settings.maxFiles > 0) { + if(this.queue.length >= this.settings.maxFiles) { + this.settings.onFilesMaxError.call(this.element, file); + + continue; + } + } + + this.queue.push(file); + + var index = this.queue.length - 1; + + this.settings.onNewFile.call(this.element, index, file); + } + + // Only start Queue if we haven't! + if(this.queueRunning){ + return false; + } + + // and only if new Failes were successfully added + if(this.queue.length == j){ + return false; + } + + this.processQueue(); + + return true; + }; + + DmUploader.prototype.processQueue = function() + { + var widget = this; + + widget.queuePos++; + + if(widget.queuePos >= widget.queue.length){ + // Cleanup + + widget.settings.onComplete.call(widget.element); + + // Wait until new files are droped + widget.queuePos = (widget.queue.length - 1); + + widget.queueRunning = false; + + return; + } + + var file = widget.queue[widget.queuePos]; + + // Form Data + var fd = new FormData(); + fd.append(widget.settings.fileName, file); + + // Return from client function (default === undefined) + var can_continue = widget.settings.onBeforeUpload.call(widget.element, widget.queuePos); + + // If the client function doesn't return FALSE then continue + if( false === can_continue ) { + return; + } + + // Append extra Form Data + $.each(widget.settings.extraData, function(exKey, exVal){ + fd.append(exKey, exVal); + }); + + widget.queueRunning = true; + + // Ajax Submit + $.ajax({ + url: widget.settings.url, + type: widget.settings.method, + dataType: widget.settings.dataType, + data: fd, + cache: false, + contentType: false, + processData: false, + forceSync: false, + xhr: function(){ + var xhrobj = $.ajaxSettings.xhr(); + if(xhrobj.upload){ + xhrobj.upload.addEventListener('progress', function(event) { + var percent = 0; + var position = event.loaded || event.position; + var total = event.total || event.totalSize; + if(event.lengthComputable){ + percent = Math.ceil(position / total * 100); + } + + widget.settings.onUploadProgress.call(widget.element, widget.queuePos, percent); + }, false); + } + + return xhrobj; + }, + success: function (data, message, xhr){ + widget.settings.onUploadSuccess.call(widget.element, widget.queuePos, data); + }, + error: function (xhr, status, errMsg){ + widget.settings.onUploadError.call(widget.element, widget.queuePos, errMsg); + }, + complete: function(xhr, textStatus){ + widget.processQueue(); + } + }); + } + + $.fn.dmUploader = function(options){ + return this.each(function(){ + if(!$.data(this, pluginName)){ + $.data(this, pluginName, new DmUploader(this, options)); + } + }); + }; + + // -- Disable Document D&D events to prevent opening the file on browser when we drop them + $(document).on('dragenter', function (e) { e.stopPropagation(); e.preventDefault(); }); + $(document).on('dragover', function (e) { e.stopPropagation(); e.preventDefault(); }); + $(document).on('drop', function (e) { e.stopPropagation(); e.preventDefault(); }); +})(jQuery); diff --git a/web_image_uploader/web_image_uploader.xml b/web_image_uploader/web_image_uploader.xml new file mode 100644 index 0000000..b0eea6c --- /dev/null +++ b/web_image_uploader/web_image_uploader.xml @@ -0,0 +1,57 @@ + + + + + + + + + +