14
Today's Appointments
↑ 3 more than yesterday
₹42,800
Revenue This Month
↑ 12% vs last month
3
Low Stock Alerts
⚠ Requires attention
₹8,400
Pending Payments
4 invoices outstanding
Today's Schedule
09:00
Priya Mehta
Laser Hair Removal · Dr. Kapoor
10:00
Anjali Singh
Skin Brightening · Dr. Reena
11:30
Neha Patel
Hair PRP · Dr. Kapoor
14:00
Ritika Joshi
Consultation · Dr. Reena
16:00
Sunita Rao
Botox · Dr. Reena
⚠ Low Stock Alerts
Vitamin C Serum
Only 3 units left · Reorder at 5
Only 3 units left · Reorder at 5
Hydroquinone Cream
Only 2 units left · Reorder at 5
Only 2 units left · Reorder at 5
Laser Cooling Gel
4 units left · Reorder at 10
4 units left · Reorder at 10
Pending Payments
| Patient | Amount | Action |
|---|---|---|
| Anjali Singh | ₹2,400 | |
| Neha Patel | ₹3,200 | |
| Sunita Rao | ₹2,800 |
March 2026
Mon
02
Tue
03
Wed
04
Thu
05
Fri
06
Sat
07
Time
Slots
09:00
✓ Priya Mehta — Laser (Dr. Kapoor)
10:00
◷ Anjali Singh — Skin Brightening
11:00
11:30
✓ Neha Patel — PRP (Done)
12:00
13:00
Lunch Break
14:00
◷ Ritika Joshi — Consultation
15:00
⚑ Kavya Nair — Hair Treatment (No-show)
16:00
✓ Sunita Rao — Botox
17:00
18:00
| Customer | Phone | Age / Gender | Blood Type | Active Packages | Last Visit | Action |
|---|---|---|---|---|---|---|
|
PM
Priya Mehta
|
+91 98765 43210 | 28 / Female | O+ | 2 Active | Mar 03, 2026 | |
|
AS
Anjali Singh
|
+91 87654 32109 | 34 / Female | A+ | 1 Active | Feb 28, 2026 | |
|
NP
Neha Patel
|
+91 76543 21098 | 42 / Female | B+ | — | Mar 03, 2026 |
Customers / Priya Mehta
PM
Personal Information
Full NamePriya Mehta
Phone+91 98765 43210
Email[email protected]
Date of Birth15 Apr 1997 (28 yrs)
GenderFemale
Blood TypeO+
AddressBandra, Mumbai 400050
Medical Notes
AllergiesNone known
Skin TypeCombination, Sensitive
Chief ConcernHyperpigmentation, Hair removal
NotesPrefers morning slots. Reacts to fragrance-based products.
Laser Hair Removal — Full Body
8-Session Package · Enrolled: Jan 15, 2026
5 / 8
Sessions done
SESSION TRACKER
1
2
3
4
5
6
7
8
5 sessions completed
3 sessions remaining
Skin Brightening Program
6-Session Package · Enrolled: Feb 10, 2026
2 / 6
1
2
3
4
5
6
| Date | Time | Treatment | Doctor | Status | Actions |
|---|---|---|---|---|---|
| Mar 03, 2026 | 09:00 AM | Laser Hair Removal | Dr. Kapoor | Confirmed | |
| Feb 17, 2026 | 10:00 AM | Laser Session 3 | Dr. Kapoor | Completed | |
| Feb 03, 2026 | 10:00 AM | Laser Session 2 | Dr. Kapoor | Completed |
| Invoice # | Date | Amount | Status | Action |
|---|---|---|---|---|
| INV-2026-0042 | Mar 03 | ₹4,500 | Paid | |
| INV-2026-0031 | Feb 17 | ₹4,500 | Paid | |
| INV-2026-0018 | Feb 03 | ₹2,800 | Pending |
No files uploaded
Upload before/after photos, reports, or consent forms
35
Total Enrollments
28
Active
6
Nearly Done
7
Completed
PM
Priya Mehta
Laser Hair Removal — Full Body Active
⚡ Diode Laser
+ Cooling Therapy
+ SPF Shield Add-on
1
2
3
4
5
6
7
8
5 / 8
AS
Anjali Singh
Skin Brightening Program Active
✨ Vitamin C Peel
🌿 Kojic Acid Serum
+ LED Therapy Add-on
1
2
3
4
5
6
2 / 6
NP
Neha Patel
Hair PRP Therapy Nearly Done
💉 PRP Injection
🌱 Mesotherapy
+ Scalp Massage Add-on
1
2
3
4
5
4 / 5
RJ
Ritika Joshi
Acne Treatment Plan Completed
🧴 Salicylic Peel
💡 Blue Light Therapy
+ Spot Gel Add-on
1
2
3
4
5
6
7
8
8 / 8 ✓
SR
Sunita Rao
Anti-Aging Facial Program Active
💧 Hydra Facial
🌟 Collagen Booster
+ Microcurrent Add-on
+ RF Tightening Add-on
1
2
3
4
5
6
7
8
9
10
2 / 10
| Product | Category | Stock | Batch # | Expiry | Vendor | Status | Actions |
|---|---|---|---|---|---|---|---|
| Vitamin C Serum 20% | Serum |
3
|
B2025-447 | Sep 2026 | Cosmo Labs | ⚠ Low Stock | |
| Hydroquinone 4% Cream | Cream |
2
|
B2025-321 | Dec 2026 | DermaCo | ⚠ Low Stock | |
| Hyaluronic Acid Serum | Serum |
24
|
B2025-501 | Mar 2027 | Cosmo Labs | ✓ In Stock | |
| Laser Cooling Gel | Consumable |
4
|
B2026-012 | Jul 2027 | LaserTech | ⚠ Low Stock | |
| Glycolic Acid 10% | Medicine |
18
|
B2025-388 | Jun 2027 | AlphaChem | ✓ In Stock |
New Invoice
Line Items
₹4,500
Charges & Adjustments
— ₹0
₹0
(Optional)
₹0
Subtotal₹4,500
Discount— ₹0
Total₹4,500
Payment Mode
Linqs Cosmetology Clinic
Skin · Hair · Laser
14-B, MG Road, Bengaluru 560001
+91 98100 55555
GSTIN: 29AABCL1234A1Z5
+91 98100 55555
GSTIN: 29AABCL1234A1Z5
Bill To
Priya MehtaBandra, Mumbai 400050
+91 98765 43210
Treatment Details
Package: Laser Hair RemovalSession #6 of 8 · Dr. Kapoor
| # | Description | Qty | Rate | Amount |
|---|---|---|---|---|
| 1 | Laser Hair Removal — Session 6 | 1 | ₹4,500 | ₹4,500 |
Subtotal₹4,500
Discount— ₹0
Total Due₹4,500
✓ PAID — Cash
Thank you for choosing Linqs Cosmetology Clinic!
This is a computer-generated invoice.
This is a computer-generated invoice.
RS
Dr. Reena Sharma
Admin · Dermatologist
Active
VK
Dr. Vivek Kapoor
Doctor · Laser Specialist
Active
MJ
Meena Joshi
Receptionist
Active
RP
Ritu Pillai
Therapist
Inactive
🏥 Clinic Information
Clinic Name
Appears on all invoices and communications
Logo
Address
Phone
💰 GST & Billing
GSTIN
GST Identification Number
Default GST Rate
Invoice Prefix
🕐 Working Hours
Monday – Saturday
to
Sunday
Appointment Slot Duration
Complete relational database schema for the LinqsClinic ERP system. All tables use UUID primary keys.
👤 customers
Column
Type
Key
Notes
id
UUID
PK
Primary key
name
VARCHAR(100)
NOT NULL
phone
VARCHAR(15)
IDX
Unique, indexed
email
VARCHAR(100)
Optional
gender
ENUM
Male/Female/Other
date_of_birth
DATE
blood_type
VARCHAR(5)
A+, O-, etc.
address
TEXT
skin_type
VARCHAR(50)
allergies
TEXT
notes
TEXT
Clinical notes
created_at
TIMESTAMP
DEFAULT NOW()
📅 appointments
Column
Type
Key
Notes
id
UUID
PK
customer_id
UUID
FK
→ customers.id
staff_id
UUID
FK
→ staff.id
treatment_type
VARCHAR(100)
Hair/Skin/Laser
appointment_date
DATE
IDX
Indexed for queries
start_time
TIME
duration_mins
INT
Default 30
status
ENUM
IDX
scheduled/confirmed/completed/cancelled/no-show
session_id
UUID
FK
→ package_sessions.id (nullable)
notes
TEXT
📦 package_plans
Column
Type
Key
Notes
id
UUID
PK
name
VARCHAR(150)
NOT NULL
description
TEXT
session_count
INT
Total sessions
price
DECIMAL(10,2)
is_active
BOOLEAN
DEFAULT true
📋 package_enrollments
Column
Type
Key
Notes
id
UUID
PK
customer_id
UUID
FK
→ customers.id
plan_id
UUID
FK
→ package_plans.id
enrolled_at
DATE
sessions_completed
INT
Computed field
status
ENUM
active/completed/cancelled
bill_id
UUID
FK
→ bills.id
🎯 package_sessions
Column
Type
Key
Notes
id
UUID
PK
enrollment_id
UUID
FK
→ package_enrollments.id
session_number
INT
1, 2, 3...
staff_id
UUID
FK
Assigned staff
status
ENUM
pending/completed
completed_at
TIMESTAMP
Nullable
notes
TEXT
Per-session notes
👩⚕️ staff
Column
Type
Key
Notes
id
UUID
PK
name
VARCHAR(100)
role
ENUM
admin/doctor/receptionist
phone
VARCHAR(15)
email
VARCHAR(100)
UNIQ
Login email
password_hash
VARCHAR(255)
bcrypt
specialization
VARCHAR(100)
is_active
BOOLEAN
DEFAULT true
🧴 inventory_items
Column
Type
Key
Notes
id
UUID
PK
name
VARCHAR(150)
category
ENUM
IDX
medicine/serum/cream/consumable
quantity
INT
Current stock
reorder_threshold
INT
Alert trigger
batch_number
VARCHAR(50)
expiry_date
DATE
IDX
For expiry alerts
vendor
VARCHAR(100)
unit_cost
DECIMAL(10,2)
📊 inventory_logs
Column
Type
Key
Notes
id
UUID
PK
item_id
UUID
FK
→ inventory_items.id
type
ENUM
stock_in / stock_out
quantity_change
INT
+/- value
bill_id
UUID
FK
Nullable, auto-deduct
staff_id
UUID
FK
Who made change
created_at
TIMESTAMP
Audit trail
💳 bills
Column
Type
Key
Notes
id
UUID
PK
invoice_number
VARCHAR(30)
UNIQ
INV-2026-0001
customer_id
UUID
FK
→ customers.id
subtotal
DECIMAL(10,2)
gst_amount
DECIMAL(10,2)
discount
DECIMAL(10,2)
total
DECIMAL(10,2)
payment_status
ENUM
IDX
paid/partial/pending
payment_mode
ENUM
cash/upi/card
created_by
UUID
FK
→ staff.id
created_at
TIMESTAMP
IDX
📝 bill_items
Column
Type
Key
Notes
id
UUID
PK
bill_id
UUID
FK
→ bills.id
description
VARCHAR(200)
item_type
ENUM
service/product/package
quantity
INT
unit_price
DECIMAL(10,2)
inventory_item_id
UUID
FK
Nullable, triggers deduction
REST API — Base URL: https://api.linqsclinic.in/v1 · Auth: Bearer JWT
Customers
GET
/customers
List all customers with filters
▼
Query Params
?search=priya&page=1&limit=20
Response 200
{
"data": [
{
"id": "uuid",
"name": "Priya Mehta",
"phone": "+91 98765 43210",
"active_packages": 2,
"last_visit": "2026-03-03"
}
],
"total": 48,
"page": 1
}
POST
/customers
Create new customer profile
▼
Request Body
{
"name": "Anjali Singh",
"phone": "+91 87654 32109",
"email": "[email protected]",
"gender": "female",
"date_of_birth": "1990-06-15",
"blood_type": "A+",
"address": "Andheri, Mumbai",
"notes": "Sensitive skin"
}
Response 201
{ "id": "uuid-here", "message": "Customer created" }
Appointments
GET
/appointments
List appointments by date/doctor
▼
Query Params
?date=2026-03-03&staff_id=uuid&status=confirmed
Response 200
{
"appointments": [
{
"id": "uuid",
"customer": { "name": "Priya Mehta", "phone": "+91..." },
"staff": { "name": "Dr. Kapoor" },
"treatment_type": "Laser",
"appointment_date": "2026-03-03",
"start_time": "09:00",
"status": "confirmed"
}
]
}
POST
/appointments
Book a new appointment
▼
Request Body
{
"customer_id": "uuid",
"staff_id": "uuid",
"treatment_type": "Laser",
"appointment_date": "2026-03-10",
"start_time": "10:00",
"duration_mins": 45,
"session_id": "uuid-or-null"
}
PATCH
/appointments/:id/status
Update appointment status
▼
Request Body
{
"status": "completed" // scheduled|confirmed|completed|cancelled|no-show
}
Response 200
{ "message": "Status updated", "whatsapp_url": "https://wa.me/919876543210?text=..." }
Packages
POST
/packages/enroll
Enroll customer in a package plan
▼
Request Body
{
"customer_id": "uuid",
"plan_id": "uuid",
"bill_id": "uuid" // Link payment
}
Response 201
{
"enrollment_id": "uuid",
"sessions_created": 8,
"message": "Enrolled in Laser Hair Removal — 8 sessions created"
}
PATCH
/packages/sessions/:id/complete
Mark a session as completed
▼
Request Body
{
"staff_id": "uuid",
"notes": "Used 3 passes, full coverage"
}
Response 200
{
"session_number": 6,
"sessions_remaining": 2,
"whatsapp_url": "https://wa.me/91...?text=Session+6+completed..."
}
Inventory
POST
/inventory/stock-in
Add stock for an inventory item
▼
Request Body
{
"item_id": "uuid",
"quantity": 20,
"batch_number": "B2026-055",
"expiry_date": "2027-09-01",
"vendor": "Cosmo Labs"
}
Response 200
{ "new_quantity": 23, "low_stock": false }
Billing
POST
/billing
Create a bill and auto-deduct inventory
▼
Request Body
{
"customer_id": "uuid",
"items": [
{
"description": "Laser Session 6",
"item_type": "service",
"quantity": 1,
"unit_price": 4500
},
{
"description": "Cooling Gel",
"item_type": "product",
"inventory_item_id": "uuid",
"quantity": 1,
"unit_price": 500
}
],
"discount": 0,
"gst_percent": 18,
"payment_mode": "cash",
"payment_status": "paid"
}
Response 201
{
"bill_id": "uuid",
"invoice_number": "INV-2026-0043",
"total": 5900,
"inventory_deducted": [{ "item": "Cooling Gel", "qty": 1, "new_stock": 3 }],
"low_stock_alerts": [{ "item": "Cooling Gel", "quantity": 3 }]
}
🏗 System Architecture
# Recommended Tech Stack
Frontend
Framework: React 18 + Vite
Routing: React Router v6
State: Zustand (simple)
UI: Tailwind CSS
Icons: Lucide React
Tables: TanStack Table
Print: browser print API
Backend
Runtime: Node.js + Express
ORM: Prisma (PostgreSQL)
Auth: JWT + bcrypt
Validation: Zod
Upload: Multer + S3/local
Database
PostgreSQL 15
Redis (sessions + alerts)
Deployment
Docker Compose
Nginx reverse proxy
PM2 process manager
📁 Folder Structure
linqs/
├── frontend/
│ ├── src/
│ │ ├── pages/
│ │ │ ├── Dashboard.jsx
│ │ │ ├── Appointments.jsx
│ │ │ ├── Customers.jsx
│ │ │ ├── CustomerDetail.jsx
│ │ │ ├── Packages.jsx
│ │ │ ├── Inventory.jsx
│ │ │ ├── Billing.jsx
│ │ │ ├── Staff.jsx
│ │ │ └── Settings.jsx
│ │ ├── components/
│ │ │ ├── AppointmentGrid.jsx
│ │ │ ├── PackageTracker.jsx
│ │ │ ├── InvoicePreview.jsx
│ │ │ ├── SessionDots.jsx
│ │ │ └── StockBadge.jsx
│ │ ├── store/
│ │ │ └── useClinicStore.js
│ │ └── api/
│ │ └── client.js
│
├── backend/
│ ├── routes/
│ │ ├── customers.js
│ │ ├── appointments.js
│ │ ├── packages.js
│ │ ├── inventory.js
│ │ ├── billing.js
│ │ ├── staff.js
│ │ └── settings.js
│ ├── middleware/
│ │ ├── auth.js
│ │ └── rbac.js
│ ├── services/
│ │ ├── whatsapp.js
│ │ ├── inventory.js
│ │ └── billing.js
│ └── prisma/
│ └── schema.prisma
│
└── docker-compose.yml
🔐 RBAC Design
| Module | Admin | Doctor | Recept. |
|---|---|---|---|
| Dashboard | ✓ Full | ✓ View | ✓ View |
| Appointments | ✓ Full | ✓ Full | ✓ Full |
| Customers | ✓ Full | ✓ Full | ✓ Full |
| Packages | ✓ Full | ✓ View | ✓ Enroll |
| Inventory | ✓ Full | View | — |
| Billing | ✓ Full | View | ✓ Full |
| Staff | ✓ Full | — | — |
| Settings | ✓ Full | — | — |
🔮 Future-Ready Design
✦ Multi-Branch: Add
✦ Revenue Reports: Pre-aggregate daily into
✦ SMS/Email: Hook into queue on appointment create
✦ Real PDF: Replace print with Puppeteer / pdf-lib
✦ Real-time: Add WebSocket via Socket.io for live calendar
✦ Analytics: Materialized views for slow queries
✦ Audit Log:
branch_id FK to all entities✦ Revenue Reports: Pre-aggregate daily into
report_snapshots✦ SMS/Email: Hook into queue on appointment create
✦ Real PDF: Replace print with Puppeteer / pdf-lib
✦ Real-time: Add WebSocket via Socket.io for live calendar
✦ Analytics: Materialized views for slow queries
✦ Audit Log:
audit_logs table captures all mutations
📱 WhatsApp Integration
Current (Free): wa.me deep links with pre-filled messages.
The API returns
· Appointment booked → reminder
· Appointment confirmed
· Session completed → confirmation
· Package nearly complete
Future (Paid): Upgrade to WhatsApp Business Cloud API for automated sends — no code changes needed, just swap the
The API returns
whatsapp_url on key events:· Appointment booked → reminder
· Appointment confirmed
· Session completed → confirmation
· Package nearly complete
Future (Paid): Upgrade to WhatsApp Business Cloud API for automated sends — no code changes needed, just swap the
whatsapp.js service.