update readme

This commit is contained in:
lasse 2025-05-26 21:59:31 +02:00
parent f88a931008
commit b68f1b51ce

243
README.md
View File

@ -2,6 +2,19 @@
A web application for tracking product prices and shopping events. Built with FastAPI (Python) backend and React (TypeScript) frontend.
## Table of Contents
- [Features](#features)
- [Quick Start with Docker](#quick-start-with-docker)
- [Architecture](#architecture)
- [Data Model](#data-model)
- [Development Setup](#development-setup)
- [API Endpoints](#api-endpoints)
- [Usage](#usage)
- [Deployment](#deployment)
- [Development](#development)
- [Contributing](#contributing)
## Features
- **Product Management**: Add, edit, and track product items with prices, categories, and organic status
@ -10,6 +23,41 @@ A web application for tracking product prices and shopping events. Built with Fa
- **Price Tracking**: Monitor price changes over time
- **Modern UI**: Clean, responsive interface built with React and Tailwind CSS
## Quick Start with Docker
The fastest way to get the application running is with Docker Compose:
### Prerequisites
- Docker Engine 20.10+
- Docker Compose 2.0+
### Deploy in 3 Steps
1. **Clone and setup:**
```bash
git clone <your-repo-url>
cd groceries
cp docker.env.example .env
# Edit .env with your secure passwords
```
2. **Start all services:**
```bash
docker-compose up -d
```
3. **Initialize database:**
```bash
docker-compose exec backend alembic upgrade head
```
### Access Your Application
- **Frontend**: http://localhost
- **Backend API**: http://localhost:8000
- **API Documentation**: http://localhost:8000/docs
For detailed Docker deployment instructions, see [DOCKER_DEPLOYMENT.md](DOCKER_DEPLOYMENT.md).
## Architecture
### Technology Stack
@ -26,7 +74,11 @@ A web application for tracking product prices and shopping events. Built with Fa
- React Router - Client-side routing
- Tailwind CSS - Utility-first CSS framework
- Axios - HTTP client for API calls
- React Hook Form - Form handling
**Deployment:**
- Docker & Docker Compose
- Nginx - Web server and reverse proxy
- PostgreSQL - Production database
### Component Communication
@ -34,7 +86,7 @@ A web application for tracking product prices and shopping events. Built with Fa
┌─────────────────┐ HTTP/REST API ┌─────────────────┐ SQL Queries ┌─────────────────┐
│ React │ ←─────────────────→ │ FastAPI │ ←───────────────→ │ PostgreSQL │
│ Frontend │ JSON requests │ Backend │ SQLAlchemy ORM │ Database │
│ (Port 3000) │ JSON responses │ (Port 8000) │ │ (Port 5432) │
│ (Port 80) │ JSON responses │ (Port 8000) │ │ (Port 5432) │
└─────────────────┘ └─────────────────┘ └─────────────────┘
```
@ -42,10 +94,30 @@ A web application for tracking product prices and shopping events. Built with Fa
### Core Entities
#### Brands (`brands` table)
- `id`: Integer, Primary key, Auto-increment
- `name`: String, Brand name (indexed, required)
- `created_at`: DateTime, Creation timestamp (auto-generated)
- `updated_at`: DateTime, Last update timestamp (auto-updated)
#### Grocery Categories (`grocery_categories` table)
- `id`: Integer, Primary key, Auto-increment
- `name`: String, Category name (indexed, required)
- `created_at`: DateTime, Creation timestamp (auto-generated)
- `updated_at`: DateTime, Last update timestamp (auto-updated)
#### Groceries (`groceries` table)
- `id`: Integer, Primary key, Auto-increment
- `name`: String, Grocery item name (indexed, required)
- `category_id`: Integer, Foreign key to grocery_categories (required)
- `created_at`: DateTime, Creation timestamp (auto-generated)
- `updated_at`: DateTime, Last update timestamp (auto-updated)
#### Products (`products` table)
- `id`: Integer, Primary key, Auto-increment
- `name`: String, Product name (indexed, required)
- `category`: String, Food category (required)
- `grocery_id`: Integer, Foreign key to groceries (required)
- `brand_id`: Integer, Foreign key to brands (optional)
- `organic`: Boolean, Organic flag (default: false)
- `weight`: Float, Weight/volume (optional)
- `weight_unit`: String, Unit of measurement (default: "piece")
@ -83,33 +155,52 @@ Many-to-many relationship between shopping events and products with additional d
### Relationships
```
┌─────────────────┐ ┌─────────────────────────────┐ ┌─────────────────┐
│ Shops │ │ Shopping Event Products │ │ Products │
│ │ │ (Association Table) │ │ │
│ • id │ ←──────→│ • shopping_event_id │ ←──────→│ • id │
│ • name │ 1:N │ • product_id │ N:M │ • name │
│ • city │ │ • amount │ │ • category │
│ • address │ │ • price │ │ • organic │
│ • created_at │ │ │ │ • weight │
└─────────────────┘ └─────────────────────────────┘ │ • weight_unit │
│ │ │ • created_at │
│ │ │ • updated_at │
│ 1:N │ └─────────────────┘
▼ │
┌─────────────────┐ │
│ Shopping Events │ ←───────────────────────┘
│ │ 1:N
│ • id │
│ • shop_id │
│ • date │
│ • total_amount │
│ • notes │
│ • created_at │
└─────────────────┘
┌─────────────────┐ 1:N ┌─────────────────┐ 1:N ┌─────────────────┐ 1:N ┌─────────────────┐
│ Brands │ ────────→ │ Products │ ←──────── │ Groceries │ ←──────── │ Grocery │
│ │ │ │ │ │ │ Categories │
│ • id │ │ • id │ │ • id │ │ • id │
│ • name │ │ • name │ │ • name │ │ • name │
│ • created_at │ │ • grocery_id │ │ • category_id │ │ • created_at │
│ • updated_at │ │ • brand_id │ │ • created_at │ │ • updated_at │
└─────────────────┘ │ • organic │ │ • updated_at │ │ • updated_at │
│ • weight │ └─────────────────┘ └─────────────────┘
│ • weight_unit │
│ • created_at │
│ • updated_at │
└─────────────────┘
│ N:M
┌─────────────────────────────┐
│ Shopping Event Products │
│ (Association Table) │
│ │
│ • id │
│ • shopping_event_id │
│ • product_id │
│ • amount │
│ • price │
└─────────────────────────────┘
│ N:1
┌─────────────────┐ 1:N ┌─────────────────┐
│ Shops │ ────────→ │ Shopping Events │
│ │ │ │
│ • id │ │ • id │
│ • name │ │ • shop_id │
│ • city │ │ • date │
│ • address │ │ • total_amount │
│ • created_at │ │ • notes │
│ • updated_at │ │ • created_at │
└─────────────────┘ │ • updated_at │
└─────────────────┘
```
### Key Features
- **Hierarchical Product Organization**: Products are organized by grocery type and category (e.g., "Apples" → "Fruits" → "Fresh Produce")
- **Brand Tracking**: Optional brand association for products
- **Price History**: Each product purchase stores the price at that time, enabling price tracking
- **Flexible Quantities**: Support for decimal amounts (e.g., 1.5 kg of apples)
- **Auto-calculation**: Total amount can be automatically calculated from individual items
@ -117,7 +208,7 @@ Many-to-many relationship between shopping events and products with additional d
- **Audit Trail**: All entities have creation timestamps for tracking
- **Data Integrity**: Foreign key constraints ensure referential integrity
## Setup Instructions
## Development Setup
### Prerequisites
@ -189,6 +280,27 @@ Many-to-many relationship between shopping events and products with additional d
## API Endpoints
### Brands
- `GET /brands/` - List all brands
- `POST /brands/` - Create new brand
- `GET /brands/{id}` - Get specific brand
- `PUT /brands/{id}` - Update brand
- `DELETE /brands/{id}` - Delete brand
### Grocery Categories
- `GET /grocery-categories/` - List all grocery categories
- `POST /grocery-categories/` - Create new grocery category
- `GET /grocery-categories/{id}` - Get specific grocery category
- `PUT /grocery-categories/{id}` - Update grocery category
- `DELETE /grocery-categories/{id}` - Delete grocery category
### Groceries
- `GET /groceries/` - List all groceries
- `POST /groceries/` - Create new grocery
- `GET /groceries/{id}` - Get specific grocery
- `PUT /groceries/{id}` - Update grocery
- `DELETE /groceries/{id}` - Delete grocery
### Products
- `GET /products/` - List all products
- `POST /products/` - Create new product
@ -200,11 +312,15 @@ Many-to-many relationship between shopping events and products with additional d
- `GET /shops/` - List all shops
- `POST /shops/` - Create new shop
- `GET /shops/{id}` - Get specific shop
- `PUT /shops/{id}` - Update shop
- `DELETE /shops/{id}` - Delete shop
### Shopping Events
- `GET /shopping-events/` - List all shopping events
- `POST /shopping-events/` - Create new shopping event
- `GET /shopping-events/{id}` - Get specific shopping event
- `PUT /shopping-events/{id}` - Update shopping event
- `DELETE /shopping-events/{id}` - Delete shopping event
### Statistics
- `GET /stats/categories` - Category spending statistics
@ -218,6 +334,41 @@ Many-to-many relationship between shopping events and products with additional d
4. **Track Prices**: Monitor how prices change over time
5. **View Statistics**: Analyze spending patterns by category and shop
## Deployment
### Docker Deployment (Recommended)
The application includes a complete Docker Compose setup for easy deployment. This is the recommended way to deploy the application in production.
**Quick deployment:**
```bash
# Clone repository
git clone <your-repo-url>
cd groceries
# Setup environment
cp docker.env.example .env
# Edit .env with your production values
# Deploy
docker-compose up -d
# Initialize database
docker-compose exec backend alembic upgrade head
```
**Services included:**
- PostgreSQL database with persistent storage
- FastAPI backend with health checks
- React frontend served by Nginx
- Automatic service restart and dependency management
For comprehensive deployment instructions, troubleshooting, and production considerations, see **[DOCKER_DEPLOYMENT.md](DOCKER_DEPLOYMENT.md)**.
### Manual Deployment
For development or custom deployments, you can also run the services manually using the [Development Setup](#development-setup) instructions above.
## Development
### Running Tests
@ -242,44 +393,6 @@ alembic revision --autogenerate -m "Description"
alembic upgrade head
```
## Docker Deployment
Create `docker-compose.yml` for easy deployment:
```yaml
version: '3.8'
services:
db:
image: postgres:15
environment:
POSTGRES_DB: product_tracker
POSTGRES_USER: product_user
POSTGRES_PASSWORD: your_password
volumes:
- postgres_data:/var/lib/postgresql/data
ports:
- "5432:5432"
backend:
build: ./backend
ports:
- "8000:8000"
depends_on:
- db
environment:
DATABASE_URL: postgresql://product_user:your_password@db:5432/product_tracker
frontend:
build: ./frontend
ports:
- "3000:3000"
depends_on:
- backend
volumes:
postgres_data:
```
## Contributing
1. Fork the repository