Code With Python
39K subscribers
841 photos
24 videos
22 files
746 links
This channel delivers clear, practical content for developers, covering Python, Django, Data Structures, Algorithms, and DSA – perfect for learning, coding, and mastering key programming skills.
Admin: @HusseinSheikho || @Hussein_Sheikho
Download Telegram
guardrails | AI Coding Glossary

📖 Application-level policies and controls that constrain how a model or agent behaves.

🏷️ #Python
This media is not supported in your browser
VIEW IN TELEGRAM
Python: How to easily upload a file via SSH

Want to upload a file to a remote server via SSH directly from a Python script? It's easy to do with the paramiko library - it provides a clean and reliable implementation of the SSH protocol.

Just install paramiko (pip install paramiko), specify the connection details, and use an SFTP session to send the file.

Make sure the user has write permissions to the target directory on the server. Subscribe for more tips every day!

import paramiko 

Connection settings
hostname = "your-server.com"
port = 22
username = "your_username"
password = "your_password"  # or use a key instead of a password

Local and remote paths
local_file = "local_file.txt"
remote_file = "/remote/path/local_file.txt"

Create SSH client
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())

try:
    ssh.connect(hostname, port=port, username=username, password=password)

# Open SFTP session and upload the file
sftp = ssh.open_sftp()
sftp.put(local_file, remote_file)
sftp.close()

print("File uploaded successfully!")
except Exception as e:
    print(f"Error: {e}")
finally:
    ()


https://t.me/DataScience4
2
💡 Python Exam Cheatsheet

A quick review of core Python concepts frequently found in technical assessments and exams. This guide covers list comprehensions, dictionary methods, enumerate, and flexible function arguments.

# Create a list of squares for even numbers from 0 to 9
squares = [x**2 for x in range(10) if x % 2 == 0]
print(squares)

# Output:
# [0, 4, 16, 36, 64]

List Comprehension: A concise, one-line syntax for creating lists.
• The structure is [expression for item in iterable if condition].
• The if condition part is optional and acts as a filter.

student_scores = {'Alice': 95, 'Bob': 87}

# Safely get a score, providing a default value if the key is missing
charlie_score = student_scores.get('Charlie', 'Not Found')
alice_score = student_scores.get('Alice', 'Not Found')

print(f"Alice: {alice_score}")
print(f"Charlie: {charlie_score}")

# Output:
# Alice: 95
# Charlie: Not Found

Dictionary .get() Method: Safely access a dictionary key without causing a KeyError.
• The first argument is the key to look up.
• The optional second argument is the default value to return if the key does not exist.

colors = ['red', 'green', 'blue']

for index, value in enumerate(colors):
print(f"Index: {index}, Value: {value}")

# Output:
# Index: 0, Value: red
# Index: 1, Value: green
# Index: 2, Value: blue

Using enumerate: The Pythonic way to loop over an iterable when you need both the index and the value.
• It returns a tuple (index, value) for each item in the sequence.

def process_data(*args, **kwargs):
print(f"Positional args (tuple): {args}")
print(f"Keyword args (dict): {kwargs}")

process_data(1, 'hello', 3.14, user='admin', status='active')

# Output:
# Positional args (tuple): (1, 'hello', 3.14)
# Keyword args (dict): {'user': 'admin', 'status': 'active'}

*args: Collects all extra positional arguments into a tuple.
**kwargs: Collects all extra keyword arguments into a dictionary.
• This pattern allows a function to accept a variable number of arguments.

#Python #PythonExam #Programming #CodeCheatsheet #LearnPython

━━━━━━━━━━━━━━━
By: @DataScience4
Clean Code Tip:

The with statement simplifies resource management, like file handling. It ensures resources are automatically closed, even if errors occur. This prevents bugs and makes your code safer and cleaner than manual try...finally blocks. It's a must-know for any Python developer! 🔐

Example:

# The old, verbose way to ensure a file is closed
print("--- Old Way ---")
file = open('greeting.txt', 'w')
try:
file.write('Hello, world!')
finally:
# This block always runs to ensure the file is closed
print("File is being closed in 'finally' block.")
file.close()


# The clean, safe, and Pythonic way using 'with'
print("\n--- Clean Way ---")
with open('greeting.txt', 'w') as file:
file.write('Hello, Python!')
print("Inside 'with' block. File is still open here.")

