This commit is contained in:
Iliyan Angelov
2025-12-10 02:01:31 +02:00
parent ab42d86127
commit d4c6ae8aec
6 changed files with 4948 additions and 370 deletions

View File

@@ -0,0 +1,9 @@
{
"filename": "backup_luxury_hotel_db_20251210_000027.sql",
"path": "backups/backup_luxury_hotel_db_20251210_000027.sql",
"size_bytes": 462323,
"size_mb": 0.44,
"created_at": "2025-12-10T00:00:28.460311",
"database": "luxury_hotel_db",
"status": "success"
}

File diff suppressed because one or more lines are too long

View File

@@ -3,6 +3,7 @@ Approval workflow routes.
""" """
from fastapi import APIRouter, Depends, HTTPException, Query from fastapi import APIRouter, Depends, HTTPException, Query
from sqlalchemy.orm import Session from sqlalchemy.orm import Session
from sqlalchemy.exc import ProgrammingError
from typing import Optional from typing import Optional
from ...shared.config.database import get_db from ...shared.config.database import get_db
from ...shared.config.logging_config import get_logger from ...shared.config.logging_config import get_logger
@@ -57,6 +58,13 @@ async def get_pending_approvals(
}) })
except HTTPException: except HTTPException:
raise raise
except ProgrammingError as e:
# Handle missing table gracefully
if "doesn't exist" in str(e) and "approval_requests" in str(e):
logger.warning('Approval requests table does not exist. Returning empty list. Run migrations to create the table.')
return success_response(data={'approvals': []})
logger.error(f'Database error getting pending approvals: {str(e)}', exc_info=True)
raise HTTPException(status_code=500, detail='Database error occurred')
except Exception as e: except Exception as e:
logger.error(f'Error getting pending approvals: {str(e)}', exc_info=True) logger.error(f'Error getting pending approvals: {str(e)}', exc_info=True)
raise HTTPException(status_code=500, detail=str(e)) raise HTTPException(status_code=500, detail=str(e))
@@ -88,6 +96,12 @@ async def approve_request(
) )
except ValueError as e: except ValueError as e:
raise HTTPException(status_code=400, detail=str(e)) raise HTTPException(status_code=400, detail=str(e))
except ProgrammingError as e:
if "doesn't exist" in str(e) and "approval_requests" in str(e):
logger.warning('Approval requests table does not exist. Run migrations to create the table.')
raise HTTPException(status_code=503, detail='Approval system not available. Please run database migrations.')
logger.error(f'Database error approving request: {str(e)}', exc_info=True)
raise HTTPException(status_code=500, detail='Database error occurred')
except Exception as e: except Exception as e:
logger.error(f'Error approving request: {str(e)}', exc_info=True) logger.error(f'Error approving request: {str(e)}', exc_info=True)
raise HTTPException(status_code=500, detail=str(e)) raise HTTPException(status_code=500, detail=str(e))
@@ -118,6 +132,12 @@ async def reject_request(
) )
except ValueError as e: except ValueError as e:
raise HTTPException(status_code=400, detail=str(e)) raise HTTPException(status_code=400, detail=str(e))
except ProgrammingError as e:
if "doesn't exist" in str(e) and "approval_requests" in str(e):
logger.warning('Approval requests table does not exist. Run migrations to create the table.')
raise HTTPException(status_code=503, detail='Approval system not available. Please run database migrations.')
logger.error(f'Database error rejecting request: {str(e)}', exc_info=True)
raise HTTPException(status_code=500, detail='Database error occurred')
except Exception as e: except Exception as e:
logger.error(f'Error rejecting request: {str(e)}', exc_info=True) logger.error(f'Error rejecting request: {str(e)}', exc_info=True)
raise HTTPException(status_code=500, detail=str(e)) raise HTTPException(status_code=500, detail=str(e))
@@ -162,6 +182,12 @@ async def get_my_approval_requests(
}) })
except HTTPException: except HTTPException:
raise raise
except ProgrammingError as e:
if "doesn't exist" in str(e) and "approval_requests" in str(e):
logger.warning('Approval requests table does not exist. Returning empty list. Run migrations to create the table.')
return success_response(data={'approvals': []})
logger.error(f'Database error getting user approvals: {str(e)}', exc_info=True)
raise HTTPException(status_code=500, detail='Database error occurred')
except Exception as e: except Exception as e:
logger.error(f'Error getting user approvals: {str(e)}', exc_info=True) logger.error(f'Error getting user approvals: {str(e)}', exc_info=True)
raise HTTPException(status_code=500, detail=str(e)) raise HTTPException(status_code=500, detail=str(e))
@@ -194,6 +220,12 @@ async def cancel_approval_request(
return success_response(message='Approval request cancelled successfully') return success_response(message='Approval request cancelled successfully')
except HTTPException: except HTTPException:
raise raise
except ProgrammingError as e:
if "doesn't exist" in str(e) and "approval_requests" in str(e):
logger.warning('Approval requests table does not exist. Run migrations to create the table.')
raise HTTPException(status_code=503, detail='Approval system not available. Please run database migrations.')
logger.error(f'Database error cancelling approval request: {str(e)}', exc_info=True)
raise HTTPException(status_code=500, detail='Database error occurred')
except Exception as e: except Exception as e:
logger.error(f'Error cancelling approval request: {str(e)}', exc_info=True) logger.error(f'Error cancelling approval request: {str(e)}', exc_info=True)
raise HTTPException(status_code=500, detail=str(e)) raise HTTPException(status_code=500, detail=str(e))

View File

@@ -1,149 +0,0 @@
# Icon Control Audit Report
## Summary
This document provides a comprehensive audit of icon usage across frontend pages and identifies which icons are controlled from the admin dashboard vs hardcoded.
---
## ✅ Pages with Full Admin Control
### 1. **HomePage** (`Frontend/src/features/content/pages/HomePage.tsx`)
**Status: ✅ Fully Controlled**
All icons are controlled from admin dashboard:
- **Features Section** - Icons controlled via `pageContent.features[].icon`
- **Luxury Features Section** - Icons controlled via `pageContent.luxury_features[].icon`
- **Stats/Achievements Section** - Icons controlled via `pageContent.stats[].icon` (FIXED: now handles lowercase icon names)
- **Amenities Section** - Icons controlled via `pageContent.amenities[].icon`
- **Awards Section** - Icons controlled via `pageContent.awards[].icon`
- **Experiences Section** - Icons controlled via `pageContent.luxury_experiences[].icon`
**Admin Location:** `PageContentDashboard.tsx` → Home Tab
- Features: Line 2179
- Luxury Features: Line 1552
- Stats: Line 2033
- Amenities: Line 1356
- Awards: Line 2524
- Experiences: Line 2373
---
### 2. **ServiceDetailPage** (`Frontend/src/features/content/pages/ServiceDetailPage.tsx`)
**Status: ✅ Fully Controlled**
- Service icon comes from `service.icon` field in database
- Managed via Service Management admin page
---
## ⚠️ Pages with Partial Admin Control
### 3. **AboutPage** (`Frontend/src/features/content/pages/AboutPage.tsx`)
**Status: ⚠️ Partially Controlled**
**Controlled Icons:**
- ✅ Values Section - Icons controlled via `pageContent.values[].icon` (Admin: Line 3794)
- ✅ Features Section - Icons controlled via `pageContent.features[].icon` (Admin: Line 3885)
- ✅ Achievements Section - Icons controlled via `pageContent.achievements[].icon` (Admin: Line 4264)
**Hardcoded Icons:**
- ❌ Hero Section - `Hotel` icon (Line 197) - Hardcoded, no admin control
- ❌ Contact Info Section - `MapPin`, `Phone`, `Mail` icons (Lines 617, 636, 651) - Hardcoded
- ❌ "Learn More" Button - `Hotel` icon (Line 671) - Hardcoded
**Recommendation:** Add admin controls for:
1. Hero section icon (when no hero image is set)
2. Contact info section icons (optional, as these are semantic)
---
### 4. **ServicesPage** (`Frontend/src/features/content/pages/ServicesPage.tsx`)
**Status: ⚠️ Partially Controlled**
**Controlled Icons:**
- ✅ Service icons come from `service.icon` field in database
**Hardcoded Icons:**
- ❌ Fallback icon - `Award` icon (Line 334) - Used when service has no icon
**Recommendation:** This is acceptable as a fallback, but could be made configurable.
---
## ❌ Pages with No Admin Control
### 5. **ContactPage** (`Frontend/src/features/content/pages/ContactPage.tsx`)
**Status: ❌ All Icons Hardcoded**
**Hardcoded Icons:**
- ❌ Hero Section - `Mail` icon (Line 191)
- ❌ Email Contact Info - `Mail` icon (Line 234)
- ❌ Phone Contact Info - `Phone` icon (Line 246)
- ❌ Location Contact Info - `MapPin` icon (Line 258)
- ❌ Form Field Icons:
- `User` icon (Line 333) - Name field
- `Mail` icon (Line 361) - Email field
- `Phone` icon (Line 387) - Phone field
- `MessageSquare` icon (Lines 410, 436) - Subject and Message fields
- ❌ Submit Button - `Send` icon (Line 497)
**Recommendation:** Add admin controls for:
1. Hero section icon
2. Contact info section icons (Email, Phone, Location)
3. Form field icons (optional, as these are semantic UI elements)
**Admin Location:** `PageContentDashboard.tsx` → Contact Tab (currently no icon controls)
---
## 📊 Summary Statistics
| Page | Total Icon Usages | Admin Controlled | Hardcoded | Control % |
|------|------------------|------------------|-----------|-----------|
| HomePage | ~20+ | 20+ | 0 | 100% ✅ |
| ServiceDetailPage | 1 | 1 | 0 | 100% ✅ |
| AboutPage | 8 | 3 | 5 | 37.5% ⚠️ |
| ServicesPage | ~6 | 5 | 1 | 83% ⚠️ |
| ContactPage | 8 | 0 | 8 | 0% ❌ |
---
## 🔧 Recommendations
### High Priority
1. **ContactPage** - Add icon controls for:
- Hero section icon
- Contact info section icons (Email, Phone, Location)
### Medium Priority
2. **AboutPage** - Add icon control for:
- Hero section icon (when no hero image is set)
### Low Priority
3. **ServicesPage** - Consider making fallback icon configurable
4. **ContactPage** - Consider making form field icons configurable (though semantic icons are fine)
---
## 🛠️ Implementation Notes
### Icon Name Handling
- Icons in database may be stored as lowercase (e.g., 'users', 'calendar')
- Lucide React icons use PascalCase (e.g., 'Users', 'Calendar')
- The `getIconComponent` helper function in HomePage.tsx handles this conversion
- Consider adding this helper to other pages that need it
### Admin Icon Picker
- IconPicker component is available at: `Frontend/src/features/system/components/IconPicker.tsx`
- Already integrated in PageContentDashboard for Home and About pages
- Can be easily added to Contact page admin section
---
## 📝 Notes
- Most content icons are properly controlled from admin
- Hardcoded icons are mostly semantic UI elements (form fields, buttons)
- The main gap is the ContactPage which has no icon controls
- AboutPage hero section could benefit from icon control when no image is set

View File

@@ -1,221 +0,0 @@
# Settings Usage Audit Report
## Summary
This document provides a comprehensive audit of how frontend pages use information from Settings (email, phone, address, currency, etc.) vs hardcoded values.
---
## ✅ Pages Using Settings Correctly
### 1. **Header Component** (`Frontend/src/shared/components/Header.tsx`)
**Status: ⚠️ Uses Settings with Hardcoded Fallbacks**
- ✅ Uses `useCompanySettings()` hook
- ✅ Uses `settings.company_phone` and `settings.company_email`
-**Hardcoded fallbacks:**
- Phone: `'+1 (234) 567-890'`
- Email: `'info@luxuryhotel.com'`
- ✅ Uses `settings.company_logo_url`
**Recommendation:** Remove hardcoded fallbacks or use empty string/null instead.
---
### 2. **Footer Component** (`Frontend/src/shared/components/Footer.tsx`)
**Status: ✅ Fully Uses Settings**
- ✅ Uses `useCompanySettings()` hook
- ✅ Uses `settings.company_phone`, `settings.company_email`, `settings.company_address`
- ✅ No hardcoded fallbacks (uses `null` if not available)
- ✅ Uses `settings.company_logo_url`
---
### 3. **ContactPage** (`Frontend/src/features/content/pages/ContactPage.tsx`)
**Status: ⚠️ Uses Settings with Hardcoded Fallback Text**
- ✅ Uses `useCompanySettings()` hook
- ✅ Uses `settings.company_phone`, `settings.company_email`, `settings.company_address`
-**Hardcoded fallback text:**
- Phone: `'Available 24/7 for your convenience'` (should be actual phone or null)
- Email: `"We'll respond within 24 hours"` (should be actual email or null)
- Address: `'Visit us at our hotel reception'` (should be actual address or null)
**Recommendation:** Use actual values from settings or show nothing if not available.
---
### 4. **AboutPage** (`Frontend/src/features/content/pages/AboutPage.tsx`)
**Status: ✅ Fully Uses Settings**
- ✅ Uses `useCompanySettings()` hook
- ✅ Uses `settings.company_phone`, `settings.company_email`, `settings.company_address`
- ✅ No hardcoded fallbacks (uses `null` if not available)
---
### 5. **Policy Pages** (Privacy, Terms, Refunds, Cancellation, Accessibility, FAQ)
**Status: ✅ Uses Settings for Email**
- ✅ All use `useCompanySettings()` hook
- ✅ Use `settings.company_email` for contact links
- ✅ Only show email link if `settings.company_email` exists
**Pages:**
- `PrivacyPolicyPage.tsx`
- `TermsPage.tsx`
- `RefundsPolicyPage.tsx`
- `CancellationPolicyPage.tsx`
- `AccessibilityPage.tsx`
- `FAQPage.tsx`
---
### 6. **Customer Pages - Currency Usage**
**Status: ✅ All Use Currency Context**
All customer pages use `useFormatCurrency()` hook which uses `CurrencyContext`:
-`BookingDetailPage.tsx`
-`BookingSuccessPage.tsx`
-`MyBookingsPage.tsx`
-`RoomDetailPage.tsx`
-`FullPaymentPage.tsx`
-`PaymentConfirmationPage.tsx`
-`InvoicePage.tsx`
-`GroupBookingPage.tsx`
-`DashboardPage.tsx`
**Currency Source:** `CurrencyContext``localStorage.getItem('currency')` → Falls back to 'VND'
---
### 7. **Content Pages - Currency Usage**
**Status: ✅ All Use Currency Context**
-`HomePage.tsx` - Uses `useFormatCurrency()` for service prices
-`ServicesPage.tsx` - Uses `useFormatCurrency()` for service prices
-`ServiceDetailPage.tsx` - Uses `useFormatCurrency()` for service prices
---
### 8. **PaymentResultPage** (`Frontend/src/pages/customer/PaymentResultPage.tsx`)
**Status: ⚠️ Uses Settings with Hardcoded Fallbacks**
- ✅ Uses `useCompanySettings()` hook
-**Hardcoded fallbacks:**
- Email: `'support@hotel.com'`
- Phone: `'1900 xxxx'`
**Recommendation:** Remove hardcoded fallbacks.
---
### 9. **Auth Components**
**Status: ⚠️ Mixed Usage**
**ForgotPasswordModal:**
- ✅ Uses `settings.company_email || 'support@hotel.com'` (has fallback)
**Other Auth Components:**
- ❌ Only use placeholder text in form fields (acceptable for UX)
---
## ❌ Pages with Hardcoded Values
### 1. **PaymentConfirmationPage** (`Frontend/src/pages/customer/PaymentConfirmationPage.tsx`)
**Status: ❌ Hardcoded Bank Details**
**Hardcoded Values:**
- Bank: `'Vietcombank (VCB)'`
- Account Number: `'0123456789'`
- Account Holder: `'KHACH SAN ABC'`
**Recommendation:** Add bank details to Settings and make them configurable from admin.
---
## 📊 Summary Statistics
| Category | Total | Uses Settings | Hardcoded Fallbacks | Hardcoded Values |
|----------|-------|---------------|---------------------|------------------|
| **Email/Phone/Address** | 15+ pages | 12 pages | 3 pages | 0 pages |
| **Currency** | 12+ pages | 12 pages | 0 pages | 0 pages |
| **Bank Details** | 1 page | 0 pages | 0 pages | 1 page |
| **Logo** | 2 components | 2 components | 0 | 0 |
---
## 🔧 Issues Found
### High Priority
1. **PaymentConfirmationPage** - Bank details are hardcoded
- Should be added to Settings
- Should be configurable from admin
### Medium Priority
2. **Header Component** - Hardcoded fallback phone/email
- Should use empty string or null instead of fake values
3. **ContactPage** - Hardcoded fallback text instead of actual values
- Should show actual phone/email/address or nothing
4. **PaymentResultPage** - Hardcoded fallback support contact
- Should use settings or show nothing
### Low Priority
5. **Auth Components** - Placeholder text in forms (acceptable for UX)
---
## ✅ What's Working Well
1. **Currency System** - Fully centralized via `CurrencyContext`
- All pages use `useFormatCurrency()` hook
- Currency stored in localStorage
- Falls back to 'VND' if not set
2. **Footer Component** - Perfect implementation
- Uses settings without hardcoded fallbacks
- Shows nothing if settings not available
3. **AboutPage** - Perfect implementation
- Uses settings without hardcoded fallbacks
4. **Policy Pages** - Good implementation
- Only show email link if available
---
## 🛠️ Recommendations
### Immediate Actions
1. **Add Bank Details to Settings**
- Add fields: `bank_name`, `bank_account_number`, `bank_account_holder`
- Update PaymentConfirmationPage to use settings
- Add admin controls for bank details
2. **Remove Hardcoded Fallbacks**
- Header: Remove `'+1 (234) 567-890'` and `'info@luxuryhotel.com'`
- ContactPage: Remove fallback text, show actual values or nothing
- PaymentResultPage: Remove `'support@hotel.com'` and `'1900 xxxx'`
### Future Enhancements
3. **Currency Settings Integration**
- Consider adding default currency to Company Settings
- Allow admin to set default currency for the platform
4. **Settings Validation**
- Add validation to ensure critical settings (email, phone) are set
- Show warnings in admin if settings are missing
---
## 📝 Notes
- Currency is well-implemented via CurrencyContext
- Most pages correctly use `useCompanySettings()` hook
- Main issues are hardcoded fallback values that should be removed
- Bank details need to be added to settings system
- Placeholder text in form fields is acceptable and doesn't need changes