diff --git a/contracts/management/commands/import_old_contracts.py b/contracts/management/commands/import_old_contracts.py
index 53c929456a7037f0d455db7ca258f74189c5f115..23f456c71d02661cf3a5bac7f2013887182c0995 100644
--- a/contracts/management/commands/import_old_contracts.py
+++ b/contracts/management/commands/import_old_contracts.py
@@ -7,10 +7,19 @@ from datetime import date, datetime
 import yaml
 from django.conf import settings
 from django.core.management.base import BaseCommand
+from postal.parser import parse_address
 
 from git import Repo
 
-from ...models import Contract, ContractFilingArea, ContractType
+from ...models import (
+    Contract,
+    ContractFilingArea,
+    ContractType,
+    Contractee,
+    Signee,
+    SigneeSignature,
+    ContracteeSignature,
+)
 
 
 class Command(BaseCommand):
@@ -25,7 +34,7 @@ class Command(BaseCommand):
         self.issue_count = 0
         self.fatal_error_count = 0
 
-    def add_arguments(self, parser):
+    def add_arguments(self, parser) -> None:
         parser.add_argument(
             "repo_url",
             type=str,
@@ -250,6 +259,103 @@ class Command(BaseCommand):
 
         return parsed_metadata
 
+    def assign_signing_party_metadata(
+        self,
+        slug: str,
+        contract: Contract,
+        signing_party: dict
+    ) -> tuple[Contract|Signee, bool, int]:
+        issue_count = 0
+
+        if (
+            "jméno" not in signing_party
+            and "název" not in signing_party
+            and "název společnosti" not in signing_party
+        ):
+            issue_count += 1
+            contract.notes += f"Nepojmenovaná smluvní strana, zdrojová data: {signing_party}\n"
+
+            if self.verbosity >= 2:
+                self.stderr.write(
+                    self.style.NOTICE(
+                        f"Contract {slug} has an unnamed signing party: {signing_party}."
+                    )
+                )
+
+            return issue_count
+
+        name = signing_party.get(
+            "jméno",
+            signing_party.get(
+                "název",
+                signing_party.get("název společnosti")
+            )
+        ).strip()
+
+        is_contractee = False
+
+        if name.lower() in (
+            "česká pirátská strana",
+            "česká pirástká strana",
+            "česká pirátkská strana",
+            "česká pirátská stran",
+        ):
+            instance = Contractee()
+            is_contractee = True
+        else:
+            instance = Signee(name=name, address_country="Česká republika")
+
+        for signing_party_key, signing_party_value in signing_party.items():
+            if isinstance(signing_party_value, str):
+                signing_party_value = signing_party_value.strip()
+
+            match signing_party_key:
+                case "sídlo":
+                    if is_contractee:
+                        continue
+
+                    if not isinstance(signing_party_value, str):
+                        issue_count += 1
+                        contract.notes += f"Špatně zadané sídlo smluvní strany: {signing_party_value}\n"
+
+                        if self.verbosity >= 2:
+                            self.stderr.write(
+                                self.style.NOTICE(
+                                    f"Contract {slug} has an invalid signing party address: {signing_party_value}."
+                                )
+                            )
+
+                        continue
+
+                    raw_parsed_address_data = parse_address(signing_party_value)
+                    address = {}
+
+                    # Convert to a dict first, so that we can access other keys in the loop later
+                    for address_info in raw_parsed_address_data:
+                        address_value, address_key = address_info
+                        address[address_key] = address_value
+
+                    instance.address_street_with_number = ""
+
+                    if "road" in address:
+                        instance.address_street_with_number = address["road"]
+
+                    if "house_number" in address:
+                        instance.address_street_with_number += address["house_number"]
+
+                    for address_key, address_value in address.items():
+                        match address_key:
+                            case "city":
+                                instance.address_district = address_value
+                            case "postcode":
+                                instance.address_zip = address_value
+                case "IČ":
+                    instance.ico_number = signing_party_value
+
+        instance.save()
+
+        return instance, is_contractee, issue_count
+
     def assign_contract_metadata(
         self,
         contract: Contract,
@@ -258,6 +364,8 @@ class Command(BaseCommand):
     ) -> None:
         filing_area = None
         types = []
+        signees = []
+        contractees = []
         is_already_imported = False
         observed_issues_count = 0
 
@@ -472,8 +580,45 @@ class Command(BaseCommand):
                                     )
                                 )
 
+                case "smluvní strany":
+                    if not isinstance(value, list):
+                        observed_issues_count += 1
+                        contract.notes += f"Špatně zadané smluvní strany, nejsou seznam: {value}\n"
+
+                        if self.verbosity >= 2:
+                            self.stderr.write(
+                                self.style.NOTICE(
+                                    f"Signing parties on {slug} are not a list: {value}."
+                                )
+                            )
+
+                        continue
+
+                    for signing_party in value:
+                        if not isinstance(signing_party, dict):
+                            observed_issues_count += 1
+                            contract.notes += f"Špatně zadaná smluvní strana: {signing_party}\n"
+
+                            if self.verbosity >= 2:
+                                self.stderr.write(
+                                    self.style.NOTICE(
+                                        f"Signing party on {slug} is not a dictionary: {value}."
+                                    )
+                                )
+
                             continue
 
