interacmanagernew / files /README.md
MichaelEdou
Initial commit β€” ICC Interac Manager full-stack app
149698e
# ICC Interac Manager β€” Scan Implementation
## What This Fixes
The "Scanner maintenant" button now actually **connects to Gmail**, **fetches Interac e-Transfer emails**, **parses them with AI** (Groq/Mistral), and **saves parsed transactions** to the database β€” all with real-time progress via WebSocket.
---
## File Map
```
icc-scan-impl/
β”œβ”€β”€ .env.example ← Copy to .env and fill in API keys
β”‚
β”œβ”€β”€ shared/ ← Shared types & constants
β”‚ β”œβ”€β”€ types/
β”‚ β”‚ β”œβ”€β”€ scan.ts ← ScanPreset, ScanDateRange, resolveScanDates()
β”‚ β”‚ β”œβ”€β”€ transaction.ts ← InteracTransaction schema
β”‚ β”‚ └── aiProvider.ts ← ProviderSlot, SwitcherEvent
β”‚ └── constants/
β”‚ └── branches.ts ← 48-branch emailβ†’city mapping
β”‚
β”œβ”€β”€ server/ ← Backend (Express + SQLite)
β”‚ β”œβ”€β”€ index.ts ← Server entry point
β”‚ β”œβ”€β”€ db/
β”‚ β”‚ └── database.ts ← SQLite schema + operations
β”‚ β”œβ”€β”€ middleware/
β”‚ β”‚ └── auth.ts ← JWT middleware
β”‚ β”œβ”€β”€ routes/
β”‚ β”‚ β”œβ”€β”€ auth.ts ← Google OAuth routes
β”‚ β”‚ β”œβ”€β”€ scan.ts ← POST /api/scan/start
β”‚ β”‚ └── transactions.ts ← GET /api/transactions
β”‚ β”œβ”€β”€ services/
β”‚ β”‚ β”œβ”€β”€ gmailService.ts ← Gmail API: query builder + email fetcher
β”‚ β”‚ β”œβ”€β”€ aiService.ts ← AI parsing: Groq + Mistral + auto-switcher
β”‚ β”‚ └── scanService.ts ← Scan pipeline: Gmail β†’ AI β†’ DB
β”‚ └── websocket/
β”‚ └── setup.ts ← WebSocket server for progress events
β”‚
└── web/ ← Frontend (React)
β”œβ”€β”€ services/
β”‚ β”œβ”€β”€ api.ts ← HTTP client with auth
β”‚ └── websocket.ts ← WebSocket client
β”œβ”€β”€ hooks/
β”‚ └── useEmailScan.ts ← React hook for scan state + progress
β”œβ”€β”€ components/scan/
β”‚ └── ScanControls.tsx ← β˜… THE scan button component
└── pages/
└── AuthCallback.tsx ← Handles OAuth redirect
```
---
## Setup Steps
### 1. Install Dependencies
In your `packages/server/` directory:
```bash
npm install express cors helmet dotenv googleapis jsonwebtoken better-sqlite3 ws uuid p-limit zod
npm install -D typescript @types/express @types/cors @types/jsonwebtoken @types/better-sqlite3 @types/ws @types/uuid tsx
```
In your `packages/web/` directory (most likely already installed):
```bash
npm install react-router-dom
```
### 2. Configure Google OAuth
1. Go to [Google Cloud Console](https://console.cloud.google.com/apis/credentials)
2. Create a project (or use existing)
3. Enable the **Gmail API**
4. Create **OAuth 2.0 Client ID** (Web application)
5. Add authorized redirect URI: `http://localhost:3001/api/auth/google/callback`
6. Copy the Client ID and Client Secret
### 3. Get AI API Keys (Free)
Pick at least one:
- **Groq** (recommended primary): [console.groq.com/keys](https://console.groq.com/keys) β€” 30 RPM free
- **Mistral** (recommended fallback): [console.mistral.ai/api-keys](https://console.mistral.ai/api-keys) β€” free tier
### 4. Create .env File
```bash
cp .env.example .env
# Edit .env with your actual keys
```
### 5. Copy Files Into Your Project
Copy each file from this package into the corresponding location in your monorepo.
The file paths in this package mirror the target paths in your project.
### 6. Add Vite Proxy (vite.config.ts)
Make sure your Vite dev server proxies API calls to the backend:
```typescript
// packages/web/vite.config.ts
export default defineConfig({
server: {
proxy: {
'/api': 'http://localhost:3001',
'/ws': {
target: 'ws://localhost:3001',
ws: true,
},
},
},
});
```
### 7. Add Route for Auth Callback
In your React Router config:
```tsx
import AuthCallback from './pages/AuthCallback';
// Add this route:
<Route path="/auth/callback" element={<AuthCallback />} />
```
### 8. Wire Up ScanControls in Your Dashboard
Replace your current scan button section with the new `ScanControls` component:
```tsx
import ScanControls from '@/components/scan/ScanControls';
function DashboardPage() {
const { refetch } = useTransactions(); // your existing hook
return (
<div>
<ScanControls
onScanComplete={(result) => {
// Refresh transaction table after scan completes
refetch();
}}
/>
{/* ... rest of your dashboard ... */}
</div>
);
}
```
### 9. Start the Backend
```bash
cd packages/server
npx tsx src/index.ts
```
You should see:
```
πŸš€ ICC Interac Manager API running on http://localhost:3001
πŸ”— WebSocket available at ws://localhost:3001/ws
πŸ”‘ Google OAuth: http://localhost:3001/api/auth/google
```
### 10. Start the Frontend
```bash
cd packages/web
npm run dev
```
---
## How It Works (Flow)
```
User clicks "Scanner maintenant"
β”‚
β–Ό
β”Œβ”€ ScanControls.tsx ──────────────────────────┐
β”‚ 1. Reads selected preset (today/7days/custom)β”‚
β”‚ 2. Calls api.startScan({ preset, dates }) β”‚
β”‚ 3. Connects to WebSocket for progress events β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
β”‚ POST /api/scan/start
β–Ό
β”Œβ”€ scan.ts (route) ──────────────────────────┐
β”‚ 1. Validates preset + dates β”‚
β”‚ 2. Calls scanService.executeScan() β”‚
β”‚ 3. Returns immediately (async background) β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
β”‚
β–Ό
β”Œβ”€ scanService.ts ───────────────────────────┐
β”‚ PHASE 1: DISCOVER β”‚
β”‚ β€’ Build Gmail query: from:notify@... β”‚
β”‚ β€’ Fetch all matching message IDs β”‚
β”‚ β€’ Deduplicate against existing DB records β”‚
β”‚ β”‚
β”‚ PHASE 2: PIPELINE (parallel) β”‚
β”‚ β€’ 10x concurrent Gmail fetches β”‚
β”‚ β€’ 5x concurrent AI parses β”‚
β”‚ β€’ Auto-switch Groq↔Mistral on rate limit β”‚
β”‚ β€’ Batch INSERT 25 rows at a time β”‚
β”‚ β€’ Emit scan:progress via WebSocket β”‚
β”‚ β”‚
β”‚ PHASE 3: COMPLETE β”‚
β”‚ β€’ Flush remaining DB buffer β”‚
β”‚ β€’ Emit scan:completed β”‚
β”‚ β€’ Update scan_logs table β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
```
---
## WebSocket Events (Frontend receives these)
| Event | Data | When |
|-------|------|------|
| `scan:started` | `{ jobId, totalEmails, newEmails, skipped }` | Scan begins |
| `scan:progress` | `{ processed, total, errored, latest, currentProvider }` | Each email processed |
| `scan:completed` | `{ jobId, summary: { found, parsed, skipped, errors } }` | Scan finished |
| `scan:error` | `{ jobId, error }` | Scan failed |
| `ai:switch` | `{ from, to, reason }` | AI provider auto-switched |
| `transaction:new` | `{ transaction }` | New transaction saved |
---
## Troubleshooting
| Issue | Fix |
|-------|-----|
| "User has no Gmail tokens" | User needs to log in via Google OAuth first: visit `/api/auth/google` |
| "No AI providers configured" | Set `GROQ_API_KEY` and/or `MISTRAL_API_KEY` in `.env` |
| "All AI providers rate-limited" | Wait 60s for cooldown, or add more API keys |
| Scan returns 0 emails | Check Gmail query β€” make sure the connected account actually has emails from `notify@payments.interac.ca` |
| WebSocket not connecting | Check Vite proxy config includes `/ws` β†’ `ws://localhost:3001` |
| "Invalid token" | JWT expired β€” log in again via Google OAuth |