def generate_python_init_file(self, cg_module):
        for component, lst_module in self._dct_import_dir.items():
            init_path = os.path.join(component, "__init__.py")
            if not component:
                lst_module = [a for a in self._dct_import_dir.keys() if a]

            lst_module.sort()

            cw = CodeWriter()

            if cg_module.license == "AGPL-3":
                cw.emit("# License AGPL-3.0 or later"
                        " (https://www.gnu.org/licenses/agpl)")
                cw.emit()
            elif cg_module.license == "LGPL-3":
                cw.emit("# License LGPL-3.0 or later"
                        " (https://www.gnu.org/licenses/lgpl)")
                cw.emit()
            else:
                _logger.warning(f"License {cg_module.license} not supported.")

            if component:
                for module in lst_module:
                    cw.emit(f"from . import {module}")
            elif lst_module:
                cw.emit(f"from . import {', '.join(lst_module)}")
            for extra_import in self._dct_extra_module_init_path.get(
                    component, []):
                cw.emit(extra_import)
            self.write_file_str(init_path, cw.render())
    def _set_website_snippet_controller_file(self, module):
        """
        Function to set the module hook file
        :param module:
        :return:
        """

        cw = CodeWriter()
        cw.emit("from odoo import http")
        cw.emit("from odoo.http import request")
        cw.emit("")
        cw.emit("")
        cw.emit("class HelloWorldController(http.Controller):")
        cw.emit("")
        with cw.indent():
            cw.emit(
                f"@http.route(['/{module.name}/helloworld'], type='json', auth=\"public\", website=True,"
            )
        with cw.indent():
            with cw.indent():
                with cw.indent():
                    with cw.indent():
                        cw.emit("methods=['POST', 'GET'], csrf=False)")
        with cw.indent():
            cw.emit("def hello_world(self):")
            with cw.indent():
                cw.emit('return {"hello": "Hello World!"}')

        out = cw.render()

        l_model = out.split("\n")

        file_path = f"{self.code_generator_data.controllers_path}/main.py"

        self.code_generator_data.write_file_lst_content(file_path, l_model)
Example #3
0
    def set_module_python_file(self, module):
        super(CodeGeneratorWriter, self).set_module_python_file(module)
        if not module.theme_website:
            return

        cw = CodeWriter()
        for line in MODEL_HEAD:
            str_line = line.strip()
            cw.emit(str_line)

        cw.emit()
        cw.emit(
            f"class {self._get_class_name(module.name)}(models.AbstractModel):"
        )
        with cw.indent():
            cw.emit("_inherit = 'theme.utils'")
        cw.emit()
        with cw.indent():
            cw.emit(f"def _{module.name}_post_copy(self, mod):")
            with cw.indent():
                cw.emit(
                    "self.disable_view('website_theme_install.customize_modal')"
                )

        file_path = os.path.join(
            self.code_generator_data.models_path, f"{module.name}.py"
        )

        self.code_generator_data.write_file_str(file_path, cw.render())
    def generate(self):
        for file_path, lst_info in self.dct_cb.items():
            cw = CodeWriter()
            lst_header = [b for a in lst_info for b in a[0]]
            # Fix divergence import
            try:
                index_pos = lst_header.index("import odoo.http as http")
                lst_header.pop(index_pos)
                lst_header.append("from odoo import http")
            except:
                pass

            set_header = set(lst_header)
            lst_cb = [a[1] for a in lst_info]
            enable_logger = any([a[3] for a in lst_info])
            lst_inherit_class = list(set([a[2] for a in lst_info]))

            if len(lst_inherit_class) > 1:
                _logger.error(
                    "Cannot support multiple class in the same python file:"
                    f" '{lst_inherit_class}', filepath: '{file_path}'")
                continue
            str_inherit_class = lst_inherit_class[0]

            for line in set_header:
                cw.emit(line)

            if enable_logger:
                cw.emit("import logging")
                cw.emit("_logger = logging.getLogger(__name__)")

            cw.emit(
                "class"
                f" {self._module.name.replace('_', ' ').title().replace(' ', '')}Controller({str_inherit_class}):"
            )

            with cw.indent():
                for cb in lst_cb:
                    cb(self._module, cw)

            out = cw.render()

            l_model = out.split("\n")

            self._code_generator_data.write_file_lst_content(
                file_path, l_model)
Example #5
0
    def _set_website_snippet_static_javascript_file(self, module):
        """
        Function to set the module hook file
        :param module:
        :return:
        """
        cw = CodeWriter()
        cw.cur_indent = 4 * cw.default_dent

        if module.generate_website_snippet_generic_model:
            lst_model_search = (
                module.generate_website_snippet_generic_model.split(";")
            )
            lst_model_id_search = []
            for s_model in lst_model_search:
                model_id = self.env["ir.model"].search(
                    [("model", "=", s_model)]
                )
                if model_id:
                    lst_model_id_search.append(model_id[0])
                else:
                    _logger.warning(f"Model not existing : {s_model}")
            for model_id in lst_model_id_search:
                for field_id in model_id.field_id:
                    if field_id.name not in MAGIC_FIELDS:
                        cw.emit(f'if (data["{field_id.name}"]) {{')
                        with cw.indent():
                            with cw.indent():
                                cw.emit(
                                    f'self.$(".{field_id.name}_value").text(data["{field_id.name}"]);'
                                )
                            cw.emit("}")
        else:
            cw.emit("var data_json = data;")
            cw.emit('var hello = data_json["hello"];')
            cw.emit(f'self.$(".{module.name}_value").text(hello);')

        code = cw.render()

        content = (
            f"odoo.define('{module.name}.animation', function (require)"
            """ {
    'use strict';

    var sAnimation = require('website.content.snippets.animation');

    sAnimation.registry."""
            f"{module.name}"
            """ = sAnimation.Class.extend({
        """
            f"selector: '.o_{module.name}',"
            """

        start: function () {
            var self = this;
            var def = this._rpc({route: '"""
            f"/{module.name}/helloworld"
            """'}).then(function (data) {

                if (data.error) {
                    return;
                }

                if (_.isEmpty(data)) {
                    return;
                }

"""
            + code
            + """    
            });

            return $.when(this._super.apply(this, arguments), def);
        }
    })
});
        """
        )

        file_path = os.path.join(
            "static", "src", "js", f"website.{module.name}.animation.js"
        )
        self.code_generator_data.write_file_str(file_path, content)
