Gitead 5ceecbeb7f feat: improve CCA preauth cell filling, implants category, preauth no recording
- Selenium: bulletproof Wait→Click→Clear→Type→Verify for tooth, billed amt cells
- Selenium: fix billed amt to click td[23] (correct column) to trigger edit mode
- Selenium: skip tentative date (auto-filled by page after tooth entry)
- Frontend: add Implants category with Implant/Abut/Crown, Fixture, Abutment, Crown buttons (D6010/D6057/D6058)
- Frontend: pdf-preview-modal renders PNG screenshots as <img> instead of PDF iframe
- Backend: CCA preauth route creates claim record if none exists
- Backend: CCA preauth processor saves authNumber into claimNumber column after submission

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-23 22:01:52 -04:00
2026-04-04 22:13:55 -04:00
2026-04-04 22:13:55 -04:00

Dental Manager - Starter

A monorepo setup to manage both Backend and Frontend of the Dental Manager application.

🖥️ Setup Guide (Fresh Machine)

Follow these steps in order after cloning the repository.

Step 1 — Clone the repository

git clone <your-repo-url>
cd DentalManagementMHAprilgg

Step 2 — Install Node.js

Required to run the Backend and Frontend.

curl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash -
sudo apt-get install -y nodejs

# Verify
node -v   # should print v20.x.x
npm -v

Step 3 — Install Python

Required to run the Selenium and OCR services.

sudo apt-get install -y python3 python3-pip python3-venv

# Verify
python3 --version   # should print 3.10 or higher

Step 4 — Install Chrome

Required for the Selenium service to control a browser.

wget -q -O - https://dl.google.com/linux/linux_signing_key.pub | sudo apt-key add -
echo "deb [arch=amd64] http://dl.google.com/linux/chrome/deb/ stable main" | sudo tee /etc/apt/sources.list.d/google-chrome.list
sudo apt-get update
sudo apt-get install -y google-chrome-stable

# Verify
google-chrome --version

The webdriver-manager package (included in requirements.txt) automatically downloads the matching ChromeDriver — no manual driver setup needed.

Step 5 — Install PostgreSQL

Primary database for the application.

sudo apt-get install -y postgresql postgresql-contrib
sudo systemctl enable postgresql
sudo systemctl start postgresql

# Create the database the app uses
sudo -u postgres psql -c "CREATE DATABASE dentalapp OWNER postgres;"

# Set the postgres user password to match packages/db/.env
sudo -u postgres psql -c "ALTER USER postgres WITH PASSWORD 'mypassword';"

Enable password authentication over TCP

By default Debian uses scram-sha-256 or peer auth for local connections, which blocks password login. Switch to md5:

