update readme
This commit is contained in:
243
README.md
243
README.md
@@ -2,6 +2,19 @@
|
|||||||
|
|
||||||
A web application for tracking product prices and shopping events. Built with FastAPI (Python) backend and React (TypeScript) frontend.
|
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
|
## Features
|
||||||
|
|
||||||
- **Product Management**: Add, edit, and track product items with prices, categories, and organic status
|
- **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
|
- **Price Tracking**: Monitor price changes over time
|
||||||
- **Modern UI**: Clean, responsive interface built with React and Tailwind CSS
|
- **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
|
## Architecture
|
||||||
|
|
||||||
### Technology Stack
|
### Technology Stack
|
||||||
@@ -26,7 +74,11 @@ A web application for tracking product prices and shopping events. Built with Fa
|
|||||||
- React Router - Client-side routing
|
- React Router - Client-side routing
|
||||||
- Tailwind CSS - Utility-first CSS framework
|
- Tailwind CSS - Utility-first CSS framework
|
||||||
- Axios - HTTP client for API calls
|
- 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
|
### Component Communication
|
||||||
|
|
||||||
@@ -34,7 +86,7 @@ A web application for tracking product prices and shopping events. Built with Fa
|
|||||||
┌─────────────────┐ HTTP/REST API ┌─────────────────┐ SQL Queries ┌─────────────────┐
|
┌─────────────────┐ HTTP/REST API ┌─────────────────┐ SQL Queries ┌─────────────────┐
|
||||||
│ React │ ←─────────────────→ │ FastAPI │ ←───────────────→ │ PostgreSQL │
|
│ React │ ←─────────────────→ │ FastAPI │ ←───────────────→ │ PostgreSQL │
|
||||||
│ Frontend │ JSON requests │ Backend │ SQLAlchemy ORM │ Database │
|
│ 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
|
### 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)
|
#### Products (`products` table)
|
||||||
- `id`: Integer, Primary key, Auto-increment
|
- `id`: Integer, Primary key, Auto-increment
|
||||||
- `name`: String, Product name (indexed, required)
|
- `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)
|
- `organic`: Boolean, Organic flag (default: false)
|
||||||
- `weight`: Float, Weight/volume (optional)
|
- `weight`: Float, Weight/volume (optional)
|
||||||
- `weight_unit`: String, Unit of measurement (default: "piece")
|
- `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
|
### Relationships
|
||||||
|
|
||||||
```
|
```
|
||||||
┌─────────────────┐ ┌─────────────────────────────┐ ┌─────────────────┐
|
┌─────────────────┐ 1:N ┌─────────────────┐ 1:N ┌─────────────────┐ 1:N ┌─────────────────┐
|
||||||
│ Shops │ │ Shopping Event Products │ │ Products │
|
│ Brands │ ────────→ │ Products │ ←──────── │ Groceries │ ←──────── │ Grocery │
|
||||||
│ │ │ (Association Table) │ │ │
|
│ │ │ │ │ │ │ Categories │
|
||||||
│ • id │ ←──────→│ • shopping_event_id │ ←──────→│ • id │
|
│ • id │ │ • id │ │ • id │ │ • id │
|
||||||
│ • name │ 1:N │ • product_id │ N:M │ • name │
|
│ • name │ │ • name │ │ • name │ │ • name │
|
||||||
│ • city │ │ • amount │ │ • category │
|
│ • created_at │ │ • grocery_id │ │ • category_id │ │ • created_at │
|
||||||
│ • address │ │ • price │ │ • organic │
|
│ • updated_at │ │ • brand_id │ │ • created_at │ │ • updated_at │
|
||||||
│ • created_at │ │ │ │ • weight │
|
└─────────────────┘ │ • organic │ │ • updated_at │ │ • updated_at │
|
||||||
└─────────────────┘ └─────────────────────────────┘ │ • weight_unit │
|
│ • weight │ └─────────────────┘ └─────────────────┘
|
||||||
│ │ │ • created_at │
|
│ • weight_unit │
|
||||||
│ │ │ • updated_at │
|
│ • created_at │
|
||||||
│ 1:N │ └─────────────────┘
|
│ • updated_at │
|
||||||
▼ │
|
└─────────────────┘
|
||||||
┌─────────────────┐ │
|
│
|
||||||
│ Shopping Events │ ←───────────────────────┘
|
│ N:M
|
||||||
│ │ 1:N
|
▼
|
||||||
│ • id │
|
┌─────────────────────────────┐
|
||||||
│ • shop_id │
|
│ Shopping Event Products │
|
||||||
│ • date │
|
│ (Association Table) │
|
||||||
│ • total_amount │
|
│ │
|
||||||
│ • notes │
|
│ • id │
|
||||||
│ • created_at │
|
│ • 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
|
### 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
|
- **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)
|
- **Flexible Quantities**: Support for decimal amounts (e.g., 1.5 kg of apples)
|
||||||
- **Auto-calculation**: Total amount can be automatically calculated from individual items
|
- **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
|
- **Audit Trail**: All entities have creation timestamps for tracking
|
||||||
- **Data Integrity**: Foreign key constraints ensure referential integrity
|
- **Data Integrity**: Foreign key constraints ensure referential integrity
|
||||||
|
|
||||||
## Setup Instructions
|
## Development Setup
|
||||||
|
|
||||||
### Prerequisites
|
### Prerequisites
|
||||||
|
|
||||||
@@ -189,6 +280,27 @@ Many-to-many relationship between shopping events and products with additional d
|
|||||||
|
|
||||||
## API Endpoints
|
## 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
|
### Products
|
||||||
- `GET /products/` - List all products
|
- `GET /products/` - List all products
|
||||||
- `POST /products/` - Create new product
|
- `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
|
- `GET /shops/` - List all shops
|
||||||
- `POST /shops/` - Create new shop
|
- `POST /shops/` - Create new shop
|
||||||
- `GET /shops/{id}` - Get specific shop
|
- `GET /shops/{id}` - Get specific shop
|
||||||
|
- `PUT /shops/{id}` - Update shop
|
||||||
|
- `DELETE /shops/{id}` - Delete shop
|
||||||
|
|
||||||
### Shopping Events
|
### Shopping Events
|
||||||
- `GET /shopping-events/` - List all shopping events
|
- `GET /shopping-events/` - List all shopping events
|
||||||
- `POST /shopping-events/` - Create new shopping event
|
- `POST /shopping-events/` - Create new shopping event
|
||||||
- `GET /shopping-events/{id}` - Get specific 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
|
### Statistics
|
||||||
- `GET /stats/categories` - Category spending 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
|
4. **Track Prices**: Monitor how prices change over time
|
||||||
5. **View Statistics**: Analyze spending patterns by category and shop
|
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
|
## Development
|
||||||
|
|
||||||
### Running Tests
|
### Running Tests
|
||||||
@@ -242,44 +393,6 @@ alembic revision --autogenerate -m "Description"
|
|||||||
alembic upgrade head
|
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
|
## Contributing
|
||||||
|
|
||||||
1. Fork the repository
|
1. Fork the repository
|
||||||
|
|||||||
Reference in New Issue
Block a user