analysis/04-functional-spec/ad-campaigns-module.md
Ad Campaigns
Ad Campaigns Module – Functional Specification
1. Purpose
The Ad Campaigns Module allows providers to create paid promotional campaigns for their trips. A campaign is linked to a single trip and requires immediate online payment to activate it.
This module manages:
- Creating an ad campaign
- Setting budget and campaign duration
- Payment flow
- Campaign lifecycle (scheduled, active, stopped, ended)
- Reporting financial outcomes
4. Ad Campaign Entity Fields
| Field | Type | Notes |
|---|---|---|
| id | PK | — |
| provider_id | FK | — |
| trip_id | FK | Trip linked to campaign |
| budget | Decimal | Budget amount |
| spent | Decimal | Total spent amount |
| start_date | Date | — |
| end_date | Date | — |
| status | Enum | Active / Scheduled / Paused / Ended |
| payment_transaction_id | FK | mandatory — campaign cannot exist without payment |
| created_at | timestamp | — |
| updated_at | timestamp | — |
5. Statuses
| UI Label | Enum | Meaning |
|---|---|---|
| Active | ACTIVE | Campaign running within date range |
| Scheduled | SCHEDULED | Starts in the future |
| Paused | PAUSED | Manually paused by provider |
| Ended | ENDED | End date passed |
6. Business Rules
BR-1. Mandatory payment to create a campaign
The UI forces payment immediately during campaign creation. No 'Save Draft', no campaign record unless payment is successful.
BR-2. Budget must be selected via slider
Budget is user-selected using a slider component. The final chosen number is stored as budget.
BR-3. Campaign can only target one trip
trip_id is required. Trips must be owned by provider and status = Active.
BR-4. Status lifecycle controlled by date + manual flags
- If now < start_date → SCHEDULED
- If start_date <= now <= end_date → ACTIVE
- If manually paused → PAUSED
- If now > end_date → ENDED
BR-5. Spent amount is read-only
Provider cannot modify spent — it's calculated by the advertising backend.
BR-6. Editing campaign
Only allowed fields: Dates, Budget, Pause/Resume. Trip cannot be changed after creation.
BR-7. Deleting campaign
Deletion not allowed if payment transaction exists AND is irreversible, or campaign is currently active. Soft-delete recommended.
BR-8. VAT inconsistency ⚠️
UI shows VAT = 20% for ad campaigns. Booking VAT = 15%. This is flagged as an open question.
7. Actions & Behaviors
A-1. Create Ad Campaign
Modal sections:
- Select Trip – dropdown
- Campaign Duration – start_date + end_date
- Set your campaign budget – slider
- Your ad preview – preview card
- Payment details – card entry fields
- Payment summary – budget + VAT 20% + total
- Pay [amount] – action creates campaign upon payment
Payment options:
- Credit Card / Mada
- STC Pay
- SADAD
A-2. Edit Campaign
Provider can modify: Dates, Budget, Pause/Resume. Preview updates accordingly.
A-3. Delete Campaign
Triggered from table row. Confirmation modal required. Blocks if campaign active or financial lock exists.
8. Validation Rules
Required fields
- trip_id
- start_date
- end_date
- budget
- card details (if payment via card)
Validation
- Dates: end_date > start_date
- Budget > 0
- Card format (Luhn)
- CVV (3–4 digits)
- Name on card required
9. Error Cases
| Case | Message |
|---|---|
| Missing required fields | Please complete all required fields |
| Invalid card | Card details are incorrect |
| Payment failed | Payment failed, please try again |
| Budget too low | Please select a valid budget |
| Attempt to delete active campaign | Cannot delete an active campaign |
| Trip not found | Cannot select this trip |
11. Cross-Module Relations
- Trip Module → campaign belongs to one trip
- Financial Reports Module → VAT, totals, and transaction appear in reports
- Payments Module → payment transaction generated
- Provider Module → provider_id ensures ownership scope