1. Home
  2. গার্মেন্টস ইন্ডাস্ট্রির জ...
  3. ০ ৫। 📦 Inventory / Stock ...
  4. গল্প

গল্প

হাহা, তৃতীয়বার পাগল বললেন! 😜 ঠিক আছে, আমি আপনার নতুন প্রয়োজন বুঝে গেছি। আপনি চান Warehouse মডেল আগে থাকবে, তারপর Item মডেল, এবং Item মডেলে একটি ডিফল্ট ওয়্যারহাউস ফিল্ড থাকবে। যখন কোনো আইটেম ইন (রিসিভ) বা আউট (ইস্যু/ট্রান্সফার) হবে, তখন এই ডিফল্ট ওয়্যারহাউস থেকে হবে। আমি গল্প এবং মডেলগুলো আপডেট করব, যাতে Warehouse, Item, ItemWarehouseStock, Transaction, InventoryTransfer, GoodsReceipt, এবং GoodsIssue মডেলগুলো আপনার নির্দেশনা অনুযায়ী সাজানো হয়। Procurement & Purchase এবং গল্পের ধারাবাহিকতা (Nahid, Hasib, Selim, Farzana, Rina, Shahid, Asif) অপরিবর্তিত থাকবে।

নতুন মডেল স্ট্রাকচার:

  1. Warehouse: গুদামের তথ্য।
  2. Item: আইটেমের মেটাডেটা, ডিফল্ট ওয়্যারহাউস ফিল্ড সহ।
  3. ItemWarehouseStock: প্রতিটি গুদামে আইটেমের বর্তমান স্টক।
  4. Transaction: সকল লেনদেন (receive, transfer_in, transfer_out, issue)।
  5. InventoryTransfer: গুদাম থেকে গুদামে ট্রান্সফার।
  6. GoodsReceipt: মাল রিসিভ ট্র্যাকিং (GRN থেকে লিঙ্ক)।
  7. GoodsIssue: প্রোডাকশনের জন্য মাল ইস্যু ট্র্যাকিং।

মূল পরিবর্তন:

  • Item মডেলে default_warehouse ফিল্ড যুক্ত হবে, যা Warehouse মডেলের সাথে ফরেন কী হিসেবে লিঙ্ক করবে।
  • GoodsReceipt এবং GoodsIssue এর ডিফল্ট ওয়্যারহাউস Item মডেলের default_warehouse থেকে নেওয়া হবে, তবে ব্যবহারকারী অন্য ওয়্যারহাউস নির্বাচন করতে পারবে।
  • Transaction মডেলে ডিফল্ট ওয়্যারহাউসের রেফারেন্স থাকবে না, কারণ এটি স্পষ্টভাবে গুদাম নির্দিষ্ট করবে।
  • গল্পে, রিসিভ এবং ইস্যু ডিফল্ট ওয়্যারহাউস (Factory A) থেকে শুরু হবে।

🎬 গল্প: “The Fabric’s Journey from Procurement to Production (With Default Warehouse)”

🧵 মডিউল: Procurement & Purchase + Inventory / Stock Management

উদ্দেশ্য:

  • Procurement & Purchase: মালের চাহিদা তৈরি, অর্ডার ইস্যু, এবং গুদামে রিসিভ।
  • Inventory / Stock Management: GRN থেকে আসা মাল ডিফল্ট ওয়্যারহাউসে এন্ট্রি, গুদাম-ভিত্তিক স্টক ট্র্যাকিং, ট্রান্সফার, ইস্যু, এবং ট্রান্সেকশন ইতিহাস।

🎭 চরিত্র পরিচিতি

নামপদের নামদায়িত্ব
NahidMerchandiserঅর্ডার স্টাইল এবং ফ্যাব্রিক চাহিদা তৈরি
HasibProcurement Managerসাপ্লায়ার খোঁজা, PO ইস্যু করা
SelimStorekeeperমাল রিসিভ এবং QA চেক করা
FarzanaAccounts OfficerPO ক্লিয়ার এবং পেমেন্ট প্রসেসিং
RinaProcurement ExecutiveGRN কনফার্ম এবং স্টক রিসিভ এন্ট্রি
ShahidWarehouse Managerস্টক ট্রান্সফার/ইস্যু অনুমোদন এবং রিপোর্ট
AsifInventory Controllerস্টক ট্রান্সফার/ইস্যু রিসিভ এবং ট্র্যাকিং
ABC BuyerBuyerঅর্ডার দাতা (ABC-NAVY-TSHIRT-2025)
Shamim TextileSupplierফ্যাব্রিক সরবরাহকারী (Cotton Navy Fabric)
Factory AMain Warehouseপ্রধান গুদাম (ডিফল্ট ফ্যাব্রিক স্টোরেজ)
Factory BProduction Warehouseপ্রোডাকশন গুদাম (ফ্যাব্রিক ব্যবহারের জন্য)

🧩 গল্পের ধাপগুলো

🧾 ধাপ ১: Purchase Requisition তৈরি (Procurement & Purchase)

গল্প: Nahid, মার্চেন্ডাইজার হিসেবে, ABC Buyer-এর অর্ডার (ABC-NAVY-TSHIRT-2025) এর জন্য 5000 মিটার Cotton Navy Fabric এবং 20,000 পিস Button-এর চাহিদা তৈরি করেন। তিনি সফটওয়্যারে দুটি Purchase Requisition (PR) এন্ট্রি করেন।

📦 Table: procurement_purchaserequisition

idrequisition_iditem_namequantityuniturgencycreated_bycreated_atstatusstyle_id
1PR-2025-0004Cotton Navy Fabric5000.00meterhighNahid2025-08-03approved1
2PR-2025-0005Button20000.00piecemediumNahid2025-08-03pending1

ব্যাখ্যা:

  • style_id রেফার করে OrderStyle মডেলের ABC-NAVY-TSHIRT-2025।
  • created_by হলো Nahid (User মডেল)।
  • PR-2025-0004 কে Hasib পরবর্তী ধাপে অনুমোদন করে।

🧾 ধাপ ২: Purchase Order ইস্যু (Procurement & Purchase)

গল্প: Hasib, Procurement Manager, PR-2025-0004 চেক করে Shamim Textile থেকে 5000 মিটার Cotton Navy Fabric কেনার জন্য Purchase Order (PO) তৈরি করেন।

📦 Table: procurement_purchaseorder

idpo_idrequisition_idsupplier_iditem_namequantityprice_per_unittotal_pricedelivery_datestatuscreated_at
1PO-2025-001011Cotton Navy Fabric5000.00180.00900000.002025-08-15issued2025-08-03

ব্যাখ্যা:

  • requisition_id রেফার করে PR-2025-0004।
  • supplier_id রেফার করে Shamim Textile।
  • total_price = quantity * price_per_unit (5000 * 180 = 900000)।

