danwel - Implementation Plan
Phased implementation approach prioritizing feature parity with the prototype on a modern, secure foundation.
---
Table of Contents
1. [MVP Definition](#mvp-definition)
2. [Implementation Phases](#implementation-phases)
3. [Phase Dependencies](#phase-dependencies)
4. [Testing Approach](#testing-approach)
5. [Deployment Strategy](#deployment-strategy)
6. [Prototype Reference](#prototype-reference)
---
MVP Definition
Goal
Rebuild the current prototype with a **clean, modern, secure foundation** that is multi-tenancy ready but initially single-user.
MVP Scope (Phases 1-4)
| Include | Exclude (Later) |
|---------|-----------------|
| Laravel 11 foundation | Team invitations |
| Single org + single user | Organization switching |
| Multi-tenancy *structure* (ready for later) | Multiple users per org |
| Google Calendar integration | Office 365 integration |
| Moneybird integration | Harvest integration |
| Calendar UI with drag-drop | Mobile/tablet PWA |
| User preferences (timezone, work hours) | Reports & analytics |
| Secure encrypted token storage | Audit logging UI |
MVP = Feature Parity with Prototype
When MVP is complete, you should be able to:
1. Register/login as a user
2. Connect Google Calendar (OAuth)
3. Connect Moneybird (OAuth)
4. See weekly calendar with time blocks
5. Create/edit/delete time blocks (drag-drop)
6. Time blocks sync to Google Calendar
7. Time blocks create Moneybird time entries
8. Set timezone, work hours, work days
---
Implementation Phases
Phase 1: Foundation (MVP) ✅ COMPLETED
**Goal:** Laravel app with auth, database, multi-tenancy structure
• [x] Fresh Laravel 11 installation
• [x] Database migrations:
- [x] users (with preferences: timezone, work_days, work_hours)
- [x] organizations
- [x] organization_user pivot (with role)
- [x] integrations
- [x] calendars
- [x] clients
- [x] projects
- [x] time_blocks
• [x] TenantContext service
• [x] BelongsToOrganization trait
• [x] SetTenantContext middleware
• [x] User authentication (Laravel Fortify)
• [x] Auto-create organization on registration
• [x] Full role system (owner, admin, member, viewer)**Status:** ✅ Complete - User can register, login, and has an organization created automatically.
**Tests:**
• [ ] User registration creates organization
• [ ] User is set as owner of their organization
• [ ] TenantContext correctly scopes queries---
Phase 2: Integration Framework (MVP) ✅ COMPLETED
**Goal:** Secure OAuth infrastructure for external services
• [x] CalendarProviderInterface
• [x] InvoicingProviderInterface
• [x] ProjectProviderInterface (added for GitHub)
• [x] IntegrationManager service
• [x] Integration model with encrypted tokens
• [x] Calendar model (for multi-calendar support)
• [x] Client model (synced from Moneybird)
• [x] Project model (synced from Moneybird)
• [x] Config-based provider registration
• [x] Token refresh middleware/job**Status:** ✅ Complete - Framework supports multiple provider types with secure token management.
**Tests:**
• [ ] Tokens are encrypted in database
• [ ] Token refresh works correctly
• [ ] Integration scoped to organization---
Phase 3: Google Calendar + Moneybird (MVP) ✅ COMPLETED
**Goal:** Working integrations matching prototype functionality
**Google Calendar:** ✅
• [x] GoogleCalendarProvider implementation
• [x] OAuth connect flow
• [x] OAuth callback handler
• [x] Token refresh
• [x] Fetch user timezone on connect
• [x] Calendar discovery (list available calendars)
• [x] Select calendars to sync
• [x] Fetch events for date range
• [x] Create event with extendedProperties
• [x] Update event
• [x] Delete event
• [x] Disconnect flow
**Moneybird:** ✅
• [x] MoneybirdProvider implementation
• [x] OAuth connect flow
• [x] OAuth callback handler
• [x] Token refresh
• [x] Fetch administration ID on connect
• [x] Fetch Moneybird user ID (required for time entries)
• [x] Sync contacts → clients table
• [x] Sync projects → projects table
• [x] Create contact
• [x] Create project
• [x] Create time entry
• [x] Update time entry
• [x] Delete time entry
• [x] Disconnect flow**Status:** ✅ Complete - Both services fully functional with comprehensive CRUD operations.
**Tests:**
• [ ] OAuth flow completes successfully (mock external APIs)
• [ ] Events sync to Google Calendar
• [ ] Time entries sync to Moneybird
• [ ] Token refresh on expiry---
Phase 4: Time Blocks + Calendar UI (MVP) ✅ COMPLETED
**Goal:** Full calendar interface with drag-drop, matching prototype
**Backend:** ✅
• [x] TimeBlock model + service
• [x] TimeBlock API endpoints:
- [x] GET /api/time-blocks (with date range)
- [x] POST /api/time-blocks
- [x] PUT /api/time-blocks/{id}
- [x] DELETE /api/time-blocks/{id}
• [x] Sync to Google Calendar on create/update/delete
• [x] Sync to Moneybird on create/update/delete
• [x] Store external IDs (calendar_event_id, time_entry_id)
• [x] Sync status tracking (pending, synced, error)
• [x] Background job for sync
• [x] Error handling + retry logic
**Frontend:** ✅
• [x] App layout (nav, user menu)
• [x] Settings page:
- [x] Connect/disconnect Google Calendar
- [x] Connect/disconnect Moneybird
- [x] Select calendars to sync
- [x] Set timezone
- [x] Set work hours (start/end)
- [x] Set work days
• [x] Calendar view:
- [x] Weekly grid (respects user work hours/days)
- [x] Horizontal scroll between days
- [x] Display time blocks
- [x] Display external calendar events (read-only, different color)
- [x] Drag to create new block
- [x] Drag to move block
- [x] Resize to change duration
- [x] Click to edit (modal)
- [x] Delete block
- [x] Assign client/project to blocks
- [x] Assign client/project to external events (metadata only)
- [x] Week navigation (prev/next/today)
- [x] Week picker
- [x] Summary row (hours per day, total week)
- [x] Sync status indicators
• [x] Client/project dropdowns (from Moneybird data)
• [x] Create client inline
• [x] Create project inline**Status:** ✅ Complete - Full feature parity achieved with enhanced functionality beyond original prototype.
**Tests:**
• [ ] Time block CRUD via API
• [ ] Sync triggers on create/update/delete
• [ ] External events display correctly
• [ ] Summary calculation correct---
Phase 5: Polish & Hardening (Post-MVP)
**Goal:** Production-ready quality
• [ ] Input validation on all endpoints
• [ ] Rate limiting
• [ ] Error pages (404, 500, etc.)
• [ ] Loading states in UI
• [ ] Optimistic UI updates
• [ ] Proper error messages to user
• [ ] Sync retry with exponential backoff
• [ ] Handle API failures gracefully
**Tests:**
• [ ] Validation rejects bad input
• [ ] Rate limiting works
• [ ] Sync retries on failure---
Phase 6: Team Features (Future)
**Goal:** Multi-user organizations
• [ ] Invitation system
• [ ] Accept invitation flow
• [ ] Team member list
• [ ] Role management (admin, member, viewer)
• [ ] Role-based policies
• [ ] Organization switching
• [ ] View team members' calendars---
Phase 7: Advanced Features (Future)
**Goal:** Extended functionality
• [ ] Office 365 calendar integration
• [ ] Harvest integration
• [ ] Recurring time blocks
• [ ] Reports & analytics
• [ ] Mobile/tablet PWA
• [ ] Subdomain per organization
• [ ] Audit logging UI---
Phase Dependencies
Phase 1: Foundation
│
▼
Phase 2: Integration Framework
│
▼
Phase 3: Google Calendar + Moneybird ─────┐
│ │
▼ │
Phase 4: Time Blocks + Calendar UI ◄──────┘
│
▼
Phase 5: Polish (Post-MVP)
│
▼
Phase 6: Team Features (Future)
│
▼
Phase 7: Advanced Features (Future)
**Critical Path:** 1 → 2 → 3 → 4
**Can parallelize within Phase 3:**
• Google Calendar provider
• Moneybird provider
(Both depend on Phase 2 framework, but not on each other)
**Can parallelize within Phase 4:**
• Backend API
• Frontend UI
(Frontend can use mock data while backend is built)
---
Testing Approach
Test As You Build
Write tests during each phase, not at the end.
| Phase | Test Focus |
|-------|------------|
| Phase 1 | Auth, organization creation, tenant scoping |
| Phase 2 | Token encryption, integration model |
| Phase 3 | OAuth flows (mocked), API calls (mocked) |
| Phase 4 | Time block CRUD, sync triggers |
Test Types
**Unit Tests** - Test services and models in isolation:
tests/Unit/
├── Services/
│ ├── TenantContextTest.php
│ └── IntegrationManagerTest.php
└── Models/
└── TimeBlockTest.php
**Feature Tests** - Test full request/response cycles:
tests/Feature/
├── Auth/
│ └── RegistrationTest.php
├── Integrations/
│ ├── GoogleCalendarTest.php
│ └── MoneybirdTest.php
├── TimeBlocks/
│ ├── CreateTimeBlockTest.php
│ ├── UpdateTimeBlockTest.php
│ └── SyncTimeBlockTest.php
└── MultiTenancy/
└── OrganizationIsolationTest.php
Critical Test Cases (MVP)
1. **Tenant isolation** - User cannot access other org's data
2. **Token security** - Tokens encrypted at rest
3. **Sync reliability** - Time blocks sync to external services
4. **Token refresh** - Expired tokens refresh automatically
Mocking External APIs
Don't hit real Google/Moneybird APIs in tests:
// Mock Google Calendar API responses
Http::fake([
'googleapis.com/*' => Http::response([...], 200),
]);
// Mock Moneybird API responses
Http::fake([
'moneybird.com/*' => Http::response([...], 200),
]);
---
Deployment Strategy
SpinupWP Setup
``
env
Application
APP_NAME=danwel
APP_ENV=production
APP_URL=https://danwel.yourdomain.com
Database
DB_CONNECTION=mysql
DB_DATABASE=danwel
DB_USERNAME=danwel_user
DB_PASSWORD=SECURE_PASSWORD
Cache & Queue
CACHE_DRIVER=redis
SESSION_DRIVER=redis
QUEUE_CONNECTION=redis
Integrations
GOOGLE_CLIENT_ID=xxx
GOOGLE_CLIENT_SECRET=xxx
GOOGLE_REDIRECT_URI=https://danwel.yourdomain.com/integrations/google_calendar/callback
MONEYBIRD_CLIENT_ID=xxx
MONEYBIRD_CLIENT_SECRET=xxx
MONEYBIRD_REDIRECT_URI=https://danwel.yourdomain.com/integrations/moneybird/callback
Deployment Script
bash
#!/bin/bash
cd $RELEASE_PATH
composer install --no-dev --optimize-autoloader
npm ci && npm run build
php artisan config:cache
php artisan route:cache
php artisan view:cache
php artisan migrate --force
php artisan queue:restart
Queue Workers
Required for background sync operations:
bash
Supervisor config for queue worker
[program:danwel-worker]
process_name=%(program_name)s_%(process_num)02d
command=php /path/to/artisan queue:work redis --sleep=3 --tries=3 --max-time=3600
autostart=true
autorestart=true
stopasgroup=true
killasgroup=true
numprocs=2
`
Scheduled Tasks
// app/Console/Kernel.php
$schedule->command('integrations:refresh-tokens')->hourly();
$schedule->command('integrations:sync-calendars')->everyFifteenMinutes();
$schedule->command('integrations:retry-failed')->everyFiveMinutes();
---
Prototype Reference
The original prototype is preserved in
initial_prototype/
for reference during the Laravel rebuild.Prototype File Summary
| File | Lines | Key Functionality |
|------|-------|-------------------|
| initial_prototype/config.php
| 44 | OAuth credentials, color constants |
| initial_prototype/index.php
| 182 | Settings page, connection status UI |
| initial_prototype/callback.php
| ~90 | Google OAuth code exchange, timezone fetch |
| initial_prototype/moneybird-callback.php
| ~87 | Moneybird OAuth, administration fetch |
| initial_prototype/api.php
| 758 | Full REST API |
| initial_prototype/calendar.php
| 1,434 | Calendar UI + JavaScript |
Key Code to Port
**From initial_prototype/callback.php
:**
• Token exchange with Google
• Fetching user timezone on connect
**From initial_prototype/moneybird-callback.php
:**
• Token exchange with Moneybird
• Fetching administration ID
• Fetching Moneybird user ID
**From initial_prototype/api.php
:**
• Time entry CRUD to Moneybird
• Event CRUD to Google Calendar
• Extended properties for linking data
**From initial_prototype/calendar.php`:**
• interact.js drag-drop configuration
• Week picker logic
• Summary calculation
• Color mapping (Google colorId → hex)
Prototype Limitations → Laravel Solutions
| Limitation | Laravel Solution |
|------------|------------------|
| Single-user (no auth) | Laravel Breeze + Sanctum |
| File-based tokens | Encrypted database storage |
| No database | MySQL with proper schema |
| Google Calendar as source of truth | Local DB as source of truth |
| Hardcoded work hours (8am-6pm) | User preferences |
| Hardcoded work days (Mon-Sun) | User preferences |
| No timezone customization | User preferences |
| No multiple calendar support | Calendar model + multi-select |
---
MVP Checklist Summary
**Phase 1: Foundation**
• [ ] Laravel 11 + Breeze auth
• [ ] All database tables created
• [ ] User registration creates org
• [ ] Tenant scoping works
**Phase 2: Integration Framework**
• [ ] Provider interfaces defined
• [ ] Encrypted token storage
• [ ] Token refresh mechanism
**Phase 3: Integrations**
• [ ] Google Calendar OAuth works
• [ ] Google Calendar CRUD works
• [ ] Moneybird OAuth works
• [ ] Moneybird time entries work
• [ ] Clients/projects sync from Moneybird
**Phase 4: UI**
• [ ] Settings page (integrations, preferences)
• [ ] Calendar grid with time blocks
• [ ] Drag-drop create/move/resize
• [ ] Week navigation
• [ ] Summary row
• [ ] Sync to external services**MVP Complete** = All above checked ✅
---
Post-MVP Development Status
**MVP was completed and the system has been significantly enhanced beyond the original scope:**
Additional Features Implemented
• **Task/Entry Management System** - Full project management with entries, comments, labels
• **Advanced Authentication** - OAuth (Google, GitHub, Apple), WebAuthn, 2FA, magic links
• **GitHub Integration** - Repository linking, issue sync, webhooks
• **Team Management** - Full invitation system with roles and permissions
• **Platform Administration** - Admin dashboard, user impersonation, audit logging
• **Multi-language Support** - Comprehensive EN/NL localization
• **Demo Mode** - Guided demo experience with usage restrictions
• **Mobile App Support** - Token-based authentication for external apps
• **Billing System** - VAT validation and billing address management
• **Advanced UI Features** - Favorites, enhanced preferences, statistics dashboard
Current Status: Production Ready
The system has evolved from a simple MVP into a comprehensive project management and time tracking platform that's currently in production use.