From 7e8972eddc87bfb09f07b9a05b5da106d5655f12 Mon Sep 17 00:00:00 2001 From: Om Gedam Date: Mon, 13 Oct 2025 17:40:29 +0530 Subject: [PATCH] pcarm --- pcarm | 705 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 705 insertions(+) create mode 100644 pcarm diff --git a/pcarm b/pcarm new file mode 100644 index 00000000..7d3775c1 --- /dev/null +++ b/pcarm @@ -0,0 +1,705 @@ +""" +Comprehensive Inventory Management System +A full-featured inventory and warehouse management application +Author: Inventory Systems Team +Date: October 13, 2025 +Version: 2.0.0 +""" + +import json +import os +from datetime import datetime, timedelta +from typing import List, Dict, Optional, Tuple +import hashlib +import uuid +from collections import defaultdict +from enum import Enum +import re + + +class UserRole(Enum): + """User role enumeration""" + ADMIN = "admin" + MANAGER = "manager" + STAFF = "staff" + VIEWER = "viewer" + + +class TransactionType(Enum): + """Transaction type enumeration""" + PURCHASE = "purchase" + SALE = "sale" + RETURN = "return" + ADJUSTMENT = "adjustment" + TRANSFER = "transfer" + + +class User: + """Represents a user in the inventory system""" + + def __init__(self, username: str, email: str, password: str, role: UserRole): + self.user_id = str(uuid.uuid4()) + self.username = username + self.email = email + self.password_hash = self._hash_password(password) + self.role = role + self.created_at = datetime.now().isoformat() + self.last_login = None + self.is_active = True + + def _hash_password(self, password: str) -> str: + """Hash password using SHA-256""" + return hashlib.sha256(password.encode()).hexdigest() + + def verify_password(self, password: str) -> bool: + """Verify password""" + return self.password_hash == self._hash_password(password) + + def update_last_login(self): + """Update last login timestamp""" + self.last_login = datetime.now().isoformat() + + def to_dict(self) -> Dict: + """Convert to dictionary""" + return { + "user_id": self.user_id, + "username": self.username, + "email": self.email, + "password_hash": self.password_hash, + "role": self.role.value, + "created_at": self.created_at, + "last_login": self.last_login, + "is_active": self.is_active + } + + @staticmethod + def from_dict(data: Dict) -> 'User': + """Create from dictionary""" + user = User.__new__(User) + user.user_id = data["user_id"] + user.username = data["username"] + user.email = data["email"] + user.password_hash = data["password_hash"] + user.role = UserRole(data["role"]) + user.created_at = data["created_at"] + user.last_login = data.get("last_login") + user.is_active = data.get("is_active", True) + return user + + +class Product: + """Represents a product in inventory""" + + def __init__(self, name: str, sku: str, description: str, category: str, + unit_price: float, reorder_level: int = 10): + self.product_id = str(uuid.uuid4()) + self.name = name + self.sku = sku.upper() + self.description = description + self.category = category + self.unit_price = unit_price + self.reorder_level = reorder_level + self.created_at = datetime.now().isoformat() + self.updated_at = datetime.now().isoformat() + self.is_active = True + self.supplier_info = {} + self.attributes = {} + + def update_price(self, new_price: float): + """Update product price""" + self.unit_price = new_price + self.updated_at = datetime.now().isoformat() + + def update_reorder_level(self, new_level: int): + """Update reorder level""" + self.reorder_level = new_level + self.updated_at = datetime.now().isoformat() + + def add_supplier(self, supplier_name: str, supplier_contact: str): + """Add supplier information""" + self.supplier_info = { + "name": supplier_name, + "contact": supplier_contact + } + self.updated_at = datetime.now().isoformat() + + def add_attribute(self, key: str, value: str): + """Add custom attribute""" + self.attributes[key] = value + self.updated_at = datetime.now().isoformat() + + def to_dict(self) -> Dict: + """Convert to dictionary""" + return { + "product_id": self.product_id, + "name": self.name, + "sku": self.sku, + "description": self.description, + "category": self.category, + "unit_price": self.unit_price, + "reorder_level": self.reorder_level, + "created_at": self.created_at, + "updated_at": self.updated_at, + "is_active": self.is_active, + "supplier_info": self.supplier_info, + "attributes": self.attributes + } + + @staticmethod + def from_dict(data: Dict) -> 'Product': + """Create from dictionary""" + product = Product.__new__(Product) + product.product_id = data["product_id"] + product.name = data["name"] + product.sku = data["sku"] + product.description = data["description"] + product.category = data["category"] + product.unit_price = data["unit_price"] + product.reorder_level = data.get("reorder_level", 10) + product.created_at = data["created_at"] + product.updated_at = data["updated_at"] + product.is_active = data.get("is_active", True) + product.supplier_info = data.get("supplier_info", {}) + product.attributes = data.get("attributes", {}) + return product + + +class Warehouse: + """Represents a warehouse location""" + + def __init__(self, name: str, location: str, capacity: int): + self.warehouse_id = str(uuid.uuid4()) + self.name = name + self.location = location + self.capacity = capacity + self.current_stock = {} # product_id: quantity + self.created_at = datetime.now().isoformat() + + def add_stock(self, product_id: str, quantity: int) -> bool: + """Add stock to warehouse""" + current = self.current_stock.get(product_id, 0) + total = sum(self.current_stock.values()) + quantity + + if total > self.capacity: + return False + + self.current_stock[product_id] = current + quantity + return True + + def remove_stock(self, product_id: str, quantity: int) -> bool: + """Remove stock from warehouse""" + current = self.current_stock.get(product_id, 0) + + if current < quantity: + return False + + self.current_stock[product_id] = current - quantity + if self.current_stock[product_id] == 0: + del self.current_stock[product_id] + return True + + def get_stock(self, product_id: str) -> int: + """Get stock level for product""" + return self.current_stock.get(product_id, 0) + + def get_available_capacity(self) -> int: + """Get available capacity""" + used = sum(self.current_stock.values()) + return self.capacity - used + + def to_dict(self) -> Dict: + """Convert to dictionary""" + return { + "warehouse_id": self.warehouse_id, + "name": self.name, + "location": self.location, + "capacity": self.capacity, + "current_stock": self.current_stock, + "created_at": self.created_at + } + + @staticmethod + def from_dict(data: Dict) -> 'Warehouse': + """Create from dictionary""" + warehouse = Warehouse.__new__(Warehouse) + warehouse.warehouse_id = data["warehouse_id"] + warehouse.name = data["name"] + warehouse.location = data["location"] + warehouse.capacity = data["capacity"] + warehouse.current_stock = data.get("current_stock", {}) + warehouse.created_at = data["created_at"] + return warehouse + + +class Transaction: + """Represents an inventory transaction""" + + def __init__(self, transaction_type: TransactionType, product_id: str, + quantity: int, warehouse_id: str, user_id: str, + unit_price: float = 0.0, notes: str = ""): + self.transaction_id = str(uuid.uuid4()) + self.transaction_type = transaction_type + self.product_id = product_id + self.quantity = quantity + self.warehouse_id = warehouse_id + self.user_id = user_id + self.unit_price = unit_price + self.total_value = quantity * unit_price + self.notes = notes + self.timestamp = datetime.now().isoformat() + + def to_dict(self) -> Dict: + """Convert to dictionary""" + return { + "transaction_id": self.transaction_id, + "transaction_type": self.transaction_type.value, + "product_id": self.product_id, + "quantity": self.quantity, + "warehouse_id": self.warehouse_id, + "user_id": self.user_id, + "unit_price": self.unit_price, + "total_value": self.total_value, + "notes": self.notes, + "timestamp": self.timestamp + } + + @staticmethod + def from_dict(data: Dict) -> 'Transaction': + """Create from dictionary""" + transaction = Transaction.__new__(Transaction) + transaction.transaction_id = data["transaction_id"] + transaction.transaction_type = TransactionType(data["transaction_type"]) + transaction.product_id = data["product_id"] + transaction.quantity = data["quantity"] + transaction.warehouse_id = data["warehouse_id"] + transaction.user_id = data["user_id"] + transaction.unit_price = data["unit_price"] + transaction.total_value = data["total_value"] + transaction.notes = data.get("notes", "") + transaction.timestamp = data["timestamp"] + return transaction + + +class InventoryManagementSystem: + """Main inventory management system""" + + def __init__(self, data_file: str = "inventory_data.json"): + self.data_file = data_file + self.users: Dict[str, User] = {} + self.products: Dict[str, Product] = {} + self.warehouses: Dict[str, Warehouse] = {} + self.transactions: List[Transaction] = [] + self.current_user: Optional[User] = None + self.load_data() + + def load_data(self): + """Load data from JSON file""" + if os.path.exists(self.data_file): + try: + with open(self.data_file, 'r') as f: + data = json.load(f) + self.users = {uid: User.from_dict(u) for uid, u in data.get("users", {}).items()} + self.products = {pid: Product.from_dict(p) for pid, p in data.get("products", {}).items()} + self.warehouses = {wid: Warehouse.from_dict(w) for wid, w in data.get("warehouses", {}).items()} + self.transactions = [Transaction.from_dict(t) for t in data.get("transactions", [])] + except Exception as e: + print(f"Error loading data: {e}") + + def save_data(self): + """Save data to JSON file""" + try: + data = { + "users": {uid: u.to_dict() for uid, u in self.users.items()}, + "products": {pid: p.to_dict() for pid, p in self.products.items()}, + "warehouses": {wid: w.to_dict() for wid, w in self.warehouses.items()}, + "transactions": [t.to_dict() for t in self.transactions] + } + with open(self.data_file, 'w') as f: + json.dump(data, f, indent=2) + except Exception as e: + print(f"Error saving data: {e}") + + # User Management + def register_user(self, username: str, email: str, password: str, role: str) -> bool: + """Register new user""" + if any(u.username == username for u in self.users.values()): + print("Username already exists!") + return False + + if not re.match(r"[^@]+@[^@]+\.[^@]+", email): + print("Invalid email format!") + return False + + try: + user_role = UserRole(role) + except ValueError: + print("Invalid role!") + return False + + user = User(username, email, password, user_role) + self.users[user.user_id] = user + self.save_data() + print(f"User {username} registered successfully!") + return True + + def login(self, username: str, password: str) -> bool: + """Login user""" + for user in self.users.values(): + if user.username == username and user.verify_password(password) and user.is_active: + self.current_user = user + user.update_last_login() + self.save_data() + print(f"Welcome, {username}!") + return True + print("Invalid credentials or inactive account!") + return False + + def logout(self): + """Logout current user""" + if self.current_user: + print(f"Goodbye, {self.current_user.username}!") + self.current_user = None + + # Product Management + def add_product(self, name: str, sku: str, description: str, category: str, + unit_price: float, reorder_level: int = 10) -> Optional[Product]: + """Add new product""" + if not self.current_user or self.current_user.role not in [UserRole.ADMIN, UserRole.MANAGER]: + print("Permission denied!") + return None + + if any(p.sku == sku.upper() for p in self.products.values()): + print("SKU already exists!") + return None + + product = Product(name, sku, description, category, unit_price, reorder_level) + self.products[product.product_id] = product + self.save_data() + print(f"Product {name} (SKU: {sku}) added successfully!") + return product + + def update_product_price(self, product_id: str, new_price: float) -> bool: + """Update product price""" + if not self.current_user or self.current_user.role not in [UserRole.ADMIN, UserRole.MANAGER]: + print("Permission denied!") + return False + + product = self.products.get(product_id) + if not product: + print("Product not found!") + return False + + product.update_price(new_price) + self.save_data() + print(f"Price updated to ${new_price:.2f}") + return True + + def search_products(self, keyword: str) -> List[Product]: + """Search products by keyword""" + keyword = keyword.lower() + return [p for p in self.products.values() + if keyword in p.name.lower() or keyword in p.sku.lower() + or keyword in p.category.lower()] + + # Warehouse Management + def add_warehouse(self, name: str, location: str, capacity: int) -> Optional[Warehouse]: + """Add new warehouse""" + if not self.current_user or self.current_user.role != UserRole.ADMIN: + print("Permission denied!") + return None + + warehouse = Warehouse(name, location, capacity) + self.warehouses[warehouse.warehouse_id] = warehouse + self.save_data() + print(f"Warehouse {name} added successfully!") + return warehouse + + # Transaction Management + def record_purchase(self, product_id: str, quantity: int, warehouse_id: str, + unit_price: float, notes: str = "") -> bool: + """Record product purchase""" + if not self.current_user: + print("Please login first!") + return False + + product = self.products.get(product_id) + warehouse = self.warehouses.get(warehouse_id) + + if not product or not warehouse: + print("Product or warehouse not found!") + return False + + if not warehouse.add_stock(product_id, quantity): + print("Insufficient warehouse capacity!") + return False + + transaction = Transaction( + TransactionType.PURCHASE, product_id, quantity, + warehouse_id, self.current_user.user_id, unit_price, notes + ) + self.transactions.append(transaction) + self.save_data() + print(f"Purchase recorded: {quantity} units of {product.name}") + return True + + def record_sale(self, product_id: str, quantity: int, warehouse_id: str, + unit_price: float, notes: str = "") -> bool: + """Record product sale""" + if not self.current_user: + print("Please login first!") + return False + + product = self.products.get(product_id) + warehouse = self.warehouses.get(warehouse_id) + + if not product or not warehouse: + print("Product or warehouse not found!") + return False + + if not warehouse.remove_stock(product_id, quantity): + print("Insufficient stock!") + return False + + transaction = Transaction( + TransactionType.SALE, product_id, quantity, + warehouse_id, self.current_user.user_id, unit_price, notes + ) + self.transactions.append(transaction) + self.save_data() + print(f"Sale recorded: {quantity} units of {product.name}") + return True + + def transfer_stock(self, product_id: str, quantity: int, + from_warehouse_id: str, to_warehouse_id: str) -> bool: + """Transfer stock between warehouses""" + if not self.current_user: + print("Please login first!") + return False + + from_warehouse = self.warehouses.get(from_warehouse_id) + to_warehouse = self.warehouses.get(to_warehouse_id) + + if not from_warehouse or not to_warehouse: + print("Warehouse not found!") + return False + + if not from_warehouse.remove_stock(product_id, quantity): + print("Insufficient stock in source warehouse!") + return False + + if not to_warehouse.add_stock(product_id, quantity): + from_warehouse.add_stock(product_id, quantity) # Rollback + print("Insufficient capacity in destination warehouse!") + return False + + self.save_data() + print(f"Stock transferred successfully!") + return True + + # Reporting and Analytics + def get_inventory_report(self) -> Dict: + """Generate inventory report""" + report = { + "total_products": len(self.products), + "total_warehouses": len(self.warehouses), + "products_by_category": defaultdict(int), + "stock_by_warehouse": {}, + "low_stock_alerts": [], + "total_inventory_value": 0.0 + } + + for product in self.products.values(): + report["products_by_category"][product.category] += 1 + + total_stock = sum(w.get_stock(product.product_id) for w in self.warehouses.values()) + + if total_stock < product.reorder_level: + report["low_stock_alerts"].append({ + "product": product.name, + "sku": product.sku, + "current_stock": total_stock, + "reorder_level": product.reorder_level + }) + + report["total_inventory_value"] += total_stock * product.unit_price + + for warehouse in self.warehouses.values(): + report["stock_by_warehouse"][warehouse.name] = { + "total_items": sum(warehouse.current_stock.values()), + "capacity": warehouse.capacity, + "utilization": f"{(sum(warehouse.current_stock.values()) / warehouse.capacity * 100):.1f}%" + } + + return report + + def get_sales_report(self, start_date: str = None, end_date: str = None) -> Dict: + """Generate sales report""" + sales_transactions = [t for t in self.transactions + if t.transaction_type == TransactionType.SALE] + + if start_date: + sales_transactions = [t for t in sales_transactions + if t.timestamp >= start_date] + if end_date: + sales_transactions = [t for t in sales_transactions + if t.timestamp <= end_date] + + report = { + "total_sales": len(sales_transactions), + "total_revenue": sum(t.total_value for t in sales_transactions), + "total_units_sold": sum(t.quantity for t in sales_transactions), + "sales_by_product": defaultdict(lambda: {"quantity": 0, "revenue": 0.0}) + } + + for transaction in sales_transactions: + product = self.products.get(transaction.product_id) + if product: + report["sales_by_product"][product.name]["quantity"] += transaction.quantity + report["sales_by_product"][product.name]["revenue"] += transaction.total_value + + return report + + def print_inventory_summary(self): + """Print inventory summary""" + print("\n" + "="*70) + print("INVENTORY SUMMARY") + print("="*70) + + for warehouse in self.warehouses.values(): + print(f"\nWarehouse: {warehouse.name} ({warehouse.location})") + print(f"Capacity: {warehouse.capacity} | Used: {sum(warehouse.current_stock.values())}") + print("-" * 70) + + for product_id, quantity in warehouse.current_stock.items(): + product = self.products.get(product_id) + if product: + value = quantity * product.unit_price + status = "LOW STOCK" if quantity < product.reorder_level else "OK" + print(f" {product.name:<30} | SKU: {product.sku:<10} | Qty: {quantity:>5} | ${value:>8.2f} | {status}") + + print("="*70 + "\n") + + +def main(): + """Main function""" + ims = InventoryManagementSystem() + + print("="*70) + print("INVENTORY MANAGEMENT SYSTEM") + print("="*70) + + while True: + if not ims.current_user: + print("\n1. Register") + print("2. Login") + print("3. Exit") + choice = input("\nSelect option: ").strip() + + if choice == "1": + username = input("Username: ").strip() + email = input("Email: ").strip() + password = input("Password: ").strip() + role = input("Role (admin/manager/staff/viewer): ").strip() + ims.register_user(username, email, password, role) + + elif choice == "2": + username = input("Username: ").strip() + password = input("Password: ").strip() + ims.login(username, password) + + elif choice == "3": + print("Goodbye!") + break + + else: + print(f"\nLogged in as: {ims.current_user.username} ({ims.current_user.role.value})") + print("\n1. Add Product") + print("2. Search Products") + print("3. Add Warehouse") + print("4. Record Purchase") + print("5. Record Sale") + print("6. Transfer Stock") + print("7. Inventory Report") + print("8. Sales Report") + print("9. Inventory Summary") + print("10. Logout") + + choice = input("\nSelect option: ").strip() + + if choice == "1": + name = input("Product Name: ").strip() + sku = input("SKU: ").strip() + desc = input("Description: ").strip() + category = input("Category: ").strip() + price = float(input("Unit Price: ")) + reorder = int(input("Reorder Level: ") or "10") + ims.add_product(name, sku, desc, category, price, reorder) + + elif choice == "2": + keyword = input("Search keyword: ").strip() + products = ims.search_products(keyword) + print(f"\nFound {len(products)} products:") + for p in products: + print(f" {p.name} - SKU: {p.sku} - ${p.unit_price:.2f}") + + elif choice == "3": + name = input("Warehouse Name: ").strip() + location = input("Location: ").strip() + capacity = int(input("Capacity: ")) + ims.add_warehouse(name, location, capacity) + + elif choice == "4": + pid = input("Product ID: ").strip() + qty = int(input("Quantity: ")) + wid = input("Warehouse ID: ").strip() + price = float(input("Unit Price: ")) + notes = input("Notes: ").strip() + ims.record_purchase(pid, qty, wid, price, notes) + + elif choice == "5": + pid = input("Product ID: ").strip() + qty = int(input("Quantity: ")) + wid = input("Warehouse ID: ").strip() + price = float(input("Unit Price: ")) + notes = input("Notes: ").strip() + ims.record_sale(pid, qty, wid, price, notes) + + elif choice == "6": + pid = input("Product ID: ").strip() + qty = int(input("Quantity: ")) + from_wid = input("From Warehouse ID: ").strip() + to_wid = input("To Warehouse ID: ").strip() + ims.transfer_stock(pid, qty, from_wid, to_wid) + + elif choice == "7": + report = ims.get_inventory_report() + print("\n" + "="*50) + print("INVENTORY REPORT") + print("="*50) + print(f"Total Products: {report['total_products']}") + print(f"Total Warehouses: {report['total_warehouses']}") + print(f"Total Inventory Value: ${report['total_inventory_value']:.2f}") + print(f"\nLow Stock Alerts: {len(report['low_stock_alerts'])}") + for alert in report['low_stock_alerts']: + print(f" - {alert['product']} ({alert['sku']}): {alert['current_stock']} units") + print("="*50) + + elif choice == "8": + report = ims.get_sales_report() + print("\n" + "="*50) + print("SALES REPORT") + print("="*50) + print(f"Total Sales: {report['total_sales']}") + print(f"Total Revenue: ${report['total_revenue']:.2f}") + print(f"Total Units Sold: {report['total_units_sold']}") + print("="*50) + + elif choice == "9": + ims.print_inventory_summary() + + elif choice == "10": + ims.logout() + + +if __name__ == "__main__": + main()