Services Domain
The Services domain manages the service catalog, categories, options, and reviews. It represents the marketplace offerings where sellers list their services and customers can browse and select services to purchase.
Overview
The Services domain encompasses:
- Services – The core offerings on the platform
- Categories – Service classification and organization
- Options – Add-ons and upgrades for services
- Service Views – View tracking and analytics
- Comments – Reviews and ratings
Entities
Service Entity
Represents a service offered by a seller.
// domain/service/service.entity.ts
export class Service {
id: string;
title: string;
slug: string;
description: string;
status: ServiceStatus; // 'pending' | 'rejected' | 'suspended' | 'active' | 'paused'
categoryId: string;
ownerId: string;
basicPrice: Decimal;
basicDeliveryTime: number; // in hours
reviewsCount: number;
averageRating: number;
salesCount: number;
notes: string; // Admin notes
createdAt: Date;
updatedAt: Date;
static create(
id: string,
title: string,
description: string,
categoryId: string,
ownerId: string,
basicPrice: Decimal,
basicDeliveryTime: number,
status: ServiceStatus = "pending"
): Service
activate(): void
isActive(): boolean
}
Key properties:
- slug – Auto-generated from title and ID (e.g., web-design-abc123)
- status – Lifecycle state of the service
- basicPrice – Base price before options
- basicDeliveryTime – Base delivery time in hours
- reviewsCount / averageRating – Computed from comments
- salesCount – Number of completed orders
Service statuses: - pending – Awaiting admin approval - active – Live and available for purchase - paused – Temporarily disabled by seller - suspended – Disabled by admin - rejected – Rejected by admin
Category Entity
Organizes services into categories.
// domain/service/category.entity.ts
export class Category {
id: string;
slug: string;
title: string;
description: string;
isActive: boolean;
iconId: string;
createdAt: Date;
updatedAt: Date;
static create(
id: string,
slug: string,
title: string,
description: string = "",
isActive: boolean = false,
iconId: string = ""
): Category
activate(): void
deactivate(): void
}
Key features: - Categories must be activated before services can be created in them - Each category has an icon (uploaded image) - Categories can be deactivated (hides from browse)
Option Entity
Service add-ons and upgrades.
// domain/service/option.vo.ts
export class Option {
id: string;
title: string;
additionalTime: number; // hours
additionalPrice: Decimal;
isAvailable: boolean;
isRecommended: boolean;
serviceId: string;
createdAt: Date;
updatedAt: Date;
static create(
id: string,
title: string,
additionalTime: number,
additionalPrice: Decimal,
isAvailable: boolean,
isRecommended: boolean,
serviceId: string
): Option
}
Example options: - Fast delivery (+$50, -24 hours) - Extra revisions (+$20, +0 hours) - Source files included (+$30, +0 hours) - Commercial license (+$100, +0 hours)
ServiceView Entity
Tracks service view analytics.
// domain/service/serviceview.entity.ts
export class ServiceView {
id: string;
serviceId: string;
viewerId: string | null; // null for anonymous
viewedAt: Date;
}
Repositories
ServiceRepository
// domain/service/service.repository.ts
export abstract class ServiceRepository extends AbstractRepository<Service, string, ServiceQueryPolicy> {
abstract all(filters: ServiceQueryPolicy & Pagination): Promise<Paginated<Service>>;
abstract get(id: string, filters?: ServiceQueryPolicy): Promise<Service>;
abstract addOptions(options: Option[]): Promise<Option[]>;
abstract addOption(option: Option): Promise<Option>;
abstract getAvailableOptions(serviceId: string): Promise<Paginated<Option>>;
abstract getOptions(serviceId: string): Promise<Paginated<Option>>;
abstract updateOption(optionId: string, data: Partial<Option>): Promise<Option>;
abstract recommendedOptionCount(serviceId: string): Promise<number>;
abstract countByUserIds(userIds: string[]): Promise<Record<string, number>>;
abstract deactivateServicesByOwner(ownerId: string): Promise<void>;
}
export class ServiceQueryPolicy {
search?: string; // Search in title/description
ownerId?: string; // Filter by seller
categoryId?: string; // Filter by category
status?: ServiceStatus; // Filter by status
ids?: string[]; // Filter by IDs
}
Key operations:
- all() – List services with filters
- get() – Get service by ID or slug
- addOption() / addOptions() – Add service options
- getAvailableOptions() – Get options where isAvailable = true
- recommendedOptionCount() – Count recommended options (max 3 allowed)
- countByUserIds() – Count services per user (batch)
- deactivateServicesByOwner() – Deactivate all services by a user
CategoryRepository
// domain/service/category.repository.ts
export abstract class CategoryRepository extends AbstractRepository<Category> {
abstract getBySlug(slug: string): Promise<Category>;
abstract listActive(): Promise<Category[]>;
}
ServiceViewRepository
// domain/service/serviceview.repository.ts
export abstract class ServiceViewRepository extends AbstractRepository<ServiceView> {
abstract countByService(serviceId: string): Promise<number>;
abstract countByServices(serviceIds: string[]): Promise<Record<string, number>>;
}
Business Rules
Service Creation
- Seller must be KYC verified – Only verified sellers can create services
- Category must be active – Can't create service in inactive category
- Pending by default – New services require admin approval
- Unique slug – Generated from title + ID
- Minimum price – May be enforced (e.g., $5 minimum)
- Maximum recommended options – Only 3 options can be marked recommended
Service Approval
- Admin reviews pending services
- Can approve (status → active) or reject (status → rejected)
- Rejection includes admin notes explaining why
- Sellers can edit and resubmit rejected services
Service Status Transitions
pending → active (admin approval)
pending → rejected (admin rejection)
active → suspended (admin action)
active → paused (seller action)
paused → active (seller action)
suspended → active (admin action)
Options Management
- Service can have multiple options
- Each option adds time and/or price
- Maximum 3 recommended options
- Options can be marked unavailable without deletion
- Customer selects 0 or more options when ordering
Service Deactivation
- When user is deactivated, all their services are deactivated
- Deactivated services don't appear in browse/search
- Existing orders continue normally
- Services can be reactivated if user is reactivated
Use Cases
Service Management
- Create service – Seller creates new service listing
- Update service – Edit title, description, price, delivery time
- Add service images – Upload gallery images
- Add service tags – Tag services for better discoverability
- Pause service – Temporarily disable
- Delete service – Soft delete (mark as deleted)
Admin Moderation
- List pending services – Review queue
- Approve service – Make service live
- Reject service – Reject with reason
- Suspend service – Remove from marketplace
- Delete service – Permanent removal
Option Management
- Add option – Create service add-on
- Update option – Edit price/time/availability
- Mark as recommended – Highlight to customers (max 3)
- Disable option – Make unavailable without deletion
- List options – Get all options for a service
Category Management
- Create category – New service category
- Update category – Edit details
- Upload category icon – Set category image
- Activate/deactivate category – Control visibility
- List categories – Get all or only active
Service Discovery
- Browse services – List with filters (category, search, seller)
- Search services – Full-text search in title/description
- View service details – Get service with options and reviews
- Track service view – Record analytics
Integration Points
With Users Domain
Service.ownerIdreferencesUser.id- Only KYC verified sellers can create services
- User deactivation triggers service deactivation
With Orders Domain
- Orders reference
Service.id - Order includes
serviceTitle,servicePrice,serviceDeliveryTime - Order
selectedOptionsare captured from service options - Completed orders increment
Service.salesCount
With Accounts Domain
- Service sales generate revenue
- Commission calculated on
Service.basicPrice+ option prices
Key Workflows
Service Creation and Approval Flow
1. Seller (KYC verified) creates service
↓
2. Service created with status = "pending"
↓
3. Admin reviews service
↓
4. Admin approves → status = "active"
OR
Admin rejects → status = "rejected" (with notes)
↓
5. If active, service appears in marketplace
Service Purchase Flow
1. Customer browses services
↓
2. Customer views service details
↓
3. ServiceView recorded for analytics
↓
4. Customer selects options (0 or more)
↓
5. Customer initiates order
↓
6. Order created with:
- serviceId
- serviceTitle
- servicePrice
- serviceDeliveryTime
- selectedOptions (captured at order time)
Option Selection Impact
Service: Web Design
├── Basic Price: $100
├── Basic Delivery: 48 hours
│
├── Option 1: Fast Delivery
│ ├── Additional Price: $50
│ └── Additional Time: -24 hours
│
└── Option 2: Extra Revisions
├── Additional Price: $20
└── Additional Time: 0 hours
Customer selects both options:
├── Total Price: $170 ($100 + $50 + $20)
└── Delivery Time: 24 hours (48 - 24 + 0)
Data Model
┌──────────────┐
│ Category │
├──────────────┤
│ id │◄────┐
│ title │ │
│ slug │ │
│ isActive │ │
└──────────────┘ │
│
┌──────────────┐ │
│ Service │ │
├──────────────┤ │
│ id │ │
│ title │ │
│ slug │ │
│ categoryId │─────┘
│ ownerId │────► User
│ basicPrice │
│ status │
│ reviewsCount │
│ averageRating│
│ salesCount │
└──────────────┘
│
│ 1:N
↓
┌──────────────┐
│ Option │
├──────────────┤
│ id │
│ serviceId │
│ title │
│ additionalPrice │
│ additionalTime │
│ isRecommended │
└──────────────┘
┌──────────────┐
│ ServiceView │
├──────────────┤
│ id │
│ serviceId │
│ viewerId │
│ viewedAt │
└──────────────┘
Analytics
Service Metrics
- Total views – Count of ServiceView records
- Conversion rate – Orders / Views
- Average rating – From Comment entities
- Sales count – Completed orders
- Revenue – Total from completed orders
Seller Metrics
- Total services – Count active services
- Total sales – Sum of sales across all services
- Average rating – Across all services
- Top performing service – By sales or revenue
Best Practices
✅ Do
- Validate service ownership – Only owner can edit service
- Capture service data in orders – Don't rely on service staying unchanged
- Use slug for SEO – Generate from title
- Limit recommended options – Max 3 to avoid choice overload
- Track views – Important for analytics and recommendations
- Moderate new services – Prevent spam/scams
❌ Don't
- Don't delete services with orders – Soft delete or deactivate
- Don't allow price changes for pending orders – Order captures price
- Don't skip admin approval – Services should be reviewed
- Don't allow non-KYC sellers – Prevent fraud
- Don't hard delete categories – May have services/orders referencing them
Validation Rules
Service Creation
- Title: 10-100 characters
- Description: 100-5000 characters
- Basic price: > $0
- Basic delivery time: > 0 hours
- Category must exist and be active
- Owner must be KYC verified
Option Creation
- Title: 5-50 characters
- Additional price: >= $0
- Additional time: Can be negative (for faster delivery)
- Max 3 recommended options per service
Category Creation
- Title: 3-50 characters
- Slug: lowercase, alphanumeric + hyphens
- Description: optional, max 500 characters
Summary
The Services domain provides:
- Service catalog management for marketplace offerings
- Category organization for service classification
- Flexible pricing with options and add-ons
- Admin moderation to ensure quality
- Analytics tracking for views and performance
- Status management for lifecycle control
This domain represents the core marketplace functionality where sellers offer services and customers discover and purchase them.