sudo sed -i 's/scram-sha-256/md5/g' /etc/postgresql/*/main/pg_hba.conf
sudo systemctl restart postgresql

Verify

psql -U postgres -d dentalapp -h 127.0.0.1 -W
# Enter: mypassword
# You should see:  dentalapp=#

The DATABASE_URL in packages/db/.env is already set to:

DATABASE_URL="postgresql://postgres:mypassword@localhost:5432/dentalapp"

Step 6 — Install Redis

Used as the job queue for Selenium and OCR background tasks.

sudo apt-get install -y redis-server
sudo systemctl enable redis-server
sudo systemctl start redis-server

# Verify
redis-cli ping   # should print: PONG

Step 7 — Install Node.js dependencies

npm install

Step 8 — Install Python dependencies

Python dependencies are installed automatically by npm install (Step 7) via each service's postinstall script. Each service creates its own .venv virtual environment — no manual pip commands needed.

This approach is required on Debian 13+ where system-wide pip installs are blocked (PEP 668).

Step 9 — Set up environment variables

Copy the .env.example files and fill in the required values.

npm run setup:env

Step 10 — Set up the database

# Run migrations
npm run db:migrate

# Generate Prisma types
npm run db:generate

# Insert seed data
npm run db:seed

Step 11 — Configure nginx

The repo includes nginx.conf in the project root. Install it as the active site config:

sudo cp nginx.conf /etc/nginx/sites-available/dental-app
sudo ln -sf /etc/nginx/sites-available/dental-app /etc/nginx/sites-enabled/dental-app
sudo nginx -t && sudo systemctl reload nginx

Important: The /api/ location block must include proxy_set_header Authorization $http_authorization; Without it, nginx strips the Authorization header and the backend returns "Access denied. No token provided."

Step 12 — Run the app

Open two terminals:

Terminal 1 — Backend + Frontend:

npm run dev

On first boot the server automatically seeds all AI chat templates, SMS templates, and greeting messages for every user — no manual configuration needed.

Terminal 2 — Selenium service:

cd apps/SeleniumService
.venv/bin/python3 agent.py

📖 Developer Documentation


This is a Turborepo. What's inside?

Apps and Packages

  • apps/Backend — Express.js API server
  • apps/Frontend — React + Vite frontend
  • apps/SeleniumService — Python FastAPI service for browser automation (insurance eligibility, claims)
  • apps/PaymentOCRService — Python service for payment OCR extraction
  • @repo/eslint-config — shared ESLint configuration
  • @repo/typescript-config — shared tsconfig.jsons

Each package/app is 100% TypeScript (except the Python services).

Utilities


Cloudflare Tunnel Setup (Remote Access per Office)

This connects each office's local app to a public subdomain via a Cloudflare Tunnel — no port forwarding needed, local network access is unchanged.

How it works:

  • Local network: other office PCs reach the app directly at http://<machine-ip>:3000
  • Internet: anyone reaches the app via https://<subdomain>.mydentalofficemanagement.com
  • Both paths hit the same app simultaneously with no conflict

Step 1 — Add domain to Cloudflare (done once for all offices)

Skip this step if the domain is already on Cloudflare.

  1. Go to dash.cloudflare.comAdd a site → enter mydentalofficemanagement.com (free plan)
  2. Cloudflare scans existing DNS records — review and keep them
  3. Cloudflare gives you 2 nameservers (e.g. holly.ns.cloudflare.com, amir.ns.cloudflare.com)
  4. Log into Ionos → replace the domain's nameservers with Cloudflare's two
  5. Wait 1030 min → Cloudflare emails you when active
  6. DNSSEC: if not purchased on Ionos, it was never enabled — nothing to turn off

Step 2 — Install cloudflared on the office PC

Run this in a terminal on the office machine:

curl -L https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-amd64.deb -o cloudflared.deb
sudo dpkg -i cloudflared.deb
cloudflared --version

Step 3 — Authenticate with Cloudflare

cloudflared tunnel login

A browser window opens → click mydentalofficemanagement.com → terminal shows success and saves a certificate to ~/.cloudflared/cert.pem.

Step 4 — Create a tunnel for this office

Use a unique tunnel name per office:

cloudflared tunnel create <office-tunnel-name>
# Example: cloudflared tunnel create summit-dental-app

Note the tunnel ID (UUID) printed — you need it in Step 5.

Step 5 — Create the config file

sudo mkdir -p /etc/cloudflared
sudo nano /etc/cloudflared/config.yml

Paste (replace tunnel ID, credentials path, and subdomain for this office):

tunnel: <tunnel-ID>
credentials-file: /home/ee/.cloudflared/<tunnel-ID>.json

ingress:
  - hostname: <subdomain>.mydentalofficemanagement.com
    service: http://localhost:3000
  - service: http_status:404

Save: Ctrl+O → Enter → Ctrl+X.

Step 6 — Route DNS for this office's subdomain

cloudflared tunnel route dns <office-tunnel-name> <subdomain>.mydentalofficemanagement.com

Step 7 — Install as a system service (auto-starts on boot)

sudo cloudflared service install
sudo systemctl enable cloudflared
sudo systemctl start cloudflared
sudo systemctl status cloudflared

Step 8 — Allow the subdomain in Vite

In apps/Frontend/vite.config.js, add the subdomain to server.allowedHosts so Vite does not block external requests.

Step 9 — Allow the subdomain in backend CORS

In apps/Backend, add the subdomain URL to the allowed CORS origins so login and API calls work from the public URL.


Example — Adding Summit Dental Care

Office subdomain: summitdentalcare.mydentalofficemanagement.com

Step 1: Already done (domain is on Cloudflare).

Step 2: Install cloudflared on Summit Dental's PC.

Step 3: Run cloudflared tunnel login on Summit Dental's PC.

Step 4:

cloudflared tunnel create summit-dental-app
# Example output: Created tunnel summit-dental-app with id a1b2c3d4-...

Step 5 — /etc/cloudflared/config.yml:

tunnel: a1b2c3d4-xxxx-xxxx-xxxx-xxxxxxxxxxxx
credentials-file: /home/ee/.cloudflared/a1b2c3d4-xxxx-xxxx-xxxx-xxxxxxxxxxxx.json

ingress:
  - hostname: summitdentalcare.mydentalofficemanagement.com
    service: http://localhost:3000
  - service: http_status:404

Step 6:

cloudflared tunnel route dns summit-dental-app summitdentalcare.mydentalofficemanagement.com

Step 7:

sudo cloudflared service install
sudo systemctl enable cloudflared
sudo systemctl start cloudflared

Step 8: Add summitdentalcare.mydentalofficemanagement.com to allowedHosts in vite.config.js.

Step 9: Add https://summitdentalcare.mydentalofficemanagement.com to backend CORS allowed origins.


Multi-office overview

Each office runs its own cloudflared tunnel on its own PC. Ports never conflict because each PC is a separate machine.

Office Local access Public access Tunnel name
Community Dentists of Lowell http://192.168.1.236:3000 https://communitydentistsoflowell.mydentalofficemanagement.com dental-app
Summit Dental Care http://<its-ip>:3000 https://summitdentalcare.mydentalofficemanagement.com summit-dental-app
Next office http://<its-ip>:3000 https://<subdomain>.mydentalofficemanagement.com <office>-app
Description
No description provided
Readme 157 MiB
Languages
JavaScript 58.5%
TypeScript 37.3%
Python 4.2%