mirror of
https://github.com/Sosokker/Inventory-Management-System.git
synced 2025-12-19 15:34:04 +01:00
Modify transfer log system
This commit is contained in:
parent
fee98a27cb
commit
921d43c8a1
@ -1,5 +1,5 @@
|
|||||||
from django.contrib import admin
|
from django.contrib import admin
|
||||||
from inventory.models import Warehouse, Inventory, Item
|
from inventory.models import Warehouse, Inventory, Item, Category
|
||||||
|
|
||||||
@admin.register(Warehouse)
|
@admin.register(Warehouse)
|
||||||
class WarehouseAdmin(admin.ModelAdmin):
|
class WarehouseAdmin(admin.ModelAdmin):
|
||||||
@ -11,4 +11,8 @@ class InventoryAdmin(admin.ModelAdmin):
|
|||||||
|
|
||||||
@admin.register(Item)
|
@admin.register(Item)
|
||||||
class ItemAdmin(admin.ModelAdmin):
|
class ItemAdmin(admin.ModelAdmin):
|
||||||
list_display = ('name', 'description', 'category', 'weight', 'quantity', 'inventory')
|
list_display = ('name', 'description', 'category', 'weight', 'quantity', 'inventory')
|
||||||
|
|
||||||
|
@admin.register(Category)
|
||||||
|
class CatergoryAdmin(admin.ModelAdmin):
|
||||||
|
list_display = ('name',)
|
||||||
@ -3,7 +3,4 @@ from django.apps import AppConfig
|
|||||||
|
|
||||||
class InventoryConfig(AppConfig):
|
class InventoryConfig(AppConfig):
|
||||||
default_auto_field = 'django.db.models.BigAutoField'
|
default_auto_field = 'django.db.models.BigAutoField'
|
||||||
name = 'inventory'
|
name = 'inventory'
|
||||||
|
|
||||||
def ready(self):
|
|
||||||
import inventory.signals
|
|
||||||
@ -0,0 +1,39 @@
|
|||||||
|
# Generated by Django 4.2.7 on 2023-11-18 21:22
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
import django.db.models.deletion
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('inventory', '0002_alter_inventory_options'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='Category',
|
||||||
|
fields=[
|
||||||
|
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||||
|
('name', models.CharField(max_length=255)),
|
||||||
|
],
|
||||||
|
options={
|
||||||
|
'verbose_name_plural': 'Categories',
|
||||||
|
},
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='inventory',
|
||||||
|
name='current_stock',
|
||||||
|
field=models.IntegerField(default=0),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='inventory',
|
||||||
|
name='min_stock',
|
||||||
|
field=models.IntegerField(default=0),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='item',
|
||||||
|
name='category',
|
||||||
|
field=models.ForeignKey(on_delete=django.db.models.deletion.DO_NOTHING, to='inventory.category'),
|
||||||
|
),
|
||||||
|
]
|
||||||
19
inventory/migrations/0004_alter_item_category.py
Normal file
19
inventory/migrations/0004_alter_item_category.py
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
# Generated by Django 4.2.7 on 2023-11-18 21:23
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
import django.db.models.deletion
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('inventory', '0003_category_alter_inventory_current_stock_and_more'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='item',
|
||||||
|
name='category',
|
||||||
|
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.DO_NOTHING, to='inventory.category'),
|
||||||
|
),
|
||||||
|
]
|
||||||
@ -0,0 +1,24 @@
|
|||||||
|
# Generated by Django 4.2.7 on 2023-11-18 21:48
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
import django.db.models.deletion
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('inventory', '0004_alter_item_category'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='item',
|
||||||
|
name='previous_inventory',
|
||||||
|
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='previous_inventory', to='inventory.inventory'),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='item',
|
||||||
|
name='description',
|
||||||
|
field=models.TextField(null=True),
|
||||||
|
),
|
||||||
|
]
|
||||||
17
inventory/migrations/0006_remove_item_previous_inventory.py
Normal file
17
inventory/migrations/0006_remove_item_previous_inventory.py
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
# Generated by Django 4.2.7 on 2023-11-18 22:23
|
||||||
|
|
||||||
|
from django.db import migrations
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('inventory', '0005_item_previous_inventory_alter_item_description'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.RemoveField(
|
||||||
|
model_name='item',
|
||||||
|
name='previous_inventory',
|
||||||
|
),
|
||||||
|
]
|
||||||
@ -1,5 +1,5 @@
|
|||||||
from django.db import models
|
from django.db import models
|
||||||
|
from django.apps import apps
|
||||||
|
|
||||||
class Warehouse(models.Model):
|
class Warehouse(models.Model):
|
||||||
"""
|
"""
|
||||||
@ -58,11 +58,25 @@ class Inventory(models.Model):
|
|||||||
class Meta:
|
class Meta:
|
||||||
verbose_name_plural = 'Inventories'
|
verbose_name_plural = 'Inventories'
|
||||||
|
|
||||||
|
class Category(models.Model):
|
||||||
|
"""
|
||||||
|
Catergory of the item
|
||||||
|
|
||||||
|
:param name: Name of the catergory
|
||||||
|
"""
|
||||||
|
name = models.CharField(max_length=255)
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return f"{self.name}"
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
verbose_name_plural = 'Categories'
|
||||||
|
|
||||||
class Item(models.Model):
|
class Item(models.Model):
|
||||||
"""
|
"""
|
||||||
Item such as food, drink, furnoture etc.
|
Item such as food, drink, furnoture etc.
|
||||||
|
|
||||||
|
:param previous_inventory: Previous inventory that the item belongs to, If null, it means the item is new or never move
|
||||||
:param inventory: Inventory that the item belongs to
|
:param inventory: Inventory that the item belongs to
|
||||||
:param name: Name of the item
|
:param name: Name of the item
|
||||||
:param description: Description of the item
|
:param description: Description of the item
|
||||||
@ -71,11 +85,38 @@ class Item(models.Model):
|
|||||||
:param quantity: Quantity of the item
|
:param quantity: Quantity of the item
|
||||||
"""
|
"""
|
||||||
inventory = models.ForeignKey(Inventory, on_delete=models.CASCADE)
|
inventory = models.ForeignKey(Inventory, on_delete=models.CASCADE)
|
||||||
|
category = models.ForeignKey(Category, on_delete=models.DO_NOTHING, null=True)
|
||||||
name = models.CharField(max_length=255)
|
name = models.CharField(max_length=255)
|
||||||
description = models.TextField()
|
description = models.TextField(null=True)
|
||||||
category = models.CharField(max_length=255)
|
|
||||||
weight = models.DecimalField(max_digits=10, decimal_places=3)
|
weight = models.DecimalField(max_digits=10, decimal_places=3)
|
||||||
quantity = models.IntegerField()
|
quantity = models.IntegerField()
|
||||||
|
|
||||||
|
__previous_inventory = None
|
||||||
|
|
||||||
|
def __init__(self, *args, **kwargs):
|
||||||
|
super().__init__(*args, **kwargs)
|
||||||
|
try:
|
||||||
|
self.__previous_inventory = self.inventory
|
||||||
|
except:
|
||||||
|
self.__previous_inventory = None
|
||||||
|
|
||||||
|
def save(self, force_insert=False, force_update=False, *args, **kwargs):
|
||||||
|
if self.__previous_inventory == None:
|
||||||
|
super().save(force_insert, force_update, *args, **kwargs)
|
||||||
|
Inventory.objects.filter(id=self.inventory.id).update(current_stock=self.inventory.current_stock + self.quantity)
|
||||||
|
return
|
||||||
|
|
||||||
|
if self.inventory != self.__previous_inventory:
|
||||||
|
Inventory.objects.filter(id=self.__previous_inventory.id).update(current_stock=self.__previous_inventory.current_stock - self.quantity)
|
||||||
|
Inventory.objects.filter(id=self.inventory.id).update(current_stock=self.inventory.current_stock + self.quantity)
|
||||||
|
apps.get_model('transaction', 'Transfer').objects.create(
|
||||||
|
from_warehouse=self.__previous_inventory.warehouse,
|
||||||
|
to_warehouse=self.inventory.warehouse,
|
||||||
|
item=self,
|
||||||
|
quantity=self.quantity,
|
||||||
|
)
|
||||||
|
super().save(force_insert, force_update, *args, **kwargs)
|
||||||
|
self.__previous_inventory = self.inventory
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return f"{self.name} - {self.quantity}"
|
return f"{self.name} - {self.quantity}"
|
||||||
@ -1,41 +0,0 @@
|
|||||||
from django.db.models.signals import post_save, pre_save
|
|
||||||
from django.dispatch import receiver
|
|
||||||
from inventory.models import Item
|
|
||||||
from transaction.models import Transfer
|
|
||||||
|
|
||||||
|
|
||||||
@receiver(pre_save, sender=Item)
|
|
||||||
def handle_item_move(sender, instance, **kwargs):
|
|
||||||
"""
|
|
||||||
Signal to handle moving an Item to a new Inventory.
|
|
||||||
"""
|
|
||||||
if instance.pk:
|
|
||||||
old_item = Item.objects.get(pk=instance.pk)
|
|
||||||
if old_item.inventory != instance.inventory:
|
|
||||||
old_item.inventory.current_stock -= old_item.quantity
|
|
||||||
old_item.inventory.save()
|
|
||||||
|
|
||||||
@receiver(post_save, sender=Item)
|
|
||||||
def update_inventory_current_stock(sender, instance, **kwargs):
|
|
||||||
"""
|
|
||||||
Signal to update current_stock of related Inventory when an Item is created or assigned to a new Inventory.
|
|
||||||
"""
|
|
||||||
if kwargs.get('created', False) or instance.pk:
|
|
||||||
instance.inventory.current_stock += instance.quantity
|
|
||||||
instance.inventory.save()
|
|
||||||
|
|
||||||
|
|
||||||
@receiver(post_save, sender=Item)
|
|
||||||
def create_transfer_instance(sender, instance, **kwargs):
|
|
||||||
"""
|
|
||||||
Signal to create a Transfer instance when an Item is transferred between warehouses.
|
|
||||||
"""
|
|
||||||
# If the item is being created or updated
|
|
||||||
if kwargs.get('created', False) or instance.pk:
|
|
||||||
if instance.pk and instance.inventory.warehouse != instance.inventory.old_warehouse:
|
|
||||||
Transfer.objects.create(
|
|
||||||
from_warehouse=instance.inventory.old_warehouse,
|
|
||||||
to_warehouse=instance.inventory.warehouse,
|
|
||||||
item=instance,
|
|
||||||
quantity=instance.quantity,
|
|
||||||
)
|
|
||||||
@ -20,4 +20,4 @@ class OrderAdmin(admin.ModelAdmin):
|
|||||||
|
|
||||||
@admin.register(Transfer)
|
@admin.register(Transfer)
|
||||||
class TransferAdmin(admin.ModelAdmin):
|
class TransferAdmin(admin.ModelAdmin):
|
||||||
list_display = ('from_warehouse', 'to_warehouse', 'item', 'from_date_timestamp', 'to_date_timestamp', 'quantity')
|
list_display = ('from_warehouse', 'to_warehouse', 'item', 'update_time', 'quantity')
|
||||||
@ -0,0 +1,26 @@
|
|||||||
|
# Generated by Django 4.2.7 on 2023-11-18 21:57
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('transaction', '0002_alter_supply_options_alter_order_order_date_and_more'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.RemoveField(
|
||||||
|
model_name='transfer',
|
||||||
|
name='from_date_timestamp',
|
||||||
|
),
|
||||||
|
migrations.RemoveField(
|
||||||
|
model_name='transfer',
|
||||||
|
name='to_date_timestamp',
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='transfer',
|
||||||
|
name='update_time',
|
||||||
|
field=models.DateTimeField(auto_now=True),
|
||||||
|
),
|
||||||
|
]
|
||||||
@ -87,8 +87,7 @@ class Transfer(models.Model):
|
|||||||
to_warehouse = models.ForeignKey(Warehouse, related_name='transfer_to', on_delete=models.CASCADE)
|
to_warehouse = models.ForeignKey(Warehouse, related_name='transfer_to', on_delete=models.CASCADE)
|
||||||
item = models.ForeignKey(Item, on_delete=models.CASCADE)
|
item = models.ForeignKey(Item, on_delete=models.CASCADE)
|
||||||
quantity = models.IntegerField()
|
quantity = models.IntegerField()
|
||||||
from_date_timestamp = models.DateTimeField()
|
update_time = models.DateTimeField(auto_now=True)
|
||||||
to_date_timestamp = models.DateTimeField()
|
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return f"{self.from_warehouse.name} - {self.to_warehouse.name} - {self.item.name} - {self.quantity}"
|
return f"{self.from_warehouse.name} - {self.to_warehouse.name} - {self.item.name} - {self.quantity}"
|
||||||
Loading…
Reference in New Issue
Block a user