céges meghívó kezelése,
This commit is contained in:
168
plans/logic_spec_garage_selector_member_audit.md
Normal file
168
plans/logic_spec_garage_selector_member_audit.md
Normal 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
|
||||
Reference in New Issue
Block a user