Ability to delete part

- Provides confirmation form
- Shows the flow-on effects (model.CASCADE) from deleting this part
- Bootstrap makes it prettyful
This commit is contained in:
Oliver 2018-04-15 08:45:50 +10:00
parent 21e3f415c6
commit 54e78bf468
7 changed files with 109 additions and 9 deletions

View File

@ -0,0 +1,24 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.11 on 2018-04-14 22:38
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('part', '0012_auto_20180414_1032'),
]
operations = [
migrations.AlterField(
model_name='part',
name='name',
field=models.CharField(max_length=100, unique=True),
),
migrations.AlterUniqueTogether(
name='part',
unique_together=set([]),
),
]

View File

@ -77,12 +77,14 @@ class Part(models.Model):
return '/part/{id}/'.format(id=self.id) return '/part/{id}/'.format(id=self.id)
# Short name of the part # Short name of the part
name = models.CharField(max_length=100) name = models.CharField(max_length=100, unique=True)
# Longer description of the part (optional) # Longer description of the part (optional)
description = models.CharField(max_length=250, blank=True) description = models.CharField(max_length=250, blank=True)
# Internal Part Number (optional) # Internal Part Number (optional)
# Potentially multiple parts map to the same internal IPN (variants?)
# So this does not have to be unique
IPN = models.CharField(max_length=100, blank=True) IPN = models.CharField(max_length=100, blank=True)
# Provide a URL for an external link # Provide a URL for an external link
@ -117,7 +119,7 @@ class Part(models.Model):
class Meta: class Meta:
verbose_name = "Part" verbose_name = "Part"
verbose_name_plural = "Parts" verbose_name_plural = "Parts"
unique_together = (("name", "category"),) #unique_together = (("name", "category"),)
@property @property
def stock(self): def stock(self):

View File

@ -9,7 +9,8 @@
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"> <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<!-- Bootstrap CSS --> <!-- Bootstrap CSS -->
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.0/css/bootstrap.min.css" integrity="sha384-9gVQ4dYFwwWSjIDZnLEWnxCjeSWFphJiwGPXr1jddIhOegiu1FwO5qRGvFXOdJZ4" crossorigin="anonymous">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
<!-- Local stylesheet --> <!-- Local stylesheet -->
<link rel="stylesheet" href="{% static 'css/inventree.css' %}"> <link rel="stylesheet" href="{% static 'css/inventree.css' %}">
@ -31,7 +32,7 @@ InvenTree
{% include "navbar.html" %} {% include "navbar.html" %}
<div class="inventree-content"> <div class="container-fluid inventree-content">
{% block content %} {% block content %}
<!-- Each view fills in here.. --> <!-- Each view fills in here.. -->
{% endblock %} {% endblock %}

View File

@ -1,2 +1,51 @@
{% extends 'part/part_base.html' %} {% extends 'part/part_base.html' %}
{% block details %}
<div class="panel panel-danger">
<div class="panel-heading">Are you sure you want to delete part '{{ part.name }}'?</div>
<div class="panel-body">
<p><b>Deleting this part is a permanent action and cannot be undone.</b></p>
{% if part.usedInCount > 0 %}
<p>This part is used in BOMs for {{ part.usedInCount }} other parts. If you delete this part, the BOMs for the following parts will be updated:
<ul class="list-group">
{% for child in part.used_in.all %}
<li class='list-group-item'>{{ child.part.name }} - {{ child.part.description }}</li>
{% endfor %}
</p>
{% endif %}
{% if part.locations.all|length > 0 %}
<p>There are {{ part.locations.all|length }} stock entries defined for this part. If you delete this part, the following stock entries will also be deleted:
<ul class='list-group'>
{% for stock in part.locations.all %}
<li class='list-group-item'>{{ stock.location.name }} - {{ stock.quantity }} items</li>
{% endfor %}
</ul>
</p>
{% endif %}
{% if part.supplier_parts.all|length > 0 %}
<p>There are {{ part.supplier_parts.all|length }} suppliers defined for this part. If you delete this part, the following supplier parts will also be deleted.
<ul class='list-group'>
{% for spart in part.supplier_parts.all %}
<li class='list-group-item'>{{ spart.supplier.name }} - {{ spart.SKU }}</li>
{% endfor %}
</ul>
</p>
{% endif %}
{% if part.serials.all|length > 0 %}
<p>There are {{ part.serials.all|length }} unique parts tracked for '{{ part.name }}'. Deleting this part will permanently remove this tracking information.</p>
{% endif %}
<form action="" method="post">{% csrf_token %}
<input type="submit" name='confirm' value="Confirm" />
<input type="submit" name="cancel" value="Cancel" />
</form>
</div>
</div>
{% endblock %}

View File

@ -40,7 +40,7 @@ bom_api_urls = [
part_detail_urls = [ part_detail_urls = [
url(r'^edit/?', views.PartEdit.as_view(), name='part-edit'), url(r'^edit/?', views.PartEdit.as_view(), name='part-edit'),
url(r'^delete/?', views.delete, name='part-delete'), url(r'^delete/?', views.PartDelete.as_view(), name='part-delete'),
url(r'^track/?', views.PartDetail.as_view(template_name='part/track.html'), name='part-track'), url(r'^track/?', views.PartDetail.as_view(template_name='part/track.html'), name='part-track'),
url(r'^bom/?', views.PartDetail.as_view(template_name='part/bom.html'), name='part-bom'), url(r'^bom/?', views.PartDetail.as_view(template_name='part/bom.html'), name='part-bom'),
url(r'^stock/?', views.PartDetail.as_view(template_name='part/stock.html'), name='part-stock'), url(r'^stock/?', views.PartDetail.as_view(template_name='part/stock.html'), name='part-stock'),

View File

@ -6,7 +6,7 @@ from django.http import HttpResponseRedirect
from django.urls import reverse from django.urls import reverse
from django.views.generic import DetailView, ListView from django.views.generic import DetailView, ListView
from django.views.generic.edit import UpdateView from django.views.generic.edit import UpdateView, DeleteView, CreateView
from .forms import EditPartForm from .forms import EditPartForm
@ -46,5 +46,15 @@ class PartEdit(UpdateView):
template_name = 'part/edit.html' template_name = 'part/edit.html'
def delete(request, pk): class PartDelete(DeleteView):
return HttpResponseRedirect('/part/{pk}/'.format(pk=pk)) model = Part
template_name = 'part/delete.html'
success_url = '/part/'
def post(self, request, *args, **kwargs):
if 'confirm' in request.POST:
return super(PartDelete, self).post(request, *args, **kwargs)
else:
return HttpResponseRedirect(self.get_object().get_absolute_url())

View File

@ -117,4 +117,18 @@ table tr:nth-child(odd) {
border: 1px solid #ddd; border: 1px solid #ddd;
border-bottom-color: transparent; border-bottom-color: transparent;
cursor: default; cursor: default;
} }
.panel-danger {
border-radius: 5px;
padding: 5px;
margin: 5px;
border-color: #ebccd1;
}
.panel-danger>.panel-heading {
background-color: #ebccd1;
border-top-left-radius: 3px;
border-top-right-radius: 3px;
}