# Searchmercials v2 — Handoff Report for Finalization

**Generated**: 2026-04-18
**Purpose**: Complete the platform for launch readiness. This report documents the exact current state, what works, what's broken, and what must be built.

---

## Platform Overview

Searchmercials v2 / Vendor Directory is a Laravel 10 multi-tenant B2B marketplace where:
- **Buyers** submit RFQs (Request for Quotes) for services
- **Vendors** pay for platform access (annual plan) and activate service markets (category subscriptions)
- **The platform** matches vendors to buyer requests, facilitates negotiation, and provides verification

**Server**: Bare metal at 148.113.189.152, Ubuntu 22.04, PHP 8.1, MySQL, Apache 2.4.52
**Domain**: beta.vendor.directory (Cloudflare-proxied)

---

## What Currently Works

### Core Systems (Functional)
- Multi-tenant architecture with domain-based routing
- Category taxonomy (78 categories with monthly base prices $10-$50)
- Public category pages with RFQ forms
- Public listing pages with vendor profiles
- User authentication and account management
- Vendor workspace with sidebar navigation

### RFQ Negotiation System (Fully Built)
- Multi-vendor split-panel conversation UI (buyer side)
- Private threads per vendor + broadcast messaging
- Attachment support (files in messages)
- Award/Remove vendor controls
- Read-only closed threads
- Status state machine (open → contacted → won → lost)
- Immutable message audit trail
- 5-second polling for real-time message delivery
- Notification bell with sound, toasts, browser notifications
- Per-RFQ unread badges

### Verification System (Fully Built)
- AI document scanning (OpenAI Vision + Tesseract OCR fallback)
- 3-tier risk scoring (auto-approve / manual review / auto-reject)
- Dynamic field extraction from any document type
- Secretary of State filing support
- Public verification badge modal on listings
- Plan-gated verification (Featured/Premium required for AI review)

### Vendor Plan Billing (Fully Built)
- 3 tiers: Verified ($50/yr), Featured ($150/yr), Premium ($350/yr)
- Stripe subscription mode checkout (real recurring subscriptions)
- Stripe Products + Prices auto-created per plan
- Plan upgrade (immediate with proration)
- Plan downgrade (scheduled for next renewal)
- Plan cancellation (at period end or immediate)
- Plan reactivation (reverse scheduled cancellation)
- Vendor billing center with plan + history + invoices
- Invoice/receipt view (printable)
- Payment receipt emails
- 7 Stripe webhook events handled

### Acquisition Engine (Fully Built)
- DataForSEO vendor discovery
- Email enrichment pipeline
- Conversion scoring (demand + email quality + geo fit = 0-100)
- 3-tier RFQ-driven vendor matching (verified → claimed → scraped)
- Demand-driven invitation emails (4-step sequence)
- Open/click tracking (signed URLs + pixel)
- Activation attribution (claim → verify → paid)
- Behavioral follow-up engine (clicked-not-claimed, claimed-no-response)
- Activation funnel dashboard (by category + geography)

### Communications Hub (Built)
- 19 email templates across 5 categories (Acquisition, Chat, Listings, Billing, Verification)
- Editable per-tenant with variable substitution
- Tenant mail settings (FROM, reply-to, BCC, SendGrid domain)

---

## What Is Broken or Missing

### CRITICAL: Market Activation Flow Does Not Exist

**The single biggest gap.** When a vendor clicks "+ Add market", they get sent to the old onboarding listing creation page, which redirects to plan selection even if they already have a plan.

**What must be built:**

1. **Market Browse Page** (`/admin/vendor/markets/browse`)
   - Shows all available categories the vendor is NOT already active in
   - Each card: category name, description, monthly base price
   - "View details" link per category

2. **Market Detail Page** (`/admin/vendor/markets/{categoryId}`)
   - Full category description
   - Vendor instructions (see below)
   - Pricing table showing monthly/quarterly/annual with savings %
   - "Activate this market" CTA

3. **Market Activation Endpoint**
   - Accepts category ID + chosen billing interval
   - Creates listing + enrollment via `ListingCategoryEnrollmentService::createEnrollment()`
   - Processes payment (Stripe or dev simulate)
   - Redirects to listing/profile editor

