# Prompt for Claude Code: Workflow Schedule Module Implementation

## Project Context

**Project Path**: `/Users/debrajdas/WORKSPACE/001_RZ/PROJECTS/ETHER/250218_nodejs_core`  
**Framework**: NestJS with TypeORM  
**Database**: MySQL  
**Task**: Implement complete workflow schedule module with Bull queue

---

## Implementation Request

I need you to implement a complete scheduled workflow system in my NestJS project. This will extend the existing workflow module to support time-based workflow execution using cron schedules.

### Target Location
Create all files in: `src/module/workflow-schedule/`

---

## Required Files and Implementation

### 1. Module Structure

Create the following directory structure:
```
src/module/workflow-schedule/
├── workflow-schedule.module.ts
├── workflow-schedule.service.ts
├── workflow-schedule.controller.ts
├── constants/
│   └── schedule.constants.ts
├── dto/
│   ├── create-schedule.dto.ts
│   ├── update-schedule.dto.ts
│   └── get-execution-logs.dto.ts
├── entities/
│   ├── scheduled-workflow.entity.ts
│   └── workflow-execution-log.entity.ts
├── interfaces/
│   └── schedule-job-data.interface.ts
├── processors/
│   └── schedule.processor.ts
└── tests/
    └── workflow-schedule.service.spec.ts
```

### 2. Database Migrations

Create in: `src/migrations/`

**Migration 1**: Add `workflow_type` column to workflows table
- Column: `workflow_type ENUM('trigger', 'schedule') DEFAULT 'trigger'`

**Migration 2**: Create `scheduled_workflows` table with:
- id, workflow_id (FK), schedule_expression, timezone
- is_active, last_executed_at, next_execution_at, execution_count
- start_date, end_date, created_at, updated_at
- Indexes: (next_execution_at, is_active), (workflow_id)

**Migration 3**: Create `workflow_execution_logs` table with:
- id, workflow_id (FK), execution_type, status
- started_at, completed_at, records_processed, records_failed
- error_message, job_id, execution_data (JSON)
- Indexes: (workflow_id, status), (started_at), (execution_type)

### 3. Configuration

Create: `src/config/bull.config.ts`
- Export `getBullConfig()` function returning BullModuleOptions
- Read from env: REDIS_HOST, REDIS_PORT, REDIS_PASSWORD, REDIS_DB
- Configure: retry strategy, job options, queue settings

---

## Detailed Requirements

### Entities

**scheduled-workflow.entity.ts**:
- TypeORM entity for `scheduled_workflows` table
- Relations: `@ManyToOne(() => Workflow)`
- Proper column decorators with snake_case naming
- Indexes using @Index decorator

**workflow-execution-log.entity.ts**:
- TypeORM entity for `workflow_execution_logs` table
- Enums: ExecutionType (trigger/schedule/manual), ExecutionStatus (running/success/failed/partial_success)
- Computed properties: `durationMs()`, `successRate()`

### DTOs

**create-schedule.dto.ts**:
```typescript
- workflowId: number (required)
- scheduleExpression: string (required, cron format validation)
- timezone: string (optional, IANA format, default: 'UTC')
- startDate: string (optional, ISO date)
- endDate: string (optional, ISO date)
- isActive: boolean (optional, default: true)
```

**update-schedule.dto.ts**:
- All fields optional from CreateScheduleDto

**get-execution-logs.dto.ts**:
```typescript
- status: ExecutionStatus (optional)
- executionType: ExecutionType (optional)
- limit: number (optional, default: 50, max: 500)
- offset: number (optional, default: 0)
```

Use `class-validator` decorators for all validation.

### Service (workflow-schedule.service.ts)

Implement these methods:

1. **scheduleWorkflow(dto: CreateScheduleDto): Promise<ScheduledWorkflow>**
   - Validate cron expression using cron-parser
   - Validate timezone using moment-timezone
   - Calculate next execution time
   - Create schedule in database
   - Add job to Bull queue if active

2. **updateSchedule(id: number, dto: UpdateScheduleDto): Promise<ScheduledWorkflow>**
   - Find schedule or throw NotFoundException
   - Validate updates
   - Recalculate next execution
   - Update Bull queue job

3. **deleteSchedule(id: number): Promise<void>**
   - Remove from database
   - Remove job from Bull queue

4. **pauseSchedule(id: number): Promise<ScheduledWorkflow>**
   - Set isActive = false
   - Remove job from queue

5. **resumeSchedule(id: number): Promise<ScheduledWorkflow>**
   - Set isActive = true
   - Recalculate next execution
   - Add job back to queue

6. **triggerSchedule(id: number): Promise<WorkflowExecutionLog>**
   - Create execution log with type 'manual'
   - Add high-priority job to queue

7. **getExecutionLogs(scheduleId, query): Promise<{logs, total}>**
   - Query with filters (status, executionType)
   - Pagination (limit, offset)
   - Order by startedAt DESC

8. **getScheduledJobs(): Promise<ScheduledWorkflow[]>**
   - Return all active schedules with relations

9. **getScheduleById(id): Promise<ScheduledWorkflow>**
   - Find with relations or throw NotFoundException

### Controller (workflow-schedule.controller.ts)

REST API endpoints with Swagger decorators:

```
POST   /workflow-schedule           - create()
GET    /workflow-schedule           - getAll()
GET    /workflow-schedule/:id       - getById()
PUT    /workflow-schedule/:id       - update()
DELETE /workflow-schedule/:id       - delete()
POST   /workflow-schedule/:id/pause - pause()
POST   /workflow-schedule/:id/resume - resume()
POST   /workflow-schedule/:id/trigger - trigger()
GET    /workflow-schedule/:id/logs  - getLogs()
```

Add @ApiTags, @ApiOperation, @ApiResponse decorators.

### Processor (schedule.processor.ts)

Bull queue processor with:

**@Process() handleScheduledJob(job: Job<ScheduleJobData>)**:
1. Create execution log (status: 'running')
2. Verify schedule is still active and hasn't ended
3. Get workflow configuration
4. Query records matching workflow criteria
5. Process in batches of 100 records
6. Execute actions for each record:
   - sendEmail(config, record)
   - updateRecord(config, record)
   - createTask(config, record)
   - sendNotification(config, record)
7. Handle template variables: `{{record.field}}`, `{{current_date}}`
8. Update execution log with results
9. Update schedule (last_executed_at, execution_count, next_execution_at)
10. Schedule next job

**Error handling**:
- Try/catch around entire process
- Log errors to execution log
- Retry with exponential backoff (3 attempts)

**Lifecycle hooks**:
- @OnQueueActive() - Log job start
- @OnQueueCompleted() - Log success
- @OnQueueFailed() - Log failure

### Constants (schedule.constants.ts)

```typescript
export const SCHEDULE_QUEUE_NAME = 'workflow-schedule';
export const MAX_BATCH_SIZE = 100;
export const EXECUTION_TIMEOUT_MS = 30 * 60 * 1000;

export const DEFAULT_JOB_OPTIONS = {
  attempts: 3,
  backoff: { type: 'exponential', delay: 5000 },
  removeOnComplete: false,
  removeOnFail: false,
};

export const COMMON_CRON_EXPRESSIONS = {
  EVERY_MINUTE: '* * * * *',
  EVERY_HOUR: '0 * * * *',
  EVERY_DAY_9AM: '0 9 * * *',
  EVERY_MONDAY_9AM: '0 9 * * 1',
  // ... etc
};
```

### Interfaces (schedule-job-data.interface.ts)

```typescript
export interface ScheduleJobData {
  scheduleId: number;
  workflowId: number;
  workflowName: string;
  scheduledAt: Date;
  attempt: number;
}

export interface WorkflowExecutionResult {
  success: boolean;
  recordsProcessed: number;
  recordsFailed: number;
  errorMessage?: string;
  executionData?: Record<string, any>;
}
```

### Module (workflow-schedule.module.ts)

```typescript
@Module({
  imports: [
    TypeOrmModule.forFeature([ScheduledWorkflow, WorkflowExecutionLog]),
    BullModule.registerQueue({ name: SCHEDULE_QUEUE_NAME }),
    WorkflowModule,
  ],
  controllers: [WorkflowScheduleController],
  providers: [WorkflowScheduleService, ScheduleProcessor],
  exports: [WorkflowScheduleService],
})
export class WorkflowScheduleModule {}
```

---

## Additional Requirements

### Update app.module.ts

Add imports:
```typescript
import { BullModule } from '@nestjs/bull';
import { WorkflowScheduleModule } from './module/workflow-schedule/workflow-schedule.module';
import { getBullConfig } from './config/bull.config';
```

Add to imports array:
```typescript
BullModule.forRootAsync({
  imports: [ConfigModule],
  inject: [ConfigService],
  useFactory: getBullConfig,
}),
WorkflowScheduleModule,
```

### Tests

Create comprehensive unit tests in `workflow-schedule.service.spec.ts`:
- Test all service methods
- Mock TypeORM repositories
- Mock Bull queue
- Test validation (invalid cron, invalid timezone)
- Test error cases (not found, etc.)

---

## Code Quality Requirements

1. **TypeScript**: Use strict types, no `any` unless necessary
2. **Error Handling**: Proper exceptions (NotFoundException, BadRequestException)
3. **Validation**: Use class-validator decorators
4. **Documentation**: JSDoc comments for all public methods
5. **Naming**: camelCase for variables, PascalCase for classes
6. **Async/Await**: Use async/await, not .then()
7. **Imports**: Organized and clean
8. **Logging**: Use Logger from @nestjs/common

---

## Dependencies (already in package.json, but for reference)

```
@nestjs/bull
bull
ioredis
cron-parser
moment-timezone
class-validator
class-transformer
```

---

## Expected Behavior

After implementation:
- ✅ Can create schedules via REST API
- ✅ Schedules execute automatically at cron time
- ✅ Can pause/resume schedules
- ✅ Can manually trigger execution
- ✅ Execution logs are created with detailed metrics
- ✅ Failed jobs retry 3 times with exponential backoff
- ✅ Records processed in batches of 100
- ✅ Template variables work correctly

---

## Notes

- Assume existing Workflow entity exists at `src/module/workflow/entities/workflow.entity.ts`
- Assume WorkflowService exists and has necessary methods
- Use proper TypeORM relationships and cascades
- Follow NestJS best practices
- Make code production-ready

---

## Please Implement

Create all the files listed above with complete, working code. Ensure:
1. All TypeScript types are correct
2. All decorators are properly used
3. Error handling is comprehensive
4. Code follows NestJS conventions
5. Everything is well-documented

Start with the entities and migrations, then services, then controller, then processor.
