# Operare ERP/CRM DiDi Ghid pentru administrare zilnica: backup, restart, log-uri, troubleshooting. ## Comenzi uzuale ### Status containere ```bash docker compose ps docker stats --no-stream # CPU/RAM realtime ``` ### Restart serviciu ```bash # Doar ERPNext (cel mai des) docker compose restart erpnext # Toate docker compose restart # Restart cu rebuild image docker compose up -d --build erpnext ``` ### Log-uri ```bash # Container ERPNext (gunicorn + nginx) docker compose logs -f erpnext # Worker job-uri background docker compose logs -f queue-short docker compose logs -f queue-long docker compose logs -f scheduler # Fisier de log Frappe (in container) docker exec didi-erpnext tail -f /home/frappe/frappe-bench/sites/didi-erp/logs/web.log docker exec didi-erpnext tail -f /home/frappe/logs/database.log ``` ### Bench (CLI Frappe) ```bash # Cache + cache static docker exec didi-erpnext bash -c 'cd /home/frappe/frappe-bench && bench --site didi-erp clear-cache' docker exec didi-erpnext bash -c 'cd /home/frappe/frappe-bench && bench --site didi-erp clear-website-cache' # Migrate (dupa update Frappe sau didi_custom) docker exec didi-erpnext bash -c 'cd /home/frappe/frappe-bench && bench --site didi-erp migrate' # Rebuild assets (CSS/JS) docker exec didi-erpnext bash -c 'cd /home/frappe/frappe-bench && bench build --force' # Reset Administrator password docker exec didi-erpnext bash -c 'cd /home/frappe/frappe-bench && bench --site didi-erp set-admin-password admin' # Console Python interactiv docker exec -it didi-erpnext bash -c 'cd /home/frappe/frappe-bench && bench --site didi-erp console' ``` ## Backup ### Backup automat zilnic (recomandare cron) Adauga in crontab (`crontab -e`): ```cron # Backup zilnic la 02:00, retentie 14 zile 0 2 * * * ~/erp_crm/bin/backup.sh ``` Continut `bin/backup.sh` (creeaza-l): ```bash #!/bin/bash set -e DATE=$(date +%Y%m%d_%H%M%S) BACKUP_DIR=/var/backups/didi-erp mkdir -p $BACKUP_DIR # DB dump docker exec didi-mariadb mariadb-dump -uroot -p --all-databases \ | gzip > $BACKUP_DIR/db-$DATE.sql.gz # Files (uploaded attachments) docker run --rm \ -v didi-data-layer_erpnext-sites:/data \ -v $BACKUP_DIR:/backup \ alpine tar czf /backup/sites-$DATE.tar.gz /data # Retention: keep last 14 days find $BACKUP_DIR -mtime +14 -delete echo "Backup OK: $DATE" ``` ### Backup manual (Frappe-managed) ERPNext are propriu mecanism de backup: ```bash docker exec didi-erpnext bash -c ' cd /home/frappe/frappe-bench && bench --site didi-erp backup --with-files ' # Fisierele apar in: sites/didi-erp/private/backups/ ``` Copy local: ```bash docker cp didi-erpnext:/home/frappe/frappe-bench/sites/didi-erp/private/backups/ ./backups-$(date +%Y%m%d) ``` ## Restore din backup ```bash # 1. Copiaza fisierele in container docker cp ./backups-20260525 didi-erpnext:/tmp/restore # 2. Restore docker exec didi-erpnext bash -c ' cd /home/frappe/frappe-bench && bench --site didi-erp restore /tmp/restore/db-XXXXXX.sql.gz \ --with-public-files /tmp/restore/files-XXXXXX.tar \ --with-private-files /tmp/restore/private-files-XXXXXX.tar \ --mariadb-root-password ' ``` ## Update / upgrade ### Update didi_custom (app-ul nostru) Dupa ce modifici cod in `didi_custom/`: ```bash docker exec didi-erpnext bash -c ' cd /home/frappe/frappe-bench && bench --site didi-erp migrate ' ``` Daca ai modificat doctype: ```bash docker exec didi-erpnext bash -c ' cd /home/frappe/frappe-bench && bench --site didi-erp execute "frappe.model.sync.sync_for" --kwargs "{\"app\":\"didi_custom\"}" ' ``` ### Upgrade ERPNext (major version) NU recomandat fara o copie test. Procedura: 1. Backup complet 2. Edit `docker-compose.yml`: `ERPNEXT_VERSION=v16` (cand apare) 3. `docker compose pull` 4. `docker compose up -d` 5. `bench --site didi-erp migrate` 6. Test extensiv ## Monitorizare ### Health checks ```bash # HTTP curl -s -o /dev/null -w "%{http_code}\n" http://localhost:8080 # DB docker exec didi-mariadb mariadb -uroot -p -e "SELECT 1" # Redis docker exec didi-redis-cache redis-cli ping docker exec didi-redis-queue redis-cli ping # Background workers (verifica heartbeat) docker exec didi-redis-queue redis-cli KEYS 'rq:worker:*' ``` ### Email queue ```bash docker exec didi-mariadb mariadb -u_xxx -pxxx didi_db -e " SELECT status, COUNT(*) FROM \`tabEmail Queue\` GROUP BY status; " # Flush manual docker exec didi-erpnext bash -c 'cd /home/frappe/frappe-bench && bench --site didi-erp execute frappe.email.queue.flush' # Trimitere imediata (bypass queue) docker exec didi-erpnext bash -c 'cd /home/frappe/frappe-bench && bench --site didi-erp send-email --send-now' ``` ## Troubleshooting ### Site nu raspunde / 500 ```bash # 1. Log-uri docker compose logs --tail 100 erpnext # 2. Restart curat docker exec didi-redis-cache redis-cli FLUSHALL docker exec didi-redis-queue redis-cli FLUSHALL docker compose restart erpnext # 3. Daca tot nu merge, verifica DB conexiune docker exec didi-erpnext bash -c ' cd /home/frappe/frappe-bench && bench --site didi-erp doctor ' ``` ### Workers nu proceseaza job-uri ```bash # Status workers docker exec didi-redis-queue redis-cli LRANGE "rq:queue:short" 0 -1 | head docker exec didi-redis-queue redis-cli LRANGE "rq:queue:long" 0 -1 | head # Restart workers docker compose restart queue-short queue-long queue-default ``` ### "Module Selling not found" sau alte module standard `installed_apps` din DB e dezsincronizat. Fix: ```bash DB=$(docker exec didi-erpnext cat /home/frappe/frappe-bench/sites/didi-erp/site_config.json | python3 -c "import sys,json; print(json.load(sys.stdin)['db_name'])") docker exec didi-mariadb mariadb -uroot -p $DB -e " UPDATE tabDefaultValue SET defvalue='[\"frappe\",\"erpnext\",\"didi_custom\"]' WHERE defkey='installed_apps'; " docker exec didi-redis-cache redis-cli FLUSHALL docker compose restart erpnext ``` ### PDF nu se genereaza ("HostNotFoundError") ```bash docker exec didi-erpnext bash -c ' cd /home/frappe/frappe-bench && bench --site didi-erp set-config -g host_name "http://didi-erpnext:8080" ' docker compose restart erpnext ``` ### Workspace cu titlu romanesc nu se gaseste URL-urile Frappe sunt slug-ificate. Diacriticele se pierd. Pune titlul fara diacritice in DB: ```sql UPDATE tabWorkspace SET title='Plati' WHERE name='Plati'; ``` ## Scenarii de operare ### Adaugare user admin nou ```bash docker exec didi-erpnext bash -c ' cd /home/frappe/frappe-bench && bench --site didi-erp add-user nume.user@clossers.com \ --first-name Nume \ --last-name User \ --password parolaTemp123 \ --add-system-manager ' ``` ### Schimbare email From-name (SendGrid) ```bash # Update Email Account docker exec didi-erpnext bash -c ' cd /home/frappe/frappe-bench && bench --site didi-erp execute "frappe.db.set_value" --kwargs "{\"doctype\":\"Email Account\", \"docname\":\"DiDi Outgoing\", \"fieldname\":\"email_id\", \"value\":\"office@clossers.com\"}" ' docker compose restart erpnext ``` ### Sterge factura emisa (anulare) ERPNext nu permite delete pe `docstatus=1`. Trebuie cancel + delete: ```bash docker exec didi-erpnext bash -c ' cd /home/frappe/frappe-bench && bench --site didi-erp execute "frappe.client.cancel" --kwargs "{\"doctype\":\"Sales Invoice\", \"name\":\"DIDI-INV-2026-00001\"}" ' ``` Apoi din UI sterge documentul anulat. ## SLA si severitati (conform contract) | Severitate | Definitie | Timp raspuns | Timp rezolvare | |------------|-----------|--------------|----------------| | Critica | Sistemul nu functioneaza / plati nefunctionale | 4 ore | 24 ore | | Majora | Functionalitate importanta afectata | 8 ore | 3 zile lucratoare | | Minora | Probleme cosmetice / minore | 24 ore | 10 zile lucratoare | Canal tichete: office@clossers.com (sau sistem helpdesk dedicat la productie). Program suport: zile lucratoare 09:00 - 18:00.