# The file is now automatically and safely closed.
print("Outside 'with' block. File is guaranteed to be closed.")


━━━━━━━━━━━━━━━
By: @DataScience4
1
Clean Code Tip:

When you need both the index and the item while looping, avoid manual index counters. Use Python's built-in enumerate() function for cleaner, more readable, and less error-prone code. It's the Pythonic way to count! 🔢

Example:

# The old, manual way to track an index
print("--- Old Way ---")
fruits = ['apple', 'banana', 'cherry']
index = 0
for fruit in fruits:
print(f"Index: {index}, Fruit: {fruit}")
index += 1


# The clean and Pythonic way using enumerate()
print("\n--- Clean Way ---")
for index, fruit in enumerate(fruits):
print(f"Index: {index}, Fruit: {fruit}")


# You can even start counting from a different number!
print("\n--- Starting from 1 ---")
for position, fruit in enumerate(fruits, start=1):
print(f"Position: {position}, Fruit: {fruit}")


━━━━━━━━━━━━━━━
By: @DataScience4
Clean Code Tip:

For reusable setup and teardown logic, you can create your own context managers. Instead of writing a full class with __enter__ and __exit__, use the @contextmanager decorator from the contextlib module for a more concise and elegant solution. This is a pro-level technique for robust resource management. 🚀

Example:

import contextlib

# The verbose, class-based way to create a context manager
class DatabaseConnection:
def __init__(self, db_name):
self._db_name = db_name
self._conn = None
print(f"Initializing connection to {self._db_name}...")

def __enter__(self):
print("-> Entering context: Opening connection.")
self._conn = f"CONNECTION_TO_{self._db_name}" # Simulate connection
return self._conn

def __exit__(self, exc_type, exc_val, exc_tb):
print("<- Exiting context: Closing connection.")
self._conn = None # Simulate closing

print("--- Class-Based Way ---")
with DatabaseConnection("users.db") as conn:
print(f" Performing operations with {conn}")


# The clean, Pythonic way using a generator and @contextmanager
@contextlib.contextmanager
def managed_database(db_name):
print(f"Initializing connection to {db_name}...")
conn = f"CONNECTION_TO_{db_name}"
try:
print("-> Entering context: Yielding connection.")
yield conn # The code inside the 'with' block runs here
finally:
# This code is guaranteed to run, just like __exit__
print("<- Exiting context: Closing connection in 'finally'.")
conn = None

print("\n--- @contextmanager Way ---")
with managed_database("products.db") as conn:
print(f" Performing operations with {conn}")


━━━━━━━━━━━━━━━
By: @DataScience4
1
Clean Code Tip:

Writing classes just to hold data often requires boilerplate methods like __init__, __repr__, and __eq__. The @dataclass decorator automates this! By simply declaring typed fields, you get a full-featured class, making your code significantly shorter, more readable, and less prone to errors. 📦

Example:

from dataclasses import dataclass

# The old, verbose way with manual boilerplate
class PointOld:
def __init__(self, x: int, y: int):
self.x = x
self.y = y

# Without this, printing the object is unhelpful
def __repr__(self):
return f"PointOld(x={self.x}, y={self.y})"

# Without this, comparison checks for object identity, not value
def __eq__(self, other):
if not isinstance(other, PointOld):
return NotImplemented
return self.x == other.x and self.y == other.y

print("--- Old Way ---")
p1_old = PointOld(10, 20)
p2_old = PointOld(10, 20)
print(f"Object representation: {p1_old}")
print(f"Are they equal? {p1_old == p2_old}")


# The clean, modern way using @dataclass
@dataclass
class PointNew:
x: int
y: int
# __init__, __repr__, and __eq__ are all generated automatically!

print("\n--- Clean @dataclass Way ---")
p1_new = PointNew(10, 20)
p2_new = PointNew(10, 20)
print(f"Object representation: {p1_new}")
print(f"Are they equal? {p1_new == p2_new}")


━━━━━━━━━━━━━━━
By: @DataScience4
1
#YOLOv8 #ComputerVision #FireDetection #Python #AI #Safety

Lesson: Real-Time Fire Detection in an Industrial Facility with YOLOv8 and Alarm System