+                        instance, is_contractee, signing_party_issue_count = (
+                            self.assign_signing_party_metadata(slug, contract, signing_party)
+                        )
+
+                        observed_issues_count += signing_party_issue_count
+
+                        if is_contractee:
+                            contractees.append(instance)
+                        else:
+                            signees.append(instance)
+
         if not is_already_imported:
             if contract.name in (None, "") or (
                 isinstance(contract.name, str)
@@ -499,6 +644,32 @@ class Command(BaseCommand):
             # Save primary key first
             contract.save()
 
+            for contractee in contractees:
+                contractee.save()
+
+                signature = ContracteeSignature(
+                    contract=contract,
+                    contractee=contractee,
+                    date=contract.valid_start_date,
+                )
+
+                signature.save()
+
+                contract.contractee_signatures.add(signature)
+
+            for signee in signees:
+                signee.save()
+
+                signature = SigneeSignature(
+                    contract=contract,
+                    signee=signee,
+                    date=contract.valid_start_date,
+                )
+
+                signature.save()
+
+                contract.signee_signatures.add(signature)
+
             contract.filing_area = filing_area
             contract.types.set(types)
             contract.save()
@@ -653,9 +824,16 @@ class Command(BaseCommand):
                 self.stdout.write(self.style.SUCCESS("Finished cloning repository."))
 
         if options["purge"]:
-            Contract.objects.filter().delete()
-            ContractType.objects.filter().delete()
-            ContractFilingArea.objects.filter().delete()
+            for model in (
+                Contract,
+                ContractType,
+                ContractFilingArea,
+                Contractee,
+                ContracteeSignature,
+                Signee,
+                SigneeSignature,
+            ):
+                model.objects.filter().delete()
 
             if self.verbosity >= 1:
                 self.stdout.write(self.style.SUCCESS("Deleted all previous records."))
diff --git a/contracts/migrations/0054_alter_signee_address_zip_alter_signee_ico_number.py b/contracts/migrations/0054_alter_signee_address_zip_alter_signee_ico_number.py
new file mode 100644
index 0000000000000000000000000000000000000000..7a6ea981dc7c481caa8939e22dafcdc9cb5b9232
--- /dev/null
+++ b/contracts/migrations/0054_alter_signee_address_zip_alter_signee_ico_number.py
@@ -0,0 +1,23 @@
+# Generated by Django 4.1.4 on 2023-04-21 22:51
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('contracts', '0053_alter_contractfile_file'),
+    ]
+
+    operations = [
+        migrations.AlterField(
+            model_name='signee',
+            name='address_zip',
+            field=models.CharField(blank=True, help_text='Veřejné pouze, když typ není nastaven na fyzickou osobu.', max_length=256, null=True, verbose_name='PSČ'),
+        ),
+        migrations.AlterField(
+            model_name='signee',
+            name='ico_number',
+            field=models.CharField(blank=True, help_text='U právnických a podnikajících fyzických osob musí být vyplněno. Vyplněním můžeš automaticky načíst data z ARES.', max_length=256, null=True, verbose_name='IČO'),
+        ),
+    ]
diff --git a/contracts/migrations/0055_alter_contractee_address_zip_and_more.py b/contracts/migrations/0055_alter_contractee_address_zip_and_more.py
new file mode 100644
index 0000000000000000000000000000000000000000..ea6c711dbaea760820bac281ddbe866dbe8e9d02
--- /dev/null
+++ b/contracts/migrations/0055_alter_contractee_address_zip_and_more.py
@@ -0,0 +1,24 @@
+# Generated by Django 4.1.4 on 2023-04-21 22:52
+
+import contracts.models
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('contracts', '0054_alter_signee_address_zip_alter_signee_ico_number'),
+    ]
+
+    operations = [
+        migrations.AlterField(
+            model_name='contractee',
+            name='address_zip',
+            field=models.CharField(default=contracts.models.get_default_contractee_zip, max_length=256, verbose_name='PSČ'),
+        ),
+        migrations.AlterField(
+            model_name='contractee',
+            name='ico_number',
+            field=models.CharField(blank=True, default=contracts.models.get_default_contractee_ico_number, max_length=256, null=True, verbose_name='IČO'),
+        ),
+    ]
diff --git a/contracts/models.py b/contracts/models.py
index 72d01d2a5649dcb0ff475234d4d607ae49870e3e..fad812edfbf29c1374396c2956a77ddc3d02b079 100644
--- a/contracts/models.py
+++ b/contracts/models.py
@@ -156,7 +156,7 @@ class Signee(
     )
 
     address_zip = models.CharField(
-        max_length=16,
+        max_length=256,
         blank=True,
         null=True,
         verbose_name="PSČ",
@@ -172,7 +172,7 @@ class Signee(
     )
 
     ico_number = models.CharField(
-        max_length=16,
+        max_length=256,
         blank=True,
         null=True,
         verbose_name="IČO",
@@ -323,7 +323,7 @@ class Contractee(
     )
 
     address_zip = models.CharField(
-        max_length=16,
+        max_length=256,
         default=get_default_contractee_zip,
         verbose_name="PSČ",
     )
@@ -335,7 +335,7 @@ class Contractee(
     )
 
     ico_number = models.CharField(
-        max_length=16,
+        max_length=256,
         blank=True,
         null=True,
         default=get_default_contractee_ico_number,
diff --git a/requirements/base.txt b/requirements/base.txt
index c8f33c620f3939b2097253df401d14bfc05fd049..f2f7e257817b7604206a85ea38a40757152f88ae 100644
--- a/requirements/base.txt
+++ b/requirements/base.txt
@@ -17,5 +17,6 @@ django-http-exceptions==1.4.0
 django-guardian==2.4.0
 GitPython==3.1.31
 Markdown==3.4.3
+postal==1.1.10
 PyJWT==2.6.0
 PyYAML==6.0