From e981595dbb575d5bc47f6ff3ba454ce11a1f8017 Mon Sep 17 00:00:00 2001 From: Mario Carloni Date: Tue, 25 Feb 2020 11:42:58 -0500 Subject: [PATCH 01/53] create inital calibration app, model, and form --- config/settings/base.py | 1 + config/urls.py | 1 + roundabout/calibrations/__init__.py | 0 roundabout/calibrations/admin.py | 3 + roundabout/calibrations/apps.py | 5 + roundabout/calibrations/forms.py | 12 +++ .../calibrations/migrations/0001_initial.py | 24 +++++ .../calibrations/migrations/__init__.py | 0 roundabout/calibrations/models.py | 17 ++++ roundabout/calibrations/tests.py | 3 + roundabout/calibrations/urls.py | 8 ++ roundabout/calibrations/views.py | 41 ++++++++ .../calibrations/calibrations_form.html | 94 +++++++++++++++++++ .../inventory/ajax_inventory_detail.html | 8 ++ 14 files changed, 217 insertions(+) create mode 100644 roundabout/calibrations/__init__.py create mode 100644 roundabout/calibrations/admin.py create mode 100644 roundabout/calibrations/apps.py create mode 100644 roundabout/calibrations/forms.py create mode 100644 roundabout/calibrations/migrations/0001_initial.py create mode 100644 roundabout/calibrations/migrations/__init__.py create mode 100644 roundabout/calibrations/models.py create mode 100644 roundabout/calibrations/tests.py create mode 100644 roundabout/calibrations/urls.py create mode 100644 roundabout/calibrations/views.py create mode 100644 roundabout/templates/calibrations/calibrations_form.html diff --git a/config/settings/base.py b/config/settings/base.py index 6d317972d..ce3f6b0d5 100644 --- a/config/settings/base.py +++ b/config/settings/base.py @@ -107,6 +107,7 @@ 'roundabout.userdefinedfields', 'roundabout.assemblies', 'roundabout.builds', + 'roundabout.calibrations', ] # https://docs.djangoproject.com/en/dev/ref/settings/#installed-apps INSTALLED_APPS = DJANGO_APPS + THIRD_PARTY_APPS + LOCAL_APPS diff --git a/config/urls.py b/config/urls.py index 400919f02..740a7b0fc 100644 --- a/config/urls.py +++ b/config/urls.py @@ -57,6 +57,7 @@ path('builds/', include('roundabout.builds.urls', namespace='builds')), path('reports/', include('roundabout.reports.urls', namespace='reports')), path('search/', include('roundabout.search.urls', namespace='search')), + path('calibrations/', include('roundabout.calibrations.urls', namespace='calibrations')), # API urls path('api/v1/', include('roundabout.inventory.api.urls')), path('api/v1/', include('roundabout.locations.api.urls')), diff --git a/roundabout/calibrations/__init__.py b/roundabout/calibrations/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/roundabout/calibrations/admin.py b/roundabout/calibrations/admin.py new file mode 100644 index 000000000..8c38f3f3d --- /dev/null +++ b/roundabout/calibrations/admin.py @@ -0,0 +1,3 @@ +from django.contrib import admin + +# Register your models here. diff --git a/roundabout/calibrations/apps.py b/roundabout/calibrations/apps.py new file mode 100644 index 000000000..68e2c2786 --- /dev/null +++ b/roundabout/calibrations/apps.py @@ -0,0 +1,5 @@ +from django.apps import AppConfig + + +class CalibrationsConfig(AppConfig): + name = 'calibrations' diff --git a/roundabout/calibrations/forms.py b/roundabout/calibrations/forms.py new file mode 100644 index 000000000..49f2ea30a --- /dev/null +++ b/roundabout/calibrations/forms.py @@ -0,0 +1,12 @@ +from django import forms +from .models import Calibration + +class CalibrationAddForm(forms.ModelForm): + + class Meta: + model = Calibration + fields = ['name', 'coefficient'] + labels = { + 'name': 'Name', + 'coefficient': 'Coefficient Value', + } \ No newline at end of file diff --git a/roundabout/calibrations/migrations/0001_initial.py b/roundabout/calibrations/migrations/0001_initial.py new file mode 100644 index 000000000..1aa758772 --- /dev/null +++ b/roundabout/calibrations/migrations/0001_initial.py @@ -0,0 +1,24 @@ +# Generated by Django 2.2.9 on 2020-02-25 16:35 + +from decimal import Decimal +import django.core.validators +from django.db import migrations, models + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + ] + + operations = [ + migrations.CreateModel( + name='Calibration', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('name', models.CharField(db_index=True, max_length=255)), + ('coefficient', models.DecimalField(blank=True, decimal_places=2, default='0.00', max_digits=9, validators=[django.core.validators.MinValueValidator(Decimal('0.00'))])), + ], + ), + ] diff --git a/roundabout/calibrations/migrations/__init__.py b/roundabout/calibrations/migrations/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/roundabout/calibrations/models.py b/roundabout/calibrations/models.py new file mode 100644 index 000000000..54acf593b --- /dev/null +++ b/roundabout/calibrations/models.py @@ -0,0 +1,17 @@ +from django.db import models +from django.core.validators import MinValueValidator + +from decimal import Decimal + +# # Create your models here. +class Calibration(models.Model): + name = models.CharField(max_length=255, unique=False, db_index=True) + coefficient = models.DecimalField(max_digits=9, decimal_places=2, validators=[MinValueValidator(Decimal('0.00'))], null=False, blank=True, default='0.00') + + def __str__(self): + return self.name + + def get_object_type(self): + return 'calibration' + + \ No newline at end of file diff --git a/roundabout/calibrations/tests.py b/roundabout/calibrations/tests.py new file mode 100644 index 000000000..7ce503c2d --- /dev/null +++ b/roundabout/calibrations/tests.py @@ -0,0 +1,3 @@ +from django.test import TestCase + +# Create your tests here. diff --git a/roundabout/calibrations/urls.py b/roundabout/calibrations/urls.py new file mode 100644 index 000000000..509b7605f --- /dev/null +++ b/roundabout/calibrations/urls.py @@ -0,0 +1,8 @@ +from django.urls import path + +from . import views + +app_name = 'calibrations' +urlpatterns = [ + path('ajax/add/', view=views.CalibrationsAddView.as_view(), name='calibrations_form') +] \ No newline at end of file diff --git a/roundabout/calibrations/views.py b/roundabout/calibrations/views.py new file mode 100644 index 000000000..b68b13579 --- /dev/null +++ b/roundabout/calibrations/views.py @@ -0,0 +1,41 @@ +from django.shortcuts import render +from django.http import HttpResponse +from django.contrib.auth.mixins import LoginRequiredMixin +from django.views.generic import CreateView +from .models import Calibration +from .forms import CalibrationAddForm +from common.util.mixins import AjaxFormMixin + +# Calibraitons landing page +class CalibrationsAddView(LoginRequiredMixin, AjaxFormMixin, CreateView): + model = Calibration + form_class = CalibrationAddForm + context_object_name = 'calibration_item' + template_name ='calibrations/calibrations_form.html' + + def get_context_data(self, **kwargs): + context = super(CalibrationsAddView, self).get_context_data(**kwargs) + context.update({ + 'node_type': 'calibrations' + }) + return context + + def get_success_url(self): + return reverse('calibrations:calibrations_detail', args=(self.object.id,)) + + def form_valid(self, form): + self.object = form.save() + + response = HttpResponseRedirect(self.get_success_url()) + + if self.request.is_ajax(): + print(form.cleaned_data) + data = { + 'message': "Successfully submitted form data.", + 'object_id': self.object.id, + 'object_type': self.object.get_object_type(), + 'detail_path': self.get_success_url(), + } + return JsonResponse(data) + else: + return response \ No newline at end of file diff --git a/roundabout/templates/calibrations/calibrations_form.html b/roundabout/templates/calibrations/calibrations_form.html new file mode 100644 index 000000000..e20fc071a --- /dev/null +++ b/roundabout/templates/calibrations/calibrations_form.html @@ -0,0 +1,94 @@ + + +{% load static i18n %} +{% load mptt_tags %} +{% load crispy_forms_tags %} + +
+ {% if calibration_item.id %} +

{{ calibration_item.name }}

+ {% else %} +

Add Calibration

+ {% endif %} +
+ +
+ + {% if latest_flag.detail %}

Why Flagged: {{ latest_flag.detail }}

{% endif %} +
+ {% csrf_token %} + {{ form.media }} + {{ form|crispy }} + +
+ {% if form.errors %} + {% for field in form %} + {% for error in field.errors %} +
+ {{ error|escape }} +
+ {% endfor %} + {% endfor %} + {% for error in form.non_field_errors %} +
+ {{ error|escape }} +
+ {% endfor %} + {% endif %} + + +
+ +
+
+ {% if calibration_item.id %} + {% if action_type == 'movetotrash' %} + + {% else %} + + {% endif %} + {% else %} + + {% endif %} + + {% if calibration_item.id %} + + {% endif %} +
+
+
+ + +
+ + +{% block javascript %} + + +{% endblock javascript %} \ No newline at end of file diff --git a/roundabout/templates/inventory/ajax_inventory_detail.html b/roundabout/templates/inventory/ajax_inventory_detail.html index 589df35e3..9e6671e16 100644 --- a/roundabout/templates/inventory/ajax_inventory_detail.html +++ b/roundabout/templates/inventory/ajax_inventory_detail.html @@ -142,6 +142,14 @@ data-location-id="{{ inventory_item.location.id}}" data-node-type="detail">Edit Inventory Details + + Add {{inventory_item.part.part_type}} calibration + + From 45dfdd1b136cbf3e04f34b5ac52c34b4267b0d0b Mon Sep 17 00:00:00 2001 From: Mario Carloni Date: Thu, 27 Feb 2020 12:06:37 -0500 Subject: [PATCH 02/53] created initial coefficient model, linked with inventory, linked calibration with part --- roundabout/calibrations/forms.py | 5 ++-- .../calibrations/migrations/0001_initial.py | 19 +++++++++++++-- roundabout/calibrations/models.py | 13 +++++++++-- roundabout/calibrations/views.py | 5 ++-- .../calibrations/calibrations_form.html | 8 ++----- .../inventory/ajax_inventory_detail.html | 23 +++++++++++++++++++ 6 files changed, 58 insertions(+), 15 deletions(-) diff --git a/roundabout/calibrations/forms.py b/roundabout/calibrations/forms.py index 49f2ea30a..08db8f87f 100644 --- a/roundabout/calibrations/forms.py +++ b/roundabout/calibrations/forms.py @@ -5,8 +5,7 @@ class CalibrationAddForm(forms.ModelForm): class Meta: model = Calibration - fields = ['name', 'coefficient'] + fields = ['name'] labels = { - 'name': 'Name', - 'coefficient': 'Coefficient Value', + 'name': 'Name' } \ No newline at end of file diff --git a/roundabout/calibrations/migrations/0001_initial.py b/roundabout/calibrations/migrations/0001_initial.py index 1aa758772..e338a8756 100644 --- a/roundabout/calibrations/migrations/0001_initial.py +++ b/roundabout/calibrations/migrations/0001_initial.py @@ -1,8 +1,10 @@ -# Generated by Django 2.2.9 on 2020-02-25 16:35 +# Generated by Django 2.2.9 on 2020-02-27 17:05 from decimal import Decimal import django.core.validators from django.db import migrations, models +import django.db.models.deletion +import django.utils.timezone class Migration(migrations.Migration): @@ -10,15 +12,28 @@ class Migration(migrations.Migration): initial = True dependencies = [ + ('inventory', '0003_auto_20191023_1347'), + ('parts', '0004_auto_20191023_1735'), ] operations = [ + migrations.CreateModel( + name='Coefficient', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('name', models.CharField(db_index=True, max_length=255)), + ('value', models.DecimalField(blank=True, decimal_places=2, default='0.00', max_digits=9, validators=[django.core.validators.MinValueValidator(Decimal('0.00'))])), + ('notes', models.TextField(blank=True)), + ('created_at', models.DateTimeField(default=django.utils.timezone.now)), + ('inventory', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='coefficient', to='inventory.Inventory')), + ], + ), migrations.CreateModel( name='Calibration', fields=[ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('name', models.CharField(db_index=True, max_length=255)), - ('coefficient', models.DecimalField(blank=True, decimal_places=2, default='0.00', max_digits=9, validators=[django.core.validators.MinValueValidator(Decimal('0.00'))])), + ('part', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='calibration', to='parts.Part')), ], ), ] diff --git a/roundabout/calibrations/models.py b/roundabout/calibrations/models.py index 54acf593b..189c737f6 100644 --- a/roundabout/calibrations/models.py +++ b/roundabout/calibrations/models.py @@ -1,12 +1,15 @@ from django.db import models from django.core.validators import MinValueValidator +from django.utils import timezone +from roundabout.parts.models import Part +from roundabout.inventory.models import Inventory from decimal import Decimal # # Create your models here. class Calibration(models.Model): name = models.CharField(max_length=255, unique=False, db_index=True) - coefficient = models.DecimalField(max_digits=9, decimal_places=2, validators=[MinValueValidator(Decimal('0.00'))], null=False, blank=True, default='0.00') + part = models.ForeignKey(Part, related_name='calibration', on_delete=models.CASCADE, null=True) def __str__(self): return self.name @@ -14,4 +17,10 @@ def __str__(self): def get_object_type(self): return 'calibration' - \ No newline at end of file + +class Coefficient(models.Model): + name = models.CharField(max_length=255, unique=False, db_index=True) + value = models.DecimalField(max_digits=9, decimal_places=2, validators=[MinValueValidator(Decimal('0.00'))], null=False, blank=True, default='0.00') + notes = models.TextField(blank=True) + created_at = models.DateTimeField(default=timezone.now) + inventory = models.ForeignKey(Inventory, related_name='coefficient', on_delete=models.CASCADE, null=True) \ No newline at end of file diff --git a/roundabout/calibrations/views.py b/roundabout/calibrations/views.py index b68b13579..d60db7bb2 100644 --- a/roundabout/calibrations/views.py +++ b/roundabout/calibrations/views.py @@ -1,10 +1,11 @@ from django.shortcuts import render -from django.http import HttpResponse +from django.http import HttpResponse, HttpResponseRedirect, JsonResponse from django.contrib.auth.mixins import LoginRequiredMixin from django.views.generic import CreateView from .models import Calibration from .forms import CalibrationAddForm from common.util.mixins import AjaxFormMixin +from django.urls import reverse, reverse_lazy # Calibraitons landing page class CalibrationsAddView(LoginRequiredMixin, AjaxFormMixin, CreateView): @@ -21,7 +22,7 @@ def get_context_data(self, **kwargs): return context def get_success_url(self): - return reverse('calibrations:calibrations_detail', args=(self.object.id,)) + return reverse('calibrations:calibrations_form') def form_valid(self, form): self.object = form.save() diff --git a/roundabout/templates/calibrations/calibrations_form.html b/roundabout/templates/calibrations/calibrations_form.html index e20fc071a..892d627d3 100644 --- a/roundabout/templates/calibrations/calibrations_form.html +++ b/roundabout/templates/calibrations/calibrations_form.html @@ -34,12 +34,8 @@

