From 16a81a2f66c54c1e8c3a2c13895ff7a5e6b2a024 Mon Sep 17 00:00:00 2001 From: Deepthi Damruwan Date: Sat, 10 May 2025 23:25:58 +0530 Subject: [PATCH 1/7] v 2.6 --- warehouse_managment/warehouse/views.py | 35 ++++++++++++++++++-------- 1 file changed, 25 insertions(+), 10 deletions(-) diff --git a/warehouse_managment/warehouse/views.py b/warehouse_managment/warehouse/views.py index e333f80..ebba245 100644 --- a/warehouse_managment/warehouse/views.py +++ b/warehouse_managment/warehouse/views.py @@ -256,31 +256,46 @@ def get_supplier_products(request, supplier_id): return Response(result) + @api_view(['GET']) def get_supplier_product_prices(request): supplier_id = request.query_params.get('supplier_id') if not supplier_id: return Response({"error": "supplier_id required"}, status=400) + connected_warehouses = WarehouseSupplier.objects.filter( + supplier_id=supplier_id + ).values_list('warehouse_id', flat=True) + supplier_products = ( SupplierProduct.objects .filter(supplier_id=supplier_id) .select_related('product') .annotate( product_name=F('product__product_name'), - SKU=F('product__product_SKU') + SKU=F('product__product_SKU'), ) - .values('product_name', 'SKU', 'supplier_price') ) - summary = [ - { - "product_name": item['product_name'], - "SKU": item['SKU'], - "supplier_price": float(item['supplier_price']), - } - for item in supplier_products - ] + summary = [] + for sp in supplier_products: + warehouse_names = ( + WarehouseInventory.objects + .filter( + warehouse_id__in=connected_warehouses, + product_id=sp.product_id + ) + .select_related('warehouse') + .values_list('warehouse__warehouse_name', flat=True) + .distinct() + ) + + summary.append({ + "product_name": sp.product.product_name, + "SKU": sp.product.product_SKU, + "supplier_price": float(sp.supplier_price), + "warehouses": list(warehouse_names), + }) return Response(summary) From bf711afc5504dc77310d2abe8faad3e4e1c2670a Mon Sep 17 00:00:00 2001 From: Deepthi Damruwan Date: Sat, 10 May 2025 23:49:01 +0530 Subject: [PATCH 2/7] v 2.7 (get_suppliers_for_product) --- warehouse_managment/product/urls.py | 5 +++++ warehouse_managment/product/views.py | 22 +++++++++++++++++++++- 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/warehouse_managment/product/urls.py b/warehouse_managment/product/urls.py index 33ace01..2b26d7a 100644 --- a/warehouse_managment/product/urls.py +++ b/warehouse_managment/product/urls.py @@ -8,6 +8,7 @@ supplier_product_list, update_supplier_product, product_stock_summary, + get_suppliers_for_product, ) urlpatterns = [ @@ -23,8 +24,12 @@ # Supplier product endpoints path('supplier-products/', supplier_product_list, name='supplier-product-list'), + path('supplier-products/update/', update_supplier_product, name='update-supplier-product'), # Product count endpoint path('product-stock-summary//', product_stock_summary), + + # GET SupplierIds for a product Id + path('suppliers-by-product', get_suppliers_for_product, name='get-suppliers-for-product'), ] diff --git a/warehouse_managment/product/views.py b/warehouse_managment/product/views.py index 434ddfc..3e299cc 100644 --- a/warehouse_managment/product/views.py +++ b/warehouse_managment/product/views.py @@ -52,7 +52,6 @@ def category_detail(request, pk): @api_view(['GET']) def supplier_product_list(request): - sp = SupplierProduct.objects.all() serializer = SupplierProductSerializer(sp, many=True) return Response(serializer.data) @@ -95,3 +94,24 @@ def product_stock_summary(request, sku_code): "product_SKU": product.product_SKU, "current_stock": float(total_stock) }, status=status.HTTP_200_OK) + + +@api_view(['GET']) +def get_suppliers_for_product(request): + product_id = request.query_params.get('product_id') + if not product_id: + return Response({"error": "product_id is required"}, status=400) + + supplier_ids = ( + SupplierProduct.objects + .filter(product_id=product_id) + .values_list('supplier_id', flat=True) + .distinct() + ) + + return Response({ + "product_id": int(product_id), + "supplier_ids": list(supplier_ids) + }) + + \ No newline at end of file From d2c91ced8d89c886aad98e51ca4080893a85596c Mon Sep 17 00:00:00 2001 From: Deepthi Damruwan Date: Sun, 11 May 2025 01:20:39 +0530 Subject: [PATCH 3/7] v 2.8 ( get_products_for_supplier ) --- warehouse_managment/product/urls.py | 4 ++++ warehouse_managment/product/views.py | 20 +++++++++++++++++++- 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/warehouse_managment/product/urls.py b/warehouse_managment/product/urls.py index 2b26d7a..0db8384 100644 --- a/warehouse_managment/product/urls.py +++ b/warehouse_managment/product/urls.py @@ -9,6 +9,7 @@ update_supplier_product, product_stock_summary, get_suppliers_for_product, + get_products_for_supplier ) urlpatterns = [ @@ -32,4 +33,7 @@ # GET SupplierIds for a product Id path('suppliers-by-product', get_suppliers_for_product, name='get-suppliers-for-product'), + + # GET Product Ids for a supplier ID + path('products-by-supplier', get_products_for_supplier, name='get-products-for-supplier'), ] diff --git a/warehouse_managment/product/views.py b/warehouse_managment/product/views.py index 3e299cc..f9195a0 100644 --- a/warehouse_managment/product/views.py +++ b/warehouse_managment/product/views.py @@ -114,4 +114,22 @@ def get_suppliers_for_product(request): "supplier_ids": list(supplier_ids) }) - \ No newline at end of file + + +@api_view(['GET']) +def get_products_for_supplier(request): + supplier_id = request.query_params.get('supplier_id') + if not supplier_id: + return Response({"error": "supplier_id is required"}, status=400) + + product_ids = ( + SupplierProduct.objects + .filter(supplier_id=supplier_id) + .values_list('product_id', flat=True) + .distinct() + ) + + return Response({ + "supplier_id": int(supplier_id), + "product_ids": list(product_ids) + }) \ No newline at end of file From adf0a58a95084d339a31c12d6f162e3e348eddfc Mon Sep 17 00:00:00 2001 From: Deepthi Damruwan Date: Sun, 11 May 2025 02:19:12 +0530 Subject: [PATCH 4/7] v 2.9 --- warehouse_managment/warehouse/views.py | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/warehouse_managment/warehouse/views.py b/warehouse_managment/warehouse/views.py index ebba245..7978f68 100644 --- a/warehouse_managment/warehouse/views.py +++ b/warehouse_managment/warehouse/views.py @@ -280,14 +280,13 @@ def get_supplier_product_prices(request): summary = [] for sp in supplier_products: warehouse_names = ( - WarehouseInventory.objects - .filter( - warehouse_id__in=connected_warehouses, - product_id=sp.product_id - ) - .select_related('warehouse') - .values_list('warehouse__warehouse_name', flat=True) - .distinct() + Warehouse.objects + .filter( + id__in=WarehouseSupplier.objects.filter(supplier_id=supplier_id) + .values_list('warehouse_id', flat=True) + ) + .values_list('warehouse_name', flat=True) + .distinct() ) summary.append({ From f1a6d12e5eaba9f206b623a16be612af27f8fd73 Mon Sep 17 00:00:00 2001 From: Deepthi Damruwan Date: Sun, 11 May 2025 02:24:15 +0530 Subject: [PATCH 5/7] v 2.10 --- warehouse_managment/product/views.py | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/warehouse_managment/product/views.py b/warehouse_managment/product/views.py index f9195a0..5a1084a 100644 --- a/warehouse_managment/product/views.py +++ b/warehouse_managment/product/views.py @@ -122,14 +122,19 @@ def get_products_for_supplier(request): if not supplier_id: return Response({"error": "supplier_id is required"}, status=400) - product_ids = ( + products = ( SupplierProduct.objects .filter(supplier_id=supplier_id) - .values_list('product_id', flat=True) + .values('product_id', 'supplier_price') .distinct() ) return Response({ "supplier_id": int(supplier_id), - "product_ids": list(product_ids) + "products": [ + { + "product_id": item["product_id"], + "supplier_price": float(item["supplier_price"]) + } for item in products + ] }) \ No newline at end of file From 1be7e65d8f310b4a80aa43ccd1fc6f0efe1d5ac2 Mon Sep 17 00:00:00 2001 From: Deepthi Damruwan Date: Fri, 16 May 2025 14:18:34 +0530 Subject: [PATCH 6/7] Models updated, Product Views updated --- warehouse_managment/product/admin.py | 7 +-- .../management/commands/populate_all_data.py | 58 +++++++++---------- .../migrations/0003_delete_supplierproduct.py | 16 +++++ warehouse_managment/product/models.py | 12 ---- warehouse_managment/product/serializers.py | 11 +--- warehouse_managment/product/urls.py | 3 +- warehouse_managment/product/views.py | 33 +++++++---- warehouse_managment/warehouse/admin.py | 12 ++-- ...upplierproduct_delete_warehousesupplier.py | 35 +++++++++++ warehouse_managment/warehouse/models.py | 19 ++++-- warehouse_managment/warehouse/serializers.py | 13 +++-- warehouse_managment/warehouse/views.py | 4 +- .../warehouse_managment/settings.py | 35 ++++++----- 13 files changed, 149 insertions(+), 109 deletions(-) create mode 100644 warehouse_managment/product/migrations/0003_delete_supplierproduct.py create mode 100644 warehouse_managment/warehouse/migrations/0004_supplierproduct_delete_warehousesupplier.py diff --git a/warehouse_managment/product/admin.py b/warehouse_managment/product/admin.py index 5700e13..6f63911 100644 --- a/warehouse_managment/product/admin.py +++ b/warehouse_managment/product/admin.py @@ -1,5 +1,5 @@ from django.contrib import admin -from .models import ProductCategory, Product, SupplierProduct +from .models import ProductCategory, Product @admin.register(ProductCategory) class ProductCategoryAdmin(admin.ModelAdmin): @@ -11,8 +11,3 @@ class ProductAdmin(admin.ModelAdmin): list_display = ('id', 'product_name', 'unit_price', 'category', 'created_at', 'updated_at') search_fields = ('product_name',) list_filter = ('category',) - -@admin.register(SupplierProduct) -class SupplierProductAdmin(admin.ModelAdmin): - list_display = ('id', 'supplier_id', 'product', 'maximum_capacity', 'supplier_price', 'lead_time_days') - list_filter = ('supplier_id',) diff --git a/warehouse_managment/product/management/commands/populate_all_data.py b/warehouse_managment/product/management/commands/populate_all_data.py index b6b69bf..48e0978 100644 --- a/warehouse_managment/product/management/commands/populate_all_data.py +++ b/warehouse_managment/product/management/commands/populate_all_data.py @@ -1,25 +1,23 @@ from django.core.management.base import BaseCommand -from product.models import ProductCategory, Product, SupplierProduct -from warehouse.models import Warehouse, WarehouseInventory, InventoryTransaction, WarehouseSupplier +from product.models import ProductCategory, Product +from warehouse.models import Warehouse, WarehouseInventory, InventoryTransaction, SupplierProduct from decimal import Decimal from django.utils import timezone import random from datetime import timedelta - class Command(BaseCommand): help = 'Delete old data and populate categories, products, suppliers, warehouses, and inventory' def handle(self, *args, **kwargs): self.stdout.write("🧹 Deleting existing data...") - # InventoryTransaction.objects.all().delete() - # WarehouseInventory.objects.all().delete() - # SupplierProduct.objects.all().delete() - # Product.objects.all().delete() - # ProductCategory.objects.all().delete() - # WarehouseSupplier.objects.all().delete() - # Warehouse.objects.all().delete() + InventoryTransaction.objects.all().delete() + WarehouseInventory.objects.all().delete() + SupplierProduct.objects.all().delete() + Product.objects.all().delete() + ProductCategory.objects.all().delete() + Warehouse.objects.all().delete() self.stdout.write("🧪 Populating new data...") @@ -40,12 +38,12 @@ def handle(self, *args, **kwargs): product = Product.objects.create( product_SKU=f"SKU{i + 1:03}", product_name=f"{category.category_name} Product {i + 1}", - unit_price=round(random.uniform(100, 2000), 2), + unit_price=round(Decimal(random.uniform(100, 2000)), 2), category=category ) products.append(product) - # Warehouses (Randomly assigning warehouses to suppliers) + # Warehouses warehouse_data = [ ("Colombo Central", "6.9271° N", "79.8612° E"), ("Kandy Depot", "7.2906° N", "80.6337° E"), @@ -61,37 +59,32 @@ def handle(self, *args, **kwargs): ) warehouses.append(warehouse) - # SupplierProduct, WarehouseInventory, InventoryTransaction, WarehouseSupplier - created_pairs = set() + # SupplierProduct, WarehouseInventory, InventoryTransaction + created_inventories = set() for product in products: - # Randomly assign suppliers (not for all suppliers) - suppliers = random.sample([101, 102, 103], k=random.randint(1, 3)) # Randomly pick 1 to 3 suppliers + # Random suppliers + suppliers = random.sample([101, 102, 103], k=random.randint(1, 3)) for supplier_id in suppliers: - # SupplierProduct (Randomly create it for some suppliers) + warehouse = random.choice(warehouses) + + # SupplierProduct if random.choice([True, False]): max_capacity = random.randint(300000, 600000) lead_time = random.randint(3, 10) SupplierProduct.objects.create( supplier_id=supplier_id, product=product, + warehouse=warehouse, maximum_capacity=max_capacity, - supplier_price=round(random.uniform(80, 1500), 2), + supplier_price=round(Decimal(random.uniform(80, 1500)), 2), lead_time_days=lead_time ) - - # WarehouseSupplier (Randomly assign warehouses for this supplier) - warehouse = random.choice(warehouses) # Randomly pick one warehouse for this supplier - if (warehouse.id, supplier_id) not in created_pairs: - WarehouseSupplier.objects.create( - warehouse=warehouse, - supplier_id=supplier_id - ) - created_pairs.add((warehouse.id, supplier_id)) - # Inventory - ensure unique product_id and warehouse_id combination - if not WarehouseInventory.objects.filter(warehouse=warehouse, product=product).exists(): - quantity = Decimal(random.uniform(100000, 400000)) + # WarehouseInventory + key = (warehouse.id, product.id) + if key not in created_inventories: + quantity = round(Decimal(random.uniform(100000, 400000)), 2) last_restocked = timezone.now() - timedelta(days=random.randint(1, 60)) inventory = WarehouseInventory.objects.create( @@ -101,10 +94,11 @@ def handle(self, *args, **kwargs): last_restocked=last_restocked, minimum_stock_level=Decimal("100000.00") ) + created_inventories.add(key) # Transactions for _ in range(random.randint(1, 2)): - qty_in = Decimal(random.uniform(10000, 50000)) + qty_in = round(Decimal(random.uniform(10000, 50000)), 2) InventoryTransaction.objects.create( inventory=inventory, transaction_type='INCOMING', @@ -115,7 +109,7 @@ def handle(self, *args, **kwargs): ) if random.choice([True, False]): - qty_out = Decimal(random.uniform(5000, 20000)) + qty_out = round(Decimal(random.uniform(5000, 20000)), 2) InventoryTransaction.objects.create( inventory=inventory, transaction_type='OUTGOING', diff --git a/warehouse_managment/product/migrations/0003_delete_supplierproduct.py b/warehouse_managment/product/migrations/0003_delete_supplierproduct.py new file mode 100644 index 0000000..d875575 --- /dev/null +++ b/warehouse_managment/product/migrations/0003_delete_supplierproduct.py @@ -0,0 +1,16 @@ +# Generated by Django 5.2 on 2025-05-16 07:39 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('product', '0002_product_product_sku'), + ] + + operations = [ + migrations.DeleteModel( + name='SupplierProduct', + ), + ] diff --git a/warehouse_managment/product/models.py b/warehouse_managment/product/models.py index 38f0a3d..cb5b8fd 100644 --- a/warehouse_managment/product/models.py +++ b/warehouse_managment/product/models.py @@ -17,15 +17,3 @@ class Product(models.Model): class Meta: db_table = 'product' -class SupplierProduct(models.Model): - supplier_id = models.IntegerField() - product = models.ForeignKey(Product, on_delete=models.CASCADE) - maximum_capacity = models.IntegerField() - supplier_price = models.DecimalField(max_digits=10, decimal_places=2) - lead_time_days = models.IntegerField(blank=True, null=True) - created_at = models.DateTimeField(auto_now_add=True) - - class Meta: - db_table = 'supplier_product' - unique_together = (('supplier_id', 'product'),) - diff --git a/warehouse_managment/product/serializers.py b/warehouse_managment/product/serializers.py index 8d4f8ea..47290c9 100644 --- a/warehouse_managment/product/serializers.py +++ b/warehouse_managment/product/serializers.py @@ -1,5 +1,5 @@ from rest_framework import serializers -from .models import ProductCategory, Product, SupplierProduct +from .models import ProductCategory, Product class ProductCategorySerializer(serializers.ModelSerializer): class Meta: @@ -11,11 +11,6 @@ class Meta: model = Product fields = '__all__' -class SupplierProductSerializer(serializers.ModelSerializer): - class Meta: - model = SupplierProduct - fields = '__all__' - class ProductCategorySerializer(serializers.ModelSerializer): class Meta: model = ProductCategory @@ -26,7 +21,3 @@ class Meta: model = Product fields = '__all__' -class SupplierProductSerializer(serializers.ModelSerializer): - class Meta: - model = SupplierProduct - fields = '__all__' diff --git a/warehouse_managment/product/urls.py b/warehouse_managment/product/urls.py index 0db8384..12fbd2e 100644 --- a/warehouse_managment/product/urls.py +++ b/warehouse_managment/product/urls.py @@ -25,7 +25,8 @@ # Supplier product endpoints path('supplier-products/', supplier_product_list, name='supplier-product-list'), - + + # Change the Supplier's maximum capacity to a new value path('supplier-products/update/', update_supplier_product, name='update-supplier-product'), # Product count endpoint diff --git a/warehouse_managment/product/views.py b/warehouse_managment/product/views.py index 5a1084a..e7d6160 100644 --- a/warehouse_managment/product/views.py +++ b/warehouse_managment/product/views.py @@ -1,10 +1,11 @@ from rest_framework.decorators import api_view from rest_framework.response import Response from rest_framework import status -from .models import ProductCategory, Product, SupplierProduct -from .serializers import ProductCategorySerializer, ProductSerializer, SupplierProductSerializer +from .models import ProductCategory, Product +from .serializers import ProductCategorySerializer, ProductSerializer +from warehouse.serializers import SupplierProductSerializer from django.db.models import Sum -from warehouse.models import WarehouseInventory +from warehouse.models import WarehouseInventory, SupplierProduct @api_view(['GET']) def root(request): @@ -58,25 +59,35 @@ def supplier_product_list(request): @api_view(['POST']) def update_supplier_product(request): + supplier_id = request.data.get('supplier_id') + product_id = request.data.get('product_id') + warehouse_id = request.data.get('warehouse_id') + new_capacity = request.data.get('maximum_capacity') - supplier_id = request.query_params.get('supplier_id') - product_id = request.query_params.get('product_id') - new_capacity = request.query_params.get('maximum_capacity') - - if not all([supplier_id, product_id, new_capacity]): + if not all([supplier_id, product_id, warehouse_id, new_capacity]): return Response({"error": "Missing fields"}, status=400) + if not WarehouseInventory.objects.filter(product_id=product_id, warehouse_id=warehouse_id).exists(): + return Response( + {"error": "This product is not currently stocked in the given warehouse."}, + status=400 + ) + try: - sp = SupplierProduct.objects.get(supplier_id=supplier_id, product_id=product_id) + sp = SupplierProduct.objects.get( + supplier_id=supplier_id, + product_id=product_id, + warehouse_id=warehouse_id + ) sp.maximum_capacity = new_capacity sp.save() return Response({"status": "success"}, status=200) except SupplierProduct.DoesNotExist: return Response({"error": "SupplierProduct not found"}, status=404) - + + @api_view(['GET']) def product_stock_summary(request, sku_code): - # Optional: Validate SKU format if needed if not sku_code.startswith("SKU") or not sku_code[3:].isdigit(): return Response({'error': 'Invalid SKU format'}, status=400) diff --git a/warehouse_managment/warehouse/admin.py b/warehouse_managment/warehouse/admin.py index faea785..5e98df2 100644 --- a/warehouse_managment/warehouse/admin.py +++ b/warehouse_managment/warehouse/admin.py @@ -1,5 +1,5 @@ from django.contrib import admin -from .models import Warehouse, WarehouseInventory, InventoryTransaction, WarehouseSupplier +from .models import Warehouse, WarehouseInventory, InventoryTransaction, SupplierProduct @admin.register(Warehouse) class WarehouseAdmin(admin.ModelAdmin): @@ -15,7 +15,9 @@ class InventoryTransactionAdmin(admin.ModelAdmin): list_display = ('id', 'inventory', 'transaction_type', 'quantity_change', 'created_at', 'created_by') list_filter = ('transaction_type', 'created_by') -@admin.register(WarehouseSupplier) -class WarehouseSupplierAdmin(admin.ModelAdmin): - list_display = ('id', 'warehouse', 'supplier_id') - list_filter = ('warehouse',) +@admin.register(SupplierProduct) +class SupplierProductAdmin(admin.ModelAdmin): + list_display = ('id', 'supplier_id', 'product', 'warehouse', 'maximum_capacity', 'supplier_price', 'lead_time_days') + list_filter = ('warehouse', 'supplier_id') + search_fields = ('supplier_id', 'product__product_name') + \ No newline at end of file diff --git a/warehouse_managment/warehouse/migrations/0004_supplierproduct_delete_warehousesupplier.py b/warehouse_managment/warehouse/migrations/0004_supplierproduct_delete_warehousesupplier.py new file mode 100644 index 0000000..a1965eb --- /dev/null +++ b/warehouse_managment/warehouse/migrations/0004_supplierproduct_delete_warehousesupplier.py @@ -0,0 +1,35 @@ +# Generated by Django 5.2 on 2025-05-16 07:39 + +import django.db.models.deletion +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('product', '0003_delete_supplierproduct'), + ('warehouse', '0003_remove_warehouseinventory_supplier_id_and_more'), + ] + + operations = [ + migrations.CreateModel( + name='SupplierProduct', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('supplier_id', models.IntegerField()), + ('maximum_capacity', models.IntegerField()), + ('supplier_price', models.DecimalField(decimal_places=2, max_digits=10)), + ('lead_time_days', models.IntegerField(blank=True, null=True)), + ('created_at', models.DateTimeField(auto_now_add=True)), + ('product', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='product.product')), + ('warehouse', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='warehouse.warehouse')), + ], + options={ + 'db_table': 'supplier_product', + 'unique_together': {('supplier_id', 'product', 'warehouse')}, + }, + ), + migrations.DeleteModel( + name='WarehouseSupplier', + ), + ] diff --git a/warehouse_managment/warehouse/models.py b/warehouse_managment/warehouse/models.py index afae8e2..4b6d31f 100644 --- a/warehouse_managment/warehouse/models.py +++ b/warehouse_managment/warehouse/models.py @@ -45,12 +45,19 @@ class InventoryTransaction(models.Model): created_by = models.CharField(max_length=100) class Meta: db_table = 'inventory_transactions' - -class WarehouseSupplier(models.Model): - warehouse = models.ForeignKey(Warehouse, on_delete=models.CASCADE) + + +class SupplierProduct(models.Model): supplier_id = models.IntegerField() + product = models.ForeignKey(Product, on_delete=models.CASCADE) + warehouse = models.ForeignKey(Warehouse, on_delete=models.CASCADE) + maximum_capacity = models.IntegerField() + supplier_price = models.DecimalField(max_digits=10, decimal_places=2) + lead_time_days = models.IntegerField(blank=True, null=True) + created_at = models.DateTimeField(auto_now_add=True) class Meta: - db_table = 'warehouse_supplier' - unique_together = (('warehouse', 'supplier_id'),) - + db_table = 'supplier_product' + unique_together = (('supplier_id', 'product', 'warehouse'),) + + diff --git a/warehouse_managment/warehouse/serializers.py b/warehouse_managment/warehouse/serializers.py index bdad607..76c1f27 100644 --- a/warehouse_managment/warehouse/serializers.py +++ b/warehouse_managment/warehouse/serializers.py @@ -1,5 +1,5 @@ from rest_framework import serializers -from .models import Warehouse, WarehouseInventory, InventoryTransaction, WarehouseSupplier +from .models import Warehouse, WarehouseInventory, InventoryTransaction, SupplierProduct class WarehouseSerializer(serializers.ModelSerializer): class Meta: @@ -11,12 +11,13 @@ class Meta: model = WarehouseInventory fields = '__all__' +class SupplierProductSerializer(serializers.ModelSerializer): + class Meta: + model = SupplierProduct + fields = '__all__' + class InventoryTransactionSerializer(serializers.ModelSerializer): class Meta: model = InventoryTransaction fields = '__all__' - -class WarehouseSupplierSerializer(serializers.ModelSerializer): - class Meta: - model = WarehouseSupplier - fields = ['id', 'name', 'location'] + \ No newline at end of file diff --git a/warehouse_managment/warehouse/views.py b/warehouse_managment/warehouse/views.py index 7978f68..d3efbbf 100644 --- a/warehouse_managment/warehouse/views.py +++ b/warehouse_managment/warehouse/views.py @@ -5,10 +5,10 @@ from django.utils import timezone from decimal import Decimal from collections import defaultdict -from product.models import Product, SupplierProduct, ProductCategory +from product.models import Product, ProductCategory from django.db.models import Sum, F from django.db import transaction -from .models import Warehouse, WarehouseInventory, InventoryTransaction, WarehouseSupplier +from .models import Warehouse, WarehouseInventory, InventoryTransaction, SupplierProduct from .utils.supplier_names import SUPPLIER_NAME_MAP from .utils.mock_orders import ORDERS from .utils.order_accept_Req import ORDER_REQUEST diff --git a/warehouse_managment/warehouse_managment/settings.py b/warehouse_managment/warehouse_managment/settings.py index 3c09ada..0a10eef 100644 --- a/warehouse_managment/warehouse_managment/settings.py +++ b/warehouse_managment/warehouse_managment/settings.py @@ -90,28 +90,27 @@ # Database configuration -DATABASES = { - 'default': dj_database_url.config( - default=os.getenv('DATABASE_URL'), - conn_max_age=600, - conn_health_checks=True, - ) -} - - - # DATABASES = { -# 'default': { -# 'ENGINE': 'django.db.backends.postgresql', -# 'NAME': os.getenv('DB_NAME', 'test_db'), -# 'USER': os.getenv('DB_USER', 'postgres'), -# 'PASSWORD': os.getenv('DB_PASSWORD', 'postgres'), -# 'HOST': os.getenv('DB_HOST', 'localhost'), -# 'PORT': os.getenv('DB_PORT', '5432'), -# } +# 'default': dj_database_url.config( +# default=os.getenv('DATABASE_URL'), +# conn_max_age=600, +# conn_health_checks=True, +# ) # } + +DATABASES = { + 'default': { + 'ENGINE': 'django.db.backends.postgresql', + 'NAME': os.getenv('DB_NAME', 'test_db'), + 'USER': os.getenv('DB_USER', 'postgres'), + 'PASSWORD': os.getenv('DB_PASSWORD', 'postgres'), + 'HOST': os.getenv('DB_HOST', 'localhost'), + 'PORT': os.getenv('DB_PORT', '5432'), + } +} + # Password validation # https://docs.djangoproject.com/en/5.2/ref/settings/#auth-password-validators From 1204fbd1e155963dc05ea55a42d6d51c2d59d13e Mon Sep 17 00:00:00 2001 From: Deepthi Damruwan Date: Fri, 16 May 2025 16:55:02 +0530 Subject: [PATCH 7/7] View updated according to new models --- warehouse_managment/warehouse/urls.py | 3 +- warehouse_managment/warehouse/views.py | 55 ++++++++++---------------- 2 files changed, 22 insertions(+), 36 deletions(-) diff --git a/warehouse_managment/warehouse/urls.py b/warehouse_managment/warehouse/urls.py index 2524c24..dfb0d6c 100644 --- a/warehouse_managment/warehouse/urls.py +++ b/warehouse_managment/warehouse/urls.py @@ -44,7 +44,8 @@ # POST endpoint to accept or reject an order request and update inventory path('order/handle/', handle_order_status, name='handle_order_status'), - # POST endpoint to add or update a supplier product + + # POST endpoint to add a supplier product enrty or update an existing one with supplier_price, lead_time_days or maximum_stock path("/supplier-product/add_or_update/", add_supplier_product, name="update_supplier_product"), # GET endpoint to get supplier product prices diff --git a/warehouse_managment/warehouse/views.py b/warehouse_managment/warehouse/views.py index d3efbbf..58a90f5 100644 --- a/warehouse_managment/warehouse/views.py +++ b/warehouse_managment/warehouse/views.py @@ -35,7 +35,7 @@ def warehouse_inventory_list(request): except Warehouse.DoesNotExist: return Response({"error": "Warehouse not found"}, status=404) - supplier_ids = WarehouseSupplier.objects.filter(warehouse_id=warehouse_id).values_list('supplier_id', flat=True) + supplier_ids = SupplierProduct.objects.filter(warehouse_id=warehouse_id).values_list('supplier_id', flat=True) inventory_qs = WarehouseInventory.objects.filter(warehouse_id=warehouse_id).select_related('product', 'product__category') supplier_products = SupplierProduct.objects.filter( @@ -105,7 +105,7 @@ def supplier_dashboard(request): if not supplier_id: return Response({"error": "supplier_id required"}, status=400) - warehouses = WarehouseSupplier.objects.filter(supplier_id=supplier_id).values_list('warehouse_id', flat=True) + warehouses = SupplierProduct.objects.filter(supplier_id=supplier_id).values_list('warehouse_id', flat=True) inventories = ( WarehouseInventory.objects @@ -225,7 +225,7 @@ def mark_delivery_received(request): @api_view(['GET']) def get_supplier_products(request, supplier_id): - warehouse_ids = WarehouseSupplier.objects.filter(supplier_id=supplier_id).values_list('warehouse_id', flat=True) + warehouse_ids = SupplierProduct.objects.filter(supplier_id=supplier_id).values_list('warehouse_id', flat=True) inventory_qs = WarehouseInventory.objects.filter(warehouse_id__in=warehouse_ids) @@ -263,43 +263,29 @@ def get_supplier_product_prices(request): if not supplier_id: return Response({"error": "supplier_id required"}, status=400) - connected_warehouses = WarehouseSupplier.objects.filter( - supplier_id=supplier_id - ).values_list('warehouse_id', flat=True) - supplier_products = ( SupplierProduct.objects .filter(supplier_id=supplier_id) - .select_related('product') + .select_related('product', 'warehouse') .annotate( product_name=F('product__product_name'), SKU=F('product__product_SKU'), + warehouse_name=F('warehouse__warehouse_name') ) ) summary = [] for sp in supplier_products: - warehouse_names = ( - Warehouse.objects - .filter( - id__in=WarehouseSupplier.objects.filter(supplier_id=supplier_id) - .values_list('warehouse_id', flat=True) - ) - .values_list('warehouse_name', flat=True) - .distinct() - ) - summary.append({ - "product_name": sp.product.product_name, - "SKU": sp.product.product_SKU, + "product_name": sp.product_name, + "SKU": sp.SKU, "supplier_price": float(sp.supplier_price), - "warehouses": list(warehouse_names), + "warehouses": [sp.warehouse_name], # one warehouse per SupplierProduct row }) return Response(summary) - @api_view(['GET']) def get_suppliers_by_category(request): category_name = request.query_params.get('category') @@ -559,33 +545,28 @@ def add_supplier_product(request): supplier_id = data.get("supplier_id") product_id = data.get("product_id") supplier_price = data.get("supplier_price") + maximum_capacity = data.get("maximum_capacity", 0) + lead_time_days = data.get("lead_time_days", 5) if not all([warehouse_id, supplier_id, product_id, supplier_price]): return Response({"error": "Missing fields"}, status=status.HTTP_400_BAD_REQUEST) - ws_exists = WarehouseSupplier.objects.filter( - warehouse_id=warehouse_id, - supplier_id=supplier_id - ).exists() - - if not ws_exists: - WarehouseSupplier.objects.create( - warehouse_id=warehouse_id, - supplier_id=supplier_id - ) sp, created = SupplierProduct.objects.get_or_create( supplier_id=supplier_id, product_id=product_id, + warehouse_id=warehouse_id, defaults={ "supplier_price": Decimal(supplier_price), - "maximum_capacity": Decimal("0.00"), # default - "lead_time_days": 5 # default + "maximum_capacity": maximum_capacity, + "lead_time_days": lead_time_days } ) if not created: sp.supplier_price = Decimal(supplier_price) + sp.maximum_capacity = maximum_capacity + sp.lead_time_days = lead_time_days sp.save() message = "SupplierProduct updated with new price." else: @@ -594,4 +575,8 @@ def add_supplier_product(request): return Response({ "supplier_product_id": sp.id, "message": message - }, status=status.HTTP_200_OK) \ No newline at end of file + }, status=status.HTTP_200_OK) + + + + \ No newline at end of file