def main():
    config = get_config()
    cw = CodeWriter()

    mydoc = minidom.parse(config.file)
    if not mydoc:
        print(f"Error, cannot parse {config.file}")
        sys.exit(1)

    cw.emit("from lxml.builder import E")
    cw.emit("from lxml import etree as ET")
    cw.emit("from code_writer import CodeWriter")
    cw.emit("")
    cw.emit('print(\'<?xml version="1.0" encoding="utf-8"?>\')')
    cw.emit('print("<odoo>")')

    lst_function = []
    comment_for_next_group = None

    for odoo in mydoc.getElementsByTagName("odoo"):
        for ir_view_item in odoo.childNodes:
            if ir_view_item.nodeType == Node.ELEMENT_NODE:
                # Show part of xml
                fct_name = "ma_fonction"
                lst_function.append(fct_name)
                cw.emit(f"def {fct_name}():")
                with cw.indent():
                    cw.emit('"""')
                    for line in transform_string_to_list(
                        ir_view_item.toprettyxml()
                    ):
                        cw.emit(line)
                    cw.emit('"""')
                    # Show comment
                    if comment_for_next_group:
                        cw.emit(
                            "print('<!--"
                            f" {comment_for_next_group.strip()} -->')"
                        )
                        comment_for_next_group = None
                    attributes_root = dict(ir_view_item.attributes.items())

                    lst_out = code_writer_deep_xml(ir_view_item)

                    generate_code = GenerateCode()
                    generate_code.generate_code(lst_out)
                    child_root = generate_code.result

                    code = (
                        "root ="
                        f" E.{ir_view_item.tagName}({str(attributes_root)},"
                        f" {child_root})"
                    )

                    for line in code.split("\n"):
                        cw.emit(line)

                    cw.emit("content = ET.tostring(root, pretty_print=True)")
                    cw.emit()
                    cw.emit("cw = CodeWriter()")
                    cw.emit(
                        'for line in content.decode("utf-8").split("\\n"):'
                    )
                    with cw.indent():
                        cw.emit("with cw.indent():")
                        with cw.indent():
                            cw.emit("cw.emit(line)")
                    cw.emit("print(cw.render())")
                cw.emit(f"{fct_name}()")
            elif ir_view_item.nodeType == Node.COMMENT_NODE:
                comment_for_next_group = ir_view_item.data
            else:
                # print(ir_view_item)
                pass

    cw.emit('print("</odoo>")')

    output = cw.render()
    if config.output:
        with open(config.output, "w") as file:
            file.write(output)
    else:
        print(output)
