# TSHIRTORDER-1570 — Guest Login: Multi-Brand Support

## Yêu cầu gốc

> TSHIRTORDER-1570 GUEST LOGIN user support Multi brands login
> now we fix so you can loggin on multiple GUEST portal , we needs to support same but on brands as well

Guest user đã login được nhiều portal (multi-channel). Cần hỗ trợ tương tự cho **brands** — guest user có thể truy cập nhiều brand sau khi login.

---

## Quan hệ giữa User, Brand, Product, Order

### Sơ đồ

```
User (ROLE_CHANNEL)
 ├── brandId (INT, 1 brand duy nhất)         ← điểm cần thay đổi
 └── UserMultiChannel[] (join table)
       ├── userId
       ├── channelId   ← nhiều channel ✅ đã có
       └── brandId     ← copy từ user.brandId (cùng brand cho mọi channel)

Product
 ├── brandId           ← thuộc 1 brand
 └── channels[]        ← ManyToMany với Channel (bảng products_channels)

Order
 ├── channelId         ← thuộc 1 channel
 └── OrderProduct[].brandId  ← từng line item mang brandId của product

Brand ──── không có liên kết trực tiếp với Channel
```

### Entities liên quan

| Entity | File | Trường quan trọng |
|---|---|---|
| `User` | `src/Entity/User.php` | `brandId`, `role = ROLE_CHANNEL` |
| `UserMultiChannel` | `src/Entity/UserMultiChannel.php` | `userId`, `channelId`, `brandId` |
| `Brand` | `src/Entity/Brand.php` | `id`, `name`, `brandKey`, `logo` |
| `Product` | `src/Entity/Product.php` | `brandId`, `channels[]` (ManyToMany) |
| `Order` | `src/Entity/Order.php` | `channelId` (không có brandId trực tiếp) |
| `OrderProduct` | `src/Entity/OrderProduct.php` | `brandId` (line item level) |

---

## Hiện trạng: cách Guest login filter data

### Multi-channel (đã hoạt động)

- `UserMultiChannel` lưu các cặp `(userId, channelId)`
- Login response trả về `channelIds: [1, 3, 7]`
- Frontend cho user chọn channel → gửi `channelId` trong mỗi request
- Backend validate `channelId` nằm trong danh sách của user

Code xử lý ở `UserService::generateItem()` (`src/Service/UserService.php:127`):
```php
$userChannels = $this->em->getRepository(UserMultiChannel::class)->findBy(['userId' => $user->getId()]);
foreach ($userChannels as $userChannel) {
    $data['channels'][] = ['id' => $userChannel->getChannelId(), 'name' => $userChannel->getChannelName()];
    $data['channelIds'][] = $userChannel->getChannelId();
}
```

### Brand (hiện chỉ 1 brand / user)

`User.brandId` là 1 integer duy nhất. Filter được áp tự động — frontend không cần gửi gì.

| File | Dòng | Code |
|---|---|---|
| `ProductService.php` | 558 | `$criteria['brandId'] = $user->getBrandId()` |
| `OrderService.php` | 4668 | `$requestData['brandId'] = $user->getBrandId()` |
| `ApiService.php` | 184 | `$brandId = $user->getBrandId()` |

Tất cả đều theo pattern: `if (!empty($user->getBrandId())) { ... filter ... }`.

### Channel settings liên quan (src/Entity/Channel.php)

- `guestLoginAddOrder`, `guestLoginAddProduct`, `guestLoginProduction`
- `guestLoginShowKickback`, `guestLoginShowPrepaid`, `guestKickbackInvoice`

---

## Vấn đề hiện tại

`User.brandId` chỉ là **1 giá trị integer** → user chỉ thấy đúng 1 brand. Không có join table tương đương `UserMultiChannel` cho brand.

`UserMultiChannel` đã có sẵn fields `brandId`, `brandName`, `brandLogo` nhưng hiện tại chúng được **copy từ user.brandId** — tức là mọi channel của user đều cùng 1 brand, không phải per-channel hay multi-brand.

---

## Giải pháp đề xuất: `UserMultiBrand` (mirror pattern của `UserMultiChannel`)

### Cấu trúc mới

```
User (ROLE_CHANNEL)
 ├── brandId          ← giữ nguyên (brand mặc định / backwards compat)
 ├── UserMultiChannel[]
 └── UserMultiBrand[] (JOIN TABLE MỚI)
       ├── userId
       └── brandId   ← nhiều brand ✅
```

### Các bước implement

**1. Entity mới** — `src/Entity/UserMultiBrand.php`
- Fields: `id`, `userId`, `brandId`, `brandName`, `brandLogo`, `dateCreated`, `dateUpdated`
- Unique constraint: `(userId, brandId)`

**2. Migration**
```bash
php bin/console doctrine:migrations:diff
php bin/console doctrine:migrations:migrate
```

**3. `UserService`** (`src/Service/UserService.php`)
- `generateItem()` → thêm `brandIds: [1, 5, 9]` vào response (như `channelIds`)
- Thêm `__updateMultiBrands()` tương tự `__updateMultiChannels()`
- `add()` / `update()` / `delete()` → xử lý `brandIds` array

**4. Filter data** — thay `$user->getBrandId()` (single) bằng validate `brandId` từ request nằm trong danh sách brands của user:

| File | Hiện tại | Sau khi sửa |
|---|---|---|
| `ProductService.php:558` | `$criteria['brandId'] = $user->getBrandId()` | validate + dùng `brandId` từ request |
| `OrderService.php:4668` | `$requestData['brandId'] = $user->getBrandId()` | validate + dùng `brandId` từ request |
| `ApiService.php:184` | `$brandId = $user->getBrandId()` | validate + dùng `brandId` từ request |

**5. Frontend** (ngoài repo này)
- Login response có thêm `brandIds: []`
- Cho user chọn brand (giống chọn channel)
- Gửi `brandId` trong mỗi request

---

## Ước tính thời gian (backend)

| Việc | Ước tính |
|---|---|
| Entity `UserMultiBrand` + migration | 1 giờ |
| `UserService` (add/update/delete/generateItem) | 2 giờ |
| `ProductService` + `OrderService` + `ApiService` | 2 giờ |
| **Tổng backend** | **~5 giờ** |

Pattern đã có sẵn từ `UserMultiChannel` — làm y chang, không phức tạp.

---

## Status

- [x] Phân tích quan hệ entities
- [x] Xác định vấn đề
- [x] Thiết kế giải pháp
- [ ] Làm rõ flow UI với product owner (brand switch trên frontend như thế nào)
- [ ] Implement backend
- [ ] Implement frontend
