Skip to content

Project: Building Maintenance System ๐Ÿ—๏ธ๐Ÿ› ๏ธ โ€‹

Welcome to your Capstone Project! ๐ŸŽ“

This module brings together everything you've learned:

  • Agile: Planning what to build.
  • Python: Writing the logic.
  • AI: Using your Copilot to build faster and better.

The Mission: You are a Junior Developer at "PropTech Solutions". Your boss wants a quick MVP (Minimum Viable Product) for a system to track maintenance requests (e.g., "Broken heater in Apt 3B").


Phase 1: Agile Planning (The Blueprint) ๐Ÿ“ โ€‹

Integration: Agile Requirements | AI Design

1.1 The Scenario โ€‹

It's Monday morning. Your Product Manager, Sarah, rushes in. "We have tenants complaining that their repair requests are getting lost in emails. We need a central list. Tenants report, Managers fix. Go!"

This is vague. If you code now, you will build the wrong thing.

1.2 From Vague Idea to User Stories โ€‹

Your Task: Use AI to turn Sarah's vague request into clear User Stories.

Prompt:

"Act as a Product Manager. I need to build a 'Building Maintenance System' MVP. Break down the vague requirement 'Tenants report issues, Managers fix them' into 3 specific User Stories. Follow the format: 'As a [User], I want [Action], so that [Value]'."

The Backlog (Your Agile Board):

IDUser StoryPriorityStatus
US-1As a Tenant, I want to submit a request, so that my issue gets fixed.HighTo Do
US-2As a Manager, I want to view pending requests, so I know what to work on.HighTo Do
US-3As a Manager, I want to mark requests as 'Completed', so we don't duplicate work.MediumTo Do

1.3 Designing the Data Structure โ€‹

We aren't using a SQL database yet. We'll use a Python List of Dictionaries.

Prompt:

"I am building a Python script for maintenance requests. Design a dictionary structure for a single request. It needs: ID, Apartment Number, Description, Status (Pending/Done), and Priority."

The Blueprint:

python
# Our "Database" is just a list in memory
requests_db = [
    {
        "id": 1,
        "apt": "3B",
        "description": "Leaky faucet",
        "status": "Pending",
        "priority": "Normal"
    }
]

Phase 2: The Core Logic (Python + AI) ๐Ÿ’ป โ€‹

Integration: Pair Programming | Python Functions

We will build the logic in a file called maintenance.py.

2.1 The Skeleton Builder โ€‹

Don't write the full code yet. Ask AI for the structure.

Prompt:

"Create a Python file structure for maintenance.py. Write empty functions (with pass) and docstrings for:

  1. add_request(db, apt, description)
  2. get_pending_requests(db)
  3. mark_completed(db, request_id) Don't implement the logic yet."

2.2 Implementing with "Driver Mode" โ€‹

Now, you drive. You know Python lists and dicts. Fill in the functions.

Your Code (Draft):

python
def add_request(db, apt, description):
    new_id = len(db) + 1
    req = {
        "id": new_id,
        "apt": apt,
        "description": description,
        "status": "Pending",
        "priority": "Normal"
    }
    db.append(req)
    return req

AI Assist: If you get stuck on how to filter the list for pending requests, ask:

"How do I filter a list of dictionaries in Python to only show ones where status is 'Pending'?"


Phase 3: The CLI Interface (Interaction) ๐Ÿ’ฌ โ€‹

Integration: Python Loops | Prompt Engineering

The logic needs a user interface. We'll build a simple command-line tool (main.py).

Prompt:

"Write a main.py script that acts as the interface. It should import maintenance. Use a while True loop to show a menu:

  1. Report Issue
  2. View Jobs
  3. Finish Job
  4. Exit

Use input() to get user choices. Call the functions from maintenance.py."


Phase 4: Refactoring & Intelligence โœจ โ€‹

Integration: Refactoring

4.1 Auto-Priority (AI Logic) โ€‹

Let's make the system smart. If the user types "Fire" or "Flood", priority should be "High".

Prompt:

"Write a helper function calculate_priority(text). If the text contains urgent words like 'fire', 'leak', 'gas', return 'High'. Otherwise, return 'Normal'. Update my add_request function to use this."

4.2 Making it Persistent (Saving Data) โ€‹

