Warehouse Web App: A Flask & Poetry Guide

by Admin 42 views
Warehouse Web App: A Flask & Poetry Guide

Hey there, coding enthusiasts! Ever wanted to build a user-friendly interface for managing a warehouse? Well, in this guide, we're going to dive headfirst into creating a warehouse web app using Flask, a lightweight Python web framework. We'll also use Poetry to manage our project dependencies, ensuring a smooth and organized development process. To make sure our code is top-notch, we'll integrate pylint for static analysis and pytest for comprehensive testing. So, buckle up, because we're about to embark on a fun journey of creating a functional and robust warehouse management system!

Setting Up Your Project with Poetry

First things first, let's get our development environment set up. We'll be using Poetry to manage our dependencies and create a virtual environment. If you haven't already, install Poetry from their official website or using your preferred package manager. With Poetry installed, let's initialize our project. Navigate to your project directory in the terminal and run the following command:

poetry new warehouse_web_app

This command will create a new directory named warehouse_web_app with a basic project structure. Now, let's navigate into the newly created directory:

cd warehouse_web_app

Open the pyproject.toml file. This file is the heart of our project's dependency management. You'll see sections for [tool.poetry] which includes project metadata, and [tool.poetry.dependencies] where we'll declare our project's dependencies. The cool thing about Poetry is it keeps track of all your libraries and their versions so you don't have to!

Let's add Flask to our dependencies:

poetry add flask

Poetry will install Flask and its dependencies, creating a virtual environment for our project. Now, let's add pylint and pytest as development dependencies:

poetry add --group dev pylint pytest

These will be used for code quality checks and testing.

Implementing the Warehouse App Logic

Before diving into the web interface, let's define the core warehouse functionality. We will use the provided Varasto class as the foundation for our warehouse management system. This class handles warehouse capacity, current stock, adding items, and taking items out. Here is the class:

class Varasto:
    def __init__(self, tilavuus, alku_saldo = 0):
        self.tilavuus = self._validoi_tilavuus(tilavuus)
        self.saldo = self._validoi_saldo(alku_saldo, self.tilavuus)

    def _validoi_tilavuus(self, tilavuus):
        if tilavuus > 0.0:
            return tilavuus
        # virheellinen, nollataan
        return 0.0

    def _validoi_saldo(self, alku_saldo, tilavuus):
        if alku_saldo < 0.0:
            # virheellinen, nollataan
            return 0.0
        if alku_saldo <= tilavuus:
            # mahtuu
            return alku_saldo
        # täyteen ja ylimäärä hukkaan!
        return tilavuus

    # huom: ominaisuus voidaan myös laskea.
    # Ei tarvita erillistä kenttää viela_tilaa tms.
    def paljonko_mahtuu(self):
        return self.tilavuus - self.saldo

    def lisaa_varastoon(self, maara):
        if maara < 0:
            return
        if maara <= self.paljonko_mahtuu():
            self.saldo = self.saldo + maara
        else:
            self.saldo = self.tilavuus

    def ota_varastosta(self, maara):
        if maara < 0:
            return 0.0
        if maara > self.saldo:
            kaikki_mita_voidaan = self.saldo
            self.saldo = 0.0

            return kaikki_mita_voidaan

        self.saldo = self.saldo - maara

        return maara

    def __str__(self):
        return f"saldo = {self.saldo}, vielä tilaa {self.paljonko_mahtuu()}"

Create a new file called varasto.py and paste this code inside. Now that we have our Varasto class ready, we can use it to create and manage our warehouses. Each warehouse will have a capacity and a current stock, allowing us to add or remove items. The paljonko_mahtuu() method will be super useful to check how much space is left in the warehouse.

Building the Flask Web Interface

Now, let's create the web interface using Flask. Create a new file named app.py in your project's root directory and add the following code:

from flask import Flask, render_template, request, redirect, url_for
from varasto import Varasto

app = Flask(__name__)

# Initialize some warehouses
warehouses = {
    'warehouse1': Varasto(100, 50),
    'warehouse2': Varasto(200, 100)
}

@app.route('/')
def index():
    return render_template('index.html', warehouses=warehouses)

@app.route('/warehouse/<warehouse_id>')
def warehouse_detail(warehouse_id):
    warehouse = warehouses.get(warehouse_id)
    if warehouse:
        return render_template('warehouse_detail.html', warehouse=warehouse, warehouse_id=warehouse_id)
    else:
        return "Warehouse not found", 404

@app.route('/warehouse/<warehouse_id>/add', methods=['POST'])
def add_to_warehouse(warehouse_id):
    warehouse = warehouses.get(warehouse_id)
    if warehouse:
        amount = float(request.form['amount'])
        warehouse.lisaa_varastoon(amount)
        return redirect(url_for('warehouse_detail', warehouse_id=warehouse_id))
    else:
        return "Warehouse not found", 404

@app.route('/warehouse/<warehouse_id>/remove', methods=['POST'])
def remove_from_warehouse(warehouse_id):
    warehouse = warehouses.get(warehouse_id)
    if warehouse:
        amount = float(request.form['amount'])
        removed = warehouse.ota_varastosta(amount)
        print(f"Removed {removed}")
        return redirect(url_for('warehouse_detail', warehouse_id=warehouse_id))
    else:
        return "Warehouse not found", 404

if __name__ == '__main__':
    app.run(debug=True)