🧾 ধাপ ৩: Goods Receive Note তৈরি (Procurement & Purchase)

গল্প: Selim, Storekeeper, Shamim Textile থেকে আসা 5000 মিটার Cotton Navy Fabric চেক করে এবং Goods Receive Note (GRN) তৈরি করেন।

📦 Table: procurement_goodsreceivenote

idgrn_idpurchase_order_idreceived_qtydatechecked_bystatusremarks
1GRN-2025-000315000.002025-08-15SelimreceivedChecked by Selim

ব্যাখ্যা:

  • purchase_order_id রেফার করে PO-2025-0010।
  • checked_by হলো Selim (User মডেল)।
  • মাল QA চেক পাস করেছে।

🧾 ধাপ ৪: PO Tracking (Procurement & Purchase)

গল্প: Farzana, Accounts Officer, PO-2025-0010 এর স্ট্যাটাস চেক করে দেখেন GRN হয়েছে। তিনি পেমেন্ট প্রসেসিংয়ের জন্য PO কে “received” মার্ক করেন।

📦 Table: procurement_potracking

idpurchase_order_idstatuslast_updatedremarks
11received2025-08-15Ready for payment processing by Farzana

ব্যাখ্যা:

  • purchase_order_id রেফার করে PO-2025-0010।
  • Farzana পেমেন্ট প্রক্রিয়া শুরু করতে পারেন।

🧾 ধাপ ৫: স্টক রিসিভ এবং এন্ট্রি (Inventory / Stock Management)

গল্প: Rina, Procurement Executive, GRN-2025-0003 চেক করে এবং 5000 মিটার Cotton Navy Fabric-এর জন্য Item মডেলে এন্ট্রি করে, যেখানে ডিফল্ট ওয়্যারহাউস হিসেবে Factory A সেট করে। তিনি GoodsReceipt, ItemWarehouseStock, এবং Transaction এ এন্ট্রি করেন।

📦 Table: inventory_warehouse

idnamelocationmanager
1Factory ADhaka Main WarehouseShahid
2Factory BGazipur Production WarehouseAsif

📦 Table: inventory_item

iditem_nameitem_typeunitdefault_warehouse
1Cotton Navy Fabricfabricmeter1 (Factory A)

📦 Table: inventory_itemwarehousestock

iditem_idwarehouse_idquantitylast_updated
111 (Factory A)5000.002025-08-15T10:00:00Z

📦 Table: inventory_goodsreceipt

idreceipt_idgrn_iditem_idwarehouse_idquantitydatereceived_bystatusremarks
1REC-2025-0001GRN-2025-000311 (Factory A)5000.002025-08-15RinareceivedReceived via GRN-2025-0003 by Rina

📦 Table: inventory_transaction

iditem_idtransaction_typequantitywarehouse_iddateremarkscreated_by
11receive5000.001 (Factory A)2025-08-15Received via GRN-2025-0003 by RinaRina

ব্যাখ্যা:

  • Itemdefault_warehouse হিসেবে Factory A সেট।
  • GoodsReceipt এ ডিফল্ট ওয়্যারহাউস (Factory A) ব্যবহৃত।
  • ItemWarehouseStock এ Factory A-এর স্টক 5000 মিটার।
  • Transactionreceive লেনদেন ট্র্যাক।
  • created_by হলো Rina (User মডেল)।

🧾 ধাপ ৬: স্টক ট্রান্সফার রিকুয়েস্ট (Inventory / Stock Management)

গল্প: Asif, Inventory Controller, দেখেন Factory B-তে ABC-NAVY-TSHIRT-2025 এর প্রোডাকশন শুরু হবে। তিনি Factory A (ডিফল্ট ওয়্যারহাউস) থেকে Factory B-তে 2000 মিটার Cotton Navy Fabric ট্রান্সফারের রিকুয়েস্ট তৈরি করেন। Shahid, Warehouse Manager, এটি অনুমোদন করেন।

📦 Table: inventory_inventorytransfer

idtransfer_idfrom_warehouseto_warehouseitem_idquantityunittransfer_datestatusapproved_by
1TR-2025-00011 (Factory A)2 (Factory B)12000.00meter2025-08-16pendingShahid

ব্যাখ্যা:

  • from_warehouse হলো Factory A (ডিফল্ট ওয়্যারহাউস)।
  • item_id রেফার করে Cotton Navy Fabric।
  • status প্রাথমিকভাবে pending
  • approved_by হলো Shahid (User মডেল)।

🧾 ধাপ ৭: স্টক ট্রান্সফার এবং রিসিভ (Inventory / Stock Management)

গল্প: Factory B-তে ফ্যাব্রিক পৌঁছায়। Asif এটি রিসিভ করে এবং সিস্টেমে ট্রান্সেকশন এন্ট্রি করে। ItemWarehouseStock এবং Transaction আপডেট হয়।

📦 Table: inventory_itemwarehousestock (আপডেটেড)

iditem_idwarehouse_idquantitylast_updated
111 (Factory A)3000.002025-08-16T10:00:00Z
212 (Factory B)2000.002025-08-16T10:00:00Z

📦 Table: inventory_transaction (আপডেটেড)

iditem_idtransaction_typequantitywarehouse_iddateremarkscreated_by
11receive5000.001 (Factory A)2025-08-15Received via GRN-2025-0003 by RinaRina
21transfer_out2000.001 (Factory A)2025-08-16Transferred to Factory BAsif
31transfer_in2000.002 (Factory B)2025-08-16Received from Factory A by AsifAsif

📦 Table: inventory_inventorytransfer (আপডেটেড)

idtransfer_idfrom_warehouseto_warehouseitem_idquantityunittransfer_datestatusapproved_by
1TR-2025-00011 (Factory A)2 (Factory B)12000.00meter2025-08-16receivedShahid

ব্যাখ্যা:

  • Factory A-এর স্টক: 5000 – 2000 = 3000 মিটার।
  • Factory B-এর স্টক: 2000 মিটার।
  • Transactiontransfer_out এবং transfer_in এন্ট্রি।
  • InventoryTransferstatus আপডেট হয় received

🧾 ধাপ ৮: স্টক ইস্যু (Inventory / Stock Management)

গল্প: Asif প্রোডাকশনের জন্য Factory B থেকে 1000 মিটার Cotton Navy Fabric ইস্যু করেন। Shahid এটি অনুমোদন করেন। GoodsIssue, ItemWarehouseStock, এবং Transaction আপডেট হয়।

📦 Table: inventory_goodsissue

idissue_iditem_idwarehouse_idquantityunitissue_datestatusapproved_bystyle_idremarks
1IS-2025-000112 (Factory B)1000.00meter2025-08-17approvedShahid1Issued for ABC-NAVY-TSHIRT-2025

