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

nastenka sync, ui facelift

parent 98d130ca
No related branches found
No related tags found
No related merge requests found
Pipeline #13269 failed
import copy import copy
import json
import logging
import typing import typing
import requests
from admin_auto_filters.filters import AutocompleteFilterFactory from admin_auto_filters.filters import AutocompleteFilterFactory
from django.conf import settings
from django.contrib import admin from django.contrib import admin
from django.contrib.auth.models import Permission from django.contrib.auth.models import Permission
from django.db import models from django.db import models
...@@ -33,6 +37,8 @@ from .models import ( ...@@ -33,6 +37,8 @@ from .models import (
SigneeSignatureRepresentative, SigneeSignatureRepresentative,
) )
logger = logging.getLogger()
class IndexHiddenModelAdmin(MarkdownxGuardedModelAdmin): class IndexHiddenModelAdmin(MarkdownxGuardedModelAdmin):
def has_module_permission(self, request): def has_module_permission(self, request):
...@@ -314,6 +320,8 @@ class ContractAdmin( ...@@ -314,6 +320,8 @@ class ContractAdmin(
return queryset return queryset
def save_model(self, request, obj, form, change): def save_model(self, request, obj, form, change):
is_new = obj.created_by is None
# Need to generate primary keys first # Need to generate primary keys first
parent_save_response = super().save_model(request, obj, form, change) parent_save_response = super().save_model(request, obj, form, change)
...@@ -333,6 +341,40 @@ class ContractAdmin( ...@@ -333,6 +341,40 @@ class ContractAdmin(
obj.valid_start_date = last_signature_date obj.valid_start_date = last_signature_date
from users.models import User
if is_new:
try:
sso_ids = []
for user in User.objects.filter(is_staff=True).all():
if user.is_superuser or user.has_perm("contracts.approve"):
sso_ids.append(user.sso_id)
requests.post(
settings.NASTENKA_API_URL,
data=json.dumps(
{
"name": f"Nová smlouva ke schválení - {obj.name}",
"description": (
obj.summary
if obj.summary is not None
else "Bez popisu."
),
"contract_id": obj.id,
"sso_ids": sso_ids,
}
),
headers={
"Authorization": f"Token {settings.NASTENKA_API_TOKEN}",
"Content-Type": "application/json",
},
)
except Exception as exception:
logger.error(
"Failed to synchronizace Nástěnka notices: %s", str(exception)
)
return parent_save_response return parent_save_response
def has_change_permission(self, request, obj=None): def has_change_permission(self, request, obj=None):
......
...@@ -4,15 +4,19 @@ from django.db import migrations, models ...@@ -4,15 +4,19 @@ from django.db import migrations, models
class Migration(migrations.Migration): class Migration(migrations.Migration):
dependencies = [ dependencies = [
('contracts', '0061_alter_contract_id_number'), ("contracts", "0061_alter_contract_id_number"),
] ]
operations = [ operations = [
migrations.AddField( migrations.AddField(
model_name='contract', model_name="contract",
name='paper_form_person_responsible', name="paper_form_person_responsible",
field=models.CharField(blank=True, max_length=256, null=True, verbose_name='Osoba zodpovědná za doručení'), field=models.CharField(
blank=True,
max_length=256,
null=True,
verbose_name="Osoba zodpovědná za doručení",
),
), ),
] ]
...@@ -747,10 +747,11 @@ class Contract(NameStrMixin, models.Model): ...@@ -747,10 +747,11 @@ class Contract(NameStrMixin, models.Model):
) )
if ( if (
self.paper_form_state not in ( self.paper_form_state
not in (
self.PaperFormStates.STORED, self.PaperFormStates.STORED,
self.PaperFormStates.SHREDDED, self.PaperFormStates.SHREDDED,
self.PaperFormStates.LOST self.PaperFormStates.LOST,
) )
and not self.paper_form_person_responsible and not self.paper_form_person_responsible
): ):
......
<div class="hidden md:block"> <ul class="flex-col gap-4 flex">
<table class="table table-auto w-full table--striped table--bordered">
<thead>
<tr>
<td class="font-bold">Název</td>
<td>Typy</td>
<td>Platná</td>
<td class="whitespace-nowrap">Účinná od</td>
<td class="whitespace-nowrap">Účinná do</td>
<td class="whitespace-nowrap">Podepsána s</td>
</tr>
</thead>
<tbody>
{% for contract in page %}
<tr>
<td{% if not contract.is_public %} class="!bg-red-100"{% endif %}>
{% if not contract.is_public %}
{% include "contracts/includes/private_info_icon.html" %}
{% endif %}
<a
class="underline"
href="{% url "contracts:view_contract" contract.id %}"
>{{ contract.name }}</a>
</td>
<td{% if not contract.is_public %} class="!bg-red-100"{% endif %}>
<ul class="flex flex-wrap gap-1.5">
{% for type in contract.types.all %}
<li class="flex">
{% include "contracts/includes/tag.html" with url=type.url icon="ico--folder" content=type.name public=contract.is_public %}
</li>
{% endfor %}
</ul>
</td>
<td{% if not contract.is_public %} class="!bg-red-100"{% endif %}>
<i
class="{% if contract.is_valid %}ico--checkmark{% else %}ico--cross{% endif %}"
aria-label="{% if contract.is_public %}Ano{% else %}Ne{% endif %}"
></i>
</td>
<td class="whitespace-nowrap{% if not contract.is_public %} !bg-red-100{% endif %}">
{{ contract.valid_start_date }}
</td>
<td class="whitespace-nowrap{% if not contract.is_public %} !bg-red-100{% endif %}">
{% if contract.valid_end_date %}
{{ contract.valid_end_date }}
{% else %}
<span class="text-grey-200">Neurčité</span>
{% endif %}
</td>
<td{% if not contract.is_public %} class="!bg-red-100"{% endif %}>
<ul class="flex flex-wrap gap-1.5">
{% for signature in contract.signee_signatures.all %}
<li class="flex">
{% if signature.signee.entity_type == signature.signee.EntityTypes.LEGAL_ENTITY or signature.signee.entity_type == signature.signee.EntityTypes.OTHER %}
{% include "contracts/includes/tag.html" with url=signature.signee.url icon="ico--office" content=signature.signee.name public=contract.is_public %}
{% else %}
{% include "contracts/includes/tag.html" with url=signature.signee.url icon="ico--user" content=signature.signee.name public=contract.is_public %}
{% endif %}
</li>
{% endfor %}
</ul>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
<ul class="flex-col gap-4 flex md:hidden">
{% for contract in page %} {% for contract in page %}
<li class="card elevation-10{% if not contract.is_public %} bg-red-100{% endif %}"> <li class="card elevation-10{% if not contract.is_public %} bg-red-100{% endif %}">
<div class="card__body p-5"> <div class="card__body p-5">
...@@ -96,7 +28,11 @@ ...@@ -96,7 +28,11 @@
<tr> <tr>
<td class="pt-1.5">Účinná od:</td> <td class="pt-1.5">Účinná od:</td>
<td class="pt-1.5"> <td class="pt-1.5">
{% if contract.valid_start_date %}
{{ contract.valid_start_date }} {{ contract.valid_start_date }}
{% else %}
<span class="text-grey-200">Neurčité</span>
{% endif %}
</td> </td>
</tr> </tr>
<tr> <tr>
......
...@@ -20,3 +20,6 @@ DEFAULT_CONTRACTEE_DISTRICT="Praha 2" ...@@ -20,3 +20,6 @@ DEFAULT_CONTRACTEE_DISTRICT="Praha 2"
DEFAULT_CONTRACTEE_ICO_NUMBER="71339698" DEFAULT_CONTRACTEE_ICO_NUMBER="71339698"
DEFAULT_STAFF_GROUPS="sso_cen:f,sso_cen:neverejni,sso_cen:smlouvy_ao,sso_cen:smlouvy_po,sso_cen:registr_smluv" DEFAULT_STAFF_GROUPS="sso_cen:f,sso_cen:neverejni,sso_cen:smlouvy_ao,sso_cen:smlouvy_po,sso_cen:registr_smluv"
NASTENKA_API_URL=http://localhost:8009/contracts/api/notices
NASTENKA_API_TOKEN=cirno
...@@ -53,6 +53,7 @@ class RegistryOIDCAuthenticationBackend(PiratesOIDCAuthenticationBackend): ...@@ -53,6 +53,7 @@ class RegistryOIDCAuthenticationBackend(PiratesOIDCAuthenticationBackend):
access_token, options={"verify_signature": False} access_token, options={"verify_signature": False}
) )
user.preferred_username = decoded_access_token["preferred_username"]
user_groups = user.groups.all() user_groups = user.groups.all()
self._remove_old_user_groups( self._remove_old_user_groups(
......
...@@ -244,6 +244,9 @@ if SENTRY_DSN != "": ...@@ -244,6 +244,9 @@ if SENTRY_DSN != "":
## App-specific ## App-specific
NASTENKA_API_URL = env.str("NASTENKA_API_URL")
NASTENKA_API_TOKEN = env.str("NASTENKA_API_TOKEN")
DEFAULT_CONTRACTEE_NAME = env.str("DEFAULT_CONTRACTEE_NAME") DEFAULT_CONTRACTEE_NAME = env.str("DEFAULT_CONTRACTEE_NAME")
DEFAULT_CONTRACTEE_STREET = env.str("DEFAULT_CONTRACTEE_STREET") DEFAULT_CONTRACTEE_STREET = env.str("DEFAULT_CONTRACTEE_STREET")
DEFAULT_CONTRACTEE_ZIP = env.str("DEFAULT_CONTRACTEE_ZIP") DEFAULT_CONTRACTEE_ZIP = env.str("DEFAULT_CONTRACTEE_ZIP")
......
...@@ -21,3 +21,4 @@ Markdown==3.4.3 ...@@ -21,3 +21,4 @@ Markdown==3.4.3
postal==1.1.10 postal==1.1.10
PyJWT==2.6.0 PyJWT==2.6.0
PyYAML==6.0 PyYAML==6.0
requests==2.31.0
# Generated by Django 4.1.4 on 2023-06-15 05:52
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("users", "0003_alter_user_is_staff_based_on_group"),
]
operations = [
migrations.AddField(
model_name="user",
name="preferred_username",
field=models.CharField(
blank=True,
max_length=64,
null=True,
verbose_name="Username v Chobotnici",
),
),
migrations.AlterField(
model_name="user",
name="sso_id",
field=models.CharField(max_length=128, verbose_name="SSO ID"),
),
]
import uuid
from django.conf import settings from django.conf import settings
from django.contrib.auth.models import Group as AuthGroup from django.contrib.auth.models import Group as AuthGroup
from django.contrib.auth.models import Permission from django.contrib.auth.models import Permission
...@@ -18,6 +20,18 @@ class Group: ...@@ -18,6 +20,18 @@ class Group:
class User(pirates_models.AbstractUser): class User(pirates_models.AbstractUser):
preferred_username = models.CharField(
max_length=64,
verbose_name="Username v Chobotnici",
blank=True,
null=True,
)
sso_id = models.CharField(
"SSO ID",
max_length=128,
)
is_staff_based_on_group = models.BooleanField( is_staff_based_on_group = models.BooleanField(
default=True, default=True,
verbose_name="Administrační přístup dle členství ve skupině", verbose_name="Administrační přístup dle členství ve skupině",
...@@ -28,6 +42,8 @@ class User(pirates_models.AbstractUser): ...@@ -28,6 +42,8 @@ class User(pirates_models.AbstractUser):
), ),
) )
USERNAME_FIELD = "preferred_username"
@property @property
def can_approve_contracts(self) -> bool: def can_approve_contracts(self) -> bool:
return self.has_perm("contracts.approve") return self.has_perm("contracts.approve")
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment