mirror of
https://github.com/SamyRai/turash.git
synced 2025-12-26 23:01:33 +00:00
959 lines
28 KiB
Markdown
959 lines
28 KiB
Markdown
# Product & Service Discovery: "I Don't Know Who Has What" - Full Concept
|
|
|
|
## Executive Summary
|
|
|
|
This document provides a complete concept for implementing a **Universal Resource Discovery** system that allows users to find products, services, skills, and resources (both from businesses and community members) through a unified search and matching platform. This extends the existing industrial symbiosis matching engine to include consumer products, services, and community resources.
|
|
|
|
---
|
|
|
|
## Problem Statement
|
|
|
|
In small cities like Bugulma, residents face a critical information gap:
|
|
- **"I need X, but I don't know who has it"**
|
|
- Products and services exist but are hard to discover
|
|
- Information is fragmented across social media, word-of-mouth, and physical locations
|
|
- Businesses have surplus/underutilized resources but no way to connect with needs
|
|
- Community members have skills/tools but no visibility
|
|
|
|
**Current Platform Gap**: The platform currently matches industrial resources (heat, water, waste) between businesses. It doesn't handle:
|
|
- Consumer products and services
|
|
- Community member listings
|
|
- Skills and expertise matching
|
|
- Real-time availability
|
|
|
|
---
|
|
|
|
## Solution Overview
|
|
|
|
### Core Concept: Unified Discovery Platform
|
|
|
|
A single search interface that finds:
|
|
1. **Business Products**: Items/services businesses offer
|
|
2. **Business Surplus**: Underutilized resources businesses want to share/rent
|
|
3. **Community Listings**: Items/services community members offer
|
|
4. **Skills & Services**: People offering expertise or services
|
|
5. **Needs**: People looking for specific items/services
|
|
|
|
All searchable through:
|
|
- Natural language queries: "I need a van", "Who fixes computers?"
|
|
- Category filters: Products, Services, Tools, Skills
|
|
- Location-based ranking
|
|
- Real-time availability
|
|
|
|
---
|
|
|
|
## Architecture Overview
|
|
|
|
### System Components
|
|
|
|
```
|
|
┌─────────────────────────────────────────────────────────┐
|
|
│ Frontend Layer │
|
|
│ - Universal Search Interface │
|
|
│ - Product/Service Listing Pages │
|
|
│ - Map View with Discovery Layer │
|
|
│ - User Dashboard (My Listings, Requests) │
|
|
└──────────────────────┬────────────────────────────────────┘
|
|
│
|
|
┌──────────────────────▼────────────────────────────────────┐
|
|
│ API Layer │
|
|
│ - /api/v1/discovery/search │
|
|
│ - /api/v1/discovery/listings │
|
|
│ - /api/v1/discovery/services │
|
|
│ - /api/v1/discovery/skills │
|
|
└──────────────────────┬────────────────────────────────────┘
|
|
│
|
|
┌──────────────────────▼────────────────────────────────────┐
|
|
│ Discovery Service Layer │
|
|
│ - Search Engine (text, category, location) │
|
|
│ - Matching Algorithm (extends existing matching) │
|
|
│ - Availability Manager │
|
|
│ - Notification Service │
|
|
└──────────────────────┬────────────────────────────────────┘
|
|
│
|
|
┌──────────────────────▼────────────────────────────────────┐
|
|
│ Data Layer │
|
|
│ - product_listings (business products) │
|
|
│ - service_listings (business services) │
|
|
│ - community_listings (community items/services) │
|
|
│ - skill_profiles (user skills) │
|
|
│ - discovery_requests (needs/wants) │
|
|
└───────────────────────────────────────────────────────────┘
|
|
```
|
|
|
|
---
|
|
|
|
## Data Model
|
|
|
|
### 1. Product Listings (Business Products)
|
|
|
|
**Purpose**: Businesses list products they sell/offer
|
|
|
|
```sql
|
|
CREATE TABLE product_listings (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
organization_id TEXT REFERENCES organizations(id) ON DELETE CASCADE,
|
|
site_id TEXT REFERENCES sites(id),
|
|
|
|
-- Product Information
|
|
name VARCHAR(255) NOT NULL,
|
|
description TEXT,
|
|
category VARCHAR(100) NOT NULL, -- 'tools', 'equipment', 'materials', 'food', etc.
|
|
subcategory VARCHAR(100),
|
|
brand VARCHAR(100),
|
|
model VARCHAR(100),
|
|
|
|
-- Pricing
|
|
price DECIMAL(10,2),
|
|
price_unit VARCHAR(50), -- 'per_item', 'per_hour', 'per_day', 'per_month'
|
|
currency VARCHAR(3) DEFAULT 'EUR',
|
|
negotiable BOOLEAN DEFAULT false,
|
|
|
|
-- Availability
|
|
quantity_available INTEGER, -- NULL = unlimited
|
|
availability_status VARCHAR(20) DEFAULT 'available', -- 'available', 'limited', 'out_of_stock', 'rental_only'
|
|
availability_schedule JSONB, -- {days: ['monday', 'wednesday'], times: ['09:00-17:00']}
|
|
|
|
-- Location
|
|
pickup_location POINT, -- PostGIS geography point
|
|
delivery_available BOOLEAN DEFAULT false,
|
|
delivery_radius_km DECIMAL(5,2),
|
|
delivery_cost DECIMAL(10,2),
|
|
|
|
-- Media
|
|
images TEXT[], -- Array of image URLs
|
|
specifications JSONB, -- Flexible product specs
|
|
|
|
-- Metadata
|
|
tags TEXT[], -- Searchable tags
|
|
search_keywords TEXT, -- Full-text search field
|
|
verified BOOLEAN DEFAULT false, -- Business verification
|
|
|
|
-- Status
|
|
status VARCHAR(20) DEFAULT 'active', -- 'active', 'inactive', 'sold_out', 'archived'
|
|
featured BOOLEAN DEFAULT false,
|
|
|
|
-- Timestamps
|
|
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
|
|
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
|
|
expires_at TIMESTAMP WITH TIME ZONE, -- Optional expiration
|
|
|
|
-- Indexes
|
|
CONSTRAINT fk_organization FOREIGN KEY (organization_id) REFERENCES organizations(id)
|
|
);
|
|
|
|
-- Indexes for product_listings
|
|
CREATE INDEX idx_product_listings_org ON product_listings(organization_id);
|
|
CREATE INDEX idx_product_listings_category ON product_listings(category);
|
|
CREATE INDEX idx_product_listings_status ON product_listings(status);
|
|
CREATE INDEX idx_product_listings_location ON product_listings USING GIST(pickup_location);
|
|
CREATE INDEX idx_product_listings_search ON product_listings USING GIN(to_tsvector('russian', name || ' ' || COALESCE(description, '') || ' ' || COALESCE(search_keywords, '')));
|
|
CREATE INDEX idx_product_listings_tags ON product_listings USING GIN(tags);
|
|
```
|
|
|
|
### 2. Service Listings (Business Services)
|
|
|
|
**Purpose**: Businesses list services they offer
|
|
|
|
```sql
|
|
CREATE TABLE service_listings (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
organization_id TEXT REFERENCES organizations(id) ON DELETE CASCADE,
|
|
site_id TEXT REFERENCES sites(id),
|
|
|
|
-- Service Information
|
|
name VARCHAR(255) NOT NULL,
|
|
description TEXT,
|
|
category VARCHAR(100) NOT NULL, -- 'repair', 'consulting', 'delivery', 'rental', etc.
|
|
subcategory VARCHAR(100),
|
|
|
|
-- Pricing
|
|
price DECIMAL(10,2),
|
|
price_type VARCHAR(50), -- 'fixed', 'hourly', 'daily', 'project_based', 'quote'
|
|
currency VARCHAR(3) DEFAULT 'EUR',
|
|
negotiable BOOLEAN DEFAULT false,
|
|
|
|
-- Availability
|
|
availability_status VARCHAR(20) DEFAULT 'available',
|
|
availability_schedule JSONB, -- {days: ['monday-friday'], times: ['09:00-18:00']}
|
|
booking_required BOOLEAN DEFAULT false,
|
|
min_advance_booking_hours INTEGER,
|
|
|
|
-- Service Area
|
|
service_location POINT, -- Where service is provided
|
|
service_radius_km DECIMAL(5,2), -- How far they travel
|
|
on_site_service BOOLEAN DEFAULT true,
|
|
remote_service BOOLEAN DEFAULT false,
|
|
|
|
-- Requirements
|
|
requirements TEXT, -- What customer needs to provide
|
|
duration_estimate VARCHAR(100), -- '1 hour', '2-3 days', etc.
|
|
|
|
-- Media
|
|
images TEXT[],
|
|
portfolio_urls TEXT[], -- Links to portfolio/examples
|
|
|
|
-- Metadata
|
|
tags TEXT[],
|
|
search_keywords TEXT,
|
|
certifications TEXT[], -- Relevant certifications
|
|
verified BOOLEAN DEFAULT false,
|
|
|
|
-- Status
|
|
status VARCHAR(20) DEFAULT 'active',
|
|
featured BOOLEAN DEFAULT false,
|
|
|
|
-- Timestamps
|
|
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
|
|
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
|
|
|
|
CONSTRAINT fk_organization FOREIGN KEY (organization_id) REFERENCES organizations(id)
|
|
);
|
|
|
|
-- Indexes for service_listings
|
|
CREATE INDEX idx_service_listings_org ON service_listings(organization_id);
|
|
CREATE INDEX idx_service_listings_category ON service_listings(category);
|
|
CREATE INDEX idx_service_listings_status ON service_listings(status);
|
|
CREATE INDEX idx_service_listings_location ON service_listings USING GIST(service_location);
|
|
CREATE INDEX idx_service_listings_search ON service_listings USING GIN(to_tsvector('russian', name || ' ' || COALESCE(description, '') || ' ' || COALESCE(search_keywords, '')));
|
|
```
|
|
|
|
### 3. Community Listings
|
|
|
|
**Purpose**: Community members list items/services they offer
|
|
|
|
```sql
|
|
CREATE TABLE community_listings (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
user_id UUID REFERENCES users(id) ON DELETE CASCADE,
|
|
|
|
-- Listing Information
|
|
title VARCHAR(255) NOT NULL,
|
|
description TEXT,
|
|
listing_type VARCHAR(50) NOT NULL, -- 'product', 'service', 'tool', 'skill', 'need'
|
|
category VARCHAR(100) NOT NULL,
|
|
subcategory VARCHAR(100),
|
|
|
|
-- For Products/Tools
|
|
condition VARCHAR(50), -- 'new', 'like_new', 'good', 'fair', 'needs_repair'
|
|
price DECIMAL(10,2), -- NULL = free
|
|
price_type VARCHAR(50), -- 'free', 'sale', 'rent', 'trade', 'borrow'
|
|
|
|
-- For Services/Skills
|
|
service_type VARCHAR(50), -- 'offering', 'seeking'
|
|
rate DECIMAL(10,2),
|
|
rate_type VARCHAR(50), -- 'hourly', 'fixed', 'negotiable', 'free'
|
|
|
|
-- Availability
|
|
availability_status VARCHAR(20) DEFAULT 'available',
|
|
availability_schedule JSONB,
|
|
quantity_available INTEGER, -- For products
|
|
|
|
-- Location
|
|
location POINT,
|
|
pickup_available BOOLEAN DEFAULT true,
|
|
delivery_available BOOLEAN DEFAULT false,
|
|
delivery_radius_km DECIMAL(5,2),
|
|
|
|
-- Media
|
|
images TEXT[],
|
|
|
|
-- Metadata
|
|
tags TEXT[],
|
|
search_keywords TEXT,
|
|
|
|
-- Trust & Verification
|
|
user_rating DECIMAL(3,2), -- Average rating from reviews
|
|
review_count INTEGER DEFAULT 0,
|
|
verified BOOLEAN DEFAULT false, -- Platform verification
|
|
|
|
-- Status
|
|
status VARCHAR(20) DEFAULT 'active', -- 'active', 'reserved', 'completed', 'archived'
|
|
|
|
-- Timestamps
|
|
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
|
|
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
|
|
expires_at TIMESTAMP WITH TIME ZONE, -- Auto-archive after X days
|
|
|
|
CONSTRAINT fk_user FOREIGN KEY (user_id) REFERENCES users(id)
|
|
);
|
|
|
|
-- Indexes for community_listings
|
|
CREATE INDEX idx_community_listings_user ON community_listings(user_id);
|
|
CREATE INDEX idx_community_listings_type ON community_listings(listing_type);
|
|
CREATE INDEX idx_community_listings_category ON community_listings(category);
|
|
CREATE INDEX idx_community_listings_status ON community_listings(status);
|
|
CREATE INDEX idx_community_listings_location ON community_listings USING GIST(location);
|
|
CREATE INDEX idx_community_listings_search ON community_listings USING GIN(to_tsvector('russian', title || ' ' || COALESCE(description, '') || ' ' || COALESCE(search_keywords, '')));
|
|
```
|
|
|
|
### 4. Skill Profiles
|
|
|
|
**Purpose**: Users list skills they can offer
|
|
|
|
```sql
|
|
CREATE TABLE skill_profiles (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
user_id UUID REFERENCES users(id) ON DELETE CASCADE,
|
|
|
|
-- Skill Information
|
|
skill_name VARCHAR(255) NOT NULL,
|
|
description TEXT,
|
|
category VARCHAR(100) NOT NULL, -- 'technical', 'creative', 'professional', 'manual', 'language', etc.
|
|
subcategory VARCHAR(100),
|
|
|
|
-- Service Details
|
|
service_type VARCHAR(50) NOT NULL, -- 'offering', 'seeking', 'both'
|
|
experience_years INTEGER,
|
|
level VARCHAR(50), -- 'beginner', 'intermediate', 'advanced', 'expert'
|
|
|
|
-- Pricing
|
|
rate DECIMAL(10,2),
|
|
rate_type VARCHAR(50), -- 'hourly', 'fixed', 'negotiable', 'free', 'trade'
|
|
currency VARCHAR(3) DEFAULT 'EUR',
|
|
|
|
-- Availability
|
|
availability_status VARCHAR(20) DEFAULT 'available',
|
|
availability_schedule JSONB,
|
|
remote_available BOOLEAN DEFAULT false,
|
|
on_site_available BOOLEAN DEFAULT true,
|
|
|
|
-- Location
|
|
service_location POINT,
|
|
service_radius_km DECIMAL(5,2),
|
|
|
|
-- Credentials
|
|
certifications TEXT[],
|
|
portfolio_urls TEXT[],
|
|
education TEXT,
|
|
|
|
-- Metadata
|
|
tags TEXT[],
|
|
search_keywords TEXT,
|
|
|
|
-- Trust
|
|
user_rating DECIMAL(3,2),
|
|
review_count INTEGER DEFAULT 0,
|
|
verified BOOLEAN DEFAULT false,
|
|
|
|
-- Status
|
|
status VARCHAR(20) DEFAULT 'active',
|
|
|
|
-- Timestamps
|
|
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
|
|
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
|
|
|
|
CONSTRAINT fk_user FOREIGN KEY (user_id) REFERENCES users(id)
|
|
);
|
|
|
|
-- Indexes for skill_profiles
|
|
CREATE INDEX idx_skill_profiles_user ON skill_profiles(user_id);
|
|
CREATE INDEX idx_skill_profiles_category ON skill_profiles(category);
|
|
CREATE INDEX idx_skill_profiles_status ON skill_profiles(status);
|
|
CREATE INDEX idx_skill_profiles_location ON skill_profiles USING GIST(service_location);
|
|
CREATE INDEX idx_skill_profiles_search ON skill_profiles USING GIN(to_tsvector('russian', skill_name || ' ' || COALESCE(description, '') || ' ' || COALESCE(search_keywords, '')));
|
|
```
|
|
|
|
### 5. Discovery Requests
|
|
|
|
**Purpose**: Users can post what they're looking for
|
|
|
|
```sql
|
|
CREATE TABLE discovery_requests (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
user_id UUID REFERENCES users(id) ON DELETE CASCADE,
|
|
|
|
-- Request Information
|
|
title VARCHAR(255) NOT NULL,
|
|
description TEXT,
|
|
request_type VARCHAR(50) NOT NULL, -- 'product', 'service', 'skill', 'tool', 'general'
|
|
category VARCHAR(100),
|
|
|
|
-- Requirements
|
|
requirements TEXT, -- Specific requirements
|
|
budget_min DECIMAL(10,2),
|
|
budget_max DECIMAL(10,2),
|
|
urgency VARCHAR(50), -- 'low', 'medium', 'high', 'urgent'
|
|
|
|
-- Location
|
|
location POINT, -- Where needed
|
|
max_distance_km DECIMAL(5,2),
|
|
pickup_preferred BOOLEAN DEFAULT true,
|
|
delivery_acceptable BOOLEAN DEFAULT false,
|
|
|
|
-- Timeline
|
|
needed_by TIMESTAMP WITH TIME ZONE,
|
|
flexible_timeline BOOLEAN DEFAULT true,
|
|
|
|
-- Status
|
|
status VARCHAR(20) DEFAULT 'open', -- 'open', 'matched', 'fulfilled', 'closed', 'expired'
|
|
match_count INTEGER DEFAULT 0, -- Number of matches found
|
|
|
|
-- Timestamps
|
|
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
|
|
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
|
|
expires_at TIMESTAMP WITH TIME ZONE, -- Auto-close after X days
|
|
|
|
CONSTRAINT fk_user FOREIGN KEY (user_id) REFERENCES users(id)
|
|
);
|
|
|
|
-- Indexes for discovery_requests
|
|
CREATE INDEX idx_discovery_requests_user ON discovery_requests(user_id);
|
|
CREATE INDEX idx_discovery_requests_type ON discovery_requests(request_type);
|
|
CREATE INDEX idx_discovery_requests_status ON discovery_requests(status);
|
|
CREATE INDEX idx_discovery_requests_location ON discovery_requests USING GIST(location);
|
|
CREATE INDEX idx_discovery_requests_search ON discovery_requests USING GIN(to_tsvector('russian', title || ' ' || COALESCE(description, '')));
|
|
```
|
|
|
|
### 6. Listing Interactions
|
|
|
|
**Purpose**: Track views, contacts, favorites, reviews
|
|
|
|
```sql
|
|
CREATE TABLE listing_interactions (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
user_id UUID REFERENCES users(id) ON DELETE CASCADE,
|
|
|
|
-- What was interacted with
|
|
listing_type VARCHAR(50) NOT NULL, -- 'product', 'service', 'community', 'skill'
|
|
listing_id UUID NOT NULL, -- References the specific listing table
|
|
|
|
-- Interaction Type
|
|
interaction_type VARCHAR(50) NOT NULL, -- 'view', 'contact', 'favorite', 'share', 'report'
|
|
|
|
-- Contact Details (if interaction_type = 'contact')
|
|
contact_method VARCHAR(50), -- 'platform_message', 'phone', 'email', 'visit'
|
|
message TEXT, -- Initial message if any
|
|
|
|
-- Metadata
|
|
metadata JSONB, -- Flexible additional data
|
|
|
|
-- Timestamps
|
|
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
|
|
|
|
CONSTRAINT fk_user FOREIGN KEY (user_id) REFERENCES users(id)
|
|
);
|
|
|
|
-- Indexes
|
|
CREATE INDEX idx_listing_interactions_user ON listing_interactions(user_id);
|
|
CREATE INDEX idx_listing_interactions_listing ON listing_interactions(listing_type, listing_id);
|
|
CREATE INDEX idx_listing_interactions_type ON listing_interactions(interaction_type);
|
|
```
|
|
|
|
---
|
|
|
|
## API Design
|
|
|
|
### 1. Universal Search Endpoint
|
|
|
|
**Endpoint**: `GET /api/v1/discovery/search`
|
|
|
|
**Purpose**: Single search interface for all product/service discovery
|
|
|
|
**Query Parameters**:
|
|
```typescript
|
|
{
|
|
q: string; // Search query (natural language)
|
|
category?: string; // Filter by category
|
|
listing_type?: string; // 'product', 'service', 'community', 'skill', 'all'
|
|
location?: { // User location for distance ranking
|
|
lat: number;
|
|
lng: number;
|
|
};
|
|
max_distance_km?: number; // Maximum distance (default: 25km)
|
|
price_min?: number;
|
|
price_max?: number;
|
|
availability?: string; // 'available', 'all'
|
|
verified_only?: boolean; // Only show verified listings
|
|
sort?: string; // 'relevance', 'distance', 'price_low', 'price_high', 'rating'
|
|
page?: number;
|
|
limit?: number;
|
|
}
|
|
```
|
|
|
|
**Response**:
|
|
```typescript
|
|
{
|
|
results: Array<{
|
|
id: string;
|
|
type: 'product' | 'service' | 'community' | 'skill';
|
|
title: string;
|
|
description: string;
|
|
category: string;
|
|
price?: number;
|
|
price_type?: string;
|
|
location: {
|
|
lat: number;
|
|
lng: number;
|
|
};
|
|
distance_km?: number;
|
|
organization_id?: string; // If business listing
|
|
organization_name?: string;
|
|
user_id?: string; // If community listing
|
|
user_name?: string;
|
|
rating?: number;
|
|
review_count?: number;
|
|
verified: boolean;
|
|
images: string[];
|
|
availability_status: string;
|
|
match_score: number; // Relevance score
|
|
}>;
|
|
total: number;
|
|
page: number;
|
|
limit: number;
|
|
facets: {
|
|
categories: Array<{name: string, count: number}>;
|
|
price_ranges: Array<{min: number, max: number, count: number}>;
|
|
distances: Array<{range: string, count: number}>;
|
|
};
|
|
}
|
|
```
|
|
|
|
### 2. Listing Management Endpoints
|
|
|
|
#### Create Product Listing (Business)
|
|
**POST** `/api/v1/discovery/products`
|
|
- Requires: Business authentication
|
|
- Body: Product listing data
|
|
|
|
#### Create Service Listing (Business)
|
|
**POST** `/api/v1/discovery/services`
|
|
- Requires: Business authentication
|
|
- Body: Service listing data
|
|
|
|
#### Create Community Listing
|
|
**POST** `/api/v1/discovery/community`
|
|
- Requires: User authentication
|
|
- Body: Community listing data
|
|
|
|
#### Create Skill Profile
|
|
**POST** `/api/v1/discovery/skills`
|
|
- Requires: User authentication
|
|
- Body: Skill profile data
|
|
|
|
#### Create Discovery Request
|
|
**POST** `/api/v1/discovery/requests`
|
|
- Requires: User authentication
|
|
- Body: Request data
|
|
|
|
#### Get Listing Details
|
|
**GET** `/api/v1/discovery/listings/:type/:id`
|
|
- `type`: 'product', 'service', 'community', 'skill'
|
|
- Returns: Full listing details
|
|
|
|
#### Update Listing
|
|
**PUT** `/api/v1/discovery/listings/:type/:id`
|
|
- Requires: Ownership verification
|
|
|
|
#### Delete Listing
|
|
**DELETE** `/api/v1/discovery/listings/:type/:id`
|
|
- Requires: Ownership verification
|
|
|
|
### 3. User Dashboard Endpoints
|
|
|
|
#### Get User Listings
|
|
**GET** `/api/v1/discovery/my-listings`
|
|
- Returns: All listings created by user
|
|
|
|
#### Get User Requests
|
|
**GET** `/api/v1/discovery/my-requests`
|
|
- Returns: All discovery requests by user
|
|
|
|
#### Get Favorites
|
|
**GET** `/api/v1/discovery/favorites`
|
|
- Returns: User's favorited listings
|
|
|
|
#### Contact Listing Owner
|
|
**POST** `/api/v1/discovery/listings/:type/:id/contact`
|
|
- Creates interaction record
|
|
- Sends notification to owner
|
|
- Returns: Contact information or initiates platform messaging
|
|
|
|
---
|
|
|
|
## Search & Matching Algorithm
|
|
|
|
### Multi-Stage Search Pipeline
|
|
|
|
```
|
|
1. Query Processing
|
|
↓
|
|
2. Text Search (Full-Text)
|
|
↓
|
|
3. Category Filtering
|
|
↓
|
|
4. Location-Based Filtering
|
|
↓
|
|
5. Availability Check
|
|
↓
|
|
6. Relevance Scoring
|
|
↓
|
|
7. Ranking & Sorting
|
|
↓
|
|
8. Result Formatting
|
|
```
|
|
|
|
### Relevance Scoring Formula
|
|
|
|
```go
|
|
func calculateRelevanceScore(listing Listing, query SearchQuery) float64 {
|
|
score := 0.0
|
|
|
|
// Text Match Score (0-40 points)
|
|
textScore := calculateTextMatch(listing, query.Text)
|
|
score += textScore * 0.4
|
|
|
|
// Category Match (0-20 points)
|
|
if listing.Category == query.Category {
|
|
score += 20.0
|
|
} else if listing.Subcategory == query.Category {
|
|
score += 15.0
|
|
}
|
|
|
|
// Distance Score (0-20 points)
|
|
distanceScore := calculateDistanceScore(listing.Location, query.Location, query.MaxDistance)
|
|
score += distanceScore * 0.2
|
|
|
|
// Trust Score (0-10 points)
|
|
trustScore := calculateTrustScore(listing)
|
|
score += trustScore * 0.1
|
|
|
|
// Availability Score (0-10 points)
|
|
availabilityScore := calculateAvailabilityScore(listing)
|
|
score += availabilityScore * 0.1
|
|
|
|
return score / 100.0 // Normalize to 0-1
|
|
}
|
|
|
|
func calculateTextMatch(listing Listing, queryText string) float64 {
|
|
// Full-text search relevance
|
|
// Uses PostgreSQL ts_rank or similar
|
|
// Returns 0-100
|
|
}
|
|
|
|
func calculateDistanceScore(listingLocation, queryLocation Point, maxDistance float64) float64 {
|
|
distance := calculateHaversineDistance(listingLocation, queryLocation)
|
|
|
|
if distance > maxDistance {
|
|
return 0.0
|
|
}
|
|
|
|
// Closer = higher score
|
|
// Linear decay: score = 100 * (1 - distance/maxDistance)
|
|
return 100.0 * (1.0 - distance/maxDistance)
|
|
}
|
|
|
|
func calculateTrustScore(listing Listing) float64 {
|
|
score := 50.0 // Base score
|
|
|
|
if listing.Verified {
|
|
score += 30.0
|
|
}
|
|
|
|
if listing.Rating > 0 {
|
|
score += listing.Rating * 20.0 // Rating is 0-5, so max +100
|
|
}
|
|
|
|
// Business listings get bonus
|
|
if listing.OrganizationID != "" {
|
|
score += 10.0
|
|
}
|
|
|
|
return min(score, 100.0)
|
|
}
|
|
|
|
func calculateAvailabilityScore(listing Listing) float64 {
|
|
if listing.AvailabilityStatus == "available" {
|
|
return 100.0
|
|
} else if listing.AvailabilityStatus == "limited" {
|
|
return 70.0
|
|
} else if listing.AvailabilityStatus == "reserved" {
|
|
return 30.0
|
|
}
|
|
return 0.0
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## Frontend Components
|
|
|
|
### 1. Universal Search Bar
|
|
|
|
**Component**: `DiscoverySearchBar.tsx`
|
|
|
|
**Features**:
|
|
- Natural language input
|
|
- Category dropdown
|
|
- Location autocomplete
|
|
- Quick filters (price, distance, verified)
|
|
- Voice input (optional)
|
|
|
|
**Location**: Top of discovery page, persistent in header
|
|
|
|
### 2. Search Results Page
|
|
|
|
**Component**: `DiscoverySearchResults.tsx`
|
|
|
|
**Layout**:
|
|
- Left sidebar: Filters (category, price, distance, availability)
|
|
- Main area: Results grid/list
|
|
- Map view toggle
|
|
- Sort options
|
|
|
|
**Result Card**:
|
|
- Image thumbnail
|
|
- Title and description
|
|
- Price/rate
|
|
- Distance
|
|
- Rating (if available)
|
|
- Verified badge
|
|
- Quick actions (contact, favorite, share)
|
|
|
|
### 3. Listing Detail Page
|
|
|
|
**Component**: `ListingDetailPage.tsx`
|
|
|
|
**Sections**:
|
|
- Image gallery
|
|
- Title, description, category
|
|
- Price/rate details
|
|
- Location map
|
|
- Availability schedule
|
|
- Owner information (business or user)
|
|
- Reviews/ratings
|
|
- Contact button
|
|
- Share button
|
|
|
|
### 4. Create Listing Forms
|
|
|
|
**Components**:
|
|
- `CreateProductListingForm.tsx` (Business)
|
|
- `CreateServiceListingForm.tsx` (Business)
|
|
- `CreateCommunityListingForm.tsx` (User)
|
|
- `CreateSkillProfileForm.tsx` (User)
|
|
- `CreateDiscoveryRequestForm.tsx` (User)
|
|
|
|
**Features**:
|
|
- Step-by-step wizard
|
|
- Image upload
|
|
- Location picker (map)
|
|
- Category selection
|
|
- Price/availability inputs
|
|
- Preview before submit
|
|
|
|
### 5. User Dashboard
|
|
|
|
**Component**: `DiscoveryDashboard.tsx`
|
|
|
|
**Tabs**:
|
|
- My Listings
|
|
- My Requests
|
|
- Favorites
|
|
- Messages/Contacts
|
|
- Activity History
|
|
|
|
### 6. Map View Integration
|
|
|
|
**Enhancement**: Add discovery layer to existing map
|
|
|
|
**Features**:
|
|
- Toggle layer: "Show Products/Services"
|
|
- Clustering for dense areas
|
|
- Click marker → Show listing preview
|
|
- Filter by category on map
|
|
|
|
---
|
|
|
|
## Implementation Phases
|
|
|
|
### Phase 1: Foundation (Weeks 1-3)
|
|
|
|
**Backend**:
|
|
1. Database migrations for all tables
|
|
2. Domain models (Go structs)
|
|
3. Repository layer
|
|
4. Basic CRUD endpoints
|
|
5. Simple search (text + category)
|
|
|
|
**Frontend**:
|
|
1. Search interface
|
|
2. Results page
|
|
3. Listing detail page
|
|
4. Basic create forms
|
|
|
|
**Goal**: Users can search and view listings
|
|
|
|
---
|
|
|
|
### Phase 2: Enhanced Search (Weeks 4-5)
|
|
|
|
**Backend**:
|
|
1. Full-text search implementation
|
|
2. Location-based filtering
|
|
3. Relevance scoring algorithm
|
|
4. Faceted search (filters)
|
|
|
|
**Frontend**:
|
|
1. Advanced filters
|
|
2. Map integration
|
|
3. Sort options
|
|
4. Result pagination
|
|
|
|
**Goal**: Powerful search with location ranking
|
|
|
|
---
|
|
|
|
### Phase 3: User Features (Weeks 6-7)
|
|
|
|
**Backend**:
|
|
1. User authentication integration
|
|
2. Listing ownership verification
|
|
3. Favorites system
|
|
4. Contact/interaction tracking
|
|
5. Notification system
|
|
|
|
**Frontend**:
|
|
1. User dashboard
|
|
2. Create/edit listings
|
|
3. Favorites management
|
|
4. Contact forms
|
|
5. My listings page
|
|
|
|
**Goal**: Users can create and manage listings
|
|
|
|
---
|
|
|
|
### Phase 4: Trust & Quality (Weeks 8-9)
|
|
|
|
**Backend**:
|
|
1. Rating/review system
|
|
2. Verification process
|
|
3. Trust scoring
|
|
4. Reporting/moderation
|
|
|
|
**Frontend**:
|
|
1. Review interface
|
|
2. Verification badges
|
|
3. Trust indicators
|
|
4. Report functionality
|
|
|
|
**Goal**: Build trust and quality
|
|
|
|
---
|
|
|
|
### Phase 5: Advanced Features (Weeks 10-12)
|
|
|
|
**Backend**:
|
|
1. Availability scheduling
|
|
2. Booking system (for services)
|
|
3. Matching algorithm (requests ↔ listings)
|
|
4. Notification system (alerts for new matches)
|
|
5. Analytics
|
|
|
|
**Frontend**:
|
|
1. Availability calendar
|
|
2. Booking interface
|
|
3. Request matching
|
|
4. Notification center
|
|
5. Analytics dashboard
|
|
|
|
**Goal**: Complete discovery platform
|
|
|
|
---
|
|
|
|
## Integration with Existing Systems
|
|
|
|
### 1. Leverage Existing Matching Engine
|
|
|
|
**Extend** `matching.Service` to handle:
|
|
- Product/service matching (not just resource flows)
|
|
- Discovery request matching
|
|
- Cross-type matching (request ↔ listing)
|
|
|
|
### 2. Use Existing Map Infrastructure
|
|
|
|
**Extend** `MapView` component:
|
|
- Add discovery layer toggle
|
|
- Show product/service markers
|
|
- Cluster markers
|
|
- Click → show listing details
|
|
|
|
### 3. Integrate with Organizations
|
|
|
|
**Link** product/service listings to:
|
|
- Existing `organizations` table
|
|
- Business profiles
|
|
- Organization verification status
|
|
|
|
### 4. Use Existing Authentication
|
|
|
|
**Reuse**:
|
|
- User authentication system
|
|
- Business authentication
|
|
- Role-based access control
|
|
|
|
---
|
|
|
|
## Success Metrics
|
|
|
|
### Engagement Metrics
|
|
- **Search Queries**: Number of searches per day
|
|
- **Listing Views**: Views per listing
|
|
- **Contact Rate**: % of views that result in contact
|
|
- **Listing Creation**: New listings per week
|
|
- **Match Success**: % of requests that find matches
|
|
|
|
### Quality Metrics
|
|
- **Search Relevance**: % of users who find what they need
|
|
- **Response Rate**: % of contacts that get responses
|
|
- **User Satisfaction**: Average rating of platform
|
|
- **Listing Quality**: % of listings with complete information
|
|
|
|
### Business Metrics
|
|
- **Business Participation**: % of businesses with listings
|
|
- **Community Participation**: % of users with listings
|
|
- **Transaction Volume**: Estimated value of matches
|
|
- **Platform Growth**: New users per month
|
|
|
|
---
|
|
|
|
## Technical Considerations
|
|
|
|
### Performance
|
|
- **Search Speed**: < 500ms for typical queries
|
|
- **Caching**: Cache popular searches
|
|
- **Indexing**: Proper database indexes
|
|
- **Pagination**: Limit results per page
|
|
|
|
### Scalability
|
|
- **Full-Text Search**: Use PostgreSQL full-text or Elasticsearch
|
|
- **Location Queries**: Use PostGIS spatial indexes
|
|
- **Image Storage**: Use CDN for images
|
|
- **Notifications**: Use message queue for async notifications
|
|
|
|
### Security
|
|
- **Input Validation**: Validate all user inputs
|
|
- **SQL Injection**: Use parameterized queries
|
|
- **XSS Prevention**: Sanitize user-generated content
|
|
- **Rate Limiting**: Prevent abuse
|
|
- **Privacy**: Respect user privacy settings
|
|
|
|
---
|
|
|
|
## Next Steps
|
|
|
|
1. **Review & Approve**: Review this concept document
|
|
2. **Database Design**: Finalize schema
|
|
3. **API Specification**: Detailed API docs
|
|
4. **UI/UX Design**: Mockups and wireframes
|
|
5. **Technical Spike**: Proof of concept for search
|
|
6. **Implementation**: Start Phase 1
|
|
|
|
---
|
|
|
|
**Document Version**: 1.0
|
|
**Last Updated**: 2025-01-27
|
|
**Status**: Concept - Ready for Review
|
|
|