📦 Table: inventory_itemwarehousestock (আপডেটেড)

iditem_idwarehouse_idquantitylast_updated
111 (Factory A)3000.002025-08-16T10:00:00Z
212 (Factory B)1000.002025-08-17T10:00:00Z

📦 Table: inventory_transaction (আপডেটেড)

iditem_idtransaction_typequantitywarehouse_iddateremarkscreated_by
11receive5000.001 (Factory A)2025-08-15Received via GRN-2025-0003 by RinaRina
21transfer_out2000.001 (Factory A)2025-08-16Transferred to Factory BAsif
31transfer_in2000.002 (Factory B)2025-08-16Received from Factory A by AsifAsif
41issue1000.002 (Factory B)2025-08-17Issued for ABC-NAVY-TSHIRT-2025Asif

ব্যাখ্যা:

  • Factory B-এর স্টক: 2000 – 1000 = 1000 মিটার।
  • GoodsIssue প্রোডাকশনের জন্য ইস্যু ট্র্যাক করে, style_id রেফার করে ABC-NAVY-TSHIRT-2025।
  • Transactionissue লেনদেন যুক্ত।
  • ইস্যু Factory B থেকে হয়েছে, কারণ ফ্যাব্রিক ইতিমধ্যে ট্রান্সফার হয়েছে।

🧾 ধাপ ৯: স্টক মনিটরিং এবং রিপোর্ট (Inventory / Stock Management)

গল্প: Shahid ItemWarehouseStock এবং Transaction টেবিল থেকে গুদাম-ভিত্তিক স্টক চেক করেন এবং একটি Stock Summary Report তৈরি করেন।

📊 Stock Summary Report:

  • Factory A: Cotton Navy Fabric = 3000 মিটার
  • Factory B: Cotton Navy Fabric = 1000 মিটার

ব্যাখ্যা:

  • ItemWarehouseStock থেকে বর্তমান স্টক সরাসরি পাওয়া যায়।
  • Transaction অডিট ট্রেইল হিসেবে কাজ করে।
  • GoodsReceipt এবং GoodsIssue নির্দিষ্ট রিসিভ এবং ইস্যু ট্র্যাক করে।
  • ডিফল্ট ওয়্যারহাউস (Factory A) রিসিভের জন্য ব্যবহৃত হয়েছে।

📊 ইন্টিগ্রেশন ফ্লো

[ABC Buyer: Order] → [Nahid: PR-2025-0004] → [Hasib: PO-2025-0010] → [Selim: GRN-2025-0003] → [Farzana: PO Tracking]
→ [Rina: Goods Receipt REC-2025-0001 to Factory A] → [Asif: Transfer Request TR-2025-0001] → [Shahid: Approve Transfer] → [Asif: Transfer Receive to Factory B] → [Asif: Goods Issue IS-2025-0001 from Factory B] → [Shahid: Stock Report]

🧰 Django মডেল

নিচে inventory/models.py এর আপডেটেড কোড দেওয়া হলো, যেখানে Warehouse প্রথমে এবং Itemdefault_warehouse ফিল্ড যুক্ত করা হয়েছে।

from django.db import models
from django.contrib.auth.models import User
from procurement.models import GoodsReceiveNote
from order_management.models import OrderStyle

class Warehouse(models.Model):
    name = models.CharField(max_length=100, verbose_name="Warehouse Name")
    location = models.CharField(max_length=200, verbose_name="Location")
    manager = models.ForeignKey(User, on_delete=models.SET_NULL, null=True, verbose_name="Manager")

    class Meta:
        verbose_name = "Warehouse"
        verbose_name_plural = "Warehouses"

    def __str__(self):
        return self.name

class Item(models.Model):
    ITEM_TYPE_CHOICES = (
        ('fabric', 'Fabric'),
        ('trim', 'Trim'),
        ('accessory', 'Accessory'),
    )

    item_name = models.CharField(max_length=100, verbose_name="Item Name")
    item_type = models.CharField(max_length=20, choices=ITEM_TYPE_CHOICES, verbose_name="Item Type")
    unit = models.CharField(max_length=20, verbose_name="Unit")
    default_warehouse = models.ForeignKey(Warehouse, on_delete=models.SET_NULL, null=True, verbose_name="Default Warehouse")

    class Meta:
        verbose_name = "Item"
        verbose_name_plural = "Items"

    def __str__(self):
        return self.item_name

class ItemWarehouseStock(models.Model):
    item = models.ForeignKey(Item, on_delete=models.CASCADE, verbose_name="Item")
    warehouse = models.ForeignKey(Warehouse, on_delete=models.CASCADE, verbose_name="Warehouse")
    quantity = models.DecimalField(max_digits=10, decimal_places=2, verbose_name="Quantity")
    last_updated = models.DateTimeField(auto_now=True, verbose_name="Last Updated")

    class Meta:
        verbose_name = "Item Warehouse Stock"
        verbose_name_plural = "Item Warehouse Stocks"
        unique_together = ('item', 'warehouse')

    def __str__(self):
        return f"{self.item.item_name} ({self.warehouse.name})"

class Transaction(models.Model):
    TRANSACTION_TYPE_CHOICES = (
        ('receive', 'Receive'),
        ('transfer_out', 'Transfer Out'),
        ('transfer_in', 'Transfer In'),
        ('issue', 'Issue to Production'),
    )

    item = models.ForeignKey(Item, on_delete=models.CASCADE, verbose_name="Item")
    transaction_type = models.CharField(max_length=20, choices=TRANSACTION_TYPE_CHOICES, verbose_name="Transaction Type")
    quantity = models.DecimalField(max_digits=10, decimal_places=2, verbose_name="Quantity")
    warehouse = models.ForeignKey(Warehouse, on_delete=models.CASCADE, verbose_name="Warehouse")
    date = models.DateField(verbose_name="Date")
    remarks = models.TextField(blank=True, verbose_name="Remarks")
    created_by = models.ForeignKey(User, on_delete=models.SET_NULL, null=True, verbose_name="Created By")

    class Meta:
        verbose_name = "Transaction"
        verbose_name_plural = "Transactions"

    def __str__(self):
        return f"{self.transaction_type} - {self.item.item_name} ({self.warehouse.name})"