Right now, data vanishes when the script stops.

Prompt:

"Refactor maintenance.py to save the list to a requests.json file.

  1. Write a save_data(db) function using the json module.
  2. Write a load_data() function that returns the list from the file (or an empty list if file missing)."

Phase 5: Quality Assurance (Testing) ๐Ÿงช โ€‹

Integration: Tests & Docs

You can't ship code without testing it.

5.1 Unit Tests โ€‹

Prompt:

"Write 3 pytest test cases for add_request.

  1. Test adding a normal request.
  2. Test that the ID increments correctly.
  3. Test that priority is set to 'High' for urgent keywords."

5.2 Manual "Smoke Test" โ€‹

Run your CLI. Try to break it.

  • Enter text when it asks for a number.
  • Try to complete a request ID that doesn't exist.

Prompt:

"I get a ValueError when I type 'apple' instead of a Request ID. How do I handle this with try/except in my main.py loop?"


Phase 6: Deployment (Going Live) ๐Ÿš€ โ€‹

A CLI is cool, but a Web API is better.

6.1 The Flask Wrapper โ€‹

We will wrap our Python functions in a tiny web server using Flask.

Prompt:

"I have maintenance.py. Create a simple app.py using Flask.

  • GET /requests: Returns the list from get_pending_requests.
  • POST /requests: Takes JSON input and calls add_request."

6.2 Deploying to Render.com โ€‹

  1. Requirements: Ask AI "Generate a requirements.txt for this Flask app."
  2. Git: Push your code to GitHub.
  3. Render: Connect your repo. Render detects the Python app and deploys it.

Result: You now have a live URL (e.g., https://my-proptech-app.onrender.com) that you can send to your "Manager"!


Appendix: The Full Code Solution ๐Ÿงฉ โ€‹

Stuck? Here is the complete working code for the CLI version.

maintenance.py โ€‹

python
import json
import os

DB_FILE = "requests.json"

def load_data():
    if not os.path.exists(DB_FILE):
        return []
    with open(DB_FILE, "r") as f:
        return json.load(f)

def save_data(db):
    with open(DB_FILE, "w") as f:
        json.dump(db, f, indent=4)

def calculate_priority(description):
    urgent_words = ["fire", "leak", "gas", "flood", "broken", "danger"]
    for word in urgent_words:
        if word in description.lower():
            return "High"
    return "Normal"

def add_request(db, apt, description):
    new_id = len(db) + 1
    priority = calculate_priority(description)
    req = {
        "id": new_id,
        "apt": apt,
        "description": description,
        "status": "Pending",
        "priority": priority
    }
    db.append(req)
    save_data(db)
    return req

def get_pending_requests(db):
    return [r for r in db if r["status"] == "Pending"]

def mark_completed(db, request_id):
    for req in db:
        if req["id"] == request_id:
            req["status"] = "Completed"
            save_data(db)
            return True
    return False

main.py โ€‹

python
import maintenance

def main():
    db = maintenance.load_data()
    
    while True:
        print("\n=== PropTech Maintenance System ===")
        print("1. Report Issue")
        print("2. View Pending Jobs")
        print("3. Mark Job Completed")
        print("4. Exit")
        
        choice = input("Select an option: ")
        
        if choice == "1":
            apt = input("Apartment Number: ")
            desc = input("Issue Description: ")
            req = maintenance.add_request(db, apt, desc)
            print(f"โœ… Request #{req['id']} added with {req['priority']} priority.")
            
        elif choice == "2":
            pending = maintenance.get_pending_requests(db)
            print(f"\nThere are {len(pending)} pending jobs:")
            for req in pending:
                print(f"[ID: {req['id']}] {req['apt']}: {req['description']} ({req['priority']})")
                
        elif choice == "3":
            try:
                req_id = int(input("Enter Request ID to finish: "))
                if maintenance.mark_completed(db, req_id):
                    print("โœ… Job marked as completed.")
                else:
                    print("โŒ ID not found.")
            except ValueError:
                print("โŒ Please enter a valid number.")
                
        elif choice == "4":
            print("Goodbye!")
            break
        else:
            print("Invalid choice, try again.")

if __name__ == "__main__":
    main()

Congratulations! You have built a full-stack Python application using an AI-Assisted workflow. ๐Ÿš€