diff --git a/finances/admin.py b/finances/admin.py
index 8c38f3f3dad51e4585f3984282c2a4bec5349c1e..d8d4d52c35c2131bf14a5313cff84015f49881a7 100644
--- a/finances/admin.py
+++ b/finances/admin.py
@@ -1,3 +1,6 @@
 from django.contrib import admin
 
-# Register your models here.
+from .models import WorkLog
+
+
+admin.site.register(WorkLog)
diff --git a/finances/forms.py b/finances/forms.py
new file mode 100644
index 0000000000000000000000000000000000000000..dd99b82bb5aa501a3b23097fbcace9a0a56e4350
--- /dev/null
+++ b/finances/forms.py
@@ -0,0 +1,16 @@
+from django import forms
+
+from .models import WorkLog
+
+
+class WorkLogForm(forms.ModelForm):
+    class Meta:
+        model = WorkLog
+        fields = (
+            'comments',
+            'duration',
+        )
+        widgets = {
+            'comments': forms.Textarea(attrs={'rows': 4}),
+            'duration': forms.TextInput(attrs={'placeholder': 'HH:MM:SS'})
+        }
diff --git a/finances/migrations/0001_initial.py b/finances/migrations/0001_initial.py
new file mode 100644
index 0000000000000000000000000000000000000000..a0b67974f46214763138959424ed10bb21f5ef96
--- /dev/null
+++ b/finances/migrations/0001_initial.py
@@ -0,0 +1,37 @@
+# -*- coding: utf-8 -*-
+# Generated by Django 1.11.4 on 2017-10-07 11:49
+from __future__ import unicode_literals
+
+from django.conf import settings
+from django.db import migrations, models
+import django.db.models.deletion
+import django.utils.timezone
+
+
+class Migration(migrations.Migration):
+
+    initial = True
+
+    dependencies = [
+        ('contenttypes', '0002_remove_content_type_name'),
+        migrations.swappable_dependency(settings.AUTH_USER_MODEL),
+    ]
+
+    operations = [
+        migrations.CreateModel(
+            name='WorkLog',
+            fields=[
+                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+                ('comments', models.TextField(blank=True)),
+                ('duration', models.DurationField(blank=True, null=True)),
+                ('work_date', models.DateField(default=django.utils.timezone.now)),
+                ('created', models.DateTimeField(auto_now_add=True)),
+                ('target_object_id', models.PositiveIntegerField(blank=True, null=True)),
+                ('target_content_type', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='work_log_target', to='contenttypes.ContentType')),
+                ('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='worklogs', to=settings.AUTH_USER_MODEL)),
+            ],
+            options={
+                'default_related_name': 'worklogs',
+            },
+        ),
+    ]
diff --git a/finances/migrations/0002_auto_20171007_1349.py b/finances/migrations/0002_auto_20171007_1349.py
new file mode 100644
index 0000000000000000000000000000000000000000..abab65056fe0b8b637687d7b06d3444086eed0a9
--- /dev/null
+++ b/finances/migrations/0002_auto_20171007_1349.py
@@ -0,0 +1,46 @@
+# -*- coding: utf-8 -*-
+# Generated by Django 1.11.4 on 2017-10-07 11:50
+from __future__ import unicode_literals
+
+from django.db import migrations
+
+
+def move_hour_registrations(apps, schema_editor):
+    """
+    Move all ProductionEvent hours to Finances model.
+    """
+    ProductionEvent = apps.get_model('production', 'ProductionEvent')
+    WorkLog = apps.get_model('finances', 'WorkLog')
+    ContentType = apps.get_model('contenttypes', 'ContentType')
+    stream_content_type = ContentType.objects.get(app_label='production', model='productionstream')
+
+    for event in ProductionEvent.objects.filter(duration__isnull=False):
+        log = WorkLog(
+            user=event.noted_by.user,
+            comments=event.comments,
+            duration=event.duration,
+            work_date=event.noted_on,
+            target_content_type=stream_content_type,
+            target_object_id=event.stream.id
+        )
+        log.save()
+    return
+
+
+def move_hour_registrations_inverse(apps, schema_editor):
+    """
+    Move all ProductionEvent hours to Finances model inversed (not implemented).
+    """
+    return
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('finances', '0001_initial'),
+        ('production', '0028_auto_20171007_1311'),
+    ]
+
+    operations = [
+        migrations.RunPython(move_hour_registrations, move_hour_registrations_inverse)
+    ]
diff --git a/finances/migrations/0003_auto_20171007_1425.py b/finances/migrations/0003_auto_20171007_1425.py
new file mode 100644
index 0000000000000000000000000000000000000000..6d667cb908443488220eeff36b3cecac147926e5
--- /dev/null
+++ b/finances/migrations/0003_auto_20171007_1425.py
@@ -0,0 +1,33 @@
+# -*- coding: utf-8 -*-
+# Generated by Django 1.11.4 on 2017-10-07 12:25
+from __future__ import unicode_literals
+
+from django.conf import settings
+from django.db import migrations, models
+import django.db.models.deletion
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('contenttypes', '0002_remove_content_type_name'),
+        ('finances', '0002_auto_20171007_1349'),
+    ]
+
+    operations = [
+        migrations.RenameField(
+            model_name='worklog',
+            old_name='target_object_id',
+            new_name='object_id',
+        ),
+        migrations.RenameField(
+            model_name='worklog',
+            old_name='target_content_type',
+            new_name='content_type',
+        ),
+        migrations.AlterField(
+            model_name='worklog',
+            name='user',
+            field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='work_logs', to=settings.AUTH_USER_MODEL),
+        ),
+    ]
diff --git a/finances/migrations/0004_auto_20171007_1426.py b/finances/migrations/0004_auto_20171007_1426.py
new file mode 100644
index 0000000000000000000000000000000000000000..5d039886b918bc5e673be76bb82caaf1e4bb3e0a
--- /dev/null
+++ b/finances/migrations/0004_auto_20171007_1426.py
@@ -0,0 +1,21 @@
+# -*- coding: utf-8 -*-
+# Generated by Django 1.11.4 on 2017-10-07 12:26
+from __future__ import unicode_literals
+
+from django.db import migrations, models
+import django.db.models.deletion
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('finances', '0003_auto_20171007_1425'),
+    ]
+
+    operations = [
+        migrations.AlterField(
+            model_name='worklog',
+            name='content_type',
+            field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='work_logs', to='contenttypes.ContentType'),
+        ),
+    ]
diff --git a/finances/models.py b/finances/models.py
index 71a836239075aa6e6e4ecb700e9c42c95c022d91..d4c8622fd8b3ac23b346343343ee41f2b3244b0e 100644
--- a/finances/models.py
+++ b/finances/models.py
@@ -1,3 +1,30 @@
+from django.conf import settings
+from django.contrib.contenttypes.models import ContentType
+from django.contrib.contenttypes.fields import GenericForeignKey
 from django.db import models