Add Calibration

{% if latest_flag.detail %}

Why Flagged: {{ latest_flag.detail }}

{% endif %} -
+ {% csrf_token %} {{ form.media }} {{ form|crispy }} diff --git a/roundabout/templates/inventory/ajax_inventory_detail.html b/roundabout/templates/inventory/ajax_inventory_detail.html index 9e6671e16..ddd120a3a 100644 --- a/roundabout/templates/inventory/ajax_inventory_detail.html +++ b/roundabout/templates/inventory/ajax_inventory_detail.html @@ -298,6 +298,12 @@ Part Specs + + + +
@@ -480,6 +486,23 @@
{{ inventory_item.assembly_part.assembly }}
+
+ + + + + + + + + {% for calibration in inventory_item.part.calibrations.all %} + + + + {% endfor %} + +
Name
{{ calibration.name }}
+
From f044e558f8c13b4e90f5b80b339bfe048b97ccf1 Mon Sep 17 00:00:00 2001 From: Mario Carloni Date: Thu, 5 Mar 2020 09:16:11 -0500 Subject: [PATCH 03/53] remove name from coefficient model, add calibration inline factory to part form --- .../0002_remove_coefficient_name.py | 17 ++++++++++ roundabout/calibrations/models.py | 9 +++-- roundabout/parts/forms.py | 2 ++ roundabout/parts/views.py | 5 +-- .../inventory/ajax_inventory_detail.html | 2 +- .../templates/parts/ajax_part_form.html | 33 +++++++++++++++++++ 6 files changed, 63 insertions(+), 5 deletions(-) create mode 100644 roundabout/calibrations/migrations/0002_remove_coefficient_name.py diff --git a/roundabout/calibrations/migrations/0002_remove_coefficient_name.py b/roundabout/calibrations/migrations/0002_remove_coefficient_name.py new file mode 100644 index 000000000..c3924d9bd --- /dev/null +++ b/roundabout/calibrations/migrations/0002_remove_coefficient_name.py @@ -0,0 +1,17 @@ +# Generated by Django 2.2.9 on 2020-03-05 14:11 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('calibrations', '0001_initial'), + ] + + operations = [ + migrations.RemoveField( + model_name='coefficient', + name='name', + ), + ] diff --git a/roundabout/calibrations/models.py b/roundabout/calibrations/models.py index 189c737f6..2c52cebd0 100644 --- a/roundabout/calibrations/models.py +++ b/roundabout/calibrations/models.py @@ -19,8 +19,13 @@ def get_object_type(self): class Coefficient(models.Model): - name = models.CharField(max_length=255, unique=False, db_index=True) value = models.DecimalField(max_digits=9, decimal_places=2, validators=[MinValueValidator(Decimal('0.00'))], null=False, blank=True, default='0.00') notes = models.TextField(blank=True) created_at = models.DateTimeField(default=timezone.now) - inventory = models.ForeignKey(Inventory, related_name='coefficient', on_delete=models.CASCADE, null=True) \ No newline at end of file + inventory = models.ForeignKey(Inventory, related_name='coefficient', on_delete=models.CASCADE, null=True) + + def __str__(self): + return self.name + + def get_object_type(self): + return 'calibration' \ No newline at end of file diff --git a/roundabout/parts/forms.py b/roundabout/parts/forms.py index afd6ae380..193940832 100644 --- a/roundabout/parts/forms.py +++ b/roundabout/parts/forms.py @@ -33,6 +33,7 @@ from roundabout.locations.models import Location from roundabout.parts.widgets import PartParentWidget, PartLocationWidget from roundabout.userdefinedfields.models import Field, FieldValue +from roundabout.calibrations.models import Calibration, Coefficient class PartForm(forms.ModelForm): @@ -60,6 +61,7 @@ def clean_part_number(self): 'note': SummernoteWidget(), }, extra=1, can_delete=False) DocumentationFormset = inlineformset_factory(Revision, Documentation, fields=('name', 'doc_type', 'doc_link'), extra=1, can_delete=True) +CalibrationFormset = inlineformset_factory(Part, Calibration, fields=('name',), extra=1, can_delete=True) class RevisionForm(forms.ModelForm): diff --git a/roundabout/parts/views.py b/roundabout/parts/views.py index 64334a052..068d299d9 100644 --- a/roundabout/parts/views.py +++ b/roundabout/parts/views.py @@ -31,7 +31,7 @@ from django.template.defaultfilters import slugify from .models import Part, PartType, Revision, Documentation -from .forms import PartForm, PartTypeForm, RevisionForm, DocumentationFormset, RevisionFormset, PartUdfAddFieldForm, PartUdfFieldSetValueForm +from .forms import PartForm, PartTypeForm, RevisionForm, DocumentationFormset, RevisionFormset, PartUdfAddFieldForm, PartUdfFieldSetValueForm, CalibrationFormset from roundabout.locations.models import Location from roundabout.inventory.models import Inventory @@ -141,7 +141,8 @@ def get(self, request, *args, **kwargs): form = self.get_form(form_class) revision_form = RevisionFormset(instance=self.object) documentation_form = DocumentationFormset(instance=self.object) - return self.render_to_response(self.get_context_data(form=form, revision_form=revision_form, documentation_form=documentation_form)) + calibration_form = CalibrationFormset(instance=self.object) + return self.render_to_response(self.get_context_data(form=form, revision_form=revision_form, documentation_form=documentation_form, calibration_form=calibration_form)) def post(self, request, *args, **kwargs): self.object = None diff --git a/roundabout/templates/inventory/ajax_inventory_detail.html b/roundabout/templates/inventory/ajax_inventory_detail.html index ddd120a3a..d424a162e 100644 --- a/roundabout/templates/inventory/ajax_inventory_detail.html +++ b/roundabout/templates/inventory/ajax_inventory_detail.html @@ -300,7 +300,7 @@ diff --git a/roundabout/templates/parts/ajax_part_form.html b/roundabout/templates/parts/ajax_part_form.html index d34d422e9..bf0c36ad7 100644 --- a/roundabout/templates/parts/ajax_part_form.html +++ b/roundabout/templates/parts/ajax_part_form.html @@ -142,6 +142,39 @@
Revision Documentation
{% endif %} +
+
Calibrations
+ + + + + + {{ calibration_form.management_form }} + + {% if calibration_form.errors %} + +
+ {% for dict in calibration_form.errors %} + + {% for error in dict.values %} + {{ error|escape }} + {% endfor %} + + {% endfor %} +
+ + {% endif %} + + {% for cal in calibration_form %} + + + + + {% endfor %} + +
Name
{% if cal.id %}{{ cal.DELETE }}{% endif %} {{ cal.id }} {{ cal.name }}
+
+
{% if part_template.id %} From 411493590268757b7a3915a5a6fa513f2a625631 Mon Sep 17 00:00:00 2001 From: Mario Carloni Date: Thu, 5 Mar 2020 15:59:15 -0500 Subject: [PATCH 04/53] part creation form allows multiple calibration inputs --- roundabout/parts/views.py | 18 ++++++++++++------ .../templates/parts/ajax_part_detail.html | 14 ++++++++++++++ roundabout/templates/parts/ajax_part_form.html | 6 +++++- 3 files changed, 31 insertions(+), 7 deletions(-) diff --git a/roundabout/parts/views.py b/roundabout/parts/views.py index 068d299d9..0df9cfe06 100644 --- a/roundabout/parts/views.py +++ b/roundabout/parts/views.py @@ -152,12 +152,14 @@ def post(self, request, *args, **kwargs): self.request.POST, instance=self.object) documentation_form = DocumentationFormset( self.request.POST, instance=self.object) + calibration_form = CalibrationFormset( + self.request.POST, instance=self.object) - if (form.is_valid() and revision_form.is_valid() and documentation_form.is_valid()): - return self.form_valid(form, revision_form, documentation_form) - return self.form_invalid(form, revision_form, documentation_form) + if (form.is_valid() and revision_form.is_valid() and documentation_form.is_valid() and calibration_form.is_valid()): + return self.form_valid(form, revision_form, documentation_form, calibration_form) + return self.form_invalid(form, revision_form, documentation_form, calibration_form) - def form_valid(self, form, revision_form, documentation_form): + def form_valid(self, form, revision_form, documentation_form, calibration_form): self.object = form.save() # Save the Revision inline model form revision_form.instance = self.object @@ -174,6 +176,10 @@ def form_valid(self, form, revision_form, documentation_form): # instance.revision = revision documentation_form.save() + # Save Calibration form + calibration_form.instance = self.object + calibration_form.save() + # Check for any global Part Type custom fields for this Part custom_fields = self.object.part_type.custom_fields.all() @@ -195,14 +201,14 @@ def form_valid(self, form, revision_form, documentation_form): else: return response - def form_invalid(self, form, documentation_form): + def form_invalid(self, form, documentation_form, calibration_form): form_errors = documentation_form.errors if self.request.is_ajax(): data = form.errors return JsonResponse(data, status=400) else: - return self.render_to_response(self.get_context_data(form=form, revision_form=revision_form, documentation_form=documentation_form, form_errors=form_errors)) + return self.render_to_response(self.get_context_data(form=form, revision_form=revision_form, documentation_form=documentation_form, calibration_form=calibration_form, form_errors=form_errors)) def get_success_url(self): return reverse('parts:ajax_parts_detail', args=(self.object.id, )) diff --git a/roundabout/templates/parts/ajax_part_detail.html b/roundabout/templates/parts/ajax_part_detail.html index bd2d3bd92..f22591e61 100644 --- a/roundabout/templates/parts/ajax_part_detail.html +++ b/roundabout/templates/parts/ajax_part_detail.html @@ -207,6 +207,20 @@

Custom Fields

{% endfor %} +
+ + + +

Calibrations

+ +
    + {% for calibration in part_template.calibration.all %} +
  • + {{ calibration.name }} +
  • + {% endfor %} +
+ diff --git a/roundabout/templates/parts/ajax_part_detail.html b/roundabout/templates/parts/ajax_part_detail.html index f22591e61..722865979 100644 --- a/roundabout/templates/parts/ajax_part_detail.html +++ b/roundabout/templates/parts/ajax_part_detail.html @@ -212,14 +212,26 @@

Custom Fields

Calibrations

- -
    - {% for calibration in part_template.calibration.all %} -
  • - {{ calibration.name }} -
  • - {% endfor %} -
