# Client Logo Upload API Documentation ## Overview API untuk mengelola logo client dengan integrasi MinIO storage. Mendukung upload, delete, dan generate presigned URL untuk logo client. ## Endpoints ### 1. Upload Client Logo **POST** `/clients/{id}/logo` Upload logo image untuk client tertentu. #### Request - **Content-Type**: `multipart/form-data` - **Parameter**: - `id` (path): Client ID (UUID) - `logo` (form-data): File image (jpg, jpeg, png, gif, webp, max 5MB) #### Response ```json { "success": true, "messages": ["Client logo uploaded successfully"], "data": { "imagePath": "clients/logos/{clientId}/filename_timestamp_random.ext" } } ``` #### Example cURL ```bash curl -X POST \ http://localhost:8080/clients/123e4567-e89b-12d3-a456-426614174000/logo \ -H "Authorization: Bearer your-token" \ -F "logo=@/path/to/logo.png" ``` ### 2. Delete Client Logo **DELETE** `/clients/{id}/logo` Hapus logo client dari MinIO dan database. #### Request - **Parameter**: - `id` (path): Client ID (UUID) #### Response ```json { "success": true, "messages": ["Client logo deleted successfully"] } ``` #### Example cURL ```bash curl -X DELETE \ http://localhost:8080/clients/123e4567-e89b-12d3-a456-426614174000/logo \ -H "Authorization: Bearer your-token" ``` ### 3. Get Logo URL **GET** `/clients/{id}/logo/url` Generate presigned URL untuk mengakses logo client (valid 24 jam). #### Request - **Parameter**: - `id` (path): Client ID (UUID) #### Response ```json { "success": true, "messages": ["Logo URL generated successfully"], "data": { "url": "https://minio.example.com/bucket/clients/logos/{clientId}/filename?X-Amz-Algorithm=..." } } ``` #### Example cURL ```bash curl -X GET \ http://localhost:8080/clients/123e4567-e89b-12d3-a456-426614174000/logo/url \ -H "Authorization: Bearer your-token" ``` ## File Validation ### Supported Formats - JPEG (.jpg, .jpeg) - PNG (.png) - GIF (.gif) - WebP (.webp) ### File Size Limit - Maximum: 5MB ### File Naming Uploaded files akan di-rename dengan format: ``` {original_name}_{timestamp}_{random_number}.{extension} ``` Example: `company_logo_1640995200_123456.png` ## Storage Structure Logo disimpan di MinIO dengan struktur path: ``` clients/logos/{clientId}/{filename} ``` ## Error Handling ### Common Errors #### 400 Bad Request ```json { "success": false, "messages": ["Invalid file type. Only jpg, jpeg, png, gif, webp are allowed"] } ``` #### 413 Payload Too Large ```json { "success": false, "messages": ["File size too large. Maximum size is 5MB"] } ``` #### 404 Not Found ```json { "success": false, "messages": ["Client not found"] } ``` #### 500 Internal Server Error ```json { "success": false, "messages": ["Failed to upload file to MinIO"] } ``` ## Database Schema ### New Fields Added to `clients` Table ```sql ALTER TABLE clients ADD COLUMN logo_url VARCHAR(255), -- External logo URL ADD COLUMN logo_image_path VARCHAR(255), -- MinIO storage path ADD COLUMN address TEXT, -- Physical address ADD COLUMN phone_number VARCHAR(50), -- Contact phone ADD COLUMN website VARCHAR(255); -- Official website ``` ## Usage Examples ### Frontend Integration #### Upload Logo ```javascript const uploadLogo = async (clientId, file) => { const formData = new FormData(); formData.append('logo', file); const response = await fetch(`/clients/${clientId}/logo`, { method: 'POST', headers: { 'Authorization': `Bearer ${token}` }, body: formData }); return response.json(); }; ``` #### Get Logo URL ```javascript const getLogoUrl = async (clientId) => { const response = await fetch(`/clients/${clientId}/logo/url`, { method: 'GET', headers: { 'Authorization': `Bearer ${token}` } }); const result = await response.json(); return result.data.url; }; ``` ### Backend Integration #### Update Client with Logo Path ```go updateReq := request.ClientsUpdateRequest{ LogoImagePath: &imagePath, // other fields... } err := clientsService.Update(clientId, updateReq) ``` ## Security Considerations 1. **Authentication**: Semua endpoint memerlukan Bearer token 2. **File Validation**: Validasi format dan ukuran file 3. **Presigned URLs**: URL hanya valid 24 jam 4. **Cleanup**: File lama otomatis dihapus saat upload baru ## Performance Notes 1. **File Size**: Batasi ukuran file untuk performa optimal 2. **CDN**: Pertimbangkan menggunakan CDN untuk distribusi logo 3. **Caching**: Cache presigned URLs di frontend 4. **Indexing**: Database indexes untuk query yang efisien ## Migration Jalankan migration untuk menambahkan kolom baru: ```sql -- File: docs/migrations/002_add_client_tenant_fields.sql \i docs/migrations/002_add_client_tenant_fields.sql ```