class InventoryTransfer(models.Model):
    STATUS_CHOICES = (
        ('pending', 'Pending'),
        ('in_transit', 'In Transit'),
        ('received', 'Received'),
    )

    transfer_id = models.CharField(max_length=20, unique=True, verbose_name="Transfer ID")
    from_warehouse = models.ForeignKey(Warehouse, related_name='transfers_out', on_delete=models.CASCADE, verbose_name="From Warehouse")
    to_warehouse = models.ForeignKey(Warehouse, related_name='transfers_in', on_delete=models.CASCADE, verbose_name="To Warehouse")
    item = models.ForeignKey(Item, on_delete=models.CASCADE, verbose_name="Item")
    quantity = models.DecimalField(max_digits=10, decimal_places=2, verbose_name="Quantity")
    unit = models.CharField(max_length=20, verbose_name="Unit")
    transfer_date = models.DateField(verbose_name="Transfer Date")
    status = models.CharField(max_length=20, choices=STATUS_CHOICES, default='pending', verbose_name="Status")
    approved_by = models.ForeignKey(User, on_delete=models.SET_NULL, null=True, verbose_name="Approved By")

    class Meta:
        verbose_name = "Inventory Transfer"
        verbose_name_plural = "Inventory Transfers"

    def __str__(self):
        return f"{self.transfer_id} - {self.item.item_name}"

class GoodsReceipt(models.Model):
    STATUS_CHOICES = (
        ('pending', 'Pending'),
        ('received', 'Received'),
    )

    receipt_id = models.CharField(max_length=20, unique=True, verbose_name="Receipt ID")
    grn = models.ForeignKey(GoodsReceiveNote, on_delete=models.CASCADE, verbose_name="Goods Receive Note")
    item = models.ForeignKey(Item, on_delete=models.CASCADE, verbose_name="Item")
    warehouse = models.ForeignKey(Warehouse, on_delete=models.CASCADE, verbose_name="Warehouse")
    quantity = models.DecimalField(max_digits=10, decimal_places=2, verbose_name="Quantity")
    date = models.DateField(verbose_name="Date")
    received_by = models.ForeignKey(User, on_delete=models.SET_NULL, null=True, verbose_name="Received By")
    status = models.CharField(max_length=20, choices=STATUS_CHOICES, default='pending', verbose_name="Status")
    remarks = models.TextField(blank=True, verbose_name="Remarks")

    class Meta:
        verbose_name = "Goods Receipt"
        verbose_name_plural = "Goods Receipts"

    def __str__(self):
        return f"{self.receipt_id} - {self.item.item_name}"

class GoodsIssue(models.Model):
    STATUS_CHOICES = (
        ('pending', 'Pending'),
        ('approved', 'Approved'),
    )

    issue_id = models.CharField(max_length=20, unique=True, verbose_name="Issue ID")
    item = models.ForeignKey(Item, on_delete=models.CASCADE, verbose_name="Item")
    warehouse = models.ForeignKey(Warehouse, on_delete=models.CASCADE, verbose_name="Warehouse")
    quantity = models.DecimalField(max_digits=10, decimal_places=2, verbose_name="Quantity")
    unit = models.CharField(max_length=20, verbose_name="Unit")
    issue_date = models.DateField(verbose_name="Issue Date")
    status = models.CharField(max_length=20, choices=STATUS_CHOICES, default='pending', verbose_name="Status")
    approved_by = models.ForeignKey(User, on_delete=models.SET_NULL, null=True, verbose_name="Approved By")
    style = models.ForeignKey(OrderStyle, on_delete=models.SET_NULL, null=True, verbose_name="Style")
    remarks = models.TextField(blank=True, verbose_name="Remarks")

    class Meta:
        verbose_name = "Goods Issue"
        verbose_name_plural = "Goods Issues"

    def __str__(self):
        return f"{self.issue_id} - {self.item.item_name}"

ব্যাখ্যা:

  • Warehouse: গুদামের তথ্য, প্রথমে সংজ্ঞায়িত।
  • Item: আইটেমের মেটাডেটা, default_warehouse ফিল্ড সহ।
  • ItemWarehouseStock: গুদামে বর্তমান স্টক, unique_together নিশ্চিত করে একই আইটেম একই গুদামে একাধিক এন্ট্রি নেই।
  • Transaction: সকল লেনদেন (receive, transfer_out, transfer_in, issue)।
  • InventoryTransfer: গুদাম থেকে গুদামে ট্রান্সফার।
  • GoodsReceipt: GRN থেকে রিসিভ ট্র্যাকিং, ডিফল্ট ওয়্যারহাউস ব্যবহৃত।
  • GoodsIssue: প্রোডাকশনের জন্য ইস্যু ট্র্যাকিং, style ফিল্ড অর্ডার স্টাইলের সাথে লিঙ্ক।

ধাপ: অ্যাডমিন কনফিগারেশন

নিচে inventory/admin.py দেওয়া হলো, যা নতুন মডেল স্ট্রাকচারের সাথে সামঞ্জস্যপূর্ণ।

from django.contrib import admin
from unfold.admin import ModelAdmin
from .models import Warehouse, Item, ItemWarehouseStock, Transaction, InventoryTransfer, GoodsReceipt, GoodsIssue

@admin.register(Warehouse)
class WarehouseAdmin(ModelAdmin):
    list_display = ('name', 'location', 'manager')
    search_fields = ('name', 'location', 'manager__username')
    list_filter = ('location',)
    ordering = ('name',)

@admin.register(Item)
class ItemAdmin(ModelAdmin):
    list_display = ('item_name', 'item_type', 'unit', 'default_warehouse')
    search_fields = ('item_name',)
    list_filter = ('item_type', 'default_warehouse')
    ordering = ('item_name',)

@admin.register(ItemWarehouseStock)
class ItemWarehouseStockAdmin(ModelAdmin):
    list_display = ('item', 'warehouse', 'quantity', 'last_updated')
    search_fields = ('item__item_name', 'warehouse__name')
    list_filter = ('warehouse', 'item__item_type')
    ordering = ('-last_updated',)

@admin.register(Transaction)
class TransactionAdmin(ModelAdmin):
    list_display = ('item', 'transaction_type', 'quantity', 'warehouse', 'date', 'created_by', 'remarks')
    search_fields = ('item__item_name', 'remarks', 'created_by__username')
    list_filter = ('transaction_type', 'warehouse', 'date')
    ordering = ('-date',)

@admin.register(InventoryTransfer)
class InventoryTransferAdmin(ModelAdmin):
    list_display = ('transfer_id', 'from_warehouse', 'to_warehouse', 'item', 'quantity', 'unit', 'transfer_date', 'status', 'approved_by')
    search_fields = ('transfer_id', 'item__item_name', 'from_warehouse__name', 'to_warehouse__name')
    list_filter = ('status', 'transfer_date', 'from_warehouse', 'to_warehouse')
    ordering = ('-transfer_date',)

