From d840b44f7a7b6cb71a6118857f163620eac7568c Mon Sep 17 00:00:00 2001 From: Oliver Walters Date: Tue, 4 Jun 2019 22:19:04 +1000 Subject: [PATCH] Create initial models for 'Order' - PurchaseOrder - PurchaseOrderLineItem (These are based on some abstract model classes) --- InvenTree/InvenTree/settings.py | 1 + .../migrations/0005_auto_20190604_2217.py | 19 ++++ InvenTree/order/__init__.py | 0 InvenTree/order/admin.py | 29 +++++ InvenTree/order/apps.py | 5 + InvenTree/order/migrations/0001_initial.py | 48 ++++++++ InvenTree/order/migrations/__init__.py | 0 InvenTree/order/models.py | 103 ++++++++++++++++++ InvenTree/order/tests.py | 3 + InvenTree/order/views.py | 3 + 10 files changed, 211 insertions(+) create mode 100644 InvenTree/build/migrations/0005_auto_20190604_2217.py create mode 100644 InvenTree/order/__init__.py create mode 100644 InvenTree/order/admin.py create mode 100644 InvenTree/order/apps.py create mode 100644 InvenTree/order/migrations/0001_initial.py create mode 100644 InvenTree/order/migrations/__init__.py create mode 100644 InvenTree/order/models.py create mode 100644 InvenTree/order/tests.py create mode 100644 InvenTree/order/views.py diff --git a/InvenTree/InvenTree/settings.py b/InvenTree/InvenTree/settings.py index 74c9eac71a..d5ff5749ba 100644 --- a/InvenTree/InvenTree/settings.py +++ b/InvenTree/InvenTree/settings.py @@ -62,6 +62,7 @@ INSTALLED_APPS = [ 'stock.apps.StockConfig', 'company.apps.CompanyConfig', 'build.apps.BuildConfig', + 'order.apps.OrderConfig', # Third part add-ons 'django_filters', # Extended filter functionality diff --git a/InvenTree/build/migrations/0005_auto_20190604_2217.py b/InvenTree/build/migrations/0005_auto_20190604_2217.py new file mode 100644 index 0000000000..019399ef12 --- /dev/null +++ b/InvenTree/build/migrations/0005_auto_20190604_2217.py @@ -0,0 +1,19 @@ +# Generated by Django 2.2 on 2019-06-04 12:17 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('build', '0004_auto_20190525_2356'), + ] + + operations = [ + migrations.AlterField( + model_name='build', + name='part', + field=models.ForeignKey(help_text='Select part to build', limit_choices_to={'active': True, 'assembly': True, 'is_template': False}, on_delete=django.db.models.deletion.CASCADE, related_name='builds', to='part.Part'), + ), + ] diff --git a/InvenTree/order/__init__.py b/InvenTree/order/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/InvenTree/order/admin.py b/InvenTree/order/admin.py new file mode 100644 index 0000000000..2fdf71950d --- /dev/null +++ b/InvenTree/order/admin.py @@ -0,0 +1,29 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.contrib import admin +from import_export.admin import ImportExportModelAdmin + +from .models import PurchaseOrder, PurchaseOrderLineItem + + +class PurchaseOrderAdmin(admin.ModelAdmin): + + list_display = ( + 'reference', + 'description', + 'creation_date' + ) + + +class PurchaseOrderLineItemAdmin(admin.ModelAdmin): + + list_display = ( + 'order', + 'quantity', + 'reference' + ) + + +admin.site.register(PurchaseOrder, PurchaseOrderAdmin) +admin.site.register(PurchaseOrderLineItem, PurchaseOrderLineItemAdmin) diff --git a/InvenTree/order/apps.py b/InvenTree/order/apps.py new file mode 100644 index 0000000000..821e6d872c --- /dev/null +++ b/InvenTree/order/apps.py @@ -0,0 +1,5 @@ +from django.apps import AppConfig + + +class OrderConfig(AppConfig): + name = 'order' diff --git a/InvenTree/order/migrations/0001_initial.py b/InvenTree/order/migrations/0001_initial.py new file mode 100644 index 0000000000..642b321d47 --- /dev/null +++ b/InvenTree/order/migrations/0001_initial.py @@ -0,0 +1,48 @@ +# Generated by Django 2.2 on 2019-06-04 12:17 + +from django.conf import settings +import django.core.validators +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + ('company', '0005_auto_20190525_2356'), + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ] + + operations = [ + migrations.CreateModel( + name='PurchaseOrder', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('reference', models.CharField(help_text='Order reference', max_length=64, unique=True)), + ('description', models.CharField(help_text='Order description', max_length=250)), + ('creation_date', models.DateField(auto_now=True)), + ('issue_date', models.DateField(blank=True, null=True)), + ('notes', models.TextField(blank=True, help_text='Order notes')), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to=settings.AUTH_USER_MODEL)), + ('supplier', models.ForeignKey(help_text='Company', on_delete=django.db.models.deletion.CASCADE, related_name='Orders', to='company.Company')), + ], + options={ + 'abstract': False, + }, + ), + migrations.CreateModel( + name='PurchaseOrderLineItem', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('quantity', models.PositiveIntegerField(default=1, help_text='Item quantity', validators=[django.core.validators.MinValueValidator(0)])), + ('reference', models.CharField(blank=True, help_text='Line item reference', max_length=100)), + ('received', models.PositiveIntegerField(default=0, help_text='Number of items received')), + ('order', models.ForeignKey(help_text='Purchase Order', on_delete=django.db.models.deletion.CASCADE, related_name='lines', to='order.PurchaseOrder')), + ], + options={ + 'abstract': False, + }, + ), + ] diff --git a/InvenTree/order/migrations/__init__.py b/InvenTree/order/migrations/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/InvenTree/order/models.py b/InvenTree/order/models.py new file mode 100644 index 0000000000..cc97506bfd --- /dev/null +++ b/InvenTree/order/models.py @@ -0,0 +1,103 @@ +from django.db import models, transaction +from django.core.validators import MinValueValidator +from django.contrib.auth.models import User + +from django.utils.translation import ugettext as _ + +from part.models import Part +from company.models import Company +from stock.models import StockItem + + +class Order(models.Model): + """ Abstract model for an order. + + Instances of this class: + + - PuchaseOrder + + Attributes: + reference: Unique order number / reference / code + description: Long form description (required) + notes: Extra note field (optional) + creation_date: Automatic date of order creation + created_by: User who created this order (automatically captured) + issue_date: Date the order was issued + + """ + + # Order status codes + PENDING = 10 # Order is pending (not yet placed) + PLACED = 20 # Order has been placed + RECEIVED = 30 # Order has been received + CANCELLED = 40 # Order was cancelled + LOST = 50 # Order was lost + RETURNED = 60 # Order was returned + + class Meta: + abstract = True + + reference = models.CharField(unique=True, max_length=64, blank=False, help_text=_('Order reference')) + + description = models.CharField(max_length=250, blank=False, help_text=_('Order description')) + + creation_date = models.DateField(auto_now=True, editable=False) + + created_by = models.ForeignKey(User, + on_delete=models.SET_NULL, + blank=True, null=True, + related_name='+' + ) + + issue_date = models.DateField(blank=True, null=True) + + + notes = models.TextField(blank=True, help_text=_('Order notes')) + + +class PurchaseOrder(Order): + """ A PurchaseOrder represents goods shipped inwards from an external supplier. + + Attributes: + supplier: Reference to the company supplying the goods in the order + + """ + + supplier = models.ForeignKey(Company, on_delete=models.CASCADE, + related_name=_('Orders'), + help_text=_('Company') + ) + +class OrderLineItem(models.Model): + """ Abstract model for an order line item + + Attributes: + quantity: Number of items + note: Annotation for the item + + """ + + class Meta: + abstract = True + + quantity = models.PositiveIntegerField(validators=[MinValueValidator(0)], default=1, help_text=_('Item quantity')) + + reference = models.CharField(max_length=100, blank=True, help_text=_('Line item reference')) + + +class PurchaseOrderLineItem(OrderLineItem): + """ Model for a purchase order line item. + + Attributes: + order: Reference to a PurchaseOrder object + + """ + + order = models.ForeignKey(PurchaseOrder, on_delete=models.CASCADE, + related_name='lines', + help_text=_('Purchase Order') + ) + + # TODO - foreign key references to part and stockitem objects + + received = models.PositiveIntegerField(default=0, help_text=_('Number of items received')) diff --git a/InvenTree/order/tests.py b/InvenTree/order/tests.py new file mode 100644 index 0000000000..7ce503c2dd --- /dev/null +++ b/InvenTree/order/tests.py @@ -0,0 +1,3 @@ +from django.test import TestCase + +# Create your tests here. diff --git a/InvenTree/order/views.py b/InvenTree/order/views.py new file mode 100644 index 0000000000..91ea44a218 --- /dev/null +++ b/InvenTree/order/views.py @@ -0,0 +1,3 @@ +from django.shortcuts import render + +# Create your views here.