# Savings Module - Code Analysis & Refactoring Plan

Generated: 2026-02-04

## Executive Summary

The Savings module is well-structured but contains several areas for improvement:
- **Unused DataTable filter input** (hardcoded, conflicts with server-side filtering)
- **Duplicate status configurations** (savings.ts vs status-badge.tsx)
- **Unused imports and type interfaces**
- **Deprecated type definitions** (PaginatedSavingsAccounts, PaginatedSavingsTransactions)
- **Missing last_transaction_date usage** in backend
- **Potential audit logging issues** (missing AuditLog import)

---

## 1. UNUSED CODE & DEPRECATED DEFINITIONS

### 1.1 DataTable Component - Hardcoded Filter Input ⚠️ CRITICAL

**File:** `resources/js/components/ui/data-table.tsx:99-108`

```typescript
// ❌ UNUSED - Conflicts with server-side filtering
<div className="flex items-center py-4">
  <Input
    placeholder="Filter names..."
    value={(table.getColumn("name")?.getFilterValue() as string) ?? ""}
    onChange={(event) =>
      table.getColumn("name")?.setFilterValue(event.target.value)
    }
    className="max-w-sm"
  />
</div>
```

**Issues:**
- Hardcoded to "name" column only
- Not used in Savings/Index.tsx (has its own filters)
- Client-side filter that only filters current page data
- Causes confusion if accidentally displayed

**Impact:** Medium - Creates confusion, doesn't work with server-side pagination

**Fix Required:** Remove this hardcoded input or make it optional via prop

---

### 1.2 Duplicate Status Configuration

**Files:**
- `resources/js/types/savings.ts:145-155`
- `resources/js/components/ui/status-badge.tsx:23-39`

**savings.ts defines:**
```typescript
export const savingsStatusConfig = {
  active: { label: 'Aktif', color: 'bg-green-100...' },
  inactive: { label: 'Tidak Aktif', color: 'bg-gray-100...' },
  frozen: { label: 'Dibekukan', color: 'bg-yellow-100...' },
  closed: { label: 'Tutup', color: 'bg-red-100...' },
} as const
```

**status-badge.tsx defines:**
```typescript
const statusConfig: Record<string, Record<string, StatusConfig>> = {
  savings: {
    active: { label: 'Aktif', className: 'bg-green-100...' },
    inactive: { label: 'Tidak Aktif', className: 'bg-gray-100...' },
    frozen: { label: 'Dibekukan', className: 'bg-yellow-100...' },
    closed: { label: 'Tutup', className: 'bg-red-100...' },
  },
}
```

**Issues:**
- Duplicate configuration
- `savingsStatusConfig` in savings.ts is never used
- Property name mismatch: `color` vs `className`
- `transactionTypeConfig` also unused (defined but not referenced)

**Impact:** Low - Code bloat, potential confusion

**Fix Required:** Remove unused configs from savings.ts, use StatusBadge component only

---

### 1.3 Unused Type Interfaces

**File:** `resources/js/types/savings.ts:75-105`

```typescript
// ❌ UNUSED - PaginatedData is used instead
export interface PaginatedSavingsAccounts {
  data: SavingsAccount[]
  current_page: number
  last_page: number
  per_page: number
  total: number
  from?: number
  to?: number
  links?: { ... }
}

export interface PaginatedSavingsTransactions {
  // ... same structure
}
```

**Actual usage in components:**
```typescript
// Savings/Index.tsx:44
interface PageProps {
  accounts: PaginatedData<SavingsAccount>;  // ✅ Uses generic type
  products: SavingsProduct[];
  branches: Branch[];
  filters: SavingsFilters;
}
```

**Issues:**
- These interfaces are defined but never used
- Generic `PaginatedData<T>` from '@/types' is used instead
- Creates confusion about which type to use

**Impact:** Low - Dead code

**Fix Required:** Remove these unused interfaces

---

### 1.4 Unused Helper Functions

**File:** `resources/js/types/savings.ts:157-175`

```typescript
// ❌ UNUSED - formatIDR and formatDateID defined but could be in utility file
export function formatIDR(amount: number): string { ... }
export function formatDateID(date: string | null): string { ... }
```

**Issues:**
- Utility functions mixed with type definitions
- Should be in `lib/utils.ts` or separate utility file
- Not necessarily "unused" but poorly organized

**Impact:** Low - Organization issue

**Fix Required:** Move to `lib/utils.ts` or `lib/formatters.ts`

---

## 2. BACKEND ISSUES

### 2.1 Missing AuditLog Import ⚠️ CRITICAL

**File:** `app/Models/SavingsAccount.php:191`

```php
static::updating(function ($account) {
    $account->updated_by = Auth::id();

    if ($account->isDirty('balance')) {
        AuditLog::log('savings_balance_changed', $account, [  // ❌ Class not found
            'user_id' => Auth::id(),
            'old_values' => $account->getOriginal(),
            'new_values' => $account->toArray(),
        ]);
    }
});
```

**Same issue in:**
- `SavingsTransaction.php:153`

**Issues:**
- `AuditLog` class is not imported
- Will cause runtime error when balance changes
- Critical for OJK compliance

**Impact:** CRITICAL - Application crash on balance updates

**Fix Required:** Add `use App\Models\AuditLog;` import or remove AuditLog calls

---

### 2.2 Unused last_transaction_date Field

**File:** `app/Models/SavingsAccount.php`

**Migration defines:**
```php
$table->timestamp('last_transaction_date')->nullable();
```

**TypeScript interface:**
```typescript
last_transaction_date: string | null  // ✅ Defined
```

**Usage:**
```typescript
// ❌ Never displayed in UI or accessed
```

**Issues:**
- Field is tracked but never used
- Should be displayed in account summary or list view
- Valuable for showing account activity

**Impact:** Low - Missed feature opportunity

**Fix Required:** Display in UI or remove field

---

### 2.3 Unused Accessor

**File:** `app/Models/SavingsAccount.php:113-116`

```php
public function getAccountNumberWithNameAttribute(): string
{
    return "{$this->account_number} - {$this->account_name}";
}
```

**Issues:**
- Accessor defined but never used
- Could be useful for dropdown selects

**Impact:** Low - Dead code

**Fix Required:** Use in UI or remove

---

## 3. FRONTEND CODE QUALITY ISSUES

### 3.1 Unnecessary optional chaining on guaranteed fields

**File:** `resources/js/pages/Savings/Index.tsx:89, 94`

```typescript
cell: ({ row }) => row.original.branch?.name || '-',
cell: ({ row }) => row.original.savingsProduct?.name || '-',
```

**Backend relationship:**
```php
public function branch(): BelongsTo { ... }
public function savingsProduct(): BelongsTo { ... }
```

**Issues:**
- If backend always eager loads these relationships, optional chaining is unnecessary
- Creates inconsistent code style
- Some use `row.original.member.name` (no optional), others use `?.`

**Impact:** Very Low - Code style consistency

**Fix Required:** Verify eager loading and standardize

---

### 3.2 Missing null checks in Transactions.tsx

**File:** `resources/js/pages/Savings/Transactions.tsx:26`

```typescript
const breadcrumbs: BreadcrumbItem[] = [
    { title: 'Simpanan', href: '/savings' },  // ❌ Hardcoded
    { title: 'Transaksi', href: '#' },
];
```

**Issues:**
- Hardcoded URL instead of using `savingsRoutes.index().url`
- Inconsistent with other pages

**Impact:** Low - Code consistency

**Fix Required:** Use `savingsRoutes.index().url`

---

### 3.3 Inconsistent exportToCSV implementations

**Files:**
- `Savings/Index.tsx:269-301`
- `Savings/Transactions.tsx:141-171`
- `Members/Index.tsx:252-282`

**Issues:**
- Same logic duplicated across 3 files
- Should be extracted to shared utility

**Impact:** Low - Code duplication

**Fix Required:** Create `lib/exportToCSV.ts` utility

---

## 4. DEPRECATED INERTIA v1 PATTERNS

### 4.1 Manual URLSearchParams Instead of useSearchParams

**Current pattern:**
```typescript
const handleSearch = (value: string) => {
    const params = new URLSearchParams(window.location.search);
    if (value) {
        params.set('search', value);
    } else {
        params.delete('search');
    }
    params.delete('page');
    router.visit(`${savingsRoutes.index().url}?${params.toString()}`);
};
```

**Issues:**
- Repeated in 4 separate functions per page
- Should use a custom hook

**Impact:** Low - Code duplication

**Fix Required:** Create `useFilterParams()` hook

---

## 5. REFACTORING PRIORITY

### Priority 1 (CRITICAL) - Must Fix

1. **Remove/fix DataTable hardcoded filter** - Conflicts with server-side filtering
2. **Fix missing AuditLog import** - Will cause runtime errors

### Priority 2 (HIGH) - Should Fix

3. **Remove duplicate status configs** - Code bloat
4. **Remove unused type interfaces** - Confusion
5. **Display last_transaction_date** - Valuable feature

### Priority 3 (MEDIUM) - Nice to Have

6. **Extract exportToCSV utility** - Code duplication
7. **Create useFilterParams hook** - Reduce repetition
8. **Move formatter functions** - Better organization
9. **Use accessor or remove it** - Dead code

### Priority 4 (LOW) - Optional

10. **Standardize optional chaining** - Code consistency
11. **Fix hardcoded breadcrumb** - Consistency

---

## 6. RECOMMENDED FILE STRUCTURE AFTER REFACTOR

```
resources/js/
├── lib/
│   ├── formatters.ts        # NEW: formatIDR, formatDateID
│   ├── exportToCSV.ts       # NEW: CSV export utility
│   └── hooks/
│       └── useFilterParams.ts  # NEW: Filter params hook
├── types/
│   └── savings.ts           # CLEANED: Remove unused configs/types
└── components/
    └── ui/
        └── data-table.tsx   # FIXED: Remove hardcoded filter
```

---

## 7. TESTING CHECKLIST

After refactoring, ensure:
- [ ] All savings pages load without errors
- [ ] Filters work correctly (search, branch, product, status)
- [ ] Pagination works
- [ ] Deposit/withdrawal forms work
- [ ] CSV export works
- [ ] Status badges display correctly
- [ ] Account closing works
- [ ] Balance changes trigger audit logs (if enabled)
- [ ] No console errors

---

## 8. FILES TO MODIFY

### Delete Code From:
1. `resources/js/components/ui/data-table.tsx` - Remove lines 99-108
2. `resources/js/types/savings.ts` - Remove unused configs/interfaces

### Add Imports To:
3. `app/Models/SavingsAccount.php` - Add AuditLog import
4. `app/Models/SavingsTransaction.php` - Add AuditLog import

### Create New Files:
5. `resources/js/lib/formatters.ts` - Move formatIDR, formatDateID
6. `resources/js/lib/exportToCSV.ts` - Extract CSV logic
7. `resources/js/lib/hooks/useFilterParams.ts` - Filter hook

### Modify Files:
8. `resources/js/pages/Savings/*.tsx` - Use new utilities
9. `resources/js/pages/Members/Index.tsx` - Use exportToCSV utility

---

## Summary Statistics

- **Total Issues Found:** 11
- **Critical Issues:** 2
- **High Priority:** 3
- **Medium Priority:** 4
- **Low Priority:** 2
- **Files Affected:** 13
- **Estimated Refactoring Time:** 2-3 hours
