---
name: v2-refactor
description: Refactor existing V2 code to follow ideal SOLID pattern. Use when user says "refactor", "fix violations", "cleanup V2", or "/v2-refactor <path>". Analyzes code, identifies violations, and applies fixes following timeoff/balance pattern.
---

# V2 Refactor

Refactor V2 module at "$ARGUMENTS" to follow the ideal SOLID pattern.

## Before You Start

1. Read `AGENTS.md` for project conventions
2. Read `src/modules/v2/AGENTS.md` for V2 layer pattern
3. Reference `src/modules/v2/timeoff/balance/` as the ideal pattern

## Refactoring Workflow

### Step 1: Analyze Current State

Read all files in the target module:
- `*.controller.js`
- `*.service.js`
- `*.processor.js`
- `*.validator.js`
- `*.helper.js` (if exists)

### Step 2: Identify Violations

Check for these violations:

#### CRITICAL (Must Fix)

| Violation | Detection | Fix |
|-----------|-----------|-----|
| Service receives `req` | Function param is `req` | Move parsing to controller |
| Service imports repository | `import * from '#repositories/...'` | Move DB calls to processor |
| Business logic in service | `if/else`, data transforms in service | Move to processor |
| Missing validator | No `*.validator.js` | Create validator file |
| Direct `res.json()` | `res.json()` in controller | Use `responseHandler` |

#### WARNING (Should Fix)

| Violation | Detection | Fix |
|-----------|-----------|-----|
| Redis in service | `redis.del/get/set` in service | Move to helper |
| Cross-module service import | `import from '../other/*.service.js'` | Use helper or processor |

### Step 3: Plan Refactoring

Create a checklist:

```markdown
## Refactoring Plan: {module}

### Files to Modify
- [ ] {feature}.controller.js — Parse req, remove req from service calls
- [ ] {feature}.service.js — Remove business logic, pure orchestration
- [ ] {feature}.processor.js — Move business logic here
- [ ] {feature}.validator.js — Create if missing

### Files to Create
- [ ] {feature}.helper.js — For cache/shared logic (if needed)

### Violations Found
1. ❌ Service receives `req` in `functionName()`
2. ❌ Business logic in service: `if (type === 'overtime')`
3. ⚠️ Redis operations in service
```

### Step 4: Apply Fixes

#### Fix 1: Service Receives `req`

**Before:**
```javascript
// service.js
export async function createFeature(req) {
  const { body, user, uploadedFiles } = req;
  // ...
}
```

**After:**
```javascript
// controller.js
export async function createFeature(req, res) {
  const payload = req.body;
  const user = req.user;
  const file = req.uploadedFiles?.[0] || null;

  const result = await featureService.createFeature(payload, user, file);
  // ...
}

// service.js
export async function createFeature(payload, user, file) {
  const validation = featureValidator.validate(payload, file);
  if (!validation.success) return validation;
  return await featureProcessor.process(validation.data, user);
}
```

#### Fix 2: Business Logic in Service

**Before:**
```javascript
// service.js
export async function clockIn(payload, type) {
  const isOvertime = type === 'overtime';
  const scheduleType = isOvertime ? 'overtime' : 'reguler';

  if (schedule.shift_name === 'dayoff') {
    return { success: false, message: 'Cannot clock in on day off' };
  }
  // more logic...
}
```

**After:**
```javascript
// service.js
export async function clockIn(payload, type) {
  const validation = clockValidator.validateClockIn(payload, type);
  if (!validation.success) return validation;
  return await clockProcessor.processClockIn(validation.data);
}

// processor.js
export async function processClockIn(data) {
  const isOvertime = data.type === 'overtime';
  const scheduleType = isOvertime ? 'overtime' : 'reguler';

  if (data.schedule.shift_name === 'dayoff') {
    return { success: false, type: 'INVALID_ACTION', message: 'Cannot clock in on day off', status: 400 };
  }
  // business logic here...
}
```

#### Fix 3: Redis/Cache in Service

**Before:**
```javascript
// service.js
import { getRedisClient } from '#utils/redis.js';
const redis = getRedisClient();

export async function createFeature(data) {
  // ... logic
  await redis.del(`Cache:${data.id}`);
}
```

**After:**
```javascript
// helper.js
import { getRedisClient } from '#utils/redis.js';
import logger from '#utils/logger.js';

const redis = getRedisClient();

export async function invalidateFeatureCache(id) {
  try {
    await redis.del(`Cache:${id}`);
    logger.info(`[FEATURE][CACHE] >>> Invalidated: ${id}`);
  } catch (err) {
    logger.warn(`[FEATURE][CACHE] >>> Failed: ${err.message}`);
  }
}

// processor.js
import * as featureHelper from './feature.helper.js';

export async function processCreate(data) {
  // ... logic
  await featureHelper.invalidateFeatureCache(data.id);
}
```

#### Fix 4: Missing Validator

**Create new file:**
```javascript
// {feature}.validator.js
import { httpStatusCode } from '#helpers/constants.js';
import { buildMissingMessage } from '#modules/v2/shared/validation.helper.js';

export function validateCreatePayload(payload, file, user) {
  const missing = [];

  if (!payload.name) missing.push('name');
  if (!payload.date) missing.push('date');

  if (missing.length > 0) {
    return {
      success: false,
      type: 'VALIDATION_ERROR',
      message: buildMissingMessage(missing),
      status: httpStatusCode.BAD_REQUEST
    };
  }

  return {
    success: true,
    data: {
      ...payload,
      file,
      userId: user.employee_id,
      companyId: user.company_id
    }
  };
}
```

### Step 5: Verify

After refactoring:

1. Check all imports resolve correctly
2. Verify return types are consistent `{ success, data, message }`
3. Run tests if available: `npm test`
4. Trace a request path to ensure flow works

### Step 6: Report

Provide summary:

```markdown
## Refactoring Complete: {module}

### Changes Made
- ✅ Controller now parses `req` and passes individual params
- ✅ Service is now pure orchestration (validator → processor)
- ✅ Business logic moved to processor
- ✅ Created `{feature}.helper.js` for cache operations
- ✅ Created `{feature}.validator.js` (was missing)

### Files Modified
- `{feature}.controller.js` — 3 functions updated
- `{feature}.service.js` — 5 functions simplified
- `{feature}.processor.js` — Added business logic from service

### Files Created
- `{feature}.validator.js` — New file
- `{feature}.helper.js` — New file

### Remaining Issues
- ⚠️ Cross-module import still exists (requires larger refactor)
```

## Reference Pattern

Always reference `src/modules/v2/timeoff/balance/` for the ideal implementation:

```
timeoff/balance/
├── balance.controller.js  # Clean req parsing
├── balance.service.js     # Pure orchestration
├── balance.processor.js   # All business logic
└── balance.validator.js   # Input validation
```

## Important Notes

- Make incremental changes — don't refactor everything at once
- Test after each major change
- Keep backward compatibility for existing API contracts
- Document any breaking changes
- If unsure, ask user before making changes