+from django.utils import timezone
 
-# Create your models here.
+from .utils import id_to_slug
+
+
+class WorkLog(models.Model):
+    user = models.ForeignKey(settings.AUTH_USER_MODEL)
+    comments = models.TextField(blank=True)
+    duration = models.DurationField(blank=True, null=True)
+    work_date = models.DateField(default=timezone.now)
+    created = models.DateTimeField(auto_now_add=True)
+
+    content_type = models.ForeignKey(ContentType, blank=True, null=True)
+    object_id = models.PositiveIntegerField(blank=True, null=True)
+    content = GenericForeignKey()
+
+    class Meta:
+        default_related_name = 'work_logs'
+
+    def __str__(self):
+        return 'Log of {0} {1} on {2}'.format(
+            self.user.first_name, self.user.last_name, self.work_date)
+
+    @property
+    def slug(self):
+        return id_to_slug(self.id)
diff --git a/finances/templates/finances/worklog_confirm_delete.html b/finances/templates/finances/worklog_confirm_delete.html
new file mode 100644
index 0000000000000000000000000000000000000000..cc03bcc7db216d340cdee18bff64e842a149e612
--- /dev/null
+++ b/finances/templates/finances/worklog_confirm_delete.html
@@ -0,0 +1,49 @@
+{% extends 'production/base.html' %}
+
+{% load scipost_extras %}
+
+{% block breadcrumb_items %}
+    {{block.super}}
+    <span class="breadcrumb-item">Delete log</span>
+{% endblock %}
+
+{% load bootstrap %}
+
+{% block content %}
+
+<div class="row">
+    <div class="col-12">
+        <h1 class="highlight">Delete log</h1>
+        {% include 'submissions/_submission_card_content_sparse.html' with submission=object.content.submission %}
+    </div>
+</div>
+<div class="row">
+  <div class="col-12">
+      <form method="post">
+        {% csrf_token %}
+            <h3 class="mb-2">Are you sure you want to delete this work log?</h3>
+            <table class="table">
+                <tr>
+                    <th>Logged by</th>
+                    <td>{{ object.user }}</td>
+                </tr>
+                <tr>
+                    <th>Comment</th>
+                    <td>{{ object.comments|default:'-' }}</td>
+                </tr>
+                <tr>
+                    <th>Logged time</th>
+                    <td>{{ object.duration|duration }}</td>
+                </tr>
+                <tr>
+                    <th>Log date</th>
+                    <td>{{ object.work_date }}</td>
+                </tr>
+            </table>
+            <input type="submit" class="btn btn-danger" value="Yes, delete log" />
+      </form>
+    </ul>
+  </div>
+</div>
+
+{% endblock content %}
diff --git a/finances/templates/partials/finances/logs.html b/finances/templates/partials/finances/logs.html
new file mode 100644
index 0000000000000000000000000000000000000000..7b9db48220dfd2ed74781910031b994031df1ce8
--- /dev/null
+++ b/finances/templates/partials/finances/logs.html
@@ -0,0 +1,34 @@
+ {% load scipost_extras %}
+
+ <ul class="list-unstyled">
+  {% for log in logs %}
+        <li id="log_{{ log.slug }}" class="pb-2">
+            <div class="d-flex justify-content-between">
+                <div>
+                    <strong>{{ log.user.first_name }} {{ log.user.last_name }}</strong>
+                    <br>
+                    {{ log.comments }}
+                </div>
+                <div class="text-muted text-right d-flex justify-content-end">
+                    <div>
+                        {{ log.work_date }}
+                        <br>
+                        <strong>Duration: {{ log.duration|duration }}</strong>
+                    </div>
+                    <div class="pl-2">
+                        <a class="text-danger" href="{% url 'finances:log_delete' log.slug %}"><i class="fa fa-trash" aria-hidden="true"></i></a>
+                    </div>
+                </div>
+            </div>
+        </li>
+    {% empty %}
+        <li>No logs were found.</li>
+    {% endfor %}
+</ul>
+{% comment %}
+user = models.ForeignKey(settings.AUTH_USER_MODEL)
+comments = models.TextField(blank=True)
+duration = models.DurationField(blank=True, null=True)
+work_date = models.DateField(default=timezone.now)
+created = models.DateTimeField(auto_now_add=True)
+{% endcomment %}
diff --git a/finances/urls.py b/finances/urls.py
index 21569e295d98c0c64a768ff55dc9c71bcbf07e7e..80346704ba12068b5150c4005395c29c3111effd 100644
--- a/finances/urls.py
+++ b/finances/urls.py
@@ -5,4 +5,5 @@ from . import views
 urlpatterns = [
     url(r'^$', views.timesheets, name='finance'),
     url(r'^timesheets$', views.timesheets, name='timesheets'),
+    url(r'^logs/(?P<slug>\d+)/delete$', views.LogDeleteView.as_view(), name='log_delete'),
 ]
