# Contractor for Industry Backend - Referral and Coupon System

This document outlines the comprehensive referral and coupon system integrated into the Contractor for Industry backend. The system is designed with modularity, scalability, and data integrity in mind, using separate Mongoose schemas to manage referrals and coupons without impacting other models (e.g., subscriptions, profiles). All schemas reference the `Contractor` model for relationships, ensuring referential integrity via ObjectId references and proper indexing for efficient queries.

Key principles:

- **Data Integrity**: Unique indexes on codes/links prevent duplicates; validation middleware (not implemented here) should enforce business rules like expiration checks.
- **Scalability**: Indexes on frequently queried fields (e.g., codes, contractors, dates) support high-volume lookups. Use aggregation pipelines for reporting (e.g., referral analytics).
- **Maintainability**: Schemas are self-contained; logic for generation/redemption is outlined for implementation in controllers (e.g., referralController.js).

## Schema Definitions

### 1. Contractor Referral (Updated in `contractorModel.js`)

This evolves the existing `Contractor` schema to track referral relationships explicitly. It adds referral fields directly to the core contractor profile for better modularity, separating service-specific details. The `referredBy` field attributes new contractors to their referrer, with core referral tracking (`referralCode`, `successfulReferrals`, `codeCreatedAt`).

**Fields** (Referral-specific additions to existing Contractor schema):

- `referralCode`: String (unique: true, index: true) - Unique code generated for sharing (e.g., via short UUID or random string).
- `successfulReferrals`: Number (default: 0) - Count of successful referrals (incremented on new contractor registration via link).
- `codeCreatedAt`: Date (default: Date.now) - Timestamp for code creation.
- `referredBy`: ObjectId (ref: "Contractor", required: false) - References the contractor who referred this one, enabling attribution and tree-like referral structures.

**Other Existing Fields** (for context, non-referral):

- `userType`, `email`, `password`, `companyName`, `companyAddress`, etc. - Core profile and authentication fields.
- `isCompltedProfile`, `isOtpVerified`, `isAccountDeleted`, `isSubscribe`, etc. - Status and subscription flags.

**Indexes**:

- `referralCode`: Unique compound index for fast lookups and collision prevention.
- Implicit timestamps index for auditing.

**Relationships**:

- Self-references via `referredBy` for referral chains (e.g., `populate('referredBy')` to trace referrers).
- On successful referral, increment `successfulReferrals` in the referrer's document atomically (use `findOneAndUpdate` with `$inc`).

**Uniqueness and Collision Prevention**:

- Generate `referralCode` using a secure random string (e.g., 8-10 alphanumeric chars via `crypto.randomBytes` or shortid library).
- Before saving, check for existence: `if (await Contractor.findOne({ referralCode })) { regenerate; }`.
- MongoDB's unique index enforces integrity; handle duplicate key errors by regenerating.

### 2. Referral Link (`referralLinkModel.js`)

A dedicated schema for shareable referral links, decoupling link management from the contractor service for scalability (e.g., multiple links per contractor).

**Fields**:

- `link`: String (required: true, unique: true, index: true) - Full shareable URL (e.g., `https://app.com/register?ref=ABC123`).
- `contractor`: ObjectId (ref: "Contractor", required: true) - The contractor owning this link.
- `code`: String (required: true, unique: true, index: true) - Short code extracted from the link for quick validation.
- `uses`: Number (default: 0) - Current usage count.
- `maxUses`: Number (default: 1) - Limit per link (e.g., one-time use for exclusivity).
- `expiresAt`: Date (default: null) - Optional expiration (null for indefinite).
- `createdAt`: Date (default: Date.now) - Link creation timestamp.

**Indexes**:

- `link` and `code`: Unique for direct lookups.
- Compound: `{ contractor: 1, createdAt: -1 }` for contractor-specific queries (e.g., list my links).

**Relationships**:

- Populates `contractor` for ownership verification.
- On registration, validate link, increment `uses`, and set `referredBy` in the new `Contractor`.

### 3. Coupon Code (`couponCodeModel.js`)

Manages coupons generated automatically at referral milestones, with redemption tracking for discounts (e.g., on subscriptions).

**Fields**:

- `code`: String (required: true, unique: true, index: true) - Unique coupon code (e.g., "REF5OFF").
- `contractor`: ObjectId (ref: "Contractor", required: true) - Contractor who earned the coupon.
- `discountValue`: Number (required: true) - Discount amount (e.g., 10 for 10%).
- `discountType`: String (enum: ["percentage", "fixed"], required: true) - Type of discount.
- `expiresAt`: Date (required: true) - Validity end date (e.g., 30 days from generation).
- `maxUses`: Number (default: 1) - Total redemptions allowed.
- `currentUses`: Number (default: 0) - Current redemptions.
- `isActive`: Boolean (default: true) - Toggled on expiration or max uses.
- `milestone`: String (required: true) - Trigger (e.g., "5_referrals", "10_referrals").
- `generatedAt`: Date (default: Date.now) - Generation timestamp.

