diff --git a/contracts/admin.py b/contracts/admin.py
index 5241206a82669c30ac9dd36c3817aa7a98f223d0..fbac371a88b7ab514acb92fdad0cf1b2f31cf723 100644
--- a/contracts/admin.py
+++ b/contracts/admin.py
@@ -66,10 +66,6 @@ class ContractAdmin(MarkdownxGuardedModelAdmin):
         "notes",
         "summary",
         "primary_contract",
-        "expected_cost_total",
-        "expected_cost_year",
-        "expected_cost_month",
-        "expected_cost_hour",
         "agreement_url",
         "filing_area",
     )
diff --git a/contracts/migrations/0002_remove_contract_expected_cost_hour_and_more.py b/contracts/migrations/0002_remove_contract_expected_cost_hour_and_more.py
new file mode 100644
index 0000000000000000000000000000000000000000..2eb5524cdd7473ad704b8fe4088fe681d6c09cfa
--- /dev/null
+++ b/contracts/migrations/0002_remove_contract_expected_cost_hour_and_more.py
@@ -0,0 +1,28 @@
+# Generated by Django 4.1.4 on 2023-02-17 03:00
+
+from django.db import migrations
+
+
+class Migration(migrations.Migration):
+    dependencies = [
+        ("contracts", "0001_initial"),
+    ]
+
+    operations = [
+        migrations.RemoveField(
+            model_name="contract",
+            name="expected_cost_hour",
+        ),
+        migrations.RemoveField(
+            model_name="contract",
+            name="expected_cost_month",
+        ),
+        migrations.RemoveField(
+            model_name="contract",
+            name="expected_cost_total",
+        ),
+        migrations.RemoveField(
+            model_name="contract",
+            name="expected_cost_year",
+        ),
+    ]
diff --git a/contracts/models.py b/contracts/models.py
index 81fb3f694ac89f9ea13f7a0e4991a45595efa3b0..b25179ae7aca37bfa0dbc2e2291cf5083aa7f50b 100644
--- a/contracts/models.py
+++ b/contracts/models.py
@@ -7,6 +7,31 @@ from shared.models import NameStrMixin
 from users.models import User
 
 
+class RepresentativeMixin:
+    @property
+    def name(self):
+        raise NotImplementedError
+
+    @property
+    def function(self):
+        raise NotImplementedError
+
+    @property
+    def role(self):
+        raise NotImplementedError
+
+    def __str__(self) -> str:
+        result = self.name
+
+        if self.function is not None:
+            result += f", {self.function}"
+
+        if self.role is not None:
+            result += f" ({self.role})"
+
+        return result
+
+
 class Signee(models.Model):
     name = models.CharField(
         max_length=256,
@@ -85,7 +110,7 @@ class Signee(models.Model):
         return result
 
 
-class SigneeRepresentative(models.Model):
+class SigneeRepresentative(RepresentativeMixin, models.Model):
     signee = models.ForeignKey(
         Signee,
         on_delete=models.CASCADE,
@@ -116,17 +141,6 @@ class SigneeRepresentative(models.Model):
         verbose_name = "Zástupce"
         verbose_name_plural = "Zástupci"
 
-    def __str__(self) -> str:
-        result = self.name
-
-        if self.function is not None:
-            result += f", {self.function}"
-
-        if self.role is not None:
-            result += f" ({self.role})"
-
-        return result
-
 
 class Contractee(models.Model):
     name = models.CharField(
@@ -194,7 +208,7 @@ class Contractee(models.Model):
         return result
 
 
-class ContracteeRepresentative(models.Model):
+class ContracteeRepresentative(RepresentativeMixin, models.Model):
     contractee = models.ForeignKey(
         Contractee,
         on_delete=models.CASCADE,
@@ -225,18 +239,6 @@ class ContracteeRepresentative(models.Model):
         verbose_name = "Zástupce"
         verbose_name_plural = "Zástupci"
 
-    # FIXME: Violates DRY, make a mixin
-    def __str__(self) -> str:
-        result = self.name
-
-        if self.function is not None:
-            result += f", {self.function}"
-
-        if self.role is not None:
-            result += f" ({self.role})"
-
-        return result
-
 
 class ContractSubtype(NameStrMixin, models.Model):
     name = models.CharField(
@@ -416,30 +418,6 @@ class Contract(models.Model):
         verbose_name="Hlavní smlouva",
     )  # WARNING: Dependent on the type!
 
-    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(
         max_length=256,
         blank=True,
@@ -518,7 +496,15 @@ class ContracteeSignature(models.Model):
         verbose_name_plural = "Podpisy našich smluvních stran"
 
     def __str__(self) -> str:
-        return f"{self.contractee.name}, {self.date}"
+        representatives = ", ".join(self.contractee.representatives)
+        result = self.contractee.name
+
+        if len(representatives) != 0:
+            result += f"zastoupena {representatives}"
+
+        result += f", {self.date}"
+
+        return result
 
 
 class SigneeSignature(models.Model):
@@ -545,7 +531,15 @@ class SigneeSignature(models.Model):
         verbose_name_plural = "Podpisy ostatních smluvních stran"
 
     def __str__(self) -> str:
-        return f"{self.signee.name}, {self.date}"
+        representatives = ", ".join(self.signee.representatives)
+        result = self.signee.name
+
+        if len(representatives) != 0:
+            result += f"zastoupena {representatives}"
+
+        result += f", {self.date}"
+
+        return result
 
 
 class ContractIntent(models.Model):