diff --git a/finances/utils.py b/finances/utils.py
new file mode 100644
index 0000000000000000000000000000000000000000..b7edcfab36651b6f6948eb299393963c27473d2e
--- /dev/null
+++ b/finances/utils.py
@@ -0,0 +1,7 @@
+
+def id_to_slug(id):
+    return max(0, int(id) + 821)
+
+
+def slug_to_id(slug):
+    return max(0, int(slug) - 821)
diff --git a/finances/views.py b/finances/views.py
index b967443f18581bfd581f6710541e6f73e46fbf4f..f235ef16abcdc2b786b14fb70eb69e69a4566182 100644
--- a/finances/views.py
+++ b/finances/views.py
@@ -1,8 +1,14 @@
+from django.contrib import messages
 from django.contrib.auth.decorators import permission_required
+from django.http import Http404
 from django.shortcuts import render
+from django.views.generic.edit import DeleteView
 
 from production.forms import ProductionUserMonthlyActiveFilter
 
+from .models import WorkLog
+from .utils import slug_to_id
+
 
 @permission_required('scipost.can_view_timesheets', raise_exception=True)
 def timesheets(request):
@@ -18,3 +24,17 @@ def timesheets(request):
     context['totals'] = form.get_totals()
 
     return render(request, 'finances/timesheets.html', context)
