198 lines
5.3 KiB
Dart
198 lines
5.3 KiB
Dart
class Booking {
|
|
final int id;
|
|
final int userId;
|
|
final int kontrakanId;
|
|
final DateTime tanggalMulai;
|
|
final DateTime tanggalSelesai;
|
|
final double totalBiaya;
|
|
final String status;
|
|
final String? catatan;
|
|
final dynamic kontrakan;
|
|
|
|
// Pembeda pengajuan survei dan sewa.
|
|
final String jenisPengajuan;
|
|
final DateTime? tanggalSurvei;
|
|
final String? jamSurvei;
|
|
final DateTime? surveyFollowUpExpiresAt;
|
|
|
|
// Pembayaran hanya digunakan pada pengajuan sewa.
|
|
final String paymentStatus;
|
|
final String? paymentProof;
|
|
|
|
Booking({
|
|
required this.id,
|
|
required this.userId,
|
|
required this.kontrakanId,
|
|
required this.tanggalMulai,
|
|
required this.tanggalSelesai,
|
|
required this.totalBiaya,
|
|
required this.status,
|
|
this.catatan,
|
|
this.kontrakan,
|
|
this.jenisPengajuan = 'sewa',
|
|
this.tanggalSurvei,
|
|
this.jamSurvei,
|
|
this.surveyFollowUpExpiresAt,
|
|
this.paymentStatus = 'unpaid',
|
|
this.paymentProof,
|
|
});
|
|
|
|
static DateTime? _parseDate(dynamic value) {
|
|
if (value == null) return null;
|
|
return DateTime.tryParse(value.toString());
|
|
}
|
|
|
|
factory Booking.fromJson(Map<String, dynamic> json) {
|
|
final startDate =
|
|
json['start_date'] ?? json['tanggal_mulai'] ?? json['tanggal_survei'];
|
|
final endDate =
|
|
json['end_date'] ?? json['tanggal_selesai'] ?? json['tanggal_survei'];
|
|
final amount = json['amount'] ?? json['total_biaya'];
|
|
final notes = json['notes'] ?? json['catatan'];
|
|
|
|
final jenis = (json['jenis_pengajuan'] ?? 'sewa').toString().toLowerCase();
|
|
|
|
final parsedSurveyDate = _parseDate(json['tanggal_survei']);
|
|
final parsedStartDate =
|
|
_parseDate(startDate) ?? parsedSurveyDate ?? DateTime.now();
|
|
final parsedEndDate = _parseDate(endDate) ?? parsedStartDate;
|
|
|
|
return Booking(
|
|
id: int.tryParse(json['id']?.toString() ?? '0') ?? 0,
|
|
userId: int.tryParse(json['user_id']?.toString() ?? '0') ?? 0,
|
|
kontrakanId: int.tryParse(json['kontrakan_id']?.toString() ?? '0') ?? 0,
|
|
tanggalMulai: parsedStartDate,
|
|
tanggalSelesai: parsedEndDate,
|
|
totalBiaya: double.tryParse(amount?.toString() ?? '0') ?? 0,
|
|
status: json['status']?.toString() ?? 'pending',
|
|
catatan: notes?.toString(),
|
|
kontrakan: json['kontrakan'],
|
|
jenisPengajuan: jenis,
|
|
tanggalSurvei: parsedSurveyDate,
|
|
jamSurvei: json['jam_survei']?.toString(),
|
|
surveyFollowUpExpiresAt: _parseDate(
|
|
json['survey_follow_up_expires_at'],
|
|
),
|
|
paymentStatus: json['payment_status']?.toString() ?? 'unpaid',
|
|
paymentProof: json['payment_proof']?.toString(),
|
|
);
|
|
}
|
|
|
|
bool get isSurvei => jenisPengajuan == 'survei';
|
|
|
|
bool get isSewa => !isSurvei;
|
|
|
|
bool get isSurveyFollowUpActive =>
|
|
isSurvei && status.toLowerCase() == 'confirmed';
|
|
|
|
String get jenisLabel {
|
|
return isSurvei ? 'Pengajuan Survei' : 'Pengajuan Sewa';
|
|
}
|
|
|
|
bool get canUploadPaymentProof {
|
|
return isSewa &&
|
|
status.toLowerCase() == 'confirmed' &&
|
|
paymentStatus == 'unpaid';
|
|
}
|
|
|
|
bool get isWaitingPaymentVerification {
|
|
return isSewa && paymentStatus == 'verification';
|
|
}
|
|
|
|
String get formattedTotalBiaya {
|
|
if (isSurvei) return '-';
|
|
|
|
final nominal = totalBiaya.toStringAsFixed(0).replaceAllMapped(
|
|
RegExp(r'(\d{1,3})(?=(\d{3})+(?!\d))'),
|
|
(Match match) => '${match[1]}.',
|
|
);
|
|
|
|
return 'Rp $nominal';
|
|
}
|
|
|
|
int get durasiBulan {
|
|
if (isSurvei) return 0;
|
|
|
|
final totalBulan =
|
|
(tanggalSelesai.year - tanggalMulai.year) * 12 +
|
|
tanggalSelesai.month -
|
|
tanggalMulai.month;
|
|
|
|
return totalBulan.clamp(1, 99).toInt();
|
|
}
|
|
|
|
String get statusColor {
|
|
switch (status.toLowerCase()) {
|
|
case 'confirmed':
|
|
return 'blue';
|
|
case 'checked_in':
|
|
case 'active':
|
|
return 'green';
|
|
case 'completed':
|
|
case 'expired':
|
|
return 'gray';
|
|
case 'cancelled':
|
|
return 'red';
|
|
default:
|
|
return 'orange';
|
|
}
|
|
}
|
|
|
|
String get statusLabel {
|
|
if (isSurvei) {
|
|
switch (status.toLowerCase()) {
|
|
case 'pending':
|
|
return 'Menunggu Konfirmasi Survei';
|
|
case 'confirmed':
|
|
return 'Survei Disetujui';
|
|
case 'completed':
|
|
return 'Survei Selesai';
|
|
case 'cancelled':
|
|
return 'Tidak Jadi Sewa';
|
|
case 'expired':
|
|
return 'Masa Tindak Lanjut Berakhir';
|
|
default:
|
|
return status;
|
|
}
|
|
}
|
|
|
|
switch (status.toLowerCase()) {
|
|
case 'pending':
|
|
return 'Menunggu Persetujuan Sewa';
|
|
case 'confirmed':
|
|
switch (paymentStatus.toLowerCase()) {
|
|
case 'paid':
|
|
return 'Sewa Disetujui';
|
|
case 'verification':
|
|
return 'Menunggu Verifikasi Pembayaran';
|
|
default:
|
|
return 'Menunggu Pembayaran';
|
|
}
|
|
case 'checked_in':
|
|
case 'active':
|
|
return 'Sedang Ditempati';
|
|
case 'completed':
|
|
return 'Sewa Selesai';
|
|
case 'cancelled':
|
|
return 'Pengajuan Sewa Dibatalkan';
|
|
default:
|
|
return status;
|
|
}
|
|
}
|
|
|
|
String get paymentStatusLabel {
|
|
if (isSurvei) return '-';
|
|
|
|
switch (paymentStatus.toLowerCase()) {
|
|
case 'paid':
|
|
return 'Lunas';
|
|
case 'verification':
|
|
return 'Menunggu Verifikasi';
|
|
case 'refunded':
|
|
return 'Dikembalikan';
|
|
default:
|
|
return 'Belum Bayar';
|
|
}
|
|
}
|
|
}
|