diff --git a/contracts/admin.py b/contracts/admin.py index 738d336d2d7e71c3b5dcfa71324d918f228b5cbb..68b92808f99bcda6dbacc63021442740c8ae68f7 100644 --- a/contracts/admin.py +++ b/contracts/admin.py @@ -5,6 +5,11 @@ from django.contrib import admin from django.utils.html import format_html from fieldsets_with_inlines import FieldsetsInlineMixin from import_export import resources +from nested_inline.admin import ( + NestedModelAdmin, + NestedStackedInline, + NestedTabularInline, +) from rangefilter.filters import DateRangeFilter from shared.admin import MarkdownxGuardedModelAdmin @@ -14,15 +19,15 @@ from .models import ( Contract, Contractee, ContracteeSignature, + ContracteeSignatureRepresentative, ContractFile, ContractFilingArea, ContractIntent, ContractIssue, ContractType, - ContractContracteeRepresentative, - ContractSigneeRepresentative, Signee, SigneeSignature, + SigneeSignatureRepresentative, ) @@ -55,55 +60,44 @@ class ContractFileAdmin(IndexHiddenModelAdmin): form = ContractFileAdminForm -class ContracteeSignatureInline(admin.TabularInline): - model = ContracteeSignature +class ContracteeSignatureRepresentativeInline(NestedStackedInline): + model = ContracteeSignatureRepresentative extra = 0 -class SigneeSignatureInline(admin.TabularInline): - model = SigneeSignature +class ContracteeSignatureInline(NestedStackedInline): + model = ContracteeSignature + inlines = (ContracteeSignatureRepresentativeInline,) extra = 0 -class ContractFileInline(admin.TabularInline): - model = ContractFile - form = ContractFileAdminForm +class SigneeSignatureRepresentativeInline(NestedStackedInline): + model = SigneeSignatureRepresentative extra = 0 -class ContractIntentInline(admin.TabularInline): - model = ContractIntent +class SigneeSignatureInline(NestedStackedInline): + model = SigneeSignature + inlines = (SigneeSignatureRepresentativeInline,) extra = 0 -class ContractContracteeRepresentativeInline(admin.TabularInline): +class ContractFileInline(admin.TabularInline): + model = ContractFile form = ContractFileAdminForm - model = ContractContracteeRepresentative extra = 0 -class ContractSigneeRepresentativeInline(admin.TabularInline): - model = ContractSigneeRepresentative +class ContractIntentInline(admin.TabularInline): + model = ContractIntent extra = 0 -class ContractAdmin(FieldsetsInlineMixin, MarkdownxGuardedModelAdmin): +class ContractAdmin(FieldsetsInlineMixin, MarkdownxGuardedModelAdmin, NestedModelAdmin): form = ContractAdminForm readonly_fields = ("created_by",) - #def __init__(self, *args, **kwargs): - #from .models import Contract - - #super().__init__(*args, **kwargs) - - #if hasattr(self, "instance"): - #self.fields["contractee_representatives"].queryset = ( - #Contract - #.objects - #.filter(contract=self.instance) - #) - fieldsets_with_inlines = [ ( "Základní informace", @@ -118,7 +112,7 @@ class ContractAdmin(FieldsetsInlineMixin, MarkdownxGuardedModelAdmin): "legal_state", "primary_contract", ] - } + }, ), ( "Data", @@ -127,7 +121,7 @@ class ContractAdmin(FieldsetsInlineMixin, MarkdownxGuardedModelAdmin): "valid_start_date", "valid_end_date", ] - } + }, ), ( "Náklady", @@ -136,15 +130,11 @@ class ContractAdmin(FieldsetsInlineMixin, MarkdownxGuardedModelAdmin): "cost_amount", "cost_unit", ] - } + }, ), - ContractFileInline, ContracteeSignatureInline, - ContractContracteeRepresentativeInline, SigneeSignatureInline, - ContractSigneeRepresentativeInline, - ( "Odkazy", { @@ -152,11 +142,9 @@ class ContractAdmin(FieldsetsInlineMixin, MarkdownxGuardedModelAdmin): "tender_url", "agreement_url", ] - } + }, ), - ContractIntentInline, - ( "Fyzický dokument", { @@ -164,7 +152,7 @@ class ContractAdmin(FieldsetsInlineMixin, MarkdownxGuardedModelAdmin): "paper_form_state", "filing_area", ] - } + }, ), ( "Doplňující informace", @@ -173,24 +161,19 @@ class ContractAdmin(FieldsetsInlineMixin, MarkdownxGuardedModelAdmin): "issues", "notes", ] - } - ) + }, + ), ] 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): fieldsets_with_inlines.insert( 8, - ( - "Schválení", - { - "fields": ["is_approved"] - } - ), + ("Schválení", {"fields": ["is_approved"]}), ) - + return [ self.make_placeholder(index, fieldset) for index, fieldset in enumerate(fieldsets_with_inlines) @@ -202,13 +185,16 @@ class ContractAdmin(FieldsetsInlineMixin, MarkdownxGuardedModelAdmin): if obj.valid_start_date is None: last_signature_date = None - + for signature_set in ( obj.contractee_signatures.all(), - obj.signee_signatures.all() + obj.signee_signatures.all(), ): for signature in signature_set: - if last_signature_date is None or last_signature_date < signature.date: + if ( + last_signature_date is None + or last_signature_date < signature.date + ): last_signature_date = signature.date obj.valid_start_date = last_signature_date @@ -234,6 +220,7 @@ class ContractAdmin(FieldsetsInlineMixin, MarkdownxGuardedModelAdmin): "is_public", ) + # END Contracts # BEGIN Signing parties @@ -263,7 +250,7 @@ class SigneeAdmin(MarkdownxGuardedModelAdmin): def load_ares_data_button(self, obj): return format_html( - "<button type=\"button\" id=\"load_ares_data\">Načíst data</button>" + '<button type="button" id="load_ares_data">Načíst data</button>' ) load_ares_data_button.allow_tags = True @@ -276,8 +263,8 @@ class SigneeAdmin(MarkdownxGuardedModelAdmin): for model in ( SigneeSignature, ContracteeSignature, - ContractSigneeRepresentative, - ContractContracteeRepresentative, + ContracteeSignatureRepresentative, + SigneeSignatureRepresentative, ContractIntent, ): admin.site.register(model, IndexHiddenModelAdmin) diff --git a/contracts/forms.py b/contracts/forms.py index 5eb5c034ef06c44c675f9915198789cc49ebbd45..36e7719be1a8df94f6318131e1d1339467934c49 100644 --- a/contracts/forms.py +++ b/contracts/forms.py @@ -1,6 +1,5 @@ -import djhacker import dal.autocomplete - +import djhacker from django import forms from django.core.exceptions import ValidationError from webpack_loader.loader import WebpackLoader @@ -18,23 +17,17 @@ class ContractAdminForm(forms.ModelForm): class Meta: widgets = { - "summary": forms.Textarea(attrs={ - "rows": 2 - }), + "summary": forms.Textarea(attrs={"rows": 2}), } class ContractFileAdminForm(forms.ModelForm): class Media: - js = ( - "shared/admin_contract_file_form.js", - ); + js = ("shared/admin_contract_file_form.js",) class Meta: widgets = { - "name": forms.TextInput(attrs={ - "list": "file-types" - }), + "name": forms.TextInput(attrs={"list": "file-types"}), } @@ -48,34 +41,62 @@ class SigneeAdminForm(forms.ModelForm): def clean(self): cleaned_data = super().clean() - + if cleaned_data.get("entity_type") == "natural_person": if cleaned_data.get("ico_number") is not None: - raise ValidationError({"ico_number": "IČO nesmí být pro fyzické osoby definováno."}) - + raise ValidationError( + {"ico_number": "IČO nesmí být pro fyzické osoby definováno."} + ) + if cleaned_data.get("department") is not None: - raise ValidationError({"department": "Organizační složka nesmí být pro fyzické osoby definována."}) - + raise ValidationError( + { + "department": "Organizační složka nesmí být pro fyzické osoby definována." + } + ) + if cleaned_data.get("date_of_birth") is None: - raise ValidationError({"date_of_birth": "Datum narození musí pro fyzické osoby být definováno."}) - + raise ValidationError( + { + "date_of_birth": "Datum narození musí pro fyzické osoby být definováno." + } + ) + if cleaned_data.get("entity_type") == "business_natural_person": if cleaned_data.get("ico_number") is None: - raise ValidationError({"ico_number": "IČO musí být pro podnikající fyzické osoby definováno."}) - + raise ValidationError( + { + "ico_number": "IČO musí být pro podnikající fyzické osoby definováno." + } + ) + if cleaned_data.get("department") is not None: - raise ValidationError({"department": "Organizační složka nesmí být pro podnikající fyzické osoby definována."}) - + raise ValidationError( + { + "department": "Organizační složka nesmí být pro podnikající fyzické osoby definována." + } + ) + if cleaned_data.get("date_of_birth") is not None: - raise ValidationError({"date_of_birth": "Datum narození nesmí pro podnikající fyzické osoby být definováno."}) - + raise ValidationError( + { + "date_of_birth": "Datum narození nesmí pro podnikající fyzické osoby být definováno." + } + ) + if cleaned_data.get("entity_type") == "legal_entity": if cleaned_data.get("ico_number") is None: - raise ValidationError({"ico_number": "IČO musí být pro právnické osoby definováno."}) - + raise ValidationError( + {"ico_number": "IČO musí být pro právnické osoby definováno."} + ) + if cleaned_data.get("date_of_birth") is not None: - raise ValidationError({"date_of_birth": "Datum narození nesmí pro právnické osoby být definováno."}) - + raise ValidationError( + { + "date_of_birth": "Datum narození nesmí pro právnické osoby být definováno." + } + ) + return cleaned_data @@ -86,7 +107,7 @@ djhacker.formfield( forms.ModelChoiceField, widget=dal.autocomplete.ModelSelect2( url="contracts:select2_djhacker_contract_autocomplete" - ) + ), ) djhacker.formfield( @@ -94,7 +115,7 @@ djhacker.formfield( forms.ModelChoiceField, widget=dal.autocomplete.ModelSelect2( url="contracts:select2_djhacker_contract_filing_area_autocomplete" - ) + ), ) djhacker.formfield( @@ -102,7 +123,7 @@ djhacker.formfield( forms.ModelMultipleChoiceField, widget=dal.autocomplete.ModelSelect2Multiple( url="contracts:select2_djhacker_contract_issue_autocomplete" - ) + ), ) djhacker.formfield( @@ -110,7 +131,7 @@ djhacker.formfield( forms.ModelMultipleChoiceField, widget=dal.autocomplete.ModelSelect2Multiple( url="contracts:select2_djhacker_contract_type_autocomplete" - ) + ), ) # END Autocompleted Contract fields @@ -122,7 +143,7 @@ djhacker.formfield( forms.ModelChoiceField, widget=dal.autocomplete.ModelSelect2( url="contracts:select2_djhacker_contractee_signature_autocomplete" - ) + ), ) djhacker.formfield( @@ -130,7 +151,7 @@ djhacker.formfield( forms.ModelChoiceField, widget=dal.autocomplete.ModelSelect2( url="contracts:select2_djhacker_signee_signature_autocomplete" - ) + ), ) # END Autocompleted ContracteeSignature / SigneeSignature fields diff --git a/contracts/migrations/0001_initial.py b/contracts/migrations/0001_initial.py index 0b7815c6521b4330d918a890686f72dec104630d..f4c19d7d67759c4e9cc436d9b880e86bdc90df30 100644 --- a/contracts/migrations/0001_initial.py +++ b/contracts/migrations/0001_initial.py @@ -1,15 +1,15 @@ # Generated by Django 4.1.4 on 2023-03-15 12:22 -import contracts.models -from django.conf import settings -from django.db import migrations, models import django.db.models.deletion import markdownx.models +from django.conf import settings +from django.db import migrations, models + +import contracts.models import shared.models class Migration(migrations.Migration): - initial = True dependencies = [ @@ -18,215 +18,668 @@ class Migration(migrations.Migration): operations = [ migrations.CreateModel( - name='Contract', + name="Contract", fields=[ - ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('all_parties_sign_date', models.DateField(blank=True, null=True, verbose_name='Datum podpisu všech stran')), - ('approval_state', models.CharField(blank=True, choices=[('no', 'Neschválená'), ('yes', 'Schválená')], help_text='Může měnit jen schvalovatel. Pokud je smlouva veřejná, se stavem "Schválená" se vypustí ven.', max_length=7, null=True, verbose_name='Stav schválení')), - ('name', models.CharField(max_length=128, verbose_name='Název')), - ('id_number', models.CharField(blank=True, max_length=128, null=True, verbose_name='Identifikační číslo')), - ('summary', models.TextField(blank=True, max_length=256, null=True, verbose_name='Sumarizace obsahu smlouvy')), - ('valid_start_date', models.DateField(blank=True, null=True, verbose_name='Začátek účinnosti')), - ('valid_end_date', models.DateField(blank=True, null=True, verbose_name='Konec účinnosti')), - ('legal_state', models.CharField(choices=[('valid', 'Platná'), ('invalid', 'Neplatná')], max_length=13, verbose_name='Stav právního ujednání')), - ('public_state', models.CharField(choices=[('yes', 'Veřejná'), ('no', 'Neveřejná')], max_length=7, verbose_name='Veřejnost smlouvy')), - ('paper_form_state', models.CharField(choices=[('sent', 'Odeslaný'), ('stored', 'Uložený'), ('to_shred', 'Ke skartaci'), ('shredded', 'Skartovaný'), ('lost', 'Ztracený')], max_length=8, verbose_name='Stav fyzického dokumentu')), - ('publishing_rejection_comment', models.CharField(blank=True, help_text='Obsah není veřejně přístupný.', max_length=65536, null=True, verbose_name='Důvod nezveřejnění')), - ('tender_url', models.URLField(blank=True, max_length=256, null=True, verbose_name='Odkaz na výběrové řízení')), - ('agreement_url', models.URLField(blank=True, max_length=256, null=True, verbose_name='Odkaz na schválení')), - ('cost_amount', models.PositiveIntegerField(blank=True, null=True, verbose_name='Náklady (Kč)')), - ('cost_unit', models.CharField(blank=True, choices=[('hour', 'Hodina'), ('month', 'Měsíc'), ('year', 'Rok'), ('total', 'Celkem')], max_length=5, null=True, verbose_name='Jednotka nákladů')), - ('notes', markdownx.models.MarkdownxField(blank=True, help_text='Poznámky jsou viditelné pro všechny, kteří mohou smlouvu spravovat.', null=True, verbose_name='Poznámky')), - ('created_by', models.ForeignKey(blank=True, help_text='Informace není veřejně přístupná. Pokud vytváříš novou smlouvu, budeš to ty.', null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='uploaded_contracts', to=settings.AUTH_USER_MODEL, verbose_name='Vytvořena uživatelem')), + ( + "id", + models.BigAutoField( + auto_created=True, + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ( + "all_parties_sign_date", + models.DateField( + blank=True, null=True, verbose_name="Datum podpisu všech stran" + ), + ), + ( + "approval_state", + models.CharField( + blank=True, + choices=[("no", "Neschválená"), ("yes", "Schválená")], + help_text='Může měnit jen schvalovatel. Pokud je smlouva veřejná, se stavem "Schválená" se vypustí ven.', + max_length=7, + null=True, + verbose_name="Stav schválení", + ), + ), + ("name", models.CharField(max_length=128, verbose_name="Název")), + ( + "id_number", + models.CharField( + blank=True, + max_length=128, + null=True, + verbose_name="Identifikační číslo", + ), + ), + ( + "summary", + models.TextField( + blank=True, + max_length=256, + null=True, + verbose_name="Sumarizace obsahu smlouvy", + ), + ), + ( + "valid_start_date", + models.DateField( + blank=True, null=True, verbose_name="Začátek účinnosti" + ), + ), + ( + "valid_end_date", + models.DateField( + blank=True, null=True, verbose_name="Konec účinnosti" + ), + ), + ( + "legal_state", + models.CharField( + choices=[("valid", "Platná"), ("invalid", "Neplatná")], + max_length=13, + verbose_name="Stav právního ujednání", + ), + ), + ( + "public_state", + models.CharField( + choices=[("yes", "Veřejná"), ("no", "Neveřejná")], + max_length=7, + verbose_name="Veřejnost smlouvy", + ), + ), + ( + "paper_form_state", + models.CharField( + choices=[ + ("sent", "Odeslaný"), + ("stored", "Uložený"), + ("to_shred", "Ke skartaci"), + ("shredded", "Skartovaný"), + ("lost", "Ztracený"), + ], + max_length=8, + verbose_name="Stav fyzického dokumentu", + ), + ), + ( + "publishing_rejection_comment", + models.CharField( + blank=True, + help_text="Obsah není veřejně přístupný.", + max_length=65536, + null=True, + verbose_name="Důvod nezveřejnění", + ), + ), + ( + "tender_url", + models.URLField( + blank=True, + max_length=256, + null=True, + verbose_name="Odkaz na výběrové řízení", + ), + ), + ( + "agreement_url", + models.URLField( + blank=True, + max_length=256, + null=True, + verbose_name="Odkaz na schválení", + ), + ), + ( + "cost_amount", + models.PositiveIntegerField( + blank=True, null=True, verbose_name="Náklady (Kč)" + ), + ), + ( + "cost_unit", + models.CharField( + blank=True, + choices=[ + ("hour", "Hodina"), + ("month", "Měsíc"), + ("year", "Rok"), + ("total", "Celkem"), + ], + max_length=5, + null=True, + verbose_name="Jednotka nákladů", + ), + ), + ( + "notes", + markdownx.models.MarkdownxField( + blank=True, + help_text="Poznámky jsou viditelné pro všechny, kteří mohou smlouvu spravovat.", + null=True, + verbose_name="Poznámky", + ), + ), + ( + "created_by", + models.ForeignKey( + blank=True, + help_text="Informace není veřejně přístupná. Pokud vytváříš novou smlouvu, budeš to ty.", + null=True, + on_delete=django.db.models.deletion.SET_NULL, + related_name="uploaded_contracts", + to=settings.AUTH_USER_MODEL, + verbose_name="Vytvořena uživatelem", + ), + ), ], options={ - 'verbose_name': 'Smlouva', - 'verbose_name_plural': 'Smlouvy', - 'permissions': (('approve', 'Schválit / zrušit schválení'),), + "verbose_name": "Smlouva", + "verbose_name_plural": "Smlouvy", + "permissions": (("approve", "Schválit / zrušit schválení"),), }, bases=(shared.models.NameStrMixin, models.Model), ), migrations.CreateModel( - name='Contractee', + name="Contractee", fields=[ - ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('name', models.CharField(default='Česká pirátská strana', max_length=256, verbose_name='Jméno')), - ('address_street_with_number', models.CharField(default='Na Moráni 360/3', max_length=256, verbose_name='Ulice, č.p.')), - ('address_district', models.CharField(default='Praha 2', max_length=256, verbose_name='Obec')), - ('address_zip', models.CharField(default='128 00', max_length=16, verbose_name='PSČ')), - ('address_country', models.CharField(default='CZ', max_length=256, verbose_name='Země')), - ('ico_number', models.CharField(blank=True, default='71339698', max_length=16, null=True, verbose_name='IČO')), - ('department', models.CharField(blank=True, max_length=128, null=True, verbose_name='Organizační složka')), - ('role', models.CharField(blank=True, max_length=256, null=True, verbose_name='Role')), + ( + "id", + models.BigAutoField( + auto_created=True, + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ( + "name", + models.CharField( + default="Česká pirátská strana", + max_length=256, + verbose_name="Jméno", + ), + ), + ( + "address_street_with_number", + models.CharField( + default="Na Moráni 360/3", + max_length=256, + verbose_name="Ulice, č.p.", + ), + ), + ( + "address_district", + models.CharField( + default="Praha 2", max_length=256, verbose_name="Obec" + ), + ), + ( + "address_zip", + models.CharField( + default="128 00", max_length=16, verbose_name="PSČ" + ), + ), + ( + "address_country", + models.CharField(default="CZ", max_length=256, verbose_name="Země"), + ), + ( + "ico_number", + models.CharField( + blank=True, + default="71339698", + max_length=16, + null=True, + verbose_name="IČO", + ), + ), + ( + "department", + models.CharField( + blank=True, + max_length=128, + null=True, + verbose_name="Organizační složka", + ), + ), + ( + "role", + models.CharField( + blank=True, max_length=256, null=True, verbose_name="Role" + ), + ), ], options={ - 'verbose_name': 'Naše smluvní strana', - 'verbose_name_plural': 'Naše smluvní strany', + "verbose_name": "Naše smluvní strana", + "verbose_name_plural": "Naše smluvní strany", }, ), migrations.CreateModel( - name='ContractFilingArea', + name="ContractFilingArea", fields=[ - ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('name', models.CharField(max_length=32, verbose_name='Jméno')), - ('person_responsible', models.CharField(max_length=256, verbose_name='Odpovědná osoba')), + ( + "id", + models.BigAutoField( + auto_created=True, + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ("name", models.CharField(max_length=32, verbose_name="Jméno")), + ( + "person_responsible", + models.CharField(max_length=256, verbose_name="Odpovědná osoba"), + ), ], options={ - 'verbose_name': 'Spisovna', - 'verbose_name_plural': 'Spisovny', + "verbose_name": "Spisovna", + "verbose_name_plural": "Spisovny", }, bases=(shared.models.NameStrMixin, models.Model), ), migrations.CreateModel( - name='ContractIssue', + name="ContractIssue", fields=[ - ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('name', models.CharField(max_length=32, verbose_name='Jméno')), + ( + "id", + models.BigAutoField( + auto_created=True, + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ("name", models.CharField(max_length=32, verbose_name="Jméno")), ], options={ - 'verbose_name': 'Problém se smlouvou', - 'verbose_name_plural': 'Problémy se smlouvami', + "verbose_name": "Problém se smlouvou", + "verbose_name_plural": "Problémy se smlouvami", }, bases=(shared.models.NameStrMixin, models.Model), ), migrations.CreateModel( - name='ContractType', + name="ContractType", fields=[ - ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('name', models.CharField(max_length=32, verbose_name='Jméno')), + ( + "id", + models.BigAutoField( + auto_created=True, + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ("name", models.CharField(max_length=32, verbose_name="Jméno")), ], options={ - 'verbose_name': 'Typ smlouvy', - 'verbose_name_plural': 'Typy smlouvy', + "verbose_name": "Typ smlouvy", + "verbose_name_plural": "Typy smlouvy", }, bases=(shared.models.NameStrMixin, models.Model), ), migrations.CreateModel( - name='Signee', + name="Signee", fields=[ - ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('name', models.CharField(max_length=256, verbose_name='Jméno')), - ('entity_type', models.CharField(choices=[('natural_person', 'Fyzická osoba'), ('legal_entity', 'Právnická osoba'), ('business_natural_person', 'Podnikající fyzická osoba'), ('other', 'Jiné')], default='legal_entity', help_text='Důležité označit správně! Fyzickým osobám nepublikujeme adresu.', max_length=23, verbose_name='Typ')), - ('address_street_with_number', models.CharField(help_text='Veřejné pouze, když typ není nastaven na fyzickou osobu.', max_length=256, verbose_name='Ulice, č.p.')), - ('address_district', models.CharField(max_length=256, verbose_name='Obec')), - ('address_zip', models.CharField(help_text='Veřejné pouze, když typ není nastaven na fyzickou osobu.', max_length=16, verbose_name='PSČ')), - ('address_country', models.CharField(default='CZ', max_length=256, verbose_name='Země')), - ('ico_number', models.CharField(blank=True, help_text='Vyplněním můžeš automaticky načíst data z ARES.', max_length=16, null=True, verbose_name='IČO')), - ('date_of_birth', models.DateField(blank=True, null=True, verbose_name='Datum narození')), - ('department', models.CharField(blank=True, max_length=128, null=True, verbose_name='Organizační složka')), - ('role', models.CharField(blank=True, max_length=256, null=True, verbose_name='Role')), + ( + "id", + models.BigAutoField( + auto_created=True, + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ("name", models.CharField(max_length=256, verbose_name="Jméno")), + ( + "entity_type", + models.CharField( + choices=[ + ("natural_person", "Fyzická osoba"), + ("legal_entity", "Právnická osoba"), + ("business_natural_person", "Podnikající fyzická osoba"), + ("other", "Jiné"), + ], + default="legal_entity", + help_text="Důležité označit správně! Fyzickým osobám nepublikujeme adresu.", + max_length=23, + verbose_name="Typ", + ), + ), + ( + "address_street_with_number", + models.CharField( + help_text="Veřejné pouze, když typ není nastaven na fyzickou osobu.", + max_length=256, + verbose_name="Ulice, č.p.", + ), + ), + ( + "address_district", + models.CharField(max_length=256, verbose_name="Obec"), + ), + ( + "address_zip", + models.CharField( + help_text="Veřejné pouze, když typ není nastaven na fyzickou osobu.", + max_length=16, + verbose_name="PSČ", + ), + ), + ( + "address_country", + models.CharField(default="CZ", max_length=256, verbose_name="Země"), + ), + ( + "ico_number", + models.CharField( + blank=True, + help_text="Vyplněním můžeš automaticky načíst data z ARES.", + max_length=16, + null=True, + verbose_name="IČO", + ), + ), + ( + "date_of_birth", + models.DateField( + blank=True, null=True, verbose_name="Datum narození" + ), + ), + ( + "department", + models.CharField( + blank=True, + max_length=128, + null=True, + verbose_name="Organizační složka", + ), + ), + ( + "role", + models.CharField( + blank=True, max_length=256, null=True, verbose_name="Role" + ), + ), ], options={ - 'verbose_name': 'Jiná smluvní strana', - 'verbose_name_plural': 'Ostatní smluvní strany', + "verbose_name": "Jiná smluvní strana", + "verbose_name_plural": "Ostatní smluvní strany", }, ), migrations.CreateModel( - name='SigneeSignature', + name="SigneeSignature", fields=[ - ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('date', models.DateField(verbose_name='Datum podpisu')), - ('contract', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='signee_signatures', to='contracts.contract', verbose_name='Podpisy jiných smluvních stran')), - ('signee', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='signatures', to='contracts.signee', verbose_name='Smluvní strana')), + ( + "id", + models.BigAutoField( + auto_created=True, + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ("date", models.DateField(verbose_name="Datum podpisu")), + ( + "contract", + models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, + related_name="signee_signatures", + to="contracts.contract", + verbose_name="Podpisy jiných smluvních stran", + ), + ), + ( + "signee", + models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, + related_name="signatures", + to="contracts.signee", + verbose_name="Smluvní strana", + ), + ), ], options={ - 'verbose_name': 'Podpis jiné smluvní strany', - 'verbose_name_plural': 'Podpisy ostatních smluvních stran', + "verbose_name": "Podpis jiné smluvní strany", + "verbose_name_plural": "Podpisy ostatních smluvních stran", }, ), migrations.CreateModel( - name='SigneeRepresentative', + name="SigneeRepresentative", fields=[ - ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('name', models.CharField(max_length=256, verbose_name='Jméno')), - ('function', models.CharField(blank=True, max_length=256, null=True, verbose_name='Funkce')), - ('signee', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='representatives', to='contracts.signee', verbose_name='Smluvní strana')), + ( + "id", + models.BigAutoField( + auto_created=True, + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ("name", models.CharField(max_length=256, verbose_name="Jméno")), + ( + "function", + models.CharField( + blank=True, max_length=256, null=True, verbose_name="Funkce" + ), + ), + ( + "signee", + models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, + related_name="representatives", + to="contracts.signee", + verbose_name="Smluvní strana", + ), + ), ], options={ - 'verbose_name': 'Zástupce', - 'verbose_name_plural': 'Zástupci', + "verbose_name": "Zástupce", + "verbose_name_plural": "Zástupci", }, bases=(contracts.models.RepresentativeMixin, models.Model), ), migrations.CreateModel( - name='ContractIntent', + name="ContractIntent", fields=[ - ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('name', models.CharField(max_length=128, verbose_name='Jméno')), - ('url', models.URLField(max_length=256, verbose_name='Odkaz')), - ('contract', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='intents', to='contracts.contract', verbose_name='Smlouva')), + ( + "id", + models.BigAutoField( + auto_created=True, + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ("name", models.CharField(max_length=128, verbose_name="Jméno")), + ("url", models.URLField(max_length=256, verbose_name="Odkaz")), + ( + "contract", + models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, + related_name="intents", + to="contracts.contract", + verbose_name="Smlouva", + ), + ), ], options={ - 'verbose_name': 'Záměr', - 'verbose_name_plural': 'Záměry', + "verbose_name": "Záměr", + "verbose_name_plural": "Záměry", }, bases=(shared.models.NameStrMixin, models.Model), ), migrations.CreateModel( - name='ContractFile', + name="ContractFile", fields=[ - ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('name', models.CharField(blank=True, max_length=128, null=True, verbose_name='Jméno')), - ('is_public', models.BooleanField(default=False, verbose_name='Veřejně dostupný')), - ('file', models.FileField(upload_to='', verbose_name='Soubor')), - ('contract', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='files', to='contracts.contract', verbose_name='Soubory')), + ( + "id", + models.BigAutoField( + auto_created=True, + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ( + "name", + models.CharField( + blank=True, max_length=128, null=True, verbose_name="Jméno" + ), + ), + ( + "is_public", + models.BooleanField(default=False, verbose_name="Veřejně dostupný"), + ), + ("file", models.FileField(upload_to="", verbose_name="Soubor")), + ( + "contract", + models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, + related_name="files", + to="contracts.contract", + verbose_name="Soubory", + ), + ), ], options={ - 'verbose_name': 'Soubor', - 'verbose_name_plural': 'Soubory', + "verbose_name": "Soubor", + "verbose_name_plural": "Soubory", }, bases=(shared.models.NameStrMixin, models.Model), ), migrations.CreateModel( - name='ContracteeSignature', + name="ContracteeSignature", fields=[ - ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('date', models.DateField(verbose_name='Datum podpisu')), - ('contract', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='contractee_signatures', to='contracts.contract', verbose_name='Podpisy našich smluvních stran')), - ('contractee', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='signatures', to='contracts.contractee', verbose_name='Smluvní strana')), + ( + "id", + models.BigAutoField( + auto_created=True, + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ("date", models.DateField(verbose_name="Datum podpisu")), + ( + "contract", + models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, + related_name="contractee_signatures", + to="contracts.contract", + verbose_name="Podpisy našich smluvních stran", + ), + ), + ( + "contractee", + models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, + related_name="signatures", + to="contracts.contractee", + verbose_name="Smluvní strana", + ), + ), ], options={ - 'verbose_name': 'Podpis naší smluvní strany', - 'verbose_name_plural': 'Podpisy našich smluvních stran', + "verbose_name": "Podpis naší smluvní strany", + "verbose_name_plural": "Podpisy našich smluvních stran", }, ), migrations.CreateModel( - name='ContracteeRepresentative', + name="ContracteeRepresentative", fields=[ - ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('name', models.CharField(max_length=256, verbose_name='Jméno')), - ('function', models.CharField(blank=True, max_length=256, null=True, verbose_name='Funkce')), - ('contractee', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='representatives', to='contracts.contractee', verbose_name='Smluvní strana')), + ( + "id", + models.BigAutoField( + auto_created=True, + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ("name", models.CharField(max_length=256, verbose_name="Jméno")), + ( + "function", + models.CharField( + blank=True, max_length=256, null=True, verbose_name="Funkce" + ), + ), + ( + "contractee", + models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, + related_name="representatives", + to="contracts.contractee", + verbose_name="Smluvní strana", + ), + ), ], options={ - 'verbose_name': 'Zástupce', - 'verbose_name_plural': 'Zástupci', + "verbose_name": "Zástupce", + "verbose_name_plural": "Zástupci", }, bases=(contracts.models.RepresentativeMixin, models.Model), ), migrations.AddField( - model_name='contract', - name='filing_area', - field=models.ForeignKey(blank=True, help_text='Obsah není veřejně přístupný.', null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='filed_contracts', to='contracts.contractfilingarea', verbose_name='Spisovna'), + model_name="contract", + name="filing_area", + field=models.ForeignKey( + blank=True, + help_text="Obsah není veřejně přístupný.", + null=True, + on_delete=django.db.models.deletion.SET_NULL, + related_name="filed_contracts", + to="contracts.contractfilingarea", + verbose_name="Spisovna", + ), ), migrations.AddField( - model_name='contract', - name='issues', - field=models.ManyToManyField(blank=True, help_text='Veřejně nazváno "Poznámky".', to='contracts.contractissue', verbose_name='Problémy'), + model_name="contract", + name="issues", + field=models.ManyToManyField( + blank=True, + help_text='Veřejně nazváno "Poznámky".', + to="contracts.contractissue", + verbose_name="Problémy", + ), ), migrations.AddField( - model_name='contract', - name='primary_contract', - field=models.ForeignKey(blank=True, help_text='Např. pro dodatky nebo objednávky u rámcových smluv.', null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='subcontracts', to='contracts.contract', verbose_name='Primární smlouva'), + model_name="contract", + name="primary_contract", + field=models.ForeignKey( + blank=True, + help_text="Např. pro dodatky nebo objednávky u rámcových smluv.", + null=True, + on_delete=django.db.models.deletion.SET_NULL, + related_name="subcontracts", + to="contracts.contract", + verbose_name="Primární smlouva", + ), ), migrations.AddField( - model_name='contract', - name='public_status_set_by', - field=models.ForeignKey(blank=True, help_text='Obsah není veřejně přístupný.', null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='public_status_altered_contracts', to=settings.AUTH_USER_MODEL, verbose_name='Zveřejněno / nezveřejněno uživatelem'), + model_name="contract", + name="public_status_set_by", + field=models.ForeignKey( + blank=True, + help_text="Obsah není veřejně přístupný.", + null=True, + on_delete=django.db.models.deletion.SET_NULL, + related_name="public_status_altered_contracts", + to=settings.AUTH_USER_MODEL, + verbose_name="Zveřejněno / nezveřejněno uživatelem", + ), ), migrations.AddField( - model_name='contract', - name='types', - field=models.ManyToManyField(to='contracts.contracttype', verbose_name='Typ'), + model_name="contract", + name="types", + field=models.ManyToManyField( + to="contracts.contracttype", verbose_name="Typ" + ), ), ] diff --git a/contracts/migrations/0002_alter_contractee_address_country_and_more.py b/contracts/migrations/0002_alter_contractee_address_country_and_more.py index 026c2995260eb10cbd449f2a86c00c6fe363e7e3..0a17fa7934f301f46ed6d13ce7fee686dd32beea 100644 --- a/contracts/migrations/0002_alter_contractee_address_country_and_more.py +++ b/contracts/migrations/0002_alter_contractee_address_country_and_more.py @@ -4,20 +4,23 @@ from django.db import migrations, models class Migration(migrations.Migration): - dependencies = [ - ('contracts', '0001_initial'), + ("contracts", "0001_initial"), ] operations = [ migrations.AlterField( - model_name='contractee', - name='address_country', - field=models.CharField(default='Česká Republika', max_length=256, verbose_name='Země'), + model_name="contractee", + name="address_country", + field=models.CharField( + default="Česká Republika", max_length=256, verbose_name="Země" + ), ), migrations.AlterField( - model_name='signee', - name='address_country', - field=models.CharField(default='Česká Republika', max_length=256, verbose_name='Země'), + model_name="signee", + name="address_country", + field=models.CharField( + default="Česká Republika", max_length=256, verbose_name="Země" + ), ), ] diff --git a/contracts/migrations/0003_contractcontracteerepresentative_and_more.py b/contracts/migrations/0003_contractcontracteerepresentative_and_more.py index 29fdb316b8028d16e17ef69d40a08074f720c45e..4f17ad9a9e39c88ebfb75d09b82ddfd5616d4d55 100644 --- a/contracts/migrations/0003_contractcontracteerepresentative_and_more.py +++ b/contracts/migrations/0003_contractcontracteerepresentative_and_more.py @@ -1,55 +1,113 @@ # Generated by Django 4.1.4 on 2023-03-16 21:56 -import contracts.models -from django.db import migrations, models import django.db.models.deletion +from django.db import migrations, models +import contracts.models -class Migration(migrations.Migration): +class Migration(migrations.Migration): dependencies = [ - ('contracts', '0002_alter_contractee_address_country_and_more'), + ("contracts", "0002_alter_contractee_address_country_and_more"), ] operations = [ migrations.CreateModel( - name='ContractContracteeRepresentative', + name="ContractContracteeRepresentative", fields=[ - ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('name', models.CharField(max_length=256, verbose_name='Jméno')), - ('function', models.CharField(blank=True, max_length=256, null=True, verbose_name='Funkce')), - ('contract', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='contractee_representatives', to='contracts.contract', verbose_name='Smlouva')), - ('contractee', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='contractee_representatives', to='contracts.contractee', verbose_name='Naše smluvní strana')), + ( + "id", + models.BigAutoField( + auto_created=True, + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ("name", models.CharField(max_length=256, verbose_name="Jméno")), + ( + "function", + models.CharField( + blank=True, max_length=256, null=True, verbose_name="Funkce" + ), + ), + ( + "contract", + models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, + related_name="contractee_representatives", + to="contracts.contract", + verbose_name="Smlouva", + ), + ), + ( + "contractee", + models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, + related_name="contractee_representatives", + to="contracts.contractee", + verbose_name="Naše smluvní strana", + ), + ), ], options={ - 'verbose_name': 'Zástupce naší smluvní strany', - 'verbose_name_plural': 'Zástupci naší smluvní strany', + "verbose_name": "Zástupce naší smluvní strany", + "verbose_name_plural": "Zástupci naší smluvní strany", }, bases=(contracts.models.RepresentativeMixin, models.Model), ), migrations.CreateModel( - name='ContractSigneeRepresentative', + name="ContractSigneeRepresentative", fields=[ - ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('name', models.CharField(max_length=256, verbose_name='Jméno')), - ('function', models.CharField(blank=True, max_length=256, null=True, verbose_name='Funkce')), - ('contract', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='signee_representatives', to='contracts.contract', verbose_name='Smlouva')), - ('signee', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='representatives', to='contracts.signee', verbose_name='Druhá smluvní strana')), + ( + "id", + models.BigAutoField( + auto_created=True, + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ("name", models.CharField(max_length=256, verbose_name="Jméno")), + ( + "function", + models.CharField( + blank=True, max_length=256, null=True, verbose_name="Funkce" + ), + ), + ( + "contract", + models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, + related_name="signee_representatives", + to="contracts.contract", + verbose_name="Smlouva", + ), + ), + ( + "signee", + models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, + related_name="representatives", + to="contracts.signee", + verbose_name="Druhá smluvní strana", + ), + ), ], options={ - 'verbose_name': 'Zástupce druhé smluvní strany', - 'verbose_name_plural': 'Zástupci druhé smluvní strany', + "verbose_name": "Zástupce druhé smluvní strany", + "verbose_name_plural": "Zástupci druhé smluvní strany", }, bases=(contracts.models.RepresentativeMixin, models.Model), ), migrations.RemoveField( - model_name='signeerepresentative', - name='signee', + model_name="signeerepresentative", + name="signee", ), migrations.DeleteModel( - name='ContracteeRepresentative', + name="ContracteeRepresentative", ), migrations.DeleteModel( - name='SigneeRepresentative', + name="SigneeRepresentative", ), ] diff --git a/contracts/migrations/0004_alter_contract_options_and_more.py b/contracts/migrations/0004_alter_contract_options_and_more.py index c66a49e0d75e447182d5e323ac456076c103a185..21cf17861cd1177e17b2397e4b5c5ee5c1d92e7b 100644 --- a/contracts/migrations/0004_alter_contract_options_and_more.py +++ b/contracts/migrations/0004_alter_contract_options_and_more.py @@ -4,56 +4,75 @@ from django.db import migrations, models class Migration(migrations.Migration): - dependencies = [ - ('contracts', '0003_contractcontracteerepresentative_and_more'), + ("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'}, + 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'}, + 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'}, + 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'}, + 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', + model_name="contract", + name="approval_state", ), migrations.RemoveField( - model_name='contract', - name='public_state', + 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á'), + 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á'), + 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ě'), + 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ě'), + model_name="signee", + name="address_country", + field=models.CharField(default="CZ", max_length=256, verbose_name="Země"), ), ] diff --git a/contracts/migrations/0005_alter_contract_notes_and_more.py b/contracts/migrations/0005_alter_contract_notes_and_more.py index c4e8e37b1b860903f368552c89d0c35f9d9f3060..bb0a73ff03f0f96da58bdcda089222570df7ec9b 100644 --- a/contracts/migrations/0005_alter_contract_notes_and_more.py +++ b/contracts/migrations/0005_alter_contract_notes_and_more.py @@ -1,29 +1,37 @@ # Generated by Django 4.1.4 on 2023-03-20 16:11 -from django.db import migrations, models import markdownx.models +from django.db import migrations, models class Migration(migrations.Migration): - dependencies = [ - ('contracts', '0004_alter_contract_options_and_more'), + ("contracts", "0004_alter_contract_options_and_more"), ] operations = [ migrations.AlterField( - model_name='contract', - name='notes', - field=markdownx.models.MarkdownxField(blank=True, help_text='Poznámky jsou viditelné pro všechny, kteří mohou smlouvu spravovat a pro tajné čtenáře.', null=True, verbose_name='Poznámky'), + model_name="contract", + name="notes", + field=markdownx.models.MarkdownxField( + blank=True, + help_text="Poznámky jsou viditelné pro všechny, kteří mohou smlouvu spravovat a pro tajné čtenáře.", + null=True, + verbose_name="Poznámky", + ), ), migrations.AlterField( - model_name='contractee', - name='address_country', - field=models.CharField(default='Česká Republika', max_length=256, verbose_name='Země'), + model_name="contractee", + name="address_country", + field=models.CharField( + default="Česká Republika", max_length=256, verbose_name="Země" + ), ), migrations.AlterField( - model_name='signee', - name='address_country', - field=models.CharField(default='Česká Republika', max_length=256, verbose_name='Země'), + model_name="signee", + name="address_country", + field=models.CharField( + default="Česká Republika", max_length=256, verbose_name="Země" + ), ), ] diff --git a/contracts/migrations/0006_alter_contract_filing_area_and_more.py b/contracts/migrations/0006_alter_contract_filing_area_and_more.py index 7aa861f6bd058d823cdb1bd42b1bb39655ef0a60..f328bfca608b11ab1ee2c79a701230149a6867aa 100644 --- a/contracts/migrations/0006_alter_contract_filing_area_and_more.py +++ b/contracts/migrations/0006_alter_contract_filing_area_and_more.py @@ -1,54 +1,77 @@ # Generated by Django 4.1.4 on 2023-03-22 09:14 -from django.db import migrations, models import django.db.models.deletion +from django.db import migrations, models class Migration(migrations.Migration): - dependencies = [ - ('contracts', '0005_alter_contract_notes_and_more'), + ("contracts", "0005_alter_contract_notes_and_more"), ] operations = [ migrations.AlterField( - model_name='contract', - name='filing_area', - field=models.ForeignKey(blank=True, help_text='Obsah není veřejně přístupný.', null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='contracts', to='contracts.contractfilingarea', verbose_name='Spisovna'), + model_name="contract", + name="filing_area", + field=models.ForeignKey( + blank=True, + help_text="Obsah není veřejně přístupný.", + null=True, + on_delete=django.db.models.deletion.SET_NULL, + related_name="contracts", + to="contracts.contractfilingarea", + verbose_name="Spisovna", + ), ), migrations.AlterField( - model_name='contract', - name='is_approved', - field=models.BooleanField(help_text='Mohou měnit jen schvalovatelé. Pokud je smlouva veřejná, schválením se vypustí ven.', verbose_name='Je schválená'), + model_name="contract", + name="is_approved", + field=models.BooleanField( + help_text="Mohou měnit jen schvalovatelé. Pokud je smlouva veřejná, schválením se vypustí ven.", + verbose_name="Je schválená", + ), ), migrations.AlterField( - model_name='contract', - name='is_public', - field=models.BooleanField(help_text='Neveřejné smlouvy nejsou vidět bez přihlášení jako min. tajný čtenář.', verbose_name='Je veřejná'), + model_name="contract", + name="is_public", + field=models.BooleanField( + help_text="Neveřejné smlouvy nejsou vidět bez přihlášení jako min. tajný čtenář.", + verbose_name="Je veřejná", + ), ), migrations.AlterField( - model_name='contract', - name='issues', - field=models.ManyToManyField(blank=True, help_text='Veřejně nazváno "Poznámky".', related_name='contracts', to='contracts.contractissue', verbose_name='Problémy'), + model_name="contract", + name="issues", + field=models.ManyToManyField( + blank=True, + help_text='Veřejně nazváno "Poznámky".', + related_name="contracts", + to="contracts.contractissue", + verbose_name="Problémy", + ), ), migrations.AlterField( - model_name='contract', - name='types', - field=models.ManyToManyField(related_name='contracts', to='contracts.contracttype', verbose_name='Typ'), + model_name="contract", + name="types", + field=models.ManyToManyField( + related_name="contracts", + to="contracts.contracttype", + verbose_name="Typ", + ), ), migrations.AlterField( - model_name='contractee', - name='address_country', - field=models.CharField(default='CZ', max_length=256, verbose_name='Země'), + model_name="contractee", + name="address_country", + field=models.CharField(default="CZ", max_length=256, verbose_name="Země"), ), migrations.AlterField( - model_name='contractfile', - name='file', - field=models.FileField(upload_to='private/', verbose_name='Soubor'), + model_name="contractfile", + name="file", + field=models.FileField(upload_to="private/", verbose_name="Soubor"), ), migrations.AlterField( - model_name='signee', - name='address_country', - field=models.CharField(default='CZ', max_length=256, verbose_name='Země'), + model_name="signee", + name="address_country", + field=models.CharField(default="CZ", max_length=256, verbose_name="Země"), ), ] diff --git a/contracts/migrations/0007_contracteesignaturerepresentative_and_more.py b/contracts/migrations/0007_contracteesignaturerepresentative_and_more.py new file mode 100644 index 0000000000000000000000000000000000000000..c1de9cc4a92c080edc89433a9874a1c7e4f7105d --- /dev/null +++ b/contracts/migrations/0007_contracteesignaturerepresentative_and_more.py @@ -0,0 +1,99 @@ +# Generated by Django 4.1.4 on 2023-03-22 09:38 + +import django.db.models.deletion +from django.db import migrations, models + +import contracts.models + + +class Migration(migrations.Migration): + dependencies = [ + ("contracts", "0006_alter_contract_filing_area_and_more"), + ] + + operations = [ + migrations.CreateModel( + name="ContracteeSignatureRepresentative", + fields=[ + ( + "id", + models.BigAutoField( + auto_created=True, + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ("name", models.CharField(max_length=256, verbose_name="Jméno")), + ( + "function", + models.CharField( + blank=True, max_length=256, null=True, verbose_name="Funkce" + ), + ), + ( + "contractee_signature", + models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, + related_name="representatives", + to="contracts.contracteesignature", + verbose_name="Podpis naši smluvní strany", + ), + ), + ], + options={ + "verbose_name": "Zástupce naší smluvní strany", + "verbose_name_plural": "Zástupci naší smluvní strany", + }, + bases=(contracts.models.RepresentativeMixin, models.Model), + ), + migrations.CreateModel( + name="SigneeSignatureRepresentative", + fields=[ + ( + "id", + models.BigAutoField( + auto_created=True, + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ("name", models.CharField(max_length=256, verbose_name="Jméno")), + ( + "function", + models.CharField( + blank=True, max_length=256, null=True, verbose_name="Funkce" + ), + ), + ( + "signee_signature", + models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, + related_name="representatives", + to="contracts.signeesignature", + verbose_name="Podpis druhé smluvní strany", + ), + ), + ], + options={ + "verbose_name": "Zástupce jiné smluvní strany", + "verbose_name_plural": "Zástupci jiných smluvních stran", + }, + bases=(contracts.models.RepresentativeMixin, models.Model), + ), + migrations.RemoveField( + model_name="contractsigneerepresentative", + name="contract", + ), + migrations.RemoveField( + model_name="contractsigneerepresentative", + name="signee", + ), + migrations.DeleteModel( + name="ContractContracteeRepresentative", + ), + migrations.DeleteModel( + name="ContractSigneeRepresentative", + ), + ] diff --git a/contracts/migrations/0008_alter_contracteesignaturerepresentative_options_and_more.py b/contracts/migrations/0008_alter_contracteesignaturerepresentative_options_and_more.py new file mode 100644 index 0000000000000000000000000000000000000000..22c3464d117dd1a3ad7cd02607b2799c2aca2d0a --- /dev/null +++ b/contracts/migrations/0008_alter_contracteesignaturerepresentative_options_and_more.py @@ -0,0 +1,20 @@ +# Generated by Django 4.1.4 on 2023-03-22 09:55 + +from django.db import migrations + + +class Migration(migrations.Migration): + dependencies = [ + ("contracts", "0007_contracteesignaturerepresentative_and_more"), + ] + + operations = [ + migrations.AlterModelOptions( + name="contracteesignaturerepresentative", + options={"verbose_name": "Zástupce", "verbose_name_plural": "Zástupci"}, + ), + migrations.AlterModelOptions( + name="signeesignaturerepresentative", + options={"verbose_name": "Zástupce", "verbose_name_plural": "Zástupci"}, + ), + ] diff --git a/contracts/models.py b/contracts/models.py index 65e305376c490463ff327df1bba39080d74916ca..811b5a502dc746c7ac0f6fdee5c65f15024c5878 100644 --- a/contracts/models.py +++ b/contracts/models.py @@ -77,7 +77,7 @@ class Signee(models.Model): blank=True, null=True, verbose_name="IČO", - help_text="Vyplněním můžeš automaticky načíst data z ARES." + help_text="Vyplněním můžeš automaticky načíst data z ARES.", ) # WARNING: Legal entity status dependent! date_of_birth = models.DateField( @@ -108,16 +108,13 @@ class Signee(models.Model): @property def url(self) -> str: - return reverse( - "contracts:view_signee", - args=(self.id,) - ) + return reverse("contracts:view_signee", args=(self.id,)) @property def entity_has_public_address(self) -> bool: return self.entity_type in ( self.EntityTypes.LEGAL_ENTITY, - self.EntityTypes.OTHER + self.EntityTypes.OTHER, ) def __str__(self) -> str: @@ -190,10 +187,7 @@ class Contractee(models.Model): @property def url(self) -> str: - return reverse( - "contracts:view_contractee", - args=(self.id,) - ) + return reverse("contracts:view_contractee", args=(self.id,)) class Meta: app_label = "contracts" @@ -218,10 +212,7 @@ class ContractType(NameStrMixin, models.Model): @property def url(self) -> str: - return reverse( - "contracts:view_contract_type", - args=(self.id,) - ) + return reverse("contracts:view_contract_type", args=(self.id,)) class Meta: app_label = "contracts" @@ -238,10 +229,7 @@ class ContractIssue(NameStrMixin, models.Model): @property def url(self) -> str: - return reverse( - "contracts:view_contract_issue", - args=(self.id,) - ) + return reverse("contracts:view_contract_issue", args=(self.id,)) class Meta: app_label = "contracts" @@ -263,10 +251,7 @@ class ContractFilingArea(NameStrMixin, models.Model): @property def url(self) -> str: - return reverse( - "contracts:view_contract_filing_area", - args=(self.id,) - ) + return reverse("contracts:view_contract_filing_area", args=(self.id,)) class Meta: app_label = "contracts" @@ -378,9 +363,8 @@ class Contract(NameStrMixin, models.Model): is_public = models.BooleanField( verbose_name="Je veřejná", help_text=( - "Neveřejné smlouvy nejsou vidět bez přihlášení " - "jako min. tajný čtenář." - ) + "Neveřejné smlouvy nejsou vidět bez přihlášení " "jako min. tajný čtenář." + ), ) paper_form_state = models.CharField( @@ -426,9 +410,7 @@ class Contract(NameStrMixin, models.Model): TOTAL = "total", "Celkem" cost_amount = models.PositiveIntegerField( - blank=True, - null=True, - verbose_name="Náklady (Kč)" + blank=True, null=True, verbose_name="Náklady (Kč)" ) cost_unit = models.CharField( @@ -436,7 +418,7 @@ class Contract(NameStrMixin, models.Model): choices=CostUnits.choices, blank=True, null=True, - verbose_name="Jednotka nákladů" + verbose_name="Jednotka nákladů", ) filing_area = models.ForeignKey( @@ -529,83 +511,12 @@ class Contract(NameStrMixin, models.Model): and signees_latest_sign_date is not None ): self.all_parties_sign_date = max( - ( - contractees_latest_sign_date, - signees_latest_sign_date - ) + (contractees_latest_sign_date, signees_latest_sign_date) ) self.save() -class ContractContracteeRepresentative(RepresentativeMixin, models.Model): - contract = models.ForeignKey( - Contract, - on_delete=models.CASCADE, - related_name="contractee_representatives", - verbose_name="Smlouva" - ) - - contractee = models.ForeignKey( - Contractee, - on_delete=models.CASCADE, - related_name="contractee_representatives", - verbose_name="Naše smluvní strana", - ) - - name = models.CharField( - max_length=256, - verbose_name="Jméno", - ) - - function = models.CharField( - max_length=256, - blank=True, - null=True, - verbose_name="Funkce", - ) - - class Meta: - app_label = "contracts" - - verbose_name = "Zástupce naší smluvní strany" - verbose_name_plural = "Zástupci naší smluvní strany" - - -class ContractSigneeRepresentative(RepresentativeMixin, models.Model): - contract = models.ForeignKey( - Contract, - on_delete=models.CASCADE, - related_name="signee_representatives", - verbose_name="Smlouva" - ) - - signee = models.ForeignKey( - Signee, - on_delete=models.CASCADE, - related_name="representatives", - verbose_name="Druhá smluvní strana", - ) - - name = models.CharField( - max_length=256, - verbose_name="Jméno", - ) - - function = models.CharField( - max_length=256, - blank=True, - null=True, - verbose_name="Funkce", - ) - - class Meta: - app_label = "contracts" - - verbose_name = "Zástupce jiné smluvní strany" - verbose_name_plural = "Zástupci jiných smluvních stran" - - class ContractFile(NameStrMixin, models.Model): name = models.CharField( max_length=128, @@ -703,14 +614,63 @@ class SigneeSignature(models.Model): return f"{str(self.signee)} - {self.date}" +class ContracteeSignatureRepresentative(RepresentativeMixin, models.Model): + contractee_signature = models.ForeignKey( + ContracteeSignature, + on_delete=models.CASCADE, + related_name="representatives", + verbose_name="Podpis naši smluvní strany", + ) + + name = models.CharField( + max_length=256, + verbose_name="Jméno", + ) + + function = models.CharField( + max_length=256, + blank=True, + null=True, + verbose_name="Funkce", + ) + + class Meta: + app_label = "contracts" + + verbose_name = "Zástupce" + verbose_name_plural = "Zástupci" + + +class SigneeSignatureRepresentative(RepresentativeMixin, models.Model): + signee_signature = models.ForeignKey( + SigneeSignature, + on_delete=models.CASCADE, + related_name="representatives", + verbose_name="Podpis druhé smluvní strany", + ) + + name = models.CharField( + max_length=256, + verbose_name="Jméno", + ) + + function = models.CharField( + max_length=256, + blank=True, + null=True, + verbose_name="Funkce", + ) + + class Meta: + app_label = "contracts" + + verbose_name = "Zástupce" + verbose_name_plural = "Zástupci" + + @receiver(post_save, sender=ContracteeSignature) @receiver(post_save, sender=SigneeSignature) -def signing_parties_post_save_update_dates( - sender, - instance, - *args, - **kwargs -) -> None: +def signing_parties_post_save_update_dates(sender, instance, *args, **kwargs) -> None: instance.contract.calculate_signing_parties_sign_date() diff --git a/contracts/templates/contracts/includes/pagination.html b/contracts/templates/contracts/includes/pagination.html index b8ab90a24bd60ccb70784968730dda9cb1b54301..d562a598a632a6e233b88da1e4bdcb946b8ea7e4 100644 --- a/contracts/templates/contracts/includes/pagination.html +++ b/contracts/templates/contracts/includes/pagination.html @@ -81,4 +81,4 @@ </a> </nav> </div> -{% endif %} +{% endif %} diff --git a/contracts/templates/contracts/includes/tag.html b/contracts/templates/contracts/includes/tag.html index 1b19d20c059eedde829399d54494c34faea4fc6f..c5d8eff2ca98debfac129b7852ac9b2aa42b461e 100644 --- a/contracts/templates/contracts/includes/tag.html +++ b/contracts/templates/contracts/includes/tag.html @@ -1,4 +1,4 @@ <a class="flex gap-2 items-baseline w-min p-1.5 rounded-sm text-ellipsis whitespace-nowrap bg-gray-200 duration-100 hover:bg-gray-300 hover:no-underline" href="{{ url }}" ->{% if icon %}<i class="{{ icon }}"></i>{% endif %}{{ content }}</a> +>{% if icon %}<i class="{{ icon }}"></i>{% endif %}{{ content }}</a> diff --git a/contracts/templates/contracts/view_contract.html b/contracts/templates/contracts/view_contract.html index 911499b22d0529db7a0b80f989db18f25b4f0e92..8051b35d3f2def85a2180ab818d137b1997f2aa0 100644 --- a/contracts/templates/contracts/view_contract.html +++ b/contracts/templates/contracts/view_contract.html @@ -17,7 +17,7 @@ <i class="ico--info mr-3"></i>Základní informace </td> </tr> - + {% if contract.id_number %} <tr> <td class="w-1/5 !p-2.5">Identifikační číslo</td> @@ -119,7 +119,7 @@ {% endwith %} </td> </tr> - + {% if user.can_view_confidential %} <tr> <td class="w-1/5 !p-2.5"> @@ -147,7 +147,7 @@ {% endif %} </tbody> </table> - + <div class="flex gap-7"> <table class="table table-auto w-full table--striped table--bordered mb-7"> <tbody> @@ -156,7 +156,7 @@ <i class="ico--folder-open mr-3"></i>Fyzický dokument </td> </tr> - + <tr> <td class="w-1/5 !p-2.5">Stav</td> <td class="w-4/5 !p-2.5">{{ contract.get_paper_form_state_display }}</td> @@ -179,7 +179,7 @@ <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> @@ -197,7 +197,7 @@ </tbody> </table> </div> - + <table class="table table-auto w-full table--striped table--bordered mb-7"> <tbody> <tr> @@ -205,7 +205,7 @@ <i class="ico--link mr-3"></i>Odkazy </td> </tr> - + <tr> <td class="w-1/5 !p-2.5">Výběrové řízení</td> <td class="w-4/5 !p-2.5"> @@ -252,7 +252,7 @@ </tr> </tbody> </table> - + {% with contract.issues.all as issues %} {% if issues or user.can_view_confidential and contract.notes %} <table class="table table-auto w-full table--striped table--bordered mb-10"> @@ -262,7 +262,7 @@ <i class="ico--question mr-3"></i>Doplňující informace </td> </tr> - + {% if issues %} <tr> <td class="w-1/5 !p-2.5">{% if not user.can_view_confidential %}Poznámky{% else %}Problémy{% endif %}</td> @@ -277,7 +277,7 @@ </td> </tr> {% endif %} - + {% if user.can_view_confidential and contract.notes %} <tr> <td class="w-1/5 !p-2.5"> @@ -341,7 +341,7 @@ {% endif %} </address> - {% with contract.contractee_representatives.all as representatives %} + {% with signature.representatives.all as representatives %} {% if representatives %} <div class="block mb-2"> <p class="block mb-2"> diff --git a/contracts/templates/contracts/view_contractee.html b/contracts/templates/contracts/view_contractee.html index 123be37ea05776af486740274bca5b0b887a3ffd..b5712eab0446a8619c2182e35377887d7094d9dc 100644 --- a/contracts/templates/contracts/view_contractee.html +++ b/contracts/templates/contracts/view_contractee.html @@ -25,7 +25,7 @@ {{ contractee.address_street_with_number }}<br> {{ contractee.address_zip }} {{ contractee.address_district }}<br> {{ contractee.get_address_country_display }}<br> - + {% if contractee.ico_number %} IČO: {{ contractee.ico_number }}<br> {% endif %} diff --git a/contracts/templates/contracts/view_signee.html b/contracts/templates/contracts/view_signee.html index e382fdc2b227cd4ad845a50dad3c8e81e067b5fa..3fe8e62029755923a299fd016b3fa74de213094c 100644 --- a/contracts/templates/contracts/view_signee.html +++ b/contracts/templates/contracts/view_signee.html @@ -21,10 +21,10 @@ ({{ signee.role }}) {% endif %} </div> - + <div class="mb-1"> {{ signee.get_entity_type_display }} - + {% if not signee.entity_has_public_address %} {% if user.can_view_confidential %} <div class="my-2 flex items-center"> @@ -36,7 +36,7 @@ {% endif %} {% endif %} </div> - + {% if user.can_view_confidential or signee.entity_has_public_address %} {{ signee.address_street_with_number }}<br> {{ signee.address_zip }} {{ signee.address_district }}<br> @@ -44,7 +44,7 @@ {% else %} {{ signee.address_district }}<br> {% endif %} - + {% if signee.ico_number %} IČO: {{ signee.ico_number }}<br> {% endif %} diff --git a/contracts/urls.py b/contracts/urls.py index b0fe3a61e6685e514cb5bfb8d5157b46ce5fc0e1..2dcfbb61626df12e4c6903e18938171cc62c1311 100644 --- a/contracts/urls.py +++ b/contracts/urls.py @@ -1,74 +1,41 @@ import dal.autocomplete - from django.urls import path -from . import views, models +from . import models, views app_name = "contracts" urlpatterns = [ path("", views.index, name="index"), path("contracts/<int:id>", views.view_contract, name="view_contract"), - path( "contracts/filing-areas/<int:id>", views.view_contract_filing_area, - name="view_contract_filing_area" + name="view_contract_filing_area", ), path( "contracts/issues/<int:id>", views.view_contract_issue, - name="view_contract_issue" + name="view_contract_issue", ), path( - "contracts/types/<int:id>", - views.view_contract_type, - name="view_contract_type" + "contracts/types/<int:id>", views.view_contract_type, name="view_contract_type" ), - path( "contracts/filing-areas", views.view_contract_filing_areas, - name="view_contract_filing_areas" - ), - path( - "contracts/issues", - views.view_contract_issues, - name="view_contract_issues" - ), - path( - "contracts/types", - views.view_contract_types, - name="view_contract_types" + name="view_contract_filing_areas", ), - + path("contracts/issues", views.view_contract_issues, name="view_contract_issues"), + path("contracts/types", views.view_contract_types, name="view_contract_types"), path( "contracts/files/<str:pk>", views.ContractFileDownloadView.as_view(), name="download_contract_file", ), - - path( - "contractees", - views.view_contractees, - name="view_contractees" - ), - path( - "signee", - views.view_signees, - name="view_signees" - ), - - path( - "contractees/<int:id>", - views.view_contractee, - name="view_contractee" - ), - path( - "signee/<int:id>", - views.view_signee, - name="view_signee" - ), - + path("contractees", views.view_contractees, name="view_contractees"), + path("signee", views.view_signees, name="view_signees"), + path("contractees/<int:id>", views.view_contractee, name="view_contractee"), + path("signee/<int:id>", views.view_signee, name="view_signee"), path( "contracts/autocomplete", dal.autocomplete.Select2QuerySetView.as_view(model=models.Contract), @@ -109,10 +76,9 @@ urlpatterns = [ dal.autocomplete.Select2QuerySetView.as_view(model=models.ContracteeSignature), name="select2_djhacker_contractee_signature_autocomplete", ), - path( "ares-info-proxy/<int:ico>", views.get_ares_info, name="get_ares_info", - ) + ), ] diff --git a/contracts/views.py b/contracts/views.py index 9a95bed328ae04166f7d1241334630c9eb2f8711..02d17a4a1d11844c87366f1273f2226636c328ce 100644 --- a/contracts/views.py +++ b/contracts/views.py @@ -1,11 +1,10 @@ import requests - from django.conf import settings from django.core.paginator import Paginator from django.http import HttpResponse from django.shortcuts import render -from django_http_exceptions import HTTPExceptions from django_downloadview import ObjectDownloadView +from django_http_exceptions import HTTPExceptions from guardian.shortcuts import get_objects_for_user from .models import Contract, ContractFile @@ -40,9 +39,7 @@ def get_base_context(request) -> dict: def get_pagination(request, objects) -> tuple: paginator = Paginator(objects, 25) - page = paginator.get_page( - request.GET.get("page") - ) + page = paginator.get_page(request.GET.get("page")) return page, paginator @@ -82,9 +79,7 @@ def index(request): def view_contract(request, id: int): - filter = { - "is_approved": True - } + filter = {"is_approved": True} if not request.user.has_perm("contracts.view_confidential"): filter["is_public"] = True @@ -111,14 +106,12 @@ def view_contract(request, id: int): def view_contract_filing_area(request, id: int): - filing_area = ( - get_objects_for_user(request.user, "contracts.view_contractfilingarea") - .get(id=id) - ) + filing_area = get_objects_for_user( + request.user, "contracts.view_contractfilingarea" + ).get(id=id) contracts_page, contracts_paginator = get_paginated_contracts( - request, - {"filing_area": filing_area} + request, {"filing_area": filing_area} ) return render( @@ -139,14 +132,12 @@ def view_contract_filing_area(request, id: int): def view_contract_issue(request, id: int): - issue = ( - get_objects_for_user(request.user, "contracts.view_contractissue") - .get(id=id) + issue = get_objects_for_user(request.user, "contracts.view_contractissue").get( + id=id ) contracts_page, contracts_paginator = get_paginated_contracts( - request, - {"issues": issue} + request, {"issues": issue} ) return render( @@ -164,14 +155,10 @@ def view_contract_issue(request, id: int): def view_contract_type(request, id: int): - type_ = ( - get_objects_for_user(request.user, "contracts.view_contracttype") - .get(id=id) - ) + type_ = get_objects_for_user(request.user, "contracts.view_contracttype").get(id=id) contracts_page, contracts_paginator = get_paginated_contracts( - request, - {"types": type_} + request, {"types": type_} ) return render( @@ -189,14 +176,12 @@ def view_contract_type(request, id: int): def view_contractee(request, id: int): - contractee = ( - get_objects_for_user(request.user, "contracts.view_contractee") - .get(id=id) + contractee = get_objects_for_user(request.user, "contracts.view_contractee").get( + id=id ) contracts_page, contracts_paginator = get_paginated_contracts( - request, - {"contractee_signatures__contractee": contractee} + request, {"contractee_signatures__contractee": contractee} ) return render( @@ -214,14 +199,10 @@ def view_contractee(request, id: int): def view_signee(request, id: int): - signee = ( - get_objects_for_user(request.user, "contracts.view_signee") - .get(id=id) - ) + signee = get_objects_for_user(request.user, "contracts.view_signee").get(id=id) contracts_page, contracts_paginator = get_paginated_contracts( - request, - {"signee_signatures__signee": signee} + request, {"signee_signatures__signee": signee} ) return render( @@ -244,13 +225,10 @@ def view_signee(request, id: int): def view_contract_filing_areas(request): - filing_areas = ( - get_objects_for_user( - request.user, - "contracts.view_contractfilingarea", - ). - order_by("name") - ) + filing_areas = get_objects_for_user( + request.user, + "contracts.view_contractfilingarea", + ).order_by("name") page, paginator = get_pagination(request, filing_areas) @@ -263,18 +241,15 @@ def view_contract_filing_areas(request): "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") - ) + issues = get_objects_for_user( + request.user, + "contracts.view_contractissue", + ).order_by("name") page, paginator = get_pagination(request, issues) @@ -284,9 +259,7 @@ def view_contract_issues(request): { **get_base_context(request), "title": ( - "Poznámky" - if not request.user.can_view_confidential - else "Problémy" + "Poznámky" if not request.user.can_view_confidential else "Problémy" ), "description": ( "Poznámky ke smlouvám." @@ -295,18 +268,15 @@ def view_contract_issues(request): ), "page": page, "paginator": paginator, - } + }, ) def view_contract_types(request): - types = ( - get_objects_for_user( - request.user, - "contracts.view_contracttype", - ). - order_by("name") - ) + types = get_objects_for_user( + request.user, + "contracts.view_contracttype", + ).order_by("name") page, paginator = get_pagination(request, types) @@ -319,18 +289,15 @@ def view_contract_types(request): "description": "Typy smluv.", "page": page, "paginator": paginator, - } + }, ) def view_contractees(request): - contractees = ( - get_objects_for_user( - request.user, - "contracts.view_contractee", - ). - order_by("name") - ) + contractees = get_objects_for_user( + request.user, + "contracts.view_contractee", + ).order_by("name") page, paginator = get_pagination(request, contractees) @@ -343,18 +310,15 @@ def view_contractees(request): "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") - ) + contractees = get_objects_for_user( + request.user, + "contracts.view_signee", + ).order_by("name") page, paginator = get_pagination(request, contractees) @@ -367,7 +331,7 @@ def view_signees(request): "description": "Jiné smluvní strany.", "page": page, "paginator": paginator, - } + }, ) @@ -386,5 +350,5 @@ def get_ares_info(request, ico: int): return HttpResponse( content=ares_info.content, status=ares_info.status_code, - content_type=ares_info.headers.get("Content-Type") + content_type=ares_info.headers.get("Content-Type"), ) diff --git a/oidc/auth.py b/oidc/auth.py index 1ec381397eb91635cc8e626e4683c4458da169b9..6d7be2d8ecace57005ed76618db44910ab105d90 100644 --- a/oidc/auth.py +++ b/oidc/auth.py @@ -1,6 +1,6 @@ -import jwt import logging +import jwt from django.conf import settings from django.contrib.auth.models import Group from pirates.auth import PiratesOIDCAuthenticationBackend @@ -43,11 +43,17 @@ class RegistryOIDCAuthenticationBackend(PiratesOIDCAuthenticationBackend): if user is None: return - decoded_access_token = jwt.decode(access_token, options={"verify_signature": False}) + decoded_access_token = jwt.decode( + access_token, options={"verify_signature": False} + ) user_groups = user.groups.all() - self._remove_old_user_groups(user, decoded_access_token, user_groups=user_groups) - self._assign_new_user_groups(user, decoded_access_token, user_groups=user_groups) + self._remove_old_user_groups( + user, decoded_access_token, user_groups=user_groups + ) + self._assign_new_user_groups( + user, decoded_access_token, user_groups=user_groups + ) return user diff --git a/registry/admin.py b/registry/admin.py index 9681f6708bfc09238725244ccb2f6030f292669a..c87549061387f9661372212061e47ef2b931113c 100644 --- a/registry/admin.py +++ b/registry/admin.py @@ -1,9 +1,8 @@ import copy -from django_admin_index.models import AppGroup, AppGroupQuerySet - from django.conf import settings from django.contrib import admin +from django_admin_index.models import AppGroup, AppGroupQuerySet def get_app_list(self, request): @@ -13,13 +12,15 @@ def get_app_list(self, request): if app_name in settings.ADMIN_ORDERING: app = app_dict[app_name] app["models"].sort( - key=lambda model: settings.ADMIN_ORDERING[app_name].index(model["object_name"]) + key=lambda model: settings.ADMIN_ORDERING[app_name].index( + model["object_name"] + ) ) app_dict[app_name] yield app else: - yield app_dict[app_name] + yield app_dict[app_name] admin.AdminSite.get_app_list = get_app_list @@ -29,11 +30,7 @@ original_as_list_func = copy.deepcopy(AppGroupQuerySet.as_list) def as_list(self, request, include_remaining=True): - result = original_as_list_func( - self, - request, - include_remaining=include_remaining - ) + result = original_as_list_func(self, request, include_remaining=include_remaining) for item in result: if item["app_label"] not in settings.ADMIN_ORDERING: @@ -41,8 +38,7 @@ def as_list(self, request, include_remaining=True): item["models"].sort( key=lambda model: ( - settings.ADMIN_ORDERING[item["app_label"]] - .index(model["object_name"]) + settings.ADMIN_ORDERING[item["app_label"]].index(model["object_name"]) ) ) diff --git a/registry/settings/base.py b/registry/settings/base.py index 9fe492d30bbb1d38763fec1aa33b46a0361a075b..576b301dd880b1aae1ea6fba1503856699508c86 100644 --- a/registry/settings/base.py +++ b/registry/settings/base.py @@ -58,6 +58,7 @@ INSTALLED_APPS = [ "django.contrib.staticfiles", "fieldsets_with_inlines", "import_export", + "nested_inline", "rangefilter", "guardian", "markdownx", @@ -79,7 +80,7 @@ MIDDLEWARE = [ "django.middleware.clickjacking.XFrameOptionsMiddleware", "django_http_exceptions.middleware.ExceptionHandlerMiddleware", "django_http_exceptions.middleware.ThreadLocalRequestMiddleware", - #"django_downloadview.SmartDownloadMiddleware", + # "django_downloadview.SmartDownloadMiddleware", ] ROOT_URLCONF = "registry.urls" @@ -87,9 +88,7 @@ ROOT_URLCONF = "registry.urls" TEMPLATES = [ { "BACKEND": "django.template.backends.django.DjangoTemplates", - "DIRS": [ - os.path.join(BASE_DIR, "registry", "templates") - ], + "DIRS": [os.path.join(BASE_DIR, "registry", "templates")], "APP_DIRS": True, "OPTIONS": { "context_processors": [ @@ -208,7 +207,6 @@ ADMIN_INDEX_AUTO_CREATE_APP_GROUP = True ADMIN_INDEX_SHOW_REMAINING_APPS = True - ADMIN_ORDERING = { "contracts": [ "Contract", diff --git a/registry/templates/admin/base_site.html b/registry/templates/admin/base_site.html index 629047619affd6ed95e13c3ad41660b71cc833b5..d593e815a12d109597cc5930c19e6db9a7f778c8 100644 --- a/registry/templates/admin/base_site.html +++ b/registry/templates/admin/base_site.html @@ -5,58 +5,58 @@ :root, :root .admin-interface { --djai-tab-bg: var(--admin-interface-header-background-color); --djai-tab-fg: var(--admin-interface-header-text-color); - + --djai-tab-bg--active: var(--djai-tab-fg); --djai-tab-bg--hover: var(--djai-tab-fg); --djai-tab-fg--active: var(--djai-tab-bg); --djai-tab-fg--hover: var(--djai-tab-bg); - + --djai-dropdown-bg: var(--djai-tab-bg); --djai-dropdown-fg: var(--djai-tab-fg); - + --djai-dropdown-bg--active: var(--djai-tab-fg); --djai-dropdown-bg--hover: var(--djai-tab-fg); --djai-dropdown-fg--active: var(--djai-tab-bg); --djai-dropdown-fg--hover: var(--djai-tab-bg); } - - + + .djai-dropdown-menu .djai-dropdown-menu__drop { box-shadow: 2px 2px 3px rgba(0, 0, 0, 0.1), -2px 2px 3px rgba(0, 0, 0, 0.1) !important; } - + .djai-dropdown-menu a.djai-dropdown-menu__item:hover { color: var(--djai-tab-fg--hover) !important; } - + .djai-dropdown-menu a.djai-dropdown-menu__item.djai-dropdown-menu__item--active { color: var(--djai-tab-fg--active) !important; } - + .djai-dropdown-menu .djai-dropdown-menu__drop-item--active a { color: var(--djai-tab-fg--active) !important; } - + #header .djai-dropdown-menu .djai-dropdown-menu__drop-item { transition: .15s; } - + #header .djai-dropdown-menu .djai-dropdown-menu__drop-item a { color: var(--djai-dropdown-fg); } - + #header .djai-dropdown-menu .djai-dropdown-menu__drop-item a:hover { color: var(--djai-dropdown-fg--hover) !important; text-decoration: none; } - - + + .index-action-buttons { display: flex; flex-direction: row; column-gap: 10px; } - + .index-action-buttons button, .index-action-buttons [aria-role="button"], .index-action-buttons button:visited, @@ -70,10 +70,10 @@ border-radius: var(--admin-interface-module-border-radius) !important; text-decoration: none !important; } - - + + .module caption, .inline-group h2 { text-transform: none; } </style> -{% endblock %} +{% endblock %} diff --git a/requirements/base.txt b/requirements/base.txt index 166f6b728b44adb2b12e4cdd9371b201a173a8c0..767a0d8ffb9a418aea2c43bf7b1b4b43b2e17424 100644 --- a/requirements/base.txt +++ b/requirements/base.txt @@ -5,9 +5,10 @@ django-admin-interface==0.24.2 django-admin-rangefilter==0.9.0 django-autocomplete-light==3.9.4 django-database-url==1.0.3 -django-downloadview==2.3.0 +django-downloadview==2.3.0 django-fieldsets-with-inlines==0.6 django-import-export==3.1.0 +django-nested-inline==0.4.6 djhacker==0.2.3 django-ordered-model==3.7.1 psycopg2-binary==2.9.5 diff --git a/shared/templatetags/__init__.py b/shared/templatetags/__init__.py index 8d1c8b69c3fce7bea45c73efd06983e3c419a92f..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 100644 --- a/shared/templatetags/__init__.py +++ b/shared/templatetags/__init__.py @@ -1 +0,0 @@ - diff --git a/static_src/admin/admin_index_custom.css b/static_src/admin/admin_index_custom.css index 4216cd1ad126fb39036d1687abf0f3fcf4b29577..083c0fe701ad311f24cbf4914e8fe8916cc7f278 100644 --- a/static_src/admin/admin_index_custom.css +++ b/static_src/admin/admin_index_custom.css @@ -1,4 +1,4 @@ :root { --djai-tab-bg: #ff0080; --djai-tab-bg--hover: #a91b60; -} +} diff --git a/static_src/admin/contract_form.js b/static_src/admin/contract_form.js index 0cbcbf75fc9490bce0ca8fe40df669cddbf4651a..2750b17e967ce53baa28301999ff7e39656d1ca0 100644 --- a/static_src/admin/contract_form.js +++ b/static_src/admin/contract_form.js @@ -7,7 +7,7 @@ $(window).ready( () => { let startDateWarningDismissed = false; let endDateWarningDismissed = false; - + $(".field-publishing_rejection_comment"). css( "display", @@ -30,7 +30,7 @@ $(window).ready( ); } ); - + $( "#contract_form .submit-row input[name=\"_save\"]," + "#contract_form .submit-row input[name=\"_addanother\"]," @@ -40,10 +40,10 @@ $(window).ready( event => { if (!startDateWarningDismissed && $("#id_valid_start_date").val() === "") { event.preventDefault(); - + alertify.alert( "Začátek platnosti není zadán", - `Začátek platnosti nebyl uveden. Pokud ho necháš tak, jak je, + `Začátek platnosti nebyl uveden. Pokud ho necháš tak, jak je, bude automaticky vyplněn podle posledního data podpisu smluvních stran. Pokud podpisy neexistují, pole zůstane prázdné.`, @@ -52,13 +52,13 @@ pole zůstane prázdné.`, } ); } - + if (!endDateWarningDismissed && $("#id_valid_end_date").val() === "") { event.preventDefault(); - + alertify.alert( "Konec platnosti není zadán", - `Konec platnosti nebyl uveden. Pokud ho necháš tak, jak je, + `Konec platnosti nebyl uveden. Pokud ho necháš tak, jak je, smlouva bude evidována jako na dobu neurčitou.`, () => { endDateWarningDismissed = true; diff --git a/static_src/admin/signee_form.js b/static_src/admin/signee_form.js index f15a9c866f2401767c4bc4a1fdd07e97765a1349..ce8e74bd8a5e76226d68598b99adac112656609f 100644 --- a/static_src/admin/signee_form.js +++ b/static_src/admin/signee_form.js @@ -12,7 +12,7 @@ $(window).ready( () => { let isNaturalPerson = ($("#id_entity_type").find(":selected").val() === "natural_person"); let isEmpty = ($("#id_entity_type").find(":selected").val() === ""); - + $(".field-date_of_birth"). css( "display", @@ -21,7 +21,7 @@ $(window).ready( "block" : "none" ) ); - + $(".field-ico_number,.field-load_ares_data_button"). css( "display", @@ -30,7 +30,7 @@ $(window).ready( "block" : "none" ) ); - + $(".field-department"). css( "display", @@ -49,7 +49,7 @@ $(window).ready( event => { isEmpty = ($(event.target).val() === ""); isNaturalPerson = ($(event.target).val() === "natural_person"); - + $(".field-date_of_birth"). css( "display", @@ -66,7 +66,7 @@ $(window).ready( "block" : "none" ) ); - + $(".field-department"). css( "display", @@ -75,78 +75,78 @@ $(window).ready( "block" : "none" ) ); - + if (!isNaturalPerson && !isEmpty) $("#id_date_of_birth").val(""); if (isNaturalPerson) $("#id_ico_number").val(""); if (!fieldDepartmentValues.has($(event.target).val()) && !isEmpty) $("#id_department").val(""); } ); - + $("#load_ares_data").on( "click", async (event) => { const icoValue = $("#id_ico_number").val(); - + const rawAresXMLResponse = await fetch( `/ares-info-proxy/${icoValue}` ); - + if (!rawAresXMLResponse.ok) { alertify.error("Chyba při načítní dat z ARES."); - + console.warn( "Error loading ARES data: ", await rawAresXMLResponse.text() ); - + return; } - + const formattedAresData = new DOMParser().parseFromString( await rawAresXMLResponse.text(), "text/xml" ); - + const errors = formattedAresData.getElementsByTagName("are:Error"); - + if (errors.length !== 0) { alertify.error("Chyba při načítní dat z ARES. Je IČO zadáno správně?"); - + console.warn( "Error(s) loading ARES data: ", errors ); - + return; } - + let streetResult = ""; - + const streetElements = formattedAresData.getElementsByTagName("dtt:Nazev_ulice"); - + if (streetElements.length !== 0) { streetResult += streetElements[0].innerHTML; } - + const houseNumberElements = formattedAresData.getElementsByTagName("dtt:Cislo_domovni"); - + if (houseNumberElements.length !== 0) { streetResult += ` ${houseNumberElements[0].innerHTML}`; } - + const orientationNumberElements = formattedAresData.getElementsByTagName("dtt:Cislo_orientacni"); - + if (orientationNumberElements.length !== 0) { streetResult += `/${orientationNumberElements[0].innerHTML}`; } - + $("#id_name").val(formattedAresData.getElementsByTagName("are:Obchodni_firma")[0].innerHTML) $("#id_address_street_with_number").val(streetResult); $("#id_address_district").val(formattedAresData.getElementsByTagName("dtt:Nazev_obce")[0].innerHTML); $("#id_address_zip").val(formattedAresData.getElementsByTagName("dtt:PSC")[0].innerHTML); // IČO numbers will always be in the Czech Republic. $("#id_address_country").val("Česká Republika"); - + console.log(formattedAresData); } ); diff --git a/users/migrations/0001_initial.py b/users/migrations/0001_initial.py index 194972146a01a8f9f4fbb10755a005b905a4ab17..4715016ea06144b88f4495c9914f89640b10660c 100644 --- a/users/migrations/0001_initial.py +++ b/users/migrations/0001_initial.py @@ -1,36 +1,114 @@ # Generated by Django 4.1.4 on 2023-03-15 12:22 -from django.db import migrations, models import django.utils.timezone +from django.db import migrations, models class Migration(migrations.Migration): - initial = True dependencies = [ - ('auth', '0012_alter_user_first_name_max_length'), + ("auth", "0012_alter_user_first_name_max_length"), ] operations = [ migrations.CreateModel( - name='User', + name="User", fields=[ - ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('is_superuser', models.BooleanField(default=False, help_text='Designates that this user has all permissions without explicitly assigning them.', verbose_name='superuser status')), - ('sso_id', models.CharField(error_messages={'unique': 'A user with that SSO ID already exists.'}, max_length=150, unique=True, verbose_name='SSO ID')), - ('first_name', models.CharField(blank=True, max_length=150, verbose_name='first name')), - ('last_name', models.CharField(blank=True, max_length=150, verbose_name='last name')), - ('email', models.EmailField(blank=True, max_length=254, verbose_name='email address')), - ('is_staff', models.BooleanField(default=False, help_text='Designates whether the user can log into this admin site.', verbose_name='staff status')), - ('is_active', models.BooleanField(default=True, help_text='Designates whether this user should be treated as active. Unselect this instead of deleting accounts.', verbose_name='active')), - ('date_joined', models.DateTimeField(default=django.utils.timezone.now, verbose_name='date joined')), - ('groups', models.ManyToManyField(blank=True, help_text='The groups this user belongs to. A user will get all permissions granted to each of their groups.', related_name='user_set', related_query_name='user', to='auth.group', verbose_name='groups')), - ('user_permissions', models.ManyToManyField(blank=True, help_text='Specific permissions for this user.', related_name='user_set', related_query_name='user', to='auth.permission', verbose_name='user permissions')), + ( + "id", + models.BigAutoField( + auto_created=True, + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ( + "is_superuser", + models.BooleanField( + default=False, + help_text="Designates that this user has all permissions without explicitly assigning them.", + verbose_name="superuser status", + ), + ), + ( + "sso_id", + models.CharField( + error_messages={ + "unique": "A user with that SSO ID already exists." + }, + max_length=150, + unique=True, + verbose_name="SSO ID", + ), + ), + ( + "first_name", + models.CharField( + blank=True, max_length=150, verbose_name="first name" + ), + ), + ( + "last_name", + models.CharField( + blank=True, max_length=150, verbose_name="last name" + ), + ), + ( + "email", + models.EmailField( + blank=True, max_length=254, verbose_name="email address" + ), + ), + ( + "is_staff", + models.BooleanField( + default=False, + help_text="Designates whether the user can log into this admin site.", + verbose_name="staff status", + ), + ), + ( + "is_active", + models.BooleanField( + default=True, + help_text="Designates whether this user should be treated as active. Unselect this instead of deleting accounts.", + verbose_name="active", + ), + ), + ( + "date_joined", + models.DateTimeField( + default=django.utils.timezone.now, verbose_name="date joined" + ), + ), + ( + "groups", + models.ManyToManyField( + blank=True, + help_text="The groups this user belongs to. A user will get all permissions granted to each of their groups.", + related_name="user_set", + related_query_name="user", + to="auth.group", + verbose_name="groups", + ), + ), + ( + "user_permissions", + models.ManyToManyField( + blank=True, + help_text="Specific permissions for this user.", + related_name="user_set", + related_query_name="user", + to="auth.permission", + verbose_name="user permissions", + ), + ), ], options={ - 'verbose_name': 'Uživatel', - 'verbose_name_plural': 'Uživatelé', + "verbose_name": "Uživatel", + "verbose_name_plural": "Uživatelé", }, ), ] diff --git a/users/models.py b/users/models.py index 87603106396e168ebf0b8587c31ad302fcc37225..fa51eb64eaa82299528a58a085c212c5eb49614a 100644 --- a/users/models.py +++ b/users/models.py @@ -35,9 +35,7 @@ class User(pirates_models.AbstractUser): from contracts.models import Contract - return Contract.objects.filter( - is_approved=False - ).count() + return Contract.objects.filter(is_approved=False).count() class Meta: app_label = "users" diff --git a/users/urls.py b/users/urls.py index cc5e95051fe7f770a6b77c339789047d50adf9bc..a86d9cdaca454b5ccdf37de10019f83baf3e5580 100644 --- a/users/urls.py +++ b/users/urls.py @@ -1,8 +1,7 @@ import dal.autocomplete - from django.urls import path -from . import views, models +from . import models, views app_name = "users" urlpatterns = [