**Current broken link**: `vendor/listings/index.blade.php` line 4 points to `route('vendors.onboarding.listing')` — must change to new market browse route.

### CRITICAL: Category `vendor_instructions` Field Missing

The `sm_categories` table has no `vendor_instructions` column. This field is needed for the market detail page to show vendors what a market expects (compliance, quoting guidance, operational notes).

**Schema change needed:**
```sql
ALTER TABLE sm_categories ADD vendor_instructions TEXT NULL AFTER description;
ALTER TABLE sm_categories ADD qualification_notes TEXT NULL AFTER vendor_instructions;
```

### HIGH: Stale UI Labels

Multiple pages still reference "listings" instead of "markets" and show removed features:
- Listing detail/show page headers
- Listing edit page framing
- Various "Free" badge references in code
- Legacy `plan_badge` partial still exists
- Old listing-level billing routes still exist (should redirect)

### HIGH: Stripe Webhook Not Registered

The webhook endpoint exists at `POST /billing/webhook/stripe` but Stripe has not been configured to send events to it. Without this, renewals, failures, and cancellations don't sync.

### MEDIUM: Category Payment Not Fully Wired

The enrollment service's `createEnrollment()` method is fixed and supports intervals, but there's no controller endpoint that:
1. Takes the vendor's market + interval selection
2. Creates the enrollment
3. Creates a Stripe checkout session for the enrollment amount
4. Handles the webhook to activate the enrollment

This needs to be built as part of the market activation flow.

### MEDIUM: Payment Method Update UI

Vendors cannot update their card from the billing center. If a renewal fails, they need to re-enter payment details through a new checkout flow rather than a dedicated card update page.

---

## Exact Current File Structure (Key Files)

### Controllers
```
app/Http/Controllers/Web/VendorPortal/
  VendorPlanController.php          — plan selection, checkout, upgrade, downgrade, cancel
  VendorBillingController.php       — billing center, invoice view
  ListingController.php             — markets (listings) index, show, edit
  VendorVerificationController.php  — verification upload, AI scan, download
  RfqInboxController.php            — vendor RFQ chat, status management
  CategoryUpgradeController.php     — legacy category upgrade (needs update)
  CategoryPaymentController.php     — legacy category payment (needs update)
  VendorMarketController.php        — DOES NOT EXIST (needs creation)

app/Http/Controllers/Web/Account/
  AccountRfqController.php          — buyer RFQ management, multi-vendor chat
  AccountAdvertiseController.php    — vendor roster

app/Http/Controllers/Web/Onboarding/
  SignupController.php              — account + vendor creation
  PlansController.php               — plan selection (uses sm_plans, not sm_listing_plans)
  CheckoutController.php            — Stripe checkout (unified with VendorPlanController flow)
  ListingController.php             — OLD listing creation (should NOT be used for market addition)

app/Http/Controllers/Billing/
  StripeWebhookController.php       — handles 7 Stripe events
```

### Services
```
app/Services/Billing/
  AccountSubscriptionService.php      — create, activate, cancel subscriptions
  StripeCheckoutService.php           — creates Stripe checkout sessions (subscription mode)
  SubscriptionPlanChangeService.php   — upgrade/downgrade via Stripe API
  SubscriptionCancellationService.php — cancel at period end or immediately
  CategoryPaymentService.php          — category transaction management + off-session charging
  BillingInvoiceService.php           — invoice creation + payment recording

app/Services/Listings/
  ListingCategoryEnrollmentService.php — enrollment CRUD (FIXED: pricing methods work, intervals supported)

app/Services/Pricing/
  CategoryPricingService.php          — category-count discounts, pricing snapshots

app/Services/Acquisition/
  VendorConversionScoringService.php  — 3-component scoring
  RfqVendorMatcherService.php         — 3-tier vendor matching
  VendorActivationService.php         — RFQ-triggered activation
  VendorInviteService.php             — demand-driven invitations
  VendorFollowUpService.php           — behavioral follow-ups
  InviteTrackingService.php           — open/click tracking URLs
  VendorActivationAttributionService.php — claim→verify→paid attribution

app/Services/Verification/
  DocumentScannerService.php          — AI vision + OCR extraction
  VerificationAiReviewService.php     — 3-tier risk scoring
  VerificationLifecycleService.php    — verification → go-live lifecycle
```