This tutorial guides you through building a computer vision project from scratch. We will use the YOLOv8 model to detect fire in a video feed from an industrial setting and trigger an alarm sound upon detection.

---

#Step 1: Project Setup and Dependencies

First, we need to install the necessary Python libraries. We'll use ultralytics for the YOLOv8 model, opencv-python for video processing, and playsound to trigger our alarm. Open your terminal or command prompt and run the following command:

pip install ultralytics opencv-python playsound

After installation, create a Python file (e.g., fire_detector.py) and import these libraries.

import cv2
from ultralytics import YOLO
from playsound import playsound
import threading

# Hashtags: #Setup #Python #OpenCV #YOLOv8


---

#Step 2: Load the Model and Prepare the Alarm System

We will load a pre-trained YOLOv8 model. For a real-world application, you must train a custom model on a dataset of fire and smoke images. For this example, we will write the code assuming you have a custom model named fire_model.pt that knows how to detect 'fire'.

You also need an alarm sound file (e.g., alarm.wav) in the same directory as your script.

# Load your custom-trained YOLOv8 model
# IMPORTANT: The standard YOLOv8 models do not detect 'fire'.
# You must train your own model on a fire dataset.
model = YOLO('fire_model.pt') # Replace with your custom model path

# Path to your alarm sound file
ALARM_SOUND_PATH = "alarm.wav"

# A flag to ensure the alarm plays only once per detection event
alarm_on = False

def play_alarm():
"""Plays the alarm sound in a separate thread."""
global alarm_on
print("ALARM: Fire Detected!")
playsound(ALARM_SOUND_PATH)
alarm_on = False # Reset alarm flag after sound finishes

# Hashtags: #AIModel #AlarmSystem #SafetyFirst


---

#Step 3: Main Loop for Video Processing and Detection

This is the core of our application. We will open a video file, read it frame by frame, and pass each frame to our YOLOv8 model for inference. If the model detects 'fire' with a certain confidence, we will draw a bounding box around it and trigger the alarm.

Create a video file named industrial_video.mp4 or use your own video source.
1
# Open the video file
video_path = 'industrial_video.mp4'
cap = cv2.VideoCapture(video_path)

# Loop through the video frames
while cap.isOpened():
# Read a frame from the video
success, frame = cap.read()

if success:
# Run YOLOv8 inference on the frame
results = model(frame)

# A flag to check if fire was detected in the current frame
fire_detected_in_frame = False

# Visualize the results on the frame
annotated_frame = results[0].plot()

# Process detection results
for r in results:
for box in r.boxes:
# Check if the detected class is 'fire'
# model.names[0] should correspond to 'fire' in your custom model
if model.names[int(box.cls[0])] == 'fire' and box.conf[0] > 0.5:
fire_detected_in_frame = True
break

# If fire is detected and alarm is not already on, trigger alarm
if fire_detected_in_frame and not alarm_on:
alarm_on = True
# Run the alarm sound in a background thread to not block video feed
alarm_thread = threading.Thread(target=play_alarm)
alarm_thread.start()

# Display the annotated frame
cv2.imshow("YOLOv8 Fire Detection", annotated_frame)

# Break the loop if 'q' is pressed
if cv2.waitKey(1) & 0xFF == ord("q"):
break
else:
# Break the loop if the end of the video is reached
break

# Release the video capture object and close the display window
cap.release()
cv2.destroyAllWindows()

# Hashtags: #RealTimeDetection #VideoProcessing #OpenCV


---

#Step 4: Results and Discussion

After running the script, you will see a window playing the video. When the model detects an object it identifies as 'fire' with a confidence score above 50%, it will:
• Draw a colored box around the fire.
• Print "ALARM: Fire Detected!" to the console.
• Play the alarm.wav sound.

