# Comparison Offers Feature Documentation ## Overview The comparison offers feature requires users to provide at least 3 comparison offers for each cost position in their application. This ensures transparency and cost-effectiveness in funding requests. Users can alternatively provide a justification if comparison offers are not applicable for specific cost positions. ## Features - **3 Offers Requirement**: Each cost position must have at least 3 comparison offers - **Justification Alternative**: Users can mark that no offers are required and provide a detailed justification - **Attachment Support**: Each offer can be linked to an uploaded attachment (e.g., quotes, invoices) - **Visual Indicators**: Cost positions without sufficient offers are highlighted with warning icons - **Status Tracking**: Real-time status display showing offer count and completion status ## Database Schema ### `comparison_offers` Table Stores comparison offers for cost positions: - `id` (INT, PRIMARY KEY) - Unique identifier - `application_id` (INT) - References the application - `cost_position_index` (INT) - Index of the cost position in the costs array - `supplier_name` (VARCHAR 255) - Name of the supplier/vendor - `amount` (INT) - Offer amount in cents - `description` (TEXT) - Optional description of the offer - `url` (VARCHAR 500) - Optional URL to offer document or webpage - `attachment_id` (INT) - Optional reference to an attachment - `created_at` (DATETIME) - Creation timestamp - `updated_at` (DATETIME) - Last update timestamp ### `cost_position_justifications` Table Stores justifications for positions without offers: - `id` (INT, PRIMARY KEY) - Unique identifier - `application_id` (INT) - References the application - `cost_position_index` (INT) - Index of the cost position - `no_offers_required` (INT) - Boolean flag (0/1) - `justification` (TEXT) - Required explanation when no_offers_required is 1 - `created_at` (DATETIME) - Creation timestamp - `updated_at` (DATETIME) - Last update timestamp ## API Endpoints ### Create Comparison Offer `POST /api/applications/{pa_id}/costs/{cost_position_index}/offers` - Request body: ```json { "supplier_name": "Supplier GmbH", "amount": 1500.50, "description": "Optional description", "url": "https://beispiel.de/angebot.pdf", "attachment_id": 123 } ``` - Returns: ComparisonOfferResponse with offer details ### Get Cost Position Offers `GET /api/applications/{pa_id}/costs/{cost_position_index}/offers` - Returns: CostPositionOffersResponse with all offers and justification info ### Delete Comparison Offer `DELETE /api/applications/{pa_id}/costs/{cost_position_index}/offers/{offer_id}` - Removes a specific offer ### Update Cost Position Justification `PUT /api/applications/{pa_id}/costs/{cost_position_index}/justification` - Request body: ```json { "no_offers_required": true, "justification": "Detailed explanation why no offers are needed..." } ``` ## Frontend Components ### ComparisonOffersDialog Main dialog for managing offers for a cost position: - Add/remove comparison offers - Add URL links to online offers - Link attachments to offers (either URL or attachment required) - Mark position as not requiring offers - Provide justification when needed ### CostPositionsList Enhanced cost positions list with offer status: - Visual indicators for offer status - Warning icons for incomplete positions - Quick access to manage offers - Real-time status updates ## User Interface ### Status Indicators - ✅ **Green checkmark**: Position has 3+ offers - ℹ️ **Blue info icon**: Position marked as not requiring offers (with justification) - ⚠️ **Yellow warning**: Position needs more offers or justification - 🔄 **Loading spinner**: Status being loaded ### Validation Rules 1. Each cost position must have either: - At least 3 comparison offers, OR - Be marked as "no offers required" with a justification (min. 10 characters) 2. Cost positions without sufficient offers are highlighted in the list 3. Offers must include: - Supplier name (required, must be unique per cost position) - Amount (required, must be greater than 0) - Either URL or attachment (at least one required) - Description (optional) 4. Duplicate suppliers: Each supplier can only have one offer per cost position 5. URL format: Must be a valid HTTP/HTTPS URL (protocol is auto-added if missing) 6. Amount format: Accepts both comma and period as decimal separator ## Migration To add the comparison offers tables to your database: ```sql mysql -u your_user -p your_database < src/migrations/add_comparison_offers_tables.sql mysql -u your_user -p your_database < src/migrations/add_url_to_comparison_offers.sql ``` ## Usage Example ### In Cost Positions List ```tsx ``` ### Managing Offers 1. Click "Angebote" button next to any cost position 2. In the dialog: - Add up to 5 comparison offers - Link existing attachments to offers - OR check "no offers required" and provide justification 3. Save changes ## Best Practices 1. **Encourage Early Collection**: Remind users to collect offers before starting the application 2. **Clear Instructions**: Provide examples of valid justifications for positions without offers 3. **Attachment Organization**: Name attachment files clearly to easily link them to offers 4. **Regular Validation**: Check offer status before submission ## Error Handling - **Duplicate Suppliers**: Shows user-friendly error message when trying to add the same supplier twice - **Invalid URLs**: Automatically prepends https:// if missing, validates format - **Invalid Amounts**: Real-time validation with support for German number format (comma as decimal) - **Missing Data**: Clear error messages when required fields are missing ## Future Enhancements 1. **Bulk Import**: Import multiple offers from CSV/Excel 2. **Templates**: Save common suppliers for quick reuse 3. **Price Comparison**: Automatic highlighting of best offer 4. **History Tracking**: Track changes to offers over time 5. **Export Function**: Export all offers as PDF/Excel report 6. **Smart Validation**: Detect duplicate suppliers or suspicious patterns 7. **URL Validation**: Automatic checking of URL availability and validity 8. **Screenshot Capture**: Automatic capture of web-based offers for archival