feat(db): implement complete database schema and models

- Add Prisma schema with PostgreSQL 15 support
- Create Users, Batches, Images, Payments, ApiKeys tables
- Implement proper foreign key relationships and indexes
- Add enum types for status fields (Plan, BatchStatus, ImageStatus, PaymentStatus)
- Support for JSON fields (vision_tags, metadata)
- UUID primary keys for security
- Created/updated timestamps with proper defaults

Database Layer Components:
- Prisma service with connection management and health checks
- Repository pattern for all entities with comprehensive CRUD operations
- TypeScript DTOs with class-validator decorations
- Swagger API documentation annotations
- Helper functions for business logic (quota management, pricing, etc.)

Development Support:
- Environment variables template
- Database seed script with realistic test data
- TypeScript configuration optimized for Nest.js
- Package.json with all required dependencies

Resolves database requirements from issues §78-81 establishing
the complete data layer foundation for the AI Bulk Image Renamer SaaS.

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

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
DustyWalker 2025-08-05 17:02:03 +02:00
parent 90016254a9
commit e7e09d5e2c
15 changed files with 3606 additions and 0 deletions

View file

@ -0,0 +1,227 @@
import {
IsString,
IsEnum,
IsInt,
IsOptional,
IsUUID,
IsObject,
Min,
IsDate
} from 'class-validator';
import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger';
import { BatchStatus } from '@prisma/client';
import { Type } from 'class-transformer';
export class CreateBatchDto {
@ApiProperty({
description: 'ID of the user creating the batch',
example: '550e8400-e29b-41d4-a716-446655440000'
})
@IsUUID()
userId: string;
@ApiPropertyOptional({
description: 'Total number of images in this batch',
example: 10,
minimum: 0
})
@IsOptional()
@IsInt()
@Min(0)
totalImages?: number;
@ApiPropertyOptional({
description: 'Additional metadata for the batch processing',
example: {
aiModel: 'gpt-4-vision',
processingOptions: { includeColors: true, includeTags: true }
}
})
@IsOptional()
@IsObject()
metadata?: Record<string, any>;
}
export class UpdateBatchDto {
@ApiPropertyOptional({
description: 'Batch processing status',
enum: BatchStatus
})
@IsOptional()
@IsEnum(BatchStatus)
status?: BatchStatus;
@ApiPropertyOptional({
description: 'Total number of images in this batch',
minimum: 0
})
@IsOptional()
@IsInt()
@Min(0)
totalImages?: number;
@ApiPropertyOptional({
description: 'Number of processed images',
minimum: 0
})
@IsOptional()
@IsInt()
@Min(0)
processedImages?: number;
@ApiPropertyOptional({
description: 'Number of failed images',
minimum: 0
})
@IsOptional()
@IsInt()
@Min(0)
failedImages?: number;
@ApiPropertyOptional({
description: 'Additional metadata for the batch processing'
})
@IsOptional()
@IsObject()
metadata?: Record<string, any>;
}
export class BatchResponseDto {
@ApiProperty({
description: 'Unique batch identifier',
example: '550e8400-e29b-41d4-a716-446655440000'
})
@IsUUID()
id: string;
@ApiProperty({
description: 'ID of the user who owns this batch',
example: '550e8400-e29b-41d4-a716-446655440000'
})
@IsUUID()
userId: string;
@ApiProperty({
description: 'Current batch processing status',
enum: BatchStatus
})
@IsEnum(BatchStatus)
status: BatchStatus;
@ApiProperty({
description: 'Total number of images in this batch',
example: 10
})
@IsInt()
@Min(0)
totalImages: number;
@ApiProperty({
description: 'Number of processed images',
example: 8
})
@IsInt()
@Min(0)
processedImages: number;
@ApiProperty({
description: 'Number of failed images',
example: 1
})
@IsInt()
@Min(0)
failedImages: number;
@ApiPropertyOptional({
description: 'Additional metadata for the batch processing'
})
@IsOptional()
@IsObject()
metadata?: Record<string, any>;
@ApiProperty({
description: 'Batch creation timestamp'
})
@IsDate()
createdAt: Date;
@ApiProperty({
description: 'Batch last update timestamp'
})
@IsDate()
updatedAt: Date;
@ApiPropertyOptional({
description: 'Batch completion timestamp'
})
@IsOptional()
@IsDate()
completedAt?: Date;
}
export class BatchStatsDto {
@ApiProperty({
description: 'Processing progress percentage',
example: 80
})
@IsInt()
@Min(0)
progressPercentage: number;
@ApiProperty({
description: 'Number of pending images',
example: 1
})
@IsInt()
@Min(0)
pendingImages: number;
@ApiProperty({
description: 'Average processing time per image in seconds',
example: 5.2
})
@Type(() => Number)
averageProcessingTime: number;
@ApiProperty({
description: 'Estimated time remaining in seconds',
example: 30
})
@Type(() => Number)
estimatedTimeRemaining: number;
}
export class BatchSummaryDto {
@ApiProperty({
description: 'Batch details'
})
batch: BatchResponseDto;
@ApiProperty({
description: 'Processing statistics'
})
stats: BatchStatsDto;
@ApiProperty({
description: 'Recent images from this batch (limited to 5)'
})
recentImages: Array<{
id: string;
originalName: string;
proposedName?: string;
status: string;
}>;
}
// Helper function to calculate progress percentage
export function calculateProgressPercentage(processedImages: number, totalImages: number): number {
if (totalImages === 0) return 0;
return Math.round((processedImages / totalImages) * 100);
}
// Helper function to determine if batch is complete
export function isBatchComplete(batch: { status: BatchStatus; processedImages: number; failedImages: number; totalImages: number }): boolean {
return batch.status === BatchStatus.DONE ||
batch.status === BatchStatus.ERROR ||
(batch.processedImages + batch.failedImages) >= batch.totalImages;
}