Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
71 changes: 71 additions & 0 deletions src/marketplace/controllers/analytics.controller.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
import {
Controller,
Get,
Query,
Param,
UseGuards,
} from '@nestjs/common';
import { ApiTags, ApiOperation, ApiResponse, ApiBearerAuth } from '@nestjs/swagger';
import { AnalyticsService } from '../services/analytics.service';
import { JwtAuthGuard } from '../../auth/guards/jwt-auth.guard';
import { RolesGuard } from '../../auth/guards/roles.guard';
import { Roles } from '../../auth/decorators/roles.decorator';
import { GetUser } from '../../auth/decorators/get-user.decorator';

@ApiTags('Analytics')
@Controller('analytics')
@UseGuards(JwtAuthGuard)
@ApiBearerAuth()
export class AnalyticsController {
constructor(private readonly analyticsService: AnalyticsService) {}

@Get('vendor/:vendorId/dashboard')
@ApiOperation({ summary: 'Get vendor analytics dashboard' })
@ApiResponse({ status: 200, description: 'Vendor dashboard retrieved successfully' })
async getVendorDashboard(
@Param('vendorId') vendorId: string,
@Query('startDate') startDate?: string,
@Query('endDate') endDate?: string,
) {
const dateRange = startDate && endDate ? {
start: new Date(startDate),
end: new Date(endDate),
} : undefined;

return this.analyticsService.getVendorDashboard(vendorId, dateRange);
}

@Get('my-dashboard')
@ApiOperation({ summary: 'Get current vendor analytics dashboard' })
@ApiResponse({ status: 200, description: 'Vendor dashboard retrieved successfully' })
async getMyDashboard(
@GetUser('vendorId') vendorId: string,
@Query('startDate') startDate?: string,
@Query('endDate') endDate?: string,
) {
const dateRange = startDate && endDate ? {
start: new Date(startDate),
end: new Date(endDate),
} : undefined;

return this.analyticsService.getVendorDashboard(vendorId, dateRange);
}

@Get('marketplace/dashboard')
@UseGuards(RolesGuard)
@Roles('admin', 'analyst')
@ApiOperation({ summary: 'Get marketplace analytics dashboard (Admin only)' })
@ApiResponse({ status: 200, description: 'Marketplace dashboard retrieved successfully' })
@ApiResponse({ status: 403, description: 'Forbidden' })
async getMarketplaceDashboard(
@Query('startDate') startDate?: string,
@Query('endDate') endDate?: string,
) {
const dateRange = startDate && endDate ? {
start: new Date(startDate),
end: new Date(endDate),
} : undefined;

return this.analyticsService.getMarketplaceDashboard(dateRange);
}
}
139 changes: 139 additions & 0 deletions src/marketplace/controllers/booking.controller.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
import {
Controller,
Get,
Post,
Body,
Patch,
Param,
Delete,
Query,
UseGuards,
HttpStatus,
HttpCode,
} from '@nestjs/common';
import { ApiTags, ApiOperation, ApiResponse, ApiBearerAuth } from '@nestjs/swagger';
import { BookingService } from '../services/booking.service';
import { CreateBookingDto } from '../dto/create-booking.dto';
import { UpdateBookingDto } from '../dto/update-booking.dto';
import { BookingQueryDto } from '../dto/booking-query.dto';
import { JwtAuthGuard } from '../../auth/guards/jwt-auth.guard';
import { RolesGuard } from '../../auth/guards/roles.guard';
import { Roles } from '../../auth/decorators/roles.decorator';
import { GetUser } from '../../auth/decorators/get-user.decorator';

@ApiTags('Bookings')
@Controller('bookings')
@UseGuards(JwtAuthGuard)
@ApiBearerAuth()
export class BookingController {
constructor(private readonly bookingService: BookingService) {}

@Post()
@ApiOperation({ summary: 'Create a new service booking' })
@ApiResponse({ status: 201, description: 'Booking created successfully' })
@ApiResponse({ status: 400, description: 'Bad request' })
async create(@Body() createBookingDto: CreateBookingDto) {
return this.bookingService.createBooking(createBookingDto);
}

@Get()
@ApiOperation({ summary: 'Get bookings with filtering and pagination' })
@ApiResponse({ status: 200, description: 'Bookings retrieved successfully' })
async findAll(@Query() query: BookingQueryDto) {
return this.bookingService.findBookings(query);
}

@Get('my-bookings')
@ApiOperation({ summary: 'Get current user bookings' })
@ApiResponse({ status: 200, description: 'User bookings retrieved successfully' })
async getMyBookings(
@GetUser('id') userId: string,
@Query() query: BookingQueryDto,
) {
query.organizerId = userId;
return this.bookingService.findBookings(query);
}

@Get('vendor/:vendorId/upcoming')
@ApiOperation({ summary: 'Get upcoming bookings for vendor' })
@ApiResponse({ status: 200, description: 'Upcoming bookings retrieved successfully' })
async getUpcomingBookings(
@Param('vendorId') vendorId: string,
@Query('limit') limit?: number,
) {
return this.bookingService.getUpcomingBookings(vendorId, limit);
}

@Get('vendor/:vendorId/calendar')
@ApiOperation({ summary: 'Get vendor bookings calendar' })
@ApiResponse({ status: 200, description: 'Calendar bookings retrieved successfully' })
async getVendorCalendar(
@Param('vendorId') vendorId: string,
@Query('startDate') startDate: string,
@Query('endDate') endDate: string,
) {
return this.bookingService.getBookingsByDateRange(
vendorId,
new Date(startDate),
new Date(endDate),
);
}

@Get(':id')
@ApiOperation({ summary: 'Get booking by ID' })
@ApiResponse({ status: 200, description: 'Booking retrieved successfully' })
@ApiResponse({ status: 404, description: 'Booking not found' })
async findOne(@Param('id') id: string) {
return this.bookingService.findBookingById(id);
}

@Get('number/:bookingNumber')
@ApiOperation({ summary: 'Get booking by booking number' })
@ApiResponse({ status: 200, description: 'Booking retrieved successfully' })
@ApiResponse({ status: 404, description: 'Booking not found' })
async findByNumber(@Param('bookingNumber') bookingNumber: string) {
return this.bookingService.findBookingByNumber(bookingNumber);
}

@Patch(':id')
@ApiOperation({ summary: 'Update booking details' })
@ApiResponse({ status: 200, description: 'Booking updated successfully' })
@ApiResponse({ status: 404, description: 'Booking not found' })
async update(
@Param('id') id: string,
@Body() updateBookingDto: UpdateBookingDto,
) {
return this.bookingService.updateBooking(id, updateBookingDto);
}

@Post(':id/confirm')
@ApiOperation({ summary: 'Confirm booking' })
@ApiResponse({ status: 200, description: 'Booking confirmed successfully' })
@ApiResponse({ status: 400, description: 'Bad request' })
@HttpCode(HttpStatus.OK)
async confirm(@Param('id') id: string) {
return this.bookingService.confirmBooking(id);
}

@Post(':id/complete')
@ApiOperation({ summary: 'Mark booking as completed' })
@ApiResponse({ status: 200, description: 'Booking completed successfully' })
@ApiResponse({ status: 400, description: 'Bad request' })
@HttpCode(HttpStatus.OK)
async complete(@Param('id') id: string) {
return this.bookingService.completeBooking(id);
}

@Post(':id/cancel')
@ApiOperation({ summary: 'Cancel booking' })
@ApiResponse({ status: 200, description: 'Booking cancelled successfully' })
@ApiResponse({ status: 400, description: 'Bad request' })
@HttpCode(HttpStatus.OK)
async cancel(
@Param('id') id: string,
@Body('reason') reason: string,
@Body('cancelledBy') cancelledBy: 'organizer' | 'vendor' | 'admin',
) {
return this.bookingService.cancelBooking(id, reason, cancelledBy);
}
}
166 changes: 166 additions & 0 deletions src/marketplace/controllers/commission.controller.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,166 @@
import {
Controller,
Get,
Post,
Body,
Patch,
Param,
Query,
UseGuards,
HttpStatus,
HttpCode,
} from '@nestjs/common';
import { ApiTags, ApiOperation, ApiResponse, ApiBearerAuth } from '@nestjs/swagger';
import { CommissionService } from '../services/commission.service';
import { CommissionStatus } from '../entities/commission.entity';
import { JwtAuthGuard } from '../../auth/guards/jwt-auth.guard';
import { RolesGuard } from '../../auth/guards/roles.guard';
import { Roles } from '../../auth/decorators/roles.decorator';
import { GetUser } from '../../auth/decorators/get-user.decorator';

@ApiTags('Commissions')
@Controller('commissions')
@UseGuards(JwtAuthGuard)
@ApiBearerAuth()
export class CommissionController {
constructor(private readonly commissionService: CommissionService) {}

@Get('vendor/:vendorId')
@ApiOperation({ summary: 'Get vendor commissions' })
@ApiResponse({ status: 200, description: 'Commissions retrieved successfully' })
async getVendorCommissions(
@Param('vendorId') vendorId: string,
@Query('status') status?: CommissionStatus,
@Query('startDate') startDate?: string,
@Query('endDate') endDate?: string,
@Query('page') page?: number,
@Query('limit') limit?: number,
) {
const filters: any = { page, limit };

if (status) filters.status = status;
if (startDate && endDate) {
filters.dateRange = {
start: new Date(startDate),
end: new Date(endDate),
};
}

return this.commissionService.getVendorCommissions(vendorId, filters);
}

@Get('my-commissions')
@ApiOperation({ summary: 'Get current vendor commissions' })
@ApiResponse({ status: 200, description: 'Commissions retrieved successfully' })
async getMyCommissions(
@GetUser('vendorId') vendorId: string,
@Query('status') status?: CommissionStatus,
@Query('startDate') startDate?: string,
@Query('endDate') endDate?: string,
@Query('page') page?: number,
@Query('limit') limit?: number,
) {
const filters: any = { page, limit };

if (status) filters.status = status;
if (startDate && endDate) {
filters.dateRange = {
start: new Date(startDate),
end: new Date(endDate),
};
}

return this.commissionService.getVendorCommissions(vendorId, filters);
}

@Get('platform/summary')
@UseGuards(RolesGuard)
@Roles('admin', 'finance')
@ApiOperation({ summary: 'Get platform commission summary (Admin only)' })
@ApiResponse({ status: 200, description: 'Platform summary retrieved successfully' })
@ApiResponse({ status: 403, description: 'Forbidden' })
async getPlatformSummary(
@Query('startDate') startDate?: string,
@Query('endDate') endDate?: string,
) {
const dateRange = startDate && endDate ? {
start: new Date(startDate),
end: new Date(endDate),
} : undefined;

return this.commissionService.getPlatformCommissionSummary(dateRange);
}

@Get('overdue')
@UseGuards(RolesGuard)
@Roles('admin', 'finance')
@ApiOperation({ summary: 'Get overdue commissions (Admin only)' })
@ApiResponse({ status: 200, description: 'Overdue commissions retrieved successfully' })
@ApiResponse({ status: 403, description: 'Forbidden' })
async getOverdueCommissions() {
return this.commissionService.getOverdueCommissions();
}

@Get(':id')
@ApiOperation({ summary: 'Get commission by ID' })
@ApiResponse({ status: 200, description: 'Commission retrieved successfully' })
@ApiResponse({ status: 404, description: 'Commission not found' })
async findOne(@Param('id') id: string) {
return this.commissionService.findCommissionById(id);
}

@Post(':id/calculate')
@UseGuards(RolesGuard)
@Roles('admin', 'finance')
@ApiOperation({ summary: 'Calculate commission (Admin only)' })
@ApiResponse({ status: 200, description: 'Commission calculated successfully' })
@ApiResponse({ status: 403, description: 'Forbidden' })
@HttpCode(HttpStatus.OK)
async calculate(@Param('id') id: string) {
return this.commissionService.calculateCommission(id);
}

@Post(':id/approve')
@UseGuards(RolesGuard)
@Roles('admin', 'finance')
@ApiOperation({ summary: 'Approve commission (Admin only)' })
@ApiResponse({ status: 200, description: 'Commission approved successfully' })
@ApiResponse({ status: 403, description: 'Forbidden' })
@HttpCode(HttpStatus.OK)
async approve(@Param('id') id: string) {
return this.commissionService.approveCommission(id);
}

@Post(':id/process-payment')
@UseGuards(RolesGuard)
@Roles('admin', 'finance')
@ApiOperation({ summary: 'Process commission payment (Admin only)' })
@ApiResponse({ status: 200, description: 'Commission payment processed successfully' })
@ApiResponse({ status: 403, description: 'Forbidden' })
@HttpCode(HttpStatus.OK)
async processPayment(@Param('id') id: string) {
return this.commissionService.processCommissionPayment(id);
}

@Post('bulk-approve')
@UseGuards(RolesGuard)
@Roles('admin', 'finance')
@ApiOperation({ summary: 'Bulk approve commissions (Admin only)' })
@ApiResponse({ status: 200, description: 'Commissions approved successfully' })
@ApiResponse({ status: 403, description: 'Forbidden' })
@HttpCode(HttpStatus.OK)
async bulkApprove(@Body('commissionIds') commissionIds: string[]) {
return this.commissionService.bulkApproveCommissions(commissionIds);
}

@Post('distributions/:distributionId/retry')
@UseGuards(RolesGuard)
@Roles('admin', 'finance')
@ApiOperation({ summary: 'Retry failed payment distribution (Admin only)' })
@ApiResponse({ status: 200, description: 'Distribution retry initiated successfully' })
@ApiResponse({ status: 403, description: 'Forbidden' })
@HttpCode(HttpStatus.OK)
async retryDistribution(@Param('distributionId') distributionId: string) {
return this.commissionService.retryFailedDistribution(distributionId);
}
}
Loading