mirror of
https://github.com/inventree/InvenTree.git
synced 2025-06-18 21:15:41 +00:00
Finally got migrations working together
This commit is contained in:
@ -2,6 +2,7 @@ from django.contrib import admin
|
||||
from import_export.admin import ImportExportModelAdmin
|
||||
|
||||
from .models import PartCategory, Part
|
||||
from .models import SupplierPart
|
||||
from .models import BomItem
|
||||
from .models import PartAttachment
|
||||
|
||||
@ -20,8 +21,11 @@ class BomItemAdmin(ImportExportModelAdmin):
|
||||
list_display = ('part', 'sub_part', 'quantity')
|
||||
|
||||
|
||||
class PartAttachmentAdmin(admin.ModelAdmin):
|
||||
list_display = ('part', 'attachment')
|
||||
#class PartAttachmentAdmin(admin.ModelAdmin):
|
||||
# list_display = ('part', 'attachment')
|
||||
|
||||
class SupplierPartAdmin(ImportExportModelAdmin):
|
||||
list_display = ('part', 'supplier', 'SKU')
|
||||
|
||||
|
||||
"""
|
||||
@ -36,8 +40,4 @@ class ParameterAdmin(admin.ModelAdmin):
|
||||
admin.site.register(Part, PartAdmin)
|
||||
admin.site.register(PartCategory, PartCategoryAdmin)
|
||||
admin.site.register(BomItem, BomItemAdmin)
|
||||
admin.site.register(PartAttachment, PartAttachmentAdmin)
|
||||
|
||||
# admin.site.register(PartParameter, ParameterAdmin)
|
||||
# admin.site.register(PartParameterTemplate, ParameterTemplateAdmin)
|
||||
# admin.site.register(CategoryParameterLink)
|
||||
admin.site.register(SupplierPart, SupplierPartAdmin)
|
||||
|
@ -3,6 +3,7 @@ from crispy_forms.helper import FormHelper
|
||||
from crispy_forms.layout import Submit
|
||||
|
||||
from .models import Part, PartCategory, BomItem
|
||||
from .models import SupplierPart
|
||||
|
||||
|
||||
class EditPartForm(forms.ModelForm):
|
||||
@ -73,3 +74,27 @@ class EditBomItemForm(forms.ModelForm):
|
||||
'sub_part',
|
||||
'quantity'
|
||||
]
|
||||
|
||||
|
||||
class EditSupplierPartForm(forms.ModelForm):
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(EditSupplierPartForm, self).__init__(*args, **kwargs)
|
||||
self.helper = FormHelper()
|
||||
|
||||
self.helper.form_id = 'id-edit-part-form'
|
||||
self.helper.form_class = 'blueForms'
|
||||
self.helper.form_method = 'post'
|
||||
|
||||
self.helper.add_input(Submit('submit', 'Submit'))
|
||||
|
||||
class Meta:
|
||||
model = SupplierPart
|
||||
fields = [
|
||||
'supplier',
|
||||
'SKU',
|
||||
'part',
|
||||
'description',
|
||||
'URL',
|
||||
'manufacturer',
|
||||
'MPN',
|
||||
]
|
||||
|
@ -1,10 +1,11 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Generated by Django 1.11 on 2018-04-12 05:02
|
||||
# Generated by Django 1.11.12 on 2018-04-22 11:53
|
||||
from __future__ import unicode_literals
|
||||
|
||||
import django.core.validators
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
import part.models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
@ -12,42 +13,57 @@ class Migration(migrations.Migration):
|
||||
initial = True
|
||||
|
||||
dependencies = [
|
||||
('company', '0001_initial'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='CategoryParameterLink',
|
||||
name='BomItem',
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('quantity', models.PositiveIntegerField(default=1, validators=[django.core.validators.MinValueValidator(0)])),
|
||||
],
|
||||
options={
|
||||
'verbose_name': 'Category Parameter',
|
||||
'verbose_name_plural': 'Category Parameters',
|
||||
'verbose_name': 'BOM Item',
|
||||
},
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='Part',
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('name', models.CharField(max_length=100)),
|
||||
('description', models.CharField(blank=True, max_length=250)),
|
||||
('IPN', models.CharField(blank=True, max_length=100)),
|
||||
('minimum_stock', models.PositiveIntegerField(default=0, validators=[django.core.validators.MinValueValidator(0)])),
|
||||
('name', models.CharField(help_text='Part name (must be unique)', max_length=100, unique=True)),
|
||||
('description', models.CharField(help_text='Part description', max_length=250)),
|
||||
('IPN', models.CharField(blank=True, help_text='Internal Part Number', max_length=100)),
|
||||
('URL', models.URLField(blank=True, help_text='Link to extenal URL')),
|
||||
('image', models.ImageField(blank=True, max_length=255, null=True, upload_to=part.models.rename_part_image)),
|
||||
('minimum_stock', models.PositiveIntegerField(default=0, help_text='Minimum allowed stock level', validators=[django.core.validators.MinValueValidator(0)])),
|
||||
('units', models.CharField(blank=True, default='pcs', max_length=20)),
|
||||
('trackable', models.BooleanField(default=False)),
|
||||
('buildable', models.BooleanField(default=False, help_text='Can this part be built from other parts?')),
|
||||
('trackable', models.BooleanField(default=False, help_text='Does this part have tracking for unique items?')),
|
||||
('purchaseable', models.BooleanField(default=True, help_text='Can this part be purchased from external suppliers?')),
|
||||
('salable', models.BooleanField(default=False, help_text='Can this part be sold to customers?')),
|
||||
('notes', models.TextField(blank=True)),
|
||||
],
|
||||
options={
|
||||
'verbose_name': 'Part',
|
||||
'verbose_name_plural': 'Parts',
|
||||
},
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='PartAttachment',
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('attachment', models.FileField(blank=True, null=True, upload_to=part.models.attach_file)),
|
||||
('part', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='attachments', to='part.Part')),
|
||||
],
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='PartCategory',
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('name', models.CharField(max_length=100)),
|
||||
('description', models.CharField(blank=True, max_length=250)),
|
||||
('parent', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='children', to='part.PartCategory')),
|
||||
('name', models.CharField(max_length=100, unique=True)),
|
||||
('description', models.CharField(max_length=250)),
|
||||
('parent', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.DO_NOTHING, related_name='children', to='part.PartCategory')),
|
||||
],
|
||||
options={
|
||||
'verbose_name': 'Part Category',
|
||||
@ -55,62 +71,63 @@ class Migration(migrations.Migration):
|
||||
},
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='PartParameter',
|
||||
name='SupplierPart',
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('value', models.CharField(blank=True, max_length=50)),
|
||||
('min_value', models.CharField(blank=True, max_length=50)),
|
||||
('max_value', models.CharField(blank=True, max_length=50)),
|
||||
('part', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='parameters', to='part.Part')),
|
||||
('SKU', models.CharField(help_text='Supplier stock keeping unit', max_length=100)),
|
||||
('manufacturer', models.CharField(blank=True, help_text='Manufacturer', max_length=100)),
|
||||
('MPN', models.CharField(blank=True, help_text='Manufacturer part number', max_length=100)),
|
||||
('URL', models.URLField(blank=True)),
|
||||
('description', models.CharField(blank=True, max_length=250)),
|
||||
('single_price', models.DecimalField(decimal_places=3, default=0, max_digits=10)),
|
||||
('base_cost', models.DecimalField(decimal_places=3, default=0, max_digits=10)),
|
||||
('packaging', models.CharField(blank=True, max_length=50)),
|
||||
('multiple', models.PositiveIntegerField(default=1, validators=[django.core.validators.MinValueValidator(0)])),
|
||||
('minimum', models.PositiveIntegerField(default=1, validators=[django.core.validators.MinValueValidator(0)])),
|
||||
('lead_time', models.DurationField(blank=True, null=True)),
|
||||
('part', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='supplier_parts', to='part.Part')),
|
||||
('supplier', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='parts', to='company.Company')),
|
||||
],
|
||||
options={
|
||||
'verbose_name': 'Part Parameter',
|
||||
'verbose_name_plural': 'Part Parameters',
|
||||
},
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='PartParameterTemplate',
|
||||
name='SupplierPriceBreak',
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('name', models.CharField(max_length=20, unique=True)),
|
||||
('units', models.CharField(blank=True, max_length=10)),
|
||||
('format', models.PositiveIntegerField(choices=[(10, 'Numeric'), (20, 'Text'), (30, 'Bool')], default=10, validators=[django.core.validators.MinValueValidator(0)])),
|
||||
('quantity', models.PositiveIntegerField(validators=[django.core.validators.MinValueValidator(0)])),
|
||||
('cost', models.DecimalField(decimal_places=3, max_digits=10)),
|
||||
('part', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='price_breaks', to='part.SupplierPart')),
|
||||
],
|
||||
options={
|
||||
'verbose_name': 'Parameter Template',
|
||||
'verbose_name_plural': 'Parameter Templates',
|
||||
},
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='partparameter',
|
||||
name='template',
|
||||
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='part.PartParameterTemplate'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='part',
|
||||
name='category',
|
||||
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='part.PartCategory'),
|
||||
field=models.ForeignKey(blank=True, help_text='Part category', null=True, on_delete=django.db.models.deletion.DO_NOTHING, related_name='parts', to='part.PartCategory'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='categoryparameterlink',
|
||||
name='category',
|
||||
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='part.PartCategory'),
|
||||
model_name='part',
|
||||
name='default_supplier',
|
||||
field=models.ForeignKey(blank=True, help_text='Default supplier part', null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='default_parts', to='part.SupplierPart'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='categoryparameterlink',
|
||||
name='template',
|
||||
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='part.PartParameterTemplate'),
|
||||
),
|
||||
migrations.AlterUniqueTogether(
|
||||
name='partparameter',
|
||||
unique_together=set([('part', 'template')]),
|
||||
),
|
||||
migrations.AlterUniqueTogether(
|
||||
model_name='bomitem',
|
||||
name='part',
|
||||
unique_together=set([('name', 'category'), ('IPN', 'category')]),
|
||||
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='bom_items', to='part.Part'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='bomitem',
|
||||
name='sub_part',
|
||||
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='used_in', to='part.Part'),
|
||||
),
|
||||
migrations.AlterUniqueTogether(
|
||||
name='categoryparameterlink',
|
||||
unique_together=set([('category', 'template')]),
|
||||
name='supplierpricebreak',
|
||||
unique_together=set([('part', 'quantity')]),
|
||||
),
|
||||
migrations.AlterUniqueTogether(
|
||||
name='supplierpart',
|
||||
unique_together=set([('part', 'supplier', 'SKU')]),
|
||||
),
|
||||
migrations.AlterUniqueTogether(
|
||||
name='bomitem',
|
||||
unique_together=set([('part', 'sub_part')]),
|
||||
),
|
||||
]
|
||||
|
@ -1,48 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Generated by Django 1.11 on 2018-04-12 06:00
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import migrations
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('part', '0001_initial'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterUniqueTogether(
|
||||
name='categoryparameterlink',
|
||||
unique_together=set([]),
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='categoryparameterlink',
|
||||
name='category',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='categoryparameterlink',
|
||||
name='template',
|
||||
),
|
||||
migrations.AlterUniqueTogether(
|
||||
name='partparameter',
|
||||
unique_together=set([]),
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='partparameter',
|
||||
name='part',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='partparameter',
|
||||
name='template',
|
||||
),
|
||||
migrations.DeleteModel(
|
||||
name='CategoryParameterLink',
|
||||
),
|
||||
migrations.DeleteModel(
|
||||
name='PartParameter',
|
||||
),
|
||||
migrations.DeleteModel(
|
||||
name='PartParameterTemplate',
|
||||
),
|
||||
]
|
@ -1,5 +1,5 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Generated by Django 1.11.12 on 2018-04-17 08:12
|
||||
# Generated by Django 1.11.12 on 2018-04-22 11:53
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import migrations, models
|
||||
@ -9,14 +9,14 @@ import django.db.models.deletion
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('stock', '0010_stockitem_build'),
|
||||
('part', '0020_part_salable'),
|
||||
('stock', '0001_initial'),
|
||||
('part', '0001_initial'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='part',
|
||||
name='default_location',
|
||||
field=models.ForeignKey(blank=True, help_text='Where is this item normally stored?', null=True, on_delete=django.db.models.deletion.SET_NULL, to='stock.StockLocation'),
|
||||
field=models.ForeignKey(blank=True, help_text='Where is this item normally stored?', null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='default_parts', to='stock.StockLocation'),
|
||||
),
|
||||
]
|
@ -1,19 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Generated by Django 1.11 on 2018-04-12 06:44
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import migrations
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('part', '0002_auto_20180412_0600'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterUniqueTogether(
|
||||
name='part',
|
||||
unique_together=set([('name', 'category')]),
|
||||
),
|
||||
]
|
@ -1,21 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Generated by Django 1.11 on 2018-04-13 08:34
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('part', '0003_auto_20180412_0644'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='part',
|
||||
name='category',
|
||||
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='parts', to='part.PartCategory'),
|
||||
),
|
||||
]
|
@ -1,20 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Generated by Django 1.11 on 2018-04-13 12:30
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('part', '0004_auto_20180413_0834'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='partcategory',
|
||||
name='name',
|
||||
field=models.CharField(max_length=100, unique=True),
|
||||
),
|
||||
]
|
@ -1,21 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Generated by Django 1.11 on 2018-04-14 04:03
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('part', '0005_auto_20180413_1230'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='part',
|
||||
name='category',
|
||||
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='parts', to='part.PartCategory'),
|
||||
),
|
||||
]
|
@ -1,33 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Generated by Django 1.11 on 2018-04-14 04:16
|
||||
from __future__ import unicode_literals
|
||||
|
||||
import django.core.validators
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('part', '0006_auto_20180414_0403'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='BomItem',
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('quantity', models.PositiveIntegerField(default=1, validators=[django.core.validators.MinValueValidator(0)])),
|
||||
('part', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='bom_items', to='part.Part')),
|
||||
('sub_part', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='used_in', to='part.Part')),
|
||||
],
|
||||
options={
|
||||
'verbose_name': 'BOM Item',
|
||||
},
|
||||
),
|
||||
migrations.AlterUniqueTogether(
|
||||
name='bomitem',
|
||||
unique_together=set([('part', 'sub_part')]),
|
||||
),
|
||||
]
|
@ -1,20 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Generated by Django 1.11 on 2018-04-14 06:31
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('part', '0007_auto_20180414_0416'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='part',
|
||||
name='URL',
|
||||
field=models.URLField(blank=True),
|
||||
),
|
||||
]
|
@ -1,20 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Generated by Django 1.11 on 2018-04-14 06:53
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('part', '0008_part_url'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='part',
|
||||
name='image',
|
||||
field=models.ImageField(blank=True, upload_to='part_images'),
|
||||
),
|
||||
]
|
@ -1,21 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Generated by Django 1.11 on 2018-04-14 07:25
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import migrations, models
|
||||
import part.models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('part', '0009_part_image'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='part',
|
||||
name='image',
|
||||
field=models.ImageField(blank=True, max_length=255, null=True, upload_to=part.models.rename_part_image),
|
||||
),
|
||||
]
|
@ -1,25 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Generated by Django 1.11 on 2018-04-14 08:21
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
import part.models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('part', '0010_auto_20180414_0725'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='PartAttachment',
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('attachment', models.FileField(blank=True, null=True, upload_to=part.models.attach_file)),
|
||||
('part', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='attachments', to='part.Part')),
|
||||
],
|
||||
),
|
||||
]
|
@ -1,21 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Generated by Django 1.11 on 2018-04-14 10:32
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('part', '0011_partattachment'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='part',
|
||||
name='category',
|
||||
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.DO_NOTHING, related_name='parts', to='part.PartCategory'),
|
||||
),
|
||||
]
|
@ -1,24 +0,0 @@
|
||||
# -*- 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([]),
|
||||
),
|
||||
]
|
@ -1,21 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Generated by Django 1.11 on 2018-04-15 01:07
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('part', '0013_auto_20180414_2238'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='partcategory',
|
||||
name='parent',
|
||||
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.DO_NOTHING, related_name='children', to='part.PartCategory'),
|
||||
),
|
||||
]
|
@ -1,20 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Generated by Django 1.11 on 2018-04-15 03:02
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('part', '0014_auto_20180415_0107'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='partcategory',
|
||||
name='description',
|
||||
field=models.CharField(max_length=250),
|
||||
),
|
||||
]
|
@ -1,20 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Generated by Django 1.11 on 2018-04-15 03:16
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('part', '0015_auto_20180415_0302'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='part',
|
||||
name='description',
|
||||
field=models.CharField(max_length=250),
|
||||
),
|
||||
]
|
@ -1,20 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Generated by Django 1.11 on 2018-04-15 14:21
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('part', '0016_auto_20180415_0316'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='part',
|
||||
name='purchaseable',
|
||||
field=models.BooleanField(default=True),
|
||||
),
|
||||
]
|
@ -1,20 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Generated by Django 1.11 on 2018-04-16 12:08
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('part', '0017_part_purchaseable'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='part',
|
||||
name='buildable',
|
||||
field=models.BooleanField(default=False),
|
||||
),
|
||||
]
|
@ -1,62 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Generated by Django 1.11 on 2018-04-16 12:49
|
||||
from __future__ import unicode_literals
|
||||
|
||||
import django.core.validators
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('part', '0018_part_buildable'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='part',
|
||||
name='IPN',
|
||||
field=models.CharField(blank=True, help_text='Internal Part Number', max_length=100),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='part',
|
||||
name='URL',
|
||||
field=models.URLField(blank=True, help_text='Link to extenal URL'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='part',
|
||||
name='buildable',
|
||||
field=models.BooleanField(default=False, help_text='Can this part be built from other parts?'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='part',
|
||||
name='category',
|
||||
field=models.ForeignKey(blank=True, help_text='Part category', null=True, on_delete=django.db.models.deletion.DO_NOTHING, related_name='parts', to='part.PartCategory'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='part',
|
||||
name='description',
|
||||
field=models.CharField(help_text='Part description', max_length=250),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='part',
|
||||
name='minimum_stock',
|
||||
field=models.PositiveIntegerField(default=0, help_text='Minimum allowed stock level', validators=[django.core.validators.MinValueValidator(0)]),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='part',
|
||||
name='name',
|
||||
field=models.CharField(help_text='Part name (must be unique)', max_length=100, unique=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='part',
|
||||
name='purchaseable',
|
||||
field=models.BooleanField(default=True, help_text='Can this part be purchased from external suppliers?'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='part',
|
||||
name='trackable',
|
||||
field=models.BooleanField(default=False, help_text='Does this part have tracking for unique items?'),
|
||||
),
|
||||
]
|
@ -1,20 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Generated by Django 1.11.12 on 2018-04-17 08:06
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('part', '0019_auto_20180416_1249'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='part',
|
||||
name='salable',
|
||||
field=models.BooleanField(default=False, help_text='Can this part be sold to customers?'),
|
||||
),
|
||||
]
|
@ -1,27 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Generated by Django 1.11.12 on 2018-04-17 08:19
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('company', '0007_auto_20180416_1253'),
|
||||
('part', '0021_part_default_location'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='part',
|
||||
name='default_supplier',
|
||||
field=models.ForeignKey(blank=True, help_text='Default supplier part', null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='default_parts', to='company.SupplierPart'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='part',
|
||||
name='default_location',
|
||||
field=models.ForeignKey(blank=True, help_text='Where is this item normally stored?', null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='default_parts', to='stock.StockLocation'),
|
||||
),
|
||||
]
|
@ -1,20 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Generated by Django 1.11.12 on 2018-04-17 15:34
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('part', '0022_auto_20180417_0819'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='part',
|
||||
name='notes',
|
||||
field=models.TextField(blank=True),
|
||||
),
|
||||
]
|
@ -11,7 +11,7 @@ from django.db.models.signals import pre_delete
|
||||
from django.dispatch import receiver
|
||||
|
||||
from InvenTree.models import InvenTreeTree
|
||||
|
||||
from company.models import Company
|
||||
|
||||
class PartCategory(InvenTreeTree):
|
||||
""" PartCategory provides hierarchical organization of Part objects.
|
||||
@ -111,7 +111,7 @@ class Part(models.Model):
|
||||
related_name='default_parts')
|
||||
|
||||
# Default supplier part
|
||||
default_supplier = models.ForeignKey('company.SupplierPart',
|
||||
default_supplier = models.ForeignKey('part.SupplierPart',
|
||||
on_delete=models.SET_NULL,
|
||||
blank=True, null=True,
|
||||
help_text='Default supplier part',
|
||||
@ -352,3 +352,78 @@ class BomItem(models.Model):
|
||||
par=self.part.name,
|
||||
child=self.sub_part.name,
|
||||
n=self.quantity)
|
||||
|
||||
class SupplierPart(models.Model):
|
||||
""" Represents a unique part as provided by a Supplier
|
||||
Each SupplierPart is identified by a MPN (Manufacturer Part Number)
|
||||
Each SupplierPart is also linked to a Part object
|
||||
- A Part may be available from multiple suppliers
|
||||
"""
|
||||
|
||||
def get_absolute_url(self):
|
||||
return "/supplier-part/{id}/".format(id=self.id)
|
||||
|
||||
class Meta:
|
||||
unique_together = ('part', 'supplier', 'SKU')
|
||||
|
||||
# Link to an actual part
|
||||
# The part will have a field 'supplier_parts' which links to the supplier part options
|
||||
part = models.ForeignKey(Part, on_delete=models.CASCADE,
|
||||
related_name='supplier_parts')
|
||||
|
||||
supplier = models.ForeignKey(Company, on_delete=models.CASCADE,
|
||||
related_name='parts')
|
||||
|
||||
SKU = models.CharField(max_length=100, help_text='Supplier stock keeping unit')
|
||||
|
||||
manufacturer = models.CharField(max_length=100, blank=True, help_text='Manufacturer')
|
||||
|
||||
MPN = models.CharField(max_length=100, blank=True, help_text='Manufacturer part number')
|
||||
|
||||
URL = models.URLField(blank=True)
|
||||
|
||||
description = models.CharField(max_length=250, blank=True)
|
||||
|
||||
# Default price for a single unit
|
||||
single_price = models.DecimalField(max_digits=10, decimal_places=3, default=0)
|
||||
|
||||
# Base charge added to order independent of quantity e.g. "Reeling Fee"
|
||||
base_cost = models.DecimalField(max_digits=10, decimal_places=3, default=0)
|
||||
|
||||
# packaging that the part is supplied in, e.g. "Reel"
|
||||
packaging = models.CharField(max_length=50, blank=True)
|
||||
|
||||
# multiple that the part is provided in
|
||||
multiple = models.PositiveIntegerField(default=1, validators=[MinValueValidator(0)])
|
||||
|
||||
# Mimumum number required to order
|
||||
minimum = models.PositiveIntegerField(default=1, validators=[MinValueValidator(0)])
|
||||
|
||||
# lead time for parts that cannot be delivered immediately
|
||||
lead_time = models.DurationField(blank=True, null=True)
|
||||
|
||||
def __str__(self):
|
||||
return "{sku} - {supplier}".format(
|
||||
sku=self.SKU,
|
||||
supplier=self.supplier.name)
|
||||
|
||||
|
||||
class SupplierPriceBreak(models.Model):
|
||||
""" Represents a quantity price break for a SupplierPart
|
||||
- Suppliers can offer discounts at larger quantities
|
||||
- SupplierPart(s) may have zero-or-more associated SupplierPriceBreak(s)
|
||||
"""
|
||||
|
||||
part = models.ForeignKey(SupplierPart, on_delete=models.CASCADE, related_name='price_breaks')
|
||||
quantity = models.PositiveIntegerField(validators=[MinValueValidator(0)])
|
||||
cost = models.DecimalField(max_digits=10, decimal_places=3)
|
||||
|
||||
class Meta:
|
||||
unique_together = ("part", "quantity")
|
||||
|
||||
def __str__(self):
|
||||
return "{mpn} - {cost}{currency} @ {quan}".format(
|
||||
mpn=self.part.MPN,
|
||||
cost=self.cost,
|
||||
currency=self.currency if self.currency else '',
|
||||
quan=self.quantity)
|
||||
|
@ -4,6 +4,19 @@ from django.views.generic.base import RedirectView
|
||||
from . import views
|
||||
from . import api
|
||||
|
||||
supplier_part_detail_urls = [
|
||||
url(r'edit/?', views.SupplierPartEdit.as_view(), name='supplier-part-edit'),
|
||||
url(r'delete/?', views.SupplierPartDelete.as_view(), name='supplier-part-delete'),
|
||||
|
||||
url('^.*$', views.SupplierPartDetail.as_view(), name='supplier-part-detail'),
|
||||
]
|
||||
|
||||
supplier_part_urls = [
|
||||
url(r'^new/?', views.SupplierPartCreate.as_view(), name='supplier-part-create'),
|
||||
|
||||
url(r'^(?P<pk>\d+)/', include(supplier_part_detail_urls)),
|
||||
]
|
||||
|
||||
# URL list for part category API
|
||||
part_cat_api_urls = [
|
||||
|
||||
|
@ -7,8 +7,14 @@ from django.http import HttpResponseRedirect
|
||||
from django.views.generic import DetailView, ListView
|
||||
from django.views.generic.edit import UpdateView, DeleteView, CreateView
|
||||
|
||||
from .forms import EditPartForm, EditCategoryForm, EditBomItemForm
|
||||
from .models import PartCategory, Part, BomItem
|
||||
from .models import SupplierPart
|
||||
|
||||
from .forms import EditPartForm
|
||||
from .forms import EditCategoryForm
|
||||
from .forms import EditBomItemForm
|
||||
|
||||
from .forms import EditSupplierPartForm
|
||||
|
||||
|
||||
class PartIndex(ListView):
|
||||
@ -191,3 +197,53 @@ class BomItemDelete(DeleteView):
|
||||
return super(BomItemDelete, self).post(request, *args, **kwargs)
|
||||
else:
|
||||
return HttpResponseRedirect(self.get_object().get_absolute_url())
|
||||
|
||||
|
||||
class SupplierPartDetail(DetailView):
|
||||
model = SupplierPart
|
||||
template_name = 'company/partdetail.html'
|
||||
context_object_name = 'part'
|
||||
queryset = SupplierPart.objects.all()
|
||||
|
||||
|
||||
class SupplierPartEdit(UpdateView):
|
||||
model = SupplierPart
|
||||
template_name = 'company/partedit.html'
|
||||
context_object_name = 'part'
|
||||
form_class = EditSupplierPartForm
|
||||
|
||||
|
||||
class SupplierPartCreate(CreateView):
|
||||
model = SupplierPart
|
||||
form_class = EditSupplierPartForm
|
||||
template_name = 'company/partcreate.html'
|
||||
context_object_name = 'part'
|
||||
|
||||
def get_initial(self):
|
||||
initials = super(SupplierPartCreate, self).get_initial().copy()
|
||||
|
||||
supplier_id = self.request.GET.get('supplier', None)
|
||||
part_id = self.request.GET.get('part', None)
|
||||
|
||||
if supplier_id:
|
||||
initials['supplier'] = get_object_or_404(Supplier, pk=supplier_id)
|
||||
# TODO
|
||||
# self.fields['supplier'].disabled = True
|
||||
if part_id:
|
||||
initials['part'] = get_object_or_404(Part, pk=part_id)
|
||||
# TODO
|
||||
# self.fields['part'].disabled = True
|
||||
|
||||
return initials
|
||||
|
||||
|
||||
class SupplierPartDelete(DeleteView):
|
||||
model = SupplierPart
|
||||
success_url = '/supplier/'
|
||||
template_name = 'company/partdelete.html'
|
||||
|
||||
def post(self, request, *args, **kwargs):
|
||||
if 'confirm' in request.POST:
|
||||
return super(SupplierPartDelete, self).post(request, *args, **kwargs)
|
||||
else:
|
||||
return HttpResponseRedirect(self.get_object().get_absolute_url())
|
||||
|
Reference in New Issue
Block a user