didi-website-erp-crm/erp_crm/OPERATIONS.md

7.7 KiB

Operare ERP/CRM DiDi

Ghid pentru administrare zilnica: backup, restart, log-uri, troubleshooting.

Comenzi uzuale

Status containere

docker compose ps
docker stats --no-stream  # CPU/RAM realtime

Restart serviciu

# 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

# 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)

# 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):

# Backup zilnic la 02:00, retentie 14 zile
0 2 * * * ~/erp_crm/bin/backup.sh

Continut bin/backup.sh (creeaza-l):

#!/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<parola-root-db> --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:

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:

docker cp didi-erpnext:/home/frappe/frappe-bench/sites/didi-erp/private/backups/ ./backups-$(date +%Y%m%d)

Restore din backup

# 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 <parola-root-db>
'

Update / upgrade

Update didi_custom (app-ul nostru)

Dupa ce modifici cod in didi_custom/:

docker exec didi-erpnext bash -c '
cd /home/frappe/frappe-bench && 
bench --site didi-erp migrate
'

Daca ai modificat doctype:

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

# HTTP
curl -s -o /dev/null -w "%{http_code}\n" http://localhost:8080

# DB
docker exec didi-mariadb mariadb -uroot -p<parola-root-db> -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

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

# 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

# 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:

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<parola-root-db> $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")

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:

UPDATE tabWorkspace SET title='Plati' WHERE name='Plati';

Scenarii de operare

Adaugare user admin nou

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)

# 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:

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.