+ + + + + + + + + {% for cal in part_template.calibration.all %} + {% for coeff in cal.coefficient.all %} + + + + + + + {% endfor %} + {% endfor %} + +
NameValueNotesCreated
{{ cal.name }}{{ coeff.value }}{{ coeff.notes }}{{ coeff.created_at }}
From 44315fcb1d373fad13327a680df28159884201ef Mon Sep 17 00:00:00 2001 From: Mario Carloni Date: Fri, 13 Mar 2020 20:26:43 -0400 Subject: [PATCH 06/53] modified Calibration and Coefficient models, added Calibration Event model, modified references --- roundabout/calibrations/forms.py | 8 +-- .../migrations/0004_auto_20200313_2300.py | 67 +++++++++++++++++++ roundabout/calibrations/models.py | 47 +++++++++---- roundabout/calibrations/views.py | 4 +- roundabout/parts/forms.py | 5 +- roundabout/parts/views.py | 26 +++---- .../inventory/ajax_inventory_detail.html | 12 +--- .../templates/parts/ajax_part_detail.html | 16 ++--- .../templates/parts/ajax_part_form.html | 11 +-- 9 files changed, 126 insertions(+), 70 deletions(-) create mode 100644 roundabout/calibrations/migrations/0004_auto_20200313_2300.py diff --git a/roundabout/calibrations/forms.py b/roundabout/calibrations/forms.py index 08db8f87f..b2d48cfa2 100644 --- a/roundabout/calibrations/forms.py +++ b/roundabout/calibrations/forms.py @@ -1,11 +1,11 @@ from django import forms -from .models import Calibration +from .models import CoefficientName class CalibrationAddForm(forms.ModelForm): class Meta: - model = Calibration - fields = ['name'] + model = CoefficientName + fields = ['calibration_name'] labels = { - 'name': 'Name' + 'calibration_name': 'Name' } \ No newline at end of file diff --git a/roundabout/calibrations/migrations/0004_auto_20200313_2300.py b/roundabout/calibrations/migrations/0004_auto_20200313_2300.py new file mode 100644 index 000000000..28ffe1242 --- /dev/null +++ b/roundabout/calibrations/migrations/0004_auto_20200313_2300.py @@ -0,0 +1,67 @@ +# Generated by Django 2.2.9 on 2020-03-13 23:00 + +from decimal import Decimal +from django.conf import settings +import django.core.validators +from django.db import migrations, models +import django.db.models.deletion +import django.utils.timezone + + +class Migration(migrations.Migration): + + dependencies = [ + ('parts', '0004_auto_20191023_1735'), + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('inventory', '0003_auto_20191023_1347'), + ('calibrations', '0003_coefficient_calibration'), + ] + + operations = [ + migrations.CreateModel( + name='CalibrationEvent', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('created_at', models.DateTimeField(default=django.utils.timezone.now)), + ('calibration_date', models.DateTimeField(default=django.utils.timezone.now)), + ('approved', models.BooleanField(choices=[(True, 'Approved'), (False, 'Draft')], default=False)), + ('deployment', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='calibration_events', to='inventory.Deployment')), + ('inventory', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='calibration_events', to='inventory.Inventory')), + ('user_approver', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='calibration_events_approver', to=settings.AUTH_USER_MODEL)), + ('user_draft', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='calibration_events_drafter', to=settings.AUTH_USER_MODEL)), + ], + ), + migrations.CreateModel( + name='CoefficientName', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('calibration_name', models.CharField(db_index=True, max_length=255)), + ('part', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='coefficient_names', to='parts.Part')), + ], + ), + migrations.CreateModel( + name='CoefficientValue', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('value', models.DecimalField(blank=True, decimal_places=2, default='0.00', max_digits=9, validators=[django.core.validators.MinValueValidator(Decimal('0.00'))])), + ('notes', models.TextField(blank=True)), + ('created_at', models.DateTimeField(default=django.utils.timezone.now)), + ('calibration_event', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='coefficient_values', to='calibrations.CalibrationEvent')), + ('coefficient_name', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='coefficient_values', to='calibrations.CoefficientName')), + ], + ), + migrations.RemoveField( + model_name='coefficient', + name='calibration', + ), + migrations.RemoveField( + model_name='coefficient', + name='inventory', + ), + migrations.DeleteModel( + name='Calibration', + ), + migrations.DeleteModel( + name='Coefficient', + ), + ] diff --git a/roundabout/calibrations/models.py b/roundabout/calibrations/models.py index bfdc2af85..c60bb9f5a 100644 --- a/roundabout/calibrations/models.py +++ b/roundabout/calibrations/models.py @@ -2,31 +2,54 @@ from django.core.validators import MinValueValidator from django.utils import timezone from roundabout.parts.models import Part -from roundabout.inventory.models import Inventory - +from roundabout.inventory.models import Inventory, Deployment +from roundabout.users.models import User from decimal import Decimal -# # Create your models here. -class Calibration(models.Model): - name = models.CharField(max_length=255, unique=False, db_index=True) - part = models.ForeignKey(Part, related_name='calibration', on_delete=models.CASCADE, null=True) + +class CoefficientName(models.Model): + calibration_name = models.CharField(max_length=255, unique=False, db_index=True) + part = models.ForeignKey(Part, related_name='coefficient_names', on_delete=models.CASCADE, null=True) + + def __str__(self): + return self.name + + def get_object_type(self): + return 'coefficient_name' + + +class CalibrationEvent(models.Model): + APPROVAL_STATUS = ( + (True, "Approved"), + (False, "Draft"), + ) + created_at = models.DateTimeField(default=timezone.now) + calibration_date = models.DateTimeField(default=timezone.now) + user_draft = models.ForeignKey(User, related_name='calibration_events_drafter', + on_delete=models.SET_NULL, null=True, blank=False) + user_approver = models.ForeignKey(User, related_name='calibration_events_approver', + on_delete=models.SET_NULL, null=True, blank=False) + inventory = models.ForeignKey(Inventory, related_name='calibration_events', on_delete=models.CASCADE, null=False) + deployment = models.ForeignKey(Deployment, related_name='calibration_events', on_delete=models.CASCADE, null=True) + approved = models.BooleanField(choices=APPROVAL_STATUS, blank=False, default=False) def __str__(self): return self.name def get_object_type(self): - return 'calibration' - + return 'calibration_event' + + -class Coefficient(models.Model): +class CoefficientValue(models.Model): value = models.DecimalField(max_digits=9, decimal_places=2, validators=[MinValueValidator(Decimal('0.00'))], null=False, blank=True, default='0.00') notes = models.TextField(blank=True) created_at = models.DateTimeField(default=timezone.now) - inventory = models.ForeignKey(Inventory, related_name='coefficient', on_delete=models.CASCADE, null=True) - calibration = models.ForeignKey(Calibration, related_name='coefficient', on_delete=models.CASCADE, null=True) + coefficient_name = models.ForeignKey(CoefficientName, related_name='coefficient_values', on_delete=models.CASCADE, null=True) + calibration_event = models.ForeignKey(CalibrationEvent, related_name='coefficient_values', on_delete=models.CASCADE, null=True) def __str__(self): return self.value def get_object_type(self): - return 'coefficient' \ No newline at end of file + return 'coefficient_value' diff --git a/roundabout/calibrations/views.py b/roundabout/calibrations/views.py index d60db7bb2..288177f45 100644 --- a/roundabout/calibrations/views.py +++ b/roundabout/calibrations/views.py @@ -2,14 +2,14 @@ from django.http import HttpResponse, HttpResponseRedirect, JsonResponse from django.contrib.auth.mixins import LoginRequiredMixin from django.views.generic import CreateView -from .models import Calibration +from .models import CoefficientName from .forms import CalibrationAddForm from common.util.mixins import AjaxFormMixin from django.urls import reverse, reverse_lazy # Calibraitons landing page class CalibrationsAddView(LoginRequiredMixin, AjaxFormMixin, CreateView): - model = Calibration + model = CoefficientName form_class = CalibrationAddForm context_object_name = 'calibration_item' template_name ='calibrations/calibrations_form.html' diff --git a/roundabout/parts/forms.py b/roundabout/parts/forms.py index a84283a3f..4bd97ee63 100644 --- a/roundabout/parts/forms.py +++ b/roundabout/parts/forms.py @@ -33,7 +33,7 @@ from roundabout.locations.models import Location from roundabout.parts.widgets import PartParentWidget, PartLocationWidget from roundabout.userdefinedfields.models import Field, FieldValue -from roundabout.calibrations.models import Calibration, Coefficient +from roundabout.calibrations.models import CoefficientName from roundabout.inventory.models import Inventory @@ -62,8 +62,7 @@ def clean_part_number(self): 'note': SummernoteWidget(), }, extra=1, can_delete=False) DocumentationFormset = inlineformset_factory(Revision, Documentation, fields=('name', 'doc_type', 'doc_link'), extra=1, can_delete=True) -CalibrationFormset = inlineformset_factory(Part, Calibration, fields=('name',), extra=1, can_delete=True) -CoefficientFormset = inlineformset_factory(Calibration, Coefficient, fields=('value','notes',), extra=1, can_delete=True) +CalibrationFormset = inlineformset_factory(Part, CoefficientName, fields=('calibration_name',), extra=1, can_delete=True) class RevisionForm(forms.ModelForm): diff --git a/roundabout/parts/views.py b/roundabout/parts/views.py index b3a386ec3..f03fcabbf 100644 --- a/roundabout/parts/views.py +++ b/roundabout/parts/views.py @@ -31,7 +31,7 @@ from django.template.defaultfilters import slugify from .models import Part, PartType, Revision, Documentation -from .forms import PartForm, PartTypeForm, RevisionForm, DocumentationFormset, RevisionFormset, PartUdfAddFieldForm, PartUdfFieldSetValueForm, CalibrationFormset, CoefficientFormset +from .forms import PartForm, PartTypeForm, RevisionForm, DocumentationFormset, RevisionFormset, PartUdfAddFieldForm, PartUdfFieldSetValueForm, CalibrationFormset from roundabout.locations.models import Location from roundabout.inventory.models import Inventory @@ -142,8 +142,7 @@ def get(self, request, *args, **kwargs): revision_form = RevisionFormset(instance=self.object) documentation_form = DocumentationFormset(instance=self.object) calibration_form = CalibrationFormset(instance=self.object) - coefficient_form = CoefficientFormset(instance=self.object) - return self.render_to_response(self.get_context_data(form=form, revision_form=revision_form, documentation_form=documentation_form, calibration_form=calibration_form, coefficient_form=coefficient_form)) + return self.render_to_response(self.get_context_data(form=form, revision_form=revision_form, documentation_form=documentation_form, calibration_form=calibration_form)) def post(self, request, *args, **kwargs): self.object = None @@ -155,14 +154,12 @@ def post(self, request, *args, **kwargs): self.request.POST, instance=self.object) calibration_form = CalibrationFormset( self.request.POST, instance=self.object) - coefficient_form = CoefficientFormset( - self.request.POST, instance=self.object) - if (form.is_valid() and revision_form.is_valid() and documentation_form.is_valid() and calibration_form.is_valid() and coefficient_form.is_valid()): - return self.form_valid(form, revision_form, documentation_form, calibration_form, coefficient_form) - return self.form_invalid(form, revision_form, documentation_form, calibration_form, coefficient_form) + if (form.is_valid() and revision_form.is_valid() and documentation_form.is_valid() and calibration_form.is_valid()): + return self.form_valid(form, revision_form, documentation_form, calibration_form) + return self.form_invalid(form, revision_form, documentation_form, calibration_form) - def form_valid(self, form, revision_form, documentation_form, calibration_form, coefficient_form): + def form_valid(self, form, revision_form, documentation_form, calibration_form): self.object = form.save() # Save the Revision inline model form revision_form.instance = self.object @@ -183,13 +180,6 @@ def form_valid(self, form, revision_form, documentation_form, calibration_form, calibration_form.instance = self.object saved_cals = calibration_form.save() - # Save Coefficient form - for cal in saved_cals: - coefficient_form.instance = cal - coefficient_form.save() - - - # Check for any global Part Type custom fields for this Part custom_fields = self.object.part_type.custom_fields.all() @@ -211,14 +201,14 @@ def form_valid(self, form, revision_form, documentation_form, calibration_form, else: return response - def form_invalid(self, form, documentation_form, calibration_form, coefficient_form): + def form_invalid(self, form, documentation_form, calibration_form): form_errors = documentation_form.errors if self.request.is_ajax(): data = form.errors return JsonResponse(data, status=400) else: - return self.render_to_response(self.get_context_data(form=form, revision_form=revision_form, documentation_form=documentation_form, calibration_form=calibration_form, coefficient_form=coefficient_form, form_errors=form_errors)) + return self.render_to_response(self.get_context_data(form=form, revision_form=revision_form, documentation_form=documentation_form, calibration_form=calibration_form, form_errors=form_errors)) def get_success_url(self): return reverse('parts:ajax_parts_detail', args=(self.object.id, )) diff --git a/roundabout/templates/inventory/ajax_inventory_detail.html b/roundabout/templates/inventory/ajax_inventory_detail.html index 509a7b8b0..023acc442 100644 --- a/roundabout/templates/inventory/ajax_inventory_detail.html +++ b/roundabout/templates/inventory/ajax_inventory_detail.html @@ -492,22 +492,14 @@
{{ inventory_item.assembly_part.assembly }}
Name - Value - Notes - Created - {% for cal in inventory_item.part.calibration.all %} - {% for coeff in cal.coefficient.all %} + {% for cal in inventory_item.part.coefficient_names.all %} - {{ cal.name }} - {{ coeff.value }} - {{ coeff.notes }} - {{ coeff.created_at }} + {{ cal.calibration_name }} {% endfor %} - {% endfor %}
diff --git a/roundabout/templates/parts/ajax_part_detail.html b/roundabout/templates/parts/ajax_part_detail.html index 722865979..a20513378 100644 --- a/roundabout/templates/parts/ajax_part_detail.html +++ b/roundabout/templates/parts/ajax_part_detail.html @@ -215,20 +215,12 @@

