Remove unnecessary deployment guides and scripts from the project
This commit removes obsolete deployment documentation, shell scripts, and backup files. Replit-Commit-Author: Agent Replit-Commit-Session-Id: dec54137-d5a2-4406-8ad4-5f2f9fb110bf Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/0715008c-7244-40f4-befc-26c014852236/ce49b69a-6c08-46b0-9012-fdaae8591d14.jpg
No files matched your search
@@ -1,115 +0,0 @@
|
|||||||
# Déploiement Docker de RegisFlow
|
|
||||||
|
|
||||||
## 1. Préparer le serveur
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Créer le répertoire de déploiement
|
|
||||||
mkdir -p /opt/regisflow
|
|
||||||
cd /opt/regisflow
|
|
||||||
|
|
||||||
# Télécharger les fichiers essentiels
|
|
||||||
wget https://raw.githubusercontent.com/votre-repo/regisflow/main/docker-compose.yml
|
|
||||||
wget https://raw.githubusercontent.com/votre-repo/regisflow/main/.env.example
|
|
||||||
cp .env.example .env
|
|
||||||
```
|
|
||||||
|
|
||||||
## 2. Configuration (.env)
|
|
||||||
|
|
||||||
Editez le fichier `.env` selon votre environnement :
|
|
||||||
|
|
||||||
```env
|
|
||||||
# Base de données PostgreSQL
|
|
||||||
DATABASE_URL=postgresql://regisflow:VotreMotDePasseSecurise@regisflow-db:5432/regisflow
|
|
||||||
POSTGRES_PASSWORD=VotreMotDePasseSecurise
|
|
||||||
|
|
||||||
# Application
|
|
||||||
NODE_ENV=production
|
|
||||||
PORT=5000
|
|
||||||
SESSION_SECRET=VotreCleSecreteTresLongueEtSecurisee
|
|
||||||
|
|
||||||
# Timezone
|
|
||||||
TZ=Europe/Paris
|
|
||||||
|
|
||||||
# Sauvegardes
|
|
||||||
BACKUP_RETENTION_DAYS=90
|
|
||||||
MAX_BACKUP_COUNT=20
|
|
||||||
DATA_RETENTION_MONTHS=19
|
|
||||||
|
|
||||||
# Production (optionnel)
|
|
||||||
SECURE_COOKIES=true
|
|
||||||
ALLOWED_DOMAIN=votre-domaine.com
|
|
||||||
```
|
|
||||||
|
|
||||||
## 3. Déploiement
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Construire et démarrer les services
|
|
||||||
docker-compose up -d --build
|
|
||||||
|
|
||||||
# Vérifier le statut
|
|
||||||
docker-compose ps
|
|
||||||
docker-compose logs -f regisflow
|
|
||||||
|
|
||||||
# Les tables sont créées automatiquement au premier démarrage
|
|
||||||
```
|
|
||||||
|
|
||||||
## 4. Vérification
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Tester l'application
|
|
||||||
curl http://localhost:5000/health
|
|
||||||
|
|
||||||
# Voir les logs en temps réel
|
|
||||||
docker-compose logs -f
|
|
||||||
|
|
||||||
# Vérifier la base de données
|
|
||||||
docker-compose exec regisflow-db psql -U regisflow -d regisflow -c "\dt"
|
|
||||||
```
|
|
||||||
|
|
||||||
## 5. Accès à l'application
|
|
||||||
|
|
||||||
- **URL** : http://votre-serveur:5000
|
|
||||||
- **Admin** : admin / admin123
|
|
||||||
- **PostgreSQL** : localhost:5433 (depuis l'hôte)
|
|
||||||
|
|
||||||
## 6. Maintenance
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Arrêter l'application
|
|
||||||
docker-compose down
|
|
||||||
|
|
||||||
# Mise à jour
|
|
||||||
docker-compose pull
|
|
||||||
docker-compose up -d --force-recreate
|
|
||||||
|
|
||||||
# Sauvegardes manuelles
|
|
||||||
docker-compose exec regisflow npm run backup
|
|
||||||
|
|
||||||
# Voir l'utilisation des ressources
|
|
||||||
docker stats
|
|
||||||
```
|
|
||||||
|
|
||||||
## 7. Production avec reverse proxy (Nginx)
|
|
||||||
|
|
||||||
```nginx
|
|
||||||
server {
|
|
||||||
listen 80;
|
|
||||||
server_name votre-domaine.com;
|
|
||||||
|
|
||||||
location / {
|
|
||||||
proxy_pass http://localhost:5000;
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## 8. Sécurité
|
|
||||||
|
|
||||||
- Changez POSTGRES_PASSWORD
|
|
||||||
- Changez SESSION_SECRET
|
|
||||||
- Configurez un firewall
|
|
||||||
- Activez HTTPS avec Let's Encrypt
|
|
||||||
- Sauvegardez régulièrement le volume PostgreSQL
|
|
||||||
@@ -1,74 +0,0 @@
|
|||||||
# Déploiement Docker pour RegisFlow
|
|
||||||
|
|
||||||
## Problème résolu : Image Docker manquante
|
|
||||||
|
|
||||||
### Le problème
|
|
||||||
Portainer essayait de télécharger une image `regisflow-regisflow:latest` qui n'existe pas sur Docker Hub.
|
|
||||||
|
|
||||||
### Solution
|
|
||||||
L'image doit être construite localement avant utilisation.
|
|
||||||
|
|
||||||
## Instructions de déploiement
|
|
||||||
|
|
||||||
### 1. Construction de l'image Docker
|
|
||||||
```bash
|
|
||||||
# Méthode 1: Utiliser le script automatique
|
|
||||||
./build-docker.sh
|
|
||||||
|
|
||||||
# Méthode 2: Construction manuelle
|
|
||||||
docker build -t regisflow:latest .
|
|
||||||
```
|
|
||||||
|
|
||||||
### 2. Démarrage avec Docker Compose
|
|
||||||
```bash
|
|
||||||
# Démarrer tous les services
|
|
||||||
docker-compose up -d
|
|
||||||
|
|
||||||
# Vérifier le statut
|
|
||||||
docker-compose ps
|
|
||||||
```
|
|
||||||
|
|
||||||
### 3. Configuration dans Portainer
|
|
||||||
1. Utiliser le nom d'image : `regisflow:latest`
|
|
||||||
2. Ou utiliser la configuration Docker Compose existante
|
|
||||||
3. L'image sera trouvée localement après construction
|
|
||||||
|
|
||||||
## Vérification du déploiement
|
|
||||||
|
|
||||||
### Vérifier que l'image existe
|
|
||||||
```bash
|
|
||||||
docker images | grep regisflow
|
|
||||||
```
|
|
||||||
|
|
||||||
### Vérifier les logs
|
|
||||||
```bash
|
|
||||||
docker-compose logs -f regisflow
|
|
||||||
```
|
|
||||||
|
|
||||||
### Tester la santé de l'application
|
|
||||||
```bash
|
|
||||||
curl http://localhost:5000/health
|
|
||||||
```
|
|
||||||
|
|
||||||
## Notes importantes
|
|
||||||
- L'image doit être construite sur le serveur de déploiement
|
|
||||||
- La base de données PostgreSQL est incluse dans la configuration
|
|
||||||
- Les volumes sont persistants pour les sauvegardes et données
|
|
||||||
- Le port 5000 est exposé pour l'application
|
|
||||||
- Le port 5433 est exposé pour PostgreSQL (pour éviter les conflits)
|
|
||||||
|
|
||||||
## Résolution des problèmes courants
|
|
||||||
|
|
||||||
### Si l'image n'est pas trouvée
|
|
||||||
1. Vérifier que l'image a été construite : `docker images`
|
|
||||||
2. Reconstruire si nécessaire : `docker build -t regisflow:latest .`
|
|
||||||
|
|
||||||
### Si le conteneur ne démarre pas
|
|
||||||
1. Vérifier les logs : `docker-compose logs regisflow`
|
|
||||||
2. Vérifier la connectivité réseau : `docker network ls`
|
|
||||||
3. Vérifier les variables d'environnement
|
|
||||||
|
|
||||||
### Si PostgreSQL ne se connecte pas
|
|
||||||
1. Vérifier que le conteneur DB est en cours d'exécution
|
|
||||||
2. Vérifier la variable DATABASE_URL
|
|
||||||
3. Attendre que le healthcheck PostgreSQL passe (30s)
|
|
||||||
@@ -1,59 +0,0 @@
|
|||||||
# Solution Finale pour Portainer
|
|
||||||
|
|
||||||
## Problème résolu
|
|
||||||
Le docker-compose.yml a été modifié pour forcer la construction locale et empêcher complètement le téléchargement d'images depuis Docker Hub.
|
|
||||||
|
|
||||||
## Modifications apportées
|
|
||||||
|
|
||||||
### 1. Suppression de la ligne `image:`
|
|
||||||
- Plus de référence à une image Docker Hub
|
|
||||||
- Force Portainer à construire localement
|
|
||||||
|
|
||||||
### 2. Ajout de `pull_policy: never`
|
|
||||||
- Empêche tout téléchargement d'image
|
|
||||||
- Force l'utilisation de la construction locale
|
|
||||||
|
|
||||||
### 3. Configuration de build explicite
|
|
||||||
```yaml
|
|
||||||
build:
|
|
||||||
context: .
|
|
||||||
dockerfile: Dockerfile
|
|
||||||
target: production
|
|
||||||
args:
|
|
||||||
- NODE_ENV=production
|
|
||||||
```
|
|
||||||
|
|
||||||
## Instructions Portainer
|
|
||||||
|
|
||||||
### Dans Portainer:
|
|
||||||
1. **Supprimez l'ancienne stack** si elle existe
|
|
||||||
2. **Créez une nouvelle stack** avec le nom "regisflow"
|
|
||||||
3. **Copiez le contenu** du docker-compose.yml modifié
|
|
||||||
4. **Déployez la stack**
|
|
||||||
|
|
||||||
### Portainer construira automatiquement:
|
|
||||||
- ✅ L'image sera construite depuis le code source
|
|
||||||
- ✅ Aucun téléchargement depuis Docker Hub
|
|
||||||
- ✅ Utilisation du réseau nginx_default
|
|
||||||
- ✅ Volumes persistants conservés
|
|
||||||
|
|
||||||
## Vérification
|
|
||||||
|
|
||||||
Après déploiement, vérifiez:
|
|
||||||
```bash
|
|
||||||
# Statut des conteneurs
|
|
||||||
docker ps | grep regisflow
|
|
||||||
|
|
||||||
# Logs de l'application
|
|
||||||
docker logs regisflow-app
|
|
||||||
|
|
||||||
# Test de l'application
|
|
||||||
curl http://localhost:5000/health
|
|
||||||
```
|
|
||||||
|
|
||||||
## Accès
|
|
||||||
- **URL**: http://votre-serveur:5000
|
|
||||||
- **Login**: admin / admin123
|
|
||||||
- **PostgreSQL**: Port 5433
|
|
||||||
|
|
||||||
Cette configuration finale devrait résoudre définitivement le problème de téléchargement d'image dans Portainer.
|
|
||||||
@@ -1,104 +0,0 @@
|
|||||||
# Guide de déploiement Portainer pour RegisFlow
|
|
||||||
|
|
||||||
## Problème résolu
|
|
||||||
L'erreur `regisflow-regisflow:latest` vient du fait que Portainer cherche une image sur Docker Hub qui n'existe pas.
|
|
||||||
|
|
||||||
## Solution complète
|
|
||||||
|
|
||||||
### Étape 1: Construire l'image sur votre serveur
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Connectez-vous à votre serveur et allez dans le dossier RegisFlow
|
|
||||||
cd /chemin/vers/regisflow
|
|
||||||
|
|
||||||
# Construisez l'image Docker
|
|
||||||
docker build -t regisflow:latest .
|
|
||||||
|
|
||||||
# Vérifiez que l'image est créée
|
|
||||||
docker images | grep regisflow
|
|
||||||
```
|
|
||||||
|
|
||||||
### Étape 2: Créer la Stack dans Portainer
|
|
||||||
|
|
||||||
1. **Ouvrez Portainer** dans votre navigateur
|
|
||||||
2. **Allez dans "Stacks"**
|
|
||||||
3. **Cliquez sur "Add stack"**
|
|
||||||
4. **Donnez un nom** : `regisflow`
|
|
||||||
5. **Copiez le contenu** du fichier `portainer-stack.yml`
|
|
||||||
6. **Cliquez sur "Deploy the stack"**
|
|
||||||
|
|
||||||
### Étape 3: Configuration alternative (Container unique)
|
|
||||||
|
|
||||||
Si vous préférez créer un conteneur unique :
|
|
||||||
|
|
||||||
1. **Allez dans "Containers"**
|
|
||||||
2. **Cliquez sur "Add container"**
|
|
||||||
3. **Nom** : `regisflow-app`
|
|
||||||
4. **Image** : `regisflow:latest`
|
|
||||||
5. **Port mapping** : `5000:5000`
|
|
||||||
6. **Variables d'environnement** :
|
|
||||||
```
|
|
||||||
NODE_ENV=production
|
|
||||||
PORT=5000
|
|
||||||
DATABASE_URL=postgresql://regisflow:RegisFlow2024!PostgreSQL@regisflow-db:5432/regisflow
|
|
||||||
SESSION_SECRET=RegisFlow2024SessionSecretKey1234567890ABCDEF
|
|
||||||
```
|
|
||||||
|
|
||||||
## Script automatique
|
|
||||||
|
|
||||||
Pour simplifier le processus :
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Exécutez le script de déploiement
|
|
||||||
./deploy-portainer.sh
|
|
||||||
```
|
|
||||||
|
|
||||||
## Vérification du déploiement
|
|
||||||
|
|
||||||
### Vérifier les conteneurs
|
|
||||||
```bash
|
|
||||||
docker ps | grep regisflow
|
|
||||||
```
|
|
||||||
|
|
||||||
### Vérifier les logs
|
|
||||||
```bash
|
|
||||||
docker logs regisflow-app
|
|
||||||
```
|
|
||||||
|
|
||||||
### Tester l'application
|
|
||||||
```bash
|
|
||||||
curl http://localhost:5000/health
|
|
||||||
```
|
|
||||||
|
|
||||||
## Résolution des problèmes
|
|
||||||
|
|
||||||
### Si l'image n'est pas trouvée
|
|
||||||
1. Vérifiez que vous êtes sur le bon serveur
|
|
||||||
2. Reconstruisez l'image : `docker build -t regisflow:latest .`
|
|
||||||
3. Vérifiez avec : `docker images | grep regisflow`
|
|
||||||
|
|
||||||
### Si Portainer ne trouve pas l'image
|
|
||||||
1. L'image doit être construite sur le même serveur que Portainer
|
|
||||||
2. Utilisez exactement le nom : `regisflow:latest`
|
|
||||||
3. Pas de préfixe `docker.io/library/`
|
|
||||||
|
|
||||||
### Si la base de données ne se connecte pas
|
|
||||||
1. Vérifiez que PostgreSQL est démarré
|
|
||||||
2. Vérifiez la variable `DATABASE_URL`
|
|
||||||
3. Attendez que le health check passe (30-60 secondes)
|
|
||||||
|
|
||||||
## Points importants
|
|
||||||
|
|
||||||
- ✅ L'image doit être construite localement
|
|
||||||
- ✅ Utilisez `regisflow:latest` (pas `regisflow-regisflow:latest`)
|
|
||||||
- ✅ PostgreSQL inclus dans la stack
|
|
||||||
- ✅ Volumes persistants pour les données
|
|
||||||
- ✅ Health checks configurés
|
|
||||||
- ✅ Ports : 5000 (app) et 5433 (PostgreSQL)
|
|
||||||
|
|
||||||
## Accès à l'application
|
|
||||||
|
|
||||||
Une fois déployé :
|
|
||||||
- **URL** : `http://votre-serveur:5000`
|
|
||||||
- **Connexion** : `admin` / `admin123`
|
|
||||||
- **Changez le mot de passe** après la première connexion
|
|
||||||
@@ -1,153 +0,0 @@
|
|||||||
# Solution Portainer pour RegisFlow
|
|
||||||
|
|
||||||
## Problème identifié
|
|
||||||
Portainer ne peut pas télécharger l'image `regisflow` car elle n'existe pas sur Docker Hub. Il faut construire l'image depuis le code source.
|
|
||||||
|
|
||||||
## Solution 1: Stack avec build automatique (RECOMMANDÉE)
|
|
||||||
|
|
||||||
### Étapes dans Portainer:
|
|
||||||
|
|
||||||
1. **Allez dans "Stacks"**
|
|
||||||
2. **Cliquez sur "Add stack"**
|
|
||||||
3. **Nom de la stack**: `regisflow`
|
|
||||||
4. **Méthode de build**: Repository
|
|
||||||
5. **Repository URL**: Collez l'URL de votre dépôt Git ou utilisez "Upload"
|
|
||||||
6. **Compose file**: Copiez le contenu de `portainer-build-stack.yml`
|
|
||||||
7. **Cliquez sur "Deploy the stack"**
|
|
||||||
|
|
||||||
### Contenu à copier dans Portainer:
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
version: '3.8'
|
|
||||||
|
|
||||||
services:
|
|
||||||
regisflow-db:
|
|
||||||
image: postgres:15-alpine
|
|
||||||
container_name: regisflow-db
|
|
||||||
environment:
|
|
||||||
POSTGRES_DB: regisflow
|
|
||||||
POSTGRES_USER: regisflow
|
|
||||||
POSTGRES_PASSWORD: RegisFlow2024!PostgreSQL
|
|
||||||
volumes:
|
|
||||||
- postgres_data:/var/lib/postgresql/data
|
|
||||||
ports:
|
|
||||||
- "5433:5432"
|
|
||||||
restart: unless-stopped
|
|
||||||
healthcheck:
|
|
||||||
test: ["CMD-SHELL", "pg_isready -U regisflow -d regisflow"]
|
|
||||||
interval: 30s
|
|
||||||
timeout: 10s
|
|
||||||
retries: 5
|
|
||||||
start_period: 30s
|
|
||||||
|
|
||||||
regisflow:
|
|
||||||
build:
|
|
||||||
context: .
|
|
||||||
dockerfile: Dockerfile
|
|
||||||
target: production
|
|
||||||
container_name: regisflow-app
|
|
||||||
depends_on:
|
|
||||||
regisflow-db:
|
|
||||||
condition: service_healthy
|
|
||||||
environment:
|
|
||||||
NODE_ENV: production
|
|
||||||
PORT: 5000
|
|
||||||
DATABASE_URL: postgresql://regisflow:RegisFlow2024!PostgreSQL@regisflow-db:5432/regisflow
|
|
||||||
SESSION_SECRET: RegisFlow2024SessionSecretKey1234567890ABCDEF
|
|
||||||
TZ: Europe/Paris
|
|
||||||
volumes:
|
|
||||||
- backup_data:/app/backups
|
|
||||||
- logs_data:/app/logs
|
|
||||||
ports:
|
|
||||||
- "5000:5000"
|
|
||||||
restart: unless-stopped
|
|
||||||
healthcheck:
|
|
||||||
test: ["CMD-SHELL", "wget --no-verbose --tries=1 --spider http://localhost:5000/health || exit 1"]
|
|
||||||
interval: 30s
|
|
||||||
timeout: 15s
|
|
||||||
retries: 3
|
|
||||||
start_period: 90s
|
|
||||||
|
|
||||||
volumes:
|
|
||||||
postgres_data:
|
|
||||||
backup_data:
|
|
||||||
logs_data:
|
|
||||||
```
|
|
||||||
|
|
||||||
## Solution 2: Construction manuelle puis image
|
|
||||||
|
|
||||||
Si la solution 1 ne fonctionne pas:
|
|
||||||
|
|
||||||
### Étape A: Sur votre serveur
|
|
||||||
```bash
|
|
||||||
# Téléchargez les fichiers RegisFlow sur votre serveur
|
|
||||||
# Puis construisez l'image:
|
|
||||||
docker build -t regisflow:latest .
|
|
||||||
|
|
||||||
# Vérifiez que l'image existe:
|
|
||||||
docker images | grep regisflow
|
|
||||||
```
|
|
||||||
|
|
||||||
### Étape B: Dans Portainer
|
|
||||||
Utilisez ensuite le fichier `portainer-stack.yml` original avec `image: regisflow:latest`
|
|
||||||
|
|
||||||
## Solution 3: Docker Hub personnel (avancée)
|
|
||||||
|
|
||||||
Si vous avez un compte Docker Hub:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Taguez l'image avec votre nom d'utilisateur
|
|
||||||
docker tag regisflow:latest votre-username/regisflow:latest
|
|
||||||
|
|
||||||
# Poussez vers Docker Hub
|
|
||||||
docker push votre-username/regisflow:latest
|
|
||||||
```
|
|
||||||
|
|
||||||
Puis utilisez `votre-username/regisflow:latest` dans Portainer.
|
|
||||||
|
|
||||||
## Vérification du déploiement
|
|
||||||
|
|
||||||
### Dans Portainer:
|
|
||||||
1. Vérifiez que la stack est "Running"
|
|
||||||
2. Consultez les logs des conteneurs
|
|
||||||
3. Vérifiez les health checks
|
|
||||||
|
|
||||||
### Accès à l'application:
|
|
||||||
- URL: `http://votre-serveur:5000`
|
|
||||||
- Login: `admin`
|
|
||||||
- Mot de passe: `admin123`
|
|
||||||
|
|
||||||
### Tests de connectivité:
|
|
||||||
```bash
|
|
||||||
# Test de santé de l'application
|
|
||||||
curl http://localhost:5000/health
|
|
||||||
|
|
||||||
# Vérification PostgreSQL
|
|
||||||
docker exec regisflow-db pg_isready -U regisflow -d regisflow
|
|
||||||
```
|
|
||||||
|
|
||||||
## Résolution des problèmes courants
|
|
||||||
|
|
||||||
### Stack en échec de build:
|
|
||||||
1. Vérifiez que tous les fichiers sont présents
|
|
||||||
2. Consultez les logs de build dans Portainer
|
|
||||||
3. Vérifiez les droits d'accès au Dockerfile
|
|
||||||
|
|
||||||
### Conteneur qui ne démarre pas:
|
|
||||||
1. Vérifiez les logs du conteneur
|
|
||||||
2. Vérifiez les variables d'environnement
|
|
||||||
3. Attendez que PostgreSQL soit prêt (health check)
|
|
||||||
|
|
||||||
### Application inaccessible:
|
|
||||||
1. Vérifiez que le port 5000 est ouvert
|
|
||||||
2. Vérifiez les logs de l'application
|
|
||||||
3. Testez le health check: `/health`
|
|
||||||
|
|
||||||
## Points importants
|
|
||||||
|
|
||||||
✅ **Utilisez la Solution 1 avec build automatique**
|
|
||||||
✅ **Tous les fichiers sources doivent être disponibles pour Portainer**
|
|
||||||
✅ **PostgreSQL démarre en premier (health check)**
|
|
||||||
✅ **Volumes persistants pour les données**
|
|
||||||
✅ **Réseau dédié pour la communication inter-conteneurs**
|
|
||||||
✅ **Health checks configurés pour surveillance automatique**
|
|
||||||
@@ -1,167 +0,0 @@
|
|||||||
# Guide de Mise en Production RegisFlow
|
|
||||||
|
|
||||||
## Configuration rapide pour production
|
|
||||||
|
|
||||||
### 1. Télécharger et préparer
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Créer le dossier de production
|
|
||||||
mkdir /opt/regisflow && cd /opt/regisflow
|
|
||||||
|
|
||||||
# Télécharger les fichiers nécessaires
|
|
||||||
curl -O https://raw.githubusercontent.com/votre-repo/regisflow/main/docker-compose.yml
|
|
||||||
curl -O https://raw.githubusercontent.com/votre-repo/regisflow/main/Dockerfile
|
|
||||||
curl -O https://raw.githubusercontent.com/votre-repo/regisflow/main/docker-entrypoint-simple.sh
|
|
||||||
```
|
|
||||||
|
|
||||||
### 2. Configuration environnement
|
|
||||||
|
|
||||||
Créer le fichier `.env` :
|
|
||||||
|
|
||||||
```env
|
|
||||||
# === OBLIGATOIRE - À MODIFIER ===
|
|
||||||
POSTGRES_PASSWORD=VotreMotDePasseSuperSecurise123!
|
|
||||||
SESSION_SECRET=VotreCleSessionTresLongueEtSecurisee456789ABCDEF
|
|
||||||
|
|
||||||
# === APPLICATION ===
|
|
||||||
NODE_ENV=production
|
|
||||||
PORT=5000
|
|
||||||
TZ=Europe/Paris
|
|
||||||
|
|
||||||
# === SÉCURITÉ ===
|
|
||||||
SECURE_COOKIES=true
|
|
||||||
DATA_RETENTION_MONTHS=19
|
|
||||||
|
|
||||||
# === SAUVEGARDES ===
|
|
||||||
BACKUP_RETENTION_DAYS=90
|
|
||||||
MAX_BACKUP_COUNT=20
|
|
||||||
```
|
|
||||||
|
|
||||||
### 3. Déploiement immédiat
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Option A: Démarrer avec Docker Compose
|
|
||||||
docker-compose up -d --build
|
|
||||||
|
|
||||||
# Option B: Utiliser le script automatisé
|
|
||||||
chmod +x deploy-production.sh
|
|
||||||
./deploy-production.sh
|
|
||||||
|
|
||||||
# Vérifier le fonctionnement
|
|
||||||
curl http://localhost:5000/health
|
|
||||||
|
|
||||||
# Voir les logs
|
|
||||||
docker-compose logs -f regisflow
|
|
||||||
```
|
|
||||||
|
|
||||||
### 3.1 Initialisation manuelle de la base (si nécessaire)
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Si les tables ne se créent pas automatiquement
|
|
||||||
chmod +x init-db.sh
|
|
||||||
./init-db.sh
|
|
||||||
|
|
||||||
# Ou avec une DATABASE_URL spécifique
|
|
||||||
./init-db.sh "postgresql://regisflow:password@localhost:5433/regisflow"
|
|
||||||
```
|
|
||||||
|
|
||||||
### 4. Accès initial
|
|
||||||
|
|
||||||
- **URL** : http://votre-serveur:5000
|
|
||||||
- **Compte admin** : `admin` / `admin123`
|
|
||||||
- **Base de données** : accessible sur port 5433
|
|
||||||
|
|
||||||
### 5. Nginx reverse proxy (recommandé)
|
|
||||||
|
|
||||||
Ajouter à votre configuration Nginx :
|
|
||||||
|
|
||||||
```nginx
|
|
||||||
server {
|
|
||||||
listen 80;
|
|
||||||
server_name votre-domaine.com;
|
|
||||||
|
|
||||||
client_max_body_size 10M; # Pour les photos
|
|
||||||
|
|
||||||
location / {
|
|
||||||
proxy_pass http://localhost:5000;
|
|
||||||
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_connect_timeout 60s;
|
|
||||||
proxy_send_timeout 60s;
|
|
||||||
proxy_read_timeout 60s;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### 6. Maintenance courante
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Voir l'état des services
|
|
||||||
docker-compose ps
|
|
||||||
|
|
||||||
# Redémarrer l'application
|
|
||||||
docker-compose restart regisflow
|
|
||||||
|
|
||||||
# Mise à jour
|
|
||||||
docker-compose down
|
|
||||||
docker-compose up -d --build --force-recreate
|
|
||||||
|
|
||||||
# Sauvegardes manuelles
|
|
||||||
docker-compose exec regisflow node -e "require('./dist/backup-scheduler.js').createAutomaticBackup()"
|
|
||||||
|
|
||||||
# Accès aux données
|
|
||||||
docker-compose exec regisflow-db psql -U regisflow -d regisflow
|
|
||||||
```
|
|
||||||
|
|
||||||
### 7. Monitoring et logs
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Logs en temps réel
|
|
||||||
docker-compose logs -f
|
|
||||||
|
|
||||||
# Utilisation des ressources
|
|
||||||
docker stats regisflow-app regisflow-db
|
|
||||||
|
|
||||||
# Espace disque des volumes
|
|
||||||
docker system df
|
|
||||||
```
|
|
||||||
|
|
||||||
## Fonctionnalités automatiques en production
|
|
||||||
|
|
||||||
✅ **Sauvegardes automatiques** : Toutes les 12h (00:00 et 12:00)
|
|
||||||
✅ **Purge des données** : Automatique après 19 mois (1er de chaque mois)
|
|
||||||
✅ **Health checks** : Surveillance continue des services
|
|
||||||
✅ **Gestion des sessions** : Sessions PostgreSQL sécurisées
|
|
||||||
✅ **Optimisation mémoire** : Configuration pour serveurs de production
|
|
||||||
|
|
||||||
## Sécurité production
|
|
||||||
|
|
||||||
- [ ] Modifier `POSTGRES_PASSWORD` et `SESSION_SECRET`
|
|
||||||
- [ ] Configurer firewall (ports 80, 443, 22 uniquement)
|
|
||||||
- [ ] Activer HTTPS avec certificats SSL
|
|
||||||
- [ ] Sauvegardes régulières vers stockage externe
|
|
||||||
- [ ] Monitoring des logs d'erreurs
|
|
||||||
- [ ] Changer le mot de passe admin par défaut
|
|
||||||
|
|
||||||
## Support et dépannage
|
|
||||||
|
|
||||||
**Problèmes courants :**
|
|
||||||
|
|
||||||
1. **Application inaccessible** : Vérifier `docker-compose ps` et les logs
|
|
||||||
2. **Erreur base de données** : Vérifier que PostgreSQL est démarré
|
|
||||||
3. **Photos ne se sauvegardent pas** : Vérifier les permissions du volume
|
|
||||||
4. **Performance lente** : Augmenter les limites mémoire Docker
|
|
||||||
|
|
||||||
**Commandes de diagnostic :**
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# État complet du système
|
|
||||||
docker-compose ps && docker-compose logs --tail=50
|
|
||||||
docker system df && df -h
|
|
||||||
|
|
||||||
# Test complet de l'application
|
|
||||||
curl -v http://localhost:5000/health
|
|
||||||
curl -v http://localhost:5000/api/auth/default-credentials-status
|
|
||||||
```
|
|
||||||
@@ -1,42 +0,0 @@
|
|||||||
📊 Backup stats: 1 users, 1 stores, 0 sales
|
|
||||||
|
|
||||||
1:10:47 AM [express] GET /api/auth/me 401 in 2ms :: {"error":"Authentication required"}
|
|
||||||
|
|
||||||
1:10:47 AM [express] GET /api/auth/me 401 in 1ms :: {"error":"Authentication required"}
|
|
||||||
|
|
||||||
1:10:47 AM [express] GET /api/auth/default-credentials-status 200 in 331ms :: {"showDefaultCredentia…
|
|
||||||
|
|
||||||
1:11:02 AM [express] POST /api/auth/login 200 in 513ms :: {"user":{"id":1,"username":"admin","email"…
|
|
||||||
|
|
||||||
1:11:03 AM [express] GET /api/auth/me 200 in 71ms :: {"id":1,"username":"admin","email":"admin@examp…
|
|
||||||
|
|
||||||
1:11:03 AM [express] GET /api/auth/me 304 in 9ms :: {"id":1,"username":"admin","email":"admin@exampl…
|
|
||||||
|
|
||||||
1:11:03 AM [express] GET /api/auth/me 304 in 7ms :: {"id":1,"username":"admin","email":"admin@exampl…
|
|
||||||
|
|
||||||
1:11:03 AM [express] GET /api/auth/me 304 in 12ms :: {"id":1,"username":"admin","email":"admin@examp…
|
|
||||||
|
|
||||||
1:11:03 AM [express] GET /api/admin/stores 200 in 30ms :: [{"id":1,"name":"Magasin Principal","addre…
|
|
||||||
|
|
||||||
1:11:11 AM [express] GET /api/admin/users 200 in 9ms :: [{"id":1,"username":"admin","email":"admin@e…
|
|
||||||
|
|
||||||
1:11:11 AM [express] GET /api/admin/backup/stats 200 in 5ms :: {"totalBackups":1,"backupDirectory":"…
|
|
||||||
|
|
||||||
1:11:11 AM [express] GET /api/admin/purge/stats 200 in 7ms :: {"totalSales":0,"oldSales":0,"cutoffDa…
|
|
||||||
|
|
||||||
1:11:36 AM [express] PUT /api/admin/users/1 200 in 410ms :: {"id":1,"username":"admin","email":"mich…
|
|
||||||
|
|
||||||
1:11:36 AM [express] GET /api/admin/users 403 in 4ms :: {"error":"Insufficient permissions"}
|
|
||||||
|
|
||||||
1:11:41 AM [express] GET /api/admin/purge/stats 403 in 5ms :: {"error":"Insufficient permissions"}
|
|
||||||
|
|
||||||
1:11:41 AM [express] GET /api/admin/backup/stats 403 in 20ms :: {"error":"Insufficient permissions"}
|
|
||||||
|
|
||||||
1:11:50 AM [express] PUT /api/admin/users/1 403 in 4ms :: {"error":"Insufficient permissions"}
|
|
||||||
|
|
||||||
1:12:08 AM [express] PUT /api/admin/users/1 403 in 38ms :: {"error":"Insufficient permissions"}
|
|
||||||
|
|
||||||
1:12:11 AM [express] GET /api/admin/purge/stats 403 in 6ms :: {"error":"Insufficient permissions"}
|
|
||||||
|
|
||||||
1:12:11 AM [express] GET /api/admin/backup/stats 403 in 6ms :: {"error":"Insufficient permissions"}
|
|
||||||
|
|
||||||
@@ -1,124 +0,0 @@
|
|||||||
✅ Node.js 18 compatibility fix applied
|
|
||||||
|
|
||||||
file:///app/node_modules/@neondatabase/serverless/index.mjs:1345
|
|
||||||
|
|
||||||
o?t(o):n(u)},"cb"),s=new r(function(o,u){n=o,t=u}).catch(o=>{throw Error.captureStackTrace(
|
|
||||||
|
|
||||||
^
|
|
||||||
|
|
||||||
␍ErrorEvent {
|
|
||||||
|
|
||||||
[Symbol(kTarget)]: WebSocket {
|
|
||||||
|
|
||||||
_events: [Object: null prototype] {
|
|
||||||
|
|
||||||
error: [Function: onError] {
|
|
||||||
|
|
||||||
[Symbol(kIsForOnEventAttribute)]: false,
|
|
||||||
|
|
||||||
[Symbol(kListener)]: [Function (anonymous)]
|
|
||||||
|
|
||||||
},
|
|
||||||
|
|
||||||
message: [Function: onMessage] {
|
|
||||||
|
|
||||||
[Symbol(kIsForOnEventAttribute)]: false,
|
|
||||||
|
|
||||||
[Symbol(kListener)]: [Function (anonymous)]
|
|
||||||
|
|
||||||
},
|
|
||||||
|
|
||||||
close: [Function: onClose] {
|
|
||||||
|
|
||||||
[Symbol(kIsForOnEventAttribute)]: false,
|
|
||||||
|
|
||||||
[Symbol(kListener)]: [Function (anonymous)]
|
|
||||||
|
|
||||||
},
|
|
||||||
|
|
||||||
open: [Function: onOpen] {
|
|
||||||
|
|
||||||
[Symbol(kIsForOnEventAttribute)]: false,
|
|
||||||
|
|
||||||
[Symbol(kListener)]: [Function: handleWebSocketOpen]
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
},
|
|
||||||
|
|
||||||
_eventsCount: 4,
|
|
||||||
|
|
||||||
_maxListeners: undefined,
|
|
||||||
|
|
||||||
_binaryType: 'arraybuffer',
|
|
||||||
|
|
||||||
_closeCode: 1006,
|
|
||||||
|
|
||||||
_closeFrameReceived: false,
|
|
||||||
|
|
||||||
_closeFrameSent: false,
|
|
||||||
|
|
||||||
_closeMessage: Buffer(0) [Uint8Array] [],
|
|
||||||
|
|
||||||
_closeTimer: null,
|
|
||||||
|
|
||||||
_errorEmitted: true,
|
|
||||||
|
|
||||||
_extensions: {},
|
|
||||||
|
|
||||||
_paused: false,
|
|
||||||
|
|
||||||
_protocol: '',
|
|
||||||
|
|
||||||
_readyState: 3,
|
|
||||||
|
|
||||||
_receiver: null,
|
|
||||||
|
|
||||||
_sender: null,
|
|
||||||
|
|
||||||
_socket: null,
|
|
||||||
|
|
||||||
_bufferedAmount: 0,
|
|
||||||
|
|
||||||
_isServer: false,
|
|
||||||
|
|
||||||
_redirects: 0,
|
|
||||||
|
|
||||||
_autoPong: true,
|
|
||||||
|
|
||||||
_url: 'wss://regisflow-db/v2',
|
|
||||||
|
|
||||||
_req: null,
|
|
||||||
|
|
||||||
[Symbol(kCapture)]: false
|
|
||||||
|
|
||||||
},
|
|
||||||
|
|
||||||
[Symbol(kType)]: 'error',
|
|
||||||
|
|
||||||
[Symbol(kError)]: Error: connect ECONNREFUSED 172.22.0.2:443
|
|
||||||
|
|
||||||
at TCPConnectWrap.afterConnect [as oncomplete] (node:net:1555:16) {
|
|
||||||
|
|
||||||
errno: -111,
|
|
||||||
|
|
||||||
code: 'ECONNREFUSED',
|
|
||||||
|
|
||||||
syscall: 'connect',
|
|
||||||
|
|
||||||
address: '172.22.0.2',
|
|
||||||
|
|
||||||
port: 443
|
|
||||||
|
|
||||||
},
|
|
||||||
|
|
||||||
[Symbol(kMessage)]: 'connect ECONNREFUSED 172.22.0.2:443'
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
Node.js v18.20.8
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -1,91 +0,0 @@
|
|||||||
at file:///app/dist/index.js:1081:5
|
|
||||||
at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
|
|
||||||
Node.js v18.20.8
|
|
||||||
🚀 Démarrage de RegisFlow (mode simplifié)...
|
|
||||||
📡 Attente de la base de données...
|
|
||||||
✅ PostgreSQL prêt!
|
|
||||||
📦 Création des tables de la base de données...
|
|
||||||
Reading config file '/app/drizzle.config.ts'
|
|
||||||
Using 'pg' driver for database querying
|
|
||||||
[⣷] Pulling schema from database...
|
|
||||||
[⣯] Pulling schema from database...
|
|
||||||
[✓] Pulling schema from database...
|
|
||||||
[i] No changes detected
|
|
||||||
✅ Tables créées avec succès
|
|
||||||
✅ Base de données configurée
|
|
||||||
🎯 Démarrage de RegisFlow...
|
|
||||||
✅ Node.js 18 compatibility fix applied
|
|
||||||
file:///app/dist/index.js:1032
|
|
||||||
throw new Error(
|
|
||||||
^
|
|
||||||
Error: Could not find the build directory: /app/public, make sure to build the client first
|
|
||||||
at serveStatic (file:///app/dist/index.js:1032:11)
|
|
||||||
at file:///app/dist/index.js:1081:5
|
|
||||||
at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
|
|
||||||
Node.js v18.20.8
|
|
||||||
🚀 Démarrage de RegisFlow (mode simplifié)...
|
|
||||||
📡 Attente de la base de données...
|
|
||||||
✅ PostgreSQL prêt!
|
|
||||||
📦 Création des tables de la base de données...
|
|
||||||
Reading config file '/app/drizzle.config.ts'
|
|
||||||
Using 'pg' driver for database querying
|
|
||||||
[⣷] Pulling schema from database...
|
|
||||||
[⣯] Pulling schema from database...
|
|
||||||
[✓] Pulling schema from database...
|
|
||||||
[i] No changes detected
|
|
||||||
✅ Tables créées avec succès
|
|
||||||
✅ Base de données configurée
|
|
||||||
🎯 Démarrage de RegisFlow...
|
|
||||||
✅ Node.js 18 compatibility fix applied
|
|
||||||
file:///app/dist/index.js:1032
|
|
||||||
throw new Error(
|
|
||||||
^
|
|
||||||
Error: Could not find the build directory: /app/public, make sure to build the client first
|
|
||||||
at serveStatic (file:///app/dist/index.js:1032:11)
|
|
||||||
at file:///app/dist/index.js:1081:5
|
|
||||||
at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
|
|
||||||
Node.js v18.20.8
|
|
||||||
🚀 Démarrage de RegisFlow (mode simplifié)...
|
|
||||||
📡 Attente de la base de données...
|
|
||||||
✅ PostgreSQL prêt!
|
|
||||||
📦 Création des tables de la base de données...
|
|
||||||
Reading config file '/app/drizzle.config.ts'
|
|
||||||
Using 'pg' driver for database querying
|
|
||||||
[⣷] Pulling schema from database...
|
|
||||||
[⣯] Pulling schema from database...
|
|
||||||
[✓] Pulling schema from database...
|
|
||||||
[i] No changes detected
|
|
||||||
✅ Tables créées avec succès
|
|
||||||
✅ Base de données configurée
|
|
||||||
🎯 Démarrage de RegisFlow...
|
|
||||||
✅ Node.js 18 compatibility fix applied
|
|
||||||
file:///app/dist/index.js:1032
|
|
||||||
throw new Error(
|
|
||||||
^
|
|
||||||
Error: Could not find the build directory: /app/public, make sure to build the client first
|
|
||||||
at serveStatic (file:///app/dist/index.js:1032:11)
|
|
||||||
at file:///app/dist/index.js:1081:5
|
|
||||||
at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
|
|
||||||
Node.js v18.20.8
|
|
||||||
🚀 Démarrage de RegisFlow (mode simplifié)...
|
|
||||||
📡 Attente de la base de données...
|
|
||||||
✅ PostgreSQL prêt!
|
|
||||||
📦 Création des tables de la base de données...
|
|
||||||
Reading config file '/app/drizzle.config.ts'
|
|
||||||
Using 'pg' driver for database querying
|
|
||||||
[⣷] Pulling schema from database...
|
|
||||||
[⣯] Pulling schema from database...
|
|
||||||
[✓] Pulling schema from database...
|
|
||||||
[i] No changes detected
|
|
||||||
✅ Tables créées avec succès
|
|
||||||
✅ Base de données configurée
|
|
||||||
🎯 Démarrage de RegisFlow...
|
|
||||||
✅ Node.js 18 compatibility fix applied
|
|
||||||
file:///app/dist/index.js:1032
|
|
||||||
throw new Error(
|
|
||||||
^
|
|
||||||
Error: Could not find the build directory: /app/public, make sure to build the client first
|
|
||||||
at serveStatic (file:///app/dist/index.js:1032:11)
|
|
||||||
at file:///app/dist/index.js:1081:5
|
|
||||||
at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
|
|
||||||
Node.js v18.20.8
|
|
||||||
@@ -1,95 +0,0 @@
|
|||||||
at async DatabaseStorage.getAllUsers (file:///app/dist/index.js:187:12)
|
|
||||||
at async DatabaseStorage.initializeDefaults (file:///app/dist/index.js:258:27)
|
|
||||||
at async registerRoutes (file:///app/dist/index.js:510:22)
|
|
||||||
at async file:///app/dist/index.js:1071:18 {
|
|
||||||
length: 105,
|
|
||||||
severity: 'ERROR',
|
|
||||||
code: '42P01',
|
|
||||||
detail: undefined,
|
|
||||||
hint: undefined,
|
|
||||||
position: '139',
|
|
||||||
internalPosition: undefined,
|
|
||||||
internalQuery: undefined,
|
|
||||||
where: undefined,
|
|
||||||
schema: undefined,
|
|
||||||
table: undefined,
|
|
||||||
column: undefined,
|
|
||||||
dataType: undefined,
|
|
||||||
constraint: undefined,
|
|
||||||
file: 'parse_relation.c',
|
|
||||||
line: '1392',
|
|
||||||
routine: 'parserOpenTable'
|
|
||||||
}
|
|
||||||
Node.js v18.20.8
|
|
||||||
🚀 Démarrage de RegisFlow (mode simplifié)...
|
|
||||||
📡 Attente de la base de données...
|
|
||||||
✅ PostgreSQL prêt!
|
|
||||||
✅ Base de données configurée
|
|
||||||
🎯 Démarrage de RegisFlow...
|
|
||||||
✅ Node.js 18 compatibility fix applied
|
|
||||||
/app/node_modules/pg-pool/index.js:45
|
|
||||||
Error.captureStackTrace(err)
|
|
||||||
^
|
|
||||||
error: relation "users" does not exist
|
|
||||||
at /app/node_modules/pg-pool/index.js:45:11
|
|
||||||
at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
|
|
||||||
at async file:///app/node_modules/drizzle-orm/node-postgres/session.js:83:22
|
|
||||||
at async DatabaseStorage.getAllUsers (file:///app/dist/index.js:187:12)
|
|
||||||
at async DatabaseStorage.initializeDefaults (file:///app/dist/index.js:258:27)
|
|
||||||
at async registerRoutes (file:///app/dist/index.js:510:22)
|
|
||||||
at async file:///app/dist/index.js:1071:18 {
|
|
||||||
length: 105,
|
|
||||||
severity: 'ERROR',
|
|
||||||
code: '42P01',
|
|
||||||
detail: undefined,
|
|
||||||
hint: undefined,
|
|
||||||
position: '139',
|
|
||||||
internalPosition: undefined,
|
|
||||||
internalQuery: undefined,
|
|
||||||
where: undefined,
|
|
||||||
schema: undefined,
|
|
||||||
table: undefined,
|
|
||||||
column: undefined,
|
|
||||||
dataType: undefined,
|
|
||||||
constraint: undefined,
|
|
||||||
file: 'parse_relation.c',
|
|
||||||
line: '1392',
|
|
||||||
routine: 'parserOpenTable'
|
|
||||||
}
|
|
||||||
Node.js v18.20.8
|
|
||||||
🚀 Démarrage de RegisFlow (mode simplifié)...
|
|
||||||
📡 Attente de la base de données...
|
|
||||||
✅ PostgreSQL prêt!
|
|
||||||
✅ Base de données configurée
|
|
||||||
🎯 Démarrage de RegisFlow...
|
|
||||||
✅ Node.js 18 compatibility fix applied
|
|
||||||
/app/node_modules/pg-pool/index.js:45
|
|
||||||
Error.captureStackTrace(err)
|
|
||||||
^
|
|
||||||
error: relation "users" does not exist
|
|
||||||
at /app/node_modules/pg-pool/index.js:45:11
|
|
||||||
at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
|
|
||||||
at async file:///app/node_modules/drizzle-orm/node-postgres/session.js:83:22
|
|
||||||
at async DatabaseStorage.getAllUsers (file:///app/dist/index.js:187:12)
|
|
||||||
at async DatabaseStorage.initializeDefaults (file:///app/dist/index.js:258:27)
|
|
||||||
at async registerRoutes (file:///app/dist/index.js:510:22)
|
|
||||||
at async file:///app/dist/index.js:1071:18 {
|
|
||||||
length: 105,
|
|
||||||
severity: 'ERROR',
|
|
||||||
code: '42P01',
|
|
||||||
detail: undefined,
|
|
||||||
hint: undefined,
|
|
||||||
position: '139',
|
|
||||||
internalPosition: undefined,
|
|
||||||
internalQuery: undefined,
|
|
||||||
where: undefined,
|
|
||||||
schema: undefined,
|
|
||||||
table: undefined,
|
|
||||||
column: undefined,
|
|
||||||
dataType: undefined,
|
|
||||||
constraint: undefined,
|
|
||||||
file: 'parse_relation.c',
|
|
||||||
line: '1392',
|
|
||||||
routine: 'parserOpenTable'
|
|
||||||
}
|
|
||||||
Node.js v18.20.8
|
|
||||||
|
Before Width: | Height: | Size: 4.4 KiB |
|
Before Width: | Height: | Size: 5.6 KiB |
|
Before Width: | Height: | Size: 61 KiB |
|
Before Width: | Height: | Size: 7.5 KiB |
|
Before Width: | Height: | Size: 8.5 KiB |
|
Before Width: | Height: | Size: 23 KiB |
|
Before Width: | Height: | Size: 26 KiB |
|
Before Width: | Height: | Size: 35 KiB |
|
Before Width: | Height: | Size: 28 KiB |
|
Before Width: | Height: | Size: 19 KiB |
@@ -1,151 +0,0 @@
|
|||||||
{
|
|
||||||
"timestamp": "2025-07-09T19:27:47.907Z",
|
|
||||||
"version": "1.0",
|
|
||||||
"type": "automatic",
|
|
||||||
"data": {
|
|
||||||
"users": [
|
|
||||||
{
|
|
||||||
"id": 2,
|
|
||||||
"username": "FFNANCY",
|
|
||||||
"email": "",
|
|
||||||
"firstName": "",
|
|
||||||
"lastName": "",
|
|
||||||
"role": "manager",
|
|
||||||
"storeId": 2,
|
|
||||||
"isActive": true,
|
|
||||||
"createdAt": "2025-07-09T18:55:01.413Z",
|
|
||||||
"updatedAt": "2025-07-09T18:55:01.413Z"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 1,
|
|
||||||
"username": "admin",
|
|
||||||
"email": "admin@example.com",
|
|
||||||
"firstName": "Administrateur",
|
|
||||||
"lastName": "Principal",
|
|
||||||
"role": "admin",
|
|
||||||
"storeId": 1,
|
|
||||||
"isActive": true,
|
|
||||||
"createdAt": "2025-07-09T18:37:53.865Z",
|
|
||||||
"updatedAt": "2025-07-09T18:37:53.865Z"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"stores": [
|
|
||||||
{
|
|
||||||
"id": 2,
|
|
||||||
"name": "Houdemont",
|
|
||||||
"address": "",
|
|
||||||
"phone": "",
|
|
||||||
"email": "",
|
|
||||||
"isActive": true,
|
|
||||||
"createdAt": "2025-07-09T19:00:30.782Z",
|
|
||||||
"updatedAt": "2025-07-09T19:00:30.782Z"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 1,
|
|
||||||
"name": "Frouard",
|
|
||||||
"address": "À définir",
|
|
||||||
"phone": "",
|
|
||||||
"email": "",
|
|
||||||
"isActive": true,
|
|
||||||
"createdAt": "2025-07-09T18:37:53.432Z",
|
|
||||||
"updatedAt": "2025-07-09T18:37:53.432Z"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"sales": [
|
|
||||||
{
|
|
||||||
"id": 5,
|
|
||||||
"storeId": 2,
|
|
||||||
"userId": 2,
|
|
||||||
"timestamp": "2025-07-09T19:16:46.797Z",
|
|
||||||
"vendeur": "Moi",
|
|
||||||
"dateVente": "2025-07-09",
|
|
||||||
"typeArticle": "Fusée",
|
|
||||||
"categorie": "F2",
|
|
||||||
"quantite": 10,
|
|
||||||
"gencode": "3660092323745",
|
|
||||||
"nom": " ASSOCIATION GRAND AIR",
|
|
||||||
"prenom": "Anne-Laure",
|
|
||||||
"dateNaissance": "2025-06-03",
|
|
||||||
"lieuNaissance": "Bar le duc",
|
|
||||||
"typeIdentite": "Passeport",
|
|
||||||
"numeroIdentite": "qsdfqsdgc23445",
|
|
||||||
"autoriteDelivrance": "Frouard",
|
|
||||||
"dateDelivrance": "2025-07-01",
|
|
||||||
"photoRecto": null,
|
|
||||||
"photoVerso": null
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 2,
|
|
||||||
"storeId": 2,
|
|
||||||
"userId": 1,
|
|
||||||
"timestamp": "2025-07-09T19:07:15.650Z",
|
|
||||||
"vendeur": "Moi",
|
|
||||||
"dateVente": "2025-07-09",
|
|
||||||
"typeArticle": "Pétard aérien",
|
|
||||||
"categorie": "F3",
|
|
||||||
"quantite": 1,
|
|
||||||
"gencode": "3660092323745",
|
|
||||||
"nom": "SCHAL",
|
|
||||||
"prenom": "Michaël",
|
|
||||||
"dateNaissance": "2025-07-02",
|
|
||||||
"lieuNaissance": "Bar le duc",
|
|
||||||
"typeIdentite": "CNI",
|
|
||||||
"numeroIdentite": "qsdfqsdgc23445",
|
|
||||||
"autoriteDelivrance": "Frouard",
|
|
||||||
"dateDelivrance": "2025-07-01",
|
|
||||||
"photoRecto": null,
|
|
||||||
"photoVerso": null
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 1,
|
|
||||||
"storeId": 2,
|
|
||||||
"userId": 1,
|
|
||||||
"timestamp": "2025-07-09T19:05:20.904Z",
|
|
||||||
"vendeur": "Moi",
|
|
||||||
"dateVente": "2025-07-09",
|
|
||||||
"typeArticle": "Pétard aérien",
|
|
||||||
"categorie": "F3",
|
|
||||||
"quantite": 1,
|
|
||||||
"gencode": "3660092323745",
|
|
||||||
"nom": "SCHAL",
|
|
||||||
"prenom": "Michaël",
|
|
||||||
"dateNaissance": "2025-07-02",
|
|
||||||
"lieuNaissance": "Bar le duc",
|
|
||||||
"typeIdentite": "CNI",
|
|
||||||
"numeroIdentite": "qsdfqsdgc23445",
|
|
||||||
"autoriteDelivrance": "Frouard",
|
|
||||||
"dateDelivrance": "2025-07-01",
|
|
||||||
"photoRecto": null,
|
|
||||||
"photoVerso": null
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 4,
|
|
||||||
"storeId": 1,
|
|
||||||
"userId": 1,
|
|
||||||
"timestamp": "2025-07-09T19:11:36.505Z",
|
|
||||||
"vendeur": "Moi",
|
|
||||||
"dateVente": "2025-07-09",
|
|
||||||
"typeArticle": "Batterie",
|
|
||||||
"categorie": "F3",
|
|
||||||
"quantite": 1,
|
|
||||||
"gencode": "3660092323745",
|
|
||||||
"nom": "SCHAL",
|
|
||||||
"prenom": "Michaël",
|
|
||||||
"dateNaissance": "2025-07-18",
|
|
||||||
"lieuNaissance": "Bar le duc",
|
|
||||||
"typeIdentite": "CNI",
|
|
||||||
"numeroIdentite": "qsdfqsdgc23445",
|
|
||||||
"autoriteDelivrance": "Frouard",
|
|
||||||
"dateDelivrance": "2025-07-01",
|
|
||||||
"photoRecto": null,
|
|
||||||
"photoVerso": null
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"metadata": {
|
|
||||||
"totalUsers": 2,
|
|
||||||
"totalStores": 2,
|
|
||||||
"totalSales": 4,
|
|
||||||
"exportedBy": "system-auto-backup"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,151 +0,0 @@
|
|||||||
{
|
|
||||||
"timestamp": "2025-07-09T19:28:49.721Z",
|
|
||||||
"version": "1.0",
|
|
||||||
"type": "automatic",
|
|
||||||
"data": {
|
|
||||||
"users": [
|
|
||||||
{
|
|
||||||
"id": 2,
|
|
||||||
"username": "FFNANCY",
|
|
||||||
"email": "",
|
|
||||||
"firstName": "",
|
|
||||||
"lastName": "",
|
|
||||||
"role": "manager",
|
|
||||||
"storeId": 2,
|
|
||||||
"isActive": true,
|
|
||||||
"createdAt": "2025-07-09T18:55:01.413Z",
|
|
||||||
"updatedAt": "2025-07-09T18:55:01.413Z"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 1,
|
|
||||||
"username": "admin",
|
|
||||||
"email": "admin@example.com",
|
|
||||||
"firstName": "Administrateur",
|
|
||||||
"lastName": "Principal",
|
|
||||||
"role": "admin",
|
|
||||||
"storeId": 1,
|
|
||||||
"isActive": true,
|
|
||||||
"createdAt": "2025-07-09T18:37:53.865Z",
|
|
||||||
"updatedAt": "2025-07-09T18:37:53.865Z"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"stores": [
|
|
||||||
{
|
|
||||||
"id": 2,
|
|
||||||
"name": "Houdemont",
|
|
||||||
"address": "",
|
|
||||||
"phone": "",
|
|
||||||
"email": "",
|
|
||||||
"isActive": true,
|
|
||||||
"createdAt": "2025-07-09T19:00:30.782Z",
|
|
||||||
"updatedAt": "2025-07-09T19:00:30.782Z"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 1,
|
|
||||||
"name": "Frouard",
|
|
||||||
"address": "À définir",
|
|
||||||
"phone": "",
|
|
||||||
"email": "",
|
|
||||||
"isActive": true,
|
|
||||||
"createdAt": "2025-07-09T18:37:53.432Z",
|
|
||||||
"updatedAt": "2025-07-09T18:37:53.432Z"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"sales": [
|
|
||||||
{
|
|
||||||
"id": 5,
|
|
||||||
"storeId": 2,
|
|
||||||
"userId": 2,
|
|
||||||
"timestamp": "2025-07-09T19:16:46.797Z",
|
|
||||||
"vendeur": "Moi",
|
|
||||||
"dateVente": "2025-07-09",
|
|
||||||
"typeArticle": "Fusée",
|
|
||||||
"categorie": "F2",
|
|
||||||
"quantite": 10,
|
|
||||||
"gencode": "3660092323745",
|
|
||||||
"nom": " ASSOCIATION GRAND AIR",
|
|
||||||
"prenom": "Anne-Laure",
|
|
||||||
"dateNaissance": "2025-06-03",
|
|
||||||
"lieuNaissance": "Bar le duc",
|
|
||||||
"typeIdentite": "Passeport",
|
|
||||||
"numeroIdentite": "qsdfqsdgc23445",
|
|
||||||
"autoriteDelivrance": "Frouard",
|
|
||||||
"dateDelivrance": "2025-07-01",
|
|
||||||
"photoRecto": null,
|
|
||||||
"photoVerso": null
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 2,
|
|
||||||
"storeId": 2,
|
|
||||||
"userId": 1,
|
|
||||||
"timestamp": "2025-07-09T19:07:15.650Z",
|
|
||||||
"vendeur": "Moi",
|
|
||||||
"dateVente": "2025-07-09",
|
|
||||||
"typeArticle": "Pétard aérien",
|
|
||||||
"categorie": "F3",
|
|
||||||
"quantite": 1,
|
|
||||||
"gencode": "3660092323745",
|
|
||||||
"nom": "SCHAL",
|
|
||||||
"prenom": "Michaël",
|
|
||||||
"dateNaissance": "2025-07-02",
|
|
||||||
"lieuNaissance": "Bar le duc",
|
|
||||||
"typeIdentite": "CNI",
|
|
||||||
"numeroIdentite": "qsdfqsdgc23445",
|
|
||||||
"autoriteDelivrance": "Frouard",
|
|
||||||
"dateDelivrance": "2025-07-01",
|
|
||||||
"photoRecto": null,
|
|
||||||
"photoVerso": null
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 1,
|
|
||||||
"storeId": 2,
|
|
||||||
"userId": 1,
|
|
||||||
"timestamp": "2025-07-09T19:05:20.904Z",
|
|
||||||
"vendeur": "Moi",
|
|
||||||
"dateVente": "2025-07-09",
|
|
||||||
"typeArticle": "Pétard aérien",
|
|
||||||
"categorie": "F3",
|
|
||||||
"quantite": 1,
|
|
||||||
"gencode": "3660092323745",
|
|
||||||
"nom": "SCHAL",
|
|
||||||
"prenom": "Michaël",
|
|
||||||
"dateNaissance": "2025-07-02",
|
|
||||||
"lieuNaissance": "Bar le duc",
|
|
||||||
"typeIdentite": "CNI",
|
|
||||||
"numeroIdentite": "qsdfqsdgc23445",
|
|
||||||
"autoriteDelivrance": "Frouard",
|
|
||||||
"dateDelivrance": "2025-07-01",
|
|
||||||
"photoRecto": null,
|
|
||||||
"photoVerso": null
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 4,
|
|
||||||
"storeId": 1,
|
|
||||||
"userId": 1,
|
|
||||||
"timestamp": "2025-07-09T19:11:36.505Z",
|
|
||||||
"vendeur": "Moi",
|
|
||||||
"dateVente": "2025-07-09",
|
|
||||||
"typeArticle": "Batterie",
|
|
||||||
"categorie": "F3",
|
|
||||||
"quantite": 1,
|
|
||||||
"gencode": "3660092323745",
|
|
||||||
"nom": "SCHAL",
|
|
||||||
"prenom": "Michaël",
|
|
||||||
"dateNaissance": "2025-07-18",
|
|
||||||
"lieuNaissance": "Bar le duc",
|
|
||||||
"typeIdentite": "CNI",
|
|
||||||
"numeroIdentite": "qsdfqsdgc23445",
|
|
||||||
"autoriteDelivrance": "Frouard",
|
|
||||||
"dateDelivrance": "2025-07-01",
|
|
||||||
"photoRecto": null,
|
|
||||||
"photoVerso": null
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"metadata": {
|
|
||||||
"totalUsers": 2,
|
|
||||||
"totalStores": 2,
|
|
||||||
"totalSales": 4,
|
|
||||||
"exportedBy": "system-auto-backup"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,155 +0,0 @@
|
|||||||
{
|
|
||||||
"timestamp": "2025-07-09T22:00:00.184Z",
|
|
||||||
"version": "1.0",
|
|
||||||
"type": "automatic",
|
|
||||||
"data": {
|
|
||||||
"users": [
|
|
||||||
{
|
|
||||||
"id": 2,
|
|
||||||
"username": "FFNANCY",
|
|
||||||
"email": "",
|
|
||||||
"firstName": "",
|
|
||||||
"lastName": "",
|
|
||||||
"role": "manager",
|
|
||||||
"storeId": 2,
|
|
||||||
"isActive": true,
|
|
||||||
"createdAt": "2025-07-09T18:55:01.413Z",
|
|
||||||
"updatedAt": "2025-07-09T18:55:01.413Z"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 1,
|
|
||||||
"username": "admin",
|
|
||||||
"email": "admin@example.com",
|
|
||||||
"firstName": "Administrateur",
|
|
||||||
"lastName": "Principal",
|
|
||||||
"role": "admin",
|
|
||||||
"storeId": 1,
|
|
||||||
"isActive": true,
|
|
||||||
"createdAt": "2025-07-09T18:37:53.865Z",
|
|
||||||
"updatedAt": "2025-07-09T18:37:53.865Z"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"stores": [
|
|
||||||
{
|
|
||||||
"id": 2,
|
|
||||||
"name": "Houdemont",
|
|
||||||
"address": "",
|
|
||||||
"phone": "",
|
|
||||||
"email": "",
|
|
||||||
"isActive": true,
|
|
||||||
"createdAt": "2025-07-09T19:00:30.782Z",
|
|
||||||
"updatedAt": "2025-07-09T19:00:30.782Z"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 1,
|
|
||||||
"name": "Frouard",
|
|
||||||
"address": "À définir",
|
|
||||||
"phone": "",
|
|
||||||
"email": "",
|
|
||||||
"isActive": true,
|
|
||||||
"createdAt": "2025-07-09T18:37:53.432Z",
|
|
||||||
"updatedAt": "2025-07-09T18:37:53.432Z"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"sales": [
|
|
||||||
{
|
|
||||||
"id": 5,
|
|
||||||
"storeId": 2,
|
|
||||||
"userId": 2,
|
|
||||||
"timestamp": "2025-07-09T19:16:46.797Z",
|
|
||||||
"vendeur": "Moi",
|
|
||||||
"dateVente": "2025-07-09",
|
|
||||||
"typeArticle": "Fusée",
|
|
||||||
"categorie": "F2",
|
|
||||||
"quantite": 10,
|
|
||||||
"gencode": "3660092323745",
|
|
||||||
"nom": " ASSOCIATION GRAND AIR",
|
|
||||||
"prenom": "Anne-Laure",
|
|
||||||
"dateNaissance": "2025-06-03",
|
|
||||||
"lieuNaissance": "Bar le duc",
|
|
||||||
"modePaiement": "Espèce",
|
|
||||||
"typeIdentite": "Passeport",
|
|
||||||
"numeroIdentite": "qsdfqsdgc23445",
|
|
||||||
"autoriteDelivrance": "Frouard",
|
|
||||||
"dateDelivrance": "2025-07-01",
|
|
||||||
"photoRecto": null,
|
|
||||||
"photoVerso": null
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 2,
|
|
||||||
"storeId": 2,
|
|
||||||
"userId": 1,
|
|
||||||
"timestamp": "2025-07-09T19:07:15.650Z",
|
|
||||||
"vendeur": "Moi",
|
|
||||||
"dateVente": "2025-07-09",
|
|
||||||
"typeArticle": "Pétard aérien",
|
|
||||||
"categorie": "F3",
|
|
||||||
"quantite": 1,
|
|
||||||
"gencode": "3660092323745",
|
|
||||||
"nom": "SCHAL",
|
|
||||||
"prenom": "Michaël",
|
|
||||||
"dateNaissance": "2025-07-02",
|
|
||||||
"lieuNaissance": "Bar le duc",
|
|
||||||
"modePaiement": "Espèce",
|
|
||||||
"typeIdentite": "CNI",
|
|
||||||
"numeroIdentite": "qsdfqsdgc23445",
|
|
||||||
"autoriteDelivrance": "Frouard",
|
|
||||||
"dateDelivrance": "2025-07-01",
|
|
||||||
"photoRecto": null,
|
|
||||||
"photoVerso": null
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 1,
|
|
||||||
"storeId": 2,
|
|
||||||
"userId": 1,
|
|
||||||
"timestamp": "2025-07-09T19:05:20.904Z",
|
|
||||||
"vendeur": "Moi",
|
|
||||||
"dateVente": "2025-07-09",
|
|
||||||
"typeArticle": "Pétard aérien",
|
|
||||||
"categorie": "F3",
|
|
||||||
"quantite": 1,
|
|
||||||
"gencode": "3660092323745",
|
|
||||||
"nom": "SCHAL",
|
|
||||||
"prenom": "Michaël",
|
|
||||||
"dateNaissance": "2025-07-02",
|
|
||||||
"lieuNaissance": "Bar le duc",
|
|
||||||
"modePaiement": "Espèce",
|
|
||||||
"typeIdentite": "CNI",
|
|
||||||
"numeroIdentite": "qsdfqsdgc23445",
|
|
||||||
"autoriteDelivrance": "Frouard",
|
|
||||||
"dateDelivrance": "2025-07-01",
|
|
||||||
"photoRecto": null,
|
|
||||||
"photoVerso": null
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 4,
|
|
||||||
"storeId": 1,
|
|
||||||
"userId": 1,
|
|
||||||
"timestamp": "2025-07-09T19:11:36.505Z",
|
|
||||||
"vendeur": "Moi",
|
|
||||||
"dateVente": "2025-07-09",
|
|
||||||
"typeArticle": "Batterie",
|
|
||||||
"categorie": "F3",
|
|
||||||
"quantite": 1,
|
|
||||||
"gencode": "3660092323745",
|
|
||||||
"nom": "SCHAL",
|
|
||||||
"prenom": "Michaël",
|
|
||||||
"dateNaissance": "2025-07-18",
|
|
||||||
"lieuNaissance": "Bar le duc",
|
|
||||||
"modePaiement": "Espèce",
|
|
||||||
"typeIdentite": "CNI",
|
|
||||||
"numeroIdentite": "qsdfqsdgc23445",
|
|
||||||
"autoriteDelivrance": "Frouard",
|
|
||||||
"dateDelivrance": "2025-07-01",
|
|
||||||
"photoRecto": null,
|
|
||||||
"photoVerso": null
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"metadata": {
|
|
||||||
"totalUsers": 2,
|
|
||||||
"totalStores": 2,
|
|
||||||
"totalSales": 4,
|
|
||||||
"exportedBy": "system-auto-backup"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,209 +0,0 @@
|
|||||||
{
|
|
||||||
"timestamp": "2025-07-10T10:00:00.591Z",
|
|
||||||
"version": "1.0",
|
|
||||||
"type": "automatic",
|
|
||||||
"data": {
|
|
||||||
"users": [
|
|
||||||
{
|
|
||||||
"id": 5,
|
|
||||||
"username": "ff579",
|
|
||||||
"email": null,
|
|
||||||
"firstName": "",
|
|
||||||
"lastName": "",
|
|
||||||
"role": "employee",
|
|
||||||
"storeId": 2,
|
|
||||||
"isActive": true,
|
|
||||||
"createdAt": "2025-07-10T09:48:22.256Z",
|
|
||||||
"updatedAt": "2025-07-10T09:48:22.256Z"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 4,
|
|
||||||
"username": "ff292",
|
|
||||||
"email": null,
|
|
||||||
"firstName": "",
|
|
||||||
"lastName": "",
|
|
||||||
"role": "employee",
|
|
||||||
"storeId": 1,
|
|
||||||
"isActive": true,
|
|
||||||
"createdAt": "2025-07-10T09:48:06.549Z",
|
|
||||||
"updatedAt": "2025-07-10T09:48:06.549Z"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 3,
|
|
||||||
"username": "gael",
|
|
||||||
"email": null,
|
|
||||||
"firstName": "",
|
|
||||||
"lastName": "",
|
|
||||||
"role": "administrator",
|
|
||||||
"storeId": null,
|
|
||||||
"isActive": true,
|
|
||||||
"createdAt": "2025-07-10T08:47:04.063Z",
|
|
||||||
"updatedAt": "2025-07-10T08:47:04.063Z"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 2,
|
|
||||||
"username": "FFNANCY",
|
|
||||||
"email": "michaelschal@gmail.com",
|
|
||||||
"firstName": "",
|
|
||||||
"lastName": "",
|
|
||||||
"role": "manager",
|
|
||||||
"storeId": 1,
|
|
||||||
"isActive": true,
|
|
||||||
"createdAt": "2025-07-09T18:55:01.413Z",
|
|
||||||
"updatedAt": "2025-07-09T18:55:01.413Z"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 1,
|
|
||||||
"username": "admin",
|
|
||||||
"email": "michaelschal@ffest.fr",
|
|
||||||
"firstName": "Administrateur",
|
|
||||||
"lastName": "Principal",
|
|
||||||
"role": "admin",
|
|
||||||
"storeId": 1,
|
|
||||||
"isActive": true,
|
|
||||||
"createdAt": "2025-07-09T18:37:53.865Z",
|
|
||||||
"updatedAt": "2025-07-09T18:37:53.865Z"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"stores": [
|
|
||||||
{
|
|
||||||
"id": 2,
|
|
||||||
"name": "Houdemont",
|
|
||||||
"address": "",
|
|
||||||
"phone": "",
|
|
||||||
"email": "",
|
|
||||||
"isActive": true,
|
|
||||||
"createdAt": "2025-07-09T19:00:30.782Z",
|
|
||||||
"updatedAt": "2025-07-09T19:00:30.782Z"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 1,
|
|
||||||
"name": "Frouard",
|
|
||||||
"address": "À définir",
|
|
||||||
"phone": "",
|
|
||||||
"email": "",
|
|
||||||
"isActive": true,
|
|
||||||
"createdAt": "2025-07-09T18:37:53.432Z",
|
|
||||||
"updatedAt": "2025-07-09T18:37:53.432Z"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"sales": [
|
|
||||||
{
|
|
||||||
"id": 5,
|
|
||||||
"storeId": 2,
|
|
||||||
"userId": 2,
|
|
||||||
"timestamp": "2025-07-09T19:16:46.797Z",
|
|
||||||
"vendeur": "Moi",
|
|
||||||
"typeArticle": "Fusée",
|
|
||||||
"categorie": "F2",
|
|
||||||
"quantite": 10,
|
|
||||||
"gencode": "3660092323745",
|
|
||||||
"nom": " ASSOCIATION GRAND AIR",
|
|
||||||
"prenom": "Anne-Laure",
|
|
||||||
"dateNaissance": "2025-06-03",
|
|
||||||
"lieuNaissance": "Bar le duc",
|
|
||||||
"modePaiement": "Espèce",
|
|
||||||
"typeIdentite": "Passeport",
|
|
||||||
"numeroIdentite": "qsdfqsdgc23445",
|
|
||||||
"autoriteDelivrance": "Frouard",
|
|
||||||
"dateDelivrance": "2025-07-01",
|
|
||||||
"photoRecto": null,
|
|
||||||
"photoVerso": null
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 2,
|
|
||||||
"storeId": 2,
|
|
||||||
"userId": 1,
|
|
||||||
"timestamp": "2025-07-09T19:07:15.650Z",
|
|
||||||
"vendeur": "Moi",
|
|
||||||
"typeArticle": "Pétard aérien",
|
|
||||||
"categorie": "F3",
|
|
||||||
"quantite": 1,
|
|
||||||
"gencode": "3660092323745",
|
|
||||||
"nom": "SCHAL",
|
|
||||||
"prenom": "Michaël",
|
|
||||||
"dateNaissance": "2025-07-02",
|
|
||||||
"lieuNaissance": "Bar le duc",
|
|
||||||
"modePaiement": "Espèce",
|
|
||||||
"typeIdentite": "CNI",
|
|
||||||
"numeroIdentite": "qsdfqsdgc23445",
|
|
||||||
"autoriteDelivrance": "Frouard",
|
|
||||||
"dateDelivrance": "2025-07-01",
|
|
||||||
"photoRecto": null,
|
|
||||||
"photoVerso": null
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 1,
|
|
||||||
"storeId": 2,
|
|
||||||
"userId": 1,
|
|
||||||
"timestamp": "2025-07-09T19:05:20.904Z",
|
|
||||||
"vendeur": "Moi",
|
|
||||||
"typeArticle": "Pétard aérien",
|
|
||||||
"categorie": "F3",
|
|
||||||
"quantite": 1,
|
|
||||||
"gencode": "3660092323745",
|
|
||||||
"nom": "SCHAL",
|
|
||||||
"prenom": "Michaël",
|
|
||||||
"dateNaissance": "2025-07-02",
|
|
||||||
"lieuNaissance": "Bar le duc",
|
|
||||||
"modePaiement": "Espèce",
|
|
||||||
"typeIdentite": "CNI",
|
|
||||||
"numeroIdentite": "qsdfqsdgc23445",
|
|
||||||
"autoriteDelivrance": "Frouard",
|
|
||||||
"dateDelivrance": "2025-07-01",
|
|
||||||
"photoRecto": null,
|
|
||||||
"photoVerso": null
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 6,
|
|
||||||
"storeId": 1,
|
|
||||||
"userId": 1,
|
|
||||||
"timestamp": "2025-07-10T00:08:19.097Z",
|
|
||||||
"vendeur": "Moi",
|
|
||||||
"typeArticle": "Chandelle romaine",
|
|
||||||
"categorie": "F2",
|
|
||||||
"quantite": 1,
|
|
||||||
"gencode": "3660092323745",
|
|
||||||
"nom": "SCHAL",
|
|
||||||
"prenom": "Anne-Laure",
|
|
||||||
"dateNaissance": "2018-02-10",
|
|
||||||
"lieuNaissance": "Bar le duc",
|
|
||||||
"modePaiement": "Espèce",
|
|
||||||
"typeIdentite": "Passeport",
|
|
||||||
"numeroIdentite": "qsdfqsdgc23445",
|
|
||||||
"autoriteDelivrance": "Frouard",
|
|
||||||
"dateDelivrance": "2025-07-01",
|
|
||||||
"photoRecto": null,
|
|
||||||
"photoVerso": null
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 4,
|
|
||||||
"storeId": 1,
|
|
||||||
"userId": 1,
|
|
||||||
"timestamp": "2025-07-09T19:11:36.505Z",
|
|
||||||
"vendeur": "Moi",
|
|
||||||
"typeArticle": "Batterie",
|
|
||||||
"categorie": "F3",
|
|
||||||
"quantite": 1,
|
|
||||||
"gencode": "3660092323745",
|
|
||||||
"nom": "SCHAL",
|
|
||||||
"prenom": "Michaël",
|
|
||||||
"dateNaissance": "2025-07-18",
|
|
||||||
"lieuNaissance": "Bar le duc",
|
|
||||||
"modePaiement": "Espèce",
|
|
||||||
"typeIdentite": "CNI",
|
|
||||||
"numeroIdentite": "qsdfqsdgc23445",
|
|
||||||
"autoriteDelivrance": "Frouard",
|
|
||||||
"dateDelivrance": "2025-07-01",
|
|
||||||
"photoRecto": null,
|
|
||||||
"photoVerso": null
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"metadata": {
|
|
||||||
"totalUsers": 5,
|
|
||||||
"totalStores": 2,
|
|
||||||
"totalSales": 5,
|
|
||||||
"exportedBy": "system-auto-backup"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,209 +0,0 @@
|
|||||||
{
|
|
||||||
"timestamp": "2025-07-11T10:00:00.586Z",
|
|
||||||
"version": "1.0",
|
|
||||||
"type": "automatic",
|
|
||||||
"data": {
|
|
||||||
"users": [
|
|
||||||
{
|
|
||||||
"id": 5,
|
|
||||||
"username": "ff579",
|
|
||||||
"email": null,
|
|
||||||
"firstName": "",
|
|
||||||
"lastName": "",
|
|
||||||
"role": "employee",
|
|
||||||
"storeId": 2,
|
|
||||||
"isActive": true,
|
|
||||||
"createdAt": "2025-07-10T09:48:22.256Z",
|
|
||||||
"updatedAt": "2025-07-10T09:48:22.256Z"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 4,
|
|
||||||
"username": "ff292",
|
|
||||||
"email": null,
|
|
||||||
"firstName": "",
|
|
||||||
"lastName": "",
|
|
||||||
"role": "employee",
|
|
||||||
"storeId": 1,
|
|
||||||
"isActive": true,
|
|
||||||
"createdAt": "2025-07-10T09:48:06.549Z",
|
|
||||||
"updatedAt": "2025-07-10T09:48:06.549Z"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 3,
|
|
||||||
"username": "gael",
|
|
||||||
"email": null,
|
|
||||||
"firstName": "",
|
|
||||||
"lastName": "",
|
|
||||||
"role": "administrator",
|
|
||||||
"storeId": null,
|
|
||||||
"isActive": true,
|
|
||||||
"createdAt": "2025-07-10T08:47:04.063Z",
|
|
||||||
"updatedAt": "2025-07-10T08:47:04.063Z"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 2,
|
|
||||||
"username": "FFNANCY",
|
|
||||||
"email": "michaelschal@gmail.com",
|
|
||||||
"firstName": "",
|
|
||||||
"lastName": "",
|
|
||||||
"role": "manager",
|
|
||||||
"storeId": 1,
|
|
||||||
"isActive": true,
|
|
||||||
"createdAt": "2025-07-09T18:55:01.413Z",
|
|
||||||
"updatedAt": "2025-07-09T18:55:01.413Z"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 1,
|
|
||||||
"username": "admin",
|
|
||||||
"email": "michaelschal@ffest.fr",
|
|
||||||
"firstName": "Administrateur",
|
|
||||||
"lastName": "Principal",
|
|
||||||
"role": "admin",
|
|
||||||
"storeId": 1,
|
|
||||||
"isActive": true,
|
|
||||||
"createdAt": "2025-07-09T18:37:53.865Z",
|
|
||||||
"updatedAt": "2025-07-09T18:37:53.865Z"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"stores": [
|
|
||||||
{
|
|
||||||
"id": 2,
|
|
||||||
"name": "Houdemont",
|
|
||||||
"address": "",
|
|
||||||
"phone": "",
|
|
||||||
"email": "",
|
|
||||||
"isActive": true,
|
|
||||||
"createdAt": "2025-07-09T19:00:30.782Z",
|
|
||||||
"updatedAt": "2025-07-09T19:00:30.782Z"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 1,
|
|
||||||
"name": "Frouard",
|
|
||||||
"address": "À définir",
|
|
||||||
"phone": "",
|
|
||||||
"email": "",
|
|
||||||
"isActive": true,
|
|
||||||
"createdAt": "2025-07-09T18:37:53.432Z",
|
|
||||||
"updatedAt": "2025-07-09T18:37:53.432Z"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"sales": [
|
|
||||||
{
|
|
||||||
"id": 5,
|
|
||||||
"storeId": 2,
|
|
||||||
"userId": 2,
|
|
||||||
"timestamp": "2025-07-09T19:16:46.797Z",
|
|
||||||
"vendeur": "Moi",
|
|
||||||
"typeArticle": "Fusée",
|
|
||||||
"categorie": "F2",
|
|
||||||
"quantite": 10,
|
|
||||||
"gencode": "3660092323745",
|
|
||||||
"nom": " ASSOCIATION GRAND AIR",
|
|
||||||
"prenom": "Anne-Laure",
|
|
||||||
"dateNaissance": "2025-06-03",
|
|
||||||
"lieuNaissance": "Bar le duc",
|
|
||||||
"modePaiement": "Espèce",
|
|
||||||
"typeIdentite": "Passeport",
|
|
||||||
"numeroIdentite": "qsdfqsdgc23445",
|
|
||||||
"autoriteDelivrance": "Frouard",
|
|
||||||
"dateDelivrance": "2025-07-01",
|
|
||||||
"photoRecto": null,
|
|
||||||
"photoVerso": null
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 2,
|
|
||||||
"storeId": 2,
|
|
||||||
"userId": 1,
|
|
||||||
"timestamp": "2025-07-09T19:07:15.650Z",
|
|
||||||
"vendeur": "Moi",
|
|
||||||
"typeArticle": "Pétard aérien",
|
|
||||||
"categorie": "F3",
|
|
||||||
"quantite": 1,
|
|
||||||
"gencode": "3660092323745",
|
|
||||||
"nom": "SCHAL",
|
|
||||||
"prenom": "Michaël",
|
|
||||||
"dateNaissance": "2025-07-02",
|
|
||||||
"lieuNaissance": "Bar le duc",
|
|
||||||
"modePaiement": "Espèce",
|
|
||||||
"typeIdentite": "CNI",
|
|
||||||
"numeroIdentite": "qsdfqsdgc23445",
|
|
||||||
"autoriteDelivrance": "Frouard",
|
|
||||||
"dateDelivrance": "2025-07-01",
|
|
||||||
"photoRecto": null,
|
|
||||||
"photoVerso": null
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 1,
|
|
||||||
"storeId": 2,
|
|
||||||
"userId": 1,
|
|
||||||
"timestamp": "2025-07-09T19:05:20.904Z",
|
|
||||||
"vendeur": "Moi",
|
|
||||||
"typeArticle": "Pétard aérien",
|
|
||||||
"categorie": "F3",
|
|
||||||
"quantite": 1,
|
|
||||||
"gencode": "3660092323745",
|
|
||||||
"nom": "SCHAL",
|
|
||||||
"prenom": "Michaël",
|
|
||||||
"dateNaissance": "2025-07-02",
|
|
||||||
"lieuNaissance": "Bar le duc",
|
|
||||||
"modePaiement": "Espèce",
|
|
||||||
"typeIdentite": "CNI",
|
|
||||||
"numeroIdentite": "qsdfqsdgc23445",
|
|
||||||
"autoriteDelivrance": "Frouard",
|
|
||||||
"dateDelivrance": "2025-07-01",
|
|
||||||
"photoRecto": null,
|
|
||||||
"photoVerso": null
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 6,
|
|
||||||
"storeId": 1,
|
|
||||||
"userId": 1,
|
|
||||||
"timestamp": "2025-07-10T00:08:19.097Z",
|
|
||||||
"vendeur": "Moi",
|
|
||||||
"typeArticle": "Chandelle romaine",
|
|
||||||
"categorie": "F2",
|
|
||||||
"quantite": 1,
|
|
||||||
"gencode": "3660092323745",
|
|
||||||
"nom": "SCHAL",
|
|
||||||
"prenom": "Anne-Laure",
|
|
||||||
"dateNaissance": "2018-02-10",
|
|
||||||
"lieuNaissance": "Bar le duc",
|
|
||||||
"modePaiement": "Espèce",
|
|
||||||
"typeIdentite": "Passeport",
|
|
||||||
"numeroIdentite": "qsdfqsdgc23445",
|
|
||||||
"autoriteDelivrance": "Frouard",
|
|
||||||
"dateDelivrance": "2025-07-01",
|
|
||||||
"photoRecto": null,
|
|
||||||
"photoVerso": null
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 4,
|
|
||||||
"storeId": 1,
|
|
||||||
"userId": 1,
|
|
||||||
"timestamp": "2025-07-09T19:11:36.505Z",
|
|
||||||
"vendeur": "Moi",
|
|
||||||
"typeArticle": "Batterie",
|
|
||||||
"categorie": "F3",
|
|
||||||
"quantite": 1,
|
|
||||||
"gencode": "3660092323745",
|
|
||||||
"nom": "SCHAL",
|
|
||||||
"prenom": "Michaël",
|
|
||||||
"dateNaissance": "2025-07-18",
|
|
||||||
"lieuNaissance": "Bar le duc",
|
|
||||||
"modePaiement": "Espèce",
|
|
||||||
"typeIdentite": "CNI",
|
|
||||||
"numeroIdentite": "qsdfqsdgc23445",
|
|
||||||
"autoriteDelivrance": "Frouard",
|
|
||||||
"dateDelivrance": "2025-07-01",
|
|
||||||
"photoRecto": null,
|
|
||||||
"photoVerso": null
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"metadata": {
|
|
||||||
"totalUsers": 5,
|
|
||||||
"totalStores": 2,
|
|
||||||
"totalSales": 5,
|
|
||||||
"exportedBy": "system-auto-backup"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,375 @@
|
|||||||
|
{
|
||||||
|
"timestamp": "2025-07-11T19:05:01.267Z",
|
||||||
|
"version": "1.0",
|
||||||
|
"type": "automatic",
|
||||||
|
"data": {
|
||||||
|
"users": [
|
||||||
|
{
|
||||||
|
"id": 5,
|
||||||
|
"username": "ff579",
|
||||||
|
"email": null,
|
||||||
|
"firstName": "",
|
||||||
|
"lastName": "",
|
||||||
|
"role": "employee",
|
||||||
|
"storeId": 2,
|
||||||
|
"isActive": true,
|
||||||
|
"createdAt": "2025-07-10T09:48:22.256Z",
|
||||||
|
"updatedAt": "2025-07-10T09:48:22.256Z"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 4,
|
||||||
|
"username": "ff292",
|
||||||
|
"email": null,
|
||||||
|
"firstName": "",
|
||||||
|
"lastName": "",
|
||||||
|
"role": "employee",
|
||||||
|
"storeId": 1,
|
||||||
|
"isActive": true,
|
||||||
|
"createdAt": "2025-07-10T09:48:06.549Z",
|
||||||
|
"updatedAt": "2025-07-10T09:48:06.549Z"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 3,
|
||||||
|
"username": "gael",
|
||||||
|
"email": null,
|
||||||
|
"firstName": "",
|
||||||
|
"lastName": "",
|
||||||
|
"role": "administrator",
|
||||||
|
"storeId": null,
|
||||||
|
"isActive": true,
|
||||||
|
"createdAt": "2025-07-10T08:47:04.063Z",
|
||||||
|
"updatedAt": "2025-07-10T08:47:04.063Z"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 2,
|
||||||
|
"username": "FFNANCY",
|
||||||
|
"email": "michaelschal@gmail.com",
|
||||||
|
"firstName": "",
|
||||||
|
"lastName": "",
|
||||||
|
"role": "manager",
|
||||||
|
"storeId": 1,
|
||||||
|
"isActive": true,
|
||||||
|
"createdAt": "2025-07-09T18:55:01.413Z",
|
||||||
|
"updatedAt": "2025-07-09T18:55:01.413Z"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 1,
|
||||||
|
"username": "admin",
|
||||||
|
"email": "michaelschal@ffest.fr",
|
||||||
|
"firstName": "Administrateur",
|
||||||
|
"lastName": "Principal",
|
||||||
|
"role": "admin",
|
||||||
|
"storeId": 1,
|
||||||
|
"isActive": true,
|
||||||
|
"createdAt": "2025-07-09T18:37:53.865Z",
|
||||||
|
"updatedAt": "2025-07-09T18:37:53.865Z"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"stores": [
|
||||||
|
{
|
||||||
|
"id": 2,
|
||||||
|
"name": "Houdemont",
|
||||||
|
"address": "",
|
||||||
|
"phone": "",
|
||||||
|
"email": "",
|
||||||
|
"isActive": true,
|
||||||
|
"createdAt": "2025-07-09T19:00:30.782Z",
|
||||||
|
"updatedAt": "2025-07-09T19:00:30.782Z"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 1,
|
||||||
|
"name": "Frouard",
|
||||||
|
"address": "À définir",
|
||||||
|
"phone": "",
|
||||||
|
"email": "",
|
||||||
|
"isActive": true,
|
||||||
|
"createdAt": "2025-07-09T18:37:53.432Z",
|
||||||
|
"updatedAt": "2025-07-09T18:37:53.432Z"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"sales": [
|
||||||
|
{
|
||||||
|
"id": 8,
|
||||||
|
"storeId": 2,
|
||||||
|
"userId": 1,
|
||||||
|
"timestamp": "2025-07-11T18:27:55.231Z",
|
||||||
|
"vendeur": "Test Vendeur",
|
||||||
|
"typeArticle": "Batterie Test",
|
||||||
|
"categorie": "F2",
|
||||||
|
"quantite": 1,
|
||||||
|
"gencode": "1234567890123",
|
||||||
|
"nom": "DUPONT",
|
||||||
|
"prenom": "Jean",
|
||||||
|
"dateNaissance": "01/01/1980",
|
||||||
|
"lieuNaissance": "Paris",
|
||||||
|
"modePaiement": "Carte bancaire",
|
||||||
|
"typeIdentite": "Carte d'identité",
|
||||||
|
"numeroIdentite": "ABC123456",
|
||||||
|
"autoriteDelivrance": "Préfecture de Paris",
|
||||||
|
"dateDelivrance": "01/01/2020",
|
||||||
|
"photo_recto": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNkYPhfDwAChwGA60e6kgAAAABJRU5ErkJggg==",
|
||||||
|
"photo_verso": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNkYPhfDwAChwGA60e6kgAAAABJRU5ErkJggg==",
|
||||||
|
"photo_ticket": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNkYPhfDwAChwGA60e6kgAAAABJRU5ErkJggg=="
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 7,
|
||||||
|
"storeId": 2,
|
||||||
|
"userId": 1,
|
||||||
|
"timestamp": "2025-07-11T15:36:32.194Z",
|
||||||
|
"vendeur": "Moi",
|
||||||
|
"typeArticle": "Batterie",
|
||||||
|
"categorie": "F3",
|
||||||
|
"quantite": 1,
|
||||||
|
"gencode": "3660092323745",
|
||||||
|
"nom": "SCHAL",
|
||||||
|
"prenom": "Michaël",
|
||||||
|
"dateNaissance": "1998-02-05",
|
||||||
|
"lieuNaissance": "Bar le duc",
|
||||||
|
"modePaiement": "Espèce",
|
||||||
|
"typeIdentite": "CNI",
|
||||||
|
"numeroIdentite": "qsdfqsdgc23445",
|
||||||
|
"autoriteDelivrance": "Frouard",
|
||||||
|
"dateDelivrance": "2025-07-11",
|
||||||
|
"photo_recto": null,
|
||||||
|
"photo_verso": null,
|
||||||
|
"photo_ticket": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 5,
|
||||||
|
"storeId": 2,
|
||||||
|
"userId": 2,
|
||||||
|
"timestamp": "2025-07-09T19:16:46.797Z",
|
||||||
|
"vendeur": "Moi",
|
||||||
|
"typeArticle": "Fusée",
|
||||||
|
"categorie": "F2",
|
||||||
|
"quantite": 10,
|
||||||
|
"gencode": "3660092323745",
|
||||||
|
"nom": " ASSOCIATION GRAND AIR",
|
||||||
|
"prenom": "Anne-Laure",
|
||||||
|
"dateNaissance": "2025-06-03",
|
||||||
|
"lieuNaissance": "Bar le duc",
|
||||||
|
"modePaiement": "Espèce",
|
||||||
|
"typeIdentite": "Passeport",
|
||||||
|
"numeroIdentite": "qsdfqsdgc23445",
|
||||||
|
"autoriteDelivrance": "Frouard",
|
||||||
|
"dateDelivrance": "2025-07-01",
|
||||||
|
"photo_recto": null,
|
||||||
|
"photo_verso": null,
|
||||||
|
"photo_ticket": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 2,
|
||||||
|
"storeId": 2,
|
||||||
|
"userId": 1,
|
||||||
|
"timestamp": "2025-07-09T19:07:15.650Z",
|
||||||
|
"vendeur": "Moi",
|
||||||
|
"typeArticle": "Pétard aérien",
|
||||||
|
"categorie": "F3",
|
||||||
|
"quantite": 1,
|
||||||
|
"gencode": "3660092323745",
|
||||||
|
"nom": "SCHAL",
|
||||||
|
"prenom": "Michaël",
|
||||||
|
"dateNaissance": "2025-07-02",
|
||||||
|
"lieuNaissance": "Bar le duc",
|
||||||
|
"modePaiement": "Espèce",
|
||||||
|
"typeIdentite": "CNI",
|
||||||
|
"numeroIdentite": "qsdfqsdgc23445",
|
||||||
|
"autoriteDelivrance": "Frouard",
|
||||||
|
"dateDelivrance": "2025-07-01",
|
||||||
|
"photo_recto": null,
|
||||||
|
"photo_verso": null,
|
||||||
|
"photo_ticket": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 1,
|
||||||
|
"storeId": 2,
|
||||||
|
"userId": 1,
|
||||||
|
"timestamp": "2025-07-09T19:05:20.904Z",
|
||||||
|
"vendeur": "Moi",
|
||||||
|
"typeArticle": "Pétard aérien",
|
||||||
|
"categorie": "F3",
|
||||||
|
"quantite": 1,
|
||||||
|
"gencode": "3660092323745",
|
||||||
|
"nom": "SCHAL",
|
||||||
|
"prenom": "Michaël",
|
||||||
|
"dateNaissance": "2025-07-02",
|
||||||
|
"lieuNaissance": "Bar le duc",
|
||||||
|
"modePaiement": "Espèce",
|
||||||
|
"typeIdentite": "CNI",
|
||||||
|
"numeroIdentite": "qsdfqsdgc23445",
|
||||||
|
"autoriteDelivrance": "Frouard",
|
||||||
|
"dateDelivrance": "2025-07-01",
|
||||||
|
"photo_recto": null,
|
||||||
|
"photo_verso": null,
|
||||||
|
"photo_ticket": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 13,
|
||||||
|
"storeId": 1,
|
||||||
|
"userId": 1,
|
||||||
|
"timestamp": "2025-07-11T19:02:01.423Z",
|
||||||
|
"vendeur": "Production Test",
|
||||||
|
"typeArticle": "Chandelle",
|
||||||
|
"categorie": "F2",
|
||||||
|
"quantite": 1,
|
||||||
|
"gencode": "1234567890999",
|
||||||
|
"nom": "PROD",
|
||||||
|
"prenom": "Test",
|
||||||
|
"dateNaissance": "1990-01-01",
|
||||||
|
"lieuNaissance": "Test",
|
||||||
|
"modePaiement": "Espèce",
|
||||||
|
"typeIdentite": "Passeport",
|
||||||
|
"numeroIdentite": "123456789",
|
||||||
|
"autoriteDelivrance": "Test",
|
||||||
|
"dateDelivrance": "2025-01-01",
|
||||||
|
"photo_recto": null,
|
||||||
|
"photo_verso": null,
|
||||||
|
"photo_ticket": "data:image/jpeg;base64,PRODUCTION_TEST_TICKET"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 12,
|
||||||
|
"storeId": 1,
|
||||||
|
"userId": 1,
|
||||||
|
"timestamp": "2025-07-11T18:48:31.159Z",
|
||||||
|
"vendeur": "Test Final",
|
||||||
|
"typeArticle": "Chandelle",
|
||||||
|
"categorie": "F2",
|
||||||
|
"quantite": 1,
|
||||||
|
"gencode": "1234567890999",
|
||||||
|
"nom": "FINAL",
|
||||||
|
"prenom": "Test",
|
||||||
|
"dateNaissance": "1990-01-01",
|
||||||
|
"lieuNaissance": "Test",
|
||||||
|
"modePaiement": "Espèce",
|
||||||
|
"typeIdentite": "Passeport",
|
||||||
|
"numeroIdentite": "123456789",
|
||||||
|
"autoriteDelivrance": "Test",
|
||||||
|
"dateDelivrance": "2025-01-01",
|
||||||
|
"photo_recto": null,
|
||||||
|
"photo_verso": null,
|
||||||
|
"photo_ticket": "data:image/jpeg;base64,TICKET_TEST_FINAL"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 11,
|
||||||
|
"storeId": 1,
|
||||||
|
"userId": 1,
|
||||||
|
"timestamp": "2025-07-11T18:39:03.438Z",
|
||||||
|
"vendeur": "Test Debug",
|
||||||
|
"typeArticle": "Chandelle",
|
||||||
|
"categorie": "F2",
|
||||||
|
"quantite": 1,
|
||||||
|
"gencode": "1234567890125",
|
||||||
|
"nom": "DEBUG",
|
||||||
|
"prenom": "Test",
|
||||||
|
"dateNaissance": "1990-01-01",
|
||||||
|
"lieuNaissance": "Test",
|
||||||
|
"modePaiement": "Espèce",
|
||||||
|
"typeIdentite": "Passeport",
|
||||||
|
"numeroIdentite": "123456789",
|
||||||
|
"autoriteDelivrance": "Test",
|
||||||
|
"dateDelivrance": "2025-01-01",
|
||||||
|
"photo_recto": null,
|
||||||
|
"photo_verso": null,
|
||||||
|
"photo_ticket": "data:image/jpeg;base64,TEST_TICKET_DATA"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 10,
|
||||||
|
"storeId": 1,
|
||||||
|
"userId": 1,
|
||||||
|
"timestamp": "2025-07-11T18:38:45.251Z",
|
||||||
|
"vendeur": "Test Vendeur 2",
|
||||||
|
"typeArticle": "Chandelle",
|
||||||
|
"categorie": "F2",
|
||||||
|
"quantite": 1,
|
||||||
|
"gencode": "1234567890124",
|
||||||
|
"nom": "TEST2",
|
||||||
|
"prenom": "Photo2",
|
||||||
|
"dateNaissance": "1990-01-01",
|
||||||
|
"lieuNaissance": "Test",
|
||||||
|
"modePaiement": "Espèce",
|
||||||
|
"typeIdentite": "Passeport",
|
||||||
|
"numeroIdentite": "123456789",
|
||||||
|
"autoriteDelivrance": "Test",
|
||||||
|
"dateDelivrance": "2025-01-01",
|
||||||
|
"photo_recto": null,
|
||||||
|
"photo_verso": null,
|
||||||
|
"photo_ticket": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 9,
|
||||||
|
"storeId": 1,
|
||||||
|
"userId": 1,
|
||||||
|
"timestamp": "2025-07-11T18:38:21.913Z",
|
||||||
|
"vendeur": "Test Vendeur",
|
||||||
|
"typeArticle": "Chandelle",
|
||||||
|
"categorie": "F2",
|
||||||
|
"quantite": 1,
|
||||||
|
"gencode": "1234567890123",
|
||||||
|
"nom": "TEST",
|
||||||
|
"prenom": "Photo",
|
||||||
|
"dateNaissance": "1990-01-01",
|
||||||
|
"lieuNaissance": "Test",
|
||||||
|
"modePaiement": "Espèce",
|
||||||
|
"typeIdentite": "Passeport",
|
||||||
|
"numeroIdentite": "123456789",
|
||||||
|
"autoriteDelivrance": "Test",
|
||||||
|
"dateDelivrance": "2025-01-01",
|
||||||
|
"photo_recto": null,
|
||||||
|
"photo_verso": null,
|
||||||
|
"photo_ticket": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 6,
|
||||||
|
"storeId": 1,
|
||||||
|
"userId": 1,
|
||||||
|
"timestamp": "2025-07-10T00:08:19.097Z",
|
||||||
|
"vendeur": "Moi",
|
||||||
|
"typeArticle": "Chandelle romaine",
|
||||||
|
"categorie": "F2",
|
||||||
|
"quantite": 1,
|
||||||
|
"gencode": "3660092323745",
|
||||||
|
"nom": "SCHAL",
|
||||||
|
"prenom": "Anne-Laure",
|
||||||
|
"dateNaissance": "2018-02-10",
|
||||||
|
"lieuNaissance": "Bar le duc",
|
||||||
|
"modePaiement": "Espèce",
|
||||||
|
"typeIdentite": "Passeport",
|
||||||
|
"numeroIdentite": "qsdfqsdgc23445",
|
||||||
|
"autoriteDelivrance": "Frouard",
|
||||||
|
"dateDelivrance": "2025-07-01",
|
||||||
|
"photo_recto": null,
|
||||||
|
"photo_verso": null,
|
||||||
|
"photo_ticket": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 4,
|
||||||
|
"storeId": 1,
|
||||||
|
"userId": 1,
|
||||||
|
"timestamp": "2025-07-09T19:11:36.505Z",
|
||||||
|
"vendeur": "Moi",
|
||||||
|
"typeArticle": "Batterie",
|
||||||
|
"categorie": "F3",
|
||||||
|
"quantite": 1,
|
||||||
|
"gencode": "3660092323745",
|
||||||
|
"nom": "SCHAL",
|
||||||
|
"prenom": "Michaël",
|
||||||
|
"dateNaissance": "2025-07-18",
|
||||||
|
"lieuNaissance": "Bar le duc",
|
||||||
|
"modePaiement": "Espèce",
|
||||||
|
"typeIdentite": "CNI",
|
||||||
|
"numeroIdentite": "qsdfqsdgc23445",
|
||||||
|
"autoriteDelivrance": "Frouard",
|
||||||
|
"dateDelivrance": "2025-07-01",
|
||||||
|
"photo_recto": null,
|
||||||
|
"photo_verso": null,
|
||||||
|
"photo_ticket": null
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"metadata": {
|
||||||
|
"totalUsers": 5,
|
||||||
|
"totalStores": 2,
|
||||||
|
"totalSales": 12,
|
||||||
|
"exportedBy": "system-auto-backup"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,24 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
# Script de construction Docker pour RegisFlow
|
|
||||||
# Ce script construit l'image Docker localement
|
|
||||||
|
|
||||||
echo "🔧 Construction de l'image Docker RegisFlow..."
|
|
||||||
|
|
||||||
# Arrêter les conteneurs existants
|
|
||||||
echo "🛑 Arrêt des conteneurs existants..."
|
|
||||||
docker-compose down
|
|
||||||
|
|
||||||
# Construire l'image avec un nom spécifique
|
|
||||||
echo "🏗️ Construction de l'image..."
|
|
||||||
docker build -t regisflow:latest .
|
|
||||||
|
|
||||||
# Vérifier que l'image a été construite
|
|
||||||
echo "📋 Vérification de l'image construite..."
|
|
||||||
docker images | grep regisflow
|
|
||||||
|
|
||||||
echo "✅ Image construite avec succès !"
|
|
||||||
echo "🐳 Vous pouvez maintenant utiliser 'regisflow:latest' dans Portainer"
|
|
||||||
echo ""
|
|
||||||
echo "Pour démarrer l'application :"
|
|
||||||
echo " docker-compose up -d"
|
|
||||||
@@ -1,58 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
# Script de déploiement simplifié pour Portainer
|
|
||||||
# Gère tout automatiquement sans configuration manuelle
|
|
||||||
|
|
||||||
echo "🚀 Déploiement RegisFlow pour Portainer (Automatique)"
|
|
||||||
echo "===================================================="
|
|
||||||
|
|
||||||
# Créer un répertoire de déploiement temporaire
|
|
||||||
DEPLOY_DIR="/tmp/regisflow-deploy"
|
|
||||||
CURRENT_DIR=$(pwd)
|
|
||||||
|
|
||||||
echo "📁 Préparation du déploiement..."
|
|
||||||
|
|
||||||
# Nettoyer le répertoire de déploiement s'il existe
|
|
||||||
rm -rf "$DEPLOY_DIR"
|
|
||||||
mkdir -p "$DEPLOY_DIR"
|
|
||||||
|
|
||||||
# Copier tous les fichiers nécessaires
|
|
||||||
echo "📋 Copie des fichiers..."
|
|
||||||
cp -r . "$DEPLOY_DIR/"
|
|
||||||
cd "$DEPLOY_DIR"
|
|
||||||
|
|
||||||
# Utiliser le Docker Compose spécifique à Portainer
|
|
||||||
mv docker-compose-portainer.yml docker-compose.yml
|
|
||||||
|
|
||||||
echo "🔧 Construction et démarrage..."
|
|
||||||
|
|
||||||
# Arrêter les conteneurs existants
|
|
||||||
docker-compose down 2>/dev/null || true
|
|
||||||
|
|
||||||
# Construire et démarrer
|
|
||||||
docker-compose up -d --build
|
|
||||||
|
|
||||||
if [ $? -eq 0 ]; then
|
|
||||||
echo "✅ Déploiement réussi!"
|
|
||||||
echo ""
|
|
||||||
echo "📊 État des conteneurs:"
|
|
||||||
docker-compose ps
|
|
||||||
echo ""
|
|
||||||
echo "🔗 Application accessible sur: http://localhost:5000"
|
|
||||||
echo "🔐 Connexion par défaut: admin/admin123"
|
|
||||||
echo "🗄️ PostgreSQL accessible sur le port: 5433"
|
|
||||||
echo ""
|
|
||||||
echo "📋 Commandes utiles:"
|
|
||||||
echo " - Voir les logs: docker-compose logs -f"
|
|
||||||
echo " - Arrêter: docker-compose down"
|
|
||||||
echo " - Redémarrer: docker-compose restart"
|
|
||||||
echo ""
|
|
||||||
echo "📁 Fichiers de déploiement dans: $DEPLOY_DIR"
|
|
||||||
else
|
|
||||||
echo "❌ Échec du déploiement"
|
|
||||||
echo "📋 Vérifiez les logs avec: docker-compose logs"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Retourner au répertoire original
|
|
||||||
cd "$CURRENT_DIR"
|
|
||||||
@@ -1,47 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
# Script de déploiement pour Portainer RegisFlow
|
|
||||||
# Ce script prépare et déploie RegisFlow via Portainer
|
|
||||||
|
|
||||||
echo "🚀 Déploiement RegisFlow pour Portainer"
|
|
||||||
echo "======================================"
|
|
||||||
|
|
||||||
# Étape 1: Construire l'image Docker
|
|
||||||
echo "🔧 Étape 1: Construction de l'image Docker..."
|
|
||||||
docker build -t regisflow:latest .
|
|
||||||
|
|
||||||
if [ $? -eq 0 ]; then
|
|
||||||
echo "✅ Image construite avec succès"
|
|
||||||
else
|
|
||||||
echo "❌ Échec de la construction de l'image"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Étape 2: Vérifier que l'image existe
|
|
||||||
echo "🔍 Étape 2: Vérification de l'image..."
|
|
||||||
docker images | grep regisflow
|
|
||||||
|
|
||||||
# Étape 3: Arrêter les conteneurs existants si ils existent
|
|
||||||
echo "🛑 Étape 3: Nettoyage des conteneurs existants..."
|
|
||||||
docker stop regisflow-app regisflow-db 2>/dev/null || true
|
|
||||||
docker rm regisflow-app regisflow-db 2>/dev/null || true
|
|
||||||
|
|
||||||
# Étape 4: Informations pour Portainer
|
|
||||||
echo ""
|
|
||||||
echo "🐳 Instructions pour Portainer:"
|
|
||||||
echo "==============================="
|
|
||||||
echo "1. Dans Portainer, allez dans 'Stacks'"
|
|
||||||
echo "2. Cliquez sur 'Add stack'"
|
|
||||||
echo "3. Donnez un nom: 'regisflow'"
|
|
||||||
echo "4. Copiez le contenu du fichier 'portainer-stack.yml'"
|
|
||||||
echo "5. Cliquez sur 'Deploy the stack'"
|
|
||||||
echo ""
|
|
||||||
echo "📝 Nom de l'image à utiliser: regisflow:latest"
|
|
||||||
echo "🔗 URL d'accès: http://votre-serveur:5000"
|
|
||||||
echo "🔐 Connexion par défaut: admin/admin123"
|
|
||||||
echo ""
|
|
||||||
echo "📋 Ports exposés:"
|
|
||||||
echo " - Application: 5000"
|
|
||||||
echo " - PostgreSQL: 5433"
|
|
||||||
echo ""
|
|
||||||
echo "✅ Prêt pour le déploiement Portainer!"
|
|
||||||
@@ -1,157 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
# Script de déploiement automatique RegisFlow Production
|
|
||||||
# Usage: ./deploy-production.sh
|
|
||||||
|
|
||||||
set -e
|
|
||||||
|
|
||||||
echo "🚀 Déploiement RegisFlow en production"
|
|
||||||
echo "======================================="
|
|
||||||
|
|
||||||
# Couleurs pour les messages
|
|
||||||
RED='\033[0;31m'
|
|
||||||
GREEN='\033[0;32m'
|
|
||||||
YELLOW='\033[1;33m'
|
|
||||||
BLUE='\033[0;34m'
|
|
||||||
NC='\033[0m' # No Color
|
|
||||||
|
|
||||||
# Fonction pour afficher les messages
|
|
||||||
log_info() {
|
|
||||||
echo -e "${BLUE}ℹ️ $1${NC}"
|
|
||||||
}
|
|
||||||
|
|
||||||
log_success() {
|
|
||||||
echo -e "${GREEN}✅ $1${NC}"
|
|
||||||
}
|
|
||||||
|
|
||||||
log_warning() {
|
|
||||||
echo -e "${YELLOW}⚠️ $1${NC}"
|
|
||||||
}
|
|
||||||
|
|
||||||
log_error() {
|
|
||||||
echo -e "${RED}❌ $1${NC}"
|
|
||||||
}
|
|
||||||
|
|
||||||
# Vérifier que Docker est installé
|
|
||||||
if ! command -v docker &> /dev/null; then
|
|
||||||
log_error "Docker n'est pas installé. Veuillez l'installer d'abord."
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
if ! command -v docker-compose &> /dev/null; then
|
|
||||||
log_error "Docker Compose n'est pas installé. Veuillez l'installer d'abord."
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Créer le répertoire de déploiement
|
|
||||||
DEPLOY_DIR="/opt/regisflow"
|
|
||||||
log_info "Création du répertoire de déploiement : $DEPLOY_DIR"
|
|
||||||
|
|
||||||
if [ ! -d "$DEPLOY_DIR" ]; then
|
|
||||||
sudo mkdir -p "$DEPLOY_DIR"
|
|
||||||
sudo chown $USER:$USER "$DEPLOY_DIR"
|
|
||||||
log_success "Répertoire créé"
|
|
||||||
else
|
|
||||||
log_info "Répertoire existant"
|
|
||||||
fi
|
|
||||||
|
|
||||||
cd "$DEPLOY_DIR"
|
|
||||||
|
|
||||||
# Vérifier la configuration .env
|
|
||||||
if [ ! -f ".env" ]; then
|
|
||||||
log_warning "Fichier .env manquant"
|
|
||||||
|
|
||||||
if [ -f ".env.production" ]; then
|
|
||||||
log_info "Copie du template .env.production vers .env"
|
|
||||||
cp .env.production .env
|
|
||||||
else
|
|
||||||
log_info "Création d'un fichier .env de base"
|
|
||||||
cat > .env << EOF
|
|
||||||
# Configuration RegisFlow Production
|
|
||||||
POSTGRES_PASSWORD=RegisFlow2024!PostgreSQL_$(date +%s)
|
|
||||||
SESSION_SECRET=RegisFlow2024SessionSecret_$(openssl rand -hex 32)
|
|
||||||
NODE_ENV=production
|
|
||||||
PORT=5000
|
|
||||||
TZ=Europe/Paris
|
|
||||||
SECURE_COOKIES=true
|
|
||||||
DATA_RETENTION_MONTHS=19
|
|
||||||
BACKUP_RETENTION_DAYS=90
|
|
||||||
MAX_BACKUP_COUNT=20
|
|
||||||
EOF
|
|
||||||
fi
|
|
||||||
|
|
||||||
log_warning "IMPORTANT: Éditez le fichier .env avec vos propres mots de passe !"
|
|
||||||
log_warning "Fichier: $DEPLOY_DIR/.env"
|
|
||||||
|
|
||||||
read -p "Appuyez sur Entrée après avoir modifié le fichier .env..."
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Vérifier les fichiers Docker requis
|
|
||||||
REQUIRED_FILES=("docker-compose.yml" "Dockerfile")
|
|
||||||
for file in "${REQUIRED_FILES[@]}"; do
|
|
||||||
if [ ! -f "$file" ]; then
|
|
||||||
log_error "Fichier manquant: $file"
|
|
||||||
log_info "Assurez-vous que tous les fichiers du projet sont présents dans $DEPLOY_DIR"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
|
|
||||||
# Arrêter les anciens conteneurs si ils existent
|
|
||||||
log_info "Arrêt des anciens conteneurs..."
|
|
||||||
docker-compose down --remove-orphans 2>/dev/null || true
|
|
||||||
|
|
||||||
# Construire et démarrer les services
|
|
||||||
log_info "Construction et démarrage des services..."
|
|
||||||
docker-compose up -d --build
|
|
||||||
|
|
||||||
# Attendre que les services soient prêts
|
|
||||||
log_info "Attente du démarrage des services..."
|
|
||||||
sleep 30
|
|
||||||
|
|
||||||
# Vérifier la santé des services
|
|
||||||
log_info "Vérification de la santé des services..."
|
|
||||||
|
|
||||||
# Vérifier PostgreSQL
|
|
||||||
if docker-compose exec -T regisflow-db pg_isready -U regisflow >/dev/null 2>&1; then
|
|
||||||
log_success "PostgreSQL est opérationnel"
|
|
||||||
else
|
|
||||||
log_error "PostgreSQL n'est pas accessible"
|
|
||||||
docker-compose logs regisflow-db
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Vérifier l'application
|
|
||||||
sleep 10
|
|
||||||
if curl -s -f http://localhost:5000/health >/dev/null 2>&1; then
|
|
||||||
log_success "Application RegisFlow est opérationnelle"
|
|
||||||
else
|
|
||||||
log_error "L'application n'est pas accessible"
|
|
||||||
docker-compose logs regisflow
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Afficher les informations de connexion
|
|
||||||
echo ""
|
|
||||||
log_success "🎉 Déploiement terminé avec succès !"
|
|
||||||
echo "======================================="
|
|
||||||
log_info "URL de l'application: http://localhost:5000"
|
|
||||||
log_info "Compte administrateur par défaut:"
|
|
||||||
log_info " - Utilisateur: admin"
|
|
||||||
log_info " - Mot de passe: admin123"
|
|
||||||
log_warning "CHANGEZ le mot de passe administrateur après la première connexion !"
|
|
||||||
echo ""
|
|
||||||
log_info "Base de données PostgreSQL accessible sur le port 5433"
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# Afficher les commandes utiles
|
|
||||||
echo "Commandes utiles:"
|
|
||||||
echo "=================="
|
|
||||||
echo "📋 Voir les logs: docker-compose logs -f"
|
|
||||||
echo "📊 État des services: docker-compose ps"
|
|
||||||
echo "🔄 Redémarrer: docker-compose restart"
|
|
||||||
echo "🛑 Arrêter: docker-compose down"
|
|
||||||
echo "📈 Statistiques: docker stats"
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
log_info "Pour configurer un reverse proxy, consultez PRODUCTION.md"
|
|
||||||
log_success "Déploiement terminé !"
|
|
||||||
@@ -1,70 +0,0 @@
|
|||||||
# Guide pour changer de réseau dans Portainer
|
|
||||||
# RegisFlow - Configuration réseau flexible
|
|
||||||
|
|
||||||
# ==========================================
|
|
||||||
# INSTALLATION STANDARD
|
|
||||||
# ==========================================
|
|
||||||
# 1. Déployez RegisFlow avec docker-compose up -d
|
|
||||||
# 2. Dans Portainer, allez dans Stacks > regisflow
|
|
||||||
# 3. Utilisez "Migrate" ou "Redeploy" pour changer de réseau
|
|
||||||
|
|
||||||
# ==========================================
|
|
||||||
# CHANGER DE RÉSEAU DANS PORTAINER
|
|
||||||
# ==========================================
|
|
||||||
# Option 1 : Via l'interface Portainer
|
|
||||||
# 1. Containers > regisflow-app/regisflow-db
|
|
||||||
# 2. "Disconnect" du réseau actuel
|
|
||||||
# 3. "Connect" au nouveau réseau
|
|
||||||
# 4. Redémarrer les containers
|
|
||||||
|
|
||||||
# Option 2 : Via la Stack Portainer
|
|
||||||
# 1. Stacks > votre-stack-regisflow
|
|
||||||
# 2. Editor > Modifier la section networks
|
|
||||||
# 3. Deploy the stack
|
|
||||||
|
|
||||||
# ==========================================
|
|
||||||
# RÉSEAUX COMPATIBLES PORTAINER
|
|
||||||
# ==========================================
|
|
||||||
|
|
||||||
# Réseau nginx_default (configuration actuelle)
|
|
||||||
networks:
|
|
||||||
default:
|
|
||||||
external: true
|
|
||||||
name: nginx_default
|
|
||||||
|
|
||||||
# Autres réseaux existants
|
|
||||||
networks:
|
|
||||||
default:
|
|
||||||
external: true
|
|
||||||
name: autre-reseau-existant
|
|
||||||
|
|
||||||
# Réseau macvlan (IP directe)
|
|
||||||
networks:
|
|
||||||
default:
|
|
||||||
driver: macvlan
|
|
||||||
driver_opts:
|
|
||||||
parent: eth0
|
|
||||||
|
|
||||||
# Réseau host (sans isolation)
|
|
||||||
# Supprimez la section networks et ajoutez :
|
|
||||||
# network_mode: host dans chaque service
|
|
||||||
|
|
||||||
# ==========================================
|
|
||||||
# PROCÉDURE MIGRATION PORTAINER
|
|
||||||
# ==========================================
|
|
||||||
# 1. Arrêter la stack dans Portainer
|
|
||||||
# 2. Modifier le docker-compose.yml si nécessaire
|
|
||||||
# 3. Redéployer la stack
|
|
||||||
# 4. Vérifier la connectivité réseau
|
|
||||||
|
|
||||||
# ==========================================
|
|
||||||
# DÉPANNAGE RÉSEAU
|
|
||||||
# ==========================================
|
|
||||||
# Vérifier les réseaux Docker :
|
|
||||||
# docker network ls
|
|
||||||
#
|
|
||||||
# Inspecter un réseau :
|
|
||||||
# docker network inspect nom-du-reseau
|
|
||||||
#
|
|
||||||
# Connecter manuellement un container :
|
|
||||||
# docker network connect nom-reseau nom-container
|
|
||||||
@@ -1,77 +0,0 @@
|
|||||||
version: '3.8'
|
|
||||||
|
|
||||||
# Docker Compose pour Portainer - Construction automatique
|
|
||||||
# Ce fichier gère tout automatiquement sans configuration supplémentaire
|
|
||||||
services:
|
|
||||||
# Base de données PostgreSQL
|
|
||||||
regisflow-db:
|
|
||||||
image: postgres:15-alpine
|
|
||||||
container_name: regisflow-db
|
|
||||||
environment:
|
|
||||||
POSTGRES_DB: regisflow
|
|
||||||
POSTGRES_USER: regisflow
|
|
||||||
POSTGRES_PASSWORD: RegisFlow2024!PostgreSQL
|
|
||||||
volumes:
|
|
||||||
- regisflow_postgres_data:/var/lib/postgresql/data
|
|
||||||
ports:
|
|
||||||
- "5433:5432"
|
|
||||||
restart: unless-stopped
|
|
||||||
healthcheck:
|
|
||||||
test: ["CMD-SHELL", "pg_isready -U regisflow -d regisflow"]
|
|
||||||
interval: 30s
|
|
||||||
timeout: 10s
|
|
||||||
retries: 5
|
|
||||||
start_period: 30s
|
|
||||||
networks:
|
|
||||||
- regisflow_network
|
|
||||||
|
|
||||||
# Application RegisFlow - Construction depuis le répertoire courant
|
|
||||||
regisflow-app:
|
|
||||||
build:
|
|
||||||
context: .
|
|
||||||
dockerfile: Dockerfile
|
|
||||||
target: production
|
|
||||||
image: regisflow-app:latest
|
|
||||||
container_name: regisflow-app
|
|
||||||
depends_on:
|
|
||||||
regisflow-db:
|
|
||||||
condition: service_healthy
|
|
||||||
environment:
|
|
||||||
NODE_ENV: production
|
|
||||||
PORT: 5000
|
|
||||||
DATABASE_URL: postgresql://regisflow:RegisFlow2024!PostgreSQL@regisflow-db:5432/regisflow
|
|
||||||
SESSION_SECRET: RegisFlow2024SessionSecretKey1234567890ABCDEF
|
|
||||||
TZ: Europe/Paris
|
|
||||||
SECURE_COOKIES: false
|
|
||||||
DATA_RETENTION_MONTHS: 19
|
|
||||||
BACKUP_RETENTION_DAYS: 90
|
|
||||||
MAX_BACKUP_COUNT: 20
|
|
||||||
volumes:
|
|
||||||
- regisflow_backup_data:/app/backups
|
|
||||||
- regisflow_logs_data:/app/logs
|
|
||||||
ports:
|
|
||||||
- "5000:5000"
|
|
||||||
restart: unless-stopped
|
|
||||||
healthcheck:
|
|
||||||
test: ["CMD-SHELL", "wget --no-verbose --tries=1 --spider http://localhost:5000/health || exit 1"]
|
|
||||||
interval: 30s
|
|
||||||
timeout: 15s
|
|
||||||
retries: 3
|
|
||||||
start_period: 90s
|
|
||||||
networks:
|
|
||||||
- regisflow_network
|
|
||||||
|
|
||||||
# Volumes avec noms uniques pour éviter les conflits
|
|
||||||
volumes:
|
|
||||||
regisflow_postgres_data:
|
|
||||||
driver: local
|
|
||||||
regisflow_backup_data:
|
|
||||||
driver: local
|
|
||||||
regisflow_logs_data:
|
|
||||||
driver: local
|
|
||||||
|
|
||||||
# Réseau dédié avec nom unique
|
|
||||||
networks:
|
|
||||||
regisflow_network:
|
|
||||||
driver: bridge
|
|
||||||
name: regisflow_net
|
|
||||||
@@ -1,113 +0,0 @@
|
|||||||
version: '3.8'
|
|
||||||
|
|
||||||
# Configuration Docker Compose optimisée pour Production
|
|
||||||
# Usage: docker-compose -f docker-compose.prod.yml up -d
|
|
||||||
services:
|
|
||||||
# Base de données PostgreSQL Production
|
|
||||||
regisflow-db:
|
|
||||||
image: postgres:15-alpine
|
|
||||||
container_name: regisflow-db-prod
|
|
||||||
environment:
|
|
||||||
POSTGRES_DB: regisflow
|
|
||||||
POSTGRES_USER: regisflow
|
|
||||||
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
|
|
||||||
POSTGRES_INITDB_ARGS: "--auth-host=scram-sha-256 --auth-local=scram-sha-256"
|
|
||||||
volumes:
|
|
||||||
- postgres_data_prod:/var/lib/postgresql/data
|
|
||||||
- ./postgresql.conf:/etc/postgresql/postgresql.conf:ro
|
|
||||||
ports:
|
|
||||||
- "5433:5432"
|
|
||||||
restart: unless-stopped
|
|
||||||
deploy:
|
|
||||||
resources:
|
|
||||||
limits:
|
|
||||||
memory: 1G
|
|
||||||
cpus: '1.0'
|
|
||||||
reservations:
|
|
||||||
memory: 512M
|
|
||||||
cpus: '0.5'
|
|
||||||
healthcheck:
|
|
||||||
test: ["CMD-SHELL", "pg_isready -U regisflow -d regisflow"]
|
|
||||||
interval: 30s
|
|
||||||
timeout: 10s
|
|
||||||
retries: 5
|
|
||||||
start_period: 60s
|
|
||||||
command: postgres -c config_file=/etc/postgresql/postgresql.conf
|
|
||||||
|
|
||||||
# Application RegisFlow Production
|
|
||||||
regisflow:
|
|
||||||
build:
|
|
||||||
context: .
|
|
||||||
dockerfile: Dockerfile
|
|
||||||
target: production
|
|
||||||
args:
|
|
||||||
- NODE_ENV=production
|
|
||||||
image: regisflow:production
|
|
||||||
container_name: regisflow-app-prod
|
|
||||||
depends_on:
|
|
||||||
regisflow-db:
|
|
||||||
condition: service_healthy
|
|
||||||
pull_policy: never
|
|
||||||
environment:
|
|
||||||
NODE_ENV: production
|
|
||||||
PORT: 5000
|
|
||||||
DATABASE_URL: postgresql://regisflow:${POSTGRES_PASSWORD}@regisflow-db:5432/regisflow
|
|
||||||
SESSION_SECRET: ${SESSION_SECRET}
|
|
||||||
TZ: ${TZ:-Europe/Paris}
|
|
||||||
SECURE_COOKIES: ${SECURE_COOKIES:-true}
|
|
||||||
DATA_RETENTION_MONTHS: ${DATA_RETENTION_MONTHS:-19}
|
|
||||||
BACKUP_RETENTION_DAYS: ${BACKUP_RETENTION_DAYS:-90}
|
|
||||||
MAX_BACKUP_COUNT: ${MAX_BACKUP_COUNT:-20}
|
|
||||||
NODE_OPTIONS: "--max-old-space-size=1024"
|
|
||||||
volumes:
|
|
||||||
- backup_data_prod:/app/backups
|
|
||||||
- logs_data_prod:/app/logs
|
|
||||||
ports:
|
|
||||||
- "5000:5000"
|
|
||||||
restart: unless-stopped
|
|
||||||
deploy:
|
|
||||||
resources:
|
|
||||||
limits:
|
|
||||||
memory: 1.5G
|
|
||||||
cpus: '2.0'
|
|
||||||
reservations:
|
|
||||||
memory: 512M
|
|
||||||
cpus: '0.5'
|
|
||||||
healthcheck:
|
|
||||||
test: ["CMD-SHELL", "wget --no-verbose --tries=1 --spider http://localhost:5000/health || exit 1"]
|
|
||||||
interval: 30s
|
|
||||||
timeout: 15s
|
|
||||||
retries: 3
|
|
||||||
start_period: 120s
|
|
||||||
logging:
|
|
||||||
driver: "json-file"
|
|
||||||
options:
|
|
||||||
max-size: "100m"
|
|
||||||
max-file: "5"
|
|
||||||
|
|
||||||
# Volumes persistants pour production
|
|
||||||
volumes:
|
|
||||||
postgres_data_prod:
|
|
||||||
driver: local
|
|
||||||
driver_opts:
|
|
||||||
type: none
|
|
||||||
o: bind
|
|
||||||
device: /opt/regisflow/data/postgres
|
|
||||||
backup_data_prod:
|
|
||||||
driver: local
|
|
||||||
driver_opts:
|
|
||||||
type: none
|
|
||||||
o: bind
|
|
||||||
device: /opt/regisflow/data/backups
|
|
||||||
logs_data_prod:
|
|
||||||
driver: local
|
|
||||||
driver_opts:
|
|
||||||
type: none
|
|
||||||
o: bind
|
|
||||||
device: /opt/regisflow/data/logs
|
|
||||||
|
|
||||||
# Réseau pour reverse proxy
|
|
||||||
networks:
|
|
||||||
default:
|
|
||||||
name: regisflow-network
|
|
||||||
driver: bridge
|
|
||||||
@@ -1,22 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
# Script pour créer l'image exacte que Portainer attend
|
|
||||||
echo "🔧 Création de l'image regisflow-regisflow:latest pour Portainer"
|
|
||||||
|
|
||||||
# Construire l'image avec le nom exact que Portainer cherche
|
|
||||||
docker build -t regisflow-regisflow:latest .
|
|
||||||
|
|
||||||
if [ $? -eq 0 ]; then
|
|
||||||
echo "✅ Image regisflow-regisflow:latest créée avec succès"
|
|
||||||
|
|
||||||
# Vérifier que l'image existe
|
|
||||||
echo "📋 Vérification de l'image:"
|
|
||||||
docker images | grep regisflow-regisflow
|
|
||||||
|
|
||||||
echo ""
|
|
||||||
echo "🐳 L'image est maintenant disponible pour Portainer"
|
|
||||||
echo "💡 Vous pouvez maintenant redéployer votre stack dans Portainer"
|
|
||||||
else
|
|
||||||
echo "❌ Échec de la création de l'image"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
@@ -1,151 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
# Script d'initialisation de la base de données RegisFlow
|
|
||||||
# Usage: ./init-db.sh [DATABASE_URL]
|
|
||||||
|
|
||||||
set -e
|
|
||||||
|
|
||||||
# Configuration par défaut
|
|
||||||
DEFAULT_DB_HOST="localhost"
|
|
||||||
DEFAULT_DB_PORT="5433"
|
|
||||||
DEFAULT_DB_NAME="regisflow"
|
|
||||||
DEFAULT_DB_USER="regisflow"
|
|
||||||
DEFAULT_DB_PASSWORD="RegisFlow2024!PostgreSQL"
|
|
||||||
|
|
||||||
# Couleurs pour les messages
|
|
||||||
RED='\033[0;31m'
|
|
||||||
GREEN='\033[0;32m'
|
|
||||||
YELLOW='\033[1;33m'
|
|
||||||
BLUE='\033[0;34m'
|
|
||||||
NC='\033[0m'
|
|
||||||
|
|
||||||
log_info() {
|
|
||||||
echo -e "${BLUE}ℹ️ $1${NC}"
|
|
||||||
}
|
|
||||||
|
|
||||||
log_success() {
|
|
||||||
echo -e "${GREEN}✅ $1${NC}"
|
|
||||||
}
|
|
||||||
|
|
||||||
log_warning() {
|
|
||||||
echo -e "${YELLOW}⚠️ $1${NC}"
|
|
||||||
}
|
|
||||||
|
|
||||||
log_error() {
|
|
||||||
echo -e "${RED}❌ $1${NC}"
|
|
||||||
}
|
|
||||||
|
|
||||||
# Fonction pour extraire les informations de DATABASE_URL
|
|
||||||
parse_database_url() {
|
|
||||||
local url="$1"
|
|
||||||
|
|
||||||
# Extraire les composants de l'URL PostgreSQL
|
|
||||||
if [[ $url =~ postgresql://([^:]+):([^@]+)@([^:]+):([^/]+)/(.+) ]]; then
|
|
||||||
DB_USER="${BASH_REMATCH[1]}"
|
|
||||||
DB_PASSWORD="${BASH_REMATCH[2]}"
|
|
||||||
DB_HOST="${BASH_REMATCH[3]}"
|
|
||||||
DB_PORT="${BASH_REMATCH[4]}"
|
|
||||||
DB_NAME="${BASH_REMATCH[5]}"
|
|
||||||
else
|
|
||||||
log_error "Format DATABASE_URL invalide. Utilisez: postgresql://user:password@host:port/database"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
# Déterminer la configuration de la base de données
|
|
||||||
if [ -n "$1" ]; then
|
|
||||||
log_info "Utilisation de DATABASE_URL fournie: $1"
|
|
||||||
parse_database_url "$1"
|
|
||||||
elif [ -n "$DATABASE_URL" ]; then
|
|
||||||
log_info "Utilisation de DATABASE_URL depuis l'environnement"
|
|
||||||
parse_database_url "$DATABASE_URL"
|
|
||||||
else
|
|
||||||
log_info "Utilisation de la configuration par défaut"
|
|
||||||
DB_HOST="$DEFAULT_DB_HOST"
|
|
||||||
DB_PORT="$DEFAULT_DB_PORT"
|
|
||||||
DB_NAME="$DEFAULT_DB_NAME"
|
|
||||||
DB_USER="$DEFAULT_DB_USER"
|
|
||||||
DB_PASSWORD="$DEFAULT_DB_PASSWORD"
|
|
||||||
fi
|
|
||||||
|
|
||||||
log_info "Configuration de la base de données:"
|
|
||||||
log_info " Host: $DB_HOST"
|
|
||||||
log_info " Port: $DB_PORT"
|
|
||||||
log_info " Database: $DB_NAME"
|
|
||||||
log_info " User: $DB_USER"
|
|
||||||
|
|
||||||
# Vérifier que psql est installé
|
|
||||||
if ! command -v psql &> /dev/null; then
|
|
||||||
log_error "psql n'est pas installé. Installez PostgreSQL client."
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Vérifier la connexion à PostgreSQL
|
|
||||||
log_info "Test de connexion à PostgreSQL..."
|
|
||||||
export PGPASSWORD="$DB_PASSWORD"
|
|
||||||
|
|
||||||
if ! psql -h "$DB_HOST" -p "$DB_PORT" -U "$DB_USER" -d "$DB_NAME" -c "\q" 2>/dev/null; then
|
|
||||||
log_error "Impossible de se connecter à PostgreSQL"
|
|
||||||
log_info "Vérifiez que PostgreSQL est démarré et accessible"
|
|
||||||
log_info "Commande de test: psql -h $DB_HOST -p $DB_PORT -U $DB_USER -d $DB_NAME"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
log_success "Connexion PostgreSQL réussie"
|
|
||||||
|
|
||||||
# Exécuter le script d'initialisation
|
|
||||||
log_info "Exécution du script d'initialisation..."
|
|
||||||
|
|
||||||
if [ -f "init.sql" ]; then
|
|
||||||
if psql -h "$DB_HOST" -p "$DB_PORT" -U "$DB_USER" -d "$DB_NAME" -f init.sql; then
|
|
||||||
log_success "Script d'initialisation exécuté avec succès"
|
|
||||||
else
|
|
||||||
log_error "Erreur lors de l'exécution du script d'initialisation"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
log_error "Fichier init.sql non trouvé"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Vérifier que les tables ont été créées
|
|
||||||
log_info "Vérification des tables créées..."
|
|
||||||
TABLES=$(psql -h "$DB_HOST" -p "$DB_PORT" -U "$DB_USER" -d "$DB_NAME" -t -c "SELECT tablename FROM pg_tables WHERE schemaname='public';" | tr -d ' ' | grep -v '^$')
|
|
||||||
|
|
||||||
if echo "$TABLES" | grep -q "users\|stores\|sales\|sessions"; then
|
|
||||||
log_success "Tables principales créées:"
|
|
||||||
echo "$TABLES" | while read -r table; do
|
|
||||||
if [ -n "$table" ]; then
|
|
||||||
log_info " - $table"
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
else
|
|
||||||
log_error "Les tables principales n'ont pas été créées correctement"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Vérifier l'utilisateur admin
|
|
||||||
log_info "Vérification de l'utilisateur administrateur..."
|
|
||||||
ADMIN_COUNT=$(psql -h "$DB_HOST" -p "$DB_PORT" -U "$DB_USER" -d "$DB_NAME" -t -c "SELECT COUNT(*) FROM users WHERE username='admin';" | tr -d ' ')
|
|
||||||
|
|
||||||
if [ "$ADMIN_COUNT" = "1" ]; then
|
|
||||||
log_success "Utilisateur admin créé avec succès"
|
|
||||||
else
|
|
||||||
log_warning "Problème avec la création de l'utilisateur admin"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Afficher le résumé
|
|
||||||
echo ""
|
|
||||||
log_success "🎉 Initialisation de la base de données terminée!"
|
|
||||||
echo "======================================================"
|
|
||||||
log_info "Base de données: $DB_NAME sur $DB_HOST:$DB_PORT"
|
|
||||||
log_info "Utilisateur administrateur:"
|
|
||||||
log_info " - Username: admin"
|
|
||||||
log_info " - Password: admin123"
|
|
||||||
log_warning "IMPORTANT: Changez le mot de passe admin après la première connexion!"
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# Nettoyer les variables d'environnement
|
|
||||||
unset PGPASSWORD
|
|
||||||
|
|
||||||
log_success "Prêt pour le déploiement!"
|
|
||||||
@@ -1,110 +0,0 @@
|
|||||||
# Configuration Nginx pour RegisFlow Production
|
|
||||||
# À placer dans /etc/nginx/sites-available/regisflow
|
|
||||||
|
|
||||||
server {
|
|
||||||
listen 80;
|
|
||||||
server_name votre-domaine.com www.votre-domaine.com;
|
|
||||||
|
|
||||||
# Redirection HTTPS (recommandé)
|
|
||||||
return 301 https://$server_name$request_uri;
|
|
||||||
}
|
|
||||||
|
|
||||||
server {
|
|
||||||
listen 443 ssl http2;
|
|
||||||
server_name votre-domaine.com www.votre-domaine.com;
|
|
||||||
|
|
||||||
# Certificats SSL (Let's Encrypt recommandé)
|
|
||||||
ssl_certificate /etc/letsencrypt/live/votre-domaine.com/fullchain.pem;
|
|
||||||
ssl_certificate_key /etc/letsencrypt/live/votre-domaine.com/privkey.pem;
|
|
||||||
|
|
||||||
# Configuration SSL moderne
|
|
||||||
ssl_protocols TLSv1.2 TLSv1.3;
|
|
||||||
ssl_ciphers ECDHE-RSA-AES256-GCM-SHA512:DHE-RSA-AES256-GCM-SHA512:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES256-GCM-SHA384;
|
|
||||||
ssl_prefer_server_ciphers off;
|
|
||||||
ssl_session_cache shared:SSL:10m;
|
|
||||||
ssl_session_timeout 10m;
|
|
||||||
|
|
||||||
# Headers de sécurité
|
|
||||||
add_header X-Frame-Options DENY;
|
|
||||||
add_header X-Content-Type-Options nosniff;
|
|
||||||
add_header X-XSS-Protection "1; mode=block";
|
|
||||||
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
|
|
||||||
add_header Referrer-Policy "strict-origin-when-cross-origin";
|
|
||||||
|
|
||||||
# Taille maximale pour les uploads (photos)
|
|
||||||
client_max_body_size 50M;
|
|
||||||
|
|
||||||
# Timeouts
|
|
||||||
proxy_connect_timeout 60s;
|
|
||||||
proxy_send_timeout 60s;
|
|
||||||
proxy_read_timeout 60s;
|
|
||||||
proxy_buffers 32 4k;
|
|
||||||
proxy_buffer_size 8k;
|
|
||||||
|
|
||||||
# Compression
|
|
||||||
gzip on;
|
|
||||||
gzip_vary on;
|
|
||||||
gzip_min_length 1024;
|
|
||||||
gzip_proxied any;
|
|
||||||
gzip_comp_level 6;
|
|
||||||
gzip_types
|
|
||||||
text/plain
|
|
||||||
text/css
|
|
||||||
text/xml
|
|
||||||
text/javascript
|
|
||||||
application/json
|
|
||||||
application/javascript
|
|
||||||
application/xml+rss
|
|
||||||
application/atom+xml
|
|
||||||
image/svg+xml;
|
|
||||||
|
|
||||||
# Cache pour les assets statiques
|
|
||||||
location ~* \.(css|js|png|jpg|jpeg|gif|ico|svg|woff|woff2)$ {
|
|
||||||
proxy_pass http://localhost:5000;
|
|
||||||
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;
|
|
||||||
|
|
||||||
expires 30d;
|
|
||||||
add_header Cache-Control "public, immutable";
|
|
||||||
access_log off;
|
|
||||||
}
|
|
||||||
|
|
||||||
# API endpoints (pas de cache)
|
|
||||||
location /api/ {
|
|
||||||
proxy_pass http://localhost:5000;
|
|
||||||
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;
|
|
||||||
|
|
||||||
# Pas de cache pour les API
|
|
||||||
add_header Cache-Control "no-cache, no-store, must-revalidate";
|
|
||||||
add_header Pragma "no-cache";
|
|
||||||
add_header Expires "0";
|
|
||||||
}
|
|
||||||
|
|
||||||
# Health check
|
|
||||||
location /health {
|
|
||||||
proxy_pass http://localhost:5000;
|
|
||||||
access_log off;
|
|
||||||
}
|
|
||||||
|
|
||||||
# Application principale
|
|
||||||
location / {
|
|
||||||
proxy_pass http://localhost:5000;
|
|
||||||
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;
|
|
||||||
|
|
||||||
# Cache court pour les pages
|
|
||||||
expires 1h;
|
|
||||||
add_header Cache-Control "public";
|
|
||||||
}
|
|
||||||
|
|
||||||
# Logs
|
|
||||||
access_log /var/log/nginx/regisflow-access.log;
|
|
||||||
error_log /var/log/nginx/regisflow-error.log;
|
|
||||||
}
|
|
||||||
@@ -1,75 +0,0 @@
|
|||||||
version: '3.8'
|
|
||||||
|
|
||||||
# Configuration Stack Portainer pour RegisFlow avec build automatique
|
|
||||||
# Cette version construit l'image automatiquement depuis le code source
|
|
||||||
services:
|
|
||||||
# Base de données PostgreSQL
|
|
||||||
regisflow-db:
|
|
||||||
image: postgres:15-alpine
|
|
||||||
container_name: regisflow-db
|
|
||||||
environment:
|
|
||||||
POSTGRES_DB: regisflow
|
|
||||||
POSTGRES_USER: regisflow
|
|
||||||
POSTGRES_PASSWORD: RegisFlow2024!PostgreSQL
|
|
||||||
volumes:
|
|
||||||
- postgres_data:/var/lib/postgresql/data
|
|
||||||
ports:
|
|
||||||
- "5433:5432"
|
|
||||||
restart: unless-stopped
|
|
||||||
healthcheck:
|
|
||||||
test: ["CMD-SHELL", "pg_isready -U regisflow -d regisflow"]
|
|
||||||
interval: 30s
|
|
||||||
timeout: 10s
|
|
||||||
retries: 5
|
|
||||||
start_period: 30s
|
|
||||||
networks:
|
|
||||||
- regisflow-net
|
|
||||||
|
|
||||||
# Application RegisFlow - Construction automatique
|
|
||||||
regisflow:
|
|
||||||
build:
|
|
||||||
context: .
|
|
||||||
dockerfile: Dockerfile
|
|
||||||
target: production
|
|
||||||
container_name: regisflow-app
|
|
||||||
depends_on:
|
|
||||||
regisflow-db:
|
|
||||||
condition: service_healthy
|
|
||||||
environment:
|
|
||||||
NODE_ENV: production
|
|
||||||
PORT: 5000
|
|
||||||
DATABASE_URL: postgresql://regisflow:RegisFlow2024!PostgreSQL@regisflow-db:5432/regisflow
|
|
||||||
SESSION_SECRET: RegisFlow2024SessionSecretKey1234567890ABCDEF
|
|
||||||
TZ: Europe/Paris
|
|
||||||
SECURE_COOKIES: false
|
|
||||||
DATA_RETENTION_MONTHS: 19
|
|
||||||
BACKUP_RETENTION_DAYS: 90
|
|
||||||
MAX_BACKUP_COUNT: 20
|
|
||||||
volumes:
|
|
||||||
- backup_data:/app/backups
|
|
||||||
- logs_data:/app/logs
|
|
||||||
ports:
|
|
||||||
- "5000:5000"
|
|
||||||
restart: unless-stopped
|
|
||||||
healthcheck:
|
|
||||||
test: ["CMD-SHELL", "wget --no-verbose --tries=1 --spider http://localhost:5000/health || exit 1"]
|
|
||||||
interval: 30s
|
|
||||||
timeout: 15s
|
|
||||||
retries: 3
|
|
||||||
start_period: 90s
|
|
||||||
networks:
|
|
||||||
- regisflow-net
|
|
||||||
|
|
||||||
# Volumes persistants
|
|
||||||
volumes:
|
|
||||||
postgres_data:
|
|
||||||
driver: local
|
|
||||||
backup_data:
|
|
||||||
driver: local
|
|
||||||
logs_data:
|
|
||||||
driver: local
|
|
||||||
|
|
||||||
# Réseau dédié
|
|
||||||
networks:
|
|
||||||
regisflow-net:
|
|
||||||
driver: bridge
|
|
||||||
@@ -1,68 +0,0 @@
|
|||||||
version: '3.8'
|
|
||||||
|
|
||||||
# Configuration Stack Portainer pour RegisFlow
|
|
||||||
# À utiliser directement dans Portainer comme Stack
|
|
||||||
services:
|
|
||||||
# Base de données PostgreSQL
|
|
||||||
regisflow-db:
|
|
||||||
image: postgres:15-alpine
|
|
||||||
container_name: regisflow-db
|
|
||||||
environment:
|
|
||||||
POSTGRES_DB: regisflow
|
|
||||||
POSTGRES_USER: regisflow
|
|
||||||
POSTGRES_PASSWORD: RegisFlow2024!PostgreSQL
|
|
||||||
volumes:
|
|
||||||
- postgres_data:/var/lib/postgresql/data
|
|
||||||
ports:
|
|
||||||
- "5433:5432"
|
|
||||||
restart: unless-stopped
|
|
||||||
healthcheck:
|
|
||||||
test: ["CMD-SHELL", "pg_isready -U regisflow -d regisflow"]
|
|
||||||
interval: 30s
|
|
||||||
timeout: 10s
|
|
||||||
retries: 5
|
|
||||||
start_period: 30s
|
|
||||||
|
|
||||||
# Application RegisFlow - Construction depuis le code source
|
|
||||||
regisflow:
|
|
||||||
build:
|
|
||||||
context: .
|
|
||||||
dockerfile: Dockerfile
|
|
||||||
target: production
|
|
||||||
container_name: regisflow-app
|
|
||||||
depends_on:
|
|
||||||
regisflow-db:
|
|
||||||
condition: service_healthy
|
|
||||||
environment:
|
|
||||||
NODE_ENV: production
|
|
||||||
PORT: 5000
|
|
||||||
DATABASE_URL: postgresql://regisflow:RegisFlow2024!PostgreSQL@regisflow-db:5432/regisflow
|
|
||||||
SESSION_SECRET: RegisFlow2024SessionSecretKey1234567890ABCDEF
|
|
||||||
TZ: Europe/Paris
|
|
||||||
SECURE_COOKIES: false
|
|
||||||
DATA_RETENTION_MONTHS: 19
|
|
||||||
BACKUP_RETENTION_DAYS: 90
|
|
||||||
MAX_BACKUP_COUNT: 20
|
|
||||||
volumes:
|
|
||||||
- backup_data:/app/backups
|
|
||||||
- logs_data:/app/logs
|
|
||||||
ports:
|
|
||||||
- "5000:5000"
|
|
||||||
restart: unless-stopped
|
|
||||||
healthcheck:
|
|
||||||
test: ["CMD-SHELL", "wget --no-verbose --tries=1 --spider http://localhost:5000/health || exit 1"]
|
|
||||||
interval: 30s
|
|
||||||
timeout: 15s
|
|
||||||
retries: 3
|
|
||||||
start_period: 90s
|
|
||||||
|
|
||||||
# Volumes persistants
|
|
||||||
volumes:
|
|
||||||
postgres_data:
|
|
||||||
backup_data:
|
|
||||||
logs_data:
|
|
||||||
|
|
||||||
# Utilisation du réseau par défaut
|
|
||||||
networks:
|
|
||||||
default:
|
|
||||||
name: regisflow-network
|
|
||||||
@@ -1,52 +0,0 @@
|
|||||||
# Configuration PostgreSQL optimisée pour production RegisFlow
|
|
||||||
|
|
||||||
# CONNECTIONS AND AUTHENTICATION
|
|
||||||
listen_addresses = '*'
|
|
||||||
port = 5432
|
|
||||||
max_connections = 100
|
|
||||||
superuser_reserved_connections = 3
|
|
||||||
|
|
||||||
# MEMORY
|
|
||||||
shared_buffers = 256MB
|
|
||||||
effective_cache_size = 512MB
|
|
||||||
work_mem = 4MB
|
|
||||||
maintenance_work_mem = 64MB
|
|
||||||
|
|
||||||
# WRITE AHEAD LOG
|
|
||||||
wal_level = replica
|
|
||||||
max_wal_size = 1GB
|
|
||||||
min_wal_size = 80MB
|
|
||||||
checkpoint_completion_target = 0.7
|
|
||||||
wal_buffers = 16MB
|
|
||||||
|
|
||||||
# QUERY TUNING
|
|
||||||
random_page_cost = 1.1
|
|
||||||
effective_io_concurrency = 200
|
|
||||||
|
|
||||||
# LOGGING
|
|
||||||
log_destination = 'stderr'
|
|
||||||
logging_collector = on
|
|
||||||
log_directory = 'log'
|
|
||||||
log_filename = 'postgresql-%Y-%m-%d.log'
|
|
||||||
log_rotation_age = 1d
|
|
||||||
log_rotation_size = 100MB
|
|
||||||
log_min_duration_statement = 1000
|
|
||||||
log_checkpoints = on
|
|
||||||
log_connections = on
|
|
||||||
log_disconnections = on
|
|
||||||
log_lock_waits = on
|
|
||||||
log_statement = 'ddl'
|
|
||||||
|
|
||||||
# AUTOVACUUM
|
|
||||||
autovacuum = on
|
|
||||||
autovacuum_max_workers = 3
|
|
||||||
autovacuum_naptime = 30s
|
|
||||||
|
|
||||||
# LOCALE AND FORMATTING
|
|
||||||
datestyle = 'iso, mdy'
|
|
||||||
timezone = 'Europe/Paris'
|
|
||||||
lc_messages = 'en_US.utf8'
|
|
||||||
lc_monetary = 'en_US.utf8'
|
|
||||||
lc_numeric = 'en_US.utf8'
|
|
||||||
lc_time = 'en_US.utf8'
|
|
||||||
default_text_search_config = 'pg_catalog.english'
|
|
||||||
@@ -276,23 +276,21 @@ Preferred communication style: Simple, everyday language.
|
|||||||
|
|
||||||
### Production Deployment System (January 11, 2025)
|
### Production Deployment System (January 11, 2025)
|
||||||
- ✅ Complete production deployment configuration with Docker Compose
|
- ✅ Complete production deployment configuration with Docker Compose
|
||||||
- ✅ Automated deployment script (deploy-production.sh) with safety checks
|
|
||||||
- ✅ Production-optimized Dockerfile with multi-stage builds and security hardening
|
- ✅ Production-optimized Dockerfile with multi-stage builds and security hardening
|
||||||
- ✅ PostgreSQL production configuration with performance tuning
|
|
||||||
- ✅ Nginx reverse proxy configuration with SSL/TLS and security headers
|
|
||||||
- ✅ Health check endpoints for monitoring and load balancer integration
|
- ✅ Health check endpoints for monitoring and load balancer integration
|
||||||
- ✅ Environment-specific configurations (.env.production template)
|
|
||||||
- ✅ Resource limits and logging configuration for production containers
|
- ✅ Resource limits and logging configuration for production containers
|
||||||
- ✅ Persistent volume management for data persistence and backups
|
- ✅ Persistent volume management for data persistence and backups
|
||||||
- ✅ Production security features: non-root user, secure cookies, session management
|
- ✅ Production security features: non-root user, secure cookies, session management
|
||||||
- ✅ Replit Deployment integration ready for one-click production deployment
|
- ✅ Replit Deployment integration ready for one-click production deployment
|
||||||
- ✅ All production configurations validated and deployment suggested to user
|
|
||||||
- ✅ Photo capture system fully integrated with database storage
|
- ✅ Photo capture system fully integrated with database storage
|
||||||
- ✅ Modal de détails des ventes opérationnel avec support complet des photos
|
- ✅ Modal de détails des ventes opérationnel avec support complet des photos
|
||||||
- ✅ API et schéma de base de données synchronisés pour la production
|
- ✅ API et schéma de base de données synchronisés pour la production
|
||||||
- ✅ Bug critique corrigé : mapping camelCase/snake_case pour photo_ticket
|
- ✅ Bug critique corrigé : mapping camelCase/snake_case pour photo_ticket
|
||||||
- ✅ NewSaleForm.tsx corrigé pour inclure photoTicket dans la soumission
|
- ✅ NewSaleForm.tsx corrigé pour inclure photoTicket dans la soumission
|
||||||
- ✅ API routes.ts corrigé avec mapping automatique des photos
|
- ✅ API routes.ts corrigé avec mapping automatique des photos
|
||||||
|
- ✅ **Production Cleanup**: Removed all unnecessary deployment files and debug code
|
||||||
|
- ✅ **Clean Architecture**: Simplified to essential files only (Dockerfile, docker-compose.yml, init.sql)
|
||||||
|
- ✅ **Debug Removal**: All debug logs and temporary files cleaned for production
|
||||||
- ✅ RegisFlow prêt pour déploiement en production avec toutes les fonctionnalités
|
- ✅ RegisFlow prêt pour déploiement en production avec toutes les fonctionnalités
|
||||||
|
|
||||||
### Docker Configuration & Cleanup (January 9, 2025)
|
### Docker Configuration & Cleanup (January 9, 2025)
|
||||||
|
|||||||
@@ -1,31 +0,0 @@
|
|||||||
#!/usr/bin/env node
|
|
||||||
|
|
||||||
// Polyfill pour import.meta.dirname dans Node.js 18
|
|
||||||
import { fileURLToPath } from 'url';
|
|
||||||
import path from 'path';
|
|
||||||
import fs from 'fs';
|
|
||||||
|
|
||||||
// Obtenir le répertoire courant
|
|
||||||
const __filename = fileURLToPath(import.meta.url);
|
|
||||||
const __dirname = path.dirname(__filename);
|
|
||||||
const projectRoot = path.resolve(__dirname, '..');
|
|
||||||
|
|
||||||
// Lire le fichier dist/index.js et remplacer import.meta.dirname
|
|
||||||
const distPath = path.join(projectRoot, 'dist', 'index.js');
|
|
||||||
let distContent = fs.readFileSync(distPath, 'utf-8');
|
|
||||||
|
|
||||||
// Remplacer toutes les instances de import.meta.dirname par une valeur statique
|
|
||||||
const replacement = `"${projectRoot.replace(/\\/g, '\\\\')}"`;
|
|
||||||
distContent = distContent.replace(/import\.meta\.dirname/g, replacement);
|
|
||||||
|
|
||||||
// Aussi corriger les chemins pour le serveur statique
|
|
||||||
distContent = distContent.replace(/path3\.resolve\(\s*import\.meta\.dirname,\s*"public"\s*\)/g,
|
|
||||||
`path3.resolve("${projectRoot.replace(/\\/g, '\\\\')}", "public")`);
|
|
||||||
|
|
||||||
// Écrire le fichier modifié
|
|
||||||
fs.writeFileSync(distPath, distContent);
|
|
||||||
|
|
||||||
console.log('✅ Node.js 18 compatibility fix applied');
|
|
||||||
|
|
||||||
// Démarrer l'application
|
|
||||||
import('../dist/index.js').catch(console.error);
|
|
||||||
@@ -1,166 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
# Script de validation pour RegisFlow - Prêt pour la production
|
|
||||||
# Ce script vérifie que tous les composants sont correctement configurés
|
|
||||||
|
|
||||||
set -e
|
|
||||||
|
|
||||||
# Couleurs pour les messages
|
|
||||||
GREEN='\033[0;32m'
|
|
||||||
YELLOW='\033[1;33m'
|
|
||||||
RED='\033[0;31m'
|
|
||||||
BLUE='\033[0;34m'
|
|
||||||
NC='\033[0m'
|
|
||||||
|
|
||||||
log_info() {
|
|
||||||
echo -e "${BLUE}ℹ️ $1${NC}"
|
|
||||||
}
|
|
||||||
|
|
||||||
log_success() {
|
|
||||||
echo -e "${GREEN}✅ $1${NC}"
|
|
||||||
}
|
|
||||||
|
|
||||||
log_warning() {
|
|
||||||
echo -e "${YELLOW}⚠️ $1${NC}"
|
|
||||||
}
|
|
||||||
|
|
||||||
log_error() {
|
|
||||||
echo -e "${RED}❌ $1${NC}"
|
|
||||||
}
|
|
||||||
|
|
||||||
echo "🚀 Validation RegisFlow - Prêt pour la production"
|
|
||||||
echo "=================================================="
|
|
||||||
|
|
||||||
# 1. Vérifier les fichiers essentiels
|
|
||||||
log_info "Vérification des fichiers essentiels..."
|
|
||||||
|
|
||||||
REQUIRED_FILES=(
|
|
||||||
"package.json"
|
|
||||||
"Dockerfile"
|
|
||||||
"docker-compose.yml"
|
|
||||||
"init.sql"
|
|
||||||
"init-db.sh"
|
|
||||||
"docker-entrypoint-simple.sh"
|
|
||||||
"replit.md"
|
|
||||||
)
|
|
||||||
|
|
||||||
for file in "${REQUIRED_FILES[@]}"; do
|
|
||||||
if [ -f "$file" ]; then
|
|
||||||
log_success "Fichier présent: $file"
|
|
||||||
else
|
|
||||||
log_error "Fichier manquant: $file"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
|
|
||||||
# 2. Vérifier les permissions des scripts
|
|
||||||
log_info "Vérification des permissions des scripts..."
|
|
||||||
|
|
||||||
EXECUTABLE_FILES=(
|
|
||||||
"init-db.sh"
|
|
||||||
"docker-entrypoint-simple.sh"
|
|
||||||
"deploy-production.sh"
|
|
||||||
)
|
|
||||||
|
|
||||||
for file in "${EXECUTABLE_FILES[@]}"; do
|
|
||||||
if [ -x "$file" ]; then
|
|
||||||
log_success "Permissions OK: $file"
|
|
||||||
else
|
|
||||||
log_warning "Ajout des permissions: $file"
|
|
||||||
chmod +x "$file"
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
|
|
||||||
# 3. Vérifier la structure de la base de données
|
|
||||||
log_info "Vérification de la structure de la base de données..."
|
|
||||||
|
|
||||||
if command -v node >/dev/null 2>&1; then
|
|
||||||
if node -e "
|
|
||||||
const { db } = require('./server/db.ts');
|
|
||||||
const { sales } = require('./shared/schema.ts');
|
|
||||||
console.log('Schema validation passed');
|
|
||||||
process.exit(0);
|
|
||||||
" 2>/dev/null; then
|
|
||||||
log_success "Schéma de base de données valide"
|
|
||||||
else
|
|
||||||
log_warning "Impossible de valider le schéma (normal en développement)"
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
log_warning "Node.js non trouvé, validation du schéma ignorée"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# 4. Vérifier init.sql pour photo_ticket
|
|
||||||
log_info "Vérification du script SQL..."
|
|
||||||
|
|
||||||
if grep -q "photo_ticket TEXT" init.sql; then
|
|
||||||
log_success "Colonne photo_ticket présente dans init.sql"
|
|
||||||
else
|
|
||||||
log_error "Colonne photo_ticket manquante dans init.sql"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
# 5. Vérifier les dépendances Docker
|
|
||||||
log_info "Vérification de Docker..."
|
|
||||||
|
|
||||||
if command -v docker >/dev/null 2>&1; then
|
|
||||||
log_success "Docker installé"
|
|
||||||
|
|
||||||
if command -v docker-compose >/dev/null 2>&1; then
|
|
||||||
log_success "Docker Compose installé"
|
|
||||||
else
|
|
||||||
log_warning "Docker Compose non trouvé (docker compose moderne peut être utilisé)"
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
log_warning "Docker non installé (requis pour le déploiement)"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# 6. Vérifier les variables d'environnement de production
|
|
||||||
log_info "Vérification des variables d'environnement..."
|
|
||||||
|
|
||||||
if [ -f ".env.production" ]; then
|
|
||||||
log_success "Fichier .env.production présent"
|
|
||||||
|
|
||||||
# Vérifier les variables critiques
|
|
||||||
REQUIRED_VARS=(
|
|
||||||
"POSTGRES_PASSWORD"
|
|
||||||
"SESSION_SECRET"
|
|
||||||
)
|
|
||||||
|
|
||||||
for var in "${REQUIRED_VARS[@]}"; do
|
|
||||||
if grep -q "^${var}=" .env.production; then
|
|
||||||
log_success "Variable configurée: $var"
|
|
||||||
else
|
|
||||||
log_warning "Variable manquante dans .env.production: $var"
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
else
|
|
||||||
log_warning "Fichier .env.production manquant (recommandé pour la production)"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# 7. Vérifier la configuration du build
|
|
||||||
log_info "Vérification de la configuration de build..."
|
|
||||||
|
|
||||||
if grep -q "photo_ticket" shared/schema.ts; then
|
|
||||||
log_success "Schema TypeScript mis à jour avec photo_ticket"
|
|
||||||
else
|
|
||||||
log_error "Schema TypeScript manque photo_ticket"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
# 8. Résumé final
|
|
||||||
echo ""
|
|
||||||
echo "=================================================="
|
|
||||||
log_success "🎉 Validation terminée avec succès!"
|
|
||||||
echo ""
|
|
||||||
log_info "Statut du déploiement:"
|
|
||||||
log_success "✅ Base de données: Prête (avec support photo_ticket)"
|
|
||||||
log_success "✅ Application: Prête (capture photo complète)"
|
|
||||||
log_success "✅ Docker: Configuré pour la production"
|
|
||||||
log_success "✅ Scripts: Exécutables et validés"
|
|
||||||
log_success "✅ Sécurité: Configuration recommandée"
|
|
||||||
echo ""
|
|
||||||
log_info "🚀 RegisFlow est prêt pour la mise en production!"
|
|
||||||
log_info "💡 Utilisez 'docker-compose up -d' pour déployer"
|
|
||||||
log_info "🔐 Credentials par défaut: admin / admin123"
|
|
||||||
log_warning "⚠️ Changez le mot de passe admin après le premier déploiement"
|
|
||||||
echo ""
|
|
||||||