### Key Database Tables
```
sm_plans                          — vendor plan catalog (Verified/Featured/Premium)
sm_account_subscriptions          — vendor subscriptions (Stripe-backed)
sm_subscription_items             — subscription line items
sm_invoices                       — invoice records
sm_invoice_lines                  — invoice line items
sm_payments                       — payment records
sm_listing_category_enrollments   — category billing contracts (supports month/quarter/year)
sm_listing_category_transactions  — category payment ledger
sm_categories                     — category catalog (base_price set, vendor_instructions MISSING)
sm_rfqs                           — listing-level RFQs
sm_rfq_messages                   — RFQ conversation messages (immutable)
sm_rfq_message_attachments        — message file attachments
sm_vendor_rfq_activations         — acquisition activation audit trail
sm_vendor_leads                   — acquisition lead pool (with scoring fields)
sm_vendor_verifications           — verification records with AI extraction
sm_vendor_invite_events           — acquisition tracking events
```

### Pricing Model
```
Category base_price = monthly rate (stored on sm_categories)
  Monthly:   base × 1,  no discount
  Quarterly: base × 3,  5% commitment discount
  Annual:    base × 12, 10% commitment discount
  
Category-count discount (stacks):
  1 category:    0%
  2-3 categories: 5%
  4-6 categories: 10%
  7+ categories:  15%

Vendor plans are separate annual subscriptions via Stripe.
```

### Stripe Configuration
```
STRIPE_SECRET=sk_test_... (test mode keys active)
STRIPE_PUBLISHABLE_KEY=pk_test_...
STRIPE_WEBHOOK_SECRET=whsec_... (set but not registered in Stripe dashboard)

Handled events:
  checkout.session.completed
  invoice.paid
  invoice.payment_failed
  customer.subscription.updated
  customer.subscription.deleted
  payment_intent.succeeded
  payment_intent.payment_failed
```

---

## Recommended Execution Order

1. **Add `vendor_instructions` + `qualification_notes` columns to categories** (10 min)
2. **Build Market Browse page** (1-2 hours)
3. **Build Market Detail page with pricing** (1-2 hours)
4. **Build Market Activation endpoint with payment** (2-3 hours)
5. **Fix "+ Add market" button to point to browse page** (5 min)
6. **Rename remaining "listing" labels to "market"** (30 min)
7. **Remove stale listing-level upgrade buttons/badges** (30 min)
8. **Register Stripe webhook in dashboard** (10 min)
9. **Full flow test: signup → plan → market → RFQ → billing** (1-2 hours)
10. **Fix any issues found in testing** (variable)

---

## Test Accounts Available

| Role | Email | Password | Purpose |
|------|-------|----------|---------|
| Buyer | kihn.arlene@example.net | (logged in via session) | RFQ testing |
| Vendor (Peach State) | marcus@peachstateins.test | vendor2026! | Vendor flow testing |
| Vendor (Forsyth) | dana@forsythins.test | vendor2026! | Multi-vendor RFQ testing |
| Tenant Admin | (use existing admin) | | Acquisition + communications |

---

## Environment Notes

- PHP 8.1 (Reverb requires 8.2 — not installed)
- Node 18 via nvm (for Soketi WebSocket server)
- Soketi running on port 6001 (systemd service) — WebSocket not exposed to browsers yet (polling fallback active)
- nginx on port 8443 for WebSocket SSL proxy (ready when DNS is configured)
- Tesseract OCR installed for document text extraction
- Alpine.js loaded on all authenticated layouts
- Tailwind via CDN (not compiled)

---

## What "Launch Ready" Means

The platform is launch-ready when a vendor can:
1. Sign up → select plan → pay → land on dashboard
2. Browse available markets → select one → see details/pricing → activate → pay → edit profile
3. Receive RFQ notifications → chat with buyer → win the job
4. Upload verification → get verified badge
5. See billing history → view invoices → manage plan → cancel if needed

And a buyer can:
1. Browse categories → submit RFQ
2. Receive vendor responses → compare → negotiate → award
3. See vendor verification data for due diligence

The critical path to this is **Tasks 1-5 from the execution order above**. Everything else is hardening and polish.