Discussion of Results:
Model Performance: The accuracy of this system depends entirely on the quality of your custom-trained model (fire_model.pt). A model trained on a diverse dataset of industrial fires (different lighting, angles, sizes) will perform best.
False Positives: The system might incorrectly identify orange/red lights, reflections, or welding sparks as fire. This is a common challenge. To fix this, you need to add more "negative" images (images of things that look like fire but aren't) to your training dataset.
Thresholding: The confidence threshold (box.conf[0] > 0.5) is a critical parameter. A lower value increases the chance of detecting real fires but also increases false alarms. A higher value reduces false alarms but might miss smaller or less obvious fires. You must tune this value based on your specific environment.
Real-World Implementation: For a real industrial facility, you would replace the video file with a live camera stream (cv2.VideoCapture(0) for a webcam) and integrate the alarm logic with a physical siren or a central monitoring system via an API or GPIO pins.

#ProjectComplete #AIforGood #IndustrialSafety

━━━━━━━━━━━━━━━
By: @DataScience4
1
weight | AI Coding Glossary

📖 A learned scalar or tensor that scales signals in a model and is updated during training to shape predictions.

🏷️ #Python
1
tensor parameter | AI Coding Glossary

📖 A learned multi-dimensional array that a model updates during training to shape its computations.

🏷️ #Python
#PyQt5 #SQLite #DesktopApp #WarehouseManagement #ERP #Python

Lesson: Advanced Warehouse ERP with PyQt5, SQLite, and Reporting

This tutorial covers building a complete desktop Enterprise Resource Planning (ERP) application for warehouse management. It features persistent storage using SQLite, inventory control, sales and purchase invoice management, a production module, and the ability to export reports to CSV.

---

#Step 1: Database Setup (database.py)

First, we create a dedicated file to handle all database interactions. This separation of concerns is crucial for a scalable application. Create a file named database.py.

import sqlite3
import csv

DB_NAME = 'warehouse.db'

def connect():
return sqlite3.connect(DB_NAME)

def setup_database():
conn = connect()
cursor = conn.cursor()
# Inventory Table: Stores raw materials and finished goods
cursor.execute('''
CREATE TABLE IF NOT EXISTS inventory (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL UNIQUE,
quantity INTEGER NOT NULL,
price REAL NOT NULL
)
''')
# Invoices Table: Tracks both sales and purchases
cursor.execute('''
CREATE TABLE IF NOT EXISTS invoices (
id INTEGER PRIMARY KEY AUTOINCREMENT,
type TEXT NOT NULL, -- 'SALE' or 'PURCHASE'
party_name TEXT, -- Customer or Supplier Name
date TIMESTAMP DEFAULT CURRENT_TIMESTAMP
)
''')
# Invoice Items Table: Links items from inventory to an invoice
cursor.execute('''
CREATE TABLE IF NOT EXISTS invoice_items (
id INTEGER PRIMARY KEY AUTOINCREMENT,
invoice_id INTEGER,
item_id INTEGER,
quantity INTEGER NOT NULL,
price_per_unit REAL NOT NULL,
FOREIGN KEY (invoice_id) REFERENCES invoices (id),
FOREIGN KEY (item_id) REFERENCES inventory (id)
)
''')
conn.commit()
conn.close()

def get_inventory():
conn = connect()
cursor = conn.cursor()
cursor.execute("SELECT id, name, quantity, price FROM inventory ORDER BY name")
items = cursor.fetchall()
conn.close()
return items

def add_inventory_item(name, quantity, price):
conn = connect()
cursor = conn.cursor()
try:
cursor.execute("INSERT INTO inventory (name, quantity, price) VALUES (?, ?, ?)", (name, quantity, price))
conn.commit()
except sqlite3.IntegrityError:
# Item with this name already exists
return False
finally:
conn.close()
return True

def update_item_quantity(item_id, change_in_quantity):
conn = connect()
cursor = conn.cursor()
cursor.execute("UPDATE inventory SET quantity = quantity + ? WHERE id = ?", (change_in_quantity, item_id))
conn.commit()
conn.close()

def find_item_by_name(name):
conn = connect()
cursor = conn.cursor()
cursor.execute("SELECT * FROM inventory WHERE name = ?", (name,))
item = cursor.fetchone()
conn.close()
return item

# Add more functions here for invoices, etc. as we build the app.

# Hashtags: #SQLite #DatabaseDesign #DataPersistence #Python


---

#Step 2: Main Application Shell and Inventory Tab

Now, create the main application file, main.py. We'll build the window, tabs, and fully implement the Inventory tab, which will read from and write to our SQLite database.
1
import sys
import csv
from PyQt5.QtWidgets import *
import database as db # Import our database module

class WarehouseApp(QMainWindow):
def __init__(self):
super().__init__()
self.setWindowTitle("Warehouse ERP System")
self.setGeometry(100, 100, 1000, 700)
db.setup_database() # Ensure tables are created

self.tabs = QTabWidget()
self.setCentralWidget(self.tabs)

# Create tabs
self.inventory_tab = QWidget()
self.purchase_tab = QWidget() # Incoming
self.sales_tab = QWidget() # Outgoing
self.production_tab = QWidget()
self.reports_tab = QWidget()

self.tabs.addTab(self.inventory_tab, "Inventory")
# Add other tabs later...

self.setup_inventory_ui()
self.load_inventory_data()

def setup_inventory_ui(self):
layout = QVBoxLayout()
# Table view
self.inventory_table = QTableWidget()
self.inventory_table.setColumnCount(4)
self.inventory_table.setHorizontalHeaderLabels(['ID', 'Name', 'Quantity', 'Price'])
self.inventory_table.setEditTriggers(QAbstractItemView.NoEditTriggers)
layout.addWidget(self.inventory_table)

# Form for adding new items
form = QFormLayout()
self.item_name = QLineEdit()
self.item_qty = QSpinBox()
self.item_qty.setRange(0, 99999)
self.item_price = QLineEdit()
form.addRow("Name:", self.item_name)
form.addRow("Quantity:", self.item_qty)
form.addRow("Price:", self.item_price)
add_btn = QPushButton("Add New Item")
add_btn.clicked.connect(self.add_item)
layout.addLayout(form)
layout.addWidget(add_btn)

self.inventory_tab.setLayout(layout)

def load_inventory_data(self):
items = db.get_inventory()
self.inventory_table.setRowCount(len(items))
for row_num, row_data in enumerate(items):
for col_num, data in enumerate(row_data):
self.inventory_table.setItem(row_num, col_num, QTableWidgetItem(str(data)))

def add_item(self):
name = self.item_name.text()
qty = self.item_qty.value()
price = float(self.item_price.text())
if not name:
QMessageBox.warning(self, "Input Error", "Item name cannot be empty.")
return
if db.add_inventory_item(name, qty, price):
self.load_inventory_data() # Refresh table
self.item_name.clear()
self.item_qty.setValue(0)
self.item_price.clear()
else:
QMessageBox.warning(self, "DB Error", f"Item '{name}' already exists.")

if __name__ == '__main__':
app = QApplication(sys.argv)
window = WarehouseApp()
window.show()
sys.exit(app.exec_())

# Hashtags: #PyQt5 #GUI #CRUD #InventoryManagement


---

#Step 3: Purchase (Incoming) and Sales (Outgoing) Tabs

We'll manage invoices. A purchase increases stock, and a sale decreases it. We need to add functions to database.py first, then build the UI.

Add to database.py:
1
def create_invoice(invoice_type, party_name, items):
conn = connect()
cursor = conn.cursor()
# Create the invoice record
cursor.execute("INSERT INTO invoices (type, party_name) VALUES (?, ?)", (invoice_type, party_name))
invoice_id = cursor.lastrowid

# Add items to the invoice and update inventory
for item in items:
item_id, quantity, price = item['id'], item['quantity'], item['price']
cursor.execute(
"INSERT INTO invoice_items (invoice_id, item_id, quantity, price_per_unit) VALUES (?, ?, ?, ?)",
(invoice_id, item_id, quantity, price)
)
# Update inventory quantity
change = quantity if invoice_type == 'PURCHASE' else -quantity
cursor.execute("UPDATE inventory SET quantity = quantity + ? WHERE id = ?", (change, item_id))

conn.commit()
conn.close()
return invoice_id


Add to main.py's WarehouseApp class:
# In __init__, add the tab and call the setup
self.tabs.addTab(self.purchase_tab, "Purchasing (Incoming)")
self.setup_purchase_ui()

# In __init__, add the sales tab and call setup
self.tabs.addTab(self.sales_tab, "Sales (Outgoing)")
self.setup_sales_ui()

# New methods for the class
def setup_purchase_ui(self):
# This is a simplified UI for demonstration
layout = QVBoxLayout()
form = QFormLayout()
self.supplier_name = QLineEdit()
self.purchase_item = QComboBox()
self.purchase_qty = QSpinBox()
self.purchase_qty.setRange(1, 1000)

form.addRow("Supplier Name:", self.supplier_name)
form.addRow("Item:", self.purchase_item)
form.addRow("Quantity:", self.purchase_qty)

add_purchase_btn = QPushButton("Record Purchase")
add_purchase_btn.clicked.connect(self.record_purchase)

layout.addLayout(form)
layout.addWidget(add_purchase_btn)
self.purchase_tab.setLayout(layout)
self.update_item_combos()

def setup_sales_ui(self):
# UI is very similar to purchase
layout = QVBoxLayout()
form = QFormLayout()
self.customer_name = QLineEdit()
self.sales_item = QComboBox()
self.sales_qty = QSpinBox()
self.sales_qty.setRange(1, 1000)

form.addRow("Customer Name:", self.customer_name)
form.addRow("Item:", self.sales_item)
form.addRow("Quantity:", self.sales_qty)

add_sale_btn = QPushButton("Record Sale")
add_sale_btn.clicked.connect(self.record_sale)

layout.addLayout(form)
layout.addWidget(add_sale_btn)
self.sales_tab.setLayout(layout)

def update_item_combos(self):
self.purchase_item.clear()
self.sales_item.clear()
items = db.get_inventory()
for item in items:
# Store the full item tuple as userData
self.purchase_item.addItem(item[1], userData=item)
self.sales_item.addItem(item[1], userData=item)

def record_purchase(self):
supplier = self.supplier_name.text()
item_data = self.purchase_item.currentData()
qty = self.purchase_qty.value()
if not supplier or not item_data:
QMessageBox.warning(self, "Input Error", "Please fill all fields.")
return

invoice_item = {'id': item_data[0], 'quantity': qty, 'price': item_data[3]}
db.create_invoice('PURCHASE', supplier, [invoice_item])

QMessageBox.information(self, "Success", "Purchase recorded successfully.")
self.load_inventory_data() # Refresh all UIs
self.update_item_combos()

def record_sale(self):
customer = self.customer_name.text()
item_data = self.sales_item.currentData()
qty_to_sell = self.sales_qty.value()

if not customer or not item_data:
QMessageBox.warning(self, "Input Error", "Please fill all fields.")
return

# Check for sufficient stock
if item_data[2] < qty_to_sell:
QMessageBox.critical(self, "Stock Error", f"Not enough {item_data[1]} in stock. Available: {item_data[2]}")
return

invoice_item = {'id': item_data[0], 'quantity': qty_to_sell, 'price': item_data[3]}
db.create_invoice('SALE', customer, [invoice_item])

QMessageBox.information(self, "Success", "Sale recorded successfully.")
self.load_inventory_data()
self.update_item_combos()

Note: This invoice UI is simplified to one item per invoice. A real app would use a table to build a multi-item invoice before saving.

---

#Step 4: Production Tab and Reporting

The production tab will consume raw materials to create a finished product. The reporting tab will export inventory data to a CSV file.

Add to main.py's WarehouseApp class:
# In __init__, add the tabs and call the setups
self.tabs.addTab(self.production_tab, "Production")
self.setup_production_ui()
self.tabs.addTab(self.reports_tab, "Reporting")
self.setup_reports_ui()

# Define Bill of Materials (can be moved to DB in a real app)
self.bill_of_materials = {
'Wooden Table': {'Wood Plank': 5, 'Varnish': 1},
'Wooden Chair': {'Wood Plank': 2, 'Nail': 10}
}

def setup_production_ui(self):
layout = QVBoxLayout()
form = QFormLayout()
self.product_to_make = QComboBox()
self.product_to_make.addItems(self.bill_of_materials.keys())
self.production_qty = QSpinBox()
self.production_qty.setRange(1, 100)

form.addRow("Product:", self.product_to_make)
form.addRow("Quantity:", self.production_qty)
produce_btn = QPushButton("Produce Items")
produce_btn.clicked.connect(self.run_production)

layout.addLayout(form)
layout.addWidget(produce_btn)
self.production_tab.setLayout(layout)

def run_production(self):
product_name = self.product_to_make.currentText()
qty_to_make = self.production_qty.value()
bom = self.bill_of_materials[product_name]

# 1. Check stock for all required materials
for material, required_qty in bom.items():
item_data = db.find_item_by_name(material)
if not item_data or item_data[2] < required_qty * qty_to_make:
QMessageBox.critical(self, "Production Halt", f"Not enough {material} in stock.")
return

# 2. If stock is sufficient, consume materials
for material, required_qty in bom.items():
item_data = db.find_item_by_name(material)
db.update_item_quantity(item_data[0], - (required_qty * qty_to_make))

# 3. Add finished product to inventory
finished_product = db.find_item_by_name(product_name)
if finished_product:
db.update_item_quantity(finished_product[0], qty_to_make)
else:
# You'd calculate a price here in a real app
db.add_inventory_item(product_name, qty_to_make, price=50.0)

QMessageBox.information(self, "Success", f"Produced {qty_to_make} of {product_name}.")
self.load_inventory_data()
self.update_item_combos()

def setup_reports_ui(self):
layout = QVBoxLayout()
label = QLabel("Select a report to export to CSV:")
self.report_type = QComboBox()
self.report_type.addItems(["Current Inventory", "Sales History"]) # Add more as needed
export_btn = QPushButton("Export Report")
export_btn.clicked.connect(self.export_report)

layout.addWidget(label)
layout.addWidget(self.report_type)
layout.addWidget(export_btn)
layout.addStretch()
self.reports_tab.setLayout(layout)

def export_report(self):
report = self.report_type.currentText()
path, _ = QFileDialog.getSaveFileName(self, "Save CSV", "", "CSV Files (*.csv)")
if not path:
return

try:
if report == "Current Inventory":
data = db.get_inventory()
headers = ['ID', 'Name', 'Quantity', 'Price']
with open(path, 'w', newline='') as f:
writer = csv.writer(f)
writer.writerow(headers)
writer.writerows(data)
# Add other report types here
# elif report == "Sales History": ...

QMessageBox.information(self, "Success", f"Report exported to {path}")
except Exception as e:
QMessageBox.critical(self, "Export Error", f"An error occurred: {e}")

# Hashtags: #Production #Reporting #CSVExport #BusinessLogic


---

#Step 5: Final Results and Discussion
By combining all the code from the steps above into database.py and main.py, you have a robust, database-driven desktop application.

Results:
Data Persistence: Your inventory and invoice data is saved in warehouse.db and will be there when you restart the application.
Integrated Workflow: Adding a purchase directly increases stock. A sale checks for and decreases stock. Production consumes raw materials and creates finished goods, all reflected in the central inventory table.
Separation of Concerns: The UI logic in main.py is cleanly separated from the data logic in database.py, making the code easier to maintain and extend.
Reporting: You can easily export a snapshot of your current inventory to a CSV file for analysis in other programs like Excel or Google Sheets.

Discussion and Next Steps:
Scalability: While SQLite is excellent for small-to-medium applications, a large-scale, multi-user system would benefit from a client-server database like PostgreSQL or MySQL.
Invoice Complexity: The current invoice system is simplified. A real system would allow multiple items per invoice and store historical invoice data for viewing and printing.
User Interface (UI/UX): The UI is functional but could be greatly improved with better layouts, icons, search/filter functionality in tables, and more intuitive workflows.
Error Handling: The error handling is basic. A production-grade app would have more comprehensive checks for user input and database operations.
Advanced Features: Future additions could include user authentication, supplier and customer management, barcode scanning, and more detailed financial reporting.

This project forms a powerful template for building custom internal business tools with Python.

#ProjectComplete #SoftwareEngineering #ERP #PythonGUI #BusinessApp

━━━━━━━━━━━━━━━
By: @DataScience4
Build a Python MCP Client to Test Servers From Your Terminal

📖 Follow this Python project to build an MCP client that discovers MCP server capabilities and feeds an AI-powered chat with tool calls.

🏷️ #intermediate #ai #projects
1
structured output | AI Coding Glossary

📖 Model responses that conform to a specified format, such as a JSON Schema.

🏷️ #Python
jailbreak | AI Coding Glossary

📖 A method of prompting that bypasses model safety constraints to elicit disallowed or unintended behavior.

🏷️ #Python
#Python #Top60 #BuiltInFunctions
👇👇👇👇👇
Please open Telegram to view this post
VIEW IN TELEGRAM