Modify transfer log system

This commit is contained in:
sosokker 2023-11-19 05:37:29 +07:00
parent fee98a27cb
commit 921d43c8a1
11 changed files with 178 additions and 53 deletions

View File

@ -1,5 +1,5 @@
from django.contrib import admin
from inventory.models import Warehouse, Inventory, Item
from inventory.models import Warehouse, Inventory, Item, Category
@admin.register(Warehouse)
class WarehouseAdmin(admin.ModelAdmin):
@ -12,3 +12,7 @@ class InventoryAdmin(admin.ModelAdmin):
@admin.register(Item)
class ItemAdmin(admin.ModelAdmin):
list_display = ('name', 'description', 'category', 'weight', 'quantity', 'inventory')
@admin.register(Category)
class CatergoryAdmin(admin.ModelAdmin):
list_display = ('name',)

View File

@ -4,6 +4,3 @@ from django.apps import AppConfig
class InventoryConfig(AppConfig):
default_auto_field = 'django.db.models.BigAutoField'
name = 'inventory'
def ready(self):
import inventory.signals

View File

@ -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'),
),
]

View 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'),
),
]

View File

@ -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),
),
]

View 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',
),
]

View File

@ -1,5 +1,5 @@
from django.db import models
from django.apps import apps
class Warehouse(models.Model):
"""
@ -58,11 +58,25 @@ class Inventory(models.Model):
class Meta:
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):
"""
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 name: Name of the item
:param description: Description of the item
@ -71,11 +85,38 @@ class Item(models.Model):
:param quantity: Quantity of the item
"""
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)
description = models.TextField()
category = models.CharField(max_length=255)
description = models.TextField(null=True)
weight = models.DecimalField(max_digits=10, decimal_places=3)
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):
return f"{self.name} - {self.quantity}"

View File

@ -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,
)

View File

@ -20,4 +20,4 @@ class OrderAdmin(admin.ModelAdmin):
@admin.register(Transfer)
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')

View File

@ -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),
),
]

View File

@ -87,8 +87,7 @@ class Transfer(models.Model):
to_warehouse = models.ForeignKey(Warehouse, related_name='transfer_to', on_delete=models.CASCADE)
item = models.ForeignKey(Item, on_delete=models.CASCADE)
quantity = models.IntegerField()
from_date_timestamp = models.DateTimeField()
to_date_timestamp = models.DateTimeField()
update_time = models.DateTimeField(auto_now=True)
def __str__(self):
return f"{self.from_warehouse.name} - {self.to_warehouse.name} - {self.item.name} - {self.quantity}"