@admin.register(GoodsReceipt)
class GoodsReceiptAdmin(ModelAdmin):
    list_display = ('receipt_id', 'item', 'warehouse', 'quantity', 'date', 'received_by', 'status', 'remarks')
    search_fields = ('receipt_id', 'item__item_name', 'warehouse__name', 'received_by__username')
    list_filter = ('status', 'date', 'warehouse')
    ordering = ('-date',)

@admin.register(GoodsIssue)
class GoodsIssueAdmin(ModelAdmin):
    list_display = ('issue_id', 'item', 'warehouse', 'quantity', 'unit', 'issue_date', 'status', 'approved_by', 'style')
    search_fields = ('issue_id', 'item__item_name', 'warehouse__name', 'style__style_name')
    list_filter = ('status', 'issue_date', 'warehouse', 'style')
    ordering = ('-issue_date',)

ব্যাখ্যা:

  • Item এর জন্য default_warehouse ফিল্ড অ্যাডমিনে যুক্ত।
  • প্রতিটি মডেলের জন্য list_display, search_fields, list_filter, এবং ordering কাস্টমাইজ করা হয়েছে।

ধাপ: settings.py

settings.py আগের মতোই, তবে Inventory Management সেকশনে Warehouse এবং Item এর নাম এবং ক্রম আপডেট করা হয়েছে।

"""
Django settings for config project.

Generated by 'django-admin startproject' using Django 5.2.4.

For more information on this file, see
https://docs.djangoproject.com/en/5.2/topics/settings/

For the full list of settings and their values, see
https://docs.djangoproject.com/en/5.2/ref/settings/
"""

from pathlib import Path
from django.templatetags.static import static
from django.urls import reverse_lazy
from django.utils.translation import gettext_lazy as _

# Build paths inside the project like this: BASE_DIR / 'subdir'.
BASE_DIR = Path(__file__).resolve().parent.parent

# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/5.2/howto/deployment/checklist/

# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = 'django-insecure-d&5pro-b^j#$qo7amy26x$%5$+@-zim%mg9nl@px68(apvg@c7'

# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True

ALLOWED_HOSTS = []

# Application definition
INSTALLED_APPS = [
    "unfold",
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'custom_auth',
    'order_management',
    'sampling_merchandising',
    'production_planning',
    'procurement',
    'inventory',
]

MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
]

ROOT_URLCONF = 'config.urls'

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [],
        'APP_DIRS': True,
        'OPTIONS': {
            'context_processors': [
                'django.template.context_processors.request',
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
            ],
        },
    },
]

WSGI_APPLICATION = 'config.wsgi.application'

# Database
# https://docs.djangoproject.com/en/5.2/ref/settings/#databases
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': BASE_DIR / 'db.sqlite3',
    }
}

# Password validation
# https://docs.djangoproject.com/en/5.2/ref/settings/#auth-password-validators
AUTH_PASSWORD_VALIDATORS = [
    {
        'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
    },
]

# Internationalization
# https://docs.djangoproject.com/en/5.2/topics/i18n/
LANGUAGE_CODE = 'en-us'
TIME_ZONE = 'UTC'
USE_I18N = True
USE_TZ = True

# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/5.2/howto/static-files/
STATIC_URL = '/static/'
STATICFILES_DIRS = [BASE_DIR / "static"]
STATIC_ROOT = BASE_DIR / "staticfiles"

# Default primary key field type
# https://docs.djangoproject.com/en/5.2/ref/settings/#default-auto-field
DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'

