diff --git a/Makefile b/Makefile index 10de836a3643e896093cd5ef118041f41c77286a..0ba8c72028107058bde3ade7598291267d169b9d 100644 --- a/Makefile +++ b/Makefile @@ -5,12 +5,14 @@ VENV = .venv PORT = 8013 SETTINGS = registry.settings.dev -.PHONY: help venv install build run shell migrations migrate +.PHONY: help venv install install-hooks hooks build run shell migrations migrate help: @echo "Setup:" @echo " venv Setup virtual environment" @echo " install Install dependencies to venv" + @echo " install-hooks Install pre-commit hooks" + @echo " hooks Run pre-commit hooks manually" @echo " build Build CSS and JS files" @echo "" @echo "Application:" diff --git a/shared/migrations/__init__.py b/contracts/__init__.py similarity index 100% rename from shared/migrations/__init__.py rename to contracts/__init__.py diff --git a/contracts/admin.py b/contracts/admin.py new file mode 100644 index 0000000000000000000000000000000000000000..8c38f3f3dad51e4585f3984282c2a4bec5349c1e --- /dev/null +++ b/contracts/admin.py @@ -0,0 +1,3 @@ +from django.contrib import admin + +# Register your models here. diff --git a/contracts/apps.py b/contracts/apps.py new file mode 100644 index 0000000000000000000000000000000000000000..d3cd662eed4aff0423a4500a18c15f1479ac238a --- /dev/null +++ b/contracts/apps.py @@ -0,0 +1,6 @@ +from django.apps import AppConfig + + +class ContractsConfig(AppConfig): + default_auto_field = "django.db.models.BigAutoField" + name = "contracts" diff --git a/shared/migrations/0001_initial.py b/contracts/migrations/0001_initial.py similarity index 68% rename from shared/migrations/0001_initial.py rename to contracts/migrations/0001_initial.py index c0a4def389d06410cc2907e8d84eb59175788879..c049786ba448c708abb09138dd3a185d6dc0399b 100644 --- a/shared/migrations/0001_initial.py +++ b/contracts/migrations/0001_initial.py @@ -1,121 +1,16 @@ -# Generated by Django 4.1.4 on 2023-02-03 15:13 +# Generated by Django 4.1.4 on 2023-02-03 15:25 -import django.db.models.deletion -import django.utils.timezone import django_countries.fields import markdownx.models -from django.conf import settings from django.db import migrations, models class Migration(migrations.Migration): initial = True - dependencies = [ - ("auth", "0012_alter_user_first_name_max_length"), - ] + dependencies = [] operations = [ - migrations.CreateModel( - 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", - ), - ), - ], - options={ - "verbose_name": "user", - "verbose_name_plural": "users", - "abstract": False, - }, - ), migrations.CreateModel( name="Contract", fields=[ @@ -281,6 +176,21 @@ class Migration(migrations.Migration): "verbose_name_plural": "Smlouvy", }, ), + migrations.CreateModel( + name="ContractExternalSignature", + fields=[ + ( + "id", + models.BigAutoField( + auto_created=True, + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ("date", models.DateField(verbose_name="Datum podpisu")), + ], + ), migrations.CreateModel( name="ContractExternalSigner", fields=[ @@ -411,6 +321,21 @@ class Migration(migrations.Migration): "verbose_name_plural": "Problémy se smlouvou", }, ), + migrations.CreateModel( + name="ContractLocalSignature", + fields=[ + ( + "id", + models.BigAutoField( + auto_created=True, + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ("date", models.DateField(verbose_name="Datum podpisu")), + ], + ), migrations.CreateModel( name="ContractLocalSigner", fields=[ @@ -498,25 +423,6 @@ class Migration(migrations.Migration): "verbose_name_plural": "Naše smlouvní strany", }, ), - migrations.CreateModel( - 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")), - ], - options={ - "verbose_name": "Podtyp smlouvy", - "verbose_name_plural": "Podtypy smlouvy", - }, - ), migrations.CreateModel( name="ContractNote", fields=[ @@ -531,22 +437,6 @@ class Migration(migrations.Migration): ), ("created_date", models.DateTimeField(verbose_name="Datum vytvoření")), ("content", markdownx.models.MarkdownxField(verbose_name="Obsah")), - ( - "author", - models.ForeignKey( - on_delete=django.db.models.deletion.CASCADE, - related_name="contract_notes", - to=settings.AUTH_USER_MODEL, - verbose_name="Autor", - ), - ), - ( - "contract", - models.ForeignKey( - on_delete=django.db.models.deletion.CASCADE, - to="shared.contract", - ), - ), ], options={ "verbose_name": "Poznámka ke smlouvě", @@ -554,29 +444,7 @@ class Migration(migrations.Migration): }, ), migrations.CreateModel( - name="ContractLocalSignature", - fields=[ - ( - "id", - models.BigAutoField( - auto_created=True, - primary_key=True, - serialize=False, - verbose_name="ID", - ), - ), - ("date", models.DateField(verbose_name="Datum podpisu")), - ( - "signer", - models.ForeignKey( - on_delete=django.db.models.deletion.CASCADE, - to="shared.contractlocalsigner", - ), - ), - ], - ), - migrations.CreateModel( - name="ContractExternalSignature", + name="ContractSubtype", fields=[ ( "id", @@ -587,82 +455,11 @@ class Migration(migrations.Migration): verbose_name="ID", ), ), - ("date", models.DateField(verbose_name="Datum podpisu")), - ( - "signer", - models.ForeignKey( - on_delete=django.db.models.deletion.CASCADE, - to="shared.contractexternalsigner", - ), - ), + ("name", models.CharField(max_length=32, verbose_name="Jméno")), ], - ), - migrations.AddField( - model_name="contract", - name="external_signature", - field=models.ManyToManyField(to="shared.contractexternalsignature"), - ), - 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, - to="shared.contractfilingarea", - ), - ), - migrations.AddField( - model_name="contract", - name="issues", - field=models.ManyToManyField(to="shared.contractissue"), - ), - migrations.AddField( - model_name="contract", - name="local_signature", - field=models.ManyToManyField(to="shared.contractlocalsignature"), - ), - migrations.AddField( - model_name="contract", - name="primary_contract", - field=models.ForeignKey( - blank=True, - null=True, - on_delete=django.db.models.deletion.CASCADE, - to="shared.contract", - verbose_name="Hlavní smlouva", - ), - ), - 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", - ), - ), - migrations.AddField( - model_name="contract", - name="subtype", - field=models.ForeignKey( - on_delete=django.db.models.deletion.CASCADE, - to="shared.contractsubtype", - verbose_name="Podtyp", - ), - ), - 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", - ), + options={ + "verbose_name": "Podtyp smlouvy", + "verbose_name_plural": "Podtypy smlouvy", + }, ), ] diff --git a/contracts/migrations/0002_initial.py b/contracts/migrations/0002_initial.py new file mode 100644 index 0000000000000000000000000000000000000000..f85a350f4139cb677dc01ddd42d22a5b6ccf2ef1 --- /dev/null +++ b/contracts/migrations/0002_initial.py @@ -0,0 +1,118 @@ +# Generated by Django 4.1.4 on 2023-02-03 15:25 + +import django.db.models.deletion +from django.conf import settings +from django.db import migrations, models + + +class Migration(migrations.Migration): + initial = True + + dependencies = [ + ("contracts", "0001_initial"), + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ] + + operations = [ + migrations.AddField( + model_name="contractnote", + name="author", + field=models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, + related_name="contract_notes", + to=settings.AUTH_USER_MODEL, + verbose_name="Autor", + ), + ), + migrations.AddField( + model_name="contractnote", + name="contract", + field=models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, to="contracts.contract" + ), + ), + migrations.AddField( + model_name="contractlocalsignature", + name="signer", + field=models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, + to="contracts.contractlocalsigner", + ), + ), + migrations.AddField( + model_name="contractexternalsignature", + name="signer", + field=models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, + to="contracts.contractexternalsigner", + ), + ), + migrations.AddField( + model_name="contract", + name="external_signature", + field=models.ManyToManyField(to="contracts.contractexternalsignature"), + ), + 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, + to="contracts.contractfilingarea", + ), + ), + migrations.AddField( + model_name="contract", + name="issues", + field=models.ManyToManyField(to="contracts.contractissue"), + ), + migrations.AddField( + model_name="contract", + name="local_signature", + field=models.ManyToManyField(to="contracts.contractlocalsignature"), + ), + migrations.AddField( + model_name="contract", + name="primary_contract", + field=models.ForeignKey( + blank=True, + null=True, + on_delete=django.db.models.deletion.CASCADE, + to="contracts.contract", + verbose_name="Hlavní smlouva", + ), + ), + 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", + ), + ), + migrations.AddField( + model_name="contract", + name="subtype", + field=models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, + to="contracts.contractsubtype", + verbose_name="Podtyp", + ), + ), + 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", + ), + ), + ] diff --git a/contracts/migrations/__init__.py b/contracts/migrations/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/contracts/models.py b/contracts/models.py new file mode 100644 index 0000000000000000000000000000000000000000..0b04f2042085cab494c1e1d6f4f01fd5fde121fa --- /dev/null +++ b/contracts/models.py @@ -0,0 +1,405 @@ +from django.conf import settings +from django.db import models +from django_countries.fields import CountryField +from markdownx.models import MarkdownxField + +from users.models import User + + +class ContractExternalSigner(models.Model): + name = models.CharField( + max_length=256, + verbose_name="Jméno", + ) + + is_legal_entity = models.BooleanField( + verbose_name="Je právnická osoba", + help_text="Důležité označit správně! Pokud není osoba právnická, zveřejňujeme pouze obec a zemi.", + ) + + address_street_with_number = models.CharField( + max_length=256, + verbose_name="Ulice, č.p.", + help_text="Viditelné pouze u právnických osob.", + ) # WARNING: Legal entity status dependent! + + address_district = models.CharField( + max_length=256, + verbose_name="Obec", + ) + + address_zip = models.CharField( + max_length=16, + verbose_name="PSČ", + help_text="Viditelné pouze u právnických osob.", + ) # WARNING: Legal entity status dependent! + + address_country = CountryField( + verbose_name="Země", + ) + + ico_number = models.CharField( + max_length=16, + blank=True, + null=True, + verbose_name="IČO", + ) # WARNING: Legal entity status dependent! + + date_of_birth = models.DateField( + blank=True, + null=True, + verbose_name="Datum narození", + ) # WARNING: Legal entity status dependent! + + representative_name = models.CharField( + max_length=256, + blank=True, + null=True, + verbose_name="Zástupce", + ) + + representative_role = models.CharField( + max_length=256, + blank=True, + null=True, + verbose_name="Funkce zástupce", + ) + + department = models.CharField( + max_length=128, + blank=True, + null=True, + verbose_name="Organizační složka", + ) + + class Meta: + verbose_name = "Druhá smluvní strana" + verbose_name_plural = "Druhé smluvní strany" + + +class ContractExternalSignature(models.Model): + signer = models.ForeignKey( + ContractExternalSigner, + on_delete=models.CASCADE, + ) + + date = models.DateField( + verbose_name="Datum podpisu", + ) + + +class ContractLocalSigner(models.Model): + name = models.CharField( + max_length=256, + default=settings.DEFAULT_LOCAL_SIGNER_NAME, + verbose_name="Jméno", + ) + + address_street_with_number = models.CharField( + max_length=256, + default=settings.DEFAULT_LCOAL_SIGNER_STREET, + verbose_name="Ulice, č.p.", + ) + + address_district = models.CharField( + max_length=256, + default=settings.DEFAULT_LOCAL_SIGNER_DISTRICT, + verbose_name="Obec", + ) + + address_zip = models.CharField( + max_length=16, + default=settings.DEFAULT_LOCAL_SIGNER_ZIP, + verbose_name="PSČ", + ) + + address_country = CountryField( + default=settings.DEFAULT_LOCAL_SIGNER_COUNTRY, + verbose_name="Země", + ) + + ico_number = models.CharField( + max_length=16, + blank=True, + null=True, + default=settings.DEFAULT_LOCAL_SIGNER_ICO_NUMBER, + verbose_name="IČO", + ) + + representative_name = models.CharField( + max_length=256, + blank=True, + null=True, + verbose_name="Zástupce", + ) + + representative_role = models.CharField( + max_length=256, + blank=True, + null=True, + verbose_name="Funkce zástupce", + ) + + department = models.CharField( + max_length=128, + blank=True, + null=True, + verbose_name="Organizační složka", + ) + + # TODO: Input validation + color = models.CharField( + max_length=6, # e.g. "ffffff" + verbose_name="Barva", + ) + + class Meta: + verbose_name = "Naše smluvní strana" + verbose_name_plural = "Naše smlouvní strany" + + +class ContractLocalSignature(models.Model): + signer = models.ForeignKey( + ContractLocalSigner, + on_delete=models.CASCADE, + ) + + date = models.DateField( + verbose_name="Datum podpisu", + ) + + +class ContractSubtype(models.Model): + name = models.CharField( + max_length=32, + verbose_name="Jméno", + ) + + class Meta: + verbose_name = "Podtyp smlouvy" + verbose_name_plural = "Podtypy smlouvy" + + +class ContractIssue(models.Model): + name = models.CharField( + max_length=32, + verbose_name="Jméno", + ) + + class Meta: + verbose_name = "Problém se smlouvou" + verbose_name_plural = "Problémy se smlouvou" + + +class ContractFilingArea(models.Model): + name = models.CharField( + max_length=32, + verbose_name="Jméno", + ) + + person_responsible = models.CharField( + max_length=256, + verbose_name="Odpovědná osoba", + ) + + class Meta: + verbose_name = "Spisovna" + verbose_name_plural = "Spisovny" + + +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, + verbose_name="Typ", + ) + + subtype = models.ForeignKey( + ContractSubtype, + on_delete=models.CASCADE, + verbose_name="Podtyp", + ) + + contains_nda = models.BooleanField( + default=False, + verbose_name="Obsahuje NDA", + ) + + external_signature = models.ManyToManyField(ContractExternalSignature) + + local_signature = models.ManyToManyField(ContractLocalSignature) + + all_parties_sign_date = models.DateField( + verbose_name="Datum podpisu všech stran", + ) # WARNING: Exclude in admin, autofill + + valid_start_date = models.DateField( + verbose_name="Začátek účinnosti", + ) + valid_end_date = models.DateField( + verbose_name="Konec platnosti", + ) + + uploaded_by = models.ForeignKey( + User, + on_delete=models.CASCADE, + related_name="uploaded_contracts", + verbose_name="Nahráno uživatelem", + help_text="Informace není veřejně přístupná.", + ) # WARNING: exclude in admin + + class LegalStates(models.TextChoices): + VALID = "valid", "Platná" + EFFECTIVE = "effective", "Účinná" + NOT_EFFECTIVE = "not_effective", "Neúčinná" + INVALID = "invalid", "Neplatná" + + class PublicStates(models.TextChoices): + UNKNOWN = "unknown", "Nová" + YES = "yes", "Zveřejněná" + NO = "no", "Neveřejná" + + class PaperFormStates(models.TextChoices): + SENT = "sent", "Odeslaná" + STORED = "stored", "Uložená" + TO_SHRED = "to_shred", "Ke skartaci" + SHREDDED = "shredded", "Skartovaná" + + legal_state = models.CharField( + max_length=13, + choices=LegalStates.choices, + verbose_name="Stav právního ujednání", + ) + + public_state = models.CharField( + max_length=7, + choices=PublicStates.choices, + verbose_name="Veřejnost smlouvy", + ) + + paper_form_state = models.CharField( + max_length=8, + choices=PaperFormStates.choices, + verbose_name="Stav papírové formy", + ) + + public_status_set_by = models.ForeignKey( + User, + on_delete=models.CASCADE, + related_name="public_status_altered_contracts", + verbose_name="Zveřejněno / nezveřejněno uživatelem", + help_text="Obsah není veřejně přístupný.", + ) # WARNING: exclude in admin + + publishing_rejection_comment = models.CharField( + max_length=65536, + blank=True, + null=True, + verbose_name="Důvod nezveřejnění", + help_text="Obsah není veřejně přístupný.", + ) # WARNING: exclude in admin + + tender_url = models.URLField( + max_length=256, + blank=True, + null=True, + verbose_name="Odkaz na výběrové řízení", + ) + + identifier = models.CharField( + max_length=128, + verbose_name="Identifikační číslo", + ) + + issues = models.ManyToManyField(ContractIssue) + + summary = models.CharField( + max_length=65536, + blank=True, + null=True, + verbose_name="Rekapitulace", + help_text="Obsah není veřejně přístupný.", + ) + + anonymized_contract_file = models.FileField( + verbose_name="Anonymizovaná smlouva (PDF)", + ) + + original_contract_file = models.FileField( + verbose_name="Originální verze smlouvy (PDF)", + help_text="Obsah není veřejně přístupný.", + ) + + primary_contract = models.ForeignKey( + "Contract", + on_delete=models.CASCADE, + blank=True, + null=True, + verbose_name="Hlavní smlouva", + ) # WARNING: Dependent on the type! + + 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") + + intent_url = models.URLField( + max_length=256, + blank=True, + null=True, + verbose_name="Odkaz na záměr", + ) + + agreement_url = models.URLField( + max_length=256, + blank=True, + null=True, + verbose_name="Odkaz na schválení", + ) # WARNING: Dependent on the type! + + filing_area = models.ForeignKey( + ContractFilingArea, + on_delete=models.CASCADE, + blank=True, + null=True, + help_text="Obsah není veřejně přístupný.", + ) # WARNING: Dependent on the type! + + class Meta: + verbose_name = "Smlouva" + verbose_name_plural = "Smlouvy" + + +class ContractNote(models.Model): + contract = models.ForeignKey( + Contract, + on_delete=models.CASCADE, + ) + + author = models.ForeignKey( + User, + related_name="contract_notes", + on_delete=models.CASCADE, + verbose_name="Autor", + ) + + created_date = models.DateTimeField( + verbose_name="Datum vytvoření", + ) + + content = MarkdownxField( + verbose_name="Obsah", + ) + + class Meta: + verbose_name = "Poznámka ke smlouvě" + verbose_name_plural = "Poznámky ke smlouvě" diff --git a/contracts/tests.py b/contracts/tests.py new file mode 100644 index 0000000000000000000000000000000000000000..7ce503c2dd97ba78597f6ff6e4393132753573f6 --- /dev/null +++ b/contracts/tests.py @@ -0,0 +1,3 @@ +from django.test import TestCase + +# Create your tests here. diff --git a/contracts/views.py b/contracts/views.py new file mode 100644 index 0000000000000000000000000000000000000000..91ea44a218fbd2f408430959283f0419c921093e --- /dev/null +++ b/contracts/views.py @@ -0,0 +1,3 @@ +from django.shortcuts import render + +# Create your views here. diff --git a/registry/settings/base.py b/registry/settings/base.py index 93c9200ab4a598fc91fbc1ba8bd3dc6b759e22ca..7fa8ccf883d258a48cf5995450e18c4faa4e4bb6 100644 --- a/registry/settings/base.py +++ b/registry/settings/base.py @@ -45,7 +45,9 @@ INSTALLED_APPS = [ "django.contrib.sessions", "django.contrib.messages", "django.contrib.staticfiles", + "contracts", "shared", + "users", ] MIDDLEWARE = [ @@ -102,7 +104,7 @@ AUTH_PASSWORD_VALIDATORS = [ "NAME": "django.contrib.auth.password_validation.NumericPasswordValidator", }, ] -AUTH_USER_MODEL = "shared.User" +AUTH_USER_MODEL = "users.User" # Internationalization diff --git a/shared/models.py b/shared/models.py index e48deae16e8c2c6a048db431fd5f7582764cf369..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 100644 --- a/shared/models.py +++ b/shared/models.py @@ -1,408 +0,0 @@ -from django.conf import settings -from django.db import models -from django_countries.fields import CountryField -from markdownx.models import MarkdownxField -from pirates import models as pirates_models - - -class User(pirates_models.AbstractUser): - pass - - -class ContractExternalSigner(models.Model): - name = models.CharField( - max_length=256, - verbose_name="Jméno", - ) - - is_legal_entity = models.BooleanField( - verbose_name="Je právnická osoba", - help_text="Důležité označit správně! Pokud není osoba právnická, zveřejňujeme pouze obec a zemi.", - ) - - address_street_with_number = models.CharField( - max_length=256, - verbose_name="Ulice, č.p.", - help_text="Viditelné pouze u právnických osob.", - ) # WARNING: Legal entity status dependent! - - address_district = models.CharField( - max_length=256, - verbose_name="Obec", - ) - - address_zip = models.CharField( - max_length=16, - verbose_name="PSČ", - help_text="Viditelné pouze u právnických osob.", - ) # WARNING: Legal entity status dependent! - - address_country = CountryField( - verbose_name="Země", - ) - - ico_number = models.CharField( - max_length=16, - blank=True, - null=True, - verbose_name="IČO", - ) # WARNING: Legal entity status dependent! - - date_of_birth = models.DateField( - blank=True, - null=True, - verbose_name="Datum narození", - ) # WARNING: Legal entity status dependent! - - representative_name = models.CharField( - max_length=256, - blank=True, - null=True, - verbose_name="Zástupce", - ) - - representative_role = models.CharField( - max_length=256, - blank=True, - null=True, - verbose_name="Funkce zástupce", - ) - - department = models.CharField( - max_length=128, - blank=True, - null=True, - verbose_name="Organizační složka", - ) - - class Meta: - verbose_name = "Druhá smluvní strana" - verbose_name_plural = "Druhé smluvní strany" - - -class ContractExternalSignature(models.Model): - signer = models.ForeignKey( - ContractExternalSigner, - on_delete=models.CASCADE, - ) - - date = models.DateField( - verbose_name="Datum podpisu", - ) - - -class ContractLocalSigner(models.Model): - name = models.CharField( - max_length=256, - default=settings.DEFAULT_LOCAL_SIGNER_NAME, - verbose_name="Jméno", - ) - - address_street_with_number = models.CharField( - max_length=256, - default=settings.DEFAULT_LCOAL_SIGNER_STREET, - verbose_name="Ulice, č.p.", - ) - - address_district = models.CharField( - max_length=256, - default=settings.DEFAULT_LOCAL_SIGNER_DISTRICT, - verbose_name="Obec", - ) - - address_zip = models.CharField( - max_length=16, - default=settings.DEFAULT_LOCAL_SIGNER_ZIP, - verbose_name="PSČ", - ) - - address_country = CountryField( - default=settings.DEFAULT_LOCAL_SIGNER_COUNTRY, - verbose_name="Země", - ) - - ico_number = models.CharField( - max_length=16, - blank=True, - null=True, - default=settings.DEFAULT_LOCAL_SIGNER_ICO_NUMBER, - verbose_name="IČO", - ) - - representative_name = models.CharField( - max_length=256, - blank=True, - null=True, - verbose_name="Zástupce", - ) - - representative_role = models.CharField( - max_length=256, - blank=True, - null=True, - verbose_name="Funkce zástupce", - ) - - department = models.CharField( - max_length=128, - blank=True, - null=True, - verbose_name="Organizační složka", - ) - - # TODO: Input validation - color = models.CharField( - max_length=6, # e.g. "ffffff" - verbose_name="Barva", - ) - - class Meta: - verbose_name = "Naše smluvní strana" - verbose_name_plural = "Naše smlouvní strany" - - -class ContractLocalSignature(models.Model): - signer = models.ForeignKey( - ContractLocalSigner, - on_delete=models.CASCADE, - ) - - date = models.DateField( - verbose_name="Datum podpisu", - ) - - -class ContractSubtype(models.Model): - name = models.CharField( - max_length=32, - verbose_name="Jméno", - ) - - class Meta: - verbose_name = "Podtyp smlouvy" - verbose_name_plural = "Podtypy smlouvy" - - -class ContractIssue(models.Model): - name = models.CharField( - max_length=32, - verbose_name="Jméno", - ) - - class Meta: - verbose_name = "Problém se smlouvou" - verbose_name_plural = "Problémy se smlouvou" - - -class ContractFilingArea(models.Model): - name = models.CharField( - max_length=32, - verbose_name="Jméno", - ) - - person_responsible = models.CharField( - max_length=256, - verbose_name="Odpovědná osoba", - ) - - class Meta: - verbose_name = "Spisovna" - verbose_name_plural = "Spisovny" - - -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, - verbose_name="Typ", - ) - - subtype = models.ForeignKey( - ContractSubtype, - on_delete=models.CASCADE, - verbose_name="Podtyp", - ) - - contains_nda = models.BooleanField( - default=False, - verbose_name="Obsahuje NDA", - ) - - external_signature = models.ManyToManyField(ContractExternalSignature) - - local_signature = models.ManyToManyField(ContractLocalSignature) - - all_parties_sign_date = models.DateField( - verbose_name="Datum podpisu všech stran", - ) # WARNING: Exclude in admin, autofill - - valid_start_date = models.DateField( - verbose_name="Začátek účinnosti", - ) - valid_end_date = models.DateField( - verbose_name="Konec platnosti", - ) - - uploaded_by = models.ForeignKey( - User, - on_delete=models.CASCADE, - related_name="uploaded_contracts", - verbose_name="Nahráno uživatelem", - help_text="Informace není veřejně přístupná.", - ) # WARNING: exclude in admin - - class LegalStates(models.TextChoices): - VALID = "valid", "Platná" - EFFECTIVE = "effective", "Účinná" - NOT_EFFECTIVE = "not_effective", "Neúčinná" - INVALID = "invalid", "Neplatná" - - class PublicStates(models.TextChoices): - UNKNOWN = "unknown", "Nová" - YES = "yes", "Zveřejněná" - NO = "no", "Neveřejná" - - class PaperFormStates(models.TextChoices): - SENT = "sent", "Odeslaná" - STORED = "stored", "Uložená" - TO_SHRED = "to_shred", "Ke skartaci" - SHREDDED = "shredded", "Skartovaná" - - legal_state = models.CharField( - max_length=13, - choices=LegalStates.choices, - verbose_name="Stav právního ujednání", - ) - - public_state = models.CharField( - max_length=7, - choices=PublicStates.choices, - verbose_name="Veřejnost smlouvy", - ) - - paper_form_state = models.CharField( - max_length=8, - choices=PaperFormStates.choices, - verbose_name="Stav papírové formy", - ) - - public_status_set_by = models.ForeignKey( - User, - on_delete=models.CASCADE, - related_name="public_status_altered_contracts", - verbose_name="Zveřejněno / nezveřejněno uživatelem", - help_text="Obsah není veřejně přístupný.", - ) # WARNING: exclude in admin - - publishing_rejection_comment = models.CharField( - max_length=65536, - blank=True, - null=True, - verbose_name="Důvod nezveřejnění", - help_text="Obsah není veřejně přístupný.", - ) # WARNING: exclude in admin - - tender_url = models.URLField( - max_length=256, - blank=True, - null=True, - verbose_name="Odkaz na výběrové řízení", - ) - - identifier = models.CharField( - max_length=128, - verbose_name="Identifikační číslo", - ) - - issues = models.ManyToManyField(ContractIssue) - - summary = models.CharField( - max_length=65536, - blank=True, - null=True, - verbose_name="Rekapitulace", - help_text="Obsah není veřejně přístupný.", - ) - - anonymized_contract_file = models.FileField( - verbose_name="Anonymizovaná smlouva (PDF)", - ) - - original_contract_file = models.FileField( - verbose_name="Originální verze smlouvy (PDF)", - help_text="Obsah není veřejně přístupný.", - ) - - primary_contract = models.ForeignKey( - "Contract", - on_delete=models.CASCADE, - blank=True, - null=True, - verbose_name="Hlavní smlouva", - ) # WARNING: Dependent on the type! - - 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") - - intent_url = models.URLField( - max_length=256, - blank=True, - null=True, - verbose_name="Odkaz na záměr", - ) - - agreement_url = models.URLField( - max_length=256, - blank=True, - null=True, - verbose_name="Odkaz na schválení", - ) # WARNING: Dependent on the type! - - filing_area = models.ForeignKey( - ContractFilingArea, - on_delete=models.CASCADE, - blank=True, - null=True, - help_text="Obsah není veřejně přístupný.", - ) # WARNING: Dependent on the type! - - class Meta: - verbose_name = "Smlouva" - verbose_name_plural = "Smlouvy" - - -class ContractNote(models.Model): - contract = models.ForeignKey( - Contract, - on_delete=models.CASCADE, - ) - - author = models.ForeignKey( - User, - related_name="contract_notes", - on_delete=models.CASCADE, - verbose_name="Autor", - ) - - created_date = models.DateTimeField( - verbose_name="Datum vytvoření", - ) - - content = MarkdownxField( - verbose_name="Obsah", - ) - - class Meta: - verbose_name = "Poznámka ke smlouvě" - verbose_name_plural = "Poznámky ke smlouvě" diff --git a/users/__init__.py b/users/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/users/admin.py b/users/admin.py new file mode 100644 index 0000000000000000000000000000000000000000..8c38f3f3dad51e4585f3984282c2a4bec5349c1e --- /dev/null +++ b/users/admin.py @@ -0,0 +1,3 @@ +from django.contrib import admin + +# Register your models here. diff --git a/users/apps.py b/users/apps.py new file mode 100644 index 0000000000000000000000000000000000000000..88f7b1798e7f1150a0e4e86781d9533d9573db3d --- /dev/null +++ b/users/apps.py @@ -0,0 +1,6 @@ +from django.apps import AppConfig + + +class UsersConfig(AppConfig): + default_auto_field = "django.db.models.BigAutoField" + name = "users" diff --git a/users/migrations/0001_initial.py b/users/migrations/0001_initial.py new file mode 100644 index 0000000000000000000000000000000000000000..e975e4f7c2e0d4271cc7f3e7312d29168503a70a --- /dev/null +++ b/users/migrations/0001_initial.py @@ -0,0 +1,115 @@ +# Generated by Django 4.1.4 on 2023-02-03 15:25 + +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"), + ] + + operations = [ + migrations.CreateModel( + 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", + ), + ), + ], + options={ + "verbose_name": "user", + "verbose_name_plural": "users", + "abstract": False, + }, + ), + ] diff --git a/users/migrations/__init__.py b/users/migrations/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/users/models.py b/users/models.py new file mode 100644 index 0000000000000000000000000000000000000000..ea62fb3fa8eef5bddf9697561fab74f215460fd4 --- /dev/null +++ b/users/models.py @@ -0,0 +1,5 @@ +from pirates import models as pirates_models + + +class User(pirates_models.AbstractUser): + pass diff --git a/users/tests.py b/users/tests.py new file mode 100644 index 0000000000000000000000000000000000000000..7ce503c2dd97ba78597f6ff6e4393132753573f6 --- /dev/null +++ b/users/tests.py @@ -0,0 +1,3 @@ +from django.test import TestCase + +# Create your tests here. diff --git a/users/views.py b/users/views.py new file mode 100644 index 0000000000000000000000000000000000000000..91ea44a218fbd2f408430959283f0419c921093e --- /dev/null +++ b/users/views.py @@ -0,0 +1,3 @@ +from django.shortcuts import render + +# Create your views here.