céges meghívó kezelése,

This commit is contained in:
Roo
2026-06-17 22:07:55 +00:00
parent bf3a971ff1
commit 127b130401
28 changed files with 5806 additions and 1313 deletions

View File

@@ -0,0 +1,168 @@
# 🏗️ Logic Spec: P1 Garage Selector & OrganizationMember Audit
## 1. Modul Célja és Masterbook 2.0 Illeszkedés
**Cél:** A Dashboard "Garage Selector" (cégválasztó) pontosítása, hogy a bejelentkezett felhasználó:
- a) Szerepeljen azon Organization rekordok között, ahol technikai tulajdonos (`owner_id`)
- b) Szerepeljen azon Organization rekordok között, ahol aktív `OrganizationMember`
Emellett az `OrganizationMember` tábla és a meghívási folyamat teljes auditja.
**Masterbook 2.0 illeszkedés:** B2B szervezetkezelés (11-es Epic), B2B szerepkörök és szervezeti hierarchia.
---
## 2. Adatmodell Elemzés
### 2.1 OrganizationMember tábla (aktuális séma)
| Oszlop | Típus | Kötelező | Megjegyzés |
|--------|-------|----------|------------|
| `id` | integer PK | YES | Auto-increment |
| `organization_id` | integer FK -> fleet.organizations.id | YES | |
| `user_id` | integer FK -> identity.users.id | NO | Lehet NULL (pending invite) |
| `person_id` | bigint FK -> identity.persons.id | NO | |
| `role` | ENUM (OrgUserRole) | YES | OWNER, ADMIN, FLEET_MANAGER, DRIVER, MECHANIC, RECEPTIONIST |
| `permissions` | JSONB | NO (default `{}`) | |
| `is_permanent` | boolean | NO (default false) | |
| `is_verified` | boolean | NO (default false) | |
### 2.2 🔴 HIÁNYZÓ OSZLOPOK (Kritikus)
1. **`status` VARCHAR** - A kód használja (`status="pending"`, `status="active"` a organizations.py:421,481 sorokban), **de az adatbázisban NINCS ilyen oszlop!** Ez futási hibát okoz az invite/join folyamatokban.
2. **`joined_at` TIMESTAMP** - Nincs nyomon követve, mikor csatlakozott a tag.
3. **`expires_at` / `valid_until` TIMESTAMP** - Nincs lejárati dátum (pl. ideiglenes hozzáféréshez).
4. **`created_at` TIMESTAMP** - Hiányzik a tag rekord létrehozási dátuma.
5. **`updated_at` TIMESTAMP** - Hiányzik a módosítás dátuma.
### 2.3 🟢 MEGLÉVŐ, HELYESEN MŰKÖDŐ
- `role` ENUM - Jól definiált, 6 szerepkörrel.
- `user_id` + `person_id` kettős hivatkozás - Támogatja a "Dual Entity" modellt.
- `is_permanent` - Alkalmas az állandó vs. ideiglenes tagság megkülönböztetésére.
---
## 3. Backend Módosítás: `get_my_organizations` Fix
### 3.1 Probléma
Jelenleg a `GET /api/v1/organizations/my` lekérdezés (`organizations.py:192`) csak `INNER JOIN`-t használ az `OrganizationMember` táblával. Ez kizárja azokat az eseteket, ahol a felhasználó `owner_id` (technikai tulajdonos), de az `OrganizationMember` rekord nem található.
### 3.2 Megoldás
Használjunk `LEFT JOIN`-t `OR` feltétellel:
```python
from sqlalchemy import or_
stmt = (
select(Organization)
.outerjoin(OrganizationMember, OrganizationMember.organization_id == Organization.id)
.where(
or_(
Organization.owner_id == current_user.id,
OrganizationMember.user_id == current_user.id
)
)
.where(Organization.org_type.notin_([OrgType.service_provider, OrgType.service]))
.where(Organization.is_deleted == False)
.distinct()
)
```
### 3.3 Válasz bővítése
A frontend számára szükséges a `user_role` mező:
```python
user_role = None
for member in o.members:
if member.user_id == current_user.id:
user_role = member.role.value if hasattr(member.role, 'value') else str(member.role)
break
```
---
## 4. Frontend Módosítások
### 4.1 HeaderCompanySwitcher.vue - Jelenlegi állapot
A komponens már használja az `authStore.myOrganizations` adatokat, és szűri a `companyOrganizations` computed property-ben az `individual`, `service_provider`, `service` típusokat. Ez rendben van.
### 4.2 Szükséges változtatások
1. **Nincs változtatás szükséges** a frontend logikában - a `fetchMyOrganizations()` már meghívja a `/organizations/my` végpontot, és a `companyOrganizations` computed property megfelelően szűr.
2. **OrganizationItem típus** (`frontend/src/types/organization.ts`) - már tartalmazza a `user_role` mezőt (nem kötelező).
### 4.3 Aktív szervezet kiválasztás
A `switchOrganization` metódus (`frontend/src/stores/auth.ts:631`) már implementálva van, a `PATCH /users/me/active-organization` hívással. A frontend globális állapota frissül a `user.value.active_organization_id` mezővel.
---
## 5. Audit Jelentés: OrganizationMember & Invite Flow
### 5.1 Meglévő API Végpontok
| Végpont | Metódus | Státusz | Leírás |
|---------|---------|---------|--------|
| POST /organizations/{org_id}/invitations | POST | Letezik | Meghívó küldése email címre |
| POST /organizations/invitations/{token}/accept | POST | Letevezik | Meghívó elfogadása token alapján |
| POST /organizations/{org_id}/join-request | POST | Letevezik | Csatlakozási kérelem (ha van admin) |
| POST /organizations/{org_id}/claim/request | POST | Letevezik | Árva cég átvételi kérelem |
| POST /organizations/{org_id}/claim/verify | POST | Letevezik | Árva cég átvétel OTP-vel |
### 5.2 🔴 HIÁNYZÓ VÉGPONTOK (Kritikus)
| Végpont | Hiány | Hatás |
|---------|-------|-------|
| GET /organizations/{org_id}/members | Nincs | Nincs lehetőség a tagok listázására |
| PATCH /organizations/{org_id}/members/{member_id}/role | Nincs | Nincs lehetőség a szerepkör módosítására |
| DELETE /organizations/{org_id}/members/{member_id} | Nincs | Nincs lehetőség a tag eltávolítására |
| GET /organizations/{org_id}/invitations | Nincs | Nincs lehetőség a függő meghívók listázására |
| DELETE /organizations/{org_id}/invitations/{invitation_id} | Nincs | Nincs lehetőség a meghívó visszavonására |
### 5.3 🔴 Kritikus Adatbázis Probléma
Az `OrganizationMember` modellben és az adatbázisban **HIÁNYZIK** a `status` oszlop, de a kód (`organizations.py:421` és `organizations.py:481`) hivatkozik rá (`status="pending"`, `status="active"`). Ez a meghívási folyamatban futási hibát okoz!
### 5.4 Meghívási Folyamat Ábrája
```
OWNER/ADMIN -> POST /invitations -> Van-e user?
|-> Igen -> Letrehoz OrganizationMember (user_id=target)
|-> Nem -> Letrehoz VerificationToken (token_type=org_invite)
|-> Email ertesites
|
Regisztracio utan -> POST /invitations/{token}/accept
-> Token validalas
-> Letezik-e mar tag?
|-> Igen -> Frissiti a szerepkört
|-> Nem -> Letrehozza a tag rekordot
-> Done
```
### 5.5 Javasolt Javítási Sorrend
1. **P0 - AZONNAL:** `status` oszlop hozzáadása az `OrganizationMember` modellhez és az adatbázishoz (sync_engine).
2. **P0 - AZONNAL:** Dátum oszlopok (`created_at`, `updated_at`) hozzáadása.
3. **P1 - JELEN FELADAT:** `get_my_organizations` javítása `OR` logikára.
4. **P2 - KOVETKEZO:** Tagkezelő API végpontok implementálása (list, role change, remove).
5. **P2 - KOVETKEZO:** Meghívókezelő API végpontok (list pending, revoke).
---
## 6. Végrehajtási Terv
### 6.1 Backend változtatások (Code mód)
1. `backend/app/models/marketplace/organization.py` - `OrganizationMember` modellbe hozzáadni: `status`, `created_at`, `updated_at`
2. `backend/app/api/v1/endpoints/organizations.py` - `get_my_organizations` query javítása `OR` logikára + `DISTINCT` + `user_role` visszaadása
### 6.2 Frontend változtatások (Code mód)
- Nincs szükség változtatásra - a frontend már helyesen használja az API-t.
### 6.3 Adatbázis szinkron
- Futtatni: `docker exec sf_api python3 -m app.scripts.sync_engine`
---
## 7. Jóváhagyás
**Kérem a felhasználó jóváhagyását a fenti tervhez!** A jóváhagyás után:
1. Létrehozom a Gitea feladatkártyákat
2. Váltok Code módba a megvalósításhoz