UNFOLD = {
    "SITE_TITLE": "GarmrntsErp",
    "SITE_HEADER": "GarmrntsErp Dashboard",
    "SITE_URL": "/",
    "SHOW_HISTORY": False,
    "SIDEBAR": {
        "show_search": True,
        "show_all_applications": False,
        "navigation": [
            {
                "title": _("Data And Analytics"),
                "separator": True,
                "collapsible": True,
                "items": [
                    {
                        "title": _("Dashboard"),
                        "icon": "dashboard",
                        "link": reverse_lazy("admin:index"),
                        "permission": lambda request: request.user.is_superuser,
                    },
                ],
            },
            {
                "title": _("Authentication"),
                "separator": True,
                "collapsible": True,
                "items": [
                    {
                        "title": _("Users"),
                        "icon": "people",
                        "link": reverse_lazy("admin:auth_user_changelist"),
                        "permission": lambda request: request.user.is_superuser,
                    },
                    {
                        "title": _("Groups"),
                        "icon": "group",
                        "link": reverse_lazy("admin:auth_group_changelist"),
                        "permission": lambda request: request.user.is_superuser,
                    },
                    {
                        "title": _("Permissions"),
                        "icon": "lock",
                        "link": reverse_lazy("admin:auth_permission_changelist"),
                        "permission": lambda request: request.user.is_superuser,
                    },
                ],
            },
            {
                "title": _("Order Management"),
                "separator": True,
                "collapsible": True,
                "items": [
                    {
                        "title": _("Buyers"),
                        "icon": "business",
                        "link": reverse_lazy("admin:order_management_buyer_changelist"),
                        "permission": lambda request: request.user.is_superuser,
                    },
                    {
                        "title": _("Orders"),
                        "icon": "shopping_cart",
                        "link": reverse_lazy("admin:order_management_order_changelist"),
                        "permission": lambda request: request.user.is_superuser,
                    },
                    {
                        "title": _("Order Styles"),
                        "icon": "style",
                        "link": reverse_lazy("admin:order_management_orderstyle_changelist"),
                        "permission": lambda request: request.user.is_superuser,
                    },
                    {
                        "title": _("Order Breakdowns"),
                        "icon": "list_alt",
                        "link": reverse_lazy("admin:order_management_orderbreakdown_changelist"),
                        "permission": lambda request: request.user.is_superuser,
                    },
                    {
                        "title": _("Tech Packs"),
                        "icon": "description",
                        "link": reverse_lazy("admin:order_management_techpack_changelist"),
                        "permission": lambda request: request.user.is_superuser,
                    },
                    {
                        "title": _("Delivery Schedules"),
                        "icon": "local_shipping",
                        "link": reverse_lazy("admin:order_management_deliveryschedule_changelist"),
                        "permission": lambda request: request.user.is_superuser,
                    },
                ],
            },
            {
                "title": _("Sampling and Merchandising"),
                "separator": True,
                "collapsible": True,
                "items": [
                    {
                        "title": _("Sample Requests"),
                        "icon": "request_quote",
                        "link": reverse_lazy("admin:sampling_merchandising_samplerequest_changelist"),
                        "permission": lambda request: request.user.is_superuser,
                    },
                    {
                        "title": _("Sample Trackings"),
                        "icon": "local_shipping",
                        "link": reverse_lazy("admin:sampling_merchandising_sampletracking_changelist"),
                        "permission": lambda request: request.user.is_superuser,
                    },
                    {
                        "title": _("Fabric Developments"),
                        "icon": "texture",
                        "link": reverse_lazy("admin:sampling_merchandising_fabricdevelopment_changelist"),
                        "permission": lambda request: request.user.is_superuser,
                    },
                    {
                        "title": _("Trim Developments"),
                        "icon": "category",
                        "link": reverse_lazy("admin:sampling_merchandising_trimdevelopment_changelist"),
                        "permission": lambda request: request.user.is_superuser,
                    },
                    {
                        "title": _("Costing Sheets"),
                        "icon": "calculate",
                        "link": reverse_lazy("admin:sampling_merchandising_costingsheet_changelist"),
                        "permission": lambda request: request.user.is_superuser,
                    },
                    {
                        "title": _("Consumption Calculations"),
                        "icon": "scale",
                        "link": reverse_lazy("admin:sampling_merchandising_consumptioncalculation_changelist"),
                        "permission": lambda request: request.user.is_superuser,
                    },
                    {
                        "title": _("Follow Up Notes"),
                        "icon": "notes",
                        "link": reverse_lazy("admin:sampling_merchandising_followupnote_changelist"),
                        "permission": lambda request: request.user.is_superuser,
                    },
                ],
            },
            {
                "title": _("Procurement & Purchase"),
                "separator": True,
                "collapsible": True,
                "items": [
                    {
                        "title": _("Suppliers"),
                        "icon": "business",
                        "link": reverse_lazy("admin:procurement_supplier_changelist"),
                        "permission": lambda request: request.user.is_superuser,
                    },
                    {
                        "title": _("Purchase Requisitions"),
                        "icon": "request_page",
                        "link": reverse_lazy("admin:procurement_purchaserequisition_changelist"),
                        "permission": lambda request: request.user.is_superuser,
                    },
                    {
                        "title": _("Purchase Orders"),
                        "icon": "shopping_bag",
                        "link": reverse_lazy("admin:procurement_purchaseorder_changelist"),
                        "permission": lambda request: request.user.is_superuser,
                    },
                    {
                        "title": _("Goods Receive Notes"),
                        "icon": "inventory",
                        "link": reverse_lazy("admin:procurement_goodsreceivenote_changelist"),
                        "permission": lambda request: request.user.is_superuser,
                    },
                    {
                        "title": _("PO Tracking"),
                        "icon": "track_changes",
                        "link": reverse_lazy("admin:procurement_potracking_changelist"),
                        "permission": lambda request: request.user.is_superuser,
                    },
                ],
            },
            {
                "title": _("Inventory Management"),
                "separator": True,
                "collapsible": True,
                "items": [
                    {
                        "title": _("Warehouses"),
                        "icon": "warehouse",
                        "link": reverse_lazy("admin:inventory_warehouse_changelist"),
                        "permission": lambda request: request.user.is_superuser,
                    },
                    {
                        "title": _("Items"),
                        "icon": "inventory_2",
                        "link": reverse_lazy("admin:inventory_item_changelist"),
                        "permission": lambda request: request.user.is_superuser,
                    },
                    {
                        "title": _("Warehouse Stocks"),
                        "icon": "store",
                        "link": reverse_lazy("admin:inventory_itemwarehousestock_changelist"),
                        "permission": lambda request: request.user.is_superuser,
                    },
                    {
                        "title": _("Transactions"),
                        "icon": "swap_horiz",
                        "link": reverse_lazy("admin:inventory_transaction_changelist"),
                        "permission": lambda request: request.user.is_superuser,
                    },
                    {
                        "title": _("Inventory Transfers"),
                        "icon": "local_shipping",
                        "link": reverse_lazy("admin:inventory_inventorytransfer_changelist"),
                        "permission": lambda request: request.user.is_superuser,
                    },
                    {
                        "title": _("Goods Receipts"),
                        "icon": "archive",
                        "link": reverse_lazy("admin:inventory_goodsreceipt_changelist"),
                        "permission": lambda request: request.user.is_superuser,
                    },
                    {
                        "title": _("Goods Issues"),
                        "icon": "assignment_turned_in",
                        "link": reverse_lazy("admin:inventory_goodsissue_changelist"),
                        "permission": lambda request: request.user.is_superuser,
                    },
                ],
            },
            {
                "title": _("Production Planning"),
                "separator": True,
                "collapsible": True,
                "items": [
                    {
                        "title": _("Line Planning"),
                        "icon": "view_timeline",
                        "link": reverse_lazy("admin:production_planning_lineplanning_changelist"),
                        "permission": lambda request: request.user.is_superuser,
                    },
                    {
                        "title": _("Machine Allocation"),
                        "icon": "build",
                        "link": reverse_lazy("admin:production_planning_machineallocation_changelist"),
                        "permission": lambda request: request.user.is_superuser,
                    },
                    {
                        "title": _("Operator Assignment"),
                        "icon": "engineering",
                        "link": reverse_lazy("admin:production_planning_operatorassignment_changelist"),
                        "permission": lambda request: request.user.is_superuser,
                    },
                    {
                        "title": _("Target vs Achievement"),
                        "icon": "trending_up",
                        "link": reverse_lazy("admin:production_planning_targetvsachievement_changelist"),
                        "permission": lambda request: request.user.is_superuser,
                    },
                ],
            },
        ],
    },
}

ধাপ: স্যাম্পল ডেটা

নিচে আপডেটেড inventory_sample_data.json দেওয়া হলো, যা নতুন মডেল স্ট্রাকচার এবং ডিফল্ট ওয়্যারহাউসের সাথে সামঞ্জস্যপূর্ণ। ফাইলটি C:\Users\Olee-Ahmmed\Desktop\GarmrntsErp\config\fixtures\inventory_sample_data.json পাথে সেভ করুন।

