diff --git a/contracts/admin.py b/contracts/admin.py index 558993c133684c25ec56b2ef1b505b406cfdab97..b2c97254357c9d9aeeed5ec89fc1cc47a728fd3d 100644 --- a/contracts/admin.py +++ b/contracts/admin.py @@ -10,7 +10,7 @@ from rangefilter.filters import DateRangeFilter from shared.admin import FieldsetInlineOrder, MarkdownxGuardedModelAdmin -from .forms import ContractAdminForm, ContractFileAdminForm, SigneeAdminForm +from .forms import ContractAdminForm, ContractFileAdminForm, SigneeAdminForm, AtLeastOneRequiredInlineFormSet from .models import ( Contract, Contractee, @@ -111,7 +111,8 @@ class ContractFileAdmin( class ContracteeSignatureRepresentativeInline(NestedStackedInline): model = ContracteeSignatureRepresentative - extra = 0 + extra = 1 + formset = AtLeastOneRequiredInlineFormSet class ContracteeSignatureInline(NestedStackedInline): diff --git a/contracts/forms.py b/contracts/forms.py index 9453e761d5ee1afb7eb34004eb66bb6f718132ee..e25eea88315d6db1baf0c846cad957e887cdfd9c 100644 --- a/contracts/forms.py +++ b/contracts/forms.py @@ -1,10 +1,27 @@ from django import forms from django.core.exceptions import ValidationError +from django.forms.models import BaseInlineFormSet from webpack_loader.loader import WebpackLoader from .models import Contract, ContracteeSignature, SigneeSignature +class AtLeastOneRequiredInlineFormSet(BaseInlineFormSet): + def clean(self): + """Check that at least one item has been entered.""" + + super().clean() + + if any(self.errors): + return + + if not any( + cleaned_data and not cleaned_data.get('DELETE', False) + for cleaned_data in self.cleaned_data + ): + raise forms.ValidationError("Vyžadován aspoň jeden záznam.") + + class ContractAdminForm(forms.ModelForm): def clean(self): clean_data = super().clean() diff --git a/contracts/migrations/0045_alter_contracteesignaturerepresentative_function.py b/contracts/migrations/0045_alter_contracteesignaturerepresentative_function.py new file mode 100644 index 0000000000000000000000000000000000000000..365c6ee0bcf2fe1f3a39aed1dd595430505642d8 --- /dev/null +++ b/contracts/migrations/0045_alter_contracteesignaturerepresentative_function.py @@ -0,0 +1,19 @@ +# Generated by Django 4.1.4 on 2023-04-16 07:36 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('contracts', '0044_alter_contract_tender_url'), + ] + + operations = [ + migrations.AlterField( + model_name='contracteesignaturerepresentative', + name='function', + field=models.CharField(default='k vyplnění', max_length=256, verbose_name='Funkce'), + preserve_default=False, + ), + ] diff --git a/contracts/migrations/0046_alter_contract_paper_form_state.py b/contracts/migrations/0046_alter_contract_paper_form_state.py new file mode 100644 index 0000000000000000000000000000000000000000..c8783c810aebe198a92e06df18493bde7539670b --- /dev/null +++ b/contracts/migrations/0046_alter_contract_paper_form_state.py @@ -0,0 +1,18 @@ +# Generated by Django 4.1.4 on 2023-04-16 07:39 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('contracts', '0045_alter_contracteesignaturerepresentative_function'), + ] + + operations = [ + migrations.AlterField( + model_name='contract', + name='paper_form_state', + field=models.CharField(choices=[('on_the_way', 'Na cestě'), ('sent', 'Odeslaný'), ('mailbox', 'Ve schránce'), ('to_shred', 'Ke skartaci'), ('shredded', 'Skartovaný'), ('stored', 'Uložený'), ('lost', 'Ztracený')], max_length=10, verbose_name='Stav fyzického dokumentu'), + ), + ] diff --git a/contracts/models.py b/contracts/models.py index 0b44dcd4795f8bb2ffd531b132597247f1c9440b..8490179301c0336ca460e90af522e9d5e847d403 100644 --- a/contracts/models.py +++ b/contracts/models.py @@ -540,10 +540,15 @@ class Contract(NameStrMixin, models.Model): NO = "no", "Neveřejná" class PaperFormStates(models.TextChoices): + ON_THE_WAY = "on_the_way", "Na cestě" SENT = "sent", "Odeslaný" - STORED = "stored", "Uložený" + MAILBOX = "mailbox", "Ve schránce" + TO_SHRED = "to_shred", "Ke skartaci" SHREDDED = "shredded", "Skartovaný" + + STORED = "stored", "Uložený" + LOST = "lost", "Ztracený" legal_state = models.CharField( @@ -568,7 +573,7 @@ class Contract(NameStrMixin, models.Model): ) # WARNING: public status dependent paper_form_state = models.CharField( - max_length=8, + max_length=10, choices=PaperFormStates.choices, verbose_name="Stav fyzického dokumentu", ) @@ -950,8 +955,6 @@ class ContracteeSignatureRepresentative(RepresentativeMixin, models.Model): function = models.CharField( max_length=256, - blank=True, - null=True, verbose_name="Funkce", ) diff --git a/package-lock.json b/package-lock.json index 025b1d69f0d1f2e0ea2fb7e95ca2c934d985b1d0..9a705a811e46537bc31c60f7b4490b6564d9abf9 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,7 +12,7 @@ "@tailwindcss/typography": "^0.5.9", "alertifyjs": "^1.13.1", "css-loader": "^6.7.3", - "jquery": "^3.6.3", + "jquery": "^3.6.4", "style-loader": "^3.3.1", "tailwindcss": "^3.2.4", "tippy.js": "^6.3.7", diff --git a/package.json b/package.json index 528abd89974cb7336d6bdfad72908e4ddbc86741..77aef2b96558d980415ba388aad4b1d05651db55 100644 --- a/package.json +++ b/package.json @@ -15,7 +15,7 @@ "@tailwindcss/typography": "^0.5.9", "alertifyjs": "^1.13.1", "css-loader": "^6.7.3", - "jquery": "^3.6.3", + "jquery": "^3.6.4", "style-loader": "^3.3.1", "tailwindcss": "^3.2.4", "tippy.js": "^6.3.7",