diff --git a/contracts/admin.py b/contracts/admin.py index 64cc7eb142d381d6705c2111e9da99655316eaae..5241206a82669c30ac9dd36c3817aa7a98f223d0 100644 --- a/contracts/admin.py +++ b/contracts/admin.py @@ -27,6 +27,16 @@ class IndexHiddenModelAdmin(MarkdownxGuardedModelAdmin): # BEGIN Contracts +class ContracteeSignatureInline(admin.TabularInline): + model = ContracteeSignature + extra = 0 + + +class SigneeSignatureInline(admin.TabularInline): + model = SigneeSignature + extra = 0 + + class ContractFileInline(admin.TabularInline): model = ContractFile extra = 0 @@ -37,19 +47,13 @@ class ContractIntentInline(admin.TabularInline): extra = 0 -class ContractIssueInline(admin.TabularInline): - model = Contract.issues.through - extra = 0 - - class ContractAdmin(MarkdownxGuardedModelAdmin): form = ContractAdminForm fields = ( + "created_by", "type", "subtype", - "signee_signatures", - "contractee_signatures", "valid_start_date", "valid_end_date", "legal_state", @@ -58,6 +62,7 @@ class ContractAdmin(MarkdownxGuardedModelAdmin): "publishing_rejection_comment", "tender_url", "identifier", + "issues", "notes", "summary", "primary_contract", @@ -69,12 +74,21 @@ class ContractAdmin(MarkdownxGuardedModelAdmin): "filing_area", ) + readonly_fields = ("created_by",) + inlines = ( + ContracteeSignatureInline, + SigneeSignatureInline, ContractFileInline, ContractIntentInline, - ContractIssueInline, ) + def save_model(self, request, obj, form, change) -> None: + if obj.created_by is None: + obj.created_by = request.user + + super().save_model(request, obj, form, change) + # END Contracts @@ -91,6 +105,7 @@ class SigneeAdmin(MarkdownxGuardedModelAdmin): inlines = ( SigneeRepresentativeInline, + SigneeSignatureInline, ) @@ -100,15 +115,15 @@ class ContracteeRepresentativeInline(admin.TabularInline): class ContracteeAdmin(MarkdownxGuardedModelAdmin): - inlines = ( - ContracteeRepresentativeInline, - ) + inlines = (ContracteeRepresentativeInline, ContracteeSignatureInline) # END Signing parties for model in ( + SigneeSignature, + ContracteeSignature, SigneeRepresentative, ContracteeRepresentative, ContractSubtype, @@ -117,8 +132,6 @@ for model in ( admin.site.register(model, IndexHiddenModelAdmin) for model in ( - SigneeSignature, - ContracteeSignature, ContractIssue, ContractFilingArea, ): diff --git a/contracts/migrations/0001_initial.py b/contracts/migrations/0001_initial.py index 466d34d134c7ace29d0b426660db2de08b0323b5..00dd0b880c98c909c1b46814ea00939cc9a09178 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-02-15 17:12 +# Generated by Django 4.1.4 on 2023-02-16 03:36 -from django.conf import settings -from django.db import migrations, models import django.db.models.deletion import django_countries.fields import markdownx.models +from django.conf import settings +from django.db import migrations, models + import shared.models class Migration(migrations.Migration): - initial = True dependencies = [ @@ -18,225 +18,669 @@ 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')), - ('type', models.CharField(choices=[('primary', 'Hlavní'), ('amendment', 'Dodatek'), ('framework_order', 'Objednávka u rámcové smlouvy')], default='primary', max_length=15, verbose_name='Typ')), - ('contains_nda', models.BooleanField(default=False, verbose_name='Obsahuje NDA')), - ('all_parties_sign_date', models.DateField(verbose_name='Datum podpisu všech stran')), - ('valid_start_date', models.DateField(verbose_name='Začátek účinnosti')), - ('valid_end_date', models.DateField(verbose_name='Konec platnosti')), - ('legal_state', models.CharField(choices=[('valid', 'Platná'), ('effective', 'Účinná'), ('not_effective', 'Neúčinná'), ('invalid', 'Neplatná')], max_length=13, verbose_name='Stav právního ujednání')), - ('public_state', models.CharField(choices=[('unknown', 'Nová'), ('yes', 'Zveřejněná'), ('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á')], max_length=8, verbose_name='Stav papírové formy')), - ('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í')), - ('identifier', models.CharField(max_length=128, verbose_name='Identifikační číslo')), - ('notes', markdownx.models.MarkdownxField(blank=True, help_text='Poznámky jsou viditelné pro všechny, kteří mohou smlouvu spravovat.', null=True, verbose_name='Obsah')), - ('summary', models.CharField(blank=True, help_text='Obsah není veřejně přístupný.', max_length=65536, null=True, verbose_name='Rekapitulace')), - ('expected_cost_total', models.IntegerField(verbose_name='Očekáváná celková cena')), - ('expected_cost_year', models.IntegerField(verbose_name='Očekáváná cena za rok')), - ('expected_cost_month', models.IntegerField(verbose_name='Očekáváná cena za měsíc')), - ('expected_cost_hour', models.IntegerField(verbose_name='Očekáváná cena za hodinu')), - ('agreement_url', models.URLField(blank=True, max_length=256, null=True, verbose_name='Odkaz na schválení')), + ( + "id", + models.BigAutoField( + auto_created=True, + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ( + "type", + models.CharField( + choices=[ + ("primary", "Hlavní"), + ("amendment", "Dodatek"), + ("framework_order", "Objednávka u rámcové smlouvy"), + ], + default="primary", + max_length=15, + verbose_name="Typ", + ), + ), + ( + "contains_nda", + models.BooleanField(default=False, verbose_name="Obsahuje NDA"), + ), + ( + "all_parties_sign_date", + models.DateField( + blank=True, null=True, verbose_name="Datum podpisu všech stran" + ), + ), + ( + "valid_start_date", + models.DateField(verbose_name="Začátek účinnosti"), + ), + ("valid_end_date", models.DateField(verbose_name="Konec platnosti")), + ( + "legal_state", + models.CharField( + choices=[ + ("valid", "Platná"), + ("effective", "Účinná"), + ("not_effective", "Neúčinná"), + ("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á"), + ], + max_length=8, + verbose_name="Stav papírové formy", + ), + ), + ( + "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í", + ), + ), + ( + "identifier", + models.CharField( + max_length=128, verbose_name="Identifikační číslo" + ), + ), + ( + "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", + ), + ), + ( + "summary", + markdownx.models.MarkdownxField( + blank=True, + help_text="Obsah není veřejně přístupný.", + null=True, + verbose_name="Rekapitulace", + ), + ), + ( + "expected_cost_total", + models.IntegerField( + blank=True, null=True, verbose_name="Očekáváná celková cena" + ), + ), + ( + "expected_cost_year", + models.IntegerField( + blank=True, null=True, verbose_name="Očekáváná cena za rok" + ), + ), + ( + "expected_cost_month", + models.IntegerField( + blank=True, null=True, verbose_name="Očekáváná cena za měsíc" + ), + ), + ( + "expected_cost_hour", + models.IntegerField( + blank=True, null=True, verbose_name="Očekáváná cena za hodinu" + ), + ), + ( + "agreement_url", + models.URLField( + blank=True, + max_length=256, + null=True, + verbose_name="Odkaz na schválení", + ), + ), + ( + "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', + "verbose_name": "Smlouva", + "verbose_name_plural": "Smlouvy", }, ), 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', django_countries.fields.CountryField(default='CZ', max_length=2, 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')), - ('color', models.CharField(blank=True, max_length=6, null=True, verbose_name='Barva')), + ( + "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", + django_countries.fields.CountryField( + default="CZ", max_length=2, 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", + ), + ), + ( + "color", + models.CharField( + blank=True, max_length=6, null=True, verbose_name="Barva" + ), + ), ], 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='ContractSubtype', + name="ContractSubtype", 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': 'Podtyp smlouvy', - 'verbose_name_plural': 'Podtypy smlouvy', + "verbose_name": "Podtyp smlouvy", + "verbose_name_plural": "Podtypy 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')), - ('is_legal_entity', models.BooleanField(help_text='Důležité označit správně! Pokud není osoba právnická, zveřejňujeme pouze obec a zemi.', verbose_name='Je právnická osoba')), - ('address_street_with_number', models.CharField(help_text='Viditelné pouze u právnických osob.', max_length=256, verbose_name='Ulice, č.p.')), - ('address_district', models.CharField(max_length=256, verbose_name='Obec')), - ('address_zip', models.CharField(help_text='Viditelné pouze u právnických osob.', max_length=16, verbose_name='PSČ')), - ('address_country', django_countries.fields.CountryField(max_length=2, verbose_name='Země')), - ('ico_number', models.CharField(blank=True, 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')), - ('color', models.CharField(blank=True, max_length=6, null=True, verbose_name='Barva')), + ( + "id", + models.BigAutoField( + auto_created=True, + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ("name", models.CharField(max_length=256, verbose_name="Jméno")), + ( + "is_legal_entity", + models.BooleanField( + help_text="Důležité označit správně! Pokud není osoba právnická, zveřejňujeme pouze obec a zemi.", + verbose_name="Je právnická osoba", + ), + ), + ( + "address_street_with_number", + models.CharField( + help_text="Viditelné pouze u právnických osob.", + max_length=256, + verbose_name="Ulice, č.p.", + ), + ), + ( + "address_district", + models.CharField(max_length=256, verbose_name="Obec"), + ), + ( + "address_zip", + models.CharField( + help_text="Viditelné pouze u právnických osob.", + max_length=16, + verbose_name="PSČ", + ), + ), + ( + "address_country", + django_countries.fields.CountryField( + max_length=2, verbose_name="Země" + ), + ), + ( + "ico_number", + models.CharField( + blank=True, 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", + ), + ), + ( + "color", + models.CharField( + blank=True, max_length=6, null=True, verbose_name="Barva" + ), + ), ], 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')), - ('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')), - ('role', models.CharField(blank=True, max_length=256, null=True, verbose_name='Role')), - ('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" + ), + ), + ( + "role", + models.CharField( + blank=True, max_length=256, null=True, verbose_name="Role" + ), + ), + ( + "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", }, ), migrations.CreateModel( - name='ContractIntent', + name="ContractIntent", fields=[ - ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('url', models.URLField(blank=True, max_length=256, null=True, 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", + ), + ), + ( + "url", + models.URLField( + blank=True, max_length=256, null=True, 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", }, ), 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')), - ('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')), - ('role', models.CharField(blank=True, max_length=256, null=True, verbose_name='Role')), - ('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" + ), + ), + ( + "role", + models.CharField( + blank=True, max_length=256, null=True, verbose_name="Role" + ), + ), + ( + "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", }, ), migrations.AddField( - model_name='contract', - name='contractee_signatures', - field=models.ManyToManyField(to='contracts.contracteesignature', verbose_name='Podpisy našich smluvních stran'), - ), - 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.CASCADE, related_name='filed_contracts', to='contracts.contractfilingarea', verbose_name='Spisovna'), - ), - migrations.AddField( - model_name='contract', - name='issues', - field=models.ManyToManyField(to='contracts.contractissue', verbose_name='Problémy'), - ), - migrations.AddField( - model_name='contract', - name='primary_contract', - field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='subcontracts', to='contracts.contract', verbose_name='Hlavní smlouva'), + 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='public_status_set_by', - field=models.ForeignKey(help_text='Obsah není veřejně přístupný.', on_delete=django.db.models.deletion.CASCADE, 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="issues", + field=models.ManyToManyField( + blank=True, to="contracts.contractissue", verbose_name="Problémy" + ), ), migrations.AddField( - model_name='contract', - name='signee_signatures', - field=models.ManyToManyField(to='contracts.signeesignature', verbose_name='Podpisy ostatních smluvních stran'), + model_name="contract", + name="primary_contract", + field=models.ForeignKey( + blank=True, + null=True, + on_delete=django.db.models.deletion.SET_NULL, + related_name="subcontracts", + to="contracts.contract", + verbose_name="Hlavní smlouva", + ), ), migrations.AddField( - model_name='contract', - name='subtype', - field=models.ManyToManyField(to='contracts.contractsubtype', verbose_name='Podtypy'), + 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='uploaded_by', - field=models.ForeignKey(help_text='Informace není veřejně přístupná.', on_delete=django.db.models.deletion.CASCADE, related_name='uploaded_contracts', to=settings.AUTH_USER_MODEL, verbose_name='Nahráno uživatelem'), + model_name="contract", + name="subtype", + field=models.ManyToManyField( + blank=True, to="contracts.contractsubtype", verbose_name="Podtypy" + ), ), ] diff --git a/contracts/migrations/0002_alter_contract_all_parties_sign_date_and_more.py b/contracts/migrations/0002_alter_contract_all_parties_sign_date_and_more.py deleted file mode 100644 index 463b58e98d3b4b3b7f94c6c48a609cbff7549eaf..0000000000000000000000000000000000000000 --- a/contracts/migrations/0002_alter_contract_all_parties_sign_date_and_more.py +++ /dev/null @@ -1,29 +0,0 @@ -# Generated by Django 4.1.4 on 2023-02-15 17:19 - -from django.db import migrations, models -import markdownx.models - - -class Migration(migrations.Migration): - - dependencies = [ - ('contracts', '0001_initial'), - ] - - operations = [ - migrations.AlterField( - model_name='contract', - name='all_parties_sign_date', - field=models.DateField(blank=True, null=True, verbose_name='Datum podpisu všech stran'), - ), - 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.', null=True, verbose_name='Poznámky'), - ), - migrations.AlterField( - model_name='contract', - name='summary', - field=markdownx.models.MarkdownxField(blank=True, help_text='Obsah není veřejně přístupný.', null=True, verbose_name='Rekapitulace'), - ), - ] diff --git a/contracts/migrations/0003_alter_contract_public_status_set_by.py b/contracts/migrations/0003_alter_contract_public_status_set_by.py deleted file mode 100644 index b662563116ef5fb2d2c0e87b10a24d9e9c25ac9a..0000000000000000000000000000000000000000 --- a/contracts/migrations/0003_alter_contract_public_status_set_by.py +++ /dev/null @@ -1,21 +0,0 @@ -# Generated by Django 4.1.4 on 2023-02-15 17:21 - -from django.conf import settings -from django.db import migrations, models -import django.db.models.deletion - - -class Migration(migrations.Migration): - - dependencies = [ - migrations.swappable_dependency(settings.AUTH_USER_MODEL), - ('contracts', '0002_alter_contract_all_parties_sign_date_and_more'), - ] - - operations = [ - migrations.AlterField( - 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.CASCADE, related_name='public_status_altered_contracts', to=settings.AUTH_USER_MODEL, verbose_name='Zveřejněno / nezveřejněno uživatelem'), - ), - ] diff --git a/contracts/models.py b/contracts/models.py index 49ab18d1ad506811b27da707f3298a4ad20bbfbe..81fb3f694ac89f9ea13f7a0e4991a45595efa3b0 100644 --- a/contracts/models.py +++ b/contracts/models.py @@ -3,8 +3,8 @@ from django.db import models from django_countries.fields import CountryField from markdownx.models import MarkdownxField -from users.models import User from shared.models import NameStrMixin +from users.models import User class Signee(models.Model): @@ -128,26 +128,6 @@ class SigneeRepresentative(models.Model): return result -class SigneeSignature(models.Model): - signee = models.ForeignKey( - Signee, - on_delete=models.CASCADE, - related_name="signatures", - verbose_name="Smluvní strana", - ) - - date = models.DateField( - verbose_name="Datum podpisu", - ) - - class Meta: - verbose_name = "Podpis jiné smluvní strany" - verbose_name_plural = "Podpisy ostatních smluvních stran" - - def __str__(self) -> str: - return f"{self.signee.name}, {self.date}" - - class Contractee(models.Model): name = models.CharField( max_length=256, @@ -258,26 +238,6 @@ class ContracteeRepresentative(models.Model): return result -class ContracteeSignature(models.Model): - contractee = models.ForeignKey( - Contractee, - on_delete=models.CASCADE, - related_name="signatures", - verbose_name="Smluvní strana", - ) - - date = models.DateField( - verbose_name="Datum podpisu", - ) - - class Meta: - verbose_name = "Podpis naší smluvní strany" - verbose_name_plural = "Podpisy našich smluvních stran" - - def __str__(self) -> str: - return f"{self.contractee.name}, {self.date}" - - class ContractSubtype(NameStrMixin, models.Model): name = models.CharField( max_length=32, @@ -332,6 +292,7 @@ class Contract(models.Model): subtype = models.ManyToManyField( ContractSubtype, verbose_name="Podtypy", + blank=True, ) contains_nda = models.BooleanField( @@ -339,16 +300,6 @@ class Contract(models.Model): verbose_name="Obsahuje NDA", ) - signee_signatures = models.ManyToManyField( - SigneeSignature, - verbose_name="Podpisy ostatních smluvních stran", - ) - - contractee_signatures = models.ManyToManyField( - ContracteeSignature, - verbose_name="Podpisy našich smluvních stran", - ) - all_parties_sign_date = models.DateField( verbose_name="Datum podpisu všech stran", blank=True, @@ -362,12 +313,14 @@ class Contract(models.Model): verbose_name="Konec platnosti", ) - uploaded_by = models.ForeignKey( - User, - on_delete=models.CASCADE, + created_by = models.ForeignKey( + settings.AUTH_USER_MODEL, + blank=True, + null=True, + on_delete=models.SET_NULL, related_name="uploaded_contracts", - verbose_name="Nahráno uživatelem", - help_text="Informace není veřejně přístupná.", + verbose_name="Vytvořena uživatelem", + help_text="Informace není veřejně přístupná. Pokud vytváříš novou smlouvu, budeš to ty.", ) # WARNING: exclude in admin class LegalStates(models.TextChoices): @@ -377,8 +330,7 @@ class Contract(models.Model): INVALID = "invalid", "Neplatná" class PublicStates(models.TextChoices): - UNKNOWN = "unknown", "Nová" - YES = "yes", "Zveřejněná" + YES = "yes", "Veřejná" NO = "no", "Neveřejná" class PaperFormStates(models.TextChoices): @@ -407,7 +359,7 @@ class Contract(models.Model): public_status_set_by = models.ForeignKey( User, - on_delete=models.CASCADE, + on_delete=models.SET_NULL, blank=True, null=True, related_name="public_status_altered_contracts", @@ -438,7 +390,9 @@ class Contract(models.Model): issues = models.ManyToManyField( ContractIssue, verbose_name="Problémy", + blank=True, ) + notes = MarkdownxField( blank=True, null=True, @@ -455,20 +409,36 @@ class Contract(models.Model): primary_contract = models.ForeignKey( "Contract", - on_delete=models.CASCADE, + on_delete=models.SET_NULL, # TODO: Figure out if we want this behavior blank=True, null=True, related_name="subcontracts", verbose_name="Hlavní smlouva", ) # WARNING: Dependent on the type! - expected_cost_total = models.IntegerField(verbose_name="Očekáváná celková cena") + expected_cost_total = models.IntegerField( + blank=True, + null=True, + verbose_name="Očekáváná celková cena", + ) - expected_cost_year = models.IntegerField(verbose_name="Očekáváná cena za rok") + expected_cost_year = models.IntegerField( + blank=True, + null=True, + verbose_name="Očekáváná cena za rok", + ) - expected_cost_month = models.IntegerField(verbose_name="Očekáváná cena za měsíc") + expected_cost_month = models.IntegerField( + blank=True, + null=True, + verbose_name="Očekáváná cena za měsíc", + ) - expected_cost_hour = models.IntegerField(verbose_name="Očekáváná cena za hodinu") + expected_cost_hour = models.IntegerField( + blank=True, + null=True, + verbose_name="Očekáváná cena za hodinu", + ) agreement_url = models.URLField( max_length=256, @@ -479,7 +449,7 @@ class Contract(models.Model): filing_area = models.ForeignKey( ContractFilingArea, - on_delete=models.CASCADE, + on_delete=models.SET_NULL, blank=True, null=True, related_name="filed_contracts", @@ -524,6 +494,60 @@ class ContractFile(NameStrMixin, models.Model): verbose_name_plural = "Soubory" +class ContracteeSignature(models.Model): + contractee = models.ForeignKey( + Contractee, + on_delete=models.CASCADE, + related_name="signatures", + verbose_name="Smluvní strana", + ) + + contract = models.ForeignKey( + Contract, + on_delete=models.CASCADE, + related_name="contractee_signatures", + verbose_name="Podpisy našich smluvních stran", + ) + + date = models.DateField( + verbose_name="Datum podpisu", + ) + + class Meta: + verbose_name = "Podpis naší smluvní strany" + verbose_name_plural = "Podpisy našich smluvních stran" + + def __str__(self) -> str: + return f"{self.contractee.name}, {self.date}" + + +class SigneeSignature(models.Model): + signee = models.ForeignKey( + Signee, + on_delete=models.CASCADE, + related_name="signatures", + verbose_name="Smluvní strana", + ) + + contract = models.ForeignKey( + Contract, + on_delete=models.CASCADE, + related_name="signee_signatures", + verbose_name="Podpisy jiných smluvních stran", + ) + + date = models.DateField( + verbose_name="Datum podpisu", + ) + + class Meta: + verbose_name = "Podpis jiné smluvní strany" + verbose_name_plural = "Podpisy ostatních smluvních stran" + + def __str__(self) -> str: + return f"{self.signee.name}, {self.date}" + + class ContractIntent(models.Model): url = models.URLField( max_length=256, diff --git a/model-desc.md b/model-desc.md index 8a67d6153a2a8a67774ea3844bc9b3b02b805e28..b17b5b599a1beb3aa965c60670749f0bc17ec098 100644 --- a/model-desc.md +++ b/model-desc.md @@ -15,6 +15,7 @@ - `Zástupce naší smluvní strany` (propojený s `Naší smluvní stranou`): - Celé jméno - Funkce + - Role - `Podpis naší smluvní strany` (propojený se `Smlouvou`): - Datum @@ -38,6 +39,7 @@ - `Zástupce druhé smluvní strany` (propojený s `Druhou smluvní stranou`): - Celé jméno - Funkce + - Role - `Podpis druhé smluvní strany` (propojený se `Smlouvou`): - Datum @@ -54,6 +56,10 @@ - `Problém` (propojený se `Smlouvou`): - Jméno +- `Soubor` (propojený se `Smlouvou`): + - Jméno + - Obsah souboru (např. PDF) + - `Spisovna` (existuje nezávisle): - Jméno - Jméno odpovědné osoby @@ -93,8 +99,7 @@ - `Problémy` - Poznámky - sdílený textový blok - Sumarizace - - PDF originální smlouvy - - PDF anonymizované smlouvy + - `Soubory` - (Pouze pro dodatky a objednávky) hlavní `Smlouva` - Očekávaná cena za: - Celkem