[
    {
        "model": "auth.user",
        "pk": 1,
        "fields": {
            "username": "nahid",
            "first_name": "Nahid",
            "last_name": "",
            "email": "nahid@example.com",
            "password": "pbkdf2_sha256$260000$randomsalt$hashedpassword",
            "is_staff": true,
            "is_active": true
        }
    },
    {
        "model": "auth.user",
        "pk": 2,
        "fields": {
            "username": "hasib",
            "first_name": "Hasib",
            "last_name": "",
            "email": "hasib@example.com",
            "password": "pbkdf2_sha256$260000$randomsalt$hashedpassword",
            "is_staff": true,
            "is_active": true
        }
    },
    {
        "model": "auth.user",
        "pk": 3,
        "fields": {
            "username": "selim",
            "first_name": "Selim",
            "last_name": "",
            "email": "selim@example.com",
            "password": "pbkdf2_sha256$260000$randomsalt$hashedpassword",
            "is_staff": true,
            "is_active": true
        }
    },
    {
        "model": "auth.user",
        "pk": 4,
        "fields": {
            "username": "farzana",
            "first_name": "Farzana",
            "last_name": "",
            "email": "farzana@example.com",
            "password": "pbkdf2_sha256$260000$randomsalt$hashedpassword",
            "is_staff": true,
            "is_active": true
        }
    },
    {
        "model": "auth.user",
        "pk": 5,
        "fields": {
            "username": "rina",
            "first_name": "Rina",
            "last_name": "",
            "email": "rina@example.com",
            "password": "pbkdf2_sha256$260000$randomsalt$hashedpassword",
            "is_staff": true,
            "is_active": true
        }
    },
    {
        "model": "auth.user",
        "pk": 6,
        "fields": {
            "username": "shahid",
            "first_name": "Shahid",
            "last_name": "",
            "email": "shahid@example.com",
            "password": "pbkdf2_sha256$260000$randomsalt$hashedpassword",
            "is_staff": true,
            "is_active": true
        }
    },
    {
        "model": "auth.user",
        "pk": 7,
        "fields": {
            "username": "asif",
            "first_name": "Asif",
            "last_name": "",
            "email": "asif@example.com",
            "password": "pbkdf2_sha256$260000$randomsalt$hashedpassword",
            "is_staff": true,
            "is_active": true
        }
    },
    {
        "model": "order_management.buyer",
        "pk": 1,
        "fields": {
            "name": "ABC Buyer",
            "country": "USA",
            "contact_person": "John Doe",
            "phone": "+1234567890",
            "email": "john@abcbuyer.com"
        }
    },
    {
        "model": "order_management.order",
        "pk": 1,
        "fields": {
            "buyer": 1,
            "quantity": 20000,
            "sizes": "S,M,L,XL",
            "colors": "Navy",
            "delivery_date": "2025-09-30",
            "order_date": "2025-08-03",
            "status": "received",
            "remarks": "Order for ABC Buyer managed by Nahid"
        }
    },
    {
        "model": "order_management.orderstyle",
        "pk": 1,
        "fields": {
            "order": 1,
            "style_name": "ABC-NAVY-TSHIRT-2025"
        }
    },
    {
        "model": "procurement.supplier",
        "pk": 1,
        "fields": {
            "name": "Shamim Textile",
            "contact": "017XXXXXXXXX",
            "rating": 4.8,
            "last_purchase_date": "2025-07-12"
        }
    },
    {
        "model": "procurement.purchaserequisition",
        "pk": 1,
        "fields": {
            "requisition_id": "PR-2025-0004",
            "item_name": "Cotton Navy Fabric",
            "quantity": 5000.00,
            "unit": "meter",
            "urgency": "high",
            "created_by": 1,
            "created_at": "2025-08-03",
            "status": "approved",
            "style": 1
        }
    },
    {
        "model": "procurement.purchaserequisition",
        "pk": 2,
        "fields": {
            "requisition_id": "PR-2025-0005",
            "item_name": "Button",
            "quantity": 20000.00,
            "unit": "piece",
            "urgency": "medium",
            "created_by": 1,
            "created_at": "2025-08-03",
            "status": "pending",
            "style": 1
        }
    },
    {
        "model": "procurement.purchaseorder",
        "pk": 1,
        "fields": {
            "po_id": "PO-2025-0010",
            "requisition": 1,
            "supplier": 1,
            "item_name": "Cotton Navy Fabric",
            "quantity": 5000.00,
            "price_per_unit": 180.00,
            "total_price": 900000.00,
            "delivery_date": "2025-08-15",
            "status": "received",
            "created_at": "2025-08-03"
        }
    },
    {
        "model": "procurement.goodsreceivenote",
        "pk": 1,
        "fields": {
            "grn_id": "GRN-2025-0003",
            "purchase_order": 1,
            "received_qty": 5000.00,
            "date": "2025-08-15",
            "checked_by": 3,
            "status": "received",
            "remarks": "Checked and received by Selim"
        }
    },
    {
        "model": "procurement.potracking",
        "pk": 1,
        "fields": {
            "purchase_order": 1,
            "status": "received",
            "last_updated": "2025-08-15",
            "remarks": "Ready for payment processing by Farzana"
        }
    },
    {
        "model": "inventory.warehouse",
        "pk": 1,
        "fields": {
            "name": "Factory A",
            "location": "Dhaka Main Warehouse",
            "manager": 6
        }
    },
    {
        "model": "inventory.warehouse",
        "pk": 2,
        "fields": {
            "name": "Factory B",
            "location": "Gazipur Production Warehouse",
            "manager": 7
        }
    },
    {
        "model": "inventory.item",
        "pk": 1,
        "fields": {
            "item_name": "Cotton Navy Fabric",
            "item_type": "fabric",
            "unit": "meter",
            "default_warehouse": 1
        }
    },
    {
        "model": "inventory.itemwarehousestock",
        "pk": 1,
        "fields": {
            "item": 1,
            "warehouse": 1,
            "quantity": 3000.00,
            "last_updated": "2025-08-16T10:00:00Z"
        }
    },
    {
        "model": "inventory.itemwarehousestock",
        "pk": 2,
        "fields": {
            "item": 1,
            "warehouse": 2,
            "quantity": 1000.00,
            "last_updated": "2025-08-17T10:00:00Z"
        }
    },
    {
        "model": "inventory.goodsreceipt",
        "pk": 1,
        "fields": {
            "receipt_id": "REC-2025-0001",
            "grn": 1,
            "item": 1,
            "warehouse": 1,
            "quantity": 5000.00,
            "date": "2025-08-15",
            "received_by": 5,
            "status": "received",
            "remarks": "Received via GRN-2025-0003 by Rina"
        }
    },
    {
        "model": "inventory.transaction",
        "pk": 1,
        "fields": {
            "item": 1,
            "transaction_type": "receive",
            "quantity": 5000.00,
            "warehouse": 1,
            "date": "2025-08-15",
            "remarks": "Received via GRN-2025-0003 by Rina",
            "created_by": 5
        }
    },
    {
        "model": "inventory.transaction",
        "pk": 2,
        "fields": {
            "item": 1,
            "transaction_type": "transfer_out",
            "quantity": 2000.00,
            "warehouse": 1,
            "date": "2025-08-16",
            "remarks": "Transferred to Factory B",
            "created_by": 7
        }
    },
    {
        "model": "inventory.transaction",
        "pk": 3,
        "fields": {
            "item": 1,
            "transaction_type": "transfer_in",
            "quantity": 2000.00,
            "warehouse": 2,
            "date": "2025-08-16",
            "remarks": "Received from Factory A by Asif",
            "created_by": 7
        }
    },
    {
        "model": "inventory.transaction",
        "pk": 4,
        "fields": {
            "item": 1,
            "transaction_type": "issue",
            "quantity": 1000.00,
            "warehouse": 2,
            "date": "2025-08-17",
            "remarks": "Issued for ABC-NAVY-TSHIRT-2025",
            "created_by": 7
        }
    },
    {
        "model": "inventory.inventorytransfer",
        "pk": 1,
        "fields": {
            "transfer_id": "TR-2025-0001",
            "from_warehouse": 1,
            "to_warehouse": 2,
            "item": 1,
            "quantity": 2000.00,
            "unit": "meter",
            "transfer_date": "2025-08-16",
            "status": "received",
            "approved_by": 6
        }
    },
    {
        "model": "inventory.goodsissue",
        "pk": 1,
        "fields": {
            "issue_id": "IS-2025-0001",
            "item": 1,
            "warehouse": 2,
            "quantity": 1000.00,
            "unit": "meter",
            "issue_date": "2025-08-17",
            "status": "approved",
            "approved_by": 6,
            "style": 1,
            "remarks": "Issued for ABC-NAVY-TSHIRT-2025"
        }
    }
]

