হাহা, তৃতীয়বার পাগল বললেন! 😜 ঠিক আছে, আমি আপনার নতুন প্রয়োজন বুঝে গেছি। আপনি চান Warehouse মডেল আগে থাকবে, তারপর Item মডেল, এবং Item মডেলে একটি ডিফল্ট ওয়্যারহাউস ফিল্ড থাকবে। যখন কোনো আইটেম ইন (রিসিভ) বা আউট (ইস্যু/ট্রান্সফার) হবে, তখন এই ডিফল্ট ওয়্যারহাউস থেকে হবে। আমি গল্প এবং মডেলগুলো আপডেট করব, যাতে Warehouse, Item, ItemWarehouseStock, Transaction, InventoryTransfer, GoodsReceipt, এবং GoodsIssue মডেলগুলো আপনার নির্দেশনা অনুযায়ী সাজানো হয়। Procurement & Purchase এবং গল্পের ধারাবাহিকতা (Nahid, Hasib, Selim, Farzana, Rina, Shahid, Asif) অপরিবর্তিত থাকবে।
নতুন মডেল স্ট্রাকচার:
- Warehouse: গুদামের তথ্য।
- Item: আইটেমের মেটাডেটা, ডিফল্ট ওয়্যারহাউস ফিল্ড সহ।
- ItemWarehouseStock: প্রতিটি গুদামে আইটেমের বর্তমান স্টক।
- Transaction: সকল লেনদেন (receive, transfer_in, transfer_out, issue)।
- InventoryTransfer: গুদাম থেকে গুদামে ট্রান্সফার।
- GoodsReceipt: মাল রিসিভ ট্র্যাকিং (GRN থেকে লিঙ্ক)।
- 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 থেকে আসা মাল ডিফল্ট ওয়্যারহাউসে এন্ট্রি, গুদাম-ভিত্তিক স্টক ট্র্যাকিং, ট্রান্সফার, ইস্যু, এবং ট্রান্সেকশন ইতিহাস।
🎭 চরিত্র পরিচিতি
| নাম | পদের নাম | দায়িত্ব |
|---|---|---|
| Nahid | Merchandiser | অর্ডার স্টাইল এবং ফ্যাব্রিক চাহিদা তৈরি |
| Hasib | Procurement Manager | সাপ্লায়ার খোঁজা, PO ইস্যু করা |
| Selim | Storekeeper | মাল রিসিভ এবং QA চেক করা |
| Farzana | Accounts Officer | PO ক্লিয়ার এবং পেমেন্ট প্রসেসিং |
| Rina | Procurement Executive | GRN কনফার্ম এবং স্টক রিসিভ এন্ট্রি |
| Shahid | Warehouse Manager | স্টক ট্রান্সফার/ইস্যু অনুমোদন এবং রিপোর্ট |
| Asif | Inventory Controller | স্টক ট্রান্সফার/ইস্যু রিসিভ এবং ট্র্যাকিং |
| ABC Buyer | Buyer | অর্ডার দাতা (ABC-NAVY-TSHIRT-2025) |
| Shamim Textile | Supplier | ফ্যাব্রিক সরবরাহকারী (Cotton Navy Fabric) |
| Factory A | Main Warehouse | প্রধান গুদাম (ডিফল্ট ফ্যাব্রিক স্টোরেজ) |
| Factory B | Production 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
| id | requisition_id | item_name | quantity | unit | urgency | created_by | created_at | status | style_id |
|---|---|---|---|---|---|---|---|---|---|
| 1 | PR-2025-0004 | Cotton Navy Fabric | 5000.00 | meter | high | Nahid | 2025-08-03 | approved | 1 |
| 2 | PR-2025-0005 | Button | 20000.00 | piece | medium | Nahid | 2025-08-03 | pending | 1 |
ব্যাখ্যা:
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
| id | po_id | requisition_id | supplier_id | item_name | quantity | price_per_unit | total_price | delivery_date | status | created_at |
|---|---|---|---|---|---|---|---|---|---|---|
| 1 | PO-2025-0010 | 1 | 1 | Cotton Navy Fabric | 5000.00 | 180.00 | 900000.00 | 2025-08-15 | issued | 2025-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
| id | grn_id | purchase_order_id | received_qty | date | checked_by | status | remarks |
|---|---|---|---|---|---|---|---|
| 1 | GRN-2025-0003 | 1 | 5000.00 | 2025-08-15 | Selim | received | Checked 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
| id | purchase_order_id | status | last_updated | remarks |
|---|---|---|---|---|
| 1 | 1 | received | 2025-08-15 | Ready 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
| id | name | location | manager |
|---|---|---|---|
| 1 | Factory A | Dhaka Main Warehouse | Shahid |
| 2 | Factory B | Gazipur Production Warehouse | Asif |
📦 Table: inventory_item
| id | item_name | item_type | unit | default_warehouse |
|---|---|---|---|---|
| 1 | Cotton Navy Fabric | fabric | meter | 1 (Factory A) |
📦 Table: inventory_itemwarehousestock
| id | item_id | warehouse_id | quantity | last_updated |
|---|---|---|---|---|
| 1 | 1 | 1 (Factory A) | 5000.00 | 2025-08-15T10:00:00Z |
📦 Table: inventory_goodsreceipt
| id | receipt_id | grn_id | item_id | warehouse_id | quantity | date | received_by | status | remarks |
|---|---|---|---|---|---|---|---|---|---|
| 1 | REC-2025-0001 | GRN-2025-0003 | 1 | 1 (Factory A) | 5000.00 | 2025-08-15 | Rina | received | Received via GRN-2025-0003 by Rina |
📦 Table: inventory_transaction
| id | item_id | transaction_type | quantity | warehouse_id | date | remarks | created_by |
|---|---|---|---|---|---|---|---|
| 1 | 1 | receive | 5000.00 | 1 (Factory A) | 2025-08-15 | Received via GRN-2025-0003 by Rina | Rina |
ব্যাখ্যা:
Itemএdefault_warehouseহিসেবে Factory A সেট।GoodsReceiptএ ডিফল্ট ওয়্যারহাউস (Factory A) ব্যবহৃত।ItemWarehouseStockএ Factory A-এর স্টক 5000 মিটার।Transactionএreceiveলেনদেন ট্র্যাক।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
| id | transfer_id | from_warehouse | to_warehouse | item_id | quantity | unit | transfer_date | status | approved_by |
|---|---|---|---|---|---|---|---|---|---|
| 1 | TR-2025-0001 | 1 (Factory A) | 2 (Factory B) | 1 | 2000.00 | meter | 2025-08-16 | pending | Shahid |
ব্যাখ্যা:
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 (আপডেটেড)
| id | item_id | warehouse_id | quantity | last_updated |
|---|---|---|---|---|
| 1 | 1 | 1 (Factory A) | 3000.00 | 2025-08-16T10:00:00Z |
| 2 | 1 | 2 (Factory B) | 2000.00 | 2025-08-16T10:00:00Z |
📦 Table: inventory_transaction (আপডেটেড)
| id | item_id | transaction_type | quantity | warehouse_id | date | remarks | created_by |
|---|---|---|---|---|---|---|---|
| 1 | 1 | receive | 5000.00 | 1 (Factory A) | 2025-08-15 | Received via GRN-2025-0003 by Rina | Rina |
| 2 | 1 | transfer_out | 2000.00 | 1 (Factory A) | 2025-08-16 | Transferred to Factory B | Asif |
| 3 | 1 | transfer_in | 2000.00 | 2 (Factory B) | 2025-08-16 | Received from Factory A by Asif | Asif |
📦 Table: inventory_inventorytransfer (আপডেটেড)
| id | transfer_id | from_warehouse | to_warehouse | item_id | quantity | unit | transfer_date | status | approved_by |
|---|---|---|---|---|---|---|---|---|---|
| 1 | TR-2025-0001 | 1 (Factory A) | 2 (Factory B) | 1 | 2000.00 | meter | 2025-08-16 | received | Shahid |
ব্যাখ্যা:
- Factory A-এর স্টক: 5000 – 2000 = 3000 মিটার।
- Factory B-এর স্টক: 2000 মিটার।
Transactionএtransfer_outএবংtransfer_inএন্ট্রি।InventoryTransferএstatusআপডেট হয়received।
🧾 ধাপ ৮: স্টক ইস্যু (Inventory / Stock Management)
গল্প: Asif প্রোডাকশনের জন্য Factory B থেকে 1000 মিটার Cotton Navy Fabric ইস্যু করেন। Shahid এটি অনুমোদন করেন। GoodsIssue, ItemWarehouseStock, এবং Transaction আপডেট হয়।
📦 Table: inventory_goodsissue
| id | issue_id | item_id | warehouse_id | quantity | unit | issue_date | status | approved_by | style_id | remarks |
|---|---|---|---|---|---|---|---|---|---|---|
| 1 | IS-2025-0001 | 1 | 2 (Factory B) | 1000.00 | meter | 2025-08-17 | approved | Shahid | 1 | Issued for ABC-NAVY-TSHIRT-2025 |
📦 Table: inventory_itemwarehousestock (আপডেটেড)
| id | item_id | warehouse_id | quantity | last_updated |
|---|---|---|---|---|
| 1 | 1 | 1 (Factory A) | 3000.00 | 2025-08-16T10:00:00Z |
| 2 | 1 | 2 (Factory B) | 1000.00 | 2025-08-17T10:00:00Z |
📦 Table: inventory_transaction (আপডেটেড)
| id | item_id | transaction_type | quantity | warehouse_id | date | remarks | created_by |
|---|---|---|---|---|---|---|---|
| 1 | 1 | receive | 5000.00 | 1 (Factory A) | 2025-08-15 | Received via GRN-2025-0003 by Rina | Rina |
| 2 | 1 | transfer_out | 2000.00 | 1 (Factory A) | 2025-08-16 | Transferred to Factory B | Asif |
| 3 | 1 | transfer_in | 2000.00 | 2 (Factory B) | 2025-08-16 | Received from Factory A by Asif | Asif |
| 4 | 1 | issue | 1000.00 | 2 (Factory B) | 2025-08-17 | Issued for ABC-NAVY-TSHIRT-2025 | Asif |
ব্যাখ্যা:
- Factory B-এর স্টক: 2000 – 1000 = 1000 মিটার।
GoodsIssueপ্রোডাকশনের জন্য ইস্যু ট্র্যাক করে,style_idরেফার করে ABC-NAVY-TSHIRT-2025।Transactionএissueলেনদেন যুক্ত।- ইস্যু 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 প্রথমে এবং Item এ default_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)।
ধাপ: ডাটাবেস প্রস্তুতি এবং টেস্ট
- মডেল আপডেট:
inventory/models.pyএবংinventory/admin.pyআপডেট করুন।
- মাইগ্রেশন প্রয়োগ:
python manage.py makemigrations
python manage.py migrate
- ডেটা লোড:
python manage.py loaddata fixtures/inventory_sample_data
- সার্ভার চালু:
python manage.py runserver
- অ্যাডমিন প্যানেল চেক:
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 চেক ট্র্যাকিং |
POTracking | PO-এর স্ট্যাটাস এবং পেমেন্ট ট্র্যাকিং |
Warehouse | গুদামের তথ্য সংরক্ষণ |
Item | আইটেমের মেটাডেটা, ডিফল্ট ওয়্যারহাউস সহ |
ItemWarehouseStock | গুদাম-ভিত্তিক বর্তমান স্টক ট্র্যাকিং |
Transaction | সকল লেনদেনের ইতিহাস (রিসিভ, ট্রান্সফার, ইস্যু) |
InventoryTransfer | গুদাম থেকে গুদামে ট্রান্সফার প্রক্রিয়া ম্যানেজ |
GoodsReceipt | GRN থেকে মাল রিসিভ ট্র্যাকিং, ডিফল্ট ওয়্যারহাউস |
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]
🔄 পরবর্তী ধাপ
অনুগ্রহ করে জানান:
- Stock Summary Report: Django Admin-এ কাস্টম রিপোর্ট তৈরি করব যাতে
ItemWarehouseStockথেকে স্টক এবংTransactionথেকে ইতিহাস দেখা যায়? - Validation:
GoodsReceiptএবংGoodsIssueএর জন্য ডিফল্ট ওয়্যারহাউস স্বয়ংক্রিয়ভাবেItem.default_warehouseথেকে নেওয়ার জন্য কাস্টম লজিক (যেমন,save()মেথড ওভাররাইড) যুক্ত করব? - Production Floor Control: এই মডিউল তৈরি করব? ফিচার যেমন Line Planning, Machine Allocation চান?
- ER Diagram: Procurement & Purchase এবং Inventory Management এর সম্মিলিত ER Diagram তৈরি করব?
- অতিরিক্ত ফিচার: রি-অর্ডার লেভেল অ্যালার্ট, ডেড স্টক রিপোর্ট, বা স্টক ভ্যালুয়েশন (FIFO/LIFO)?
- API এন্ডপয়েন্ট: REST API তৈরি করব (যেমন,
/api/itemwarehousestock/,/api/inventorytransfer/)? - ডেটা লোড বা সাইডবারে সমস্যা হলে বিস্তারিত শেয়ার করুন।
আশা করি এবার মডেলগুলো আপনার প্রত্যাশা পূরণ করেছে! 😊 কোনো পরিবর্তন বা অতিরিক্ত ফিচার চাইলে জানান।