mirror of
https://github.com/inventree/InvenTree
synced 2024-08-30 18:33:04 +00:00
Merge remote-tracking branch 'inventree/master'
This commit is contained in:
commit
6da0106aa2
@ -26,12 +26,12 @@ InvenTree | Company - {{ company.name }}
|
|||||||
<p>{{ company.description }}</p>
|
<p>{{ company.description }}</p>
|
||||||
<div class='btn-group'>
|
<div class='btn-group'>
|
||||||
{% if company.is_supplier %}
|
{% if company.is_supplier %}
|
||||||
<button type='button' class='btn btn-default btn-glyph' id='company-order' title='Create purchase order'>
|
<button type='button' class='btn btn-default btn-glyph' id='company-order-2' title='Create purchase order'>
|
||||||
<span class='glyphicon glyphicon-shopping-cart'/>
|
<span class='glyphicon glyphicon-shopping-cart'/>
|
||||||
</button>
|
</button>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<button type='button' class='btn btn-default btn-glyph' id='company-edit' title='Edit company information'>
|
<button type='button' class='btn btn-default btn-glyph' id='company-edit' title='Edit company information'>
|
||||||
<span class='glyphicon glyphicon-cog'/>
|
<span class='glyphicon glyphicon-edit'/>
|
||||||
</button>
|
</button>
|
||||||
<button type='button' class='btn btn-default btn-glyph' id='company-delete' title='Delete company'>
|
<button type='button' class='btn btn-default btn-glyph' id='company-delete' title='Delete company'>
|
||||||
<span class='glyphicon glyphicon-trash'/>
|
<span class='glyphicon glyphicon-trash'/>
|
||||||
@ -98,6 +98,17 @@ InvenTree | Company - {{ company.name }}
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
$("#company-order-2").click(function() {
|
||||||
|
launchModalForm("{% url 'purchase-order-create' %}",
|
||||||
|
{
|
||||||
|
data: {
|
||||||
|
supplier: {{ company.id }},
|
||||||
|
},
|
||||||
|
follow: true,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
$('#company-delete').click(function() {
|
$('#company-delete').click(function() {
|
||||||
launchModalForm(
|
launchModalForm(
|
||||||
"{% url 'company-delete' company.id %}",
|
"{% url 'company-delete' company.id %}",
|
||||||
|
@ -119,6 +119,7 @@ class PartList(generics.ListCreateAPIView):
|
|||||||
'image',
|
'image',
|
||||||
'name',
|
'name',
|
||||||
'IPN',
|
'IPN',
|
||||||
|
'revision',
|
||||||
'description',
|
'description',
|
||||||
'keywords',
|
'keywords',
|
||||||
'is_template',
|
'is_template',
|
||||||
|
@ -93,6 +93,7 @@ class EditPartForm(HelperForm):
|
|||||||
'name',
|
'name',
|
||||||
'IPN',
|
'IPN',
|
||||||
'description',
|
'description',
|
||||||
|
'revision',
|
||||||
'keywords',
|
'keywords',
|
||||||
'variant_of',
|
'variant_of',
|
||||||
'is_template',
|
'is_template',
|
||||||
|
19
InvenTree/part/migrations/0010_auto_20190620_2135.py
Normal file
19
InvenTree/part/migrations/0010_auto_20190620_2135.py
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
# Generated by Django 2.2.2 on 2019-06-20 11:35
|
||||||
|
|
||||||
|
import InvenTree.validators
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('part', '0009_part_virtual'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='part',
|
||||||
|
name='name',
|
||||||
|
field=models.CharField(help_text='Part name', max_length=100, validators=[InvenTree.validators.validate_part_name]),
|
||||||
|
),
|
||||||
|
]
|
18
InvenTree/part/migrations/0011_part_revision.py
Normal file
18
InvenTree/part/migrations/0011_part_revision.py
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
# Generated by Django 2.2.2 on 2019-06-20 11:37
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('part', '0010_auto_20190620_2135'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='part',
|
||||||
|
name='revision',
|
||||||
|
field=models.CharField(blank=True, help_text='Part revision or version number', max_length=100),
|
||||||
|
),
|
||||||
|
]
|
@ -203,6 +203,7 @@ class Part(models.Model):
|
|||||||
description: Longer form description of the part
|
description: Longer form description of the part
|
||||||
keywords: Optional keywords for improving part search results
|
keywords: Optional keywords for improving part search results
|
||||||
IPN: Internal part number (optional)
|
IPN: Internal part number (optional)
|
||||||
|
revision: Part revision
|
||||||
is_template: If True, this part is a 'template' part and cannot be instantiated as a StockItem
|
is_template: If True, this part is a 'template' part and cannot be instantiated as a StockItem
|
||||||
URL: Link to an external page with more information about this part (e.g. internal Wiki)
|
URL: Link to an external page with more information about this part (e.g. internal Wiki)
|
||||||
image: Image of this part
|
image: Image of this part
|
||||||
@ -245,6 +246,9 @@ class Part(models.Model):
|
|||||||
|
|
||||||
elements.append(self.name)
|
elements.append(self.name)
|
||||||
|
|
||||||
|
if self.revision:
|
||||||
|
elements.append(self.revision)
|
||||||
|
|
||||||
return ' | '.join(elements)
|
return ' | '.join(elements)
|
||||||
|
|
||||||
def get_absolute_url(self):
|
def get_absolute_url(self):
|
||||||
@ -260,13 +264,32 @@ class Part(models.Model):
|
|||||||
return static('/img/blank_image.png')
|
return static('/img/blank_image.png')
|
||||||
|
|
||||||
def validate_unique(self, exclude=None):
|
def validate_unique(self, exclude=None):
|
||||||
|
""" Validate that a part is 'unique'.
|
||||||
|
Uniqueness is checked across the following (case insensitive) fields:
|
||||||
|
|
||||||
|
* Name
|
||||||
|
* IPN
|
||||||
|
* Revision
|
||||||
|
|
||||||
|
e.g. there can exist multiple parts with the same name, but only if
|
||||||
|
they have a different revision or internal part number.
|
||||||
|
|
||||||
|
"""
|
||||||
super().validate_unique(exclude)
|
super().validate_unique(exclude)
|
||||||
|
|
||||||
# Part name uniqueness should be case insensitive
|
# Part name uniqueness should be case insensitive
|
||||||
try:
|
try:
|
||||||
if Part.objects.filter(name__iexact=self.name).exclude(id=self.id).exists():
|
parts = Part.objects.exclude(id=self.id).filter(
|
||||||
|
name__iexact=self.name,
|
||||||
|
IPN__iexact=self.IPN,
|
||||||
|
revision__iexact=self.revision)
|
||||||
|
|
||||||
|
if parts.exists():
|
||||||
|
msg = _("Part must be unique for name, IPN and revision")
|
||||||
raise ValidationError({
|
raise ValidationError({
|
||||||
"name": _("A part with this name already exists")
|
"name": msg,
|
||||||
|
"IPN": msg,
|
||||||
|
"revision": msg,
|
||||||
})
|
})
|
||||||
except Part.DoesNotExist:
|
except Part.DoesNotExist:
|
||||||
pass
|
pass
|
||||||
@ -280,8 +303,8 @@ class Part(models.Model):
|
|||||||
'variant_of': _("Part cannot be a variant of another part if it is already a template"),
|
'variant_of': _("Part cannot be a variant of another part if it is already a template"),
|
||||||
})
|
})
|
||||||
|
|
||||||
name = models.CharField(max_length=100, blank=False, unique=True,
|
name = models.CharField(max_length=100, blank=False,
|
||||||
help_text='Part name (must be unique)',
|
help_text='Part name',
|
||||||
validators=[validators.validate_part_name]
|
validators=[validators.validate_part_name]
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -307,6 +330,8 @@ class Part(models.Model):
|
|||||||
|
|
||||||
IPN = models.CharField(max_length=100, blank=True, help_text='Internal Part Number')
|
IPN = models.CharField(max_length=100, blank=True, help_text='Internal Part Number')
|
||||||
|
|
||||||
|
revision = models.CharField(max_length=100, blank=True, help_text='Part revision or version number')
|
||||||
|
|
||||||
URL = models.URLField(blank=True, help_text='Link to extenal URL')
|
URL = models.URLField(blank=True, help_text='Link to extenal URL')
|
||||||
|
|
||||||
image = models.ImageField(upload_to=rename_part_image, max_length=255, null=True, blank=True)
|
image = models.ImageField(upload_to=rename_part_image, max_length=255, null=True, blank=True)
|
||||||
@ -785,6 +810,14 @@ class Part(models.Model):
|
|||||||
item.pk = None
|
item.pk = None
|
||||||
item.save()
|
item.save()
|
||||||
|
|
||||||
|
# Copy the fields that aren't available in the duplicate form
|
||||||
|
self.salable = other.salable
|
||||||
|
self.assembly = other.assembly
|
||||||
|
self.component = other.component
|
||||||
|
self.purchaseable = other.purchaseable
|
||||||
|
self.trackable = other.trackable
|
||||||
|
self.virtual = other.virtual
|
||||||
|
|
||||||
self.save()
|
self.save()
|
||||||
|
|
||||||
def export_bom(self, **kwargs):
|
def export_bom(self, **kwargs):
|
||||||
|
@ -22,7 +22,7 @@
|
|||||||
</button>
|
</button>
|
||||||
{% if category %}
|
{% if category %}
|
||||||
<button class='btn btn-default btn-glyph' id='cat-edit' title='Edit part category'>
|
<button class='btn btn-default btn-glyph' id='cat-edit' title='Edit part category'>
|
||||||
<span class='glyphicon glyphicon-cog'/>
|
<span class='glyphicon glyphicon-edit'/>
|
||||||
</button>
|
</button>
|
||||||
<button class='btn btn-default btn-glyph' id='cat-delete' title='Delete part category'>
|
<button class='btn btn-default btn-glyph' id='cat-delete' title='Delete part category'>
|
||||||
<span class='glyphicon glyphicon-trash'/>
|
<span class='glyphicon glyphicon-trash'/>
|
||||||
|
@ -13,7 +13,7 @@
|
|||||||
<table class='table table-striped'>
|
<table class='table table-striped'>
|
||||||
<tr>
|
<tr>
|
||||||
<td><b>Part name</b></td>
|
<td><b>Part name</b></td>
|
||||||
<td>{{ part.full_name }}</td>
|
<td>{{ part.name }}</td>
|
||||||
</tr>
|
</tr>
|
||||||
{% if part.IPN %}
|
{% if part.IPN %}
|
||||||
<tr>
|
<tr>
|
||||||
@ -21,6 +21,12 @@
|
|||||||
<td>{{ part.IPN }}</td>
|
<td>{{ part.IPN }}</td>
|
||||||
</tr>
|
</tr>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
{% if part.revision %}
|
||||||
|
<tr>
|
||||||
|
<td><b>Revision</b></td>
|
||||||
|
<td>{{ part.revision }}</td>
|
||||||
|
</tr>
|
||||||
|
{% endif %}
|
||||||
<tr>
|
<tr>
|
||||||
<td><b>Description</b></td>
|
<td><b>Description</b></td>
|
||||||
<td>{{ part.description }}</td>
|
<td>{{ part.description }}</td>
|
||||||
|
@ -189,8 +189,8 @@ function loadBomTable(table, options) {
|
|||||||
if (options.editable) {
|
if (options.editable) {
|
||||||
cols.push({
|
cols.push({
|
||||||
formatter: function(value, row, index, field) {
|
formatter: function(value, row, index, field) {
|
||||||
var bEdit = "<button title='Edit BOM Item' class='btn btn-default btn-glyph' type='button' url='/part/bom/" + row.pk + "/edit'><span class='glyphicon glyphicon-edit'/></button>";
|
var bEdit = "<button title='Edit BOM Item' class='bom-edit-button btn btn-default btn-glyph' type='button' url='/part/bom/" + row.pk + "/edit'><span class='glyphicon glyphicon-edit'/></button>";
|
||||||
var bDelt = "<button title='Delete BOM Item' class='btn btn-default btn-glyph' type='button' url='/part/bom/" + row.pk + "/delete'><span class='glyphicon glyphicon-trash'/></button>";
|
var bDelt = "<button title='Delete BOM Item' class='bom-delete-button btn btn-default btn-glyph' type='button' url='/part/bom/" + row.pk + "/delete'><span class='glyphicon glyphicon-trash'/></button>";
|
||||||
|
|
||||||
return "<div class='btn-group'>" + bEdit + bDelt + "</div>";
|
return "<div class='btn-group'>" + bEdit + bDelt + "</div>";
|
||||||
}
|
}
|
||||||
|
@ -126,6 +126,11 @@ function loadPartTable(table, url, options={}) {
|
|||||||
|
|
||||||
name += value;
|
name += value;
|
||||||
|
|
||||||
|
if (row.revision) {
|
||||||
|
name += ' | ';
|
||||||
|
name += row.revision;
|
||||||
|
}
|
||||||
|
|
||||||
if (row.is_template) {
|
if (row.is_template) {
|
||||||
name = '<i>' + name + '</i>';
|
name = '<i>' + name + '</i>';
|
||||||
}
|
}
|
||||||
|
@ -27,7 +27,7 @@
|
|||||||
</button>
|
</button>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<button type='button' class='btn btn-default btn-glyph' id='stock-edit' title='Edit stock item'>
|
<button type='button' class='btn btn-default btn-glyph' id='stock-edit' title='Edit stock item'>
|
||||||
<span class='glyphicon glyphicon-cog'/>
|
<span class='glyphicon glyphicon-edit'/>
|
||||||
</button>
|
</button>
|
||||||
<button type='button' class='btn btn-default btn-glyph' id='stock-delete' title='Edit stock item'>
|
<button type='button' class='btn btn-default btn-glyph' id='stock-delete' title='Edit stock item'>
|
||||||
<span class='glyphicon glyphicon-trash'/>
|
<span class='glyphicon glyphicon-trash'/>
|
||||||
|
@ -22,7 +22,7 @@
|
|||||||
<span class='glyphicon glyphicon-ok-circle'/>
|
<span class='glyphicon glyphicon-ok-circle'/>
|
||||||
</button>
|
</button>
|
||||||
<button class='btn btn-default btn-glyph' id='location-edit' title='Edit stock location'>
|
<button class='btn btn-default btn-glyph' id='location-edit' title='Edit stock location'>
|
||||||
<span class='glyphicon glyphicon-cog'/>
|
<span class='glyphicon glyphicon-edit'/>
|
||||||
</button>
|
</button>
|
||||||
<button class='btn btn-default btn-glyph' id='location-delete' title='Delete stock location'>
|
<button class='btn btn-default btn-glyph' id='location-delete' title='Delete stock location'>
|
||||||
<span class='glyphicon glyphicon-trash'/>
|
<span class='glyphicon glyphicon-trash'/>
|
||||||
|
Loading…
Reference in New Issue
Block a user