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

9.5 KiB

Instalare ERP/CRM DiDi de la 0

Ghid complet pentru a porni stack-ul ERPNext + DiDi custom de la o masina goala.

Prerequisite

Software pe host

docker --version            # >= 24.0
docker compose version      # >= v2

Toata logica de setup ruleaza IN containerul ERPNext prin bench execute pe functiile din app-ul didi_custom — nu e nevoie de Python pe host.

Resurse

  • 4 GB RAM disponibili
  • 10 GB spatiu disc
  • Port 8080 liber (sau schimba ERPNEXT_PORT)

Retea Docker

ERPNext-ul ruleaza pe reteaua didi-network (impartita cu website-ul). Creeaz-o:

docker network create didi-network 2>/dev/null || true

Build automat (recomandat)

Ruleaza:

cd ~/erp_crm
bash build-from-zero.sh

Scriptul face urmatoarele (~5 min):

  1. Verifica docker network si .env
  2. Porneste containerele (docker compose up -d)
  3. Asteapta MariaDB sa fie healthy
  4. Configureaza Redis in common_site_config.json
  5. Creeaza site-ul didi-erp cu ERPNext instalat
  6. Instaleaza app-ul didi_custom
  7. Creeaza Company TOP CLOSSERS SRL + plan de conturi RO + An Fiscal curent
  8. Ruleaza setup-ul complet din didi_custom prin bench execute (doctypes, campuri custom, CMS, items DIDI + user API, print format, email, workspace + scurtaturi)
  9. Build assets (bench build)
  10. Verifica accesul HTTP

Build manual (pas cu pas)

Daca preferi sa rulezi fiecare pas individual:

Pas 1. Containere

cd ~/erp_crm
docker compose up -d

Asteapta ~30 secunde pana MariaDB e healthy:

docker compose ps
# Toate trebuie sa fie Up; mariadb cu (healthy)

Pas 2. Configurare Redis

docker exec didi-erpnext bash -c '
cd /home/frappe/frappe-bench && 
bench set-config -g redis_cache "redis://redis-cache:6379" && 
bench set-config -g redis_queue "redis://redis-queue:6379" && 
bench set-config -g redis_socketio "redis://redis-queue:6379"
'

Pas 3. Creare site + instalare ERPNext

docker exec didi-erpnext bash -c '
cd /home/frappe/frappe-bench && 
bench new-site didi-erp \
  --mariadb-root-password <parola-root-db> \
  --admin-password <parola-admin> \
  --db-host mariadb \
  --install-app erpnext
'

Dureaza ~3 minute.

Pas 4. Fix MariaDB user pentru orice host

Userul DB creat de Frappe e restrictionat la host-ul curent. Pentru ca containerele cu workers/scheduler sa se conecteze, schimba la wildcard:

DB_NAME=$(docker exec didi-erpnext python3 -c "
import json
with open('/home/frappe/frappe-bench/sites/didi-erp/site_config.json') as f:
    print(json.load(f)['db_name'])
")
DB_PWD=$(docker exec didi-erpnext python3 -c "
import json
with open('/home/frappe/frappe-bench/sites/didi-erp/site_config.json') as f:
    print(json.load(f)['db_password'])
")

docker exec didi-mariadb mariadb -uroot -p<parola-root-db> -e "
DROP USER IF EXISTS '$DB_NAME'@'%';
CREATE USER '$DB_NAME'@'%' IDENTIFIED BY '$DB_PWD';
GRANT ALL PRIVILEGES ON \`$DB_NAME\`.* TO '$DB_NAME'@'%';
FLUSH PRIVILEGES;
"

Pas 5. Instalare didi_custom

docker exec didi-erpnext bash -c '
cd /home/frappe/frappe-bench && 
printf "frappe\nerpnext\ndidi_custom\n" > sites/apps.txt &&
env/bin/pip install -e apps/didi_custom &&
bench --site didi-erp install-app didi_custom
'

Pas 6. Patch ERPNext (portal_users compatibility)

Frappe v15 are un bug minor cu campul portal_users pe Customer (referinta la modul lipsa). Patch:

docker exec didi-erpnext sed -i \
  's|for portal_user in self.portal_users:|for portal_user in (getattr(self, "portal_users", None) or []):|' \
  /home/frappe/frappe-bench/apps/erpnext/erpnext/selling/doctype/customer/customer.py

Pas 7. Companie + plan de conturi Romania + An Fiscal

⚠️ NU rula logica frappe cu python3 pe host sau cu python-ul de sistem din container — esueaza tacut (frappe e instalat doar in venv-ul bench). Foloseste bench --site didi-erp execute <modul.functie>.

BE='docker exec didi-erpnext bash -c'

# Warehouse Type "Transit" — cerut la crearea companiei, lipseste in instalarea curata
$BE 'cd /home/frappe/frappe-bench && bench --site didi-erp execute frappe.client.insert \
  --kwargs "{\"doc\":{\"doctype\":\"Warehouse Type\",\"name\":\"Transit\"}}"' || true

# Company TOP CLOSSERS SRL (cu patch-uri country fixtures incluse in modul)
$BE 'cd /home/frappe/frappe-bench && bench --site didi-erp execute didi_custom.make_company_ro3.execute'

# Plan de conturi RO complet (447 conturi: TVA 4426/4427/4423/4424, venituri 704/707,
# default-uri companie, template TVA 21%)
$BE 'cd /home/frappe/frappe-bench && bench --site didi-erp execute didi_custom.setup_ro_coa.execute'

# An Fiscal curent — lipseste complet dupa instalarea curata; facturile pica fara el
YEAR=$(date +%Y)
$BE "cd /home/frappe/frappe-bench && bench --site didi-erp execute frappe.client.insert \
  --kwargs '{\"doc\":{\"doctype\":\"Fiscal Year\",\"year\":\"$YEAR\",\"year_start_date\":\"$YEAR-01-01\",\"year_end_date\":\"$YEAR-12-31\"}}'"

# Price list implicit in RON
$BE 'cd /home/frappe/frappe-bench && bench --site didi-erp execute frappe.client.set_value \
  --kwargs "{\"doctype\":\"Price List\",\"name\":\"Standard Selling\",\"fieldname\":\"currency\",\"value\":\"RON\"}"'

Pas 8. Doctypes custom, campuri si continut CMS

for fn in didi_custom.setup_doctypes.execute \
          didi_custom.integrations.migrations.setup_custom_fields.execute \
          didi_custom.fix_sa.execute \
          didi_custom.populate_content.execute; do
  docker exec didi-erpnext bash -c "cd /home/frappe/frappe-bench && bench --site didi-erp execute $fn"
done

Creeaza: doctype-urile Service Agreement / Payment Log / Website Content, campurile custom pe Customer / Sales Invoice / Lead (didi_user_id, iam_role, active_plan, sales_invoice „Factura asociata" pe Service Agreement etc.) si continutul CMS.

Pas 9. Integrare website, print format, email, workspace

for fn in didi_custom.setup_website_integration.execute \
          didi_custom.setup_phase2_final.setup_print_format \
          didi_custom.setup_website_integration.fix_print_format \
          didi_custom.setup_email.execute \
          didi_custom.setup_workspaces.execute \
          didi_custom.setup_shortcuts.execute; do
  docker exec didi-erpnext bash -c "cd /home/frappe/frappe-bench && bench --site didi-erp execute $fn"
done
  • setup_website_integration.execute creeaza items DIDI, rolul „Website Integration" (cu toate permisiunile read necesare validarii facturilor) si userul API website_api@didi-erp.localnoteaza api_key/api_secret afisate, intra in .env.production-ul website-ului.
  • fix_print_format repara print formatul „DiDi Invoice" si seteaza host_name (altfel wkhtmltopdf da HostNotFoundError la logo).
  • setup_email.execute configureaza contul SMTP „DiDi Outgoing" (Mailpit in test; in productie se schimba doar host/port/credentiale in Email Account).

Pas 10. Scripturile legacy (scripts/setup/) — NU se mai folosesc

Directorul scripts/setup/ contine prima generatie de scripturi (rulate pe host). Sunt pastrate doar ca referinta istorica — totul a fost mutat in module didi_custom rulabile cu bench execute (pasii 7-9 de mai sus).

Pas 11. Build assets + restart

docker exec didi-erpnext bash -c 'cd /home/frappe/frappe-bench && bench build --force'
docker restart didi-erpnext
sleep 8
curl -s -o /dev/null -w "ERPNext: %{http_code}\n" http://localhost:8080

Verificare instalare

Daca totul a mers, deschide http://localhost:8080:

  • Login: Administrator / admin
  • Sidebar trebuie sa contina: Home, Facturi, Clienti, CRM, Servicii, Plati, Contabilitate, Financial Reports, Website CMS
  • Pagina /app/customer arata Customer-ul Test User (daca ai rulat seed)

Curl rapid de verificare:

# Login + verifica company
curl -s -c /tmp/c -X POST http://localhost:8080/api/method/login \
  -d 'usr=Administrator&pwd=admin' && echo

curl -s -b /tmp/c http://localhost:8080/api/resource/Company | python3 -m json.tool

Date de test (seed)

Pentru smoke testing dupa instalare:

bash seed-data.sh

Creeaza:

  • 1 Customer (Test User)
  • 3 Sales Invoices submitted + paid
  • 1 Payment Log (Stripe simulat)
  • 1 Service Agreement

Probleme frecvente

"Module Selling not found"

installed_apps global value nu contine erpnext. 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 restart didi-erpnext

"wkhtmltopdf reported an error: HostNotFoundError"

host_name lipseste in Website Settings. Fix:

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 restart didi-erpnext

"Access denied for user '_xxxx'@'host'"

User DB are host limitat. Vezi Pas 4 mai sus pentru fix.

Site ramane la 500 pe /app/home

setup_complete e 0 si lipsesc accounts. Treci prin Setup Wizard manual din browser, SAU re-ruleaza Pasul 7 + 8.

Reset complet

Pentru a reseta totul si a porni de la 0:

cd ~/erp_crm
docker compose down -v       # -v sterge volumele!
docker network rm didi-network 2>/dev/null
docker network create didi-network
bash build-from-zero.sh

ATENTIE: down -v sterge IREVERSIBIL toate datele din MariaDB. Faci backup intai daca ai date importante.