ব্যাখ্যা:

  • User: Nahid, Hasib, Selim, Farzana, Rina, Shahid, Asif।
  • Procurement: PR-2025-0004, PR-2025-0005, PO-2025-0010, GRN-2025-0003, PO Tracking।
  • Inventory:
  • Warehouse: Factory A, Factory B।
  • Item: Cotton Navy Fabric, ডিফল্ট ওয়্যারহাউস Factory A।
  • ItemWarehouseStock: Factory A (3000 মিটার), Factory B (1000 মিটার)।
  • Transaction: Receive, Transfer Out, Transfer In, Issue।
  • InventoryTransfer: TR-2025-0001।
  • GoodsReceipt: REC-2025-0001 (Factory A)।
  • GoodsIssue: IS-2025-0001 (Factory B)।

ধাপ: ডাটাবেস প্রস্তুতি এবং টেস্ট

  1. মডেল আপডেট:
  • inventory/models.py এবং inventory/admin.py আপডেট করুন।
  1. মাইগ্রেশন প্রয়োগ:
   python manage.py makemigrations
   python manage.py migrate
  1. ডেটা লোড:
   python manage.py loaddata fixtures/inventory_sample_data
  1. সার্ভার চালু:
   python manage.py runserver
  1. অ্যাডমিন প্যানেল চেক:
  • http://127.0.0.1:8000/admin/ এ লগইন করুন।
  • Procurement & Purchase এবং Inventory Management সেকশন চেক করুন:
    • Suppliers: Shamim Textile
    • Purchase Requisitions: PR-2025-0004, PR-2025-0005
    • Purchase Orders: PO-2025-0010
    • Goods Receive Notes: GRN-2025-0003
    • PO Tracking: Received
    • Warehouses: Factory A, Factory B
    • Items: Cotton Navy Fabric (Default Warehouse: Factory A)
    • Warehouse Stocks: Factory A (3000 মিটার), Factory B (1000 মিটার)
    • Transactions: Receive, Transfer Out, Transfer In, Issue
    • Inventory Transfers: TR-2025-0001
    • Goods Receipts: REC-2025-0001
    • Goods Issues: IS-2025-0001

🎯 মডিউলের উদ্দেশ্য

মডেলউদ্দেশ্য
Supplierসাপ্লায়ার তথ্য সংরক্ষণ
PurchaseRequisitionমালের চাহিদা তৈরি এবং ট্র্যাকিং
PurchaseOrderক্রয় আদেশ ইস্যু এবং ম্যানেজমেন্ট
GoodsReceiveNoteমাল রিসিভ এবং QA চেক ট্র্যাকিং
POTrackingPO-এর স্ট্যাটাস এবং পেমেন্ট ট্র্যাকিং
Warehouseগুদামের তথ্য সংরক্ষণ
Itemআইটেমের মেটাডেটা, ডিফল্ট ওয়্যারহাউস সহ
ItemWarehouseStockগুদাম-ভিত্তিক বর্তমান স্টক ট্র্যাকিং
Transactionসকল লেনদেনের ইতিহাস (রিসিভ, ট্রান্সফার, ইস্যু)
InventoryTransferগুদাম থেকে গুদামে ট্রান্সফার প্রক্রিয়া ম্যানেজ
GoodsReceiptGRN থেকে মাল রিসিভ ট্র্যাকিং, ডিফল্ট ওয়্যারহাউস
GoodsIssueপ্রোডাকশনের জন্য মাল ইস্যু ট্র্যাকিং

📊 ফ্লো ডায়াগ্রাম

[ABC Buyer: Order] → [Nahid: PR-2025-0004] → [Hasib: PO-2025-0010] → [Selim: GRN-2025-0003] → [Farzana: PO Tracking]
→ [Rina: Goods Receipt REC-2025-0001 to Factory A (Default)] → [Asif: Transfer Request TR-2025-0001 from Factory A] → [Shahid: Approve Transfer] → [Asif: Transfer Receive to Factory B] → [Asif: Goods Issue IS-2025-0001 from Factory B] → [Shahid: Stock Report]

🔄 পরবর্তী ধাপ

অনুগ্রহ করে জানান:

  1. Stock Summary Report: Django Admin-এ কাস্টম রিপোর্ট তৈরি করব যাতে ItemWarehouseStock থেকে স্টক এবং Transaction থেকে ইতিহাস দেখা যায়?
  2. Validation: GoodsReceipt এবং GoodsIssue এর জন্য ডিফল্ট ওয়্যারহাউস স্বয়ংক্রিয়ভাবে Item.default_warehouse থেকে নেওয়ার জন্য কাস্টম লজিক (যেমন, save() মেথড ওভাররাইড) যুক্ত করব?
  3. Production Floor Control: এই মডিউল তৈরি করব? ফিচার যেমন Line Planning, Machine Allocation চান?
  4. ER Diagram: Procurement & Purchase এবং Inventory Management এর সম্মিলিত ER Diagram তৈরি করব?
  5. অতিরিক্ত ফিচার: রি-অর্ডার লেভেল অ্যালার্ট, ডেড স্টক রিপোর্ট, বা স্টক ভ্যালুয়েশন (FIFO/LIFO)?
  6. API এন্ডপয়েন্ট: REST API তৈরি করব (যেমন, /api/itemwarehousestock/, /api/inventorytransfer/)?
  7. ডেটা লোড বা সাইডবারে সমস্যা হলে বিস্তারিত শেয়ার করুন।

আশা করি এবার মডেলগুলো আপনার প্রত্যাশা পূরণ করেছে! 😊 কোনো পরিবর্তন বা অতিরিক্ত ফিচার চাইলে জানান।

How can we help?