**Indexes**:

- `code`: Unique for redemption checks.
- Compound: `{ contractor: 1, generatedAt: -1 }` for listing coupons.
- Compound: `{ isActive: 1, expiresAt: 1 }` for active/expired queries.

**Relationships**:

- Populates `contractor` for ownership.
- Integrates with subscription redemption (e.g., apply discount in `subscriptionController`).

## Automated Coupon Generation Logic

Coupons are generated server-side when `successfulReferrals` hits milestones (e.g., 5, 10, 20). Implement in a post-save hook or cron job on `Contractor`:

1. After incrementing `successfulReferrals` (on new registration):
   - Check if count matches milestone (e.g., if `successfulReferrals % 5 === 0 && > 0`).
   - Generate unique `code` (e.g., `REF${milestone}OFF` + random suffix; check uniqueness).
   - Create `CouponCode` document with:
     - `milestone`: e.g., `${successfulReferrals}_referrals`.
     - `discountValue`: Tiered (e.g., 5 referrals = 10% off, 10 = 20% off).
     - `discountType`: "percentage".
     - `expiresAt`: `Date.now() + 30 days`.
     - `maxUses`: 1 (personal use) or higher for sharing.
   - Notify contractor via email/push (using `notificationController`).

Use transactions for atomicity: Update `successfulReferrals` and create coupon in one operation to prevent race conditions.

**Milestone Examples**:

- 5 referrals: 10% off next subscription.
- 10 referrals: 20% off + free month.
- Scale discounts based on business rules.

## Usage Instructions

### Generating and Sharing a Referral Link

1. **Contractor Login**: Authenticated contractors access their profile via `/profile` endpoint.
2. **Generate Link**: Call `POST /referral/generate` (implement in referralController):
   - Auto-generate `referralCode` if none exists (ensure uniqueness).
   - Create `ReferralLink`: `link = baseUrl + '/register?ref=' + code`, `maxUses = 10` (configurable).
   - Save and return link.
3. **Share**: Contractors share via social/email. Track shares optionally via analytics.

### Registering with a Referral Link

1. **New User Access**: Visit registration page with `?ref=CODE` query param.
2. **Validation**: On submit (`POST /auth/register`):
   - Extract `code` from query.
   - Find `ReferralLink` by `code`; check `uses < maxUses`, `!expiresAt || !expired`, `isActive`.
   - If valid: Increment `uses`; create new `Contractor` and `ContractorService` with `referredBy = link.contractor`.
   - Increment referrer's `successfulReferrals`.
   - Trigger milestone check for coupon generation.
3. **Attribution**: Store `referredBy` for reporting; deny if invalid link (return error).

### Coupon Code Redemption

1. **Access Coupon**: Contractors view earned coupons via `GET /coupons/my` (filter by `contractor`, `isActive: true`).
2. **Redeem**: During subscription purchase (`POST /subscription/create`):
   - Submit `code`.
   - Validate: Find `CouponCode` by `code`; check `currentUses < maxUses`, `!expiresAt || !expired`, `isActive`.
   - If valid: Apply discount (e.g., `total = total * (1 - discountValue/100)` for percentage).
   - Increment `currentUses`; deactivate if `maxUses` reached or expired (set `isActive: false`).
   - Log redemption in audit trail (optional new schema).
3. **Limitations**: One-time use per coupon; expires after period; non-transferable (tied to contractor).

### Querying and Managing Referral Links and Coupons

- **Admin Queries** (via admin routes, e.g., `GET /admin/referrals`):
  - List all: `ReferralLink.find({}).populate('contractor')`.
  - Contractor-specific: `ReferralLink.find({ contractor: id }).sort({ createdAt: -1 })`.
  - Stats: Aggregate `$group` by contractor for total referrals/uses.
  - Coupons: `CouponCode.find({ isActive: true }).populate('contractor')`; filter by milestone.
- **Contractor Queries**:
  - My links: `GET /referral/my-links`.
  - My coupons: `GET /coupons/my` (as above).
- **Management**:
  - Deactivate link: `PATCH /referral/:id/deactivate` (set expiresAt).
  - Revoke coupon: `PATCH /coupons/:id/revoke` (set isActive: false).
  - Use MongoDB views or aggregations for dashboards (e.g., referral tree).

For implementation, add controllers/routes (e.g., `referralController.js`, `couponController.js`) and middleware for validation. Test with sample data to ensure integrity (e.g., duplicate code handling). Scale by sharding on `contractor` if volume grows.
