Skip to content
Snippets Groups Projects
Commit 63159cfd authored by Tomáš Valenta's avatar Tomáš Valenta
Browse files

finish requirements for admin, implement private information in frontend, permissions

parent ac77e322
No related branches found
No related tags found
No related merge requests found
Pipeline #11915 passed
import copy
from dal_admin_filters import AutocompleteFilter from dal_admin_filters import AutocompleteFilter
from django.contrib import admin from django.contrib import admin
from django.utils.html import format_html from django.utils.html import format_html
...@@ -111,7 +113,7 @@ class ContractAdmin(FieldsetsInlineMixin, MarkdownxGuardedModelAdmin): ...@@ -111,7 +113,7 @@ class ContractAdmin(FieldsetsInlineMixin, MarkdownxGuardedModelAdmin):
"id_number", "id_number",
"types", "types",
"summary", "summary",
"public_state", "is_public",
"publishing_rejection_comment", "publishing_rejection_comment",
"legal_state", "legal_state",
"primary_contract", "primary_contract",
...@@ -176,18 +178,23 @@ class ContractAdmin(FieldsetsInlineMixin, MarkdownxGuardedModelAdmin): ...@@ -176,18 +178,23 @@ class ContractAdmin(FieldsetsInlineMixin, MarkdownxGuardedModelAdmin):
] ]
def get_fieldsets(self, request, obj=None): def get_fieldsets(self, request, obj=None):
fieldsets_with_inlines = copy.deepcopy(self.fieldsets_with_inlines)
if request.user.is_superuser or request.user.has_perm("approve", self): if request.user.is_superuser or request.user.has_perm("approve", self):
self.fieldsets_with_inlines.insert( fieldsets_with_inlines.insert(
8, 8,
( (
"Schválení", "Schválení",
{ {
"fields": ["approval_state"] "fields": ["is_approved"]
} }
), ),
) )
return super().get_fieldsets(request, obj) return [
self.make_placeholder(index, fieldset)
for index, fieldset in enumerate(fieldsets_with_inlines)
]
def save_model(self, request, obj, form, change) -> None: def save_model(self, request, obj, form, change) -> None:
if obj.created_by is None: if obj.created_by is None:
...@@ -210,9 +217,9 @@ class ContractAdmin(FieldsetsInlineMixin, MarkdownxGuardedModelAdmin): ...@@ -210,9 +217,9 @@ class ContractAdmin(FieldsetsInlineMixin, MarkdownxGuardedModelAdmin):
list_filter = ( list_filter = (
"types", "types",
"approval_state", "is_approved",
"legal_state", "legal_state",
"public_state", "is_public",
"paper_form_state", "paper_form_state",
ContractAuthorPlaceholderFilter, ContractAuthorPlaceholderFilter,
"issues", "issues",
...@@ -223,8 +230,8 @@ class ContractAdmin(FieldsetsInlineMixin, MarkdownxGuardedModelAdmin): ...@@ -223,8 +230,8 @@ class ContractAdmin(FieldsetsInlineMixin, MarkdownxGuardedModelAdmin):
list_display = ( list_display = (
"name", "name",
"approval_state", "is_approved",
"public_state", "is_public",
) )
# END Contracts # END Contracts
......
# Generated by Django 4.1.4 on 2023-03-20 10:06
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('contracts', '0003_contractcontracteerepresentative_and_more'),
]
operations = [
migrations.AlterModelOptions(
name='contract',
options={'permissions': (('approve', 'Schválit / zrušit schválení'), ('view_confidential', 'Zobrazit tajné informace')), 'verbose_name': 'Smlouva', 'verbose_name_plural': 'Smlouvy'},
),
migrations.AlterModelOptions(
name='contractsigneerepresentative',
options={'verbose_name': 'Zástupce jiné smluvní strany', 'verbose_name_plural': 'Zástupci jiných smluvních stran'},
),
migrations.AlterModelOptions(
name='contracttype',
options={'verbose_name': 'Typ smlouvy', 'verbose_name_plural': 'Typy smluv'},
),
migrations.AlterModelOptions(
name='signeesignature',
options={'verbose_name': 'Podpis jiné smluvní strany', 'verbose_name_plural': 'Podpisy jiných smluvních stran'},
),
migrations.RemoveField(
model_name='contract',
name='approval_state',
),
migrations.RemoveField(
model_name='contract',
name='public_state',
),
migrations.AddField(
model_name='contract',
name='is_approved',
field=models.BooleanField(default=True, help_text='Může měnit jen schvalovatel. Pokud je smlouva veřejná, schválením se vypustí ven.', verbose_name='Je schválená'),
preserve_default=False,
),
migrations.AddField(
model_name='contract',
name='is_public',
field=models.BooleanField(default=True, verbose_name='Je veřejná'),
preserve_default=False,
),
migrations.AlterField(
model_name='contractee',
name='address_country',
field=models.CharField(default='CZ', max_length=256, verbose_name='Země'),
),
migrations.AlterField(
model_name='signee',
name='address_country',
field=models.CharField(default='CZ', max_length=256, verbose_name='Země'),
),
]
import math
from django.conf import settings from django.conf import settings
from django.db import models from django.db import models
from django.db.models.signals import post_save
from django.dispatch import receiver
from markdownx.models import MarkdownxField from markdownx.models import MarkdownxField
from shared.models import NameStrMixin from shared.models import NameStrMixin
...@@ -103,6 +103,13 @@ class Signee(models.Model): ...@@ -103,6 +103,13 @@ class Signee(models.Model):
verbose_name = "Jiná smluvní strana" verbose_name = "Jiná smluvní strana"
verbose_name_plural = "Ostatní smluvní strany" verbose_name_plural = "Ostatní smluvní strany"
@property
def entity_has_public_address(self) -> bool:
return self.entity_type in (
self.EntityTypes.LEGAL_ENTITY,
self.EntityTypes.OTHER
)
def __str__(self) -> str: def __str__(self) -> str:
result = self.name result = self.name
...@@ -263,19 +270,11 @@ class Contract(NameStrMixin, models.Model): ...@@ -263,19 +270,11 @@ class Contract(NameStrMixin, models.Model):
# BEGIN Approval fields # BEGIN Approval fields
class ApprovalStates(models.TextChoices): is_approved = models.BooleanField(
NO = "no", "Neschválená" verbose_name="Je schválená",
YES = "yes", "Schválená"
approval_state = models.CharField(
max_length=7,
choices=ApprovalStates.choices,
blank=True,
null=True,
verbose_name="Stav schválení",
help_text=( help_text=(
"Může měnit jen schvalovatel. Pokud je smlouva " "Může měnit jen schvalovatel. Pokud je smlouva "
"veřejná, se stavem \"Schválená\" se vypustí ven." "veřejná, schválením se vypustí ven."
), ),
) )
...@@ -337,10 +336,8 @@ class Contract(NameStrMixin, models.Model): ...@@ -337,10 +336,8 @@ class Contract(NameStrMixin, models.Model):
verbose_name="Stav právního ujednání", verbose_name="Stav právního ujednání",
) )
public_state = models.CharField( is_public = models.BooleanField(
max_length=7, verbose_name="Je veřejná",
choices=PublicStates.choices,
verbose_name="Veřejnost smlouvy",
) )
paper_form_state = models.CharField( paper_form_state = models.CharField(
...@@ -422,7 +419,7 @@ class Contract(NameStrMixin, models.Model): ...@@ -422,7 +419,7 @@ class Contract(NameStrMixin, models.Model):
blank=True, blank=True,
null=True, null=True,
verbose_name="Poznámky", verbose_name="Poznámky",
help_text="Poznámky jsou viditelné pro všechny, kteří mohou smlouvu spravovat.", help_text="Poznámky jsou viditelné pro všechny, kteří mohou smlouvu spravovat a pro tajné čtenáře.",
) )
class Meta: class Meta:
...@@ -431,7 +428,10 @@ class Contract(NameStrMixin, models.Model): ...@@ -431,7 +428,10 @@ class Contract(NameStrMixin, models.Model):
verbose_name = "Smlouva" verbose_name = "Smlouva"
verbose_name_plural = "Smlouvy" verbose_name_plural = "Smlouvy"
permissions = (("approve", "Schválit / zrušit schválení"),) permissions = (
("approve", "Schválit / zrušit schválení"),
("view_confidential", "Zobrazit tajné informace"),
)
def get_public_files(self): def get_public_files(self):
return ContractFile.objects.filter( return ContractFile.objects.filter(
...@@ -439,6 +439,43 @@ class Contract(NameStrMixin, models.Model): ...@@ -439,6 +439,43 @@ class Contract(NameStrMixin, models.Model):
is_public=True, is_public=True,
).all() ).all()
def get_private_files(self):
return ContractFile.objects.filter(
contract=self,
is_public=False,
).all()
def calculate_signing_parties_sign_date(self) -> None:
contractees_latest_sign_date = None
signees_latest_sign_date = None
for contractee_signature in self.contractee_signatures.all():
if (
contractees_latest_sign_date is None
or contractee_signature.date > contractees_latest_sign_date
):
contractees_latest_sign_date = contractee_signature.date
for signee_signature in self.signee_signatures.all():
if (
signees_latest_sign_date is None
or signee_signature.date > signees_latest_sign_date
):
signees_latest_sign_date = signee_signature.date
if (
contractees_latest_sign_date is not None
and signees_latest_sign_date is not None
):
self.all_parties_sign_date = max(
(
contractees_latest_sign_date,
signees_latest_sign_date
)
)
self.save()
class ContractContracteeRepresentative(RepresentativeMixin, models.Model): class ContractContracteeRepresentative(RepresentativeMixin, models.Model):
contract = models.ForeignKey( contract = models.ForeignKey(
...@@ -597,6 +634,17 @@ class SigneeSignature(models.Model): ...@@ -597,6 +634,17 @@ class SigneeSignature(models.Model):
return f"{str(self.signee)} - {self.date}" return f"{str(self.signee)} - {self.date}"
@receiver(post_save, sender=ContracteeSignature)
@receiver(post_save, sender=SigneeSignature)
def signing_parties_post_save_update_dates(
sender,
instance,
*args,
**kwargs
) -> None:
instance.contract.calculate_signing_parties_sign_date()
class ContractIntent(NameStrMixin, models.Model): class ContractIntent(NameStrMixin, models.Model):
name = models.CharField( name = models.CharField(
max_length=128, max_length=128,
......
{% extends "shared/includes/base.html" %} {% extends "shared/includes/base.html" %}
{% load subtract %} {% load subtract markdownify %}
{% block content %} {% block content %}
<h1 class="head-alt-lg mb-10"><i class="ico--file-blank mr-4"></i>{{ contract.name }}</h1> <h1 class="head-alt-lg mb-10"><i class="ico--file-blank mr-4"></i>{{ contract.name }}</h1>
...@@ -20,7 +20,7 @@ ...@@ -20,7 +20,7 @@
{% endif %} {% endif %}
<tr> <tr>
<td class="w-1/5 !p-2.5">Typy</td> <td class="w-1/5 !p-2.5">Typy</td>
<td class="w-4/5 !p-2.5"> <td class="w-4/5 !pl-2.5 !py-1 !pr-1">
<ul class="flex flex-wrap gap-1.5"> <ul class="flex flex-wrap gap-1.5">
{% for type in contract.types.all %} {% for type in contract.types.all %}
<li class="flex"> <li class="flex">
...@@ -44,6 +44,17 @@ ...@@ -44,6 +44,17 @@
<td class="w-1/5 !p-2.5">Souhrn</td> <td class="w-1/5 !p-2.5">Souhrn</td>
<td class="w-4/5 !p-2.5">{{ contract.summary }}</td> <td class="w-4/5 !p-2.5">{{ contract.summary }}</td>
</tr> </tr>
{% if user.can_view_confidential %}
<tr>
<td class="w-1/5 !p-2.5">Je veřejná</td>
<td class="w-4/5 !p-2.5">
<i
class="{% if contract.legal_state == contract.LegalStates.VALID %}ico--checkmark{% else %}ico--cross{% endif %} __tooltipped"
aria-label="{{ contract.get_legal_state_display }}"
></i>
</td>
</tr>
{% endif %}
<tr> <tr>
<td class="w-1/5 !p-2.5">Je platná</td> <td class="w-1/5 !p-2.5">Je platná</td>
<td class="w-4/5 !p-2.5"> <td class="w-4/5 !p-2.5">
...@@ -53,9 +64,22 @@ ...@@ -53,9 +64,22 @@
></i> ></i>
</td> </td>
</tr> </tr>
{% if contract.cost_amount %}
<tr>
<td class="w-1/5 !p-2.5">Náklady</td>
<td class="w-4/5 !p-2.5">
{{ contract.cost_amount }} Kč
{% if contract.cost_unit != contract.CostUnits.TOTAL %}
/ {{ contract.get_cost_unit_display }}
{% else %}
celkem
{% endif %}
</td>
</tr>
{% endif %}
<tr> <tr>
<td class="w-1/5 !p-2.5">Soubory</td> <td class="w-1/5 !p-2.5">{% if user.can_view_confidential %}Veřejné s{% else %}S{% endif %}oubory</td>
<td class="w-4/5 !p-2.5"> <td class="w-4/5 !pl-2.5 !py-1 !pr-1">
{% with contract.get_public_files as files %} {% with contract.get_public_files as files %}
{% if files|length != 0 %} {% if files|length != 0 %}
<ul class="flex gap-2"> <ul class="flex gap-2">
...@@ -71,63 +95,87 @@ ...@@ -71,63 +95,87 @@
{% endwith %} {% endwith %}
</td> </td>
</tr> </tr>
</tbody>
<table>
<table class="table table-auto w-full table--striped table--bordered mb-7">
<tbody>
<tr>
<td colspan="2" class="text-lg font-bold">
<i class="ico--clock mr-3"></i>Data
</td>
</tr>
<tr> {% if user.can_view_confidential %}
<td class="w-1/5 !p-2.5">Začátek účinnosti</td> <tr>
<td class="w-4/5 !p-2.5">{{ contract.valid_start_date }}</td> <td class="w-1/5 !p-2.5">
</tr> <div class="flex items-center">
<tr> <i
<td class="w-1/5 !p-2.5">Konec účinnosti</td> class="ico--eye-off text-red-600 mr-2 __tooltipped"
<td class="w-4/5 !p-2.5"> aria-label="Neveřejný údaj"
{% if contract.valid_end_date %} ></i>
{{ contract.valid_end_date }} Neveřejné soubory
{% else %} </div>
<span class="text-grey-200">Neurčitý</span> </td>
{% endif %} <td class="w-4/5 !pl-2.5 !py-1 !pr-1">
</td> {% with contract.get_private_files as files %}
</tr> {% if files|length != 0 %}
<ul class="flex gap-2">
{% for file in files %}
<li class="flex">
{% include "contracts/includes/tag.html" with url=file.file.url icon="ico--attachment" content=file.name %}
</li>
{% endfor %}
</ul>
{% else %}
<span class="text-grey-200">Žádné</span>
{% endif %}
{% endwith %}
</td>
</tr>
{% endif %}
</tbody> </tbody>
</table> </table>
<table class="table table-auto w-full table--striped table--bordered mb-7"> <div class="flex gap-7">
<tbody> <table class="table table-auto w-full table--striped table--bordered mb-7">
<tr> <tbody>
<td colspan="2" class="text-lg font-bold"> <tr>
<i class="ico--folder-open mr-3"></i>Fyzický dokument <td colspan="2" class="text-lg font-bold">
</td> <i class="ico--folder-open mr-3"></i>Fyzický dokument
</tr> </td>
</tr>
<tr>
<td class="w-1/5 !p-2.5">Stav</td> <tr>
<td class="w-4/5 !p-2.5">{{ contract.get_paper_form_state_display }}</td> <td class="w-1/5 !p-2.5">Stav</td>
</tr> <td class="w-4/5 !p-2.5">{{ contract.get_paper_form_state_display }}</td>
<tr> </tr>
<td class="w-1/5 !p-2.5">Spisovna</td> <tr>
<td class="w-4/5 !p-2.5"> <td class="w-1/5 !p-2.5">Spisovna</td>
<div class="flex gap-3 items-center"> <td class="w-4/5 !pl-2.5 !py-1 !pr-1">
<div class="flex"> <div class="flex gap-3 items-center">
{% include "contracts/includes/tag.html" with url="#TODO" icon="ico--drawer" content=contract.filing_area.name %} {% include "contracts/includes/tag.html" with url="#TODO" icon="ico--drawer" content=contract.filing_area.name %}
</div> </div>
<span>|</span> </td>
<span> </tr>
zodpovědná osoba </tbody>
{{ contract.filing_area.person_responsible }} </table>
</span>
</div> <table class="table table-auto w-full table--striped table--bordered mb-7">
</td> <tbody>
</tr> <tr>
</tbody> <td colspan="2" class="text-lg font-bold">
</table> <i class="ico--calendar mr-3"></i>Data
</td>
</tr>
<tr>
<td class="w-1/5 !p-2.5 whitespace-nowrap">Začátek účinnosti</td>
<td class="w-4/5 !p-2.5">{{ contract.valid_start_date }}</td>
</tr>
<tr>
<td class="w-1/5 !p-2.5 whitespace-nowrap">Konec účinnosti</td>
<td class="w-4/5 !p-2.5">
{% if contract.valid_end_date %}
{{ contract.valid_end_date }}
{% else %}
<span class="text-grey-200">Neurčitý</span>
{% endif %}
</td>
</tr>
</tbody>
</table>
</div>
<table class="table table-auto w-full table--striped table--bordered mb-7"> <table class="table table-auto w-full table--striped table--bordered mb-7">
<tbody> <tbody>
...@@ -165,7 +213,7 @@ ...@@ -165,7 +213,7 @@
</tr> </tr>
<tr> <tr>
<td class="w-1/5 !p-2.5">Záměry</td> <td class="w-1/5 !p-2.5">Záměry</td>
<td class="w-4/5 !p-2.5"> <td class="w-4/5 !pl-2.5 !py-1 !pr-1">
{% with contract.intents.all as intents %} {% with contract.intents.all as intents %}
{% if intents|length != 0 %} {% if intents|length != 0 %}
<ul class="flex gap-2"> <ul class="flex gap-2">
...@@ -184,29 +232,6 @@ ...@@ -184,29 +232,6 @@
</tbody> </tbody>
</table> </table>
{% if contract.cost_amount %}
<table class="table table-auto w-full table--striped table--bordered mb-7">
<tbody>
<tr>
<td colspan="2" class="text-lg font-bold">
<i class="ico--calculator mr-3"></i>Finance
</td>
</tr>
<tr>
<td class="w-1/5 !p-2.5">Náklady</td>
<td class="w-4/5 !p-2.5">
{{ contract.cost_amount }} Kč
{% if contract.cost_unit != contract.CostUnits.TOTAL %}
/ {{ contract.get_cost_unit_display }}
{% else %}
celkem
{% endif %}
</td>
</tr>
</tbody>
</table>
{% endif %}
{% with contract.issues.all as issues %} {% with contract.issues.all as issues %}
{% if issues|length != 0 %} {% if issues|length != 0 %}
<table class="table table-auto w-full table--striped table--bordered mb-10"> <table class="table table-auto w-full table--striped table--bordered mb-10">
...@@ -218,17 +243,36 @@ ...@@ -218,17 +243,36 @@
</tr> </tr>
<tr> <tr>
<td class="w-1/5 !p-2.5">Poznámky</td> <td class="w-1/5 !p-2.5">{% if not user.can_view_confidential %}Poznámky{% else %}Problémy{% endif %}</td>
<td class="w-4/5 !p-2.5"> <td class="w-4/5 !pl-2.5 !py-1 !pr-1">
<ul class="flex gap-2"> <ul class="flex gap-2">
{% for issue in issues %} {% for issue in issues %}
<li class="flex"> <li class="flex">
{% include "contracts/includes/tag.html" with url="#TODO" content=issue.name %} {% include "contracts/includes/tag.html" with url="#TODO" icon="ico--warning" content=issue.name %}
</li> </li>
{% endfor %} {% endfor %}
</ul> </ul>
</td> </td>
</tr> </tr>
{% if user.can_view_confidential and contract.notes %}
<tr>
<td class="w-1/5 !p-2.5">
<div class="flex items-center">
<i
class="ico--eye-off text-red-600 mr-2 __tooltipped"
aria-label="Neveřejný údaj"
></i>
Interní poznámky
</div>
</td>
<td class="w-4/5 !p-2.5">
<p class="prose min-w-none">
{{ contract.notes|markdownify|safe }}
</p>
</td>
</tr>
{% endif %}
</tbody> </tbody>
</table> </table>
{% endif %} {% endif %}
...@@ -236,7 +280,15 @@ ...@@ -236,7 +280,15 @@
<h2 class="text-xl font-bold mb-5"><i class="ico--pencil mr-3"></i>Podpisy</h2> <h2 class="text-xl font-bold mb-5"><i class="ico--pencil mr-3"></i>Podpisy</h2>
<h3 class="text-lg font-bold mb-4">Naší smluvní strany</h3> {% if contract.all_parties_sign_date %}
<p class="text-lg mb-5">
<i class="ico--calendar mr-3"></i>
Datum podpisu všech smluvních stran:
<strong>{{ contract.all_parties_sign_date }}</strong>
</p>
{% endif %}
<h3 class="text-lg font-bold mb-4">Podpisy naší smluvní strany</h3>
{% with contract.contractee_signatures.all as signatures %} {% with contract.contractee_signatures.all as signatures %}
{% if signatures|length != 0 %} {% if signatures|length != 0 %}
...@@ -268,16 +320,21 @@ ...@@ -268,16 +320,21 @@
{% endif %} {% endif %}
</address> </address>
<div class="block mb-2"> {% with contract.contractee_representatives.all as representatives %}
<p class="block mb-2"> {% if representatives %}
<strong>Zástupci:</strong> <div class="block mb-2">
</p> <p class="block mb-2">
<ul class="list-disc ml-6"> <strong>Zástupci:</strong>
{% for representative in signature.contractee.representatives.all %} </p>
<li>{{ representative.name }}, {{ representative.function }}</li> <ul class="list-disc ml-6">
{% endfor %} {% for representative in representatives %}
</ul> <li>{{ representative.name }}, {{ representative.function }}</li>
</div> {% endfor %}
</ul>
</div>
{% endif %}
{% endwith %}
<p> <p>
<strong>Datum podpisu:</strong> {{ signature.date }} <strong>Datum podpisu:</strong> {{ signature.date }}
</p> </p>
...@@ -289,7 +346,7 @@ ...@@ -289,7 +346,7 @@
{% endif %} {% endif %}
{% endwith %} {% endwith %}
<h3 class="text-lg font-bold mb-5">Ostatních smluvních stran</h3> <h3 class="text-lg font-bold mb-5">Podpisy otatních smluvních stran</h3>
{% with contract.signee_signatures.all as signatures %} {% with contract.signee_signatures.all as signatures %}
{% if signatures|length != 0 %} {% if signatures|length != 0 %}
...@@ -315,12 +372,21 @@ ...@@ -315,12 +372,21 @@
<div class="mb-1"> <div class="mb-1">
{{ signature.signee.get_entity_type_display }} {{ signature.signee.get_entity_type_display }}
{% if signature.signee.entity_type == signature.signee.EntityTypes.NATURAL_PERSON or signature.signee.entity_type == signature.signee.EntityTypes.BUSINESS_NATURAL_PERSON %} {% if not signature.signee.entity_has_public_address %}
<span class="text-gray-300">(zobrazujeme pouze obec)</span> {% if user.can_view_confidential %}
<div class="my-2 flex items-center">
<i
class="ico--eye-off text-red-600 mr-2 __tooltipped"
aria-label="Neveřejný údaj"
></i><span class="text-gray-500">Máš přístup k celé adrese.</span>
</div>
{% else %}
<span class="text-gray-500">(zobrazujeme pouze obec)</span>
{% endif %}
{% endif %} {% endif %}
</div> </div>
{% if signature.signee.entity_type == signature.signee.EntityTypes.LEGAL_ENTITY or signature.signee.entity_type == signature.signee.EntityTypes.OTHER %} {% if user.can_view_confidential or signature.signee.entity_has_public_address %}
{{ signature.signee.address_street_with_number }}<br> {{ signature.signee.address_street_with_number }}<br>
{{ signature.signee.address_zip }} {{ signature.signee.address_district }}<br> {{ signature.signee.address_zip }} {{ signature.signee.address_district }}<br>
{{ signature.signee.get_address_country_display }}<br> {{ signature.signee.get_address_country_display }}<br>
...@@ -333,16 +399,21 @@ ...@@ -333,16 +399,21 @@
{% endif %} {% endif %}
</address> </address>
<div class="block mb-2"> {% with contract.signee_representatives.all as representatives %}
<p class="block mb-2"> {% if representatives %}
<strong>Zástupci:</strong> <div class="block mb-2">
</p> <p class="block mb-2">
<ul class="list-disc ml-6"> <strong>Zástupci:</strong>
{% for representative in signature.signee.representatives.all %} </p>
<li>{{ representative.name }}, {{ representative.function }}</li> <ul class="list-disc ml-6">
{% endfor %} {% for representative in representatives %}
</ul> <li>{{ representative.name }}, {{ representative.function }}</li>
</div> {% endfor %}
</ul>
</div>
{% endif %}
{% endwith %}
<p> <p>
<strong>Datum podpisu:</strong> {{ signature.date }} <strong>Datum podpisu:</strong> {{ signature.date }}
</p> </p>
......
from django.conf import settings from django.conf import settings
from django.core.paginator import Paginator from django.core.paginator import Paginator
from django.shortcuts import render from django.shortcuts import render
from guardian.shortcuts import get_objects_for_user
from .models import Contract from .models import Contract
...@@ -8,11 +9,16 @@ from .models import Contract ...@@ -8,11 +9,16 @@ from .models import Contract
def index(request): def index(request):
filter = {
"is_approved": True
}
if not request.user.has_perm("contracts.view_confidential"):
filter["is_public"] = True
contracts = ( contracts = (
Contract.objects.filter( get_objects_for_user(request.user, "contracts.view_contract")
approval_state=Contract.ApprovalStates.YES, .filter(**filter)
public_state=Contract.PublicStates.YES,
)
.order_by("valid_start_date") .order_by("valid_start_date")
.all() .all()
) )
...@@ -35,10 +41,18 @@ def index(request): ...@@ -35,10 +41,18 @@ def index(request):
def view_contract(request, id: int): def view_contract(request, id: int):
contract = Contract.objects.filter( filter = {
approval_state=Contract.ApprovalStates.YES, "is_approved": True
public_state=Contract.PublicStates.YES, }
).get(id=id)
if not request.user.has_perm("contracts.view_confidential"):
filter["is_public"] = True
contract = (
get_objects_for_user(request.user, "contracts.view_contract")
.filter(**filter)
.get(id=id)
)
return render( return render(
request, request,
...@@ -47,7 +61,7 @@ def view_contract(request, id: int): ...@@ -47,7 +61,7 @@ def view_contract(request, id: int):
"site_url": settings.SITE_URL, "site_url": settings.SITE_URL,
"user": request.user, "user": request.user,
"title": contract.name, "title": contract.name,
"description": "", # TODO "description": contract.summary,
"contract": contract, "contract": contract,
}, },
) )
import copy
from django_admin_index.models import AppGroup, AppGroupQuerySet from django_admin_index.models import AppGroup, AppGroupQuerySet
from django.conf import settings from django.conf import settings
...@@ -23,18 +25,28 @@ def get_app_list(self, request): ...@@ -23,18 +25,28 @@ def get_app_list(self, request):
admin.AdminSite.get_app_list = get_app_list admin.AdminSite.get_app_list = get_app_list
class CustomOrderAppGroupQuerySet(AppGroupQuerySet): original_as_list_func = copy.deepcopy(AppGroupQuerySet.as_list)
def as_list(self, request, include_remaining=True):
result = super().as_list(request, include_remaining=include_remaining)
for item in result: def as_list(self, request, include_remaining=True):
if app_label not in settings.ADMIN_ORDERING: result = original_as_list_func(
continue self,
request,
include_remaining=include_remaining
)
item["models"].sort( for item in result:
key=lambda model: settings.ADMIN_ORDERING[app_name].index(model["name"]) if item["app_label"] not in settings.ADMIN_ORDERING:
continue
item["models"].sort(
key=lambda model: (
settings.ADMIN_ORDERING[item["app_label"]]
.index(model["object_name"])
) )
)
return result
return result
AppGroup.objects = AppGroupQuerySet.as_manager() AppGroupQuerySet.as_list = as_list
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
<div class="index-action-buttons"> <div class="index-action-buttons">
{% if request.user.can_approve_contracts %} {% if request.user.can_approve_contracts %}
<a <a
href="contracts/contract/?approval_state__exact=no" href="contracts/contract/?is_approved__exact=0"
aria-role="button" aria-role="button"
>Smlouvy ke schválení ({{ request.user.contracts_to_approve_count }})</a> >Smlouvy ke schválení ({{ request.user.contracts_to_approve_count }})</a>
{% endif %} {% endif %}
......
import html
import markdownx
from django import template
register = template.Library()
@register.filter
def markdownify(text: str) -> str:
return markdownx.utils.markdownify(html.escape(text))
...@@ -24,6 +24,10 @@ class User(pirates_models.AbstractUser): ...@@ -24,6 +24,10 @@ class User(pirates_models.AbstractUser):
# TODO: Do we need the superuser check? # TODO: Do we need the superuser check?
return self.is_superuser or self.has_perm("contracts.add") return self.is_superuser or self.has_perm("contracts.add")
@property
def can_view_confidential(self) -> bool:
return self.is_superuser or self.has_perm("contracts.view_confidential")
@property @property
def contracts_to_approve_count(self) -> int: def contracts_to_approve_count(self) -> int:
if not self.can_approve_contracts: if not self.can_approve_contracts:
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment