Просмотр исходного кода

Previous entry form will not retain the selected date. The current months entry form will auto select the current day as long as a previous form submission hasn't set a selected date.

Entries are now identified with a randomly generated UID.

Entries also have new data properties, approved, status, approved. These will be used for managing entries by supervisors and generating reports.
Adam Day 4 лет назад
Родитель
Сommit
37796426b9

+ 11 - 1
app/models.py

@@ -1,6 +1,6 @@
 from django.db import models
 from hashlib import sha256
-import datetime
+import uuid
 
 levels = (
     ('1', 'Standard User'),
@@ -8,6 +8,11 @@ levels = (
     ('3', 'Administrator')
 )
 
+entry_status = (
+    ('current', 'Current'),
+    ('historical', 'historical')
+)
+
 
 class User(models.Model):
     status = models.BooleanField(default=True, blank=True)
@@ -37,11 +42,15 @@ class Project(models.Model):
 
 
 class Entry(models.Model):
+    uid = models.CharField(max_length=255, blank=False, default=uuid.uuid4, editable=False, unique=True)
     user = models.ForeignKey(User, on_delete=models.DO_NOTHING, default=None, null=True)
     date = models.DateField(blank=False)
     project = models.ForeignKey(Project, on_delete=models.CASCADE, blank=True, null=True)
     hours = models.CharField(max_length=2, default=0, blank=False)
     minutes = models.CharField(max_length=4, default=0, blank=False)
+    status = models.CharField(default="", max_length=255, blank=False, choices=entry_status)
+    validated = models.BooleanField(default=False)
+    approved = models.BooleanField(default=False)
 
     def __str__(self):
         return "%s, %s %s" % (self.date, self.user.last_name, self.user.first_name)
@@ -60,6 +69,7 @@ class EntryNote(models.Model):
     class Meta:
         verbose_name_plural = "Time Entry Notes"
 
+
 class Message(models.Model):
     message = models.TextField(blank=False)
     expire_date = models.DateTimeField(blank=False)

+ 19 - 1
app/templates/forms/entry_edit.html

@@ -1,7 +1,25 @@
 {% load crispy_forms_tags %}
 
-<form action="{% url 'edit_entry' entry_id=entry.id %}" method="post">
+<form action="{% url 'edit_entry' entry_id=entry.uid %}" method="post">
     <div class="row">
+        <div class="col-sm-12 col-md-4">
+            <label class="form-label" for="day_of_month">Day of month*</label>
+            <select id="day_of_month" name="day_of_month" class="form-control form-control-lg {% if form.day_of_month.errors %}is-invalid{% endif %}">
+                <option value="Blank">---</option>
+                {% for day in days_of_month %}
+                    {% if selected_day == day.day %}
+                        <option value="{{ day.day }}" selected>{{ day.label }}</option>
+                    {% else %}
+                        <option value="{{ day.day }}">{{ day.label }}</option>
+                    {% endif %}
+                {% endfor %}
+            </select>
+            {% if form.day_of_month.errors %}
+                {% for error in form.day_of_month.errors %}
+                    <p class="invalid-feedback"><strong>{{ error }}</strong></p>
+                {% endfor %}
+            {% endif %}
+        </div>
         <div class="col-sm-12 col-md-4">
             {{ form.hours | as_crispy_field }}
         </div>

+ 21 - 3
app/templates/forms/entry_edit_projects.html

@@ -1,11 +1,29 @@
 {% load crispy_forms_tags %}
 
-<form action="{% url 'edit_entry' entry_id=entry.id %}" method="post">
+<form action="{% url 'edit_entry' entry_id=entry.uid %}" method="post">
     <div class="row">
-        <div class="col-sm-12 col-md-6">
+        <div class="col-sm-12 col-md-4">
+            <label class="form-label" for="day_of_month">Day of month*</label>
+            <select id="day_of_month" name="day_of_month" class="form-control form-control-lg {% if form.day_of_month.errors %}is-invalid{% endif %}">
+                <option value="Blank">---</option>
+                {% for day in days_of_month %}
+                    {% if selected_day == day.day %}
+                        <option value="{{ day.day }}" selected>{{ day.label }}</option>
+                    {% else %}
+                        <option value="{{ day.day }}">{{ day.label }}</option>
+                    {% endif %}
+                {% endfor %}
+            </select>
+            {% if form.day_of_month.errors %}
+                {% for error in form.day_of_month.errors %}
+                    <p class="invalid-feedback"><strong>{{ error }}</strong></p>
+                {% endfor %}
+            {% endif %}
+        </div>
+        <div class="col-sm-12 col-md-4">
             {{ form.hours | as_crispy_field }}
         </div>
-        <div class="col-sm-12 col-md-6">
+        <div class="col-sm-12 col-md-4">
             {{ form.minutes | as_crispy_field }}
         </div>
         <div class="col-sm-12 col-md-6">

+ 5 - 1
app/templates/forms/timesheet_entry.html

@@ -3,7 +3,6 @@
 <form action="{% url 'timesheet' year=current_month.year month=current_month.month %}" method="post">
     <div class="row">
         <div class="col-sm-12 col-md-3">
-
             <label class="form-label" for="day_of_month">Day of month*</label>
             <select id="day_of_month" name="day_of_month" class="form-control form-control-lg">
                 <option value="-">---</option>
@@ -34,3 +33,8 @@
         {% csrf_token %}
     </div>
 </form>
+<script>
+    $(document).ready(function() {
+        console.log('test');
+    });
+</script>

+ 27 - 7
app/templates/forms/timesheet_entry_projects.html

@@ -5,13 +5,23 @@
             <label class="form-label" for="day_of_month">Day of month*</label>
             <select id="day_of_month" name="day_of_month" class="form-control form-control-lg {% if form.day_of_month.errors %}is-invalid{% endif %}">
                 <option value="Blank">---</option>
-                {% for day in days_of_month %}
-                    {% if selected_day == day.day %}
-                        <option value="{{ day.day }}" selected>{{ day.label }}</option>
-                    {% else %}
-                        <option value="{{ day.day }}">{{ day.label }}</option>
-                    {% endif %}
-                {% endfor %}
+                {% if selected_day == current_month_day %}
+                    {% for day in days_of_month %}
+                        {% if current_month_day == day.day %}
+                            <option value="{{ day.day }}" selected>{{ day.label }}</option>
+                        {% else %}
+                            <option value="{{ day.day }}">{{ day.label }}</option>
+                        {% endif %}
+                    {% endfor %}
+                {% else %}
+                    {% for day in days_of_month %}
+                        {% if selected_day == day.day %}
+                            <option value="{{ day.day }}" selected>{{ day.label }}</option>
+                        {% else %}
+                            <option value="{{ day.day }}">{{ day.label }}</option>
+                        {% endif %}
+                    {% endfor %}
+                {% endif %}
             </select>
             {% if form.day_of_month.errors %}
                 {% for error in form.day_of_month.errors %}
@@ -35,5 +45,15 @@
         {% csrf_token %}
     </div>
 </form>
+<script>
+    $(document).ready(function() {
+        console.log("{{ current_month_day }}");
+        {% if today_is_today %}
+            {% if selected_day is None %}
+                $('#day_of_month').val("{{ current_month_day }}");
+            {% endif %}
+        {% endif %}
+    });
+</script>
 
 

+ 17 - 14
app/templates/timesheet.html

@@ -4,7 +4,7 @@
 
     <div class="row mb-3">
         <div class="col-sm-12 col-md-12 col-lg-6 text-sm-center text-lg-start">
-            <h2>{{ user.first_name | title }} {{ user.last_name | title }}</h2>
+            <h2 class="p-2"><span class="oi" data-glyph="person"></span> {{ user.first_name | title }} {{ user.last_name | title }}</h2>
         </div>
         <div class="col-sm-12 col-md-12 col-lg-6 text-sm-center text-lg-end">
             {% if user.level == '3' %}
@@ -66,12 +66,12 @@
                     {% if entries %}
                     <div class="row mb-3 border-bottom">
                         <div class="col-sm-6">
-                            <h3>Total Time Worked: {{ total_time_worked }}</h3>
+                            <h3 class="mt-2">Total Time Worked: {{ total_time_worked }}</h3>
                         </div>
                         <div class="col-sm-3 text-center">
 
                         </div>
-                        <div class="col-sm-3 text-end">
+                        <div class="col-sm-3 text-end mb-3">
                             <a href="#!" class="btn btn-lg btn-dark"><span class="oi" data-glyph="print"></span></a>
                         </div>
                     </div>
@@ -79,7 +79,7 @@
                         <div class="col-sm-4 col-md-3">
                             <b>Date</b>
                         </div>
-                        <div class="col-sm-4 col-md-2">
+                        <div class="col-sm-4 col-md-3">
                             <b>Hours</b>
                         </div>
                         <div class="d-sm-none d-md-block col-md-3">
@@ -87,20 +87,19 @@
                             <b>Project</b>
                             {% endif %}
                         </div>
-                        <div class="col-md-4 text-end">
-
+                        <div class="col-sm-4 col-md-3">
                         </div>
                     </div>
 
                     {% for entry in entries %}
                         <div class="row report-row pb-3 pt-3">
-                            <div class="col-sm-12 col-md-3">
-                                {{ entry.date }}
+                            <div class="col-sm-6 col-md-3">
+                                {{ entry.date | date:'F jS Y (D.)'}}
                             </div>
-                            <div class="col-sm-6 col-md-2">
+                            <div class="col-sm-6 col-md-3">
                                 {{ entry.time_worked }}
                             </div>
-                            <div class="col-md-3">
+                            <div class="col-sm-6 col-md-3">
                                 {% if projects == "True" %}
                                     {% if entry.project %}
                                         {{ entry.project.name }}
@@ -109,9 +108,13 @@
                                     {% endif %}
                                 {% endif %}
                             </div>
-                            <div class="col-sm-6 col-md-4 text-end">
-                                <a href="{% url 'edit_entry' entry_id=entry.id %}" class="btn btn-secondary"><span class="oi" data-glyph="pencil"></span></a>
-                                <a href="#!" data-bs-toggle="modal" data-bs-target="#entry-{{ entry.id }}" class="btn btn-danger"><span class="oi" data-glyph="trash"></span></a>
+                            <div class="col-sm-6 col-md-3 text-sm-start text-md-end">
+                                {% if entry.approved %}
+                                    <span class="oi text-success" data-glyph="circle-check"></span>
+                                {% else %}
+                                    <a href="{% url 'edit_entry' entry_id=entry.uid %}" class="btn btn-secondary"><span class="oi" data-glyph="pencil"></span></a>
+                                    <a href="#!" data-bs-toggle="modal" data-bs-target="#entry-{{ entry.id }}" class="btn btn-danger"><span class="oi" data-glyph="trash"></span></a>
+                                {% endif %}
                             </div>
                             <div class="modal fade" id="entry-{{ entry.id }}" tabindex="-1" aria-labelledby="exampleModalLabel" aria-hidden="true">
                                 <div class="modal-dialog modal-dialog-centered">
@@ -129,7 +132,7 @@
                                                     <button type="button" class="btn btn-lg form-control btn-secondary" data-bs-dismiss="modal">No</button>
                                                 </div>
                                                 <div class="col-sm-12 col-md-6">
-                                                    <a href="{% url 'remove_entry' entry_id=entry.id %}" class="btn btn-lg form-control btn-dark">Yes</a>
+                                                    <a href="{% url 'remove_entry' entry_id=entry.uid %}" class="btn btn-lg form-control btn-dark">Yes</a>
                                                 </div>
                                             </div>
                                         </div>

+ 2 - 2
app/urls.py

@@ -24,6 +24,6 @@ urlpatterns = [
     path('timesheet/<int:year>/<int:month>/<int:day>', views.timesheet, name="timesheet"),
     path('logout', views.logout_user, name="logout"),
     path('create/user', views.create_user, name="create_user"),
-    path('remove/<int:entry_id>', views.remove, name='remove_entry'),
-    path('edit/<int:entry_id>', views.edit, name='edit_entry'),
+    path('remove/<slug:entry_id>', views.remove, name='remove_entry'),
+    path('edit/<slug:entry_id>', views.edit, name='edit_entry'),
 ]

+ 27 - 13
app/views.py

@@ -29,7 +29,7 @@ def days_of_month(year, month):
     days = []
     for day in range(1, r[1]+1):
         d = datetime.date(year, month, day)
-        days.append({'day': str(day), 'label': d.strftime('%A, %b. %d')})
+        days.append({'day': str(day), 'label': d.strftime('%B %d (%A)')})
     return days
 
 
@@ -193,8 +193,8 @@ def timesheet(request, year=None, month=None, day=None):
             data = form.cleaned_data
             if data['hours'] == '0' and data['minutes'] == '0':
                 selected_day = data['day_of_month']
-                form.add_error('hours', 'No time worked provided')
-                form.add_error('minutes', 'No time worked provided')
+                form.add_error('hours', 'No time provided')
+                form.add_error('minutes', 'No time provided')
             else:
                 entry = Entry()
                 entry.user = user
@@ -203,6 +203,10 @@ def timesheet(request, year=None, month=None, day=None):
                                            day=int(data['day_of_month']))
                 entry.hours = data['hours']
                 entry.minutes = data['minutes']
