From 31ad3ebc6508190253100f2fae275e58f919e1c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1=C5=A1=20Valenta?= <git@imaniti.org> Date: Sun, 19 Feb 2023 15:41:31 +0100 Subject: [PATCH] wip - single contract display --- contracts/admin.py | 7 +- ...name_subtype_contract_subtypes_and_more.py | 29 ++++ ...ttype_remove_contract_subtypes_and_more.py | 48 ++++++ .../0005_rename_type_contract_types.py | 18 +++ .../0006_remove_contract_contains_nda.py | 17 +++ contracts/models.py | 45 ++---- contracts/templates/contracts/index.html | 18 ++- .../templates/contracts/view_contract.html | 140 ++++++++++++++++++ contracts/templatetags/subtract.py | 3 +- contracts/urls.py | 1 + contracts/views.py | 16 ++ static_src/admin/contract_form.js | 29 ---- 12 files changed, 300 insertions(+), 71 deletions(-) create mode 100644 contracts/migrations/0003_rename_subtype_contract_subtypes_and_more.py create mode 100644 contracts/migrations/0004_contracttype_remove_contract_subtypes_and_more.py create mode 100644 contracts/migrations/0005_rename_type_contract_types.py create mode 100644 contracts/migrations/0006_remove_contract_contains_nda.py create mode 100644 contracts/templates/contracts/view_contract.html diff --git a/contracts/admin.py b/contracts/admin.py index 5c97886..448b493 100644 --- a/contracts/admin.py +++ b/contracts/admin.py @@ -15,7 +15,7 @@ from .models import ( ContractFilingArea, ContractIntent, ContractIssue, - ContractSubtype, + ContractType, Signee, SigneeRepresentative, SigneeSignature, @@ -55,8 +55,7 @@ class ContractAdmin(MarkdownxGuardedModelAdmin): fields = ( "created_by", - "type", - "subtype", + "types", "valid_start_date", "valid_end_date", "legal_state", @@ -125,7 +124,7 @@ for model in ( ContracteeSignature, SigneeRepresentative, ContracteeRepresentative, - ContractSubtype, + ContractType, ContractIntent, ): admin.site.register(model, IndexHiddenModelAdmin) diff --git a/contracts/migrations/0003_rename_subtype_contract_subtypes_and_more.py b/contracts/migrations/0003_rename_subtype_contract_subtypes_and_more.py new file mode 100644 index 0000000..fa1788d --- /dev/null +++ b/contracts/migrations/0003_rename_subtype_contract_subtypes_and_more.py @@ -0,0 +1,29 @@ +# Generated by Django 4.1.4 on 2023-02-19 12:40 + +import colorfield.fields +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('contracts', '0002_remove_contract_expected_cost_hour_and_more'), + ] + + operations = [ + migrations.RenameField( + model_name='contract', + old_name='subtype', + new_name='subtypes', + ), + migrations.AlterField( + model_name='contractee', + name='color', + field=colorfield.fields.ColorField(blank=True, default=None, image_field=None, max_length=18, null=True, samples=None, verbose_name='Barva'), + ), + migrations.AlterField( + model_name='signee', + name='color', + field=colorfield.fields.ColorField(blank=True, default=None, image_field=None, max_length=18, null=True, samples=None, verbose_name='Barva'), + ), + ] diff --git a/contracts/migrations/0004_contracttype_remove_contract_subtypes_and_more.py b/contracts/migrations/0004_contracttype_remove_contract_subtypes_and_more.py new file mode 100644 index 0000000..1048d44 --- /dev/null +++ b/contracts/migrations/0004_contracttype_remove_contract_subtypes_and_more.py @@ -0,0 +1,48 @@ +# Generated by Django 4.1.4 on 2023-02-19 13:08 + +from django.db import migrations, models +import django.db.models.deletion +import shared.models + + +class Migration(migrations.Migration): + + dependencies = [ + ('contracts', '0003_rename_subtype_contract_subtypes_and_more'), + ] + + operations = [ + migrations.CreateModel( + 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')), + ], + options={ + 'verbose_name': 'Typ smlouvy', + 'verbose_name_plural': 'Typy smlouvy', + }, + bases=(shared.models.NameStrMixin, models.Model), + ), + migrations.RemoveField( + model_name='contract', + name='subtypes', + ), + migrations.AlterField( + 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='Primární smlouva'), + ), + migrations.RemoveField( + model_name='contract', + name='type', + ), + migrations.DeleteModel( + name='ContractSubtype', + ), + migrations.AddField( + model_name='contract', + name='type', + field=models.ManyToManyField(to='contracts.contracttype', verbose_name='Typ'), + ), + ] diff --git a/contracts/migrations/0005_rename_type_contract_types.py b/contracts/migrations/0005_rename_type_contract_types.py new file mode 100644 index 0000000..6e55348 --- /dev/null +++ b/contracts/migrations/0005_rename_type_contract_types.py @@ -0,0 +1,18 @@ +# Generated by Django 4.1.4 on 2023-02-19 13:09 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('contracts', '0004_contracttype_remove_contract_subtypes_and_more'), + ] + + operations = [ + migrations.RenameField( + model_name='contract', + old_name='type', + new_name='types', + ), + ] diff --git a/contracts/migrations/0006_remove_contract_contains_nda.py b/contracts/migrations/0006_remove_contract_contains_nda.py new file mode 100644 index 0000000..a9a9f4d --- /dev/null +++ b/contracts/migrations/0006_remove_contract_contains_nda.py @@ -0,0 +1,17 @@ +# Generated by Django 4.1.4 on 2023-02-19 13:13 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('contracts', '0005_rename_type_contract_types'), + ] + + operations = [ + migrations.RemoveField( + model_name='contract', + name='contains_nda', + ), + ] diff --git a/contracts/models.py b/contracts/models.py index aa8b93c..975098f 100644 --- a/contracts/models.py +++ b/contracts/models.py @@ -254,15 +254,15 @@ class ContracteeRepresentative(RepresentativeMixin, models.Model): verbose_name_plural = "Zástupci" -class ContractSubtype(NameStrMixin, models.Model): +class ContractType(NameStrMixin, models.Model): name = models.CharField( max_length=32, verbose_name="Jméno", ) class Meta: - verbose_name = "Podtyp smlouvy" - verbose_name_plural = "Podtypy smlouvy" + verbose_name = "Typ smlouvy" + verbose_name_plural = "Typy smlouvy" class ContractIssue(NameStrMixin, models.Model): @@ -293,29 +293,11 @@ class ContractFilingArea(NameStrMixin, models.Model): class Contract(models.Model): - class ContractTypes(models.TextChoices): - PRIMARY = "primary", "Hlavní" - AMENDMENT = "amendment", "Dodatek" - FRAMEWORK_ORDER = "framework_order", "Objednávka u rámcové smlouvy" - - type = models.CharField( - max_length=15, - choices=ContractTypes.choices, - default=ContractTypes.PRIMARY, + types = models.ManyToManyField( + ContractType, verbose_name="Typ", ) - subtype = models.ManyToManyField( - ContractSubtype, - verbose_name="Podtypy", - blank=True, - ) - - contains_nda = models.BooleanField( - default=False, - verbose_name="Obsahuje NDA", - ) - all_parties_sign_date = models.DateField( verbose_name="Datum podpisu všech stran", blank=True, @@ -354,6 +336,7 @@ class Contract(models.Model): STORED = "stored", "Uložená" TO_SHRED = "to_shred", "Ke skartaci" SHREDDED = "shredded", "Skartovaná" + LOST = "lost", "Ztracená" legal_state = models.CharField( max_length=13, @@ -397,6 +380,13 @@ class Contract(models.Model): null=True, verbose_name="Odkaz na výběrové řízení", ) + + agreement_url = models.URLField( + max_length=256, + blank=True, + null=True, + verbose_name="Odkaz na schválení", + ) # WARNING: Dependent on the type! identifier = models.CharField( max_length=128, @@ -429,14 +419,7 @@ class Contract(models.Model): blank=True, null=True, related_name="subcontracts", - verbose_name="Hlavní smlouva", - ) # WARNING: Dependent on the type! - - agreement_url = models.URLField( - max_length=256, - blank=True, - null=True, - verbose_name="Odkaz na schválení", + verbose_name="Primární smlouva", ) # WARNING: Dependent on the type! filing_area = models.ForeignKey( diff --git a/contracts/templates/contracts/index.html b/contracts/templates/contracts/index.html index f25553a..9f51d4a 100644 --- a/contracts/templates/contracts/index.html +++ b/contracts/templates/contracts/index.html @@ -21,28 +21,34 @@ <td> <a class="underline" - href="#" + href="{% url "contracts:view_contract" contract.id %}" >{{ contract.identifier }}</a> </td> - <td>{{ contract.get_type_display }}</td> + <td> + <ul class="flex flex-wrap gap-1.5"> + {% for type in contract.types.all %} + <li class="p-1.5 rounded-sm whitespace-nowrap bg-gray-200">{{ type.name }}</li> + {% endfor %} + </ul> + </td> <td>{{ contract.get_legal_state_display }}</td> <td>{{ contract.valid_start_date }}</td> <td>{{ contract.valid_end_date }}</td> <td> - <ul class="flex flex-col gap-1"> + <ul class="flex flex-wrap gap-1.5"> {% for signature in contract.contractee_signatures.all %} <li - class="p-2 rounded-sm cursor-pointer text-center {% if not signature.signee.color %}bg-gray-200 duration-100 hover:bg-gray-300{% endif %}" + class="p-1.5 rounded-sm whitespace-nowrap cursor-pointer {% if not signature.signee.color %}bg-gray-200 duration-100 hover:bg-gray-300{% endif %}" {% if signature.signee.color %}style="background-color:{{ signature.signee.color }}"{% endif %} >{{ signature.contractee.name }}</li> {% endfor %} </ul> </td> <td> - <ul class="flex flex-col gap-1"> + <ul class="flex flex-wrap gap-1.5"> {% for signature in contract.signee_signatures.all %} <li - class="p-2 rounded-sm cursor-pointer text-center {% if not signature.signee.color %}bg-gray-200 duration-100 hover:bg-gray-300{% endif %}" + class="p-1.5 rounded-sm whitespace-nowrap cursor-pointer {% if not signature.signee.color %}bg-gray-200 duration-100 hover:bg-gray-300{% endif %}" {% if signature.signee.color %}style="background-color:{{ signature.signee.color }}"{% endif %} >{{ signature.signee.name }}</li> {% endfor %} diff --git a/contracts/templates/contracts/view_contract.html b/contracts/templates/contracts/view_contract.html new file mode 100644 index 0000000..29f7c3a --- /dev/null +++ b/contracts/templates/contracts/view_contract.html @@ -0,0 +1,140 @@ +{% extends "shared/includes/base.html" %} +{% load subtract %} + +{% block content %} + <h1 class="head-alt-lg mb-10">{{ contract.identifier }}</h1> + + <h2 class="text-xl font-bold mb-5"><i class="ico--info mr-3"></i>Základní informace</h2> + + <table class="table table-auto w-full table--striped table--bordered mb-10"> + <tbody> + <tr> + <td class="w-1/5 !p-2.5">Typy</td> + <td class="w-4/5 !p-2.5"> + <ul class="flex flex-wrap gap-1.5"> + {% for type in contract.types.all %} + <li class="p-1.5 rounded-sm whitespace-nowrap bg-gray-200">{{ type.name }}</li> + {% endfor %} + </ul> + </td> + </tr> + <tr> + <td class="w-1/5 !p-2.5">Právní stav</td> + <td class="w-4/5 !p-2.5">{{ contract.get_legal_state_display }}</td> + </tr> + <tr> + <td class="w-1/5 !p-2.5">Stav papírové verze</td> + <td class="w-4/5 !p-2.5">{{ contract.get_paper_form_state_display }}</td> + </tr> + <tr> + <td class="w-1/5 !p-2.5">Výběrové řízení</td> + <td class="w-4/5 !p-2.5"> + {% if contract.tender_url %} + <a + class="underline" + href="{{ contract.tender_url }}" + >{{ contract.tender_url }}</a> + {% else %} + <span class="text-grey-200">Není zadáno</span> + {% endif %} + </td> + </tr> + <tr> + <td class="w-1/5 !p-2.5">Schválení</td> + <td class="w-4/5 !p-2.5"> + {% if contract.agreement_url %} + <a + class="underline" + href="{{ contract.agreement_url }}" + >{{ contract.agreement_url }}</a> + {% else %} + <span class="text-grey-200">Není zadáno</span> + {% endif %} + </td> + </tr> + <tr> + <td class="w-1/5 !p-2.5">Problémy</td> + <td class="w-4/5 !p-2.5"> + {% with contract.issues.all as issues %} + {% if issues|length != 0 %} + <ul class="flex gap-2"> + {% for issue in issues %} + <li class="p-1.5 rounded-sm bg-grey-200">{{ issue.name }}</li> + {% endfor %} + </ul> + {% else %} + <span class="text-grey-200">Žádné</span> + {% endif %} + {% endwith %} + </td> + </tr> + {% if contract.primary_contract %} + <tr> + <td class="w-1/5 !p-2.5">Primární smlouva</td> + <td class="w-4/5 !p-2.5"> + <a + href="{% url "contracts:view_contract" contract.primary_contract.id %}" + >{{ contract.primary_contract.identifier }}</a> + </td> + </tr> + {% endif %} + <tr> + <td class="w-1/5 !p-2.5">Soubory</td> + <td class="w-4/5 !p-2.5"> + {% with contract.files.all as files %} + {% if files|length != 0 %} + <ul class="flex gap-2"> + {% for file in files %} + <li class="p-1.5 rounded-sm bg-gray-200"> + <a + href="{{ file.file.url }}" + ><i class="ico--attachment mr-2"></i>{{ file.name }}</a> + </li> + {% endfor %} + </ul> + {% else %} + <span class="text-grey-200">Žádné</span> + {% endif %} + {% endwith %} + </td> + </tr> + </tbody> + </table> + + <h2 class="text-xl font-bold mb-5"><i class="ico--pencil mr-3"></i>Podpisy</h2> + + <h3 class="text-lg font-bold mb-5">Naší smluvní strany</h3> + + {% with contract.contractee_signatures.all as signatures %} + {% if signatures|length != 0 %} + <ul class="mb-5"> + {% for signature in signatures %} + <li class="py-2 {% if not forloop.last %}border-b border-grey-200{% endif %}"> + <address> + <strong>{{ signature.contractee.name }}</strong> + {% if signature.contractee.department %} + - {{ signature.contractee.department }} + {% endif %}<br> + + {{ signature.contractee.address_street_with_number }}<br> + {{ signature.contractee.address_zip }} {{ signature.contractee.address_district }}<br> + {{ signature.contractee.get_address_country_display }}<br> + + {% if signature.contractee.ico_number %} + IČO: {{ signature.contractee.ico_number }}<br> + {% endif %} + </address> + </li> + {% endfor %} + </ul> + {% else %} + <div class="mb-5 text-grey-200">Žádné podpisy.</div> + {% endif %} + {% endwith %} + + <h3 class="text-lg font-bold mb-5">Ostatních smluvní stran</h3> + + <ul> + + </ul> +{% endblock %} diff --git a/contracts/templatetags/subtract.py b/contracts/templatetags/subtract.py index 076ef2c..6faf0b9 100644 --- a/contracts/templatetags/subtract.py +++ b/contracts/templatetags/subtract.py @@ -2,6 +2,7 @@ from django import template register = template.Library() -@register.filter(name='subtract') + +@register.filter(name="subtract") def subtract(value, arg): return value - arg diff --git a/contracts/urls.py b/contracts/urls.py index 3d6e452..e649007 100644 --- a/contracts/urls.py +++ b/contracts/urls.py @@ -5,4 +5,5 @@ from . import views app_name = "contracts" urlpatterns = [ path("", views.index, name="index"), + path("contracts/<int:id>", views.view_contract, name="view_contract"), ] diff --git a/contracts/views.py b/contracts/views.py index 226b333..d55d154 100644 --- a/contracts/views.py +++ b/contracts/views.py @@ -27,3 +27,19 @@ def index(request): "page": page, } ) + + +def view_contract(request, id: int): + contract = Contract.objects.get(id=id) + + return render( + request, + "contracts/view_contract.html", + { + "site_url": settings.SITE_URL, + "user": request.user, + "title": contract.identifier, + "description": "", # TODO + "contract": contract, + } + ) diff --git a/static_src/admin/contract_form.js b/static_src/admin/contract_form.js index a3672ce..edfdaf9 100644 --- a/static_src/admin/contract_form.js +++ b/static_src/admin/contract_form.js @@ -11,21 +11,6 @@ $(window).ready( ) ); - const allowedPrimaryContractValues = new Set(["amendment", "framework_order"]); - - $(".field-primary_contract"). - css( - "display", - ( - ( - allowedPrimaryContractValues.has( - $("#id_type").find(":selected").val() - ) - ) ? - "block": "none" - ) - ); - $("#id_public_state").on( "change", event => { @@ -39,19 +24,5 @@ $(window).ready( ); } ); - - $("#id_type").on( - "change", - event => { - $(".field-primary_contract"). - css( - "display", - ( - (allowedPrimaryContractValues.has($(event.target).val())) ? - "block": "none" - ) - ); - } - ); } ); -- GitLab