Calibrations

- - - - {% for cal in part_template.calibration.all %} - {% for coeff in cal.coefficient.all %} - - - - - - - {% endfor %} + {% for cal in part_template.coefficient_names.all %} + + + {% endfor %}
NameValueNotesCreated
{{ cal.name }}{{ coeff.value }}{{ coeff.notes }}{{ coeff.created_at }}
{{ cal.calibration_name }}
diff --git a/roundabout/templates/parts/ajax_part_form.html b/roundabout/templates/parts/ajax_part_form.html index 962ca6f0d..f7a94f4e5 100644 --- a/roundabout/templates/parts/ajax_part_form.html +++ b/roundabout/templates/parts/ajax_part_form.html @@ -147,12 +147,9 @@
Calibrations
- - {{ calibration_form.management_form }} - {{ coefficient_form.management_form }} {% if calibration_form.errors %} @@ -169,15 +166,11 @@
Calibrations
{% endif %} {% for cal in calibration_form %} - {% for coeff in coefficient_form %} - - - + {% endfor %} - {% endfor %}
NameValueNotes
{% if cal.id %}{{ cal.DELETE }}{% endif %} {{ cal.id }} {{ cal.name }}{{ cal.id }} {{ coeff.value }}{{ cal.id }} {{ coeff.notes }}{% if cal.id %}{{ cal.DELETE }}{% endif %} {{ cal.id }} {{ cal.calibration_name }}
@@ -221,7 +214,7 @@
Calibrations
deleteText: 'remove', }); $('.calibration-form tbody tr').formset({ - prefix: 'calibration', + prefix: 'coefficient_names', addText: 'add calibration', deleteText: 'remove', }); From a85ee17768cf376e2dcd94012681f3d5fdefaaa3 Mon Sep 17 00:00:00 2001 From: Mario Carloni Date: Mon, 16 Mar 2020 16:07:46 -0400 Subject: [PATCH 07/53] included coefficient name to the coefficient value form, obtained inventory item for calibration event instance, first pass at populating calibration event model --- roundabout/calibrations/forms.py | 15 +++-- roundabout/calibrations/models.py | 24 +++---- roundabout/calibrations/views.py | 63 ++++++++++++++----- .../calibrations/calibrations_form.html | 1 + .../inventory/ajax_inventory_detail.html | 12 +++- 5 files changed, 83 insertions(+), 32 deletions(-) diff --git a/roundabout/calibrations/forms.py b/roundabout/calibrations/forms.py index b2d48cfa2..675a6073c 100644 --- a/roundabout/calibrations/forms.py +++ b/roundabout/calibrations/forms.py @@ -1,11 +1,16 @@ from django import forms -from .models import CoefficientName +from .models import CoefficientName, CoefficientValue +from django.forms.models import inlineformset_factory class CalibrationAddForm(forms.ModelForm): class Meta: - model = CoefficientName - fields = ['calibration_name'] + model = CoefficientValue + fields = ['coefficient_name', 'value', 'notes'] labels = { - 'calibration_name': 'Name' - } \ No newline at end of file + 'coefficient_name': 'Name', + 'value': 'Value', + 'notes': 'Notes' + } + +CoefficientFormset = inlineformset_factory(CoefficientName, CoefficientValue, fields=('value','notes',), extra=1, can_delete=True) \ No newline at end of file diff --git a/roundabout/calibrations/models.py b/roundabout/calibrations/models.py index c60bb9f5a..89a2ccb01 100644 --- a/roundabout/calibrations/models.py +++ b/roundabout/calibrations/models.py @@ -12,7 +12,7 @@ class CoefficientName(models.Model): part = models.ForeignKey(Part, related_name='coefficient_names', on_delete=models.CASCADE, null=True) def __str__(self): - return self.name + return self.calibration_name def get_object_type(self): return 'coefficient_name' @@ -20,36 +20,38 @@ def get_object_type(self): class CalibrationEvent(models.Model): APPROVAL_STATUS = ( - (True, "Approved"), - (False, "Draft"), + (True, "Approved"), + (False, "Draft"), ) created_at = models.DateTimeField(default=timezone.now) calibration_date = models.DateTimeField(default=timezone.now) user_draft = models.ForeignKey(User, related_name='calibration_events_drafter', - on_delete=models.SET_NULL, null=True, blank=False) + on_delete=models.SET_NULL, null=True, blank=False) user_approver = models.ForeignKey(User, related_name='calibration_events_approver', - on_delete=models.SET_NULL, null=True, blank=False) + on_delete=models.SET_NULL, null=True, blank=False) inventory = models.ForeignKey(Inventory, related_name='calibration_events', on_delete=models.CASCADE, null=False) deployment = models.ForeignKey(Deployment, related_name='calibration_events', on_delete=models.CASCADE, null=True) approved = models.BooleanField(choices=APPROVAL_STATUS, blank=False, default=False) def __str__(self): - return self.name + return self.calibration_date def get_object_type(self): return 'calibration_event' - class CoefficientValue(models.Model): - value = models.DecimalField(max_digits=9, decimal_places=2, validators=[MinValueValidator(Decimal('0.00'))], null=False, blank=True, default='0.00') + value = models.DecimalField(max_digits=9, decimal_places=2, validators=[ + MinValueValidator(Decimal('0.00'))], null=False, blank=True, default='0.00') notes = models.TextField(blank=True) created_at = models.DateTimeField(default=timezone.now) - coefficient_name = models.ForeignKey(CoefficientName, related_name='coefficient_values', on_delete=models.CASCADE, null=True) - calibration_event = models.ForeignKey(CalibrationEvent, related_name='coefficient_values', on_delete=models.CASCADE, null=True) + coefficient_name = models.ForeignKey( + CoefficientName, related_name='coefficient_values', on_delete=models.CASCADE, null=True) + calibration_event = models.ForeignKey( + CalibrationEvent, related_name='coefficient_values', on_delete=models.CASCADE, null=True) def __str__(self): - return self.value + return self.notes def get_object_type(self): return 'coefficient_value' diff --git a/roundabout/calibrations/views.py b/roundabout/calibrations/views.py index 288177f45..a19b04b22 100644 --- a/roundabout/calibrations/views.py +++ b/roundabout/calibrations/views.py @@ -2,31 +2,54 @@ from django.http import HttpResponse, HttpResponseRedirect, JsonResponse from django.contrib.auth.mixins import LoginRequiredMixin from django.views.generic import CreateView -from .models import CoefficientName -from .forms import CalibrationAddForm +from .models import CoefficientName, CalibrationEvent +from .forms import CalibrationAddForm, CoefficientFormset from common.util.mixins import AjaxFormMixin from django.urls import reverse, reverse_lazy +from roundabout.parts.models import Part +from roundabout.users.models import User +from roundabout.inventory.models import Inventory # Calibraitons landing page class CalibrationsAddView(LoginRequiredMixin, AjaxFormMixin, CreateView): model = CoefficientName form_class = CalibrationAddForm - context_object_name = 'calibration_item' - template_name ='calibrations/calibrations_form.html' + context_object_name = 'part_template' + template_name='calibrations/calibrations_form.html' - def get_context_data(self, **kwargs): - context = super(CalibrationsAddView, self).get_context_data(**kwargs) - context.update({ - 'node_type': 'calibrations' - }) - return context + def get(self, request, *args, **kwargs): + self.object = None + form_class = self.get_form_class() + form = self.get_form(form_class) + coefficient_form = CoefficientFormset(instance=self.object) - def get_success_url(self): - return reverse('calibrations:calibrations_form') + return self.render_to_response(self.get_context_data(form=form, coefficient_form=coefficient_form)) + + def post(self, request, *args, **kwargs): + self.object = None + form_class = self.get_form_class() + form = self.get_form(form_class) + + coefficient_form = CoefficientFormset( + self.request.POST, instance=self.object) - def form_valid(self, form): + if (form.is_valid() and coefficient_form.is_valid()): + return self.form_valid(form, coefficient_form) + return self.form_invalid(form, coefficient_form) + + def form_valid(self, form, coefficient_form): self.object = form.save() + # Save CoefficientValue form using CoefficientName instance + calibration_name = form.cleaned_data['coefficient_name'] + coeffname_inst = CoefficientName.objects.get(calibration_name=calibration_name) + coefficient_form.instance = coeffname_inst + coefficient_form.save() + + inv_inst = coeffname_inst.part.inventory.all() + inv_id = inv_inst[0] + event_record = CalibrationEvent.objects.create(inventory=inv_id, user_draft=self.request.user) + response = HttpResponseRedirect(self.get_success_url()) if self.request.is_ajax(): @@ -39,4 +62,16 @@ def form_valid(self, form): } return JsonResponse(data) else: - return response \ No newline at end of file + return response + + def form_invalid(self, form, coefficient_form): + form_errors = coefficient_form.errors + + if self.request.is_ajax(): + data = form.errors + return JsonResponse(data, status=400) + else: + return self.render_to_response(self.get_context_data(form=form, coefficient_form=coefficient_form, form_errors=form_errors)) + + def get_success_url(self): + return reverse('inventory:ajax_inventory_detail', args=(self.object.id, )) \ No newline at end of file diff --git a/roundabout/templates/calibrations/calibrations_form.html b/roundabout/templates/calibrations/calibrations_form.html index 892d627d3..042c2f410 100644 --- a/roundabout/templates/calibrations/calibrations_form.html +++ b/roundabout/templates/calibrations/calibrations_form.html @@ -38,6 +38,7 @@

Add Calibration