+
+
+class LogDeleteView(DeleteView):
+    model = WorkLog
+
+    def get_object(self):
+        try:
+            return WorkLog.objects.get(user=self.request.user, id=slug_to_id(self.kwargs['slug']))
+        except WorkLog.DoesNotExist:
+            raise Http404
+
+    def get_success_url(self):
+        messages.success(self.request, 'Log deleted.')
+        return self.object.content.get_absolute_url()
diff --git a/production/forms.py b/production/forms.py
index 0ec7169e7c27e77e3fc40f76d5fc106d4eb34a7a..9fc2edc32957ed5d292f545c06e840ab6f2b87b4 100644
--- a/production/forms.py
+++ b/production/forms.py
@@ -1,7 +1,6 @@
 import datetime
 
 from django import forms
-from django.contrib.auth import get_user_model
 from django.utils.dates import MONTHS
 from django.db.models import Sum
 
@@ -17,11 +16,9 @@ class ProductionEventForm(forms.ModelForm):
         model = ProductionEvent
         fields = (
             'comments',
-            'duration'
         )
         widgets = {
             'comments': forms.Textarea(attrs={'rows': 4}),
-            'duration': forms.TextInput(attrs={'placeholder': 'HH:MM:SS'})
         }
 
 
diff --git a/production/migrations/0028_auto_20171007_1311.py b/production/migrations/0028_auto_20171007_1311.py
new file mode 100644
index 0000000000000000000000000000000000000000..547f5cb709e966342cc30782477dbd275f98471c
--- /dev/null
+++ b/production/migrations/0028_auto_20171007_1311.py
@@ -0,0 +1,24 @@
+# -*- coding: utf-8 -*-
+# Generated by Django 1.11.4 on 2017-10-07 11:11
+from __future__ import unicode_literals
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('production', '0027_merge_20171004_1947'),
+    ]
+
+    operations = [
+        migrations.AlterModelOptions(
+            name='proof',
+            options={'ordering': ['stream', 'version']},
+        ),
+        migrations.AlterField(
+            model_name='proof',
+            name='status',
+            field=models.CharField(choices=[('uploaded', 'Proofs uploaded'), ('sent', 'Proofs sent to authors'), ('accepted_sup', 'Proofs accepted by supervisor'), ('declined_sup', 'Proofs declined by supervisor'), ('accepted', 'Proofs accepted by authors'), ('declined', 'Proofs declined by authors'), ('renewed', 'Proofs renewed')], default='uploaded', max_length=16),
+        ),
+    ]
diff --git a/production/models.py b/production/models.py
index c04f85841a1f6e31859b269b1cd6903a3bee3aa1..fa6da78dbfb8d539f2e34ecceaf20ef93e21cc93 100644
--- a/production/models.py
+++ b/production/models.py
@@ -1,5 +1,6 @@
 from django.db import models
 from django.conf import settings
+from django.contrib.contenttypes.fields import GenericRelation
 from django.core.urlresolvers import reverse
 from django.contrib.auth.models import User
 from django.utils import timezone
@@ -11,6 +12,7 @@ from .constants import PRODUCTION_STREAM_STATUS, PRODUCTION_STREAM_INITIATED, PR
 from .managers import ProductionStreamQuerySet, ProductionEventManager, ProofsQuerySet
 from .utils import proof_id_to_slug
 
+from finances.models import WorkLog
 from scipost.storage import SecureFileStorage
 
 
@@ -41,6 +43,8 @@ class ProductionStream(models.Model):
     supervisor = models.ForeignKey('production.ProductionUser', blank=True, null=True,
                                    related_name='supervised_streams')
 
+    work_logs = GenericRelation(WorkLog, related_query_name='streams')
+
     objects = ProductionStreamQuerySet.as_manager()
 
     class Meta:
diff --git a/production/templates/production/partials/production_stream_card.html b/production/templates/production/partials/production_stream_card.html
index 3367c515d6e65280e97e0d95506184476f417b52..0a3537e741a6dc75d329acea3bb45210e7d27bae 100644
--- a/production/templates/production/partials/production_stream_card.html
+++ b/production/templates/production/partials/production_stream_card.html
@@ -9,7 +9,7 @@
   {% include 'production/partials/production_events.html' with events=stream.events.all %}
 
   {% if "can_work_for_stream" in sub_perms and prodevent_form %}
-    <h3>Add message and/or hours to the Stream</h3>
+    <h3>Add message to the Stream</h3>
     <form action="{% url 'production:add_event' stream_id=stream.id %}" method="post" class="mb-2">
         {% csrf_token %}
         {{ prodevent_form|bootstrap }}
@@ -17,6 +17,22 @@
     </form>
   {% endif %}
 
+  <h3>Work Log</h3>
+  {% if "can_work_for_stream" in sub_perms and work_log_form %}
+    <ul>
+        <li>
+            <a href="javascript:;" data-toggle="toggle" data-target="#log_form">Add hours to the Stream</a>
+            <form id="log_form" style="display: none;" action="{% url 'production:add_event' stream_id=stream.id %}" method="post" class="mb-2">
+                {% csrf_token %}
+                {{ work_log_form|bootstrap }}
+                <input type="submit" class="btn btn-secondary" name="submit" value="Log">
+            </form>
+        </li>
+    </ul>
+  {% endif %}
+
+  {% include 'partials/finances/logs.html' with logs=stream.work_logs.all %}
+
     {% if "can_perform_supervisory_actions" in sub_perms %}
           <h3>Actions</h3>
           <ul>
diff --git a/production/templates/production/partials/production_stream_card_completed.html b/production/templates/production/partials/production_stream_card_completed.html
index 2745f2d6505b8c73f6def8e51c5cf18ebfd7d30a..13f535c159b4fb283195584d49fb4dea2dcc7754 100644
--- a/production/templates/production/partials/production_stream_card_completed.html
+++ b/production/templates/production/partials/production_stream_card_completed.html
@@ -31,6 +31,9 @@
       {% block actions %}
           <h3>Events</h3>
           {% include 'production/partials/production_events.html' with events=stream.events.all non_editable=1 %}
+
+          <h3>Work Log</h3>
+          {% include 'partials/finances/logs.html' with logs=stream.work_logs.all %}
       {% endblock %}
 
     {% if "can_work_for_stream" in sub_perms %}
diff --git a/production/views.py b/production/views.py
index 11911b9b402f17ea8398f3ac6e56599ca565bf3e..20110d94d4477936b0ee99b629ed8ff74eb8e4d8 100644
--- a/production/views.py
+++ b/production/views.py
@@ -15,6 +15,8 @@ from django.views.generic.edit import UpdateView, DeleteView
 from guardian.core import ObjectPermissionChecker
 from guardian.shortcuts import assign_perm, remove_perm
 
+from finances.forms import WorkLogForm
+
 from . import constants
 from .models import ProductionUser, ProductionStream, ProductionEvent, Proof
 from .forms import ProductionEventForm, AssignOfficerForm, UserToOfficerForm,\
@@ -98,6 +100,7 @@ def stream(request, stream_id):
     assign_officer_form = AssignOfficerForm()
     assign_supervisor_form = AssignSupervisorForm()
     upload_proofs_form = ProofUploadForm()
+    work_log_form = WorkLogForm()
     status_form = StreamStatusForm(instance=stream, production_user=request.user.production_user)
 
     context = {
@@ -107,6 +110,7 @@ def stream(request, stream_id):
         'assign_supervisor_form': assign_supervisor_form,
         'status_form': status_form,
         'upload_proofs_form': upload_proofs_form,
+        'work_log_form': work_log_form,
     }
 
     if request.GET.get('json'):
@@ -161,8 +165,6 @@ def add_event(request, stream_id):
     if prodevent_form.is_valid():
         prodevent = prodevent_form.save(commit=False)
         prodevent.stream = stream
-        if prodevent.duration:
-            prodevent.event = constants.EVENT_HOUR_REGISTRATION
         prodevent.noted_by = request.user.production_user
         prodevent.save()
         messages.success(request, 'Comment added to Stream.')