grabbit f557c06771 feat: complete database schema migration to UUID primary keys
## Database Migrations (18 new)
- Migrate all primary keys from SERIAL to UUID
- Add soft delete (deleted_at) to all 19 entities
- Add missing indexes for performance optimization
- Add CHECK constraints for data validation
- Add user audit fields (last_login_at, timezone, locale)
- Add weather station location fields (latitude, longitude, elevation)
- Add foreign key relationships (CameraDevice→Device, ValidatedEvent→WeatherStation)
- Prepare private key encryption fields

## Backend Entity Updates
- All entities updated with UUID primary keys
- Added @DeleteDateColumn for soft delete support
- Updated relations and foreign key types

## Backend Service/Controller Updates
- Changed ID parameters from number to string (UUID)
- Removed ParseIntPipe from controllers
- Updated TypeORM queries for string IDs

## Frontend Updates
- Updated all service interfaces to use string IDs
- Fixed CameraDevice.location as JSONB object
- Updated weather.ts with new fields (elevation, timezone)
- Added Supabase integration hooks and lib
- Fixed chart components for new data structure

## Cleanup
- Removed deprecated .claude/agents configuration files

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-21 03:33:26 +08:00

85 lines
2.4 KiB
TypeScript

import { Controller, Get, Post, Patch, Query, Param, Body, UseGuards } from '@nestjs/common';
import { SubscriptionService, SubscriptionQuery } from './subscription.service';
import { JwtAuthGuard } from '../auth/guards/jwt-auth.guard';
@Controller('api/v1/subscriptions')
@UseGuards(JwtAuthGuard)
export class SubscriptionController {
constructor(private readonly subscriptionService: SubscriptionService) {}
// Subscription Plans
@Get('plans')
async getAllPlans() {
return await this.subscriptionService.getAllPlans();
}
@Get('plans/stats')
async getPlanStats() {
return await this.subscriptionService.getPlanStats();
}
@Get('plans/:id')
async getPlan(@Param('id') id: string) {
return await this.subscriptionService.getPlan(id);
}
@Get('plans/by-plan-id/:planId')
async getPlanByPlanId(@Param('planId') planId: string) {
return await this.subscriptionService.getPlanByPlanId(planId);
}
// User Subscriptions
@Get('users')
async getUserSubscriptions(@Query() query: SubscriptionQuery) {
return await this.subscriptionService.getUserSubscriptions(query);
}
@Get('users/:userId')
async getUserSubscription(@Param('userId') userId: string) {
return await this.subscriptionService.getUserSubscription(userId);
}
@Post('users/:userId')
async createSubscription(
@Param('userId') userId: string,
@Body('planId') planId: string,
@Body() subscriptionData: any,
) {
return await this.subscriptionService.createSubscription(userId, planId, subscriptionData);
}
@Patch(':id/status')
async updateSubscriptionStatus(
@Param('id') id: string,
@Body('status') status: string,
@Body('metadata') metadata?: any,
) {
return await this.subscriptionService.updateSubscriptionStatus(id, status, metadata);
}
// Subscription History
@Get(':id/history')
async getSubscriptionHistory(@Param('id') id: string) {
return await this.subscriptionService.getSubscriptionHistory(id);
}
// Payment Records
@Get(':id/payments')
async getPaymentRecords(@Param('id') id: string) {
return await this.subscriptionService.getPaymentRecords(id);
}
@Post(':id/payments')
async createPaymentRecord(
@Param('id') id: string,
@Body() paymentData: any,
) {
return await this.subscriptionService.createPaymentRecord(id, paymentData);
}
// Statistics
@Get('stats')
async getSubscriptionStats() {
return await this.subscriptionService.getSubscriptionStats();
}
}