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 _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)
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)
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)
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())
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)