PostgreSQL 16+. Toate cheile primare sunt UUID. Toate marcajele temporale sunt stocate în UTC.
Users & Auth
users
| Coloană | Tip | Descriere |
|---|
id | UUID (PK) | |
email | string | Unic |
phone | string | Unic |
role | enum | client · professional · admin |
encrypted_password | string | bcrypt |
confirmed_at | timestamp | Confirmare email |
discarded_at | timestamp | Ștergere logică |
Proprietarul salonului este determinat prin salons.owner_id, nu prin role.
profiles
| Coloană | Tip |
|---|
user_id | UUID (FK → users) |
first_name | string |
last_name | string |
avatar_url | string |
bio | text |
locale | string |
oauth_identities
| Coloană | Tip | Descriere |
|---|
id | UUID (PK) | |
user_id | UUID (FK) | → users.id |
provider | string | "google" și alții în viitor |
uid | string | ID unic la furnizor (sub) |
created_at | timestamp | |
updated_at | timestamp | |
Index unic: provider + uid.
Saloane & Servicii
salons
| Coloană | Tip | Descriere |
|---|
id | UUID (PK) | |
owner_id | UUID (FK) | → users.id |
name | string | |
slug | string | Prietenos pentru URL, unic |
address | string | |
lat, lng | decimal | Coordonate |
phone | string | |
status | enum | pending · active · suspended |
photo_url | string | |
reviews_count | integer | Cache contor |
rating | decimal | Rating mediu |
currency | string | ISO 4217, implicit MDL |
timezone | string | IANA, implicit Europe/Chisinau |
cancellation_hours_before | integer | Implicit 24 |
cancellation_fee_percent | decimal | Implicit 0 |
auto_cancel_after_min | integer | nullable |
salon_services (AR model: Service)
| Coloană | Tip |
|---|
id | UUID (PK) |
salon_id | UUID (FK) |
name | string |
description | text |
duration_min | integer |
category_id | integer (FK → categories) |
Index unic: salon_id + name.
service_master_prices (AR model: ServiceMasterPrice)
| Coloană | Tip |
|---|
id | UUID (PK) |
salon_id | UUID (FK) |
service_id | UUID (FK → salon_services) |
master_id | UUID (FK → users) |
price | decimal |
Index unic: service_id + master_id.
categories
| Coloană | Tip |
|---|
id | integer |
name | string |
slug | string |
parent_id | integer (auto-join, nullable) |
position | integer |
Membrii & Profiluri maeștri
salon_memberships
| Coloană | Tip | Descriere |
|---|
id | UUID (PK) | |
salon_id | UUID (FK) | |
user_id | UUID (FK) | |
role | enum | master · receptionist |
status | enum | pending · active · deactivated |
invite_token | string | Pentru acceptarea invitațiilor |
invited_at | timestamp | |
accepted_at | timestamp | nullable |
Index unic: salon_id + user_id.
master_profiles
| Coloană | Tip |
|---|
id | UUID (PK) |
user_id | UUID (FK) |
specialization | string |
experience_years | integer |
instagram_url | string |
portfolio_url | string |
reviews_count | integer |
rating | decimal |
Programare & Rezervări
working_hours
| Coloană | Tip | Descriere |
|---|
salon_id | UUID (FK) | |
membership_id | UUID (FK → salon_memberships, nullable) | null = întreg salonul |
day_of_week | integer | 0=Dum, 1=Lun ... 6=Sâm |
start_time | time | |
end_time | time | |
appointments
| Coloană | Tip | Descriere |
|---|
id | UUID (PK) | |
client_id | UUID (FK) | → users.id |
salon_id | UUID (FK) | |
master_id | UUID (FK) | → users.id |
service_id | UUID (FK) | → salon_services.id |
starts_at | timestamp | |
ends_at | timestamp | |
status | string | AASM: confirmed/in_progress/completed/reviewed/cancelled/no_show |
price_snapshot | decimal | Prețul la momentul rezervării (înghețat) |
duration_min_snapshot | integer | Durata la momentul rezervării |
total_amount | decimal | |
Recenzii & Favorite
reviews
| Coloană | Tip |
|---|
id | UUID (PK) |
appointment_id | UUID (FK) |
client_id | UUID (FK) |
salon_id | UUID (FK) |
master_id | UUID (FK) |
rating | integer |
body | text |
favorites
| Coloană | Tip |
|---|
id | UUID (PK) |
user_id | UUID (FK) |
salon_id | UUID (FK) |
Index unic: user_id + salon_id.