enctype="multipart/form-data" data-url='{{ request.build_absolute_uri|safe }}'> {% csrf_token %} {{ form.media }} + {{ coefficient_form.management_form }} {{ form|crispy }}
diff --git a/roundabout/templates/inventory/ajax_inventory_detail.html b/roundabout/templates/inventory/ajax_inventory_detail.html index 023acc442..bd569a555 100644 --- a/roundabout/templates/inventory/ajax_inventory_detail.html +++ b/roundabout/templates/inventory/ajax_inventory_detail.html @@ -491,13 +491,21 @@
{{ inventory_item.assembly_part.assembly }}
+ + + + - {% for cal in inventory_item.part.coefficient_names.all %} + {% for caL_event in inventory_item.calibration_events.all %} - + + + + + {% endfor %} From 9fb87bb79a4d4c043c2c9efb26b7fbb0a2bf63ee Mon Sep 17 00:00:00 2001 From: Mario Carloni Date: Tue, 17 Mar 2020 16:00:46 -0400 Subject: [PATCH 08/53] added unique constraint on calibration names, returned inventory detail template on completion of coefficient form using the inventory id, added logic to display related coefficient information for event history --- .../migrations/0005_auto_20200317_1916.py | 17 +++++++ roundabout/calibrations/models.py | 5 ++ roundabout/calibrations/views.py | 10 ++-- roundabout/parts/views.py | 6 +-- .../inventory/ajax_inventory_detail.html | 50 ++++++++++--------- 5 files changed, 57 insertions(+), 31 deletions(-) create mode 100644 roundabout/calibrations/migrations/0005_auto_20200317_1916.py diff --git a/roundabout/calibrations/migrations/0005_auto_20200317_1916.py b/roundabout/calibrations/migrations/0005_auto_20200317_1916.py new file mode 100644 index 000000000..e978acf99 --- /dev/null +++ b/roundabout/calibrations/migrations/0005_auto_20200317_1916.py @@ -0,0 +1,17 @@ +# Generated by Django 2.2.9 on 2020-03-17 19:16 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('calibrations', '0004_auto_20200313_2300'), + ] + + operations = [ + migrations.AddConstraint( + model_name='coefficientname', + constraint=models.UniqueConstraint(fields=('calibration_name',), name='unique_name'), + ), + ] diff --git a/roundabout/calibrations/models.py b/roundabout/calibrations/models.py index 89a2ccb01..d07a08f0e 100644 --- a/roundabout/calibrations/models.py +++ b/roundabout/calibrations/models.py @@ -17,6 +17,11 @@ def __str__(self): def get_object_type(self): return 'coefficient_name' + class Meta: + constraints = [ + models.UniqueConstraint(fields=['calibration_name'], name='unique_name'), + ] + class CalibrationEvent(models.Model): APPROVAL_STATUS = ( diff --git a/roundabout/calibrations/views.py b/roundabout/calibrations/views.py index a19b04b22..e781885fd 100644 --- a/roundabout/calibrations/views.py +++ b/roundabout/calibrations/views.py @@ -46,9 +46,11 @@ def form_valid(self, form, coefficient_form): coefficient_form.instance = coeffname_inst coefficient_form.save() - inv_inst = coeffname_inst.part.inventory.all() - inv_id = inv_inst[0] - event_record = CalibrationEvent.objects.create(inventory=inv_id, user_draft=self.request.user) + inventory = coeffname_inst.part.inventory.all() + inv_inst = inventory[0] + event_record = CalibrationEvent.objects.create(inventory=inv_inst, user_draft=self.request.user) + + self.inv_inst_id = inv_inst.id response = HttpResponseRedirect(self.get_success_url()) @@ -74,4 +76,4 @@ def form_invalid(self, form, coefficient_form): return self.render_to_response(self.get_context_data(form=form, coefficient_form=coefficient_form, form_errors=form_errors)) def get_success_url(self): - return reverse('inventory:ajax_inventory_detail', args=(self.object.id, )) \ No newline at end of file + return reverse('inventory:ajax_inventory_detail', args=(self.inv_inst_id, )) \ No newline at end of file diff --git a/roundabout/parts/views.py b/roundabout/parts/views.py index f03fcabbf..e5db001e7 100644 --- a/roundabout/parts/views.py +++ b/roundabout/parts/views.py @@ -178,8 +178,8 @@ def form_valid(self, form, revision_form, documentation_form, calibration_form): # Save Calibration form calibration_form.instance = self.object - saved_cals = calibration_form.save() - + calibration_form.save() + # Check for any global Part Type custom fields for this Part custom_fields = self.object.part_type.custom_fields.all() @@ -201,7 +201,7 @@ def form_valid(self, form, revision_form, documentation_form, calibration_form): else: return response - def form_invalid(self, form, documentation_form, calibration_form): + def form_invalid(self, form, revision_form, documentation_form, calibration_form): form_errors = documentation_form.errors if self.request.is_ajax(): diff --git a/roundabout/templates/inventory/ajax_inventory_detail.html b/roundabout/templates/inventory/ajax_inventory_detail.html index bd569a555..979bbd7ee 100644 --- a/roundabout/templates/inventory/ajax_inventory_detail.html +++ b/roundabout/templates/inventory/ajax_inventory_detail.html @@ -487,31 +487,33 @@
{{ inventory_item.assembly_part.assembly }}
- -
Date NameValueNotesUser
{{ cal.calibration_name }}{{ caL_event.calibration_date }}{{ caL_event.coefficient_values.all }}{{ caL_event.coefficient_values.value }}{{ caL_event.coefficient_values.notes }}{{ caL_event.user_draft.username }}
- - - - - - - - - - - {% for caL_event in inventory_item.calibration_events.all %} - - - - - - - - {% endfor %} - -
DateNameValueNotesUser
{{ caL_event.calibration_date }}{{ caL_event.coefficient_values.all }}{{ caL_event.coefficient_values.value }}{{ caL_event.coefficient_values.notes }}{{ caL_event.user_draft.username }}
+ {% for cal_event in inventory_item.calibration_events.all %} +
    +
  • Calibration Date: {{ cal_event.calibration_date }}
  • +
  • User (Draft): {{ cal_event.user_draft.username }}
  • +
  • User (Approved): {{ cal_event.user_approver.username }}
  • +
  • Approved: {{ cal_event.approved }}
  • +
  • + + + + + + + + {% for coeff_val in cal_event.coefficient_values.all %} + + + + + + {% endfor %} + +
    NameValueNotes
    {{ coeff_val.coefficient_name }}{{ coeff_val.value }}{{ coeff_val.notes }}
    +
  • +
+ {% endfor %}
-
From b4b4003121daab1370848ece14f6af4244bf9b04 Mon Sep 17 00:00:00 2001 From: Mario Carloni Date: Thu, 19 Mar 2020 15:08:01 -0400 Subject: [PATCH 09/53] modified value formset to include event, added inventory pk to calibration form url route, modified coefficient history template --- roundabout/calibrations/forms.py | 4 +- roundabout/calibrations/urls.py | 2 +- roundabout/calibrations/views.py | 13 ++-- .../inventory/ajax_inventory_detail.html | 71 ++++++++++++------- 4 files changed, 54 insertions(+), 36 deletions(-) diff --git a/roundabout/calibrations/forms.py b/roundabout/calibrations/forms.py index 675a6073c..fab82a656 100644 --- a/roundabout/calibrations/forms.py +++ b/roundabout/calibrations/forms.py @@ -1,5 +1,5 @@ from django import forms -from .models import CoefficientName, CoefficientValue +from .models import CoefficientName, CoefficientValue, CalibrationEvent from django.forms.models import inlineformset_factory class CalibrationAddForm(forms.ModelForm): @@ -13,4 +13,4 @@ class Meta: 'notes': 'Notes' } -CoefficientFormset = inlineformset_factory(CoefficientName, CoefficientValue, fields=('value','notes',), extra=1, can_delete=True) \ No newline at end of file +CoefficientFormset = inlineformset_factory(CalibrationEvent, CoefficientValue, fields=('value','notes',), extra=1, can_delete=True) \ No newline at end of file diff --git a/roundabout/calibrations/urls.py b/roundabout/calibrations/urls.py index 509b7605f..c77159ae1 100644 --- a/roundabout/calibrations/urls.py +++ b/roundabout/calibrations/urls.py @@ -4,5 +4,5 @@ app_name = 'calibrations' urlpatterns = [ - path('ajax/add/', view=views.CalibrationsAddView.as_view(), name='calibrations_form') + path('ajax/add//', view=views.CalibrationsAddView.as_view(), name='calibrations_form') ] \ No newline at end of file diff --git a/roundabout/calibrations/views.py b/roundabout/calibrations/views.py index e781885fd..519bc8cf2 100644 --- a/roundabout/calibrations/views.py +++ b/roundabout/calibrations/views.py @@ -12,7 +12,7 @@ # Calibraitons landing page class CalibrationsAddView(LoginRequiredMixin, AjaxFormMixin, CreateView): - model = CoefficientName + model = CalibrationEvent form_class = CalibrationAddForm context_object_name = 'part_template' template_name='calibrations/calibrations_form.html' @@ -40,17 +40,16 @@ def post(self, request, *args, **kwargs): def form_valid(self, form, coefficient_form): self.object = form.save() - # Save CoefficientValue form using CoefficientName instance + # # Save CoefficientValue form using CoefficientName instance calibration_name = form.cleaned_data['coefficient_name'] coeffname_inst = CoefficientName.objects.get(calibration_name=calibration_name) - coefficient_form.instance = coeffname_inst - coefficient_form.save() + coefficient_form.coefficient_name = coeffname_inst inventory = coeffname_inst.part.inventory.all() inv_inst = inventory[0] event_record = CalibrationEvent.objects.create(inventory=inv_inst, user_draft=self.request.user) - - self.inv_inst_id = inv_inst.id + coefficient_form.instance = event_record + coefficient_form.save() response = HttpResponseRedirect(self.get_success_url()) @@ -76,4 +75,4 @@ def form_invalid(self, form, coefficient_form): return self.render_to_response(self.get_context_data(form=form, coefficient_form=coefficient_form, form_errors=form_errors)) def get_success_url(self): - return reverse('inventory:ajax_inventory_detail', args=(self.inv_inst_id, )) \ No newline at end of file + return reverse('inventory:ajax_inventory_detail', args=(self.kwargs['pk'], )) \ No newline at end of file diff --git a/roundabout/templates/inventory/ajax_inventory_detail.html b/roundabout/templates/inventory/ajax_inventory_detail.html index 979bbd7ee..7343f47d6 100644 --- a/roundabout/templates/inventory/ajax_inventory_detail.html +++ b/roundabout/templates/inventory/ajax_inventory_detail.html @@ -144,10 +144,10 @@ Add {{inventory_item.part.part_type}} calibration + data-node-type="detail">Add Calibration Coefficients
@@ -487,32 +487,51 @@
{{ inventory_item.assembly_part.assembly }}
- {% for cal_event in inventory_item.calibration_events.all %} -
    -
  • Calibration Date: {{ cal_event.calibration_date }}
  • -
  • User (Draft): {{ cal_event.user_draft.username }}
  • -
  • User (Approved): {{ cal_event.user_approver.username }}
  • -
  • Approved: {{ cal_event.approved }}
  • +
      + {% for event in inventory_item.calibration_events.all %}
    • - - - - - - - - {% for coeff_val in cal_event.coefficient_values.all %} - - - - - - {% endfor %} - -
      NameValueNotes
      {{ coeff_val.coefficient_name }}{{ coeff_val.value }}{{ coeff_val.notes }}
      + + +
      +
      +

      Approved: {{ event.approved }}

      +

      Approved by: {{ event.user_approver.username }}

      + +
      + {% if event.coefficient_values.all %} +
      + + + + + + + + {% for val in event.coefficient_values.all %} + + + + + + {% endfor %} + +
      NameValueNotes
      {{ val.coefficient_name }}{{ val.value }}{{ val.notes }}
      +
      + {% endif %} +
      +
    • -
    - {% endfor %} + {% endfor %} +