Example #7
0
    def _set_hook_file(self, module):
        """
        Function to set the module hook file
        :param module:
        :return:
        """

        cw = CodeWriter()
        lst_keep_f2exports = []

        for line in MODEL_SUPERUSER_HEAD:
            str_line = line.strip()
            cw.emit(str_line)

        is_generator_demo = module.name == "code_generator_demo"

        # Add constant
        if module.hook_constant_code:
            if module.enable_template_code_generator_demo:
                cw.emit(
                    "# TODO HUMAN: change my module_name to create a specific demo functionality"
                )
            for line in module.hook_constant_code.split("\n"):
                cw.emit(line)

        def _add_hook(
            cw,
            hook_show,
            hook_code,
            hook_feature_gen_conf,
            post_init_hook_feature_code_generator,
            uninstall_hook_feature_code_generator,
            method_name,
            has_second_arg,
        ):
            if hook_show:
                cw.emit()
                cw.emit()
                if has_second_arg:
                    cw.emit(f"def {method_name}(cr, e):")
                else:
                    cw.emit(f"def {method_name}(cr):")
                with cw.indent():
                    for line in hook_code.split("\n"):
                        cw.emit(line)
                    if hook_feature_gen_conf:
                        with cw.indent():
                            cw.emit("# General configuration")
                            with cw.block(before="values =", delim=("{", "}")):
                                pass

                            cw.emit(
                                "event_config = env['res.config.settings'].sudo().create(values)"
                            )
                            cw.emit("event_config.execute()")
                    if post_init_hook_feature_code_generator:
                        with cw.indent():
                            cw.emit()
                            cw.emit("# The path of the actual file")
                            if module.template_module_path_generated_extension:
                                cw.emit(
                                    "path_module_generate = os.path.normpath(os.path.join(os.path.dirname"
                                    f"(__file__), '..', {module.template_module_path_generated_extension}))"
                                )
                            else:
                                cw.emit(
                                    "# path_module_generate = os.path.normpath(os.path.join(os.path.dirname"
                                    "(__file__), '..'))")
                            cw.emit()
                            cw.emit(
                                'short_name = MODULE_NAME.replace("_", " ").title()'
                            )
                            cw.emit()
                            cw.emit("# Add code generator")
                            cw.emit("value = {")
                            with cw.indent():
                                cw.emit('"shortdesc": short_name,')
                                cw.emit('"name": MODULE_NAME,')
                                cw.emit('"license": "AGPL-3",')
                                cw.emit('"author": "TechnoLibre",')
                                cw.emit('"website": "https://technolibre.ca",')
                                cw.emit('"application": True,')
                                # with cw.block(before='"depends" :', delim=('[', '],')):
                                #     cw.emit('"code_generator",')
                                #     cw.emit('"code_generator_hook",')
                                cw.emit('"enable_sync_code": True,')
                                if module.template_module_path_generated_extension:
                                    cw.emit(
                                        '"path_sync_code": path_module_generate,'
                                    )
                                else:
                                    cw.emit(
                                        '# "path_sync_code": path_module_generate,'
                                    )
                            cw.emit("}")
                            cw.emit()
                            cw.emit(
                                "# TODO HUMAN: enable your functionality to generate"
                            )
                            enable_template_code_generator_demo = (
                                module.enable_template_code_generator_demo
                                if module.name == "code_generator_demo" else
                                False)
                            if module.enable_template_code_generator_demo:
                                cw.emit(
                                    'value["enable_template_code_generator_demo"] = '
                                    f"{enable_template_code_generator_demo}")
                                cw.emit('value["template_model_name"] = ""')
                                cw.emit(
                                    'value["enable_template_wizard_view"] = False'
                                )
                                cw.emit(
                                    'value["enable_template_website_snippet_view"] = '
                                    f"{module.enable_template_website_snippet_view}"
                                )
                            elif module.enable_template_website_snippet_view:
                                cw.emit(
                                    'value["enable_generate_website_snippet"] = True'
                                )
                                cw.emit(
                                    'value["enable_generate_website_snippet_javascript"] = True'
                                )
                                cw.emit(
                                    'value["generate_website_snippet_type"] = "effect"'
                                    "  # content,effect,feature,structure")
                            cw.emit(
                                f'value["enable_sync_template"] = {module.enable_sync_template}'
                            )
                            cw.emit(f'value["ignore_fields"] = ""')
                            cw.emit(
                                f'value["post_init_hook_show"] = {module.enable_template_code_generator_demo}'
                            )
                            cw.emit(
                                f'value["uninstall_hook_show"] = {module.enable_template_code_generator_demo}'
                            )
                            cw.emit(
                                'value["post_init_hook_feature_code_generator"] = '
                                f"{module.enable_template_code_generator_demo}"
                            )
                            cw.emit(
                                'value["uninstall_hook_feature_code_generator"] = '
                                f"{module.enable_template_code_generator_demo}"
                            )
                            cw.emit()
                            if module.enable_template_code_generator_demo:
                                cw.emit("new_module_name = MODULE_NAME")
                                cw.emit(
                                    'if MODULE_NAME != "code_generator_demo" and "code_generator_" in MODULE_NAME:'
                                )
                                with cw.indent():
                                    cw.emit(
                                        'if "code_generator_template" in MODULE_NAME:'
                                    )
                                    with cw.indent():
                                        cw.emit(
                                            'if value["enable_template_code_generator_demo"]:'
                                        )
                                        with cw.indent():
                                            cw.emit(
                                                'new_module_name = f"code_generator_{MODULE_NAME['
                                                "len('code_generator_template_'):]}\""
                                            )
                                        cw.emit("else:")
                                        with cw.indent():
                                            cw.emit(
                                                'new_module_name = MODULE_NAME[len("code_generator_template_"):]'
                                            )
                                    cw.emit("else:")
                                    with cw.indent():
                                        cw.emit(
                                            'new_module_name = MODULE_NAME[len("code_generator_"):]'
                                        )
                                    cw.emit(
                                        'value["template_module_name"] = new_module_name'
                                    )
                                cw.emit(
                                    'value["hook_constant_code"] = f\'MODULE_NAME = "{new_module_name}"\''
                                )
                            else:
                                cw.emit(
                                    'value["hook_constant_code"] = f\'MODULE_NAME = "{MODULE_NAME}"\''
                                )
                            cw.emit()
                            cw.emit(
                                'code_generator_id = env["code.generator.module"].create(value)'
                            )
                            cw.emit()
                            if module.dependencies_template_id:
                                cw.emit("# Add dependencies")
                                cw.emit(
                                    "# TODO HUMAN: update your dependencies")
                                with cw.block(before="lst_depend =",
                                              delim=("[", "]")):
                                    for depend in module.dependencies_template_id:
                                        cw.emit(f'"{depend.depend_id.name}",')
                                cw.emit(
                                    'lst_dependencies = env["ir.module.module"]'
                                    '.search([("name", "in", lst_depend)])')
                                cw.emit("for depend in lst_dependencies:")
                                with cw.indent():
                                    with cw.block(before="value =",
                                                  delim=("{", "}")):
                                        cw.emit(
                                            '"module_id": code_generator_id.id,'
                                        )
                                        cw.emit('"depend_id": depend.id,')
                                        cw.emit('"name": depend.display_name,')
                                    cw.emit(
                                        'env["code.generator.module.dependency"].create(value)'
                                    )
                                cw.emit()
                                if is_generator_demo:
                                    with cw.block(before="lst_depend =",
                                                  delim=("[", "]")):
                                        for depend in module.dependencies_template_id:
                                            cw.emit(
                                                f'"{depend.depend_id.name}",')
                                    cw.emit(
                                        'lst_dependencies = env["ir.module.module"]'
                                        '.search([("name", "in", lst_depend)])'
                                    )
                                    cw.emit("for depend in lst_dependencies:")
                                    with cw.indent():
                                        with cw.block(before="value =",
                                                      delim=("{", "}")):
                                            cw.emit(
                                                '"module_id": code_generator_id.id,'
                                            )
                                            cw.emit('"depend_id": depend.id,')
                                            cw.emit(
                                                '"name": depend.display_name,')
                                        cw.emit(
                                            'env["code.generator.module.template.dependency"].create(value)'
                                        )
                                    cw.emit()

                            if module.template_model_name:
                                lst_model = module.template_model_name.split(
                                    ";")
                                len_model = len(lst_model)
                                i = -1
                                for model_model in lst_model:
                                    i += 1
                                    model_name = model_model.replace(".", "_")
                                    title_model_model = model_name.replace(
                                        "_", " ").title()
                                    variable_model_model = f"model_{model_name}"
                                    cw.emit(f"# Add {title_model_model}")
                                    cw.emit("value = {")
                                    with cw.indent():
                                        cw.emit(f'"name": "{model_name}",')
                                        cw.emit(f'"model": "{model_model}",')
                                        cw.emit(
                                            '"m2o_module": code_generator_id.id,'
                                        )
                                        cw.emit('"rec_name": None,')
                                        cw.emit('"nomenclator": True,')
                                    cw.emit("}")
                                    cw.emit(
                                        f'{variable_model_model} = env["ir.model"].create(value)'
                                    )
                                    cw.emit("")
                                    self._write_generated_template(
                                        module, model_model, cw)
                                    cw.emit("##### Begin Field")
                                    if module.enable_sync_template:
                                        module_file_sync = ExtractorModule(
                                            module, model_model)
                                        self._write_sync_template(
                                            module,
                                            model_model,
                                            cw,
                                            variable_model_model,
                                            lst_keep_f2exports,
                                            module_file_sync,
                                        )
                                    else:
                                        cw.emit("value_field_boolean = {")
                                        with cw.indent():
                                            cw.emit('"name": "field_boolean",')
                                            cw.emit('"model": "demo.model",')
                                            cw.emit(
                                                '"field_description": "field description",'
                                            )
                                            cw.emit('"ttype": "boolean",')
                                            cw.emit(
                                                f'"model_id": {variable_model_model}.id,'
                                            )
                                        cw.emit("}")
                                        cw.emit(
                                            'env["ir.model.fields"].create(value_field_boolean)'
                                        )
                                        cw.emit()
                                        cw.emit("# FIELD TYPE Many2one")
                                        cw.emit("#value_field_many2one = {")
                                        with cw.indent():
                                            cw.emit(
                                                '#"name": "field_many2one",')
                                            cw.emit('#"model": "demo.model",')
                                            cw.emit(
                                                '#"field_description": "field description",'
                                            )
                                            cw.emit('#"ttype": "many2one",')
                                            cw.emit(
                                                '#"comodel_name": "model.name",'
                                            )
                                            cw.emit(
                                                '#"relation": "model.name",')
                                            cw.emit(
                                                f'#"model_id": {variable_model_model}.id,'
                                            )
                                        cw.emit("#}")
                                        cw.emit(
                                            '#env["ir.model.fields"].create(value_field_many2one)'
                                        )
                                        cw.emit("")
                                        cw.emit("# Hack to solve field name")
                                        cw.emit(
                                            "field_x_name = env[\"ir.model.fields\"].search([('model_id', '=', "
                                            f"{variable_model_model}.id), ('name', '=', 'x_name')])"
                                        )
                                        cw.emit('field_x_name.name = "name"')
                                        cw.emit(
                                            f'{variable_model_model}.rec_name = "name"'
                                        )
                                        cw.emit("")
                                    if i >= len_model - 1 and lst_keep_f2exports:
                                        cw.emit("")
                                        cw.emit(
                                            "# Added one2many field, many2many need to be creat before add "
                                            "one2many")
                                        for (
                                                field_id,
                                                model_model,
                                                variable_model_model,
                                        ) in lst_keep_f2exports:
                                            # Finish to print one2many move at the end
                                            self._write_sync_template(
                                                module,
                                                model_model,
                                                cw,
                                                variable_model_model,
                                                lst_keep_f2exports,
                                                None,
                                                lst_force_f2exports=[field_id],
                                            )
                                    cw.emit("##### End Field")
                                    cw.emit()
                                    # TODO add data nomenclator, research data from model
                                    # TODO By default, no data will be nomenclator
                                    # cw.emit("# Add data nomenclator")
                                    # cw.emit("value = {")
                                    # with cw.indent():
                                    #     cw.emit("\"field_boolean\": True,")
                                    #     cw.emit("\"name\": \"demo\",")
                                    # cw.emit("}")
                                    # cw.emit(f"env[\"{model_model}\"].create(value)")
                                    # cw.emit()
                            if module.enable_template_wizard_view:
                                cw.emit("# Generate view")
                                cw.emit(
                                    "wizard_view = env['code.generator.generate.views.wizard'].create({"
                                )
                                with cw.indent():
                                    cw.emit(
                                        "'code_generator_id': code_generator_id.id,"
                                    )
                                    cw.emit("'enable_generate_all': False,")
                                    if module.enable_generate_portal:
                                        cw.emit(
                                            f"'enable_generate_portal': {module.enable_generate_portal},"
                                        )
                                cw.emit("})")
                                cw.emit("")
                                cw.emit("wizard_view.button_generate_views()")
                                cw.emit()
                            cw.emit("# Generate module")
                            cw.emit("value = {")
                            with cw.indent():
                                cw.emit(
                                    '"code_generator_ids": code_generator_id.ids'
                                )
                            cw.emit("}")
                            cw.emit(
                                'code_generator_writer = env["code.generator.writer"].create(value)'
                            )
                    if uninstall_hook_feature_code_generator:
                        with cw.indent():
                            cw.emit(
                                'code_generator_id = env["code.generator.module"].search([("name", "=", MODULE_NAME)])'
                            )
                            cw.emit("if code_generator_id:")
                            with cw.indent():
                                cw.emit("code_generator_id.unlink()")

        _add_hook(
            cw,
            module.pre_init_hook_show,
            module.pre_init_hook_code,
            module.pre_init_hook_feature_general_conf,
            False,
            False,
            "pre_init_hook",
            False,
        )
        _add_hook(
            cw,
            module.post_init_hook_show,
            module.post_init_hook_code,
            module.post_init_hook_feature_general_conf,
            module.post_init_hook_feature_code_generator,
            False,
            "post_init_hook",
            True,
        )
        _add_hook(
            cw,
            module.uninstall_hook_show,
            module.uninstall_hook_code,
            module.uninstall_hook_feature_general_conf,
            False,
            module.post_init_hook_feature_code_generator,
            "uninstall_hook",
            True,
        )

        hook_file_path = "hooks.py"

        self.code_generator_data.write_file_str(hook_file_path, cw.render())
    def _set_website_leaflet_controller_file(self, module):
        """
        Function to set the module hook file
        :param module:
        :return:
        """

        lst_fields = []
        lst_model = []
        for a in module.o2m_models:
            active_id = a.field_id.filtered(lambda key: key.name == "active")
            open_popup_id = a.field_id.filtered(
                lambda key: key.name == "open_popup")
            html_text_id = a.field_id.filtered(
                lambda key: key.name == "html_text")
            fields_id = a.field_id.filtered(
                lambda key: "geo_" in key.ttype).sorted(key="name")
            if fields_id:
                lst_model.append(a)
                lst_fields = [b for b in fields_id]
                # Find right model
                break
        if not len(lst_fields):
            return
        # Cannot support multiple model with field geo
        assert len(lst_model) == 1
        model_id = lst_model[0]

        cw = CodeWriter()
        cw.emit("from odoo import http")
        cw.emit("from operator import attrgetter")
        cw.emit("import json")
        cw.emit("import numpy")
        cw.emit("from pyproj import Transformer")
        cw.emit("from odoo.http import request")
        cw.emit("from collections import defaultdict")
        cw.emit("")
        cw.emit("")
        cw.emit("class MapFeatureController(http.Controller):")
        cw.emit("")
        with cw.indent():
            cw.emit(
                f"@http.route(['/{module.name}/map/config'], type='json', auth=\"public\", website=True,"
            )
        with cw.indent():
            with cw.indent():
                with cw.indent():
                    with cw.indent():
                        cw.emit("methods=['POST', 'GET'], csrf=False)")
        with cw.indent():
            cw.emit("def map_detail(self):")
            with cw.indent():
                cw.emit('name = "test"')
                cw.emit("lat = 45.587134")
                cw.emit("lng = -73.733368")
                cw.emit("enable = True")
                cw.emit("size_width = 800")
                cw.emit("size_height = 600")
                cw.emit('provider = "CartoDB"')
                cw.emit("zoom = 13")
                cw.emit("categories = {}")
                # cw.emit(f"for i in http.request.env['{model_id.model}'].search([[\"active\", \"=\", True]]):")
                # with cw.indent():
                #     cw.emit("categories[i.id] = {")
                #     with cw.indent():
                #         cw.emit("\"name\": i.name,")
                #         cw.emit("\"description\": i.description,")
                # with cw.indent():
                #     cw.emit("}")
            with cw.indent():
                cw.emit("features = defaultdict(list)")
                cw.emit(
                    'transformer = Transformer.from_crs("epsg:3857", "epsg:4326")'
                )
            cw.emit("")
            with cw.indent():
                str_search = ""
                if active_id:
                    str_search = '("active", "=", True)'
                cw.emit(
                    f'map_feature_ids = request.env["{model_id.model}"].sudo().search([{str_search}])'
                )
                cw.emit("for feature in map_feature_ids:")
                with cw.indent():
                    cw.emit("value = {}")
                    cw.emit("# Help robot, ignore this")
                    cw.emit("if False:")
                    with cw.indent():
                        cw.emit("pass")
                    for field_id in lst_fields:
                        cw.emit(f'elif feature.type == "{field_id.name}":')
                        with cw.indent():
                            cw.emit(f"if not feature.{field_id.name}:")
                            with cw.indent():
                                cw.emit(f"continue")
                            if field_id.ttype == "geo_polygon":
                                cw.emit(
                                    f"xy = feature.{field_id.name}.exterior.coords.xy"
                                )
                            else:
                                cw.emit(f"xy = feature.{field_id.name}.xy")
            cw.emit("")
            with cw.indent():
                with cw.indent():
                    cw.emit("coord_UTM = numpy.column_stack(xy).tolist()")
                    cw.emit(
                        "coord_lat_long = [transformer.transform(*i) for i in coord_UTM]"
                    )
            # cw.emit("")
            with cw.indent():
                # with cw.indent():
                #     cw.emit("if feature.category_id:")
                #     with cw.indent():
                #         cw.emit("value[\"category_id\"] = feature.category_id.id")
                if open_popup_id:
                    with cw.indent():
                        cw.emit("if feature.open_popup:")
                        with cw.indent():
                            cw.emit('value["open_popup"] = feature.open_popup')
                if html_text_id:
                    with cw.indent():
                        cw.emit("if feature.html_text:")
                        with cw.indent():
                            cw.emit('value["html_popup"] = feature.html_text')
            cw.emit("")
            with cw.indent():
                with cw.indent():
                    cw.emit("# Help robot, ignore this")
                    cw.emit("if False:")
                    with cw.indent():
                        cw.emit("pass")
                for field_id in lst_fields:
                    with cw.indent():
                        cw.emit(f'elif feature.type == "{field_id.name}":')
                        with cw.indent():
                            if field_id.ttype == "geo_point":
                                cw.emit(
                                    'value["coordinates"] = coord_lat_long[0]')
                                cw.emit('features["markers"].append(value)')
                            else:
                                cw.emit(
                                    'value["coordinates"] = coord_lat_long')
                                if field_id.ttype == "geo_polygon":
                                    cw.emit('features["areas"].append(value)')
                                elif field_id.ttype == "geo_line":
                                    cw.emit('features["lines"].append(value)')
            cw.emit("")
        with cw.indent():
            with cw.indent():
                cw.emit("return {")
                with cw.indent():
                    cw.emit('"name": name,')
                    cw.emit('"lat": lat,')
                    cw.emit('"lng": lng,')
                    cw.emit('"enable": enable,')
                    cw.emit('"size_width": size_width,')
                    cw.emit('"size_height": size_height,')
                    cw.emit('"zoom": zoom,')
                    cw.emit('"provider": provider,')
                    cw.emit('"features": features,')
                    cw.emit('"categories": categories,')
            with cw.indent():
                cw.emit("}")

        out = cw.render()

        l_model = out.split("\n")

        file_path = f"{self.code_generator_data.controllers_path}/main.py"

        self.code_generator_data.write_file_lst_content(file_path, l_model)
    def set_module_css_file(self, module):
        super(CodeGeneratorWriter, self).set_module_css_file(module)
        if not module.theme_website:
            return

        # _variables.scss files
        cw = CodeWriter(default_width=80)
        # cw.emit(f"$primary: {module.theme_website_primary_color} !default;")
        # cw.emit(f"$secondary: {module.theme_website_secondary_color} !default;")
        # cw.emit(f"$body-color: {module.theme_website_body_color} !default;")
        file_path = os.path.join(self.code_generator_data.css_path, "_variables.scss")
        self.code_generator_data.write_file_str(file_path, cw.render())

        # custom.scss files
        cw = CodeWriter()
        file_path = os.path.join(self.code_generator_data.css_path, "custom.scss")
        self.code_generator_data.write_file_str(file_path, cw.render())

        # primary_variables.scss files
        cw = CodeWriter()
        file_path = os.path.join(self.code_generator_data.css_path, "primary_variables.scss")
        cw.emit("$o-theme-layout: 'full';")
        cw.emit("//$o-theme-navbar-height: 300px;")
        cw.emit()
        cw.emit("//" + "-" * 78)
        cw.emit_wrapped_text(
            "Colors",
            prefix="// ",
            indent_after_first=True,
        )
        cw.emit("//" + "-" * 78)
        cw.emit()
        cw.emit("// Extend default color palettes with website-related colors")
        cw.emit("$-palettes: ();")
        cw.emit("@each $palette in $o-color-palettes {")
        with cw.indent():
            cw.emit("$-palettes: append($-palettes, map-merge((")
            with cw.indent():
                cw.emit(f"'body': {module.theme_website_body_color},")
                cw.emit(f"'menu': {module.theme_website_menu_color},")
                cw.emit(f"'footer': {module.theme_website_footer_color},")
                cw.emit(f"'text': {module.theme_website_text_color},")
                cw.emit(f"'alpha': {module.theme_website_primary_color},")
                cw.emit(f"'beta': {module.theme_website_secondary_color},")
                cw.emit(f"'gamma': {module.theme_website_extra_1_color},")
                cw.emit(f"'delta': {module.theme_website_extra_2_color},")
                cw.emit(f"'epsilon': {module.theme_website_extra_3_color},")
                cw.emit(f"'h1': null, // Default to text")
                cw.emit(f"'h2': null, // Default to h1")
                cw.emit(f"'h3': null, // Default to h2")
                cw.emit(f"'h4': null, // Default to h3")
                cw.emit(f"'h5': null, // Default to h4")
                cw.emit(f"'h6': null, // Default to h5")
            cw.emit("), $palette));")
        cw.emit("}")
        cw.emit()
        cw.emit("$o-color-palettes: $-palettes;")
        cw.emit()
        cw.emit("$o-theme-color-palettes: ();")
        cw.emit("@each $-palette in $-palettes {")
        with cw.indent():
            cw.emit(
                "$o-theme-color-palettes: append($o-theme-color-palettes, map-merge($-palette, ("
            )
            with cw.indent():
                cw.emit("'primary': map-get($-palette, 'alpha'),")
                cw.emit("'secondary': map-get($-palette, 'beta'),")
            cw.emit(")));")
        cw.emit("}")
        cw.emit()
        cw.emit("// By default, all user color palette values are null. Each null value is")
        cw.emit("// automatically replaced with corresponding color of chosen color palette.")
        cw.emit("$o-user-color-palette: () !default;")
        cw.emit()
        cw.emit("// By default, all user theme color palette values are null. Each null value")
        cw.emit("// is automatically replaced with corresponding color of chosen theme color")
        cw.emit("// palette.")
        cw.emit("$o-user-theme-color-palette: () !default;")
        cw.emit()
        cw.emit("//" + "-" * 78)
        cw.emit_wrapped_text(
            "Fonts",
            prefix="// ",
            indent_after_first=True,
        )
        cw.emit("//" + "-" * 78)
        cw.emit()
        cw.emit("$o-theme-fonts: (")
        with cw.indent():
            cw.emit(
                '(-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Noto, "Helvetica Neue", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"), // This is BS default'
            )
            cw.emit("('Open Sans', sans-serif),")
            cw.emit("('Source Sans Pro', sans-serif),")
            cw.emit("('Raleway', sans-serif),")
            cw.emit("('Noto Serif', serif),")
            cw.emit("('Arvo', Times, serif),")
        cw.emit(") !default;")
        cw.emit("$o-theme-font-urls: (")
        with cw.indent():
            cw.emit("null,")
            cw.emit("'Open+Sans:400,400i,700,700i',")
            cw.emit("'Source+Sans+Pro:400,400i,700,700i',")
            cw.emit("'Raleway:400,400i,700,700i',")
            cw.emit("'Noto+Serif:400,400i,700,700i',")
            cw.emit("'Arvo:400,400i,700,700i',")
        cw.emit(") !default;")
        cw.emit("$o-theme-font-names: (")
        with cw.indent():
            cw.emit("'Bootstrap',")
            cw.emit("'Open Sans',")
            cw.emit("'Source Sans Pro',")
            cw.emit("'Raleway',")
            cw.emit("'Noto Serif',")
            cw.emit("'Arvo',")
        cw.emit(") !default;")
        cw.emit("$o-theme-font-number: 1 !default;")
        cw.emit("$o-theme-headings-font-number: 1 !default;")
        cw.emit("$o-theme-buttons-font-number: 1 !default;")
        cw.emit("$o-theme-navbar-font-number: 1 !default;")
        self.code_generator_data.write_file_str(file_path, cw.render())
