[IMP] prototype: implementation of jinja syntax.
[IMP] prototype: Switched to v8 api. [IMP] prototype: renamed the templates to avoid confusion with pep8 tests. [IMP] prototype: renamed some fields in prototype.py. [IMP] prototype: implemented the process to create the zip file to export. [IMP] prototype: worked on the generation of __openerp__.py and __init__.py files from the prototype. [IMP] prototype: pep8 [IMP] prototype: added more comments. [IMP] prototype: worked on fields. [IMP] prototype: implemented the generation of files from models/model_name.py.template and models/init.py.template [IMP] prototype: first work on implementation of generations of views. [IMP] prototype: improved the arch section in model_view.xml.template [IMP] prototype: Reviewed the names of many2many from plurials to name_ids. [IMP] prototype: added menus. [IMP] prototype: typo in templates/8.0/views/model_view.xml.template [IMP] prototype: improved template with adding extension to header.template to ease management of file with licence header. [IMP] prototype: prototype.prototype demo data [IMP] prototype: worked to get the views and menus properly generated. Added actions to model_menus.xml.template. [IMP] prototype: should fix pep8 in model_name.py.template.pull/107/head
parent
75d00737c9
commit
69db83fc87
|
@ -45,10 +45,10 @@ Contributors
|
|||
* Maxime Chambreuil <maxime.chambreuil@savoirfairelinux.com>
|
||||
* Savoir-faire Linux <support@savoirfairelinux.com>
|
||||
|
||||
More informations
|
||||
-----------------
|
||||
* Module developped and tested with Odoo version 8.0
|
||||
* For questions, please contact our support services \
|
||||
More information
|
||||
----------------
|
||||
* Module developed and tested with Odoo version 8.0
|
||||
* For questions, please contact our support services
|
||||
(support@savoirfairelinux.com)
|
||||
""",
|
||||
'depends': [
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -87,7 +87,7 @@ msgid "Demo filters"
|
|||
msgstr "Filtres pour les données de démo"
|
||||
|
||||
#. module: prototype
|
||||
#: view:prototype:prototype.view_prototype_form field:prototype,depends:0
|
||||
#: view:prototype:prototype.view_prototype_form field:prototype,dependencies:0
|
||||
msgid "Dependencies"
|
||||
msgstr "Dépendances"
|
||||
|
||||
|
@ -190,7 +190,7 @@ msgid "Module"
|
|||
msgstr ""
|
||||
|
||||
#. module: prototype
|
||||
#: field:prototype,shortdesc:0
|
||||
#: field:prototype,human_name:0
|
||||
msgid "Module Name"
|
||||
msgstr "Nom du module"
|
||||
|
||||
|
|
|
@ -87,7 +87,7 @@ msgid "Demo filters"
|
|||
msgstr ""
|
||||
|
||||
#. module: prototype
|
||||
#: view:prototype:prototype.view_prototype_form field:prototype,depends:0
|
||||
#: view:prototype:prototype.view_prototype_form field:prototype,dependencies:0
|
||||
msgid "Dependencies"
|
||||
msgstr ""
|
||||
|
||||
|
@ -190,7 +190,7 @@ msgid "Module"
|
|||
msgstr ""
|
||||
|
||||
#. module: prototype
|
||||
#: field:prototype,shortdesc:0
|
||||
#: field:prototype,human_name:0
|
||||
msgid "Module Name"
|
||||
msgstr ""
|
||||
|
||||
|
|
|
@ -19,12 +19,10 @@
|
|||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
##############################################################################
|
||||
from openerp.osv import fields, osv
|
||||
from openerp import fields, models
|
||||
|
||||
|
||||
class ir_model_fields(osv.osv):
|
||||
class ir_model_fields(models.Model):
|
||||
_inherit = "ir.model.fields"
|
||||
|
||||
_columns = {
|
||||
'notes': fields.text('Notes'),
|
||||
}
|
||||
notes = fields.Text('Notes')
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
# -*- encoding: utf-8 -*-
|
||||
##############################################################################
|
||||
# #############################################################################
|
||||
#
|
||||
# OpenERP, Open Source Management Solution
|
||||
# This module copyright (C) 2010 - 2014 Savoir-faire Linux
|
||||
|
@ -19,51 +19,321 @@
|
|||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
##############################################################################
|
||||
from openerp.osv import fields, osv
|
||||
import os
|
||||
import re
|
||||
import base64
|
||||
from datetime import date
|
||||
YEAR = date.today().year
|
||||
|
||||
from collections import namedtuple
|
||||
from jinja2 import Environment, FileSystemLoader
|
||||
from openerp import models, api, fields
|
||||
|
||||
|
||||
class prototype(osv.osv):
|
||||
class Prototype(models.Model):
|
||||
_name = "prototype"
|
||||
_description = "Prototype"
|
||||
|
||||
_columns = {
|
||||
'name': fields.char('Technical Name', required=True),
|
||||
'category_id': fields.many2one('ir.module.category', 'Category'),
|
||||
'shortdesc': fields.char('Module Name', required=True),
|
||||
'summary': fields.char('Summary', required=True),
|
||||
'description': fields.html('Description', required=True),
|
||||
'author': fields.char('Author', required=True),
|
||||
'maintainer': fields.char('Maintainer'),
|
||||
'website': fields.char('Website'),
|
||||
'icon_image': fields.binary('Icon'),
|
||||
'version': fields.char('Version', size=3),
|
||||
'auto_install': fields.boolean('Auto Install'),
|
||||
licence = fields.Char(
|
||||
'Licence',
|
||||
default='AGPL-3',
|
||||
)
|
||||
name = fields.Char(
|
||||
'Technical Name', required=True,
|
||||
help=('The technical name will be used to define the name of '
|
||||
'the exported module, the name of the model.')
|
||||
)
|
||||
category_id = fields.Many2one('ir.module.category', 'Category')
|
||||
human_name = fields.Char(
|
||||
'Module Name', required=True,
|
||||
help=('The Module Name will be used as the displayed name of the '
|
||||
'exported module.')
|
||||
)
|
||||
summary = fields.Char('Summary', required=True)
|
||||
description = fields.Text('Description', required=True)
|
||||
author = fields.Char('Author', required=True)
|
||||
maintainer = fields.Char('Maintainer')
|
||||
website = fields.Char('Website')
|
||||
icon_image = fields.Binary(
|
||||
'Icon',
|
||||
help=('The icon set up here will be used as the icon '
|
||||
'for the exported module also')
|
||||
)
|
||||
version = fields.Char('Version', size=3, default='0.1')
|
||||
auto_install = fields.Boolean(
|
||||
'Auto Install',
|
||||
default=False,
|
||||
help='Check if the module should be install by default.'
|
||||
)
|
||||
application = fields.Boolean(
|
||||
'Application',
|
||||
default=False,
|
||||
help='Check if the module is an Odoo application.'
|
||||
)
|
||||
# Relations
|
||||
'depends': fields.many2many('ir.module.module', 'prototype_module_rel',
|
||||
dependency_ids = fields.Many2many(
|
||||
'ir.module.module', 'prototype_module_rel',
|
||||
'prototype_id', 'module_id',
|
||||
'Dependencies'),
|
||||
'data': fields.many2many('ir.filters', 'prototype_data_rel',
|
||||
'Dependencies'
|
||||
)
|
||||
data_ids = fields.Many2many(
|
||||
'ir.filters',
|
||||
'prototype_data_rel',
|
||||
'prototype_id', 'filter_id',
|
||||
'Data filters', help="The records matching the filters will be added as data."),
|
||||
'demo': fields.many2many('ir.filters', 'prototype_demo_rel',
|
||||
'Data filters',
|
||||
help="The records matching the filters will be added as data."
|
||||
)
|
||||
demo_ids = fields.Many2many(
|
||||
'ir.filters',
|
||||
'prototype_demo_rel',
|
||||
'prototype_id', 'filter_id',
|
||||
'Demo filters', help="The records matching the filters will be added as demo data."),
|
||||
'fields': fields.many2many('ir.model.fields', 'prototype_fields_rel',
|
||||
'prototype_id', 'field_id', 'Fields'),
|
||||
'menu': fields.many2many('ir.ui.menu', 'prototype_menu_rel',
|
||||
'prototype_id', 'menu_id', 'Menu Items'),
|
||||
'views': fields.many2many('ir.ui.view', 'prototype_view_rel',
|
||||
'prototype_id', 'view_id', 'Views'),
|
||||
'groups': fields.many2many('res.groups', 'prototype_groups_rel',
|
||||
'prototype_id', 'group_id', 'Groups'),
|
||||
'rights': fields.many2many('ir.model.access', 'prototype_rights_rel',
|
||||
'Demo filters',
|
||||
help="The records matching the filters will be added as demo data."
|
||||
)
|
||||
field_ids = fields.Many2many(
|
||||
'ir.model.fields', 'prototype_fields_rel',
|
||||
'prototype_id', 'field_id', 'Fields'
|
||||
)
|
||||
menu_ids = fields.Many2many(
|
||||
'ir.ui.menu', 'prototype_menu_rel',
|
||||
'prototype_id', 'menu_id', 'Menu Items'
|
||||
)
|
||||
view_ids = fields.Many2many(
|
||||
'ir.ui.view', 'prototype_view_rel',
|
||||
'prototype_id', 'view_id', 'Views'
|
||||
)
|
||||
group_ids = fields.Many2many(
|
||||
'res.groups', 'prototype_groups_rel',
|
||||
'prototype_id', 'group_id', 'Groups'
|
||||
)
|
||||
right_ids = fields.Many2many(
|
||||
'ir.model.access', 'prototype_rights_rel',
|
||||
'prototype_id', 'right_id',
|
||||
'Access Rights'),
|
||||
'rules': fields.many2many('ir.rule', 'prototype_rule_rel',
|
||||
'prototype_id', 'rule_id', 'Record Rules'),
|
||||
}
|
||||
'Access Rights'
|
||||
)
|
||||
rule_ids = fields.Many2many(
|
||||
'ir.rule', 'prototype_rule_rel',
|
||||
'prototype_id', 'rule_id', 'Record Rules'
|
||||
)
|
||||
|
||||
_defaults = {
|
||||
'auto_install': False,
|
||||
'version': '0.1',
|
||||
__data_files = []
|
||||
__field_descriptions = {}
|
||||
_env = None
|
||||
File_details = namedtuple('file_details', ['filename', 'filecontent'])
|
||||
template_path = '{}/../templates/'.format(os.path.dirname(__file__))
|
||||
|
||||
@api.model
|
||||
def set_jinja_env(self, api_version):
|
||||
"""Set the Jinja2 environment.
|
||||
The environment will helps the system to find the templates to render.
|
||||
:param api_version: string, odoo api
|
||||
:return: jinja2.Environment instance.
|
||||
"""
|
||||
if self._env is None:
|
||||
self._env = Environment(
|
||||
loader=FileSystemLoader(
|
||||
os.path.join(self.template_path, api_version)
|
||||
)
|
||||
)
|
||||
return self._env
|
||||
|
||||
def set_field_descriptions(self):
|
||||
"""Mock the list of fields into dictionary.
|
||||
It allows us to add or change attributes of the fields.
|
||||
|
||||
:return: None
|
||||
"""
|
||||
for field in self.field_ids:
|
||||
field_description = {}
|
||||
# This will mock a field record.
|
||||
# the mock will allow us to add data or modify the data
|
||||
# of the field (like for the name) with keeping all the
|
||||
# attributes of the record.
|
||||
field_description.update({
|
||||
attr_name: getattr(field, attr_name)
|
||||
for attr_name in dir(field)
|
||||
if not attr_name[0] == '_'
|
||||
})
|
||||
# custom fields start with the prefix x_.
|
||||
# it has to be removed.
|
||||
field_description['name'] = re.sub(r'^x_', '', field.name)
|
||||
self.__field_descriptions[field] = field_description
|
||||
|
||||
@api.model
|
||||
def generate_files(self):
|
||||
""" Generates the files from the details of the prototype.
|
||||
:return: tuple
|
||||
"""
|
||||
assert self._env is not None, \
|
||||
'Run set_env(api_version) before to generate files.'
|
||||
|
||||
self.set_field_descriptions()
|
||||
file_details = []
|
||||
file_details.extend(self.generate_models_details())
|
||||
file_details.extend(self.generate_views_details())
|
||||
file_details.extend(self.generate_menus_details())
|
||||
file_details.append(self.generate_module_init_file_details())
|
||||
# must be the last as the other generations might add information
|
||||
# to put in the __openerp__: additional dependencies, views files, etc.
|
||||
file_details.append(self.generate_module_openerp_file_details())
|
||||
file_details.append(self.save_icon())
|
||||
|
||||
return file_details
|
||||
|
||||
@api.model
|
||||
def save_icon(self):
|
||||
return self.File_details(
|
||||
os.path.join('static', 'description', 'icon.jpg'),
|
||||
base64.b64decode(self.icon_image)
|
||||
)
|
||||
|
||||
@api.model
|
||||
def generate_module_openerp_file_details(self):
|
||||
"""Wrapper to generate the __openerp__.py file of the module."""
|
||||
return self.generate_file_details(
|
||||
'__openerp__.py',
|
||||
'__openerp__.py.template',
|
||||
prototype=self,
|
||||
data_files=self.__data_files,
|
||||
)
|
||||
|
||||
@api.model
|
||||
def generate_module_init_file_details(self):
|
||||
"""Wrapper to generate the __init__.py file of the module."""
|
||||
return self.generate_file_details(
|
||||
'__init__.py',
|
||||
'__init__.py.template',
|
||||
# no import models if no work of fields in
|
||||
# the prototype
|
||||
models=bool(self.field_ids)
|
||||
)
|
||||
|
||||
@api.model
|
||||
def generate_models_details(self):
|
||||
"""Finds the models from the list of fields and generates
|
||||
the __init__ file and each models files (one by class).
|
||||
"""
|
||||
files = []
|
||||
# TODO: doesn't work as need to find the module to import
|
||||
# and it is not necessary the name of the model the fields
|
||||
# belongs to.
|
||||
# ie. field.cell_phone is defined in a model inheriting from
|
||||
# res.partner.
|
||||
# How do we find the module the field was defined in?
|
||||
# dependencies = set([dep.id for dep in self.dependencies])
|
||||
|
||||
relations = {}
|
||||
for field in self.__field_descriptions.itervalues():
|
||||
model = field.get('model_id')
|
||||
relations.setdefault(model, []).append(field)
|
||||
# dependencies.add(model.id)
|
||||
|
||||
# blind update of dependencies.
|
||||
# self.write({
|
||||
# 'dependencies': [(6, 0, [id_ for id_ in dependencies])]
|
||||
# })
|
||||
|
||||
files.append(self.generate_models_init_details(relations.keys()))
|
||||
for model, fields in relations.iteritems():
|
||||
files.append(self.generate_model_details(model, fields))
|
||||
|
||||
return files
|
||||
|
||||
@api.model
|
||||
def generate_models_init_details(self, ir_models):
|
||||
"""Wrapper to generate the __init__.py file in models folder."""
|
||||
return self.generate_file_details(
|
||||
'models/__init__.py',
|
||||
'models/__init__.py.template',
|
||||
models=[
|
||||
self.friendly_name(ir_model.model)
|
||||
for ir_model in ir_models
|
||||
]
|
||||
)
|
||||
|
||||
@api.model
|
||||
def generate_views_details(self):
|
||||
"""Wrapper to generate the views files."""
|
||||
relations = {}
|
||||
for view in self.view_ids:
|
||||
relations.setdefault(view.model, []).append(view)
|
||||
|
||||
views_details = []
|
||||
for model, views in relations.iteritems():
|
||||
filepath = 'views/{}_view.xml'.format(
|
||||
self.friendly_name(model)
|
||||
)
|
||||
views_details.append(
|
||||
self.generate_file_details(
|
||||
filepath,
|
||||
'views/model_views.xml.template',
|
||||
views=views
|
||||
)
|
||||
)
|
||||
self.__data_files.append(filepath)
|
||||
|
||||
return views_details
|
||||
|
||||
@api.model
|
||||
def generate_menus_details(self):
|
||||
"""Wrapper to generate the menus files."""
|
||||
relations = {}
|
||||
for menu in self.menu_ids:
|
||||
relations.setdefault(menu.action.res_model, []).append(menu)
|
||||
|
||||
menus_details = []
|
||||
for model_name, menus in relations.iteritems():
|
||||
filepath = 'views/{}_menus.xml'.format(
|
||||
self.friendly_name(model_name)
|
||||
)
|
||||
menus_details.append(
|
||||
self.generate_file_details(
|
||||
filepath,
|
||||
'views/model_menus.xml.template',
|
||||
menus=menus,
|
||||
)
|
||||
)
|
||||
self.__data_files.append(filepath)
|
||||
|
||||
return menus_details
|
||||
|
||||
@api.model
|
||||
def generate_model_details(self, model, field_descriptions):
|
||||
"""Wrapper to generate the python file for the model.
|
||||
|
||||
:param model: ir.model record.
|
||||
:param field_descriptions: list of ir.model.fields records.
|
||||
:return: FileDetails instance.
|
||||
"""
|
||||
python_friendly_name = self.friendly_name(model.model)
|
||||
return self.generate_file_details(
|
||||
'models/{}.py'.format(python_friendly_name),
|
||||
'models/model_name.py.template',
|
||||
name=python_friendly_name,
|
||||
inherit=model.model,
|
||||
fields=field_descriptions,
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
def friendly_name(name):
|
||||
return name.replace('.', '_')
|
||||
|
||||
@api.model
|
||||
def generate_file_details(self, filename, template, **kwargs):
|
||||
""" generate file details from jinja2 template.
|
||||
:param filename: name of the file the content is related to
|
||||
:param template: path to the file to render the content
|
||||
:param kwargs: arguments of the template
|
||||
:return: File_details instance
|
||||
"""
|
||||
template = self._env.get_template(template)
|
||||
# keywords used in several templates.
|
||||
kwargs.update(
|
||||
{
|
||||
'export_year': YEAR,
|
||||
'author': self.author,
|
||||
'website': self.website,
|
||||
'cr': self._cr,
|
||||
}
|
||||
)
|
||||
return self.File_details(filename, template.render(kwargs))
|
||||
|
|
|
@ -1,50 +0,0 @@
|
|||
# -*- encoding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# Odoo, Open Source Management Solution
|
||||
# This module copyright (C) $export_date $author
|
||||
# (<$website>).
|
||||
#
|
||||
# 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': '$name',
|
||||
'version': '$version',
|
||||
'author': '$author',
|
||||
'maintainer': '$maintainer',
|
||||
'website': '$website',
|
||||
'license': 'AGPL-3',
|
||||
'category': '$category',
|
||||
'summary': '$summary',
|
||||
'description': """
|
||||
$description
|
||||
|
||||
* Module exported by the prototype module for version 7.0.
|
||||
* If you have any questions, please contact Savoir-faire Linux \
|
||||
(support@savoirfairelinux.com)
|
||||
""",
|
||||
'depends': [
|
||||
$depends
|
||||
],
|
||||
'external_dependencies': {
|
||||
'python': [],
|
||||
},
|
||||
'data': [
|
||||
$data
|
||||
],
|
||||
'installable': True,
|
||||
'auto_install': $auto_install,
|
||||
}
|
|
@ -1,8 +0,0 @@
|
|||
<?xml version="1.0"?>
|
||||
<openerp>
|
||||
<data>
|
||||
|
||||
$data
|
||||
|
||||
</data>
|
||||
</openerp>
|
|
@ -1,8 +0,0 @@
|
|||
<?xml version="1.0"?>
|
||||
<openerp>
|
||||
<data>
|
||||
|
||||
$demo
|
||||
|
||||
</data>
|
||||
</openerp>
|
|
@ -1,24 +0,0 @@
|
|||
# -*- encoding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# Odoo, Open Source Management Solution
|
||||
# This module copyright (C) $generation_date $author
|
||||
# (<$website>).
|
||||
#
|
||||
# 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 (
|
||||
$models.py
|
||||
)
|
|
@ -1,36 +0,0 @@
|
|||
# -*- encoding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# Odoo, Open Source Management Solution
|
||||
# This module copyright (C) $generation_date $author
|
||||
# (<$website>).
|
||||
#
|
||||
# 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.osv import fields, osv
|
||||
|
||||
|
||||
class $model_name(osv.osv):
|
||||
_name = "$model_name"
|
||||
_inherit = "$model_name"
|
||||
_description = "$model_description"
|
||||
|
||||
_columns = {
|
||||
$model_fields
|
||||
}
|
||||
|
||||
_defaults = {
|
||||
|
||||
}
|
|
@ -1 +0,0 @@
|
|||
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
|
|
|
@ -0,0 +1,6 @@
|
|||
{% extends "header.template" %}
|
||||
{% block body %}
|
||||
{% if models -%}
|
||||
from . import models
|
||||
{% endif %}
|
||||
{% endblock %}
|
|
@ -1,50 +0,0 @@
|
|||
# -*- encoding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# Odoo, Open Source Management Solution
|
||||
# This module copyright (C) $export_date $author
|
||||
# (<$website>).
|
||||
#
|
||||
# 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': '$name',
|
||||
'version': '$version',
|
||||
'author': '$author',
|
||||
'maintainer': '$maintainer',
|
||||
'website': '$website',
|
||||
'license': 'AGPL-3',
|
||||
'category': '$category',
|
||||
'summary': '$summary',
|
||||
'description': """
|
||||
$description
|
||||
|
||||
* Module exported by the prototype module for version 8.0.
|
||||
* If you have any questions, please contact Savoir-faire Linux \
|
||||
(support@savoirfairelinux.com)
|
||||
""",
|
||||
'depends': [
|
||||
$depends
|
||||
],
|
||||
'external_dependencies': {
|
||||
'python': [],
|
||||
},
|
||||
'data': [
|
||||
$data
|
||||
],
|
||||
'installable': True,
|
||||
'auto_install': $auto_install,
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
{% extends "header.template" %}
|
||||
{% block body %}
|
||||
{
|
||||
'name': '{{ prototype.name }}',
|
||||
'version': '{{ prototype.version }}',
|
||||
'author': '{{ prototype.author }}',
|
||||
'maintainer': '{{ prototype.maintainer }}',
|
||||
'website': '{{ prototype.website }}',
|
||||
'license': '{{ prototype.licence }}',
|
||||
'category': '{{ prototype.category_id.name }}',
|
||||
'summary': '{{ prototype.summary }}',
|
||||
'description': """
|
||||
{{ prototype.description }}
|
||||
|
||||
* Module exported by the prototype module for version 8.0.
|
||||
* If you have any questions, please contact Savoir-faire Linux \
|
||||
(support@savoirfairelinux.com)
|
||||
""",
|
||||
'depends': [
|
||||
{% for dependency in prototype.dependency_ids -%}
|
||||
'{{ dependency.name }}',
|
||||
{% endfor -%}],
|
||||
'external_dependencies': {
|
||||
'python': [],
|
||||
},
|
||||
'data': [
|
||||
{% for data_file in data_files -%}
|
||||
'{{ data_file }}',
|
||||
{% endfor -%}],
|
||||
'demo': [
|
||||
{% for demo_file in prototype.demo_ids -%}
|
||||
'{{ demo_file.name }}',
|
||||
{% endfor -%}],
|
||||
'installable': True,
|
||||
'auto_install': {{ prototype.auto_install }},
|
||||
'application': {{ prototype.application }},
|
||||
}
|
||||
{% endblock %}
|
|
@ -2,7 +2,7 @@
|
|||
<openerp>
|
||||
<data>
|
||||
|
||||
$data
|
||||
{{ data }}
|
||||
|
||||
</data>
|
||||
</openerp>
|
|
@ -1,8 +0,0 @@
|
|||
<?xml version="1.0"?>
|
||||
<openerp>
|
||||
<data>
|
||||
|
||||
$demo
|
||||
|
||||
</data>
|
||||
</openerp>
|
|
@ -2,7 +2,7 @@
|
|||
<openerp>
|
||||
<data>
|
||||
|
||||
$views
|
||||
{{ demo }}
|
||||
|
||||
</data>
|
||||
</openerp>
|
|
@ -2,8 +2,8 @@
|
|||
##############################################################################
|
||||
#
|
||||
# Odoo, Open Source Management Solution
|
||||
# This module copyright (C) $generation_date $author
|
||||
# (<$website>).
|
||||
# This module copyright (C) {{ export_year }} {{ author }}
|
||||
# ({{ website }}).
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as
|
||||
|
@ -19,4 +19,4 @@
|
|||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
##############################################################################
|
||||
from . import models
|
||||
{% block body %}{% endblock %}
|
|
@ -1,24 +0,0 @@
|
|||
# -*- encoding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# Odoo, Open Source Management Solution
|
||||
# This module copyright (C) $generation_date $author
|
||||
# (<$website>).
|
||||
#
|
||||
# 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 (
|
||||
$models.py
|
||||
)
|
|
@ -0,0 +1,6 @@
|
|||
{% extends "header.template" %}
|
||||
{% block body %}
|
||||
{% for model in models -%}
|
||||
from . import {{ model }}
|
||||
{% endfor %}
|
||||
{% endblock %}
|
|
@ -1,34 +0,0 @@
|
|||
# -*- encoding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# Odoo, Open Source Management Solution
|
||||
# This module copyright (C) $generation_date $author
|
||||
# (<$website>).
|
||||
#
|
||||
# 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.osv import fields, osv
|
||||
|
||||
|
||||
class $model_name(osv.osv):
|
||||
_name = "$model_name"
|
||||
_inherit = "$model_name"
|
||||
_description = "$model_description"
|
||||
|
||||
$model_fields
|
||||
|
||||
_defaults = {
|
||||
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
{% extends "header.template" %}
|
||||
{% block body %}
|
||||
from openerp import models, fields
|
||||
from openerp.tools.translate import _
|
||||
|
||||
|
||||
class {{ name }}(models.Model):
|
||||
_inherit = "{{ inherit }}"
|
||||
{% if description %}_description = "{{ description }}"{% endif %}
|
||||
|
||||
{% for field in fields -%}
|
||||
{{ field.name }} = fields.{{ field.ttype|capitalize }}(
|
||||
string=_("{{ field.field_description }}"),
|
||||
required={{ field.required }},
|
||||
translate={{ field.translate }},
|
||||
readonly={{ field.readonly }},
|
||||
help=_('{{ field.notes }}'),
|
||||
)
|
||||
{% endfor %}
|
||||
|
||||
{% endblock %}
|
|
@ -1 +0,0 @@
|
|||
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
|
|
|
@ -0,0 +1,4 @@
|
|||
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
|
||||
{% for rule in access_rules %}
|
||||
{{ rule.id }},{{ rule.name }},{{ rule.model_id.id }},{{ rule.group_id.id }},{{ rule.perm_write }},{{ rule.perm_write }},{{ rule.perm_create }},{{ rule.perm_unlink }}
|
||||
{% endfor %}
|
|
@ -1,10 +0,0 @@
|
|||
<?xml version="1.0"?>
|
||||
<openerp>
|
||||
<data>
|
||||
|
||||
$groups
|
||||
|
||||
$rules
|
||||
|
||||
</data>
|
||||
</openerp>
|
|
@ -2,9 +2,9 @@
|
|||
<openerp>
|
||||
<data>
|
||||
|
||||
$groups
|
||||
{{ groups }}
|
||||
|
||||
$rules
|
||||
{{ rules }}
|
||||
|
||||
</data>
|
||||
</openerp>
|
|
@ -0,0 +1,24 @@
|
|||
<?xml version="1.0"?>
|
||||
<openerp>
|
||||
<data>
|
||||
{% for menu in menus -%}
|
||||
<record id="action_{{ menu.action.name }}_{{ menu.action.view_type }}_view" model="{{ menu.action.type }}">
|
||||
<field name="name">{{ menu.action.name }}</field>
|
||||
<field name="type">{{ menu.action.type }}</field>
|
||||
<field name="res_model">{{ menu.action.res_model }}</field>
|
||||
<field name="view_type">{{ menu.action.view_type }}</field>
|
||||
<field name="view_mode">{{ menu.action.view_mode }}</field>
|
||||
{% if menu.action.help %}<field name="help" type="html">{{ menu.action.help }}
|
||||
</field>{% endif %}
|
||||
</record>
|
||||
|
||||
<menuitem action="action_{{ menu.action.name }}_{{ menu.action.view_type }}_view"
|
||||
name="{{ menu.name }}"
|
||||
id="menu_action_{{ menu.name|replace('.', '_') }}_{{ menu.action.view_type }}"
|
||||
{% if menu.parent_id %}parent="{{ menu.parent_id.get_xml_id(cr,1,1).values()[0] }}"{% endif %}
|
||||
sequence="{{ menu.sequence }}"
|
||||
groups="{% for group in menu.groups_id %}{{ group.get_xml_id(cr,1,1).values()[0] }},{% endfor %}"
|
||||
/>
|
||||
{% endfor -%}
|
||||
</data>
|
||||
</openerp>
|
|
@ -1,8 +0,0 @@
|
|||
<?xml version="1.0"?>
|
||||
<openerp>
|
||||
<data>
|
||||
|
||||
$views
|
||||
|
||||
</data>
|
||||
</openerp>
|
|
@ -0,0 +1,23 @@
|
|||
<?xml version="1.0"?>
|
||||
<openerp>
|
||||
<data>
|
||||
<!-- TODO: put here a reminder on what to do at the first edition -->
|
||||
|
||||
{% for view in views %}
|
||||
<record id="{{ view.name|replace('.', '_')}}_view" model="ir.ui.model">
|
||||
<field name="name">{{ view.name }}.view</field>
|
||||
<field name="model">{{ view.model }}</field>
|
||||
<field name="view_type">{{ view.type }}</field>
|
||||
<field name="inherit_id" ref="{{ view.inherit_id.get_xml_id(cr,1,1).values()[0] }}"/>
|
||||
<field name="arch" type="xml">
|
||||
{# the arch given by odoo start with an xml tag that
|
||||
will break the xml tree we build.
|
||||
Be careful, custom field have a x_ prefix that has to be
|
||||
removed
|
||||
#}
|
||||
{{ view.arch|replace('<?xml version="1.0"?>', '')|replace('"x_', '"') }}
|
||||
</field>
|
||||
</record>
|
||||
{% endfor %}
|
||||
</data>
|
||||
</openerp>
|
|
@ -1,9 +1,9 @@
|
|||
# -*- encoding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# Odoo, Open Source Management Solution
|
||||
# This module copyright (C) $generation_date $author
|
||||
# (<$website>).
|
||||
# OpenERP, Open Source Management Solution
|
||||
# This module copyright (C) 2010 - 2014 Savoir-faire Linux
|
||||
# (<http://www.savoirfairelinux.com>).
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as
|
||||
|
@ -19,4 +19,10 @@
|
|||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
##############################################################################
|
||||
from . import models
|
||||
from . import test_prototype_module_export
|
||||
from . import test_prototype
|
||||
|
||||
checks = [
|
||||
test_prototype_module_export,
|
||||
test_prototype,
|
||||
]
|
|
@ -0,0 +1,83 @@
|
|||
# -*- encoding: utf-8 -*- #
|
||||
# OpenERP, Open Source Management Solution
|
||||
# This module copyright (C) 2013 Savoir-faire Linux
|
||||
# (<http://www.savoirfairelinux.com>).
|
||||
#
|
||||
# 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 jinja2 import Environment
|
||||
from jinja2.exceptions import TemplateNotFound
|
||||
from openerp.tests import common
|
||||
|
||||
|
||||
class test_prototype(common.TransactionCase):
|
||||
def setUp(self):
|
||||
super(test_prototype, self).setUp()
|
||||
self.main_model = self.env['prototype']
|
||||
self.module_category_model = self.env['ir.module.category']
|
||||
self.module_module_model = self.env['ir.module.module']
|
||||
|
||||
self.prototype = self.main_model.create({
|
||||
'name': 't_name',
|
||||
'category_id': self.module_category_model.browse(1).id,
|
||||
'human_name': 't_human_name',
|
||||
'summary': 't_summary',
|
||||
'description': 't_description',
|
||||
'author': 't_author',
|
||||
'maintainer': 't_maintainer',
|
||||
'website': 't_website',
|
||||
'dependencies': [(6, 0, [1, 2, 3, 4])],
|
||||
})
|
||||
self.api_version = '8.0'
|
||||
|
||||
def test_generate_files_assert_if_no_env(self):
|
||||
self.assertRaises(
|
||||
AssertionError,
|
||||
self.prototype.generate_files
|
||||
)
|
||||
|
||||
def test_generate_files(self):
|
||||
"""Test generate_files returns a tuple."""
|
||||
self.prototype.set_jinja_env(self.api_version)
|
||||
details = self.prototype.generate_files()
|
||||
self.assertIsInstance(details, list)
|
||||
# namedtuples in tuple
|
||||
for file_details in details:
|
||||
self.assertIsInstance(file_details, tuple)
|
||||
self.assertIsInstance(file_details.filename, basestring)
|
||||
self.assertIsInstance(file_details.filecontent, basestring)
|
||||
|
||||
def test_generate_files_raise_templatenotfound_if_not_found(self):
|
||||
self.prototype.set_jinja_env('t_api_version')
|
||||
self.assertRaises(
|
||||
TemplateNotFound,
|
||||
self.prototype.generate_files
|
||||
)
|
||||
|
||||
def test_set_env(self):
|
||||
"""test the jinja2 environment is set."""
|
||||
self.assertIsNone(self.prototype._env)
|
||||
self.prototype.set_jinja_env(self.api_version)
|
||||
self.assertIsInstance(
|
||||
self.prototype._env, Environment
|
||||
)
|
||||
|
||||
def test_friendly_name_return(self):
|
||||
"""Test if the returns match the pattern."""
|
||||
name = 'res.partner'
|
||||
self.assertEqual(
|
||||
self.prototype.friendly_name(name),
|
||||
name.replace('.', '_')
|
||||
)
|
|
@ -0,0 +1,83 @@
|
|||
# -*- encoding: utf-8 -*-
|
||||
# #############################################################################
|
||||
#
|
||||
# OpenERP, Open Source Management Solution
|
||||
# This module copyright (C) 2010 - 2014 Savoir-faire Linux
|
||||
# (<http://www.savoirfairelinux.com>).
|
||||
#
|
||||
# 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.tests import common
|
||||
import zipfile
|
||||
import StringIO
|
||||
|
||||
|
||||
class test_prototype_module_export(common.TransactionCase):
|
||||
def setUp(self):
|
||||
super(test_prototype_module_export, self).setUp()
|
||||
self.main_model = self.env['prototype.module.export']
|
||||
self.prototype_model = self.env['prototype']
|
||||
self.module_category_model = self.env[
|
||||
'ir.module.category'
|
||||
]
|
||||
|
||||
self.prototype = self.prototype_model.create({
|
||||
'name': 't_name',
|
||||
'category_id': self.module_category_model.browse(1).id,
|
||||
'human_name': 't_human_name',
|
||||
'summary': 't_summary',
|
||||
'description': 't_description',
|
||||
'author': 't_author',
|
||||
'maintainer': 't_maintainer',
|
||||
'website': 't_website',
|
||||
})
|
||||
|
||||
self.exporter = self.main_model.create({'name': 't_name'})
|
||||
|
||||
def test_action_export_assert_for_wrong_active_model(self):
|
||||
"""Test if the assertion raises."""
|
||||
exporter = self.main_model.with_context(
|
||||
active_model='t_active_model'
|
||||
).create({})
|
||||
self.assertRaises(
|
||||
AssertionError,
|
||||
exporter.action_export,
|
||||
[exporter.id],
|
||||
)
|
||||
|
||||
def test_action_export_update_wizard(self):
|
||||
"""Test if the wizard is updated during the process."""
|
||||
exporter = self.main_model.with_context(
|
||||
active_model=self.prototype_model._name,
|
||||
active_id=self.prototype.id
|
||||
).create({})
|
||||
exporter.action_export(exporter.id)
|
||||
self.assertEqual(exporter.state, 'get')
|
||||
self.assertEqual(exporter.name, '{}.zip'.format(self.prototype.name))
|
||||
|
||||
def test_zip_files_returns_tuple(self):
|
||||
"""Test the method return of the method that generate the zip file."""
|
||||
file_details = (
|
||||
('test.txt', 'generated'),
|
||||
)
|
||||
ret = self.main_model.zip_files(file_details)
|
||||
self.assertIsInstance(ret, tuple)
|
||||
self.assertIsInstance(
|
||||
ret.zip_file, zipfile.ZipFile
|
||||
)
|
||||
|
||||
self.assertIsInstance(
|
||||
ret.stringIO, StringIO.StringIO
|
||||
)
|
|
@ -7,8 +7,8 @@
|
|||
<field name="model">prototype</field>
|
||||
<field name="arch" type="xml">
|
||||
<tree string="Prototype">
|
||||
<field name="human_name"/>
|
||||
<field name="name"/>
|
||||
<field name="shortdesc"/>
|
||||
<field name="summary"/>
|
||||
</tree>
|
||||
</field>
|
||||
|
@ -19,19 +19,24 @@
|
|||
<field name="model">prototype</field>
|
||||
<field name="arch" type="xml">
|
||||
<form string="Module">
|
||||
<link rel="stylesheet" href="/base/static/src/css/description.css"/>
|
||||
<link rel="stylesheet"
|
||||
href="/base/static/src/css/description.css"/>
|
||||
<sheet>
|
||||
<field name="icon_image" widget="image" class="oe_avatar oe_left"/>
|
||||
<field name="icon_image" widget="image"
|
||||
class="oe_avatar oe_left"/>
|
||||
<div class="oe_title">
|
||||
<h1><field name="summary"/></h1>
|
||||
<h1>
|
||||
<field name="human_name"/>
|
||||
</h1>
|
||||
<div>
|
||||
<button name="%(button_module_export_action)d" string="Export" type="action"/>
|
||||
<button name="%(button_module_export_action)d"
|
||||
string="Export" type="action"/>
|
||||
</div>
|
||||
</div>
|
||||
<group>
|
||||
<group>
|
||||
<field name="name"/>
|
||||
<field name="shortdesc"/>
|
||||
<field name="summary"/>
|
||||
<field name="category_id"/>
|
||||
<field name="version"/>
|
||||
</group>
|
||||
|
@ -40,6 +45,7 @@
|
|||
<field name="website" widget="url"/>
|
||||
<field name="maintainer"/>
|
||||
<field name="auto_install"/>
|
||||
<field name="application"/>
|
||||
</group>
|
||||
</group>
|
||||
<notebook>
|
||||
|
@ -47,31 +53,31 @@
|
|||
<field name="description"/>
|
||||
</page>
|
||||
<page string="Dependencies">
|
||||
<field name="depends"/>
|
||||
<field name="dependency_ids"/>
|
||||
</page>
|
||||
<page string="Data & Demo">
|
||||
<label for="data"/>
|
||||
<field name="data"/>
|
||||
<label for="demo"/>
|
||||
<field name="demo"/>
|
||||
<label for="data_ids"/>
|
||||
<field name="data_ids"/>
|
||||
<label for="demo_ids"/>
|
||||
<field name="demo_ids"/>
|
||||
</page>
|
||||
<page string="Models">
|
||||
<label for="fields"/>
|
||||
<field name="fields" domain="[('state', '=', 'manual')]"/>
|
||||
<page string="Fields">
|
||||
<label for="field_ids"/>
|
||||
<field name="field_ids"/>
|
||||
</page>
|
||||
<page string="Interface">
|
||||
<label for="menu"/>
|
||||
<field name="menu"/>
|
||||
<label for="views"/>
|
||||
<field name="views"/>
|
||||
<label for="menu_ids"/>
|
||||
<field name="menu_ids"/>
|
||||
<label for="view_ids"/>
|
||||
<field name="view_ids"/>
|
||||
</page>
|
||||
<page string="Security">
|
||||
<label for="groups"/>
|
||||
<field name="groups"/>
|
||||
<label for="rights"/>
|
||||
<field name="rights"/>
|
||||
<label for="rules"/>
|
||||
<field name="rules"/>
|
||||
<label for="group_ids"/>
|
||||
<field name="group_ids"/>
|
||||
<label for="right_ids"/>
|
||||
<field name="right_ids"/>
|
||||
<label for="rule_ids"/>
|
||||
<field name="rule_ids"/>
|
||||
</page>
|
||||
</notebook>
|
||||
</sheet>
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
# -*- encoding: utf-8 -*-
|
||||
##############################################################################
|
||||
# #############################################################################
|
||||
#
|
||||
# OpenERP, Open Source Management Solution
|
||||
# This module copyright (C) 2010 - 2014 Savoir-faire Linux
|
||||
|
@ -19,49 +19,103 @@
|
|||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
##############################################################################
|
||||
from openerp.osv import fields,osv
|
||||
from openerp.tools.translate import _
|
||||
import StringIO
|
||||
import base64
|
||||
import zipfile
|
||||
from collections import namedtuple
|
||||
from openerp import fields, models, api
|
||||
|
||||
|
||||
class prototype_module_export(osv.osv_memory):
|
||||
class prototype_module_export(models.TransientModel):
|
||||
_name = "prototype.module.export"
|
||||
|
||||
_columns = {
|
||||
'name': fields.char('File Name', readonly=True),
|
||||
'api_version': fields.selection([('8.0','8.0'),
|
||||
('7.0', '7.0')], 'API version',
|
||||
required=True),
|
||||
'data': fields.binary('File', readonly=True),
|
||||
'state': fields.selection([('choose', 'choose'), # choose version
|
||||
('get', 'get')]) # get module
|
||||
}
|
||||
_defaults = {
|
||||
'state': 'choose',
|
||||
'api_version': '8.0',
|
||||
}
|
||||
name = fields.Char('File Name', readonly=True)
|
||||
# It is implemented in order to manage previous and next versions
|
||||
# of odoo
|
||||
api_version = fields.Selection(
|
||||
[
|
||||
('8.0', '8.0'),
|
||||
# ('7.0', '7.0')
|
||||
],
|
||||
'API version',
|
||||
required=True,
|
||||
default='8.0'
|
||||
)
|
||||
data = fields.Binary('File', readonly=True)
|
||||
state = fields.Selection(
|
||||
[
|
||||
('choose', 'choose'), # choose version
|
||||
('get', 'get') # get module
|
||||
],
|
||||
default='choose'
|
||||
)
|
||||
|
||||
def act_getfile(self, cr, uid, ids, context=None):
|
||||
@api.model
|
||||
def action_export(self, ids):
|
||||
"""
|
||||
Export a zip file containing the module based on the information
|
||||
provided in the prototype, using the templates chosen in the wizard.
|
||||
"""
|
||||
this = self.browse(cr, uid, ids)[0]
|
||||
if isinstance(ids, (int, long)):
|
||||
ids = [ids]
|
||||
wizard = self.browse(ids)
|
||||
|
||||
# TODO: Implement the export logic here
|
||||
filename = 'new'
|
||||
this.name = "%s.%s" % (filename, 'zip')
|
||||
out = 'toto'
|
||||
# /TODO
|
||||
active_model = self._context.get('active_model')
|
||||
|
||||
# checking if the wizard was called by a prototype.
|
||||
assert active_model == 'prototype', \
|
||||
'{} has to be called from a "prototype" , not a "{}"'.format(
|
||||
self, active_model
|
||||
)
|
||||
|
||||
# getting the prototype of the wizard
|
||||
prototype = self.env[active_model].browse(
|
||||
self._context.get('active_id')
|
||||
)
|
||||
|
||||
# setting the jinja environment.
|
||||
# They will help the program to find the template to render the files
|
||||
# with.
|
||||
prototype.set_jinja_env(wizard.api_version)
|
||||
|
||||
# generate_files ask the prototype to investigate the input
|
||||
# and to generate the file templates according to it.
|
||||
# zip_files, in another hand, put all the template files into a package
|
||||
# ready to be saved by the user.
|
||||
zip_details = self.zip_files(prototype.generate_files())
|
||||
|
||||
wizard.write(
|
||||
{
|
||||
'name': '{}.zip'.format(prototype.name),
|
||||
'state': 'get',
|
||||
'data': base64.encodestring(zip_details.stringIO.getvalue())
|
||||
}
|
||||
)
|
||||
|
||||
self.write(cr, uid, ids, {'state': 'get',
|
||||
'data': out,
|
||||
'name':this.name}, context=context)
|
||||
return {
|
||||
'type': 'ir.actions.act_window',
|
||||
'res_model': 'prototype.module.export',
|
||||
'view_mode': 'form',
|
||||
'view_type': 'form',
|
||||
'res_id': this.id,
|
||||
'res_id': wizard.id,
|
||||
'views': [(False, 'form')],
|
||||
'target': 'new',
|
||||
}
|
||||
|
||||
@staticmethod
|
||||
def zip_files(file_details):
|
||||
"""Takes a set of file and zips them.
|
||||
:param file_details: tuple (filename, filecontent)
|
||||
:return: tuple (zip_file, stringIO)
|
||||
"""
|
||||
zip_details = namedtuple('Zip_details', ['zip_file', 'stringIO'])
|
||||
out = StringIO.StringIO()
|
||||
|
||||
with zipfile.ZipFile(out, 'w') as target:
|
||||
for filename, filecontent in file_details:
|
||||
info = zipfile.ZipInfo(filename)
|
||||
info.compress_type = zipfile.ZIP_DEFLATED
|
||||
info.external_attr = 2175008768 # specifies mode 0644
|
||||
target.writestr(info, filecontent)
|
||||
|
||||
return zip_details(zip_file=target, stringIO=out)
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
<p>Here is the exported module: <field name="data" readonly="1" filename="name"/></p>
|
||||
</div>
|
||||
<footer states="choose">
|
||||
<button name="act_getfile" string="Export" type="object" class="oe_highlight"/> or
|
||||
<button name="action_export" string="Export" type="object" class="oe_highlight"/> or
|
||||
<button special="cancel" string="Cancel" type="object" class="oe_link"/>
|
||||
</footer>
|
||||
<footer states="get">
|
||||
|
|
Loading…
Reference in New Issue