From eafa9e84f240ea3130f7174a0895396349d766c9 Mon Sep 17 00:00:00 2001 From: Mario Carloni Date: Mon, 23 Mar 2020 15:55:39 -0400 Subject: [PATCH 10/53] multiple coeficient values now generated per event --- roundabout/calibrations/forms.py | 20 ++++++--- .../migrations/0006_auto_20200323_1851.py | 26 ++++++++++++ .../migrations/0007_auto_20200323_1900.py | 21 ++++++++++ .../migrations/0008_auto_20200323_1940.py | 21 ++++++++++ .../migrations/0009_auto_20200323_1951.py | 21 ++++++++++ roundabout/calibrations/models.py | 6 +-- roundabout/calibrations/views.py | 17 +++----- .../calibrations/calibrations_form.html | 42 +++++++++++++++++++ .../inventory/ajax_inventory_detail.html | 3 +- 9 files changed, 156 insertions(+), 21 deletions(-) create mode 100644 roundabout/calibrations/migrations/0006_auto_20200323_1851.py create mode 100644 roundabout/calibrations/migrations/0007_auto_20200323_1900.py create mode 100644 roundabout/calibrations/migrations/0008_auto_20200323_1940.py create mode 100644 roundabout/calibrations/migrations/0009_auto_20200323_1951.py diff --git a/roundabout/calibrations/forms.py b/roundabout/calibrations/forms.py index fab82a656..d850f2578 100644 --- a/roundabout/calibrations/forms.py +++ b/roundabout/calibrations/forms.py @@ -5,12 +5,20 @@ class CalibrationAddForm(forms.ModelForm): class Meta: - model = CoefficientValue - fields = ['coefficient_name', 'value', 'notes'] + model = CalibrationEvent + fields = ['calibration_date', 'approved'] labels = { - 'coefficient_name': 'Name', - 'value': 'Value', - 'notes': 'Notes' + 'calibration_date': 'Calibration Date', + 'approved': 'Approved' + } + widgets = { + 'calibration_date': forms.DateInput(), } -CoefficientFormset = inlineformset_factory(CalibrationEvent, CoefficientValue, fields=('value','notes',), extra=1, can_delete=True) \ No newline at end of file +CoefficientFormset = inlineformset_factory( + CalibrationEvent, + CoefficientValue, + fields=('coefficient_name','value','notes',), + extra=1, + can_delete=True + ) \ No newline at end of file diff --git a/roundabout/calibrations/migrations/0006_auto_20200323_1851.py b/roundabout/calibrations/migrations/0006_auto_20200323_1851.py new file mode 100644 index 000000000..42ac59146 --- /dev/null +++ b/roundabout/calibrations/migrations/0006_auto_20200323_1851.py @@ -0,0 +1,26 @@ +# Generated by Django 2.2.9 on 2020-03-23 18:51 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('calibrations', '0005_auto_20200317_1916'), + ] + + operations = [ + migrations.RemoveConstraint( + model_name='coefficientname', + name='unique_name', + ), + migrations.AlterField( + model_name='coefficientvalue', + name='value', + field=models.CharField(max_length=20), + ), + migrations.AddConstraint( + model_name='coefficientname', + constraint=models.UniqueConstraint(fields=('part', 'calibration_name'), name='unique_name'), + ), + ] diff --git a/roundabout/calibrations/migrations/0007_auto_20200323_1900.py b/roundabout/calibrations/migrations/0007_auto_20200323_1900.py new file mode 100644 index 000000000..63bc8a38e --- /dev/null +++ b/roundabout/calibrations/migrations/0007_auto_20200323_1900.py @@ -0,0 +1,21 @@ +# Generated by Django 2.2.9 on 2020-03-23 19:00 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('calibrations', '0006_auto_20200323_1851'), + ] + + operations = [ + migrations.RemoveConstraint( + model_name='coefficientname', + name='unique_name', + ), + migrations.AddConstraint( + model_name='coefficientname', + constraint=models.UniqueConstraint(fields=('calibration_name', 'part'), name='unique_name'), + ), + ] diff --git a/roundabout/calibrations/migrations/0008_auto_20200323_1940.py b/roundabout/calibrations/migrations/0008_auto_20200323_1940.py new file mode 100644 index 000000000..b4ea60607 --- /dev/null +++ b/roundabout/calibrations/migrations/0008_auto_20200323_1940.py @@ -0,0 +1,21 @@ +# Generated by Django 2.2.9 on 2020-03-23 19:40 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('calibrations', '0007_auto_20200323_1900'), + ] + + operations = [ + migrations.RemoveConstraint( + model_name='coefficientname', + name='unique_name', + ), + migrations.AddConstraint( + model_name='coefficientname', + constraint=models.UniqueConstraint(fields=('part',), name='unique_names_per_part'), + ), + ] diff --git a/roundabout/calibrations/migrations/0009_auto_20200323_1951.py b/roundabout/calibrations/migrations/0009_auto_20200323_1951.py new file mode 100644 index 000000000..d47c954ae --- /dev/null +++ b/roundabout/calibrations/migrations/0009_auto_20200323_1951.py @@ -0,0 +1,21 @@ +# Generated by Django 2.2.9 on 2020-03-23 19:51 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('calibrations', '0008_auto_20200323_1940'), + ] + + operations = [ + migrations.RemoveConstraint( + model_name='coefficientname', + name='unique_names_per_part', + ), + migrations.AddConstraint( + model_name='coefficientname', + constraint=models.UniqueConstraint(fields=('part', 'calibration_name'), name='unique_names_per_part'), + ), + ] diff --git a/roundabout/calibrations/models.py b/roundabout/calibrations/models.py index d07a08f0e..6ca08fa04 100644 --- a/roundabout/calibrations/models.py +++ b/roundabout/calibrations/models.py @@ -19,7 +19,7 @@ def get_object_type(self): class Meta: constraints = [ - models.UniqueConstraint(fields=['calibration_name'], name='unique_name'), + models.UniqueConstraint(fields=['part','calibration_name'], name='unique_names_per_part'), ] @@ -46,8 +46,8 @@ def get_object_type(self): class CoefficientValue(models.Model): - value = models.DecimalField(max_digits=9, decimal_places=2, validators=[ - MinValueValidator(Decimal('0.00'))], null=False, blank=True, default='0.00') + # + value = models.CharField(max_length=20, unique=False, db_index=False) notes = models.TextField(blank=True) created_at = models.DateTimeField(default=timezone.now) coefficient_name = models.ForeignKey( diff --git a/roundabout/calibrations/views.py b/roundabout/calibrations/views.py index 519bc8cf2..d38ce2589 100644 --- a/roundabout/calibrations/views.py +++ b/roundabout/calibrations/views.py @@ -14,7 +14,7 @@ class CalibrationsAddView(LoginRequiredMixin, AjaxFormMixin, CreateView): model = CalibrationEvent form_class = CalibrationAddForm - context_object_name = 'part_template' + context_object_name = 'event_template' template_name='calibrations/calibrations_form.html' def get(self, request, *args, **kwargs): @@ -38,17 +38,12 @@ def post(self, request, *args, **kwargs): return self.form_invalid(form, coefficient_form) def form_valid(self, form, coefficient_form): + inv_inst = Inventory.objects.get(id=self.kwargs['pk']) + form.instance.inventory = inv_inst + form.instance.user_draft = self.request.user self.object = form.save() - - # # Save CoefficientValue form using CoefficientName instance - calibration_name = form.cleaned_data['coefficient_name'] - coeffname_inst = CoefficientName.objects.get(calibration_name=calibration_name) - coefficient_form.coefficient_name = coeffname_inst - - inventory = coeffname_inst.part.inventory.all() - inv_inst = inventory[0] - event_record = CalibrationEvent.objects.create(inventory=inv_inst, user_draft=self.request.user) - coefficient_form.instance = event_record + + coefficient_form.instance = self.object coefficient_form.save() response = HttpResponseRedirect(self.get_success_url()) diff --git a/roundabout/templates/calibrations/calibrations_form.html b/roundabout/templates/calibrations/calibrations_form.html index 042c2f410..5a454170c 100644 --- a/roundabout/templates/calibrations/calibrations_form.html +++ b/roundabout/templates/calibrations/calibrations_form.html @@ -41,6 +41,39 @@

Add Calibration

{{ coefficient_form.management_form }} {{ form|crispy }} +
+
Calibrations
+ + + + + + + {% if coefficient_form.errors %} + +
+ {% for dict in coefficient_form.errors %} + + {% for error in dict.values %} + {{ error|escape }} + {% endfor %} + + {% endfor %} +
+ + {% endif %} + + {% for coeff in coefficient_form %} + + + + + + {% endfor %} + +
Name
{% if coeff.id %}{{ coeff.DELETE }}{% endif %} {{ coeff.id }} {{ coeff.coefficient_name }}{% if coeff.id %}{{ coeff.DELETE }}{% endif %} {{ coeff.id }} {{ coeff.value }}{% if coeff.id %}{{ coeff.DELETE }}{% endif %} {{ coeff.id }} {{ coeff.notes }}
+
+
{% if form.errors %} {% for field in form %} @@ -86,6 +119,15 @@

Add Calibration