Example #10
0
    def _set_portal_controller_file(self, module):
        """
        Function to set the module hook file
        :param module:
        :return:
        """

        cw = CodeWriter()
        cw.emit("from collections import OrderedDict")
        cw.emit("from operator import itemgetter")
        cw.emit("")
        cw.emit("from odoo import http, _")
        cw.emit("from odoo.exceptions import AccessError, MissingError")
        cw.emit("from odoo.http import request")
        cw.emit(
            "from odoo.addons.portal.controllers.portal import CustomerPortal, pager as portal_pager"
        )
        cw.emit("from odoo.tools import groupby as groupbyelem")
        cw.emit("")
        cw.emit("from odoo.osv.expression import OR")
        cw.emit("")
        cw.emit("")
        cw.emit("class CustomerPortal(CustomerPortal):")
        cw.emit("")
        with cw.indent():
            cw.emit("def _prepare_portal_layout_values(self):")
            with cw.indent():
                cw.emit("values = super(CustomerPortal, self)._prepare_portal_layout_values()")
                for model in module.o2m_models:
                    cw.emit(
                        f"values['{self._fmt_underscores(model.model)}_count'] = request.env['{model.model}']."
                        f"search_count([])"
                    )
                cw.emit("return values")
        cw.emit("")

        for model in module.o2m_models:
            has_group_by = False
            with cw.indent():
                cw.emit("# ------------------------------------------------------------")
                cw.emit(f"# My {self._fmt_title(model.model)}")
                cw.emit("# ------------------------------------------------------------")
                cw.emit(
                    f"def _{self._fmt_underscores(model.model)}_get_page_view_values(self, {self._fmt_underscores(model.model)}, "
                    f"access_token, **kwargs):"
                )
                with cw.indent():
                    cw.emit("values = {")
                    with cw.indent():
                        cw.emit(f"'page_name': '{self._fmt_underscores(model.model)}',")
                        cw.emit(
                            f"'{self._fmt_underscores(model.model)}': {self._fmt_underscores(model.model)},"
                        )
                        # MATHBEN ADDED
                        cw.emit("'user': request.env.user")
                with cw.indent():
                    cw.emit("}")
                    cw.emit(
                        f"return self._get_page_view_values({self._fmt_underscores(model.model)}, access_token, values, "
                        f"'my_{self._fmt_underscores(model.model)}s_history', False, **kwargs)"
                    )
            cw.emit("")
            with cw.indent():
                cw.emit(
                    f"@http.route(['/my/{self._fmt_underscores(model.model)}s', "
                    f"'/my/{self._fmt_underscores(model.model)}s/page/<int:page>'], type='http', auth=\"user\", "
                    f"website=True)"
                )
                # cw.emit(f"def portal_my_{_fmt_underscores(model.model)}s(self, page=1, date_begin=None, date_end=None, "
                #         f"sortby=None, **kw):")
                # MATHBEN ADDED
                cw.emit(
                    f"def portal_my_{self._fmt_underscores(model.model)}s(self, page=1, date_begin=None, date_end=None, "
                    f"sortby=None, filterby=None, search=None, search_in='content', **kw):"
                )
                # MATHBEN NEED THIS FOR NEXT MODEL IF ONE DEPEND TO ANOTHER ONE
                # f"sortby=None, filterby=None, search=None, search_in='content', groupby='project', **kw):")
                with cw.indent():
                    cw.emit("values = self._prepare_portal_layout_values()")
                    cw.emit(f"{self._fmt_camel(model.model)} = request.env['{model.model}']")
                    cw.emit("domain = []")
            cw.emit("")
            with cw.indent():
                with cw.indent():
                    cw.emit("searchbar_sortings = {")
                    with cw.indent():
                        cw.emit("'date': {'label': _('Newest'), 'order': 'create_date desc'},")
                        cw.emit("'name': {'label': _('Name'), 'order': 'name'},")
                        # MATHBEN NEEDED BY TASK
                        # cw.emit("'name': {'label': _('Title'), 'order': 'name'},")
                        # cw.emit("'stage': {'label': _('Stage'), 'order': 'stage_id'},")
                        # cw.emit("'update': {'label': _('Last Stage Update'), 'order': 'date_last_stage_update desc'},")
                with cw.indent():
                    cw.emit("}")
                    cw.emit("searchbar_filters = {")
                    with cw.indent():
                        cw.emit("'all': {'label': _('All'), 'domain': []},")
                with cw.indent():
                    cw.emit("}")
                    cw.emit("searchbar_inputs = {")
                    # MATHBEN REMOVED, WAS in task
                    # with cw.indent():
                    #     cw.emit(
                    #         "'content': {'input': 'content', 'label': _('Search <span class=\"nolabel\"> (in Content)</span>')},")
                    #     cw.emit("'message': {'input': 'message', 'label': _('Search in Messages')},")
                    #     cw.emit("'customer': {'input': 'customer', 'label': _('Search in Customer')},")
                    #     cw.emit("'stage': {'input': 'stage', 'label': _('Search in Stages')},")
                    #     cw.emit("'all': {'input': 'all', 'label': _('Search in All')},")
                with cw.indent():
                    cw.emit("}")
                    cw.emit("searchbar_groupby = {")
                    # MATHBEN REMOVED, WAS in task
                    # with cw.indent():
                    #     cw.emit("'none': {'input': 'none', 'label': _('None')},")
                    #     cw.emit("'project': {'input': 'project', 'label': _('Project')},")
                with cw.indent():
                    cw.emit("}")
            cw.emit("")
            with cw.indent():
                with cw.indent():
                    pass
                    # MATHBEN WAS FOR TASK NOT USE IN PROJECT
                    # cw.emit("# extends filterby criteria with project the customer has access to")
                    # cw.emit("projects = request.env['project.project'].search([])")
                    # cw.emit("for project in projects:")
                    # with cw.indent():
                    #     cw.emit("searchbar_filters.update({")
                    #     with cw.indent():
                    #         cw.emit(
                    #             "str(project.id): {'label': project.name, 'domain': [('project_id', '=', project.id)]}")
                    # with cw.indent():
                    #     cw.emit("})")
            pass
            # cw.emit("")
            # with cw.indent():
            #     with cw.indent():
            #         cw.emit("# extends filterby criteria with project (criteria name is the project id)")
            #         cw.emit("# Note: portal users can't view projects they don't follow")
            #         cw.emit(
            #             "project_groups = request.env['project.task'].read_group([('project_id', 'not in', projects.ids)], "
            #             "['project_id'], ['project_id'])")
            #     with cw.indent():
            #         cw.emit("for group in project_groups:")
            #         with cw.indent():
            #             cw.emit("proj_id = group['project_id'][0] if group['project_id'] else False")
            #             cw.emit("proj_name = group['project_id'][1] if group['project_id'] else _('Others')")
            #             cw.emit("searchbar_filters.update({")
            #             with cw.indent():
            #                 cw.emit("str(proj_id): {'label': proj_name, 'domain': [('project_id', '=', proj_id)]}")
            #         with cw.indent():
            #             cw.emit("})")
            # cw.emit("")
            with cw.indent():
                with cw.indent():
                    cw.emit("# default sort by value")
                    cw.emit("if not sortby:")
                    with cw.indent():
                        cw.emit("sortby = 'date'")
                with cw.indent():
                    cw.emit("order = searchbar_sortings[sortby]['order']")
                    cw.emit("# default filter by value")
                    cw.emit("if not filterby:")
                    with cw.indent():
                        cw.emit("filterby = 'all'")
                with cw.indent():
                    cw.emit("domain = searchbar_filters[filterby]['domain']")
            cw.emit("")
            with cw.indent():
                with cw.indent():
                    cw.emit("# search")
                    cw.emit("if search and search_in:")
                    with cw.indent():
                        cw.emit("search_domain = []")
                    pass
                    # MATHBEN REMOVE IT, NOT USED IN PROJECT
                    #     cw.emit("if search_in in ('content', 'all'):")
                    #     with cw.indent():
                    #         cw.emit(
                    #             "search_domain = OR([search_domain, ['|', ('name', 'ilike', search), ('description', 'ilike', search)]])")
                    # with cw.indent():
                    #     cw.emit("if search_in in ('customer', 'all'):")
                    #     with cw.indent():
                    #         cw.emit("search_domain = OR([search_domain, [('partner_id', 'ilike', search)]])")
                    # with cw.indent():
                    #     cw.emit("if search_in in ('message', 'all'):")
                    #     with cw.indent():
                    #         cw.emit("search_domain = OR([search_domain, [('message_ids.body', 'ilike', search)]])")
                    # with cw.indent():
                    #     cw.emit("if search_in in ('stage', 'all'):")
                    #     with cw.indent():
                    #         cw.emit("search_domain = OR([search_domain, [('stage_id', 'ilike', search)]])")
                    with cw.indent():
                        cw.emit("domain += search_domain")
            with cw.indent():
                with cw.indent():
                    cw.emit("# archive groups - Default Group By 'create_date'")
                    cw.emit(f"archive_groups = self._get_archive_groups('{model.model}', domain)")
                    cw.emit("if date_begin and date_end:")
                    with cw.indent():
                        cw.emit(
                            "domain += [('create_date', '>', date_begin), ('create_date', '<=', date_end)]"
                        )
                with cw.indent():
                    cw.emit(f"# {self._fmt_underscores(model.model)}s count")
                    cw.emit(
                        f"{self._fmt_underscores(model.model)}_count = {self._fmt_camel(model.model)}.search_count(domain)"
                    )
                    cw.emit("# pager")
                    cw.emit("pager = portal_pager(")
                    with cw.indent():
                        cw.emit(f'url="/my/{self._fmt_underscores(model.model)}s",')
                        cw.emit(
                            "url_args={'date_begin': date_begin, 'date_end': date_end, 'sortby': sortby, 'filterby': "
                            "filterby, 'search_in': search_in, 'search': search},"
                        )
                        cw.emit(f"total={self._fmt_underscores(model.model)}_count,")
                        cw.emit("page=page,")
                        cw.emit("step=self._items_per_page")
                with cw.indent():
                    cw.emit(")")
                    cw.emit("# content according to pager and archive selected")
                    # MATHBEN NOT IN PROJECT, BUT TASK
                    # cw.emit("if groupby == 'project':")
                    # with cw.indent():
                    #     cw.emit("order = \"project_id, %s\" % order  "
                    #             "# force sort on project first to group by project in view")
            cw.emit("")
            with cw.indent():
                with cw.indent():
                    cw.emit("# content according to pager and archive selected")
                    cw.emit(
                        f"{self._fmt_underscores(model.model)}s = {self._fmt_camel(model.model)}.search(domain, order=order, "
                        f"limit=self._items_per_page, offset=pager['offset'])"
                    )
                    # MATHBEN LAST LINE, TASK WAS offset=(page - 1) * self._items_per_page
                    cw.emit(
                        f"request.session['my_{self._fmt_underscores(model.model)}s_history'] = "
                        f"{self._fmt_underscores(model.model)}s.ids[:100]"
                    )
                    # MATHBEN NEXT BLOCK 43 COMMENT TO NEXT LINE
                    # cw.emit("if groupby == 'project':")
                    # with cw.indent():
                    #     cw.emit(
                    #         "grouped_tasks = [request.env['project.task'].concat(*g) for k, g in groupbyelem(tasks, itemgetter('project_id'))]")
                pass
                # with cw.indent():
                #     cw.emit("else:")
                #     with cw.indent():
                #         cw.emit("grouped_tasks = [tasks]")
                # MATHBEN END BLOCK 43
            cw.emit("")
            with cw.indent():
                with cw.indent():
                    cw.emit("values.update({")
                    with cw.indent():
                        cw.emit("'date': date_begin,")
                        cw.emit("'date_end': date_end,")
                        # MATHBEN WAS IN TASK
                        # cw.emit("'grouped_tasks': grouped_tasks,")
                        # GROUPED_TASKS CAN REPLACE PROJECTS
                        cw.emit(
                            f"'{self._fmt_underscores(model.model)}s': {self._fmt_underscores(model.model)}s,"
                        )
                        cw.emit(f"'page_name': '{self._fmt_underscores(model.model)}',")
                        cw.emit("'archive_groups': archive_groups,")
                        cw.emit(f"'default_url': '/my/{self._fmt_underscores(model.model)}s',")
                        cw.emit("'pager': pager,")
                        cw.emit("'searchbar_sortings': searchbar_sortings,")
                        cw.emit("'searchbar_groupby': searchbar_groupby,")
                        cw.emit("'searchbar_inputs': searchbar_inputs,")
                        cw.emit("'search_in': search_in,")
                        if has_group_by:
                            cw.emit("'groupby': groupby,")
                        cw.emit(
                            "'searchbar_filters': OrderedDict(sorted(searchbar_filters.items())),"
                        )
                        cw.emit("'sortby': sortby,")
                        cw.emit("'filterby': filterby,")
                with cw.indent():
                    cw.emit("})")
                    cw.emit(
                        f'return request.render("{module.name}.portal_my_{self._fmt_underscores(model.model)}s", values)'
                    )
            cw.emit("")
            with cw.indent():
                cw.emit(
                    f"@http.route(['/my/{self._fmt_underscores(model.model)}/<int:{self._fmt_underscores(model.model)}_id>'], "
                    f"type='http', auth=\"public\", website=True)"
                )
                cw.emit(
                    f"def portal_my_{self._fmt_underscores(model.model)}(self, {self._fmt_underscores(model.model)}_id=None, "
                    f"access_token=None, **kw):"
                )
                with cw.indent():
                    cw.emit("try:")
                    with cw.indent():
                        cw.emit(
                            f"{self._fmt_underscores(model.model)}_sudo = self._document_check_access('{model.model}', "
                            f"{self._fmt_underscores(model.model)}_id, access_token)"
                        )
                with cw.indent():
                    cw.emit("except (AccessError, MissingError):")
                    with cw.indent():
                        cw.emit("return request.redirect('/my')")
            cw.emit("")
            with cw.indent():
                with cw.indent():
                    if "attachment_ids" in [a.name for a in model.field_id]:
                        cw.emit(
                            "# ensure attachment are accessible with access token inside template"
                        )
                        cw.emit(
                            f"for attachment in {self._fmt_underscores(model.model)}_sudo.attachment_ids:"
                        )
                        with cw.indent():
                            cw.emit("attachment.generate_access_token()")
                with cw.indent():
                    cw.emit(
                        f"values = self._{self._fmt_underscores(model.model)}_get_page_view_values("
                        f"{self._fmt_underscores(model.model)}_sudo, access_token, **kw)"
                    )
                    cw.emit(
                        f'return request.render("{module.name}.portal_my_{self._fmt_underscores(model.model)}", values)'
                    )
            cw.emit("")

        out = cw.render()

        l_model = out.split("\n")

        file_path = f"{self.code_generator_data.controllers_path}/portal.py"

        self.code_generator_data.write_file_lst_content(file_path, l_model)