import os from xml.etree import ElementTree import requests from django.conf import settings from django.core.paginator import Paginator from django.db import models from django.db.models.functions import Lower from django.http import HttpResponse from django.shortcuts import get_object_or_404, render from django_downloadview import ObjectDownloadView from django_http_exceptions import HTTPExceptions from guardian.shortcuts import get_objects_for_user from .models import Contract, ContractFile class ContractFileDownloadView(ObjectDownloadView): model = ContractFile file_field = "file" attachment = False def get_queryset(self, *args, **kwargs): queryset = super().get_queryset(*args, **kwargs) if not self.current_user.has_perm("contracts.view_confidential"): queryset = queryset.filter(is_public=True) return queryset def get(self, request, *args, **kwargs): self.current_user = request.user return super().get(request, *args, **kwargs) def get_base_context(request) -> dict: return { "site_url": settings.SITE_URL, "user": request.user, } def get_pagination(request, objects) -> tuple: paginator = Paginator(objects, 25) page = paginator.get_page(request.GET.get("page")) return page, paginator def get_paginated_contracts(request, filter=None, annotations=None) -> tuple: if filter is None: filter = models.Q() filter = filter & models.Q(is_approved=True) if not request.user.has_perm("contracts.view_confidential"): additional_filter = models.Q(is_public=True) if not request.user.is_anonymous: additional_filter = additional_filter | models.Q(created_by=request.user) filter = filter & additional_filter contracts = get_objects_for_user(request.user, "contracts.view_contract") if annotations is not None: contracts = contracts.annotate(**annotations) contracts = contracts.filter(filter).order_by("-valid_start_date").all() page, paginator = get_pagination(request, contracts) return page, paginator def index(request): page, paginator = get_paginated_contracts(request) return render( request, "contracts/index.html", { **get_base_context(request), "title": "Seznam smluv", "description": "", "page": page, "paginator": paginator, "settings": Contract.settings, }, ) def view_contract(request, id: int): filter = models.Q(is_approved=True) if not request.user.has_perm("contracts.view_confidential"): filter = filter & ( models.Q(is_public=True) | ( models.Q(created_by=request.user) if not request.user.is_anonymous else models.Value(True) ) ) contract = get_object_or_404( (get_objects_for_user(request.user, "contracts.view_contract").filter(filter)), id=id, ) return render( request, "contracts/view_contract.html", { **get_base_context(request), "title": contract.name, "description": contract.summary, "contract": contract, }, ) def search(request): query = request.GET.get("q") page = paginator = None title = "Vyhledávání" # Query is defined and is more than spaces query_is_set = query is not None and len(query.replace(" ", "")) != 0 if query_is_set: title = f"Vyhledávání - „{query}“" lower_query = query.lower() # WARNING: PostgreSQL-dependent page, paginator = get_paginated_contracts( request, ( models.Q(lower_name__contains=lower_query) | models.Q(lower_summary__contains=lower_query) ), { "lower_name": Lower("name"), "lower_summary": Lower("summary"), }, ) return render( request, "contracts/search.html", { **get_base_context(request), "title": title, "description": "", "page": page, "paginator": paginator, "query": query, "query_is_set": query_is_set, }, ) # BEGIN Filtered contract + submodel views def view_contract_filing_area(request, id: int): filing_area = get_object_or_404( get_objects_for_user(request.user, "contracts.view_contractfilingarea"), id=id ) contracts_page, contracts_paginator = get_paginated_contracts( request, models.Q(filing_area=filing_area) ) return render( request, "contracts/view_contract_filing_area.html", { **get_base_context(request), "title": filing_area.name, "description": ( f"Spisovna smluv - {filing_area.name}, " f"zodpovědná osoba {filing_area.person_responsible}" ), "filing_area": filing_area, "contracts_page": contracts_page, "contracts_paginator": contracts_paginator, }, ) def view_contract_issue(request, id: int): issue = get_object_or_404( get_objects_for_user(request.user, "contracts.view_contractissue"), id=id ) contracts_page, contracts_paginator = get_paginated_contracts( request, models.Q(issues=issue) ) return render( request, "contracts/view_contract_issue.html", { **get_base_context(request), "title": issue.name, "description": f"Problém se smlouvami - {issue.name}", "issue": issue, "contracts_page": contracts_page, "contracts_paginator": contracts_paginator, }, ) def view_contract_type(request, id: int): type_ = get_object_or_404( get_objects_for_user(request.user, "contracts.view_contracttype"), id=id ) contracts_page, contracts_paginator = get_paginated_contracts( request, models.Q(types=type_) ) return render( request, "contracts/view_contract_type.html", { **get_base_context(request), "title": type_.name, "description": f"Typ smluv - {type_.name}", "type": type_, "contracts_page": contracts_page, "contracts_paginator": contracts_paginator, }, ) def view_contractee(request, id: int): contractee = get_object_or_404( get_objects_for_user(request.user, "contracts.view_contractee"), id=id ) contracts_page, contracts_paginator = get_paginated_contracts( request, models.Q(contractee_signatures__contractee=contractee) ) return render( request, "contracts/view_contractee.html", { **get_base_context(request), "title": contractee.name, "description": f"Naše smluvní strana - {contractee.name}", "contractee": contractee, "contracts_page": contracts_page, "contracts_paginator": contracts_paginator, }, ) def view_signee(request, id: int): signee = get_object_or_404( get_objects_for_user(request.user, "contracts.view_signee"), id=id ) contracts_page, contracts_paginator = get_paginated_contracts( request, models.Q(signee_signatures__signee=signee) ) return render( request, "contracts/view_signee.html", { **get_base_context(request), "title": signee.name, "description": f"Jiná smluvní strana - {signee.name}", "signee": signee, "contracts_page": contracts_page, "contracts_paginator": contracts_paginator, }, ) # END Filtered contract + submodel views # BEGIN Submodel listing views def view_contract_filing_areas(request): filing_areas = get_objects_for_user( request.user, "contracts.view_contractfilingarea", ).order_by("name") page, paginator = get_pagination(request, filing_areas) return render( request, "contracts/view_contract_filing_areas.html", { **get_base_context(request), "title": "Spisovny", "description": "Seznam fyzických spisoven, kde jsou ukládány smlouvy.", "page": page, "paginator": paginator, }, ) def view_contract_issues(request): issues = get_objects_for_user( request.user, "contracts.view_contractissue", ).order_by("name") page, paginator = get_pagination(request, issues) return render( request, "contracts/view_contract_issues.html", { **get_base_context(request), "title": ( "Poznámky" if (request.user.is_anonymous or not request.user.can_view_confidential) else "Problémy" ), "description": ( "Poznámky ke smlouvám." if (request.user.is_anonymous or not request.user.can_view_confidential) else "Problémy se smlouvami." ), "page": page, "paginator": paginator, }, ) def view_contract_types(request): types = get_objects_for_user( request.user, "contracts.view_contracttype", ).order_by("name") page, paginator = get_pagination(request, types) return render( request, "contracts/view_contract_types.html", { **get_base_context(request), "title": "Typy", "description": "Typy smluv.", "page": page, "paginator": paginator, }, ) def view_contractees(request): contractees = get_objects_for_user( request.user, "contracts.view_contractee", ).order_by("name") page, paginator = get_pagination(request, contractees) return render( request, "contracts/view_contractees.html", { **get_base_context(request), "title": "Naše smluvní strany", "description": "Naše smluvní strany.", "page": page, "paginator": paginator, }, ) def view_signees(request): contractees = get_objects_for_user( request.user, "contracts.view_signee", ).order_by("name") page, paginator = get_pagination(request, contractees) return render( request, "contracts/view_signees.html", { **get_base_context(request), "title": "Jiné smluvní strany", "description": "Jiné smluvní strany.", "page": page, "paginator": paginator, }, ) # END Submodel listing views # ARES CORS proxy def get_ares_info(request, ico: int): if not request.user.is_staff: raise HTTPExceptions.FORBIDDEN ares_info = requests.get( f"https://wwwinfo.mfcr.cz/cgi-bin/ares/darv_std.cgi?ico={ico}" ) tree = ElementTree.fromstring(ares_info.content) for result_count in tree.iter("are:Pocet_zaznamu"): if result_count.text == "0": raise HTTPExceptions.NOT_FOUND return HttpResponse( content=ares_info.content, status=ares_info.status_code, content_type=ares_info.headers.get("Content-Type"), ) def handle_404(request, exception): path = os.path.normpath(request.get_full_path()) archive_url = f"https://smlouvy-archiv.pirati.cz{path}" archive_response = requests.get(archive_url) # Quick dirty check for whether the page found is an actual contract was_found = archive_response.ok and "Datum podpisu" in str(archive_response.content) return render( request, "contracts/404.html", { **get_base_context(request), "title": "Stránka nenalezena", "description": "", "archive_page_exists": was_found, "archive_url": archive_url, } )