feat: ajout Docker Compose et documentation outils
- Dockerfile backend (Python 3.11 + Poetry + Playwright/Chromium) - Dockerfile frontend (Node 20 + Vite build + Nginx) - docker-compose.yml avec services et volumes persistants - Proxy Nginx pour API (/api -> backend:8008) - Healthchecks sur les deux services - Configuration Docker (.env.docker, .dockerignore) - Documentation déploiement Docker dans README - Fichier docs/tools_used.md avec liste des technologies Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
68
.dockerignore
Normal file
68
.dockerignore
Normal file
@@ -0,0 +1,68 @@
|
||||
# Git
|
||||
.git
|
||||
.gitignore
|
||||
|
||||
# Python
|
||||
__pycache__
|
||||
*.py[cod]
|
||||
*$py.class
|
||||
*.so
|
||||
.Python
|
||||
.venv
|
||||
venv/
|
||||
ENV/
|
||||
.mypy_cache/
|
||||
.pytest_cache/
|
||||
.ruff_cache/
|
||||
*.egg-info/
|
||||
dist/
|
||||
|
||||
# Node
|
||||
node_modules/
|
||||
frontend/node_modules/
|
||||
frontend/dist/
|
||||
.npm
|
||||
|
||||
# IDE
|
||||
.vscode/
|
||||
.idea/
|
||||
*.swp
|
||||
*.swo
|
||||
*~
|
||||
|
||||
# Logs et données locales
|
||||
*.log
|
||||
backend/logs/
|
||||
backend/data/
|
||||
backend/app/samples/debug/
|
||||
|
||||
# Fichiers temporaires
|
||||
*.tmp
|
||||
*.temp
|
||||
.DS_Store
|
||||
Thumbs.db
|
||||
|
||||
# Documentation et fichiers de projet
|
||||
*.md
|
||||
!README.md
|
||||
docs/
|
||||
|
||||
# Tests
|
||||
tests/
|
||||
**/tests/
|
||||
.coverage
|
||||
htmlcov/
|
||||
|
||||
# Docker (éviter récursion)
|
||||
docker-compose*.yml
|
||||
Dockerfile*
|
||||
|
||||
# Environnement
|
||||
.env
|
||||
.env.*
|
||||
!.env.example
|
||||
|
||||
# Autres
|
||||
kanban.md
|
||||
TODO.md
|
||||
CHANGELOG.md
|
||||
16
.env.docker
Normal file
16
.env.docker
Normal file
@@ -0,0 +1,16 @@
|
||||
# Configuration Docker - suivi_produit
|
||||
# Copier ce fichier en .env pour utiliser avec docker-compose
|
||||
|
||||
# Environnement (development, production)
|
||||
APP_ENV=production
|
||||
|
||||
# Ports exposés
|
||||
API_PORT=8008
|
||||
FRONTEND_PORT=8080
|
||||
|
||||
# Niveau de log
|
||||
LOG_LEVEL=INFO
|
||||
|
||||
# URL de l'API pour le frontend (utilisé via proxy Nginx)
|
||||
# En production Docker, utiliser /api pour passer par le proxy Nginx
|
||||
VITE_API_URL=/api
|
||||
26
CHANGELOG.md
26
CHANGELOG.md
@@ -1,5 +1,31 @@
|
||||
# CHANGELOG
|
||||
|
||||
## 0.3.0 - Docker (2026-01-20)
|
||||
### Ajouté
|
||||
- Dockerfile backend (Python 3.11 + Poetry + Playwright/Chromium)
|
||||
- Dockerfile frontend (Node 20 + Vite build + Nginx)
|
||||
- docker-compose.yml avec services backend/frontend
|
||||
- Volumes persistants pour données SQLite et logs
|
||||
- Proxy Nginx pour API (/api -> backend:8008)
|
||||
- Healthchecks sur les deux services
|
||||
- Configuration Docker (.env.docker, .dockerignore)
|
||||
- Documentation déploiement Docker dans README
|
||||
|
||||
## 0.2.0 - Améliorations UX (2026-01-20)
|
||||
### Ajouté
|
||||
- Popup logs backend en bas à droite (style terminal, auto-hide 5s)
|
||||
- Slider ratio image/infos dans Settings (mise à jour temps réel)
|
||||
- Sélecteur période graphique (7j/30j/90j/Tout)
|
||||
- Lignes de référence prix conseillé et min 30j dans le graphique
|
||||
- Formatage dates adaptatif (heure si <1j, date+heure si <7j, date si >7j)
|
||||
- Backup/restore base de données dans Settings
|
||||
- Endpoints scheduler (/scrape/scheduler/status, /scrape/scheduler/trigger)
|
||||
|
||||
### Modifié
|
||||
- Lien "Voir sur Amazon" déplacé dans le header de la carte
|
||||
- Store useProductStore intégré avec système de logs
|
||||
- Configuration frontend enrichie (image_ratio)
|
||||
|
||||
## 0.1.0 - Initial setup
|
||||
- création structure backend/frontend
|
||||
- ajout configurations JSON
|
||||
|
||||
69
README.md
69
README.md
@@ -40,9 +40,74 @@ Suite self-hosted pour suivre les prix et l'état des produits Amazon.fr (et aut
|
||||
- `.venv/bin/coverage run -m pytest`
|
||||
- `.venv/bin/coverage report -m`
|
||||
|
||||
## Déploiement
|
||||
1. `docker compose up --build` (à configurer)
|
||||
## Déploiement Docker
|
||||
|
||||
### Lancement rapide
|
||||
```bash
|
||||
# Copier la configuration Docker
|
||||
cp .env.docker .env
|
||||
|
||||
# Build et lancement
|
||||
docker compose up --build -d
|
||||
|
||||
# Voir les logs
|
||||
docker compose logs -f
|
||||
```
|
||||
|
||||
### Services
|
||||
| Service | Port | Description |
|
||||
|---------|------|-------------|
|
||||
| frontend | 8080 | Interface web (Nginx) |
|
||||
| backend | 8008 | API FastAPI + Scheduler |
|
||||
|
||||
### Volumes persistants
|
||||
- `suivi_produit_data` : base SQLite + raw JSON (`backend/data/`)
|
||||
- `suivi_produit_logs` : fichiers de log (`backend/logs/`)
|
||||
|
||||
### Commandes utiles
|
||||
```bash
|
||||
# Arrêter les services
|
||||
docker compose down
|
||||
|
||||
# Reconstruire après modification
|
||||
docker compose up --build -d
|
||||
|
||||
# Voir l'état des services
|
||||
docker compose ps
|
||||
|
||||
# Accéder aux logs d'un service
|
||||
docker compose logs backend -f
|
||||
docker compose logs frontend -f
|
||||
|
||||
# Backup de la base (volume Docker)
|
||||
docker run --rm -v suivi_produit_data:/data -v $(pwd):/backup alpine tar cvf /backup/data_backup.tar /data
|
||||
```
|
||||
|
||||
### Configuration
|
||||
Variables d'environnement (`.env`) :
|
||||
- `API_PORT` : port du backend (défaut: 8008)
|
||||
- `FRONTEND_PORT` : port du frontend (défaut: 8080)
|
||||
- `APP_ENV` : environnement (development/production)
|
||||
- `LOG_LEVEL` : niveau de log (DEBUG/INFO/WARNING/ERROR)
|
||||
|
||||
## Notes
|
||||
- Le scraping est volontairement lent (15-20 produits/jour) pour éviter le blocage.
|
||||
- Le raw JSON est conservé pendant 30 jours dans `backend/data/raw`.
|
||||
|
||||
|
||||
Voici les commandes pour lancer les services :
|
||||
|
||||
Backend (port 8008) :
|
||||
|
||||
|
||||
cd /home/gilles/Documents/vscode/suivi_produit
|
||||
.venv/bin/python -m uvicorn backend.app.main:app --host 0.0.0.0 --port 8008 --reload
|
||||
Frontend (port 5173) :
|
||||
|
||||
|
||||
cd /home/gilles/Documents/vscode/suivi_produit/frontend
|
||||
npm run dev
|
||||
Ou en une seule commande avec Poetry pour le backend :
|
||||
|
||||
|
||||
poetry run uvicorn backend.app.main:app --host 0.0.0.0 --port 8008 --reload
|
||||
14
TODO.md
14
TODO.md
@@ -31,8 +31,18 @@
|
||||
- [x] refresh après ajout produit
|
||||
- [x] décalage horaire dates (UTC → local)
|
||||
- [x] popup prévisualisation avant enregistrement avec scrape preview
|
||||
- [x] améliorations UX avancées (Étape 9)
|
||||
- [x] popup logs backend (style terminal, auto-hide 5s)
|
||||
- [x] slider ratio image/infos dans Settings (temps réel)
|
||||
- [x] sélecteur période graphique (7j/30j/90j/Tout)
|
||||
- [x] lignes référence prix conseillé/min 30j
|
||||
- [x] formatage dates adaptatif selon span
|
||||
- [x] backup/restore BDD dans Settings
|
||||
- [x] lien Amazon dans header carte produit
|
||||
- [ ] dans setting ajoute une option pour sauvegarder image en local plutot qu'image en ligne + bouton pour faire un scrap specifique des images
|
||||
|
||||
|
||||
## Phase 3 - Industrialisation
|
||||
- [ ] dockeriser backend + frontend + scheduler
|
||||
- [ ] docker-compose avec volumes persistants
|
||||
- [x] dockeriser backend + frontend + scheduler
|
||||
- [x] docker-compose avec volumes persistants
|
||||
- [ ] tests E2E frontend
|
||||
|
||||
66
docker-compose.yml
Normal file
66
docker-compose.yml
Normal file
@@ -0,0 +1,66 @@
|
||||
#version: "3.8"
|
||||
|
||||
services:
|
||||
backend:
|
||||
build:
|
||||
context: .
|
||||
dockerfile: docker/backend/Dockerfile
|
||||
container_name: suivi_produit_backend
|
||||
restart: unless-stopped
|
||||
ports:
|
||||
- "${API_PORT:-8008}:8008"
|
||||
environment:
|
||||
- APP_ENV=${APP_ENV:-production}
|
||||
- LOG_LEVEL=${LOG_LEVEL:-INFO}
|
||||
- DATABASE_URL=sqlite:///backend/data/suivi.db
|
||||
volumes:
|
||||
# Persistance données SQLite + raw JSON (bind mount host)
|
||||
- ./backend/data:/app/backend/data
|
||||
# Persistance logs
|
||||
- backend_logs:/app/backend/logs
|
||||
# Config backend (optionnel, pour override)
|
||||
- ./backend/config_backend.json:/app/backend/config_backend.json:ro
|
||||
# Config frontend pour l'API (fallback docker)
|
||||
- ./frontend/public/config_frontend.json:/app/backend/config_frontend.json:ro
|
||||
healthcheck:
|
||||
test: ["CMD", "curl", "-f", "http://localhost:8008/health"]
|
||||
interval: 30s
|
||||
timeout: 10s
|
||||
retries: 3
|
||||
start_period: 10s
|
||||
networks:
|
||||
- suivi_network
|
||||
|
||||
frontend:
|
||||
build:
|
||||
context: .
|
||||
dockerfile: docker/frontend/Dockerfile
|
||||
args:
|
||||
- VITE_API_URL=${VITE_API_URL:-http://backend:8008}
|
||||
container_name: suivi_produit_frontend
|
||||
restart: unless-stopped
|
||||
ports:
|
||||
- "${FRONTEND_PORT:-8080}:80"
|
||||
environment:
|
||||
- VITE_API_URL=${VITE_API_URL:-/api}
|
||||
depends_on:
|
||||
backend:
|
||||
condition: service_healthy
|
||||
healthcheck:
|
||||
test: ["CMD", "wget", "-q", "--spider", "http://localhost/health"]
|
||||
interval: 30s
|
||||
timeout: 5s
|
||||
retries: 3
|
||||
networks:
|
||||
- suivi_network
|
||||
|
||||
volumes:
|
||||
backend_data:
|
||||
name: suivi_produit_data
|
||||
backend_logs:
|
||||
name: suivi_produit_logs
|
||||
|
||||
networks:
|
||||
suivi_network:
|
||||
name: suivi_produit_network
|
||||
driver: bridge
|
||||
70
docker/backend/Dockerfile
Normal file
70
docker/backend/Dockerfile
Normal file
@@ -0,0 +1,70 @@
|
||||
# Dockerfile Backend - FastAPI + Playwright
|
||||
FROM python:3.11-slim
|
||||
|
||||
# Métadonnées
|
||||
LABEL maintainer="gilles" \
|
||||
description="Backend suivi_produit - FastAPI + Playwright scraper"
|
||||
|
||||
# Variables d'environnement
|
||||
ENV PYTHONDONTWRITEBYTECODE=1 \
|
||||
PYTHONUNBUFFERED=1 \
|
||||
POETRY_VERSION=1.7.1 \
|
||||
POETRY_HOME="/opt/poetry" \
|
||||
POETRY_VIRTUALENVS_CREATE=false \
|
||||
POETRY_NO_INTERACTION=1
|
||||
|
||||
# Dépendances système pour Playwright
|
||||
RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||
curl \
|
||||
# Dépendances Playwright/Chromium
|
||||
libnss3 \
|
||||
libnspr4 \
|
||||
libatk1.0-0 \
|
||||
libatk-bridge2.0-0 \
|
||||
libcups2 \
|
||||
libdrm2 \
|
||||
libdbus-1-3 \
|
||||
libxkbcommon0 \
|
||||
libatspi2.0-0 \
|
||||
libxcomposite1 \
|
||||
libxdamage1 \
|
||||
libxfixes3 \
|
||||
libxrandr2 \
|
||||
libgbm1 \
|
||||
libasound2 \
|
||||
libpango-1.0-0 \
|
||||
libcairo2 \
|
||||
fonts-liberation \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# Installer Poetry
|
||||
RUN curl -sSL https://install.python-poetry.org | python3 - \
|
||||
&& ln -s /opt/poetry/bin/poetry /usr/local/bin/poetry
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
# Copier les fichiers de dépendances
|
||||
COPY pyproject.toml poetry.lock* ./
|
||||
|
||||
# Installer les dépendances Python
|
||||
RUN poetry install --only main --no-root
|
||||
|
||||
# Installer Playwright et le navigateur Chromium
|
||||
RUN playwright install chromium \
|
||||
&& playwright install-deps chromium
|
||||
|
||||
# Copier le code source
|
||||
COPY backend/ ./backend/
|
||||
|
||||
# Créer les répertoires de données
|
||||
RUN mkdir -p backend/data backend/logs backend/data/raw
|
||||
|
||||
# Exposer le port
|
||||
EXPOSE 8008
|
||||
|
||||
# Healthcheck
|
||||
HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \
|
||||
CMD curl -f http://localhost:8008/health || exit 1
|
||||
|
||||
# Commande de démarrage
|
||||
CMD ["uvicorn", "backend.app.main:app", "--host", "0.0.0.0", "--port", "8008"]
|
||||
40
docker/frontend/Dockerfile
Normal file
40
docker/frontend/Dockerfile
Normal file
@@ -0,0 +1,40 @@
|
||||
# Dockerfile Frontend - Build Vite + Nginx
|
||||
# Stage 1: Build
|
||||
FROM node:20-alpine AS builder
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
# Copier les fichiers de dépendances
|
||||
COPY frontend/package*.json ./
|
||||
|
||||
# Installer les dépendances
|
||||
RUN npm ci
|
||||
|
||||
# Copier le code source
|
||||
COPY frontend/ ./
|
||||
|
||||
# Argument pour l'URL de l'API (défaut: docker network)
|
||||
ARG VITE_API_URL=http://backend:8008
|
||||
|
||||
# Build de production
|
||||
RUN npm run build
|
||||
|
||||
# Stage 2: Nginx
|
||||
FROM nginx:alpine
|
||||
|
||||
# Copier la config Nginx personnalisée
|
||||
COPY docker/frontend/nginx.conf /etc/nginx/conf.d/default.conf
|
||||
|
||||
# Copier les fichiers buildés
|
||||
COPY --from=builder /app/dist /usr/share/nginx/html
|
||||
|
||||
# Copier le script d'entrypoint pour injecter les variables d'environnement
|
||||
COPY docker/frontend/entrypoint.sh /docker-entrypoint.d/40-env-config.sh
|
||||
RUN chmod +x /docker-entrypoint.d/40-env-config.sh
|
||||
|
||||
# Exposer le port
|
||||
EXPOSE 80
|
||||
|
||||
# Healthcheck
|
||||
HEALTHCHECK --interval=30s --timeout=5s --start-period=5s --retries=3 \
|
||||
CMD wget -q --spider http://localhost/ || exit 1
|
||||
13
docker/frontend/entrypoint.sh
Normal file
13
docker/frontend/entrypoint.sh
Normal file
@@ -0,0 +1,13 @@
|
||||
#!/bin/sh
|
||||
# Entrypoint pour injecter la configuration API au runtime
|
||||
|
||||
# Si VITE_API_URL est défini, on l'injecte dans la config frontend
|
||||
if [ -n "$VITE_API_URL" ]; then
|
||||
# Remplacer l'URL de l'API dans config_frontend.json si présent
|
||||
CONFIG_FILE="/usr/share/nginx/html/config_frontend.json"
|
||||
if [ -f "$CONFIG_FILE" ]; then
|
||||
# Utiliser sed pour remplacer l'URL de l'API
|
||||
sed -i "s|http://localhost:8008|${VITE_API_URL}|g" "$CONFIG_FILE"
|
||||
echo "Config API URL updated to: $VITE_API_URL"
|
||||
fi
|
||||
fi
|
||||
47
docker/frontend/nginx.conf
Normal file
47
docker/frontend/nginx.conf
Normal file
@@ -0,0 +1,47 @@
|
||||
server {
|
||||
listen 80;
|
||||
server_name localhost;
|
||||
root /usr/share/nginx/html;
|
||||
index index.html;
|
||||
resolver 127.0.0.11 ipv6=off valid=10s;
|
||||
|
||||
# Gzip compression
|
||||
gzip on;
|
||||
gzip_vary on;
|
||||
gzip_min_length 1024;
|
||||
gzip_proxied expired no-cache no-store private auth;
|
||||
gzip_types text/plain text/css text/xml text/javascript application/javascript application/json application/xml;
|
||||
|
||||
# Cache static assets
|
||||
location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2)$ {
|
||||
expires 1y;
|
||||
add_header Cache-Control "public, immutable";
|
||||
}
|
||||
|
||||
# SPA fallback - toutes les routes vers index.html
|
||||
location / {
|
||||
try_files $uri $uri/ /index.html;
|
||||
}
|
||||
|
||||
# Proxy vers le backend API
|
||||
location /api/ {
|
||||
set $backend_upstream http://backend:8008;
|
||||
rewrite ^/api/(.*)$ /$1 break;
|
||||
proxy_pass $backend_upstream;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection 'upgrade';
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
proxy_cache_bypass $http_upgrade;
|
||||
}
|
||||
|
||||
# Health check endpoint
|
||||
location /health {
|
||||
access_log off;
|
||||
return 200 "healthy\n";
|
||||
add_header Content-Type text/plain;
|
||||
}
|
||||
}
|
||||
256
docs/tools_used.md
Normal file
256
docs/tools_used.md
Normal file
@@ -0,0 +1,256 @@
|
||||
# Outils et Technologies
|
||||
|
||||
Ce document liste les technologies utilisées dans le projet suivi_produit.
|
||||
|
||||
---
|
||||
|
||||
## Backend
|
||||
|
||||
| Outil | Version | Description |
|
||||
|-------|---------|-------------|
|
||||
| **Python** | 3.11+ | Langage principal du backend |
|
||||
| **FastAPI** | ^0.109 | Framework web asynchrone, génération automatique OpenAPI |
|
||||
| **Uvicorn** | ^0.24 | Serveur ASGI haute performance pour FastAPI |
|
||||
| **Pydantic** | ^2.5 | Validation des données et sérialisation JSON |
|
||||
| **APScheduler** | ^3.11 | Planificateur de tâches pour le scraping périodique |
|
||||
| **Loguru** | ^0.7 | Logging simplifié avec rotation automatique |
|
||||
| **python-dotenv** | ^1.0 | Chargement des variables d'environnement depuis `.env` |
|
||||
|
||||
### Gestion des dépendances
|
||||
| Outil | Description |
|
||||
|-------|-------------|
|
||||
| **Poetry** | Gestionnaire de dépendances et environnements virtuels Python |
|
||||
|
||||
---
|
||||
|
||||
## Scraping
|
||||
|
||||
| Outil | Version | Description |
|
||||
|-------|---------|-------------|
|
||||
| **Playwright** | ^1.40 | Automatisation navigateur (Chromium) pour le scraping |
|
||||
| **BeautifulSoup4** | ^4.12 | Parsing HTML pour extraction des données |
|
||||
|
||||
### Configuration Playwright
|
||||
- **Navigateur** : Chromium (headless par défaut)
|
||||
- **Locale** : `fr-FR`
|
||||
- **Timezone** : `Europe/Paris`
|
||||
- **Viewport** : 1366x768
|
||||
- **Délais aléatoires** : 1-3s entre les requêtes (anti-détection)
|
||||
|
||||
---
|
||||
|
||||
## Base de Données
|
||||
|
||||
| Outil | Description |
|
||||
|-------|-------------|
|
||||
| **SQLite** | Base de données relationnelle légère, fichier unique |
|
||||
| **SQLAlchemy** | ORM Python pour la gestion des modèles et requêtes |
|
||||
|
||||
### Structure des tables
|
||||
- `products` : informations produits (URL, ASIN, titre, catégorie)
|
||||
- `product_snapshots` : historique des prix et états (prix, stock, note, badges)
|
||||
- `scrape_runs` : métadonnées des exécutions de scraping
|
||||
|
||||
### Stockage fichiers
|
||||
- **Raw JSON** : sauvegarde brute des scrapes dans `backend/data/raw/`
|
||||
- **Screenshots** : captures debug dans `backend/data/screenshots/`
|
||||
|
||||
---
|
||||
|
||||
## Frontend
|
||||
|
||||
| Outil | Version | Description |
|
||||
|-------|---------|-------------|
|
||||
| **React** | ^18.3 | Bibliothèque UI composants |
|
||||
| **Vite** | ^5.1 | Bundler et serveur de développement rapide |
|
||||
| **Zustand** | ^4.4 | Gestion d'état globale légère |
|
||||
| **React Router** | ^6.22 | Routage SPA |
|
||||
| **SCSS/Sass** | ^1.77 | Préprocesseur CSS |
|
||||
|
||||
### Graphiques
|
||||
| Outil | Version | Description |
|
||||
|-------|---------|-------------|
|
||||
| **Chart.js** | ^4.5 | Bibliothèque de graphiques |
|
||||
| **react-chartjs-2** | ^5.3 | Wrapper React pour Chart.js |
|
||||
| **chartjs-plugin-annotation** | ^3.1 | Plugin pour lignes de référence |
|
||||
|
||||
### Icônes
|
||||
| Outil | Version | Description |
|
||||
|-------|---------|-------------|
|
||||
| **Font Awesome** | ^6.5 | Bibliothèque d'icônes (Free) |
|
||||
|
||||
---
|
||||
|
||||
## Thème UI
|
||||
|
||||
### Palette Gruvbox Dark
|
||||
Le thème utilise la palette **Gruvbox** en mode sombre :
|
||||
|
||||
| Couleur | Hex | Usage |
|
||||
|---------|-----|-------|
|
||||
| Background | `#282828` | Fond principal |
|
||||
| Background Alt | `#3c3836` | Cartes, modales |
|
||||
| Background Light | `#504945` | Hover, bordures |
|
||||
| Foreground | `#ebdbb2` | Texte principal |
|
||||
| Foreground Dim | `#a89984` | Texte secondaire |
|
||||
| Orange | `#fe8019` | Accent principal, liens |
|
||||
| Yellow | `#fabd2f` | Warnings, tendance stable |
|
||||
| Green | `#b8bb26` | Succès, baisse de prix |
|
||||
| Red | `#fb4934` | Erreurs, hausse de prix |
|
||||
| Blue | `#83a598` | Info, badges |
|
||||
| Purple | `#d3869b` | Badges spéciaux |
|
||||
| Aqua | `#8ec07c` | Stock disponible |
|
||||
|
||||
### Style
|
||||
- **Arrondis** : `border-radius: 8px` (cartes), `4px` (boutons)
|
||||
- **Ombres** : `box-shadow: 0 4px 6px rgba(0,0,0,0.3)`
|
||||
- **Police** : System fonts stack (sans-serif)
|
||||
- **Responsive** : Grille configurable (1-4 colonnes)
|
||||
|
||||
---
|
||||
|
||||
## Tests
|
||||
|
||||
| Outil | Version | Description |
|
||||
|-------|---------|-------------|
|
||||
| **Pytest** | ^8.4 | Framework de tests Python |
|
||||
| **Coverage** | - | Mesure de couverture de code |
|
||||
|
||||
### Commandes
|
||||
```bash
|
||||
# Tests unitaires
|
||||
poetry run pytest
|
||||
|
||||
# Avec couverture
|
||||
poetry run coverage run -m pytest
|
||||
poetry run coverage report -m
|
||||
|
||||
# Test scraper CLI
|
||||
SCRAPE_TEST_MAX=0 poetry run python backend/app/scraper/run_scrape_tests.py
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Qualité de Code
|
||||
|
||||
| Outil | Version | Description |
|
||||
|-------|---------|-------------|
|
||||
| **Ruff** | ^0.1 | Linter Python ultra-rapide (remplace flake8, isort) |
|
||||
| **MyPy** | ^1.9 | Vérification de types statique |
|
||||
| **Pre-commit** | ^3.5 | Hooks Git pour qualité automatique |
|
||||
|
||||
### Configuration Pre-commit
|
||||
```bash
|
||||
# Installation des hooks
|
||||
pre-commit install
|
||||
|
||||
# Exécution manuelle
|
||||
pre-commit run --all-files
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Déploiement
|
||||
|
||||
### Docker
|
||||
| Outil | Description |
|
||||
|-------|-------------|
|
||||
| **Docker** | Conteneurisation des services |
|
||||
| **Docker Compose** | Orchestration multi-conteneurs |
|
||||
| **Nginx** | Serveur web pour le frontend (reverse proxy) |
|
||||
|
||||
### Images Docker
|
||||
| Service | Base | Description |
|
||||
|---------|------|-------------|
|
||||
| Backend | `python:3.11-slim` | FastAPI + Playwright + Chromium |
|
||||
| Frontend | `node:20-alpine` → `nginx:alpine` | Build Vite + serveur Nginx |
|
||||
|
||||
### Volumes
|
||||
| Volume | Contenu |
|
||||
|--------|---------|
|
||||
| `suivi_produit_data` | SQLite + raw JSON |
|
||||
| `suivi_produit_logs` | Fichiers de log |
|
||||
|
||||
### Ports
|
||||
| Service | Port interne | Port exposé |
|
||||
|---------|--------------|-------------|
|
||||
| Backend | 8008 | 8008 |
|
||||
| Frontend | 80 | 8080 |
|
||||
|
||||
---
|
||||
|
||||
## Versionnement
|
||||
|
||||
| Outil | Description |
|
||||
|-------|-------------|
|
||||
| **Git** | Contrôle de version |
|
||||
| **Gitea** | Serveur Git self-hosted |
|
||||
|
||||
### Conventions de commit
|
||||
Format : `type: description`
|
||||
|
||||
| Type | Description |
|
||||
|------|-------------|
|
||||
| `feat` | Nouvelle fonctionnalité |
|
||||
| `fix` | Correction de bug |
|
||||
| `refactor` | Refactorisation sans changement fonctionnel |
|
||||
| `docs` | Documentation |
|
||||
| `style` | Formatage, pas de changement de code |
|
||||
| `test` | Ajout ou modification de tests |
|
||||
| `chore` | Maintenance, dépendances |
|
||||
|
||||
---
|
||||
|
||||
## Structure des Fichiers de Configuration
|
||||
|
||||
| Fichier | Description |
|
||||
|---------|-------------|
|
||||
| `pyproject.toml` | Config Poetry, dépendances Python, scripts |
|
||||
| `backend/config_backend.json` | Paramètres scraping, stores, taxonomie |
|
||||
| `frontend/config_frontend.json` | Thème, layout, champs visibles |
|
||||
| `.env` | Variables d'environnement (non versionné) |
|
||||
| `.env.example` | Template des variables d'environnement |
|
||||
| `.env.docker` | Config pour déploiement Docker |
|
||||
| `docker-compose.yml` | Définition des services Docker |
|
||||
|
||||
---
|
||||
|
||||
## Diagramme d'Architecture
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ Client (Browser) │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
│
|
||||
▼
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ Frontend (Nginx :8080) │
|
||||
│ ┌─────────────────────────────────────────────────────┐ │
|
||||
│ │ React 18 + Vite + Zustand + Chart.js │ │
|
||||
│ │ Thème Gruvbox Dark │ │
|
||||
│ └─────────────────────────────────────────────────────┘ │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
│ /api/*
|
||||
▼
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ Backend (FastAPI :8008) │
|
||||
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
|
||||
│ │ API REST │ │ Scheduler │ │ Scraper │ │
|
||||
│ │ (Routes) │ │ (APScheduler)│ │ (Playwright) │ │
|
||||
│ └──────────────┘ └──────────────┘ └──────────────┘ │
|
||||
│ │ │
|
||||
│ ▼ │
|
||||
│ ┌─────────────────────────────────────────────────────┐ │
|
||||
│ │ SQLAlchemy ORM + SQLite │ │
|
||||
│ └─────────────────────────────────────────────────────┘ │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
│
|
||||
▼
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ Stockage Persistant │
|
||||
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
|
||||
│ │ suivi.db │ │ data/raw/ │ │ logs/ │ │
|
||||
│ │ (SQLite) │ │ (JSON) │ │ (Loguru) │ │
|
||||
│ └──────────────┘ └──────────────┘ └──────────────┘ │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
95
kanban.md
95
kanban.md
@@ -1,13 +1,11 @@
|
||||
# Kanban
|
||||
|
||||
## Backlog
|
||||
- Docker Compose setup
|
||||
- Tests E2E frontend
|
||||
- Récupérer catégorie Amazon lors du scrape
|
||||
- Mode édition dans détail produit
|
||||
- Popup logs backend temps réel
|
||||
- Nouveaux stores (Cdiscount, Backmarket, Aliexpress)
|
||||
- Amélioration graphique (échelles, prix conseillé en fond)
|
||||
- Récupérer manuel utilisateur si présent
|
||||
- Configurer chemins images/captures/debug/logs
|
||||
- Catégories modifiables et extensibles (format JSON)
|
||||
|
||||
## Doing
|
||||
(vide)
|
||||
@@ -38,6 +36,18 @@
|
||||
- Affichage versions frontend/backend dans le header
|
||||
- Lightbox image (clic sur image pour agrandir)
|
||||
- Popup détail produit (clic sur titre ou bouton détail)
|
||||
- Stockage données étendues (a_propos, description, carateristique, details)
|
||||
- Popup détail fullscreen avec toutes les données scrappées
|
||||
- Correction endpoint snapshots (désérialisation JSON)
|
||||
- Extraction catégorie Amazon depuis breadcrumb (Informatique > Composants > ...)
|
||||
- Mode édition dans popup détail produit (titre, catégorie, type, actif)
|
||||
- Popup logs backend (style terminal, 4-5 lignes, auto-hide)
|
||||
- Slider ratio image/infos dans Settings (mise à jour temps réel)
|
||||
- Sélecteur période graphique (7j/30j/90j/Tout) + lignes référence prix
|
||||
- Formatage dates adaptatif (heure seule si <1j, date+heure si <7j)
|
||||
- Backup/restore base de données dans Settings
|
||||
- Lien Amazon déplacé dans header de la carte produit
|
||||
- Docker Compose setup (backend + frontend + volumes persistants)
|
||||
|
||||
## Divers problème à résoudre
|
||||
- consigne : analyse du problème avant de le résoudre + plan
|
||||
@@ -47,73 +57,16 @@
|
||||
- [x] si on clique sur une vignette produit, affiche un popup avec le détail (clic sur titre ou bouton détail)
|
||||
- [x] clique sur image pour afficher une image en grand (lightbox)
|
||||
- [x] afficher dans le header la version du frontend et du backend
|
||||
- [ ] peut on récupérer une catégorie lors du scrap sur le site amazon
|
||||
- [x] pour la popup detail integrer tous les element scrappé (a_propos, description, carateristique, details)
|
||||
- [x] peut on récupérer une catégorie lors du scrap sur le site amazon
|
||||
- [x] verifier si la tache de mise a jours des produits depuis le backend s'effectue bien a l'interval defini (ajout endpoints /scrape/scheduler/status et /scrape/scheduler/trigger)
|
||||
- [ ] peut on récupérer le manuel utilisateur s'il est présent
|
||||
- [ ] configurer chemin des images, des captures, des debug et log
|
||||
- [ ] catégorie : doit être modifiable et extensible avec des sous catégories (format json ?)
|
||||
- [ ] un mode edit dispo dans détail produit
|
||||
- [x] un mode edit dispo dans détail produit
|
||||
- [ ] ajout de nouveaux store: cdiscount, backmarket, aliexpress,... => analyse et création de modules spécifique; détection adresse
|
||||
- [ ] ajout d'un popup de 4 à 5 ligne qui apparaît et disparaît lorsque des commande backend sont exécutées avec son log (style commandline avec effet ombre, bordure arrondi et texte défilant)
|
||||
- [ ] échelle de temps pas clair => brainstorming sur les différentes possibilités d'échelle de prix et de temps (ajouter peut-être en fond le prix conseillé, le prix 30j?)
|
||||
- [ ] pour la popup detail integrer tous les element scrappé dans le json : {
|
||||
"id": "sample-009",
|
||||
"url": "https://www.amazon.fr/dp/B0CWLSQ8FS",
|
||||
"url_canonique": "https://www.amazon.fr/dp/B0CWLSQ8FS",
|
||||
"reference": "B0CWLSQ8FS",
|
||||
"statut": "ok",
|
||||
"donnees": {
|
||||
"url": "https://www.amazon.fr/dp/B0CWLSQ8FS",
|
||||
"asin": "B0CWLSQ8FS",
|
||||
"titre": "Crucial Basics Mémoire pour Ordinateur de Bureau DDR4 3200 MT/s CL22 UDIMM 288 Broches 1,2 V 8 Go",
|
||||
"url_image_principale": "https://m.media-amazon.com/images/I/51h-KCaB5vL._AC_SX679_.jpg",
|
||||
"prix_actuel": 80.0,
|
||||
"prix_conseille": null,
|
||||
"prix_min_30j": null,
|
||||
"prix_conseille_reduction": null,
|
||||
"prix_min_30j_reduction": null,
|
||||
"etat_stock": "Habituellement expédié sous 5 à 6 jours",
|
||||
"en_stock": null,
|
||||
"note": 3.7,
|
||||
"nombre_avis": 27,
|
||||
"choix_amazon": null,
|
||||
"offre_limitee": null,
|
||||
"prime": null,
|
||||
"exclusivite_amazon": null,
|
||||
"a_propos": [
|
||||
"Crucial Basics Mémoire pour ordinateur de bureau DDR4 3200 MT/s CL22 UDIMM 288 broches 1,2 V 8 Go",
|
||||
"Une mise à niveau de la mémoire devrait vous permettre de charger des programmes plus rapidement, d'améliorer la réactivité de votre ordinateur portable et d'offrir des applications multitâches et d'exécution fluides et des applications gourmandes en données.",
|
||||
"Vous verrez également de grandes améliorations dans le processus de travail encore plus simple mais important avec les navigateurs Web et les feuilles de calcul.",
|
||||
"L'installation de la mémoire est aussi simple que d'ouvrir votre ordinateur, de localiser les emplacements de mémoire et d'insérer les modules. C'est tout.",
|
||||
"Pas de mises à jour, pas de nouvelles versions, rien à télécharger — juste des performances plus rapides qui prolongent la durée de vie de votre PC"
|
||||
],
|
||||
"description": "Crucial Basics Mémoire pour ordinateur de bureau DDR4 3200 MT/s CL22 UDIMM 288 broches 1,2 V 8 Go",
|
||||
"carateristique": {
|
||||
"Marque": "Crucial",
|
||||
"Numéro du modèle de l'article": "CB8GU3200",
|
||||
"séries": "Basics",
|
||||
"Couleur": "vert",
|
||||
"Taille de la mémoire vive": "8 Go",
|
||||
"Compatibilité du périphérique": "Ordinateur",
|
||||
"Dimensions de l'article L x L x H": "13.3 x 0.1 x 3.1 centimètres",
|
||||
"Poids du produit": "13 Grammes",
|
||||
"Divers": "Facile à installer, Meilleure performance",
|
||||
"Disponibilité des pièces détachées": "Information indisponible sur les pièces détachées",
|
||||
"Mises à jour logicielles garanties jusqu’à": "Information non disponible"
|
||||
},
|
||||
"details": {
|
||||
"Marque": "Crucial",
|
||||
"Numéro du modèle de l'article": "CB8GU3200",
|
||||
"séries": "Basics",
|
||||
"Couleur": "vert",
|
||||
"Taille de la mémoire vive": "8 Go",
|
||||
"Compatibilité du périphérique": "Ordinateur",
|
||||
"Dimensions de l'article L x L x H": "13.3 x 0.1 x 3.1 centimètres",
|
||||
"Poids du produit": "13 Grammes",
|
||||
"Divers": "Facile à installer, Meilleure performance",
|
||||
"Disponibilité des pièces détachées": "Information indisponible sur les pièces détachées",
|
||||
"Mises à jour logicielles garanties jusqu’à": "Information non disponible",
|
||||
"ASIN": "B0CWLSQ8FS",
|
||||
"Moyenne des commentaires client": "3,7 3,7 sur 5 étoiles (27) 3,7 sur 5 étoiles",
|
||||
"Classement des meilleures ventes d'Amazon": "10 729 en Informatique ( Voir les 100 premiers en Informatique ) 218 en Mémoire RAM",
|
||||
"Date de mise en ligne sur Amazon.fr": "30 juillet 2024"
|
||||
}
|
||||
- [x] ajout d'un popup de 4 à 5 ligne qui apparaît et disparaît lorsque des commande backend sont exécutées avec son log (style commandline avec effet ombre, bordure arrondi et texte défilant)
|
||||
- [x] échelle de temps pas clair => ajout sélecteur période (7j/30j/90j/Tout) + ligne prix conseillé en pointillés
|
||||
- [x] ajouter dans setting une fonction de backup de la bdd (download + restore)
|
||||
- [x] voir sur amzon : deplacer ce lien a gauche de la section active dans la barre de menu
|
||||
- [x] slider ratio image/infos dans Settings (mise à jour temps réel)
|
||||
Reference in New Issue
Block a user