{% block javascript %} + {% endblock javascript %} \ No newline at end of file diff --git a/roundabout/templates/inventory/ajax_inventory_detail.html b/roundabout/templates/inventory/ajax_inventory_detail.html index 7343f47d6..d035336be 100644 --- a/roundabout/templates/inventory/ajax_inventory_detail.html +++ b/roundabout/templates/inventory/ajax_inventory_detail.html @@ -491,7 +491,7 @@
{{ inventory_item.assembly_part.assembly }}
{% for event in inventory_item.calibration_events.all %}
  • From f1b50a5577b65cf61e2a844e0950c05a4a6eec3a Mon Sep 17 00:00:00 2001 From: Mario Carloni Date: Tue, 7 Apr 2020 15:32:01 -0400 Subject: [PATCH 12/53] coefficient value decimals, added or updated, are now formatted with a variable number of decimal places defined by the part, including trailing zeroes, regenerated calibration migrations --- requirements/base.txt | 1 + roundabout/calibrations/forms.py | 3 +- .../calibrations/migrations/0001_initial.py | 43 +++++++--- .../0002_remove_coefficient_name.py | 17 ---- .../0003_coefficient_calibration.py | 19 ----- .../migrations/0004_auto_20200313_2300.py | 67 --------------- .../migrations/0005_auto_20200317_1916.py | 17 ---- .../migrations/0006_auto_20200323_1851.py | 26 ------ .../migrations/0007_auto_20200323_1900.py | 21 ----- .../migrations/0008_auto_20200323_1940.py | 21 ----- .../migrations/0009_auto_20200323_1951.py | 21 ----- .../migrations/0010_auto_20200330_1937.py | 19 ----- .../migrations/0011_auto_20200401_1846.py | 19 ----- .../migrations/0012_auto_20200401_1853.py | 18 ---- .../migrations/0013_auto_20200401_1930.py | 17 ---- .../migrations/0014_auto_20200403_1650.py | 18 ---- .../migrations/0015_auto_20200403_1714.py | 21 ----- .../migrations/0016_auto_20200406_1347.py | 18 ---- roundabout/calibrations/models.py | 12 +-- roundabout/calibrations/urls.py | 3 +- roundabout/calibrations/views.py | 84 +++++++++++++++++-- roundabout/parts/views.py | 22 ++++- .../inventory/ajax_inventory_detail.html | 19 ++++- .../templates/parts/ajax_part_detail.html | 36 ++++---- .../templates/parts/ajax_part_form.html | 22 ++++- 25 files changed, 195 insertions(+), 389 deletions(-) delete mode 100644 roundabout/calibrations/migrations/0002_remove_coefficient_name.py delete mode 100644 roundabout/calibrations/migrations/0003_coefficient_calibration.py delete mode 100644 roundabout/calibrations/migrations/0004_auto_20200313_2300.py delete mode 100644 roundabout/calibrations/migrations/0005_auto_20200317_1916.py delete mode 100644 roundabout/calibrations/migrations/0006_auto_20200323_1851.py delete mode 100644 roundabout/calibrations/migrations/0007_auto_20200323_1900.py delete mode 100644 roundabout/calibrations/migrations/0008_auto_20200323_1940.py delete mode 100644 roundabout/calibrations/migrations/0009_auto_20200323_1951.py delete mode 100644 roundabout/calibrations/migrations/0010_auto_20200330_1937.py delete mode 100644 roundabout/calibrations/migrations/0011_auto_20200401_1846.py delete mode 100644 roundabout/calibrations/migrations/0012_auto_20200401_1853.py delete mode 100644 roundabout/calibrations/migrations/0013_auto_20200401_1930.py delete mode 100644 roundabout/calibrations/migrations/0014_auto_20200403_1650.py delete mode 100644 roundabout/calibrations/migrations/0015_auto_20200403_1714.py delete mode 100644 roundabout/calibrations/migrations/0016_auto_20200406_1347.py diff --git a/requirements/base.txt b/requirements/base.txt index 8adb8db47..929726386 100644 --- a/requirements/base.txt +++ b/requirements/base.txt @@ -23,3 +23,4 @@ django-mptt==0.9.1 django-summernote==0.8.11.4 whitenoise==4.1.2 django-bootstrap-datepicker-plus==3.0.5 +sigfig==1.1.8 #https://pypi.org/project/sigfig/ \ No newline at end of file diff --git a/roundabout/calibrations/forms.py b/roundabout/calibrations/forms.py index f935ace12..53c802aeb 100644 --- a/roundabout/calibrations/forms.py +++ b/roundabout/calibrations/forms.py @@ -27,8 +27,7 @@ def __init__(self, *args, **kwargs): super(CoefficientValueForm, self).__init__(*args, **kwargs) if hasattr(self,'inv_id'): inv_inst = Inventory.objects.get(id=self.inv_id) - part_inst = Part.objects.get(id=inv_inst.part.id) - self.fields['coefficient_name'].queryset = CoefficientName.objects.filter(part=part_inst) + self.fields['coefficient_name'].queryset = CoefficientName.objects.filter(part=inv_inst.part) CoefficientFormset = inlineformset_factory( diff --git a/roundabout/calibrations/migrations/0001_initial.py b/roundabout/calibrations/migrations/0001_initial.py index e338a8756..648259789 100644 --- a/roundabout/calibrations/migrations/0001_initial.py +++ b/roundabout/calibrations/migrations/0001_initial.py @@ -1,7 +1,6 @@ -# Generated by Django 2.2.9 on 2020-02-27 17:05 +# Generated by Django 2.2.9 on 2020-04-07 19:24 -from decimal import Decimal -import django.core.validators +from django.conf import settings from django.db import migrations, models import django.db.models.deletion import django.utils.timezone @@ -13,27 +12,47 @@ class Migration(migrations.Migration): dependencies = [ ('inventory', '0003_auto_20191023_1347'), - ('parts', '0004_auto_20191023_1735'), + ('parts', '0006_auto_20200406_1347'), + migrations.swappable_dependency(settings.AUTH_USER_MODEL), ] operations = [ migrations.CreateModel( - name='Coefficient', + name='CalibrationEvent', fields=[ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('name', models.CharField(db_index=True, max_length=255)), - ('value', models.DecimalField(blank=True, decimal_places=2, default='0.00', max_digits=9, validators=[django.core.validators.MinValueValidator(Decimal('0.00'))])), - ('notes', models.TextField(blank=True)), ('created_at', models.DateTimeField(default=django.utils.timezone.now)), - ('inventory', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='coefficient', to='inventory.Inventory')), + ('calibration_date', models.DateTimeField(default=django.utils.timezone.now)), + ('approved', models.BooleanField(choices=[(True, 'Approved'), (False, 'Draft')], default=False)), + ('deployment', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='calibration_events', to='inventory.Deployment')), + ('inventory', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='calibration_events', to='inventory.Inventory')), + ('user_approver', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='calibration_events_approver', to=settings.AUTH_USER_MODEL)), + ('user_draft', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='calibration_events_drafter', to=settings.AUTH_USER_MODEL)), + ], + options={ + 'ordering': ['-calibration_date'], + }, + ), + migrations.CreateModel( + name='CoefficientName', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('calibration_name', models.CharField(db_index=True, max_length=255)), + ('part', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='coefficient_names', to='parts.Part')), ], + options={ + 'ordering': ['calibration_name'], + }, ), migrations.CreateModel( - name='Calibration', + name='CoefficientValue', fields=[ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('name', models.CharField(db_index=True, max_length=255)), - ('part', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='calibration', to='parts.Part')), + ('value', models.CharField(max_length=20)), + ('notes', models.TextField(blank=True)), + ('created_at', models.DateTimeField(default=django.utils.timezone.now)), + ('calibration_event', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='coefficient_values', to='calibrations.CalibrationEvent')), + ('coefficient_name', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='coefficient_values', to='calibrations.CoefficientName')), ], ), ] diff --git a/roundabout/calibrations/migrations/0002_remove_coefficient_name.py b/roundabout/calibrations/migrations/0002_remove_coefficient_name.py deleted file mode 100644 index c3924d9bd..000000000 --- a/roundabout/calibrations/migrations/0002_remove_coefficient_name.py +++ /dev/null @@ -1,17 +0,0 @@ -# Generated by Django 2.2.9 on 2020-03-05 14:11 - -from django.db import migrations - - -class Migration(migrations.Migration): - - dependencies = [ - ('calibrations', '0001_initial'), - ] - - operations = [ - migrations.RemoveField( - model_name='coefficient', - name='name', - ), - ] diff --git a/roundabout/calibrations/migrations/0003_coefficient_calibration.py b/roundabout/calibrations/migrations/0003_coefficient_calibration.py deleted file mode 100644 index 097755517..000000000 --- a/roundabout/calibrations/migrations/0003_coefficient_calibration.py +++ /dev/null @@ -1,19 +0,0 @@ -# Generated by Django 2.2.9 on 2020-03-09 15:56 - -from django.db import migrations, models -import django.db.models.deletion - - -class Migration(migrations.Migration): - - dependencies = [ - ('calibrations', '0002_remove_coefficient_name'), - ] - - operations = [ - migrations.AddField( - model_name='coefficient', - name='calibration', - field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='coefficient', to='calibrations.Calibration'), - ), - ] diff --git a/roundabout/calibrations/migrations/0004_auto_20200313_2300.py b/roundabout/calibrations/migrations/0004_auto_20200313_2300.py deleted file mode 100644 index 28ffe1242..000000000 --- a/roundabout/calibrations/migrations/0004_auto_20200313_2300.py +++ /dev/null @@ -1,67 +0,0 @@ -# Generated by Django 2.2.9 on 2020-03-13 23:00 - -from decimal import Decimal -from django.conf import settings -import django.core.validators -from django.db import migrations, models -import django.db.models.deletion -import django.utils.timezone - - -class Migration(migrations.Migration): - - dependencies = [ - ('parts', '0004_auto_20191023_1735'), - migrations.swappable_dependency(settings.AUTH_USER_MODEL), - ('inventory', '0003_auto_20191023_1347'), - ('calibrations', '0003_coefficient_calibration'), - ] - - operations = [ - migrations.CreateModel( - name='CalibrationEvent', - fields=[ - ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('created_at', models.DateTimeField(default=django.utils.timezone.now)), - ('calibration_date', models.DateTimeField(default=django.utils.timezone.now)), - ('approved', models.BooleanField(choices=[(True, 'Approved'), (False, 'Draft')], default=False)), - ('deployment', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='calibration_events', to='inventory.Deployment')), - ('inventory', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='calibration_events', to='inventory.Inventory')), - ('user_approver', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='calibration_events_approver', to=settings.AUTH_USER_MODEL)), - ('user_draft', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='calibration_events_drafter', to=settings.AUTH_USER_MODEL)), - ], - ), - migrations.CreateModel( - name='CoefficientName', - fields=[ - ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('calibration_name', models.CharField(db_index=True, max_length=255)), - ('part', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='coefficient_names', to='parts.Part')), - ], - ), - migrations.CreateModel( - name='CoefficientValue', - fields=[ - ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('value', models.DecimalField(blank=True, decimal_places=2, default='0.00', max_digits=9, validators=[django.core.validators.MinValueValidator(Decimal('0.00'))])), - ('notes', models.TextField(blank=True)), - ('created_at', models.DateTimeField(default=django.utils.timezone.now)), - ('calibration_event', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='coefficient_values', to='calibrations.CalibrationEvent')), - ('coefficient_name', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='coefficient_values', to='calibrations.CoefficientName')), - ], - ), - migrations.RemoveField( - model_name='coefficient', - name='calibration', - ), - migrations.RemoveField( - model_name='coefficient', - name='inventory', - ), - migrations.DeleteModel( - name='Calibration', - ), - migrations.DeleteModel( - name='Coefficient', - ), - ] diff --git a/roundabout/calibrations/migrations/0005_auto_20200317_1916.py b/roundabout/calibrations/migrations/0005_auto_20200317_1916.py deleted file mode 100644 index e978acf99..000000000 --- a/roundabout/calibrations/migrations/0005_auto_20200317_1916.py +++ /dev/null @@ -1,17 +0,0 @@ -# Generated by Django 2.2.9 on 2020-03-17 19:16 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('calibrations', '0004_auto_20200313_2300'), - ] - - operations = [ - migrations.AddConstraint( - model_name='coefficientname', - constraint=models.UniqueConstraint(fields=('calibration_name',), name='unique_name'), - ), - ] diff --git a/roundabout/calibrations/migrations/0006_auto_20200323_1851.py b/roundabout/calibrations/migrations/0006_auto_20200323_1851.py deleted file mode 100644 index 42ac59146..000000000 --- a/roundabout/calibrations/migrations/0006_auto_20200323_1851.py +++ /dev/null @@ -1,26 +0,0 @@ -# Generated by Django 2.2.9 on 2020-03-23 18:51 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('calibrations', '0005_auto_20200317_1916'), - ] - - operations = [ - migrations.RemoveConstraint( - model_name='coefficientname', - name='unique_name', - ), - migrations.AlterField( - model_name='coefficientvalue', - name='value', - field=models.CharField(max_length=20), - ), - migrations.AddConstraint( - model_name='coefficientname', - constraint=models.UniqueConstraint(fields=('part', 'calibration_name'), name='unique_name'), - ), - ] diff --git a/roundabout/calibrations/migrations/0007_auto_20200323_1900.py b/roundabout/calibrations/migrations/0007_auto_20200323_1900.py deleted file mode 100644 index 63bc8a38e..000000000 --- a/roundabout/calibrations/migrations/0007_auto_20200323_1900.py +++ /dev/null @@ -1,21 +0,0 @@ -# Generated by Django 2.2.9 on 2020-03-23 19:00 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('calibrations', '0006_auto_20200323_1851'), - ] - - operations = [ - migrations.RemoveConstraint( - model_name='coefficientname', - name='unique_name', - ), - migrations.AddConstraint( - model_name='coefficientname', - constraint=models.UniqueConstraint(fields=('calibration_name', 'part'), name='unique_name'), - ), - ] diff --git a/roundabout/calibrations/migrations/0008_auto_20200323_1940.py b/roundabout/calibrations/migrations/0008_auto_20200323_1940.py deleted file mode 100644 index b4ea60607..000000000 --- a/roundabout/calibrations/migrations/0008_auto_20200323_1940.py +++ /dev/null @@ -1,21 +0,0 @@ -# Generated by Django 2.2.9 on 2020-03-23 19:40 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('calibrations', '0007_auto_20200323_1900'), - ] - - operations = [ - migrations.RemoveConstraint( - model_name='coefficientname', - name='unique_name', - ), - migrations.AddConstraint( - model_name='coefficientname', - constraint=models.UniqueConstraint(fields=('part',), name='unique_names_per_part'), - ), - ] diff --git a/roundabout/calibrations/migrations/0009_auto_20200323_1951.py b/roundabout/calibrations/migrations/0009_auto_20200323_1951.py deleted file mode 100644 index d47c954ae..000000000 --- a/roundabout/calibrations/migrations/0009_auto_20200323_1951.py +++ /dev/null @@ -1,21 +0,0 @@ -# Generated by Django 2.2.9 on 2020-03-23 19:51 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('calibrations', '0008_auto_20200323_1940'), - ] - - operations = [ - migrations.RemoveConstraint( - model_name='coefficientname', - name='unique_names_per_part', - ), - migrations.AddConstraint( - model_name='coefficientname', - constraint=models.UniqueConstraint(fields=('part', 'calibration_name'), name='unique_names_per_part'), - ), - ] diff --git a/roundabout/calibrations/migrations/0010_auto_20200330_1937.py b/roundabout/calibrations/migrations/0010_auto_20200330_1937.py deleted file mode 100644 index 6a6d43040..000000000 --- a/roundabout/calibrations/migrations/0010_auto_20200330_1937.py +++ /dev/null @@ -1,19 +0,0 @@ -# Generated by Django 2.2.9 on 2020-03-30 19:37 - -import django.core.validators -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('calibrations', '0009_auto_20200323_1951'), - ] - - operations = [ - migrations.AlterField( - model_name='coefficientvalue', - name='value', - field=models.CharField(max_length=20, validators=[django.core.validators.DecimalValidator(12, 12), django.core.validators.MaxValueValidator(1), django.core.validators.MinValueValidator(0)]), - ), - ] diff --git a/roundabout/calibrations/migrations/0011_auto_20200401_1846.py b/roundabout/calibrations/migrations/0011_auto_20200401_1846.py deleted file mode 100644 index 1d4873a40..000000000 --- a/roundabout/calibrations/migrations/0011_auto_20200401_1846.py +++ /dev/null @@ -1,19 +0,0 @@ -# Generated by Django 2.2.9 on 2020-04-01 18:46 - -import django.core.validators -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('calibrations', '0010_auto_20200330_1937'), - ] - - operations = [ - migrations.AlterField( - model_name='coefficientvalue', - name='value', - field=models.CharField(max_length=20, validators=[django.core.validators.RegexValidator(code='numbers_only', message='Numbers only', regex='^([\\s\\d]+)$')]), - ), - ] diff --git a/roundabout/calibrations/migrations/0012_auto_20200401_1853.py b/roundabout/calibrations/migrations/0012_auto_20200401_1853.py deleted file mode 100644 index dafe37618..000000000 --- a/roundabout/calibrations/migrations/0012_auto_20200401_1853.py +++ /dev/null @@ -1,18 +0,0 @@ -# Generated by Django 2.2.9 on 2020-04-01 18:53 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('calibrations', '0011_auto_20200401_1846'), - ] - - operations = [ - migrations.AlterField( - model_name='coefficientvalue', - name='value', - field=models.CharField(max_length=20), - ), - ] diff --git a/roundabout/calibrations/migrations/0013_auto_20200401_1930.py b/roundabout/calibrations/migrations/0013_auto_20200401_1930.py deleted file mode 100644 index 615b81ce6..000000000 --- a/roundabout/calibrations/migrations/0013_auto_20200401_1930.py +++ /dev/null @@ -1,17 +0,0 @@ -# Generated by Django 2.2.9 on 2020-04-01 19:30 - -from django.db import migrations - - -class Migration(migrations.Migration): - - dependencies = [ - ('calibrations', '0012_auto_20200401_1853'), - ] - - operations = [ - migrations.AlterModelOptions( - name='calibrationevent', - options={'ordering': ['-calibration_date']}, - ), - ] diff --git a/roundabout/calibrations/migrations/0014_auto_20200403_1650.py b/roundabout/calibrations/migrations/0014_auto_20200403_1650.py deleted file mode 100644 index c1dd35a96..000000000 --- a/roundabout/calibrations/migrations/0014_auto_20200403_1650.py +++ /dev/null @@ -1,18 +0,0 @@ -# Generated by Django 2.2.9 on 2020-04-03 16:50 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('calibrations', '0013_auto_20200401_1930'), - ] - - operations = [ - migrations.AlterField( - model_name='coefficientname', - name='calibration_name', - field=models.CharField(db_index=True, max_length=255, unique=True), - ), - ] diff --git a/roundabout/calibrations/migrations/0015_auto_20200403_1714.py b/roundabout/calibrations/migrations/0015_auto_20200403_1714.py deleted file mode 100644 index e46d89038..000000000 --- a/roundabout/calibrations/migrations/0015_auto_20200403_1714.py +++ /dev/null @@ -1,21 +0,0 @@ -# Generated by Django 2.2.9 on 2020-04-03 17:14 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('calibrations', '0014_auto_20200403_1650'), - ] - - operations = [ - migrations.RemoveConstraint( - model_name='coefficientname', - name='unique_names_per_part', - ), - migrations.AddConstraint( - model_name='coefficientname', - constraint=models.UniqueConstraint(fields=('calibration_name', 'part'), name='unique_names_per_part'), - ), - ] diff --git a/roundabout/calibrations/migrations/0016_auto_20200406_1347.py b/roundabout/calibrations/migrations/0016_auto_20200406_1347.py deleted file mode 100644 index 2f2963f92..000000000 --- a/roundabout/calibrations/migrations/0016_auto_20200406_1347.py +++ /dev/null @@ -1,18 +0,0 @@ -# Generated by Django 2.2.9 on 2020-04-06 13:47 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('calibrations', '0015_auto_20200403_1714'), - ] - - operations = [ - migrations.AlterField( - model_name='coefficientname', - name='calibration_name', - field=models.CharField(db_index=True, max_length=255), - ), - ] diff --git a/roundabout/calibrations/models.py b/roundabout/calibrations/models.py index 12d0869c3..7c15618a6 100644 --- a/roundabout/calibrations/models.py +++ b/roundabout/calibrations/models.py @@ -10,17 +10,12 @@ class CoefficientName(models.Model): calibration_name = models.CharField(max_length=255, unique=False, db_index=True) part = models.ForeignKey(Part, related_name='coefficient_names', on_delete=models.CASCADE, null=True) - def __str__(self): return self.calibration_name - def get_object_type(self): return 'coefficient_name' - class Meta: - constraints = [ - models.UniqueConstraint(fields=['calibration_name','part'], name='unique_names_per_part'), - ] + ordering = ['calibration_name'] class CalibrationEvent(models.Model): @@ -35,13 +30,10 @@ class CalibrationEvent(models.Model): inventory = models.ForeignKey(Inventory, related_name='calibration_events', on_delete=models.CASCADE, null=False) deployment = models.ForeignKey(Deployment, related_name='calibration_events', on_delete=models.CASCADE, null=True) approved = models.BooleanField(choices=APPROVAL_STATUS, blank=False, default=False) - def __str__(self): return self.calibration_date - def get_object_type(self): return 'calibration_event' - class Meta: ordering = ['-calibration_date'] @@ -52,9 +44,7 @@ class CoefficientValue(models.Model): created_at = models.DateTimeField(default=timezone.now) coefficient_name = models.ForeignKey(CoefficientName, related_name='coefficient_values', on_delete=models.CASCADE, null=True) calibration_event = models.ForeignKey(CalibrationEvent, related_name='coefficient_values', on_delete=models.CASCADE, null=True) - def __str__(self): return self.notes - def get_object_type(self): return 'coefficient_value' diff --git a/roundabout/calibrations/urls.py b/roundabout/calibrations/urls.py index c77159ae1..5eea3025d 100644 --- a/roundabout/calibrations/urls.py +++ b/roundabout/calibrations/urls.py @@ -4,5 +4,6 @@ app_name = 'calibrations' urlpatterns = [ - path('ajax/add//', view=views.CalibrationsAddView.as_view(), name='calibrations_form') + path('ajax/add//', view=views.CalibrationsAddView.as_view(), name='calibrations_form'), + path('ajax/edit//', view=views.CalibrationsUpdateView.as_view(), name='event_form') ] \ No newline at end of file diff --git a/roundabout/calibrations/views.py b/roundabout/calibrations/views.py index 04f40083f..9f0b92235 100644 --- a/roundabout/calibrations/views.py +++ b/roundabout/calibrations/views.py @@ -1,14 +1,16 @@ from django.shortcuts import render from django.http import HttpResponse, HttpResponseRedirect, JsonResponse -from django.contrib.auth.mixins import LoginRequiredMixin -from django.views.generic import CreateView +from django.contrib.auth.mixins import LoginRequiredMixin, PermissionRequiredMixin +from django.views.generic import CreateView, UpdateView from .models import CoefficientName, CalibrationEvent -from .forms import CalibrationAddForm, CoefficientFormset +from .forms import CalibrationAddForm, CoefficientFormset, CoefficientValueForm from common.util.mixins import AjaxFormMixin from django.urls import reverse, reverse_lazy from roundabout.parts.models import Part from roundabout.users.models import User from roundabout.inventory.models import Inventory +from django.core import validators +from sigfig import round # Calibrations landing page class CalibrationsAddView(LoginRequiredMixin, AjaxFormMixin, CreateView): @@ -38,14 +40,84 @@ def form_valid(self, form, coefficient_form): form.instance.inventory = inv_inst if form.cleaned_data['approved']: form.instance.user_approver = self.request.user + form.instance.user_draft = self.request.user + self.object = form.save() + coefficient_form.instance = self.object + for form in coefficient_form: + try: + form_coeff_val = form.cleaned_data['value'] + part_dec_places = inv_inst.part.cal_dec_places + sigfig_formatted_value = round(form_coeff_val, decimals = part_dec_places) + except: + raise validators.ValidationError( + ('Invalid value') + ) + form.instance.value = sigfig_formatted_value + coefficient_form.save() + response = HttpResponseRedirect(self.get_success_url()) + if self.request.is_ajax(): + data = { + 'message': "Successfully submitted form data.", + 'object_id': self.object.id, + 'object_type': self.object.get_object_type(), + 'detail_path': self.get_success_url(), + } + return JsonResponse(data) else: - form.instance.user_draft = self.request.user + return response + + def form_invalid(self, form, coefficient_form): + form_errors = coefficient_form.errors + if self.request.is_ajax(): + data = form.errors + return JsonResponse(data, status=400) + else: + return self.render_to_response(self.get_context_data(form=form, coefficient_form=coefficient_form, form_errors=form_errors)) + + def get_success_url(self): + return reverse('inventory:ajax_inventory_detail', args=(self.kwargs['pk'], )) + + +class CalibrationsUpdateView(LoginRequiredMixin, PermissionRequiredMixin, AjaxFormMixin, UpdateView): + model = CalibrationEvent + form_class = CalibrationAddForm + context_object_name = 'event_template' + template_name='calibrations/calibrations_form.html' + permission_required = 'calibrations.add_calibration' + redirect_field_name = 'home' + + def get(self, request, *args, **kwargs): + self.object = self.get_object() + form_class = self.get_form_class() + form = self.get_form(form_class) + coefficient_form = CoefficientFormset(instance=self.object, form_kwargs={'inv_id': self.object.inventory.id}) + return self.render_to_response(self.get_context_data(form=form, coefficient_form=coefficient_form)) + + def post(self, request, *args, **kwargs): + self.object = self.get_object() + form_class = self.get_form_class() + form = self.get_form(form_class) + coefficient_form = CoefficientFormset(self.request.POST, instance=self.object) + if (form.is_valid() and coefficient_form.is_valid()): + return self.form_valid(form, coefficient_form) + return self.form_invalid(form, coefficient_form) + + def form_valid(self, form, coefficient_form): + inv_inst = Inventory.objects.get(id=self.object.inventory.id) + form.instance.inventory = inv_inst + if form.cleaned_data['approved']: + form.instance.user_approver = self.request.user + form.instance.user_draft = self.request.user self.object = form.save() coefficient_form.instance = self.object + for form in coefficient_form: + form_coeff_val = form.cleaned_data.get('value') + part_dec_places = inv_inst.part.cal_dec_places + sigfig_formatted_value = round(form_coeff_val, decimals = part_dec_places) + form.instance.value = sigfig_formatted_value coefficient_form.save() response = HttpResponseRedirect(self.get_success_url()) if self.request.is_ajax(): - print(form.cleaned_data) data = { 'message': "Successfully submitted form data.", 'object_id': self.object.id, @@ -65,4 +137,4 @@ def form_invalid(self, form, coefficient_form): return self.render_to_response(self.get_context_data(form=form, coefficient_form=coefficient_form, form_errors=form_errors)) def get_success_url(self): - return reverse('inventory:ajax_inventory_detail', args=(self.kwargs['pk'], )) \ No newline at end of file + return reverse('inventory:ajax_inventory_detail', args=(self.object.inventory.id, )) \ No newline at end of file diff --git a/roundabout/parts/views.py b/roundabout/parts/views.py index e5db001e7..2400646b6 100644 --- a/roundabout/parts/views.py +++ b/roundabout/parts/views.py @@ -222,8 +222,28 @@ class PartsAjaxUpdateView(LoginRequiredMixin, PermissionRequiredMixin, AjaxFormM permission_required = 'parts.add_part' redirect_field_name = 'home' - def form_valid(self, form): + def get(self, request, *args, **kwargs): + self.object = self.get_object() + form_class = self.get_form_class() + form = self.get_form(form_class) + calibration_form = CalibrationFormset(instance=self.object) + return self.render_to_response(self.get_context_data(form=form, calibration_form=calibration_form)) + + def post(self, request, *args, **kwargs): + self.object = self.get_object() + form_class = self.get_form_class() + form = self.get_form(form_class) + calibration_form = CalibrationFormset( + self.request.POST, instance=self.object) + + if (form.is_valid() and calibration_form.is_valid()): + return self.form_valid(form, calibration_form) + return self.form_invalid(form, calibration_form) + + def form_valid(self, form, calibration_form): self.object = form.save() + calibration_form.instance = self.object + calibration_form.save() response = HttpResponseRedirect(self.get_success_url()) if self.request.is_ajax(): diff --git a/roundabout/templates/inventory/ajax_inventory_detail.html b/roundabout/templates/inventory/ajax_inventory_detail.html index d035336be..7a2921281 100644 --- a/roundabout/templates/inventory/ajax_inventory_detail.html +++ b/roundabout/templates/inventory/ajax_inventory_detail.html @@ -497,11 +497,19 @@
    {{ inventory_item.assembly_part.assembly }}
    Expand/Collapse Calibration {{ event.calibration_date }} +

    Approved: {{ event.approved }}

    Approved by: {{ event.user_approver.username }}

    -

    Drafted by: {{ event.user_draft.username }}

    +

    Last Updated by: {{ event.user_draft.username }}

    @@ -618,12 +630,10 @@
    {{ inventory_item.assembly_part.assembly }}
    {% regroup value_set.coefficient_values.all by row as row_sets %} {% for row in row_sets %} - {% for val in value_set.coefficient_values.all %} - {% if val.row == row.grouper %} - -
    {{ val }}
    - - {% endif %} + {% for val in row.list %} + +
    {{ val }}
    + {% endfor %} {% endfor %} @@ -677,7 +687,7 @@
    {{ inventory_item.assembly_part.assembly }}
    role="button" data-detail-url="{% url 'configs_constants:config_event_value_update' event.id %}" data-node-id="{{ event.id }}" - data-node-type="detail"> + data-node-type="{{ event.get_object_type }}"> Edit Values
    @@ -826,6 +836,7 @@
    {{ inventory_item.assembly_part.assembly }}
    let inv_part_type = '{{ inventory_item.part.part_type }}'; let deployment = '{{ inventory_item.build.current_deployment }}'; let part_has_cals = '{{ inventory_item.part.coefficient_names.exists }}'; + let user_id = '{{ user.id }}' if (inv_part_type == 'Instrument' && part_has_cals == 'True') { $('#add_coefficient_action').show(); $('#calibration-template-tab').show().css('display', ''); @@ -858,15 +869,24 @@
    {{ inventory_item.assembly_part.assembly }}
    }) } - // Remove User as Event Reviewer + // Swap Reviewers as Approvers $('#calibration-template').on('click', 'a[id^=expander]', function() { let url = $(this).attr('data-reviewer-url'); - let badge = $(this).next('span[id=review-badge]'); - if (badge.length) { + let review_badge = $(this).parent().find('#review-badge'); + let progress_badge = $(this).parent().find('#progress-badge'); + let reviewer = $(this).parent().find('#reviewer-' + user_id) + let approver_list = $(this).parent().find('#approvers'); + if (review_badge.length) { $.ajax({ url: url, success: function (data) { - badge.remove(); + if (data.approved) { + review_badge.after('Approved') + progress_badge.hide() + } + approver_list.append("{{ user.username }}") + review_badge.remove(); + reviewer.hide() } }); } From bfa44fcc8db2e153bb87d949581798f660ef373d Mon Sep 17 00:00:00 2001 From: Mario Carloni Date: Mon, 29 Jun 2020 14:39:17 -0400 Subject: [PATCH 46/53] moved approver logic to button within Event --- .../inventory/ajax_inventory_detail.html | 51 ++++++++++--------- 1 file changed, 28 insertions(+), 23 deletions(-) diff --git a/roundabout/templates/inventory/ajax_inventory_detail.html b/roundabout/templates/inventory/ajax_inventory_detail.html index df0e9d65e..8983a97e0 100644 --- a/roundabout/templates/inventory/ajax_inventory_detail.html +++ b/roundabout/templates/inventory/ajax_inventory_detail.html @@ -511,8 +511,6 @@
    {{ inventory_item.assembly_part.assembly }}
    href="#event-{{ event.id }}" aria-expanded="false" aria-controls="event-{{ event.id }}" - id='expander-date-{{event.id}}' - data-reviewer-url="{% url 'calibrations:event_review_delete' event.id user.id %}" > {{ event.calibration_date|date:"n/j/y" }} @@ -522,8 +520,6 @@
    {{ inventory_item.assembly_part.assembly }}
    aria-controls="event-{{ event.id }}" aria-expanded="false" role="button" - id='expander-{{event.id}}' - data-reviewer-url="{% url 'calibrations:event_review_delete' event.id user.id %}" > Expand/Collapse Calibration {{ event.calibration_date }} @@ -548,6 +544,11 @@
    {{ inventory_item.assembly_part.assembly }}

    + {% if user in event.user_draft.all %} + + {% endif %}