Files
WooNooW/.agent/plans/affiliate-module.md
Dwindi Ramadhana 40aee67c46 feat: Implement A4 invoice layout and hide Label for virtual orders
Invoice:
- Enhanced A4-ready layout with proper structure
- Store header with invoice number
- Billing/shipping address sections
- Styled items table with alternating rows
- Totals summary with conditional display
- Thank you footer

Label:
- Label button now hidden for virtual-only orders
- Uses existing isVirtualOnly detection

Print CSS:
- Added @page A4 size directive
- Print-color-adjust for background colors
- 20mm padding for proper margins

Documentation:
- Updated subscription module plan (comprehensive)
- Updated affiliate module plan (comprehensive)
- Created shipping label standardization plan
2026-01-05 19:16:13 +07:00

7.2 KiB

Affiliate Module Plan

Overview

Referral tracking with hybrid customer/affiliate roles, integrated as a core plugin module.


Module Architecture

Core Features

  • Affiliate registration: Customers can become affiliates
  • Approval workflow: Manual or auto-approval of affiliates
  • Unique referral links/codes: Each affiliate gets unique tracking
  • Commission tracking: Track referrals and calculate earnings
  • Tiered commission rates: Different rates per product/category/affiliate level
  • Payout management: Track and process affiliate payouts
  • Affiliate dashboard: Self-service stats and link generator

Hybrid Roles

  • A customer can also be an affiliate
  • No separate user type; affiliate data linked to existing user
  • Affiliates can still make purchases (self-referral rules configurable)

Database Schema

Table: woonoow_affiliates

CREATE TABLE woonoow_affiliates (
  id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
  user_id BIGINT UNSIGNED NOT NULL UNIQUE,
  status ENUM('pending', 'active', 'rejected', 'suspended') DEFAULT 'pending',
  referral_code VARCHAR(50) NOT NULL UNIQUE,
  commission_rate DECIMAL(5,2) DEFAULT NULL,  -- Override global rate
  tier_id BIGINT UNSIGNED DEFAULT NULL,
  payment_email VARCHAR(255) DEFAULT NULL,
  payment_method VARCHAR(50) DEFAULT NULL,
  total_earnings DECIMAL(15,2) DEFAULT 0,
  total_unpaid DECIMAL(15,2) DEFAULT 0,
  total_paid DECIMAL(15,2) DEFAULT 0,
  referral_count INT UNSIGNED DEFAULT 0,
  created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
  updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  INDEX idx_user_id (user_id),
  INDEX idx_status (status),
  INDEX idx_referral_code (referral_code)
);

Table: woonoow_referrals

CREATE TABLE woonoow_referrals (
  id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
  affiliate_id BIGINT UNSIGNED NOT NULL,
  order_id BIGINT UNSIGNED NOT NULL,
  customer_id BIGINT UNSIGNED DEFAULT NULL,
  subtotal DECIMAL(15,2) NOT NULL,
  commission_rate DECIMAL(5,2) NOT NULL,
  commission_amount DECIMAL(15,2) NOT NULL,
  status ENUM('pending', 'approved', 'rejected', 'paid') DEFAULT 'pending',
  referral_type ENUM('link', 'code', 'coupon') DEFAULT 'link',
  ip_address VARCHAR(45) DEFAULT NULL,
  user_agent TEXT,
  created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
  approved_at DATETIME DEFAULT NULL,
  paid_at DATETIME DEFAULT NULL,
  INDEX idx_affiliate (affiliate_id),
  INDEX idx_order (order_id),
  INDEX idx_status (status)
);

Table: woonoow_payouts

CREATE TABLE woonoow_payouts (
  id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
  affiliate_id BIGINT UNSIGNED NOT NULL,
  amount DECIMAL(15,2) NOT NULL,
  method VARCHAR(50) DEFAULT NULL,
  reference VARCHAR(255) DEFAULT NULL,  -- Bank ref, PayPal transaction, etc.
  status ENUM('pending', 'processing', 'completed', 'failed') DEFAULT 'pending',
  notes TEXT,
  created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
  completed_at DATETIME DEFAULT NULL,
  INDEX idx_affiliate (affiliate_id),
  INDEX idx_status (status)
);

Table: woonoow_affiliate_tiers (Optional)

