# Copyright 2018 Rémy Taymans # Copyright 2015-2016 Odoo S.A. # Copyright 2016 Jairo Llopis # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). import base64 from odoo import http from odoo.http import request, Response from odoo.fields import Date class DocumentWebsite(http.Controller): @http.route("/documents/", auth="public", website=True) def get_document(self, oid=-1): """Render a http response for a document""" document_mgr = request.env["document_hosting.document"] doc = document_mgr.sudo().browse(oid) ir_http_mgr = request.env["ir.http"] status, headers, content = ir_http_mgr.sudo().binary_content( model=doc._name, id=oid, field="document", filename_field="filename", download=True, ) if status == 304: return Response(status, headers) elif status == 301: # TODO: test this case not sure if this render the same # return werkzeug.utils.redirect(content, code=301) return request.redirect(content, code=301) elif status != 200: return request.not_found() content_base64 = base64.b64decode(content) headers.append(("Content-Length", len(content_base64))) return request.make_response(content_base64, headers) @http.route("/documents", auth="public", website=True) def template_website_document(self, date_begin=None, date_end=None, **kw): """ """ values = {} values.update( self.website_document_side_bar( date_begin=date_begin, date_end=date_end, user=request.env.user, ) ) values.update( self.display_categories_and_documents( date_begin=date_begin, date_end=date_end, user=request.env.user, ) ) values["size_to_str"] = self.size_to_str return request.render( "easy_my_coop_website_document.template_website_document", values, ) def website_document_side_bar( self, date_begin=None, date_end=None, user=None ): domains = [] # Show only doc that are published domains.append(("published", "=", True)) # Show only authorized documents if not self._is_authorized_user(user): domains.append(("public", "=", True)) # Show only doc in the time frame if date_begin and date_end: domains.append(("document_date", ">=", date_begin)) domains.append(("document_date", "<", date_end)) return { "archive_groups": self._get_archive_groups( "document_hosting.document", domains, fields=["name", "document_date"], groupby="document_date", order="document_date desc", ), } def display_categories_and_documents( self, date_begin=None, date_end=None, user=None ): """Prepare value for display_categories_and_documents template""" data = self._data_tree() # Show only doc that are published data = self._data_filter_document(data, lambda r: r.published) # Show only authorized documents if not self._is_authorized_user(user): data = self._data_filter_document(data, lambda r: r.public) # Show only doc in the time frame if date_begin and date_end: data = self._data_filter_document( data, lambda r: ( r.document_date >= date_begin and r.document_date < date_end ), ) # After all the filter, remove the empty categories data = self._data_remove_empty_category(data) return { "category_tree": data, } def size_to_str(self, size): units = ["o", "ko", "Mo", "Go", "To"] size_float = float(size) for unit in units: if size_float < 1000: return "%.01f %s" % (size_float, unit) size_float /= 1000 def _data_tree(self, category=None): """Return a tree with categories and documents in it""" category_mgr = request.env["document_hosting.document.category"] document_mgr = request.env["document_hosting.document"] if category: categories = category.child_ids.sorted(key=lambda r: r.name) documents = category.document_ids else: categories = category_mgr.sudo().search( [("parent_id", "=", False)], order="name" ) documents = document_mgr.sudo().search([("category", "=", False)]) if categories.ids: tree = [] for cat in categories: tree.append(self._data_tree(cat)) return (category, tree, documents) else: return (category, [], documents) def _data_filter_document(self, data, filter_fun): category, child_data, documents = data tree = [] for entry in child_data: tree.append(self._data_filter_document(entry, filter_fun)) return (category, tree, documents.filtered(filter_fun)) def _data_remove_empty_category(self, data): category, child_data, documents = data child_data = [ self._data_remove_empty_category(c) for c in child_data if not self._data_is_empty(c) ] return (category, child_data, documents) def _data_is_empty(self, data): """Return True if data is empty""" _, child_data, documents = data # If there is documents, it's not empty. if documents.ids: return False # We are sure there is no documents. # If there is no child, it's empty. if not child_data: return True # We are sure there is childs for entry in child_data: # If a child is not empty, it's not empty if not self._data_is_empty(entry): return False # Else it's empty return True def _is_authorized_user(self, user=None): return user is not None and ( user.has_group("base.group_portal") or user.has_group("base.group_user") ) def _get_archive_groups( self, model, domain=None, fields=None, groupby="create_date", order="create_date desc", ): if not model: return [] if domain is None: domain = [] if fields is None: fields = ["name", "create_date"] groups = [] for group in ( request.env[model] .sudo() .read_group(domain, fields=fields, groupby=groupby, orderby=order) ): label = group[groupby] date_begin = date_end = None for leaf in group["__domain"]: if leaf[0] == groupby: if leaf[1] == ">=": date_begin = leaf[2] elif leaf[1] == "<": date_end = leaf[2] groups.append( { "date_begin": Date.to_string(Date.from_string(date_begin)), "date_end": Date.to_string(Date.from_string(date_end)), "name": label, "item_count": group[groupby + "_count"], } ) return groups