Section A Scenario
Question 1-Computer Part Ordering System
ServerModule
from http.server import BaseHTTPRequestHandler, HTTPServer
import json
computer_parts = {
"monitor": {"name": "Monitor", "quantity": 100, "price": 120.00},
"keyboard-wireless": {"name": "Keyboard-Wireless", "quantity": 200, "price":
30.00},
"cable": {"name": "Cable", "quantity": 150, "price": 200.00},
"webcam": {"name": "Webcam", "quantity": 250, "price": 25.00},
}
class RequestHandler(BaseHTTPRequestHandler):
def do_GET(self):
if self.path == '/parts':
self.send_response(200)
self.send_header('Content-type', 'application/json')
self.end_headers()
self.wfile.write(json.dumps(computer_parts).encode())
else:
self.send_response(404)
self.end_headers()
def do_POST(self):
if self.path == '/order':
content_length = int(self.headers['Content-Length'])
post_data = self.rfile.read(content_length)
order = json.loads(post_data.decode())
for part in order:
if part in computer_parts and computer_parts[part]['quantity'] >=
order[part]:
computer_parts[part]['quantity'] -= order[part]
else:
self.send_response(400)
self.send_header('Content-type', 'application/json')
self.end_headers()
self.wfile.write(json.dumps({"error": f"Not enough stock for
{part}"}).encode())
return
self.send_response(200)
self.send_header('Content-type', 'application/json')
self.end_headers()
self.wfile.write(json.dumps({"message": "Order placed
successfully"}).encode())
else:
self.send_response(404)
self.end_headers()
def run_server():
server_address = ('', 8080)
httpd = HTTPServer(server_address, RequestHandler)
print('Running server...')
httpd.serve_forever()
if __name__ == '__main__':
run_server()
CustomerModule
import http.client
import json
BASE_URL = '127.0.0.1'
PORT = 8080
def browse_parts():
conn = http.client.HTTPConnection(BASE_URL, PORT)
conn.request("GET", "/parts")
response = conn.getresponse()
data = response.read()
parts = json.loads(data.decode())
conn.close()
for part, details in parts.items():
print(f"{part.capitalize()}: {details['quantity']} available at
${details['price']} each")
def place_order():
order = {}
while True:
part = input("Enter the part to order (or 'done' to finish): ").lower()
if part == 'done':
break
quantity = int(input(f"Enter the quantity for {part}: "))
order[part] = quantity
conn = http.client.HTTPConnection(BASE_URL, PORT)
headers = {'Content-type': 'application/json'}
conn.request("POST", "/order", body=json.dumps(order), headers=headers)
response = conn.getresponse()
data = response.read()
print(json.loads(data.decode()))
conn.close()
if __name__ == '__main__':
while True:
print("\n1. Browse parts\n2. Place an order\n3. Exit")
choice = input("Choose an option: ")
if choice == '1':
browse_parts()
elif choice == '2':
place_order()
elif choice == '3':
break
else:
print("Invalid option, please try again.")
Output-Order Item Successful
Question 2 – Implementing CRUD Operations
from http.server import BaseHTTPRequestHandler, HTTPServer
import json
inventory = {
"monitor": {"name": "Monitor", "quantity": 100, "price": 2250.00}, # Price in
ZAR
"keyboard-wireless": {"name": "Keyboard-Wireless", "quantity": 200, "price":
600.00}, # Price in ZAR
"cable": {"name": "Cable", "quantity": 300, "price": 150.00}, # Price in ZAR
"webcam": {"name": "Webcam", "quantity": 150, "price": 750.00}, # Price in ZAR
}
orders = []
class RequestHandler(BaseHTTPRequestHandler):
def do_GET(self):
if self.path == '/parts':
self.send_response(200)
self.send_header('Content-type', 'application/json')
self.end_headers()
self.wfile.write(json.dumps(inventory).encode())
elif self.path.startswith('/order/'):
order_id = self.path.split('/')[-1]
order = next((order for order in orders if order['id'] == order_id),
None)
if order:
self.send_response(200)
self.send_header('Content-type', 'application/json')
self.end_headers()
self.wfile.write(json.dumps(order).encode())
else:
self.send_response(404)
self.end_headers()
else:
self.send_response(404)
self.end_headers()
def do_POST(self):
if self.path == '/order':
content_length = int(self.headers['Content-Length'])
post_data = self.rfile.read(content_length)
order = json.loads(post_data.decode())
order_id = str(len(orders) + 1)
order['id'] = order_id
for part in order['items']:
if part in inventory and inventory[part]['quantity'] >=
order['items'][part]:
inventory[part]['quantity'] -= order['items'][part]
else:
self.send_response(400)
self.send_header('Content-type', 'application/json')
self.end_headers()
self.wfile.write(json.dumps({"error": f"Not enough stock for
{part}"}).encode())
return
orders.append(order)
self.send_response(200)
self.send_header('Content-type', 'application/json')
self.end_headers()
self.wfile.write(json.dumps({"message": "Order placed successfully",
"order_id": order_id}).encode())
elif self.path == '/parts':
content_length = int(self.headers['Content-Length'])
post_data = self.rfile.read(content_length)
new_part = json.loads(post_data.decode())
part_id = new_part['name'].lower().replace(' ', '-')
inventory[part_id] = new_part
self.send_response(201)
self.send_header('Content-type', 'application/json')
self.end_headers()
self.wfile.write(json.dumps({"message": "Part added
successfully"}).encode())
else:
self.send_response(404)
self.end_headers()
def do_PUT(self):
if self.path.startswith('/parts/'):
part_id = self.path.split('/')[-1]
if part_id in inventory:
content_length = int(self.headers['Content-Length'])
put_data = self.rfile.read(content_length)
updated_part = json.loads(put_data.decode())
inventory[part_id].update(updated_part)
self.send_response(200)
self.send_header('Content-type', 'application/json')
self.end_headers()
self.wfile.write(json.dumps({"message": "Part updated
successfully"}).encode())
else:
self.send_response(404)
self.end_headers()
else:
self.send_response(404)
self.end_headers()
def do_DELETE(self):
if self.path.startswith('/parts/'):
part_id = self.path.split('/')[-1]
if part_id in inventory:
del inventory[part_id]
self.send_response(200)
self.send_header('Content-type', 'application/json')
self.end_headers()
self.wfile.write(json.dumps({"message": "Part deleted
successfully"}).encode())
else:
self.send_response(404)
self.end_headers()
else:
self.send_response(404)
self.end_headers()
def run_server():
server_address = ('', 8080)
httpd = HTTPServer(server_address, RequestHandler)
print('Running server...')
httpd.serve_forever()
if __name__ == '__main__':
run_server()
Customer Moduleimport http.client
import json
BASE_URL = '127.0.0.1'
PORT = 8080
def browse_parts():
conn = http.client.HTTPConnection(BASE_URL, PORT)
conn.request("GET", "/parts")
response = conn.getresponse()
data = response.read()
parts = json.loads(data.decode())
conn.close()
for part, details in parts.items():
print(f"{part.capitalize()}: {details['quantity']} available at
R{details['price']} each")
def place_order():
order = {"items": {}}
while True:
part = input("Enter the part to order (or 'done' to finish): ").lower()
if part == 'done':
break
quantity = int(input(f"Enter the quantity for {part}: "))
order["items"][part] = quantity
conn = http.client.HTTPConnection(BASE_URL, PORT)
headers = {'Content-type': 'application/json'}
conn.request("POST", "/order", body=json.dumps(order), headers=headers)
response = conn.getresponse()
data = response.read()
print(json.loads(data.decode()))
conn.close()
def add_part():
part = input("Enter the part name: ").lower().replace(' ', '-')
quantity = int(input(f"Enter the quantity for {part}: "))
price = float(input(f"Enter the price for {part}: "))
new_part = {"name": part, "quantity": quantity, "price": price}
conn = http.client.HTTPConnection(BASE_URL, PORT)
headers = {'Content-type': 'application/json'}
conn.request("POST", "/parts", body=json.dumps(new_part), headers=headers)
response = conn.getresponse()
data = response.read()
print(json.loads(data.decode()))
conn.close()
def update_part():
part = input("Enter the part name to update: ").lower().replace(' ', '-')
quantity = int(input(f"Enter the new quantity for {part}: "))
price = float(input(f"Enter the new price for {part}: "))
updated_part = {"quantity": quantity, "price": price}
conn = http.client.HTTPConnection(BASE_URL, PORT)
headers = {'Content-type': 'application/json'}
conn.request("PUT", f"/parts/{part}", body=json.dumps(updated_part),
headers=headers)
response = conn.getresponse()
data = response.read()
print(json.loads(data.decode()))
conn.close()
def delete_part():
part = input("Enter the part name to delete: ").lower().replace(' ', '-')
conn = http.client.HTTPConnection(BASE_URL, PORT)
conn.request("DELETE", f"/parts/{part}")
response = conn.getresponse()
data = response.read()
print(json.loads(data.decode()))
conn.close()
if __name__ == '__main__':
while True:
print("\n1. Browse parts\n2. Place an order\n3. Add a part\n4. Update a
part\n5. Delete a part\n6. Exit")
choice = input("Choose an option: ")
if choice == '1':
browse_parts()
elif choice == '2':
place_order()
elif choice == '3':
add_part()
elif choice == '4':
update_part()
elif choice == '5':
delete_part()
elif choice == '6':
break
else:
print("Invalid option, please try again.")
Output-
Question 3 – Security Implementation
from http.server import BaseHTTPRequestHandler, HTTPServer
import json
from base64 import b64decode
inventory = {
"monitor": {"name": "Monitor", "quantity": 100, "price": 2250.00},
# Price in
ZAR
"keyboard-wireless": {"name": "Keyboard-Wireless", "quantity": 200, "price":
600.00}, # Price in ZAR
"cable": {"name": "Cable", "quantity": 300, "price": 150.00},
# Price in ZAR
"webcam": {"name": "Webcam", "quantity": 150, "price": 750.00},
}
orders = []
users = {"user1": "password1"}
class RequestHandler(BaseHTTPRequestHandler):
def do_GET(self):
if self.path == '/parts':
self.send_response(200)
self.send_header('Content-type', 'application/json')
self.end_headers()
self.wfile.write(json.dumps(inventory).encode())
elif self.path.startswith('/order/'):
order_id = self.path.split('/')[-1]
# Price in ZAR
order = next((order for order in orders if order['id'] == order_id),
None)
if order:
self.send_response(200)
self.send_header('Content-type', 'application/json')
self.end_headers()
self.wfile.write(json.dumps(order).encode())
else:
self.send_response(404)
self.end_headers()
else:
self.send_response(404)
self.end_headers()
def do_POST(self):
if self.path == '/order':
auth_header = self.headers.get('Authorization')
if auth_header and auth_header.startswith('Basic '):
encoded_credentials = auth_header.split(' ')[1]
decoded_credentials = b64decode(encoded_credentials).decode('utf-8')
username, password = decoded_credentials.split(':')
if users.get(username) == password:
content_length = int(self.headers['Content-Length'])
post_data = self.rfile.read(content_length)
order = json.loads(post_data.decode())
order_id = str(len(orders) + 1)
order['id'] = order_id
for part in order['items']:
if part in inventory and inventory[part]['quantity'] >=
order['items'][part]:
inventory[part]['quantity'] -= order['items'][part]
else:
self.send_response(400)
self.send_header('Content-type', 'application/json')
self.end_headers()
self.wfile.write(json.dumps({"error": f"Not enough stock
for {part}"}).encode())
return
orders.append(order)
self.send_response(200)
self.send_header('Content-type', 'application/json')
self.end_headers()
self.wfile.write(json.dumps({"message": "Order placed
successfully", "order_id": order_id}).encode())
else:
self.send_response(401)
self.end_headers()
else:
self.send_response(401)
self.end_headers()
else:
self.send_response(404)
self.end_headers()
def run_server():
server_address = ('', 8080)
print('Running server...')
(HTTPServer(server_address, RequestHandler)).serve_forever()
if __name__ == '__main__':
run_server()
Customer Module import http.client
import json
from base64 import b64encode
BASE_URL = '127.0.0.1'
PORT = 8080
username = None
password = None
def login():
global username, password
username = input("Enter username: ")
password = input("Enter password: ")
print("Login successful!")
def browse_parts():
conn = http.client.HTTPConnection(BASE_URL, PORT)
conn.request("GET", "/parts")
response = conn.getresponse()
data = response.read()
parts = json.loads(data.decode())
conn.close()
for part, details in parts.items():
print(f"{part.capitalize()}: {details['quantity']} available at
R{details['price']} each")
def place_order():
if not username or not password:
print("Please login first.")
return
order = {"items": {}}
while True:
part = input("Enter the part to order (or 'done' to finish): ").lower()
if part == 'done':
break
quantity = int(input(f"Enter the quantity for {part}: "))
order["items"][part] = quantity
conn = http.client.HTTPConnection(BASE_URL, PORT)
credentials = f"{username}:{password}"
encoded_credentials = b64encode(credentials.encode('utf-8')).decode('utf-8')
headers = {'Content-type': 'application/json', 'Authorization': f'Basic
{encoded_credentials}'}
conn.request("POST", "/order", body=json.dumps(order), headers=headers)
response = conn.getresponse()
data = response.read()
print(json.loads(data.decode()))
conn.close()
if __name__ == '__main__':
while True:
print("\n1. Login\n2. Browse parts\n3. Place an order\n4. Exit")
choice = input("Choose an option: ")
if choice == '1':
login()
elif choice == '2':
browse_parts()
elif choice == '3':
place_order()
elif choice == '4':
break
else:
print("Invalid option, please try again.")
Output-
Question 4 – Email Report
Email Receiptfrom http.server import BaseHTTPRequestHandler, HTTPServer
import json
from base64 import b64decode
import smtplib
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
import threading
import time
from datetime import datetime
inventory = {
"monitor": {"name": "Monitor", "quantity": 100, "price": 2250.00}, # Price in
ZAR
"keyboard-wireless": {"name": "Keyboard-Wireless", "quantity": 200, "price":
600.00}, # Price in ZAR
"cable": {"name": "Cable", "quantity": 300, "price": 150.00}, # Price in ZAR
"webcam": {"name": "Webcam", "quantity": 150, "price": 750.00}, # Price in ZAR
}
orders = []
users = {"user1": "password1"}
def send_email(to_address, subject, body):
from_address =-
password = "your_password"
msg = MIMEMultipart()
msg['From'] = from_address
msg['To'] = to_address
msg['Subject'] = subject
msg.attach(MIMEText(body, 'plain'))
server = smtplib.SMTP('smtp.gmail.com', 587)
server.starttls()
server.login(from_address, password)
text = msg.as_string()
server.sendmail(from_address, to_address, text)
server.quit()
class RequestHandler(BaseHTTPRequestHandler):
def do_GET(self):
if self.path == '/parts':
self.send_response(200)
self.send_header('Content-type', 'application/json')
self.end_headers()
self.wfile.write(json.dumps(inventory).encode())
elif self.path.startswith('/order/'):
order_id = self.path.split('/')[-1]
order = next((order for order in orders if order['id'] == order_id),
None)
if order:
self.send_response(200)
self.send_header('Content-type', 'application/json')
self.end_headers()
self.wfile.write(json.dumps(order).encode())
else:
self.send_response(404)
self.end_headers()
else:
self.send_response(404)
self.end_headers()
def do_POST(self):
if self.path == '/order':
auth_header = self.headers.get('Authorization')
if auth_header and auth_header.startswith('Basic '):
encoded_credentials = auth_header.split(' ')[1]
decoded_credentials = b64decode(encoded_credentials).decode('utf-8')
username, password = decoded_credentials.split(':')
if users.get(username) == password:
content_length = int(self.headers['Content-Length'])
post_data = self.rfile.read(content_length)
order = json.loads(post_data.decode())
order_id = str(len(orders) + 1)
order['id'] = order_id
for part in order['items']:
if part in inventory and inventory[part]['quantity'] >=
order['items'][part]:
inventory[part]['quantity'] -= order['items'][part]
else:
self.send_response(400)
self.send_header('Content-type', 'application/json')
self.end_headers()
self.wfile.write(json.dumps({"error": f"Not enough stock
for {part}"}).encode())
return
orders.append(order)
self.send_response(200)
self.send_header('Content-type', 'application/json')
self.end_headers()
self.wfile.write(json.dumps({"message": "Order placed
successfully", "order_id": order_id}).encode())
to_address =-
subject = "Order Confirmation"
body = f"Your order {order_id} has been confirmed. Details:
{json.dumps(order, indent=4)}"
send_email(to_address, subject, body)
else:
self.send_response(401)
self.end_headers()
else:
self.send_response(401)
self.end_headers()
else:
self.send_response(404)
self.end_headers()
def send_monthly_summary():
while True:
now = datetime.now()
if now.day == 1 and now.hour == 0 and now.minute == 0:
to_address =-
subject = "Monthly Purchase Summary"
body = f"Summary of all purchases for the month:\n\n{json.dumps(orders,
indent=4)}"
send_email(to_address, subject, body)
time.sleep(60)
def run_server():
server_address = ('', 8080)
httpd = HTTPServer(server_address, RequestHandler)
print('Running server...')
httpd.serve_forever()
if __name__ == '__main__':
server_thread = threading.Thread(target=run_server)
scheduler_thread = threading.Thread(target=send_monthly_summary)
server_thread.start()
scheduler_thread.start()
This script will allow the system to send receipts to customers each time there is an order confirmed.
Monthly Email Summaryimport smtplib
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
import threading
import time
from datetime import datetime
import json
orders = [
{"id": "1", "items": {"monitor": 2, "keyboard-wireless": 1}, "total": 5100.00},
{"id": "2", "items": {"cable": 5, "webcam": 2}, "total": 1800.00},
]
def send_email(to_address, subject, body):
from_address =-
password = "your_password"
msg = MIMEMultipart()
msg['From'] = from_address
msg['To'] = to_address
msg['Subject'] = subject
msg.attach(MIMEText(body, 'plain'))
server = smtplib.SMTP('smtp.gmail.com', 587)
server.starttls()
server.login(from_address, password)
text = msg.as_string()
server.sendmail(from_address, to_address, text)
server.quit()
def send_monthly_summary():
while True:
now = datetime.now()
if now.day == 1 and now.hour == 0 and now.minute == 0:
to_address =-
subject = "Monthly Purchase Summary"
body = f"Summary of all purchases for the month:\n\n{json.dumps(orders,
indent=4)}"
send_email(to_address, subject, body)
time.sleep(60)
if __name__ == '__main__':
scheduler_thread = threading.Thread(target=send_monthly_summary)
scheduler_thread.start()
This script will send a monthly email summary to the customer of the orders.
Bibliography
Itsy-Bitsy-Spider - Overview. (n.d.). Retrieved from https://github.com/Itsy-Bitsy-Spider
Langen, J. de. (2023). Sending Emails With Python. Retrieved from
https://realpython.com/python-send-email/
Top 12 Ways to Send Emails with Python: Solutions and Examples. (2024). Retrieved from
https://sqlpey.com/python/top-12-ways-to-send-emails-with-python/
email - An email and MIME handling package. (n.d.-a). Retrieved from
https://docs.python.org/3/library/email.html
smtplib - SMTP protocol client. (n.d.-b). Retrieved from
https://docs.python.org/3/library/smtplib.html