# Multi-Location Job Posting Feature

> **Feature Flag**: `FEATURE_MULTI_LOCATION_JOB_POST` (default: `false`)
> **Created**: 2026-04-08
> **Status**: Development complete, not yet deployed to PROD

---

## 1. Feature Overview

Allows recruiters to post the same job across multiple locations in a single submission. Each location creates a **separate `company_jobs` record** with its own Job ID, child table rows, and Elasticsearch index entry.

### User Flow:
1. On the Add Job page, recruiter sees a "Posting Type" toggle: **Single Location** (default) / **Multiple Locations**
2. Selecting "Multiple Locations":
   - Location field changes to a multi-add input with Google Places autocomplete
   - JD file upload is hidden (rich-text only)
   - A `{{location}}` variable helper appears near the JD editor
3. Recruiter adds 2-10 locations, writes JD with optional `{{location}}` placeholder
4. On submit, one job is created per location with `{{location}}` replaced in the JD
5. Result modal shows how many jobs were created (supports partial failure)

---

## 2. Architecture

### Feature Flag
- **Constant**: `FEATURE_MULTI_LOCATION_JOB_POST` in `app/config/config.php`
- **Method**: `FeatureFlags::multiLocationJobPost()` in `app/helpers/FeatureFlags.php`
- **Default**: `false` — all multi-location UI and backend logic is hidden when off
- **Enable**: Set to `true` in config.php (gitignored, deployed via SCP)
- **Rollback**: Set to `false` — feature disappears instantly, no code changes needed

### Service Class
`MultiLocationJobService` (`app/Services/MultiLocationJobService.php`):
- Follows `JobActionService` pattern (same codebase)
- Self-contained, no dependency on `$_POST` or `$_SESSION` (except CleverTap which reads `$_SESSION['mobile']`)
- Can be called from any entry point (web form, API, CLI)
- Creates independent jobs per location (no transaction rollback on partial failure)

### Data Flow
```
Form Submit (multi mode)
  → public/add_job.php detects location_mode=multi
  → Delegates to MultiLocationJobService::createMultiLocationJobs()
  → For each location:
      → INSERT company_jobs (with {{location}} replaced in JD)
      → INSERT company_jobs_location
      → INSERT company_jobs_types, _education, _skills, _soft_skills, _benefits, _supplement_pay, _questions
      → RabbitMQ: pushJobUpdate + pushAutoMatch
      → CleverTap: postjob_published event
  → Returns JSON: { success, created_jobs, failed_jobs, message }
  → Frontend shows result modal
```

---

## 3. Files Changed

### Created
| File | Purpose |
|------|---------|
| `app/Services/MultiLocationJobService.php` | Core service: creates jobs per location, inserts child tables, syncs ES |

### Modified
| File | What Changed | Why |
|------|-------------|-----|
| `app/config/config.php` | Added `FEATURE_MULTI_LOCATION_JOB_POST` constant | Feature flag |
| `app/helpers/FeatureFlags.php` | Added `multiLocationJobPost()` method | Feature flag check |
| `public/add_job.php` | Added `location_mode` parsing, screening question parsing moved earlier, multi-location branch that delegates to service, JSON response path | Backend handler for multi-location |
| `app/views/add_job.php` | Added: radio toggle, multi-location container, `{{location}}` helper, file upload wrapper, multi-location JS functions, updated validation/confirmation/submit, result modal | Frontend UI and logic |

---

## 4. Deployment Checklist

When ready to ship to PROD, deploy these files via SCP:

```bash
PEM="/Users/apple/Projects/kaam-ec2/kaabil-cc-key-pair.pem"
EC2="ubuntu@65.1.107.228"
REMOTE="/var/www/tools.kaabil.cc/recruiter"

# 1. New file
scp -i "$PEM" recruiter/app/Services/MultiLocationJobService.php "$EC2:/tmp/MultiLocationJobService.php"
ssh -i "$PEM" "$EC2" "sudo cp /tmp/MultiLocationJobService.php $REMOTE/app/Services/ && rm /tmp/MultiLocationJobService.php"

# 2. Modified files
scp -i "$PEM" recruiter/app/helpers/FeatureFlags.php "$EC2:/tmp/FeatureFlags.php"
scp -i "$PEM" recruiter/public/add_job.php "$EC2:/tmp/add_job_public.php"
scp -i "$PEM" recruiter/app/views/add_job.php "$EC2:/tmp/add_job_view.php"

ssh -i "$PEM" "$EC2" "
  sudo cp /tmp/FeatureFlags.php $REMOTE/app/helpers/
  sudo cp /tmp/add_job_public.php $REMOTE/public/add_job.php
  sudo cp /tmp/add_job_view.php $REMOTE/app/views/add_job.php
  sudo chown -R www-data:www-data $REMOTE/
  rm /tmp/FeatureFlags.php /tmp/add_job_public.php /tmp/add_job_view.php
"

# 3. Enable feature flag in PROD config (SCP only - gitignored)
# Edit app/config/config.php on PROD and set:
# define('FEATURE_MULTI_LOCATION_JOB_POST', true);
```

---

## 5. Database

**No schema changes required.** All existing tables support this feature.

### Tables Used
| Table | Role | Per-Job? |
|-------|------|----------|
| `company_jobs` | Main job record | Yes (1 row per location) |
| `company_jobs_location` | Job location with lat/lng | Yes (1 row per job) |
| `company_jobs_types` | Full-time/Part-time/Internship | Yes |
| `company_jobs_education` | Education requirement | Yes |
| `company_jobs_skills` | Hard skills | Yes (N rows per job) |
| `company_jobs_soft_skills` | Soft skills | Yes (N rows per job) |
| `company_jobs_benefits` | Benefits | Yes (N rows per job) |
| `company_jobs_supplement_pay_offer` | Supplement pay | Yes (N rows per job) |
| `company_jobs_questions` | Screening questions | Yes (N rows per job) |

---

## 6. Testing Guide

### Prerequisites
```php
// In app/config/config.php (local only)
define('FEATURE_MULTI_LOCATION_JOB_POST', true);
```

### Test Cases
1. **Flag off**: Load add_job.php — no radio toggle visible
2. **Flag on + Single**: Post single job — identical to current behavior
3. **Flag on + Multi**: Switch to Multiple, add 3 locations with `{{location}}` in JD, submit
   - Verify 3 jobs in DB with different locations and replaced JD
4. **Validation**: Try submitting with <2 locations — should show error
5. **Partial failure**: N/A for normal testing (each job is independent)
6. **Mode switching**: Toggle between Single/Multi — verify state clears correctly

---

## 7. Known Limitations

- **Max 10 locations** per submission (enforced in JS and backend)
- **Rich-text JD only** in multi mode (no PDF/DOC/audio upload)
- **`{{location}}` replacement is plain text** — replaces everywhere in the HTML, no escaping
- **No batch edit** — once posted, each job is independent and must be edited separately
- **Local strict mode**: Service includes all NOT NULL columns with defaults for local MySQL compatibility

---

## 8. Rollback

Set the feature flag to `false` on PROD:
```php
define('FEATURE_MULTI_LOCATION_JOB_POST', false);
```
This immediately hides all multi-location UI. No code deployment needed.
Existing jobs created via multi-location are regular `company_jobs` records and are unaffected.
