This document describes the enhanced dispute resolution system with evidence attachments, internal notes, automated SLA warnings, and state machine management.
The advanced dispute resolution workflow provides:
- Evidence Attachments: Secure file uploads to S3 for dispute evidence
- Internal Notes: Private notes for support team collaboration
- Automated SLA Warnings: Priority-based SLA monitoring with automatic escalation
- State Machine: Enforced status transitions with validation
- Timeline Tracking: Complete audit trail of all dispute activities
- Priority Management: Four-tier priority system with automatic SLA calculation
open ──→ investigating ──→ resolved
│ │
└──────────────┴──→ rejected
- open: Initial state when dispute is created
- investigating: Dispute assigned to agent and under review
- resolved: Dispute resolved in favor of customer
- rejected: Dispute rejected after investigation
| From | To | Requirements |
|---|---|---|
| open | investigating | Must be assigned to agent |
| open | resolved | Resolution text required |
| open | rejected | Resolution text required |
| investigating | resolved | Resolution text required |
| investigating | rejected | Resolution text required |
| Priority | SLA Hours | Use Case |
|---|---|---|
| critical | 4 hours | System outages, security issues |
| high | 24 hours | Payment failures, account lockouts |
| medium | 72 hours | General transaction disputes |
| low | 168 hours (7 days) | Minor issues, feature requests |
- Warning Threshold: 2 hours before SLA deadline
- Automatic Escalation: Priority increased for overdue disputes
- Notifications: Sent via configured notification system
POST /api/transactions/:id/dispute
Content-Type: application/json
Authorization: Bearer <token>
{
"reason": "Transaction failed but amount was debited",
"reportedBy": "user123",
"priority": "high",
"category": "payment_failure"
}GET /api/disputes/:disputeId/details
Authorization: Bearer <token>Returns dispute with notes, evidence, and timeline.
PATCH /api/disputes/:disputeId/status
Content-Type: application/json
Authorization: Bearer <token>
{
"status": "resolved",
"resolution": "Transaction was successfully reversed",
"assignedTo": "agent@company.com"
}PATCH /api/disputes/:disputeId
Content-Type: application/json
Authorization: Bearer <token>
{
"priority": "critical",
"category": "fraud",
"internalNotes": "Customer provided additional evidence"
}POST /api/disputes/:disputeId/evidence
Content-Type: multipart/form-data
Authorization: Bearer <token>
file: <binary_data>
description: "Bank statement showing duplicate charge"POST /api/disputes/:disputeId/evidence/multiple
Content-Type: multipart/form-data
Authorization: Bearer <token>
files[]: <binary_data>
files[]: <binary_data>
descriptions[]: "Receipt"
descriptions[]: "Email confirmation"GET /api/disputes/:disputeId/evidence
Authorization: Bearer <token>POST /api/disputes/:disputeId/notes
Content-Type: application/json
Authorization: Bearer <token>
{
"author": "agent@company.com",
"note": "Contacted payment processor for transaction details"
}POST /api/disputes/:disputeId/assign
Content-Type: application/json
Authorization: Bearer <token>
{
"agentName": "senior.agent@company.com"
}GET /api/disputes/report?from=2024-01-01&to=2024-01-31&assignedTo=agent@company.com
Authorization: Bearer <token>GET /api/disputes/sla/report?days=30
Authorization: Bearer <token>GET /api/disputes/overdue
Authorization: Bearer <token>POST /api/disputes/sla/process
Authorization: Bearer <token>- Documents: PDF, DOC, DOCX, XLS, XLSX, TXT
- Images: JPEG, JPG, PNG, GIF
- Maximum Size: 10MB per file
- Maximum Files: 5 files per upload
dispute-evidence/
├── 2024/
│ ├── 01/
│ │ ├── dispute-uuid-1/
│ │ │ ├── receipt-1704067200-abc123.pdf
│ │ │ └── statement-1704067300-def456.jpg
│ │ └── dispute-uuid-2/
│ └── 02/
└── 2025/
CREATE TABLE dispute_evidence (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
dispute_id UUID NOT NULL REFERENCES disputes(id) ON DELETE CASCADE,
file_name VARCHAR(255) NOT NULL,
file_type VARCHAR(50) NOT NULL,
file_size INTEGER NOT NULL,
s3_key VARCHAR(500) NOT NULL,
s3_url VARCHAR(500) NOT NULL,
uploaded_by VARCHAR(100) NOT NULL,
description TEXT,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
);CREATE TABLE dispute_timeline (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
dispute_id UUID NOT NULL REFERENCES disputes(id) ON DELETE CASCADE,
event_type VARCHAR(50) NOT NULL,
old_status VARCHAR(20),
new_status VARCHAR(20),
actor VARCHAR(100) NOT NULL,
description TEXT,
metadata JSONB,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
);New columns added:
sla_due_date: Calculated SLA deadlinesla_warning_sent: Flag for warning notificationpriority: Priority level (low/medium/high/critical)category: Dispute category for classificationinternal_notes: Private notes for support team
dispute:create- Create new disputesdispute:read- View dispute detailsdispute:update- Update dispute fields and add notesdispute:assign- Assign disputes to agentsdispute:manage- Administrative functions (SLA processing)
- Customer: Can create disputes and view their own
- Agent: Can view, update, and resolve assigned disputes
- Supervisor: Can view all disputes and reassign
- Admin: Full access including SLA management
Schedule: Every hour (0 * * * *)
Functions:
- Send SLA warning notifications
- Escalate overdue disputes
- Update priority levels
- Generate compliance metrics
Configuration:
DISPUTE_SLA_CRON=0 * * * * # Every hourdispute.opened- New dispute createddispute.assigned- Dispute assigned to agentdispute.status_changed- Status transitiondispute.evidence_added- Evidence uploadeddispute.sla_warning- SLA deadline approachingdispute.escalated- Dispute escalated due to SLA breach
{
"event": "dispute.sla_warning",
"disputeId": "uuid",
"transactionId": "uuid",
"status": "investigating",
"message": "Dispute approaching SLA deadline",
"metadata": {
"slaDueDate": "2024-01-15T14:00:00Z",
"priority": "high",
"assignedTo": "agent@company.com"
}
}# S3 Configuration
AWS_REGION=us-east-1
AWS_S3_BUCKET=dispute-evidence-bucket
AWS_ACCESS_KEY_ID=your-access-key
AWS_SECRET_ACCESS_KEY=your-secret-key
# SLA Job Schedule
DISPUTE_SLA_CRON=0 * * * *
# File Upload Limits
MAX_EVIDENCE_FILE_SIZE=10485760 # 10MB
MAX_EVIDENCE_FILES=5- File type validation using MIME type checking
- File size limits to prevent DoS attacks
- Unique filename generation to prevent conflicts
- Private S3 bucket with restricted access
- Virus scanning (recommended for production)
- JWT-based authentication required
- RBAC permissions for all operations
- Audit trail for all dispute activities
- Secure file URLs with expiration (recommended)
- SLA Compliance Rate: Percentage of disputes resolved within SLA
- Average Resolution Time: Mean time from creation to resolution
- Escalation Rate: Percentage of disputes requiring escalation
- Evidence Upload Success Rate: File upload reliability
Recommended Grafana dashboard panels:
- Dispute volume by priority
- SLA compliance trends
- Agent workload distribution
- Resolution time by category
- Check S3 credentials and bucket permissions
- Verify file size and type restrictions
- Monitor S3 service availability
- Verify cron schedule configuration
- Check job scheduler logs
- Ensure database connectivity
- Review state machine validation rules
- Check required fields for transitions
- Verify user permissions
Key log patterns to monitor:
[DisputeSlaJob] Starting SLA monitoring job...
[DisputeNotification] dispute.sla_warning sent for dispute-uuid
S3 dispute evidence upload error: <error-details>
Run the migration script:
psql -d mobile_money -f database/migrations/add_dispute_evidence_and_sla.sql- Deploy new dispute model and service files
- Update route handlers with new endpoints
- Configure S3 bucket and permissions
- Update scheduler with SLA job
- Test file upload functionality
- Verify SLA monitoring
# Run dispute-related tests
npm test -- --grep "dispute"
# Test file upload endpoints
curl -X POST -F "file=@test.pdf" \
-H "Authorization: Bearer <token>" \
http://localhost:3000/api/disputes/uuid/evidence
# Test SLA job manually
curl -X POST -H "Authorization: Bearer <token>" \
http://localhost:3000/api/disputes/sla/processThis completes the advanced dispute resolution workflow implementation with evidence attachments, internal notes, automated SLA warnings, and state machine management.