From ea688ac7e0ec4bdba52127c5609074c805c8a1ca Mon Sep 17 00:00:00 2001 From: agp8x Date: Sat, 28 Oct 2017 23:12:47 +0200 Subject: [PATCH] add view to enter whole sketches at once --- .gitignore | 3 + partdoc/partdoc/settings.py | 1 + partdoc/partdoc/urls.py | 6 +- partdoc/parts/admin.py | 37 ++++++++++++- partdoc/parts/models.py | 48 +++++++++++----- partdoc/parts/static/parts/add_sketch.js | 8 +++ partdoc/parts/templates/parts/add.html | 30 ++++++++++ partdoc/parts/urls.py | 2 + partdoc/parts/views.py | 70 +++++++++++++++++++++++- 9 files changed, 185 insertions(+), 20 deletions(-) create mode 100644 partdoc/parts/static/parts/add_sketch.js create mode 100644 partdoc/parts/templates/parts/add.html diff --git a/.gitignore b/.gitignore index 2060e8c..dd137c1 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,8 @@ /venv /pgdata +sketches/ db.sqlite3 __pycache__/ +*/*/migrations/*.py +!migrations/__init__.py diff --git a/partdoc/partdoc/settings.py b/partdoc/partdoc/settings.py index 9704fcf..31adb7d 100644 --- a/partdoc/partdoc/settings.py +++ b/partdoc/partdoc/settings.py @@ -124,3 +124,4 @@ USE_TZ = True # https://docs.djangoproject.com/en/1.11/howto/static-files/ STATIC_URL = '/static/' +STATIC_ROOT = 'static/' diff --git a/partdoc/partdoc/urls.py b/partdoc/partdoc/urls.py index 699d678..e592657 100644 --- a/partdoc/partdoc/urls.py +++ b/partdoc/partdoc/urls.py @@ -13,10 +13,12 @@ Including another URLconf 1. Import the include() function: from django.conf.urls import url, include 2. Add a URL to urlpatterns: url(r'^blog/', include('blog.urls')) """ +from django.conf import settings from django.conf.urls import url, include from django.contrib import admin +from django.conf.urls.static import static urlpatterns = [ url(r'^parts/', include('parts.urls'), name="parts"), - url(r'^admin/', admin.site.urls), -] + url(r'^admin/', admin.site.urls), +] + static(settings.STATIC_URL, document_root=settings.STATIC_ROOT) diff --git a/partdoc/parts/admin.py b/partdoc/parts/admin.py index c5473ff..10c9137 100644 --- a/partdoc/parts/admin.py +++ b/partdoc/parts/admin.py @@ -2,4 +2,39 @@ from django.contrib import admin from .models import Brand, Product, Version, Sketch, Part, Usage, BrandedPart, ProductUsage -admin.site.register([Brand, Product, Version, Sketch, Part, Usage, BrandedPart, ProductUsage]) +#admin.site.register([Brand, Product, Version, Sketch, Part, Usage, BrandedPart, ProductUsage]) +admin.site.register([Brand, Product, Version, Sketch, ProductUsage]) + +class BrandedPartInline(admin.StackedInline): + model = BrandedPart + extra = 1 + +class PartAdmin(admin.ModelAdmin): + inlines = [BrandedPartInline] + +class PartInline(admin.StackedInline): + model = Part + +#class ProductUsageInline(admin.TabularInline): +# model = ProductUsage +# extra = 1 + +class ProductUsageInline(admin.StackedInline): + model = ProductUsage + extra = 1 + +class UsageAdmin(admin.ModelAdmin): + model = Usage + extra = 1 + inlines = [ProductUsageInline] + +class UsageInline(admin.StackedInline): + model = Usage + extra = 1 + +class BrandedPartAdmin(admin.ModelAdmin): + inlines = [UsageInline] + +admin.site.register(Usage, UsageAdmin) +admin.site.register(Part, PartAdmin) +admin.site.register(BrandedPart, BrandedPartAdmin) \ No newline at end of file diff --git a/partdoc/parts/models.py b/partdoc/parts/models.py index 7fee156..6839430 100644 --- a/partdoc/parts/models.py +++ b/partdoc/parts/models.py @@ -1,13 +1,21 @@ from django.db import models -class Brand(models.Model): +class PartModel(models. Model): + creation = models.DateTimeField(auto_now_add=True) + modification = models.DateTimeField(auto_now=True) + + class Meta: + abstract = True + + +class Brand(PartModel): name = models.CharField(max_length=256) def __str__(self): return self.name -class Product(models.Model): +class Product(PartModel): name = models.CharField(max_length=256) brand = models.ForeignKey(Brand) @@ -15,12 +23,13 @@ class Product(models.Model): return self.name + " (" + self.brand.name + ")" -class Sketch(models.Model): +class Sketch(PartModel): class Meta: verbose_name_plural = "sketches" name = models.CharField(max_length=256) brand = models.ForeignKey(Brand, blank=True, null=True) product = models.ForeignKey(Product, blank=True, null=True) + image = models.FileField(upload_to="sketches/", blank=True, null=True) def __str__(self): return "Sketch: " + self.name + " (" + str(self.brand) + ")" @@ -35,30 +44,37 @@ class Sketch(models.Model): return self.usage_set.values('productusage__product__brand').distinct() -class Version(models.Model): +class Version(PartModel): product = models.ForeignKey(Product) name = models.CharField(max_length=256) + replaced_by = models.ForeignKey('self', blank=True, null=True, related_name='replaces') + start = models.DateField(blank=True, null=True) + end = models.DateField(blank=True, null=True) + + additional_sketch = models.ManyToManyField(Sketch, blank=True, related_name='added') + unused_sketch = models.ManyToManyField(Sketch, blank=True, related_name='replaced') def __str__(self): return "Version: " + self.name + " (" + str(self.product) + ")" -class Part(models.Model): +class Part(PartModel): name = models.CharField(max_length=256) def __str__(self): return self.name -class BrandedPart(models.Model): - part = models.ForeignKey(Part) +class BrandedPart(PartModel): + part = models.ForeignKey(Part, null=True) brand = models.ForeignKey(Brand) - number = models.CharField(max_length=32, unique=True) + number = models.CharField(max_length=32, unique=True, blank=True, null=True) def __str__(self): - return self.number +": "+ self.part.name + " @ " + self.brand.name + na = self.part.name if self.part else "--(part)--" + return str(self.number) +": "+ na + " @ " + self.brand.name -class Usage(models.Model): +class Usage(PartModel): part = models.ForeignKey(BrandedPart) sketch = models.ForeignKey(Sketch) sketch_number = models.CharField(max_length=32) @@ -66,13 +82,15 @@ class Usage(models.Model): #quantity = models.ManyToManyField(ProductUsage) def __str__(self): - return self.sketch_number +"; " + self.part.number +"; "+ self.part.part.name + "; " + str(self.sketch) + no = self.part.number if self.part else "--(part.number)--" + na = self.part.part.name if self.part.part else "--(part.part.name)--" + return self.sketch_number +"; " + str(no) +"; "+ na + "; " + str(self.sketch) -class ProductUsage(models.Model): - usage = models.ForeignKey(Usage) +class ProductUsage(PartModel): + usage = models.ForeignKey(Usage, null=True) product = models.ForeignKey(Product) - quantity = models.IntegerField() + quantity = models.IntegerField(null=True) on_demand = models.BooleanField(default=False) obsolete = models.BooleanField(default=False) used_until = models.ForeignKey(Version, null=True, blank=True, related_name='introduces') @@ -83,4 +101,4 @@ class ProductUsage(models.Model): internal_note = models.CharField(max_length=2, blank=True) def __str__(self): - return "ProductUsage: " + self.product.name + " @ " + str(self.quantity) + "; "+ self.usage.part.number \ No newline at end of file + return "ProductUsage: " + self.product.name + " @ " + str(self.quantity) + "; "+ str(self.usage.part.number) \ No newline at end of file diff --git a/partdoc/parts/static/parts/add_sketch.js b/partdoc/parts/static/parts/add_sketch.js new file mode 100644 index 0000000..3919ff5 --- /dev/null +++ b/partdoc/parts/static/parts/add_sketch.js @@ -0,0 +1,8 @@ +function addRow(){ + var src = document.getElementById("template"); + var clone = src.cloneNode(true); + clone.id = ""; + clone.className ="entry"; + clone.children[0].children[0].value = document.getElementsByClassName("entry").length + 1 + document.getElementById("table").appendChild(clone); +} \ No newline at end of file diff --git a/partdoc/parts/templates/parts/add.html b/partdoc/parts/templates/parts/add.html new file mode 100644 index 0000000..dca2146 --- /dev/null +++ b/partdoc/parts/templates/parts/add.html @@ -0,0 +1,30 @@ +{% load static %} + +

add sketch to {{product.name}}

+ + + +
+{% csrf_token %} +

+ + + + +
Bild-Nr.Teil-Nr.InternTeilbezeichnungAnzahlverbaut bisverbaut abersetzt durchAnmerkungen
+ +
+ + + + + + + + + + + + +
+ \ No newline at end of file diff --git a/partdoc/parts/urls.py b/partdoc/parts/urls.py index b6b6e0c..0c432b0 100644 --- a/partdoc/parts/urls.py +++ b/partdoc/parts/urls.py @@ -2,8 +2,10 @@ from django.conf.urls import url from . import views +app_name = "parts" urlpatterns = [ url(r'^$', views.index, name="index"), url(r'^product/(?P[0-9]+)/$', views.product, name="detail"), url(r'^sketch/(?P[0-9]+)/$', views.sketch, name="sketch"), + url(r'^add/(?P[0-9]+)/sketch', views.sketch_add, name="new_sketch"), ] \ No newline at end of file diff --git a/partdoc/parts/views.py b/partdoc/parts/views.py index 69e9d1e..e3f26db 100644 --- a/partdoc/parts/views.py +++ b/partdoc/parts/views.py @@ -1,7 +1,12 @@ -from django.shortcuts import render +from django.shortcuts import get_object_or_404, render +from django.http import HttpResponseRedirect +from django.urls import reverse +from django.db import transaction from .models import * +ADD_SKETCH_REQUIRES = ['sketch_name','sketch_number',''] + def index(request): product_list = Product.objects.all() context = {'product_list': product_list} @@ -16,4 +21,65 @@ def product(request, product_id): def sketch(request, sketch_id): sketch = Sketch.objects.get(id=sketch_id) context = {'sketch': sketch} - return render(request, 'parts/sketch.html', context) \ No newline at end of file + return render(request, 'parts/sketch.html', context) + +@transaction.atomic +def sketch_add(request, product_id): + product = get_object_or_404(Product, pk=product_id) + print(request.POST) + if not "sketch_name" in request.POST: + return render(request, 'parts/add.html', {'product': product}) + sketch = Sketch() + sketch.name = request.POST["sketch_name"] + sketch.product = product + sketch.brand = product.brand + sketch.save() + for i in range(len(request.POST.getlist('name'))): + print(i) + usage = Usage() + print("ASDF2") + usage.sketch = sketch + usage.sketch_number = request.POST.getlist('fignumber')[i] + if "ähn" in usage.sketch_number or "vgl" in usage.sketch_number: + usage.exact_sketch = False + + print("ASDF3") + branded_part, created = BrandedPart.objects.get_or_create(brand=product.brand, number=request.POST.getlist('partnumber')[i]) + print("ASDF", branded_part, created) + if created: + try: + part, _ = Part.objects.get_or_create(name=request.POST.getlist('name')[i]) + except Part.MultipleObjectsReturned: + part = Part.objects.filter(name=request.POST.getlist('name')[i]).first() + branded_part.part = part + branded_part.brand = product.brand + branded_part.save() + print("ASDF") + usage.part = branded_part + usage.save() + + prod = ProductUsage() + prod.usage = usage + prod.product = product + prod.quantity = int(request.POST.getlist('quantity')[i]) + last_version = request.POST.getlist('last_version')[i] + if len(last_version): + version, _ = Version.objects.get_or_create(product=product, name=last_version) + prod.used_until = version + first_version = request.POST.getlist('first_version')[i] + if len(first_version): + version, _ = Version.objects.get_or_create(product=product, name=first_version) + prod.used_since = version + replaced = request.POST.getlist('replaced_by')[i] + if len(replaced): + replacement, _ = ProductUsage.objects.get_or_create(product=product, usage__part__number=replaced) + prod.replaced_by = replacement + note = request.POST.getlist('notes')[i] + if len(note): + prod.note = note + internal = request.POST.getlist('internal')[i] + if len(internal): + prod.internal = internal + prod.save() + + return HttpResponseRedirect(reverse('parts:sketch', args=(sketch.id,))) \ No newline at end of file