Files
tasq/lib/models/it_service_request.model.dart
T
2026-04-27 06:20:39 +08:00

269 lines
7.8 KiB
Dart

import 'dart:convert';
import 'package:brick_offline_first_with_supabase/brick_offline_first_with_supabase.dart';
import 'package:brick_sqlite/brick_sqlite.dart';
import 'package:brick_supabase/brick_supabase.dart';
import '../utils/app_time.dart';
/// Available IT services from the form.
class ItServiceType {
static const fbLiveStream = 'fb_live_stream';
static const videoRecording = 'video_recording';
static const technicalAssistance = 'technical_assistance';
static const wifi = 'wifi';
static const others = 'others';
static const all = [
fbLiveStream,
videoRecording,
technicalAssistance,
wifi,
others,
];
static String label(String type) {
switch (type) {
case fbLiveStream:
return 'FB Live Stream';
case videoRecording:
return 'Video Recording';
case technicalAssistance:
return 'Technical Assistance';
case wifi:
return 'WiFi';
case others:
return 'Others';
default:
return type;
}
}
}
/// Status lifecycle for an IT Service Request.
class ItServiceRequestStatus {
static const draft = 'draft';
static const pendingApproval = 'pending_approval';
static const scheduled = 'scheduled';
static const inProgressDryRun = 'in_progress_dry_run';
static const inProgress = 'in_progress';
static const completed = 'completed';
static const cancelled = 'cancelled';
static const all = [
draft,
pendingApproval,
scheduled,
inProgressDryRun,
inProgress,
completed,
cancelled,
];
static String label(String status) {
switch (status) {
case draft:
return 'Draft';
case pendingApproval:
return 'Pending Approval';
case scheduled:
return 'Scheduled';
case inProgressDryRun:
return 'In Progress (Dry Run)';
case inProgress:
return 'In Progress';
case completed:
return 'Completed';
case cancelled:
return 'Cancelled';
default:
return status;
}
}
}
@ConnectOfflineFirstWithSupabase(
supabaseConfig: SupabaseSerializable(tableName: 'it_service_requests'),
)
class ItServiceRequest extends OfflineFirstWithSupabaseModel {
final String id;
final String? requestNumber;
final List<String> services;
final String? servicesOther;
final String eventName;
// Quill Delta JSON stored as plain strings.
final String? eventDetails;
final DateTime? eventDate;
final DateTime? eventEndDate;
final DateTime? dryRunDate;
final DateTime? dryRunEndDate;
final String? contactPerson;
final String? contactNumber;
final String? remarks;
final String? officeId;
final String? requestedBy;
final String? requestedByUserId;
final String? approvedBy;
final String? approvedByUserId;
final DateTime? approvedAt;
final String status;
final bool outsidePremiseAllowed;
final String? cancellationReason;
final DateTime? cancelledAt;
final String? creatorId;
final DateTime createdAt;
final DateTime updatedAt;
final DateTime? completedAt;
final DateTime? dateTimeReceived;
final DateTime? dateTimeChecked;
ItServiceRequest({
required this.id,
this.requestNumber,
required this.services,
this.servicesOther,
required this.eventName,
this.eventDetails,
this.eventDate,
this.eventEndDate,
this.dryRunDate,
this.dryRunEndDate,
this.contactPerson,
this.contactNumber,
this.remarks,
this.officeId,
this.requestedBy,
this.requestedByUserId,
this.approvedBy,
this.approvedByUserId,
this.approvedAt,
required this.status,
required this.outsidePremiseAllowed,
this.cancellationReason,
this.cancelledAt,
this.creatorId,
required this.createdAt,
required this.updatedAt,
this.completedAt,
this.dateTimeReceived,
this.dateTimeChecked,
});
@Supabase(ignore: true)
@Sqlite(ignore: true)
@override
bool operator ==(Object other) =>
identical(this, other) ||
other is ItServiceRequest &&
runtimeType == other.runtimeType &&
id == other.id &&
requestNumber == other.requestNumber &&
status == other.status &&
updatedAt == other.updatedAt;
@Supabase(ignore: true)
@Sqlite(ignore: true)
@override
int get hashCode => Object.hash(id, requestNumber, status, updatedAt);
bool isGeofenceOverrideActive(DateTime now) {
if (!outsidePremiseAllowed) return false;
final today = DateTime(now.year, now.month, now.day);
if (dryRunDate != null) {
final dryDay = DateTime(
dryRunDate!.year,
dryRunDate!.month,
dryRunDate!.day,
);
if (!today.isBefore(dryDay) &&
today.isBefore(dryDay.add(const Duration(days: 1)))) {
return true;
}
}
if (eventDate != null) {
final eventDay = DateTime(
eventDate!.year,
eventDate!.month,
eventDate!.day,
);
if (!today.isBefore(eventDay) &&
today.isBefore(eventDay.add(const Duration(days: 1)))) {
return true;
}
}
return false;
}
factory ItServiceRequest.fromMap(Map<String, dynamic> map) {
List<String> parseServices(dynamic raw) {
if (raw is List) return raw.map((e) => e.toString()).toList();
if (raw is String) {
final trimmed = raw.replaceAll('{', '').replaceAll('}', '');
if (trimmed.isEmpty) return [];
return trimmed.split(',').map((e) => e.trim()).toList();
}
return [];
}
String? quillField(dynamic raw) {
if (raw == null) return null;
if (raw is String) return raw;
try {
return jsonEncode(raw);
} catch (_) {
return raw.toString();
}
}
return ItServiceRequest(
id: map['id'] as String,
requestNumber: map['request_number'] as String?,
services: parseServices(map['services']),
servicesOther: map['services_other'] as String?,
eventName: map['event_name'] as String? ?? '',
eventDetails: quillField(map['event_details']),
eventDate: map['event_date'] == null
? null
: AppTime.parse(map['event_date'] as String),
eventEndDate: map['event_end_date'] == null
? null
: AppTime.parse(map['event_end_date'] as String),
dryRunDate: map['dry_run_date'] == null
? null
: AppTime.parse(map['dry_run_date'] as String),
dryRunEndDate: map['dry_run_end_date'] == null
? null
: AppTime.parse(map['dry_run_end_date'] as String),
contactPerson: map['contact_person'] as String?,
contactNumber: map['contact_number'] as String?,
remarks: quillField(map['remarks']),
officeId: map['office_id'] as String?,
requestedBy: map['requested_by'] as String?,
requestedByUserId: map['requested_by_user_id'] as String?,
approvedBy: map['approved_by'] as String?,
approvedByUserId: map['approved_by_user_id'] as String?,
approvedAt: map['approved_at'] == null
? null
: AppTime.parse(map['approved_at'] as String),
status: map['status'] as String? ?? 'draft',
outsidePremiseAllowed: map['outside_premise_allowed'] as bool? ?? false,
cancellationReason: map['cancellation_reason'] as String?,
cancelledAt: map['cancelled_at'] == null
? null
: AppTime.parse(map['cancelled_at'] as String),
creatorId: map['creator_id'] as String?,
createdAt: AppTime.parse(map['created_at'] as String),
updatedAt: AppTime.parse(map['updated_at'] as String),
completedAt: map['completed_at'] == null
? null
: AppTime.parse(map['completed_at'] as String),
dateTimeReceived: map['date_time_received'] == null
? null
: AppTime.parse(map['date_time_received'] as String),
dateTimeChecked: map['date_time_checked'] == null
? null
: AppTime.parse(map['date_time_checked'] as String),
);
}
}