This code sets up a basic Flask application. It defines routes for:

  • /: Displays a list of warehouses.
  • /warehouse/<warehouse_id>: Shows the details of a specific warehouse.
  • /warehouse/<warehouse_id>/add: Handles adding items to a warehouse.
  • /warehouse/<warehouse_id>/remove: Handles removing items from a warehouse.

Creating the HTML Templates

We also need to create some HTML templates to render our web pages. Create a directory named templates in your project's root directory. Inside this directory, create two files: index.html and warehouse_detail.html.

index.html:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Warehouse App</title>
</head>
<body>
    <h1>Warehouses</h1>
    <ul>
        {% for id, warehouse in warehouses.items() %}
            <li><a href="/warehouse/{{ id }}">Warehouse {{ id }}</a></li>
        {% endfor %}
    </ul>
</body>
</html>

warehouse_detail.html:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Warehouse Detail</title>
</head>
<body>
    <h1>Warehouse {{ warehouse_id }}</h1>
    <p>Current Stock: {{ warehouse.saldo }}</p>
    <p>Capacity: {{ warehouse.tilavuus }}</p>
    <p>Space Available: {{ warehouse.paljonko_mahtuu() }}</p>

    <h2>Add Items</h2>
    <form action="/warehouse/{{ warehouse_id }}/add" method="post">
        <label for="amount">Amount:</label>
        <input type="number" id="amount" name="amount" required>
        <button type="submit">Add</button>
    </form>

    <h2>Remove Items</h2>
    <form action="/warehouse/{{ warehouse_id }}/remove" method="post">
        <label for="amount">Amount:</label>
        <input type="number" id="amount" name="amount" required>
        <button type="submit">Remove</button>
    </form>

    <a href="/">Back to Home</a>
</body>
</html>

These templates use Jinja2, Flask's templating engine, to display information about the warehouses and provide forms for adding and removing items.

Running the Application

Now, let's run our application! Make sure you're in the project's root directory and that your virtual environment is activated. Then, use the following command:

poetry run python app.py

This will start the Flask development server. Open your web browser and go to http://127.0.0.1:5000/. You should see the index page with a list of warehouses. Clicking on a warehouse will take you to its detail page, where you can add and remove items.

Testing Your Warehouse App

Testing is crucial for ensuring that your application works correctly. Let's create some tests using pytest. Create a directory named tests in your project's root directory. Inside this directory, create a file named test_varasto.py with the following content:

import pytest
from varasto import Varasto


def test_varasto_init_with_valid_capacity():
    varasto = Varasto(100)
    assert varasto.tilavuus == 100
    assert varasto.saldo == 0


def test_varasto_init_with_initial_stock():
    varasto = Varasto(100, 50)
    assert varasto.saldo == 50


def test_varasto_init_with_invalid_capacity():
    varasto = Varasto(-100)
    assert varasto.tilavuus == 0
    assert varasto.saldo == 0


def test_varasto_init_with_invalid_initial_stock():
    varasto = Varasto(100, -50)
    assert varasto.saldo == 0


def test_lisaa_varastoon_valid_amount():
    varasto = Varasto(100, 50)
    varasto.lisaa_varastoon(20)
    assert varasto.saldo == 70


def test_lisaa_varastoon_exceeding_capacity():
    varasto = Varasto(100, 80)
    varasto.lisaa_varastoon(50)
    assert varasto.saldo == 100


def test_lisaa_varastoon_negative_amount():
    varasto = Varasto(100, 50)
    varasto.lisaa_varastoon(-10)
    assert varasto.saldo == 50


def test_ota_varastosta_valid_amount():
    varasto = Varasto(100, 50)
    removed = varasto.ota_varastosta(20)
    assert removed == 20
    assert varasto.saldo == 30


def test_ota_varastosta_exceeding_stock():
    varasto = Varasto(100, 10)
    removed = varasto.ota_varastosta(20)
    assert removed == 10
    assert varasto.saldo == 0


def test_ota_varastosta_negative_amount():
    varasto = Varasto(100, 50)
    removed = varasto.ota_varastosta(-10)
    assert removed == 0
    assert varasto.saldo == 50


def test_paljonko_mahtuu():
    varasto = Varasto(100, 50)
    assert varasto.paljonko_mahtuu() == 50

This file contains several test functions that cover different scenarios for the Varasto class, such as initialization, adding items, removing items, and handling invalid input. To run these tests, execute the following command in your terminal:

poetry run pytest

Pytest will run the tests and report any failures. Make sure all tests pass to ensure your Varasto class is working correctly.

Code Quality with Pylint

Code quality is just as important as functionality. Let's use pylint to check our code for style and potential errors. Run the following command in your terminal:

poetry run pylint app.py varasto.py

Pylint will analyze your code and provide feedback on style, potential bugs, and code smells. Address any warnings or errors that Pylint reports to improve the quality of your code.

Conclusion: Your Web App Warehouse!

And there you have it, folks! We've successfully built a warehouse web app using Flask, managed our dependencies with Poetry, and ensured code quality with Pylint and testing using pytest. You can expand on this by adding features such as:

  • Database integration to store warehouse data persistently.
  • User authentication and authorization.
  • More sophisticated UI elements.
  • More advanced warehouse management functions (e.g., item tracking, location management, etc.).

This is just the beginning; the possibilities are endless. Keep experimenting, keep coding, and most importantly, keep having fun! Happy coding!