# راهنمای پنل پرونده ایران هلث

این بسته نسخه اول پنل است. کارکنان پرونده می‌سازند و مرحله را جلو می‌برند. بیمار فقط روند پرونده‌های خودش را می‌بیند. زبان صفحه کارکنان فارسی و راست‌چین است. زبان صفحه بیمار همان زبان پرونده است: فارسی، انگلیسی یا عربی. فارسی و عربی راست‌چین‌اند و انگلیسی چپ‌چین.

آدرس عمومی این پنل `panel.iranhealthagency.com` است.

پیامک واقعی در این نسخه خاموش است، تا وقتی خودتان شرکت پیامک را انتخاب کنید و سه متغیر بخش پیامک را پر کنید. تا آن لحظه هیچ درخواستی به بیرون فرستاده نمی‌شود.

## ۱. پیش‌نیاز

- Node.js نسخه ۲۰ یا جدیدتر، همراه با npm. با `node -v` و `npm -v` چک کنید.
- روی لینوکس، ابزار ساخت برای افزونه SQLite: بسته `build-essential` و `python3`.
- برای استقرار روی سرور: nginx، certbot، و یک رکورد DNS از نوع A که `panel.iranhealthagency.com` را به IP سرور برساند.

اگر Node نصب نیست، روی اوبونتو این مسیر را بروید:

```bash
sudo apt update
sudo apt install -y build-essential python3 nginx certbot python3-certbot-nginx curl
curl -fsSL https://deb.nodesource.com/setup_22.x | sudo -E bash -
sudo apt install -y nodejs
node -v
npm -v
```

## ۲. نصب

فایل zip را در یک پوشه خالی باز کنید، بعد وابستگی‌ها را نصب کنید:

```bash
unzip iran-health-panel.zip -d iran-health-panel
cd iran-health-panel
npm install
```

`node_modules` داخل zip نیست و باید همین‌جا ساخته شود.

## ۳. فایل env

```bash
cp .env.example .env
```

فایل `.env` را باز کنید و این مقدارها را بگذارید.

`SESSION_SECRET` یک رشته تصادفی با حداقل ۱۶ نویسه است. در اجرای واقعی (`npm start`) اگر این مقدار نباشد پنل بالا نمی‌آید. برای آزمایش محلی با `npm run dev` می‌توانید موقتاً خالی بگذارید، ولی روی سرور حتماً پر شود.

`APP_BASE_URL` آدرس عمومی پنل است. لینک بیمار با همین ساخته می‌شود. محلی: `http://localhost:3000`. سرور: `https://panel.iranhealthagency.com`. این را پیش از ساخت پرونده واقعی درست کنید.

`SQLITE_PATH` جای فایل پایگاه است. محلی: `./data/panel.sqlite`. سرور: `/var/lib/iran-health-panel/panel.sqlite`.

`PATIENT_CODE_TTL_MINUTES` مدت اعتبار کد ورود بیمار به دقیقه است. پیش‌فرض ۱۰ است. کد کوتاه‌عمر است و خود لینک، بدون کد، پرونده را باز نمی‌کند.

`SMS_API_URL` و `SMS_API_KEY` و `SMS_FROM` را خالی بگذارید. معنی این سه مقدار در بخش پیامک آمده است.

`ADMIN_INITIAL_USERNAME` و `ADMIN_INITIAL_PASSWORD` را خالی بگذارید، مگر بخواهید همان بار اول به‌جای حساب پیش‌فرض، نام و رمز دیگری ساخته شود. این دو فقط وقتی اثر دارند که هنوز هیچ کاربر کارمندی در پایگاه نباشد.

## ۴. ساخت اولین مدیر

حساب اول را خود پنل می‌سازد، همان بار اول که برنامه به پایگاه خالی وصل می‌شود.

اگر دو متغیر مدیر در `.env` خالی باشد، حساب این است:

- نام کاربری: `admin`
- گذرواژه: `IranHealth-1405`