CREATE TABLE woonoow_affiliate_tiers (
  id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
  name VARCHAR(100) NOT NULL,
  commission_rate DECIMAL(5,2) NOT NULL,
  min_referrals INT UNSIGNED DEFAULT 0,  -- Auto-promote at X referrals
  min_earnings DECIMAL(15,2) DEFAULT 0,   -- Auto-promote at X earnings
  created_at DATETIME DEFAULT CURRENT_TIMESTAMP
);

Backend Structure

includes/Modules/Affiliate/
├── AffiliateModule.php      # Bootstrap, hooks, tracking
├── AffiliateManager.php     # Core logic
├── ReferralTracker.php      # Track referral cookies/links
└── AffiliateSettings.php    # Settings schema

includes/Api/AffiliatesController.php  # REST endpoints

AffiliateManager Methods

- register($user_id)              # Register user as affiliate
- approve($affiliate_id)          # Approve pending affiliate
- reject($affiliate_id, $reason)  # Reject application
- suspend($affiliate_id)          # Suspend affiliate
- track_referral($order, $affiliate) # Create referral record
- calculate_commission($order, $affiliate) # Calculate earnings
- approve_referral($referral_id)  # Approve pending referral
- create_payout($affiliate_id, $amount) # Create payout request
- process_payout($payout_id)      # Mark payout complete
- get_affiliate_stats($affiliate_id) # Dashboard stats

Referral Tracking

  1. Affiliate shares link: yourstore.com/?ref=CODE
  2. ReferralTracker sets cookie: wnw_ref=CODE (30 days default)
  3. On checkout, check cookie and link to affiliate
  4. On order completion, create referral record

REST API Endpoints

Admin Endpoints

GET    /affiliates                 # List affiliates
GET    /affiliates/{id}            # Affiliate details
PUT    /affiliates/{id}            # Update affiliate
POST   /affiliates/{id}/approve    # Approve affiliate
POST   /affiliates/{id}/reject     # Reject affiliate
GET    /affiliates/referrals       # All referrals
GET    /affiliates/payouts         # All payouts
POST   /affiliates/payouts/{id}/complete # Complete payout

Customer/Affiliate Endpoints

GET    /my-affiliate               # Check if affiliate
POST   /my-affiliate/register      # Register as affiliate
GET    /my-affiliate/stats         # Dashboard stats
GET    /my-affiliate/referrals     # My referrals
GET    /my-affiliate/payouts       # My payouts
POST   /my-affiliate/payout-request # Request payout
GET    /my-affiliate/links         # Generate referral links

Admin SPA

Affiliates List (/marketing/affiliates)

  • Table: Name, Email, Status, Referrals, Earnings, Actions
  • Filters: Status, Date range
  • Actions: Approve, Reject, View

Affiliate Detail (/marketing/affiliates/:id)

  • Affiliate info card
  • Stats summary
  • Referrals list
  • Payouts history
  • Action buttons

Referrals List (/marketing/affiliates/referrals)

  • All referrals across affiliates
  • Filters: Status, Affiliate, Date

Payouts (/marketing/affiliates/payouts)

  • Payout requests
  • Process payouts
  • Payment history

Customer SPA

Become an Affiliate (/my-account/affiliate)

  • Registration form (if not affiliate)
  • Dashboard (if affiliate)

Affiliate Dashboard

  • Stats: Total Referrals, Pending, Approved, Earnings
  • Referral link generator
  • Recent referrals
  • Payout request button

My Referrals

  • List of referrals with status
  • Commission amount

My Payouts

  • Payout history
  • Pending amount
  • Request payout form

Settings Schema

return [
  'enabled' => true,
  'registration_type' => 'open',  // open, approval, invite
  'auto_approve' => false,
  'default_commission_rate' => 10,  // 10%
  'commission_type' => 'percentage',  // percentage, flat
  'cookie_duration' => 30,  // days
  'min_payout_amount' => 50,
  'payout_methods' => ['bank_transfer', 'paypal'],
  'allow_self_referral' => false,
  'referral_approval' => 'auto',  // auto, manual
  'approval_delay_days' => 14,  // Wait X days before auto-approve
];

Implementation Priority

  1. Database tables and AffiliateManager
  2. ReferralTracker (cookie-based tracking)
  3. Order hook to create referrals
  4. Admin SPA affiliates management
  5. Customer SPA affiliate dashboard
  6. Payout management
  7. Tier system (optional)