+                if current_month.year == date.year and current_month.month == date.month:
+                    entry.status = "current"
+                else:
+                    entry.status = "historical"
                 entry.save()
                 form = TimeEntryForm()
 
@@ -223,7 +227,7 @@ def timesheet(request, year=None, month=None, day=None):
     for entry in entries:
         time_worked = float(entry.hours) + float(entry.minutes)
         e = {
-            'id': entry.id,
+            'uid': entry.uid,
             'date': entry.date,
             'hours': entry.hours,
             'minutes': entry.minutes,
@@ -266,9 +270,12 @@ def remove(request, entry_id):
     uid = request.session.get('uid')
     user = get_user(uid)
 
-    entry = Entry.objects.filter(id=entry_id, user=user)
+    entry = Entry.objects.filter(uid=entry_id, user=user).first()
+    print(entry)
+    year = entry.date.year
+    month = entry.date.month
     entry.delete()
-    return redirect('timesheet')
+    return redirect('timesheet', year, month)
 
 
 def edit(request, entry_id):
@@ -286,18 +293,23 @@ def edit(request, entry_id):
         if form.is_valid():
             data = form.cleaned_data
             if data['hours'] == '0' and data['minutes'] == '0':
-                form.add_error('hours', 'Hours and Minutes may not be both 0')
-                form.add_error('minutes', 'Hours and Minutes may not be both 0')
+                form.add_error('hours', 'No time provided')
+                form.add_error('minutes', 'No time provided')
             else:
-                entry = Entry.objects.filter(id=entry_id, user=user).first()
+                entry = Entry.objects.filter(uid=entry_id, user=user).first()
+                year = entry.date.year
+                month = entry.date.month
+                entry.date = datetime.date(year=year, month=month, day=int(data['day_of_month']))
                 entry.hours = data['hours']
                 entry.minutes = data['minutes']
                 entry.project = data['project']
                 entry.save()
 
-                return redirect('timesheet')
+                return redirect('timesheet', year, month)
 
-    entry = Entry.objects.filter(id=entry_id, user=user).first()
+    entry = Entry.objects.filter(uid=entry_id, user=user).first()
+    year = entry.date.year
+    month = entry.date.month
     projects = Setting.objects.get(setting="Projects")
     auth_timeout = int(Setting.objects.get(setting="Session Timeout").value) * 60
 
@@ -309,14 +321,16 @@ def edit(request, entry_id):
         else:
             del form.fields['project']
     else:
-        return redirect('timesheet')
+        return redirect('timesheet', year, month)
 
     context = {
         'form': form,
         'user': user,
         'entry': entry,
         'projects': projects.value,
-        'session_timeout': auth_timeout
+        'session_timeout': auth_timeout,
+        'days_of_month': days_of_month(year, month),
+        'selected_day': str(entry.date.day)
     }
 
     return render(request, 'edit.html', context=context)