بعد از اولین ورود، از منوی «گذرواژه» رمز را عوض کنید. تا وقتی رمز همان مقدار اولیه باشد، بالای صفحات کارکنان یک هشدار می‌ماند.

برای ساختن کاربر بعدی، یک بار برنامه را اجرا کرده باشید، بعد:

```bash
npm run create-staff -- nama  "رمز-حداقل-۸-نویسه"
```

نام کاربری فقط حروف انگلیسی، عدد، نقطه، خط تیره و زیرخط است، بین ۳ تا ۴۰ نویسه.

## ۵. اجرای محلی

```bash
npm run dev
```

مرورگر را باز کنید: `http://localhost:3000`

با `admin` و `IranHealth-1405` وارد شوید. بعد از ورود، فهرست پرونده‌ها باز می‌شود.

برای بستن برنامه، در همان ترمینال `Ctrl+C` بزنید.

`npm start` فقط بعد از `npm run build` است و برنامه را روی `127.0.0.1` و پورت `3000` نگه می‌دارد. برای کار روزمره روی رایانه خودتان `npm run dev` کافی است.

## ۶. ساخت پرونده

1. «پرونده جدید» را باز کنید.
2. نام، نام خانوادگی، موبایل، زبان پرونده، کشور و شهر را بنویسید. شکل `0912...` و `+98912...` یکی حساب می‌شود.
3. یک تخصص را از فهرست انتخاب کنید. هر پرونده یک تخصص دارد. اگر یک سفر دو تخصص دارد، دو پرونده با همان موبایل بسازید.
4. خدمت درخواستی را تیک بزنید. خدمت دریافت‌شده را وقتی انجام شد تیک بزنید.
5. در صورت نیاز نام مرکز درمانی، توضیح کوتاه، تاریخ ورود به ایران، تاریخ مراجعه به شرکت، تاریخ مراجعه به مرکز درمانی، تاریخ خروج، و تاریخ‌های دیگر مسیر را بنویسید. عنوان تاریخ‌های دیگر را خودتان می‌نویسید، مثل ویزا، پرواز، مشاوره، زمان عمل، ترخیص.
6. یادداشت داخلی را فقط کارکنان می‌بینند.
7. «ذخیره پرونده» را بزنید.

با اولین ذخیره، شماره پرونده ساخته می‌شود، مرحله «پرونده تشکیل شد» ثبت می‌شود، و متن پیامک روی همان پرونده می‌ماند. ویرایش بعدی پرونده پیامک تازه نمی‌سازد.

## ۷. باز کردن لینک بیمار

1. در صفحه همان پرونده، لینک بیمار را کپی کنید.
2. لینک را در مرورگر باز کنید. صفحه فقط فرم ورود را نشان می‌دهد و مشخصات پرونده را نشان نمی‌دهد.
3. بیمار شماره موبایل پرونده و کد یک‌بارمصرف را وارد می‌کند.
4. چون پیامک خاموش است، کد را از همان صفحه کارکنان بردارید. کنار کد نوشته شده که پیامک واقعی خاموش است.
5. کد به‌طور پیش‌فرض ۱۰ دقیقه اعتبار دارد. اگر تمام شد یا استفاده شد، «صدور کد تازه» را بزنید. کد تازه پیامک نمی‌شود و دوباره روی صفحه کارکنان دیده می‌شود.
6. بعد از ورود، بیمار خلاصه پرونده، تاریخ‌ها، و خط زمان را می‌بیند. مرحله‌های گذشته زمان دارند، مرحله فعلی مشخص است، و مرحله‌های نرسیده بدون زمان دیده می‌شوند.
7. اگر چند پرونده با یک موبایل باشد، بعد از ورود فقط همان پرونده‌ها را می‌بیند و می‌تواند بین آن‌ها جابه‌جا شود.
8. بیمار از پایین صفحه زبان را عوض می‌کند. انتخاب روی پرونده ذخیره می‌شود. جمله‌های پیش‌فرض مرحله با زبان جدید عوض می‌شوند. اگر کارکنان جمله را دستی عوض کرده باشند، همان متن دستی می‌ماند.

ثبت مرحله جدید از صفحه کارکنان است: مرحله، زمان تهران، و جمله بیمار. اگر زمان را خالی بگذارید، زمان همان لحظه ثبت می‌شود. این کار پیامک نمی‌فرستد.

## ۸. پیامک واقعی خاموش است

تا وقتی هر سه مقدار `SMS_API_URL` و `SMS_API_KEY` و `SMS_FROM` با هم پر نشده باشند، پنل به هیچ شرکت پیامکی وصل نمی‌شود و درخواستی نمی‌فرستد. فروشنده‌ای انتخاب نشده است.

در این حالت:

- متن پیام، به زبان پرونده، روی پرونده ذخیره می‌شود.
- وضعیت پیامک «ارسال‌نشده» می‌ماند.
- کد ورود بیمار روی صفحه کارکنان نشان داده می‌شود تا پنل را آزمایش کنید.

متن‌ها این‌ها هستند:

- فارسی: پرونده شما در ایران هلث ساخته شد. روند خدمت را اینجا ببینید: {لینک}
- انگلیسی: Your Iran Health file is open. Follow your care here: {link}
- عربی: تم فتح ملفك لدى إيران هلث. تابع مسار خدمتك من هنا: {الرابط}

پیامک فقط هنگام اولین ذخیره پرونده ساخته می‌شود. تغییر مرحله، ویرایش پرونده، و صدور کد تازه پیامک نمی‌فرستند.

وقتی شرکت پیامک را خودتان انتخاب کردید، در `.env` این سه مقدار را بگذارید و برنامه را یک بار ری‌استارت کنید. پنل به `SMS_API_URL` یک POST با این بدنه می‌فرستد:

```json
{"to":"شماره بیمار","from":"مقدار SMS_FROM","text":"متن پیام"}
```

هدر درخواست: `Authorization: Bearer` و بعد مقدار `SMS_API_KEY`. اگر پاسخ موفق نباشد، وضعیت پرونده «ناموفق» می‌شود و کد روی صفحه کارکنان دیده می‌شود تا بیمار بدون پیامک هم بتواند وارد شود. پرونده‌هایی که قبلاً ساخته شده‌اند دوباره پیامک نمی‌شوند.

## ۹. استقرار روی panel.iranhealthagency.com

این یک مسیر کامل است: فرآیند Node پشت nginx. پورت برنامه فقط روی خود سرور باز است و nginx آن را به اینترنت می‌دهد.

### نام و پایگاه

```bash
sudo useradd --system --create-home --home-dir /home/iranhealth --shell /usr/sbin/nologin iranhealth
sudo mkdir -p /opt/iran-health-panel /var/lib/iran-health-panel /var/backups/iran-health
sudo chown -R iranhealth:iranhealth /opt/iran-health-panel /var/lib/iran-health-panel /var/backups/iran-health
```

فایل پایگاه اینجاست:

`/var/lib/iran-health-panel/panel.sqlite`

فایل‌های `panel.sqlite-wal` و `panel.sqlite-shm` هم کنار همین فایل ساخته می‌شوند. این پوشه را داخل پوشه برنامه نگذارید، تا عوض کردن کد، پایگاه را پاک نکند. کاربر `iranhealth` باید روی این پوشه حق نوشتن داشته باشد.

### کد و env

zip را در `/opt/iran-health-panel` باز کنید، مالک را درست کنید، بعد با همان کاربر نصب و ساخت را انجام دهید:

```bash
sudo -u iranhealth -H bash
cd /opt/iran-health-panel
cp .env.example .env
```

در `.env` سرور حداقل این‌ها را بگذارید:

```bash
SESSION_SECRET=یک-رشته-طولانی-و-تصادفی
APP_BASE_URL=https://panel.iranhealthagency.com
SQLITE_PATH=/var/lib/iran-health-panel/panel.sqlite
PATIENT_CODE_TTL_MINUTES=10
SMS_API_URL=
SMS_API_KEY=
SMS_FROM=
```

بعد:

```bash
npm install
npm run build
exit
sudo chmod 600 /opt/iran-health-panel/.env
sudo chown iranhealth:iranhealth /opt/iran-health-panel/.env
```

### فرآیند Node

فایل `/etc/systemd/system/iran-health-panel.service`:

```ini
[Unit]
Description=Iran Health panel
After=network.target

[Service]
Type=simple
User=iranhealth
Group=iranhealth
WorkingDirectory=/opt/iran-health-panel
EnvironmentFile=/opt/iran-health-panel/.env
ExecStart=/usr/bin/npm run start
Restart=on-failure
RestartSec=5

[Install]
WantedBy=multi-user.target
```

اگر `command -v npm` چیزی غیر از `/usr/bin/npm` نشان داد، همان مسیر را در `ExecStart` بگذارید. `npm start` برنامه را به `127.0.0.1:3000` وصل می‌کند.

```bash
sudo systemctl daemon-reload
sudo systemctl enable --now iran-health-panel
sudo systemctl status iran-health-panel
```

اولین بالا آمدن، حساب `admin` را می‌سازد. رمز را همان روز عوض کنید.

### nginx

اول رکورد A دامنه `panel.iranhealthagency.com` باید به IP همین سرور رسیده باشد.

فایل `/etc/nginx/sites-available/iran-health-panel`:

```nginx
server {
    listen 80;
    server_name panel.iranhealthagency.com;

    location / {
        proxy_pass http://127.0.0.1:3000;
        proxy_http_version 1.1;
        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;
    }
}
```

```bash
sudo ln -s /etc/nginx/sites-available/iran-health-panel /etc/nginx/sites-enabled/iran-health-panel
sudo nginx -t
sudo systemctl reload nginx
sudo certbot --nginx -d panel.iranhealthagency.com
```

بعد از گواهی، سایت روی `https://panel.iranhealthagency.com` باز می‌شود. چون `APP_BASE_URL` با `https` شروع می‌شود، کوکی ورود فقط روی HTTPS فرستاده می‌شود.

## ۱۰. پشتیبان

فایل مهم همان `SQLITE_PATH` است. این دستور، در حالی که برنامه روشن است، یک کپی سالم می‌سازد:

```bash
sudo -u iranhealth -H bash -lc 'cd /opt/iran-health-panel && npm run backup -- /var/backups/iran-health/panel-$(date +%F).sqlite'
```

برای پشتیبان شبانه، در cron کاربر `iranhealth`:

```bash
0 3 * * * cd /opt/iran-health-panel && /usr/bin/npm run backup -- /var/backups/iran-health/panel-$(date +\%F).sqlite
```

اگر خواستید خود فایل را کپی کنید، اول سرویس را متوقف کنید، بعد هر سه فایل sqlite و wal و shm را بردارید و دوباره سرویس را روشن کنید:

```bash
sudo systemctl stop iran-health-panel
sudo cp -a /var/lib/iran-health-panel/panel.sqlite /var/backups/iran-health/panel-manual.sqlite
sudo cp -a /var/lib/iran-health-panel/panel.sqlite-wal /var/backups/iran-health/ 2>/dev/null || true
sudo cp -a /var/lib/iran-health-panel/panel.sqlite-shm /var/backups/iran-health/ 2>/dev/null || true
sudo systemctl start iran-health-panel
```

## ۱۱. به‌روزرسانی کد

پوشه `/var/lib/iran-health-panel` و فایل `.env` را دست نزنید. کد جدید را در `/opt/iran-health-panel` بریزید، بعد:

```bash
sudo systemctl stop iran-health-panel
sudo -u iranhealth -H bash -lc 'cd /opt/iran-health-panel && npm install && npm run build'
sudo systemctl start iran-health-panel
```
