bmc_hub/SERVICE_CONTRACT_WIZARD_README.md

202 lines
7.4 KiB
Markdown
Raw Normal View History

# Service Contract Migration Wizard - Implementation Summary
## ✅ What Was Built
A step-by-step wizard that migrates Vtiger service contracts to Hub systems:
- **Cases** → Archived to `tticket_archived_tickets`
- **Timelogs** → Transferred as klippekort top-ups (prepaid card hours)
Features:
- ✅ Dry-run toggle (preview mode without database writes)
- ✅ Step-by-step review of each case/timelog
- ✅ Manual klippekort selection per timelog
- ✅ Progress tracking and summary report
- ✅ Read-only from Vtiger (no writes back to Vtiger)
## 🎯 Files Created/Modified
### New Files:
1. **[app/timetracking/backend/service_contract_wizard.py](app/timetracking/backend/service_contract_wizard.py)** (275 lines)
- Core wizard service with all business logic
- Methods: `load_contract_detailed_data()`, `archive_case()`, `transfer_timelog_to_klippekort()`, `get_wizard_summary()`
- Dry-run support built into each method
2. **[app/timetracking/frontend/service_contract_wizard.html](app/timetracking/frontend/service_contract_wizard.html)** (650 lines)
- Complete wizard UI with Nordic design
- Contract dropdown selector
- Progress bar with live counters
- Current item display with conditional klippekort dropdown
- Summary report on completion
### Modified Files:
1. **[app/services/vtiger_service.py](app/services/vtiger_service.py)** (+65 lines)
- Added `get_service_contracts(account_id=None)` - Fetch active service contracts
- Added `get_service_contract_cases(contract_id)` - Fetch cases linked to contract
- Added `get_service_contract_timelogs(contract_id)` - Fetch timelogs linked to contract
2. **[app/timetracking/backend/models.py](app/timetracking/backend/models.py)** (+70 lines)
- `ServiceContractBase` - Base contract model
- `ServiceContractItem` - Single case/timelog item
- `ServiceContractWizardData` - Complete contract data for wizard
- `ServiceContractWizardAction` - Action result (archive/transfer)
- `ServiceContractWizardSummary` - Final summary
- `TimologTransferRequest` - Request model for timelog transfer
- `TimologTransferResult` - Transfer result
3. **[app/timetracking/backend/router.py](app/timetracking/backend/router.py)** (+180 lines)
- `GET /api/v1/timetracking/service-contracts` - List contracts dropdown
- `POST /api/v1/timetracking/service-contracts/wizard/load` - Load contract data
- `POST /api/v1/timetracking/service-contracts/wizard/archive-case` - Archive case
- `POST /api/v1/timetracking/service-contracts/wizard/transfer-timelog` - Transfer timelog
- `GET /api/v1/timetracking/service-contracts/wizard/customer-cards/{customer_id}` - Get klippekort
4. **[app/timetracking/frontend/views.py](app/timetracking/frontend/views.py)** (+5 lines)
- Added frontend route: `/timetracking/service-contract-wizard`
## 🚀 How to Test
### 1. Start the API
```bash
docker-compose up -d api
docker-compose logs -f api
```
### 2. Access the Wizard
```
http://localhost:8000/timetracking/service-contract-wizard
```
### 3. Dry-Run Mode (Recommended First)
1. Check the "Preview Mode" checkbox at top (enabled by default)
2. Select a service contract from dropdown
3. Review each case/timelog and click "Gem & Næste"
4. No data is written to database in dry-run mode
5. Review summary report to see what WOULD be changed
### 4. Live Mode
1. **Uncheck** "Preview Mode" checkbox
2. Select same or different contract
3. Process items - changes ARE committed to database
4. Cases are exported to `tticket_archived_tickets`
5. Timelogs are added to klippekort via top-up transaction
## 🔍 Database Changes
### Dryrun Mode:
- All operations are **logged** but **NOT committed**
- Queries are constructed but rolled back
- UI shows what WOULD happen
### Live Mode:
- Cases are inserted into `tticket_archived_tickets` with:
- `source_system = 'vtiger_service_contract'`
- `external_id = vtiger case ID`
- Full case data in `raw_data` JSONB field
- Timelogs create transactions in `tticket_prepaid_transactions` with:
- `transaction_type = 'top_up'`
- Hours added to klippekort `purchased_hours`
- Description references vTiger timelog
## 📊 Data Flow
```
Vtiger Service Contract
SelectContract (dropdown)
LoadContractData
├─ Cases → Archive to tticket_archived_tickets
└─ Timelogs → Transfer to klippekort (top-up)
WizardProgress (step-by-step review)
├─ [DRY RUN] Preview mode (no DB writes)
└─ [LIVE] Commit to database
Summary Report
├─ Cases archived: N
├─ Hours transferred: N
└─ Failed items: N
```
## 🔐 Safety Features
1. **Dry-run mode enabled by default** - Users see what WOULD happen first
2. **Customer linking** - Looks up Hub customer ID from vTiger account
3. **Klippekort validation** - Verifies card belongs to customer before transfer
4. **Read-only from Vtiger** - No writes back to Vtiger (only reads)
5. **Transaction handling** - Each operation is atomic
6. **Audit logging** - All actions logged with DRY RUN/COMMITTED markers
## 🛠️ Technical Details
### Wizard Service (`ServiceContractWizardService`)
- Stateless service class
- All methods are static
- Database operations via `execute_query()` helpers
- Klippekort transfers via `KlippekortService.top_up_card()`
### Frontend UI
- Vanilla JavaScript (no frameworks)
- Nordic Top design system (matches existing Hub UI)
- Responsive Bootstrap 5 grid
- Real-time progress updates
- Conditional klippekort dropdown (only for timelogs)
### API Endpoints
- RESTful architecture
- All endpoints support `dry_run` query parameter
- Request/response models use Pydantic validation
- Comprehensive error handling with HTTPException
## 📝 Logging Output
### Dry-Run Mode:
```
🔍 DRY RUN: Would archive case 1x123: 'Case Title'
🔍 DRY RUN: Would transfer 5h to card 42 from timelog 2x456
```
### Live Mode:
```
✅ Archived case 1x123 to tticket_archived_tickets (ID: 1234)
✅ Transferred 5h from timelog 2x456 to card 42
```
## 🐛 Troubleshooting
### Contracts dropdown is empty:
- Verify Vtiger integration is configured (VTIGER_URL, VTIGER_USERNAME, VTIGER_API_KEY in .env)
- Check vTiger has active ServiceContracts
- Check API user has access to ServiceContracts module
### Klippekort dropdown empty for customer:
- Customer may not have any active prepaid cards
- Or customer is not linked between Vtiger account and Hub customer
- Create a prepaid card for the customer first
### Dry-run mode not working:
- Ensure checkbox is checked
- Check browser console for JavaScript errors
- Verify `dry_run` parameter is passed to API endpoints
## 📋 Next Steps
1. **Test with sample data** - Create test service contract in Vtiger
2. **Verify database changes** - Query `tticket_archived_tickets` post-migration
3. **Monitor klippekort** - Check `tticket_prepaid_transactions` for top-up entries
4. **Adjust as needed** - Tweak timelog filtering or case mapping based on results
## 🔗 Related Components
- **Klippekort System**: [app/ticket/backend/klippekort_service.py](app/ticket/backend/klippekort_service.py)
- **Archive System**: Database table `tticket_archived_tickets`
- **Timetracking Module**: [app/timetracking/](app/timetracking/)
- **Vtiger Integration**: [app/services/vtiger_service.py](app/services/vtiger_service.py)
---
**Status**: ✅ Ready for testing and deployment
**Estimated Time to Test**: 15-20 minutes
**Database Dependency**: PostgreSQL (no migrations needed - uses existing tables)