cashumit/lib/models/report_transaction.dart

144 lines
4.9 KiB
Dart
Raw Permalink Normal View History

// lib/models/report_transaction.dart
class ReportTransaction {
final String id;
DateTime date;
String description;
double amount;
final String direction; // 'pemasukan' atau 'pengeluaran'
final String counterpartyName; // Nama akun lawan atau keterangan
List<String> tags;
// Metadata Firefly III untuk keperluan sinkronisasi/edit
String? transactionGroupId;
String? transactionJournalId;
// File attachments lokal untuk keperluan SPJ/Laporan
String? fotoBarangPath;
String? fotoBarangName;
String? invoicePath;
String? invoiceName;
String? invoiceType; // 'pdf' atau 'image'
String? invoiceSnapshotPath; // Path gambar PNG hasil render halaman PDF invoice
ReportTransaction({
required this.id,
required this.date,
required this.description,
required this.amount,
required this.direction,
required this.counterpartyName,
this.tags = const [],
this.transactionGroupId,
this.transactionJournalId,
this.fotoBarangPath,
this.fotoBarangName,
this.invoicePath,
this.invoiceName,
this.invoiceType,
this.invoiceSnapshotPath,
});
bool get isPengeluaran => direction == 'pengeluaran';
bool get isPemasukan => direction == 'pemasukan';
bool get hasFotoBarang => fotoBarangPath != null && fotoBarangPath!.isNotEmpty;
bool get hasInvoice => invoicePath != null && invoicePath!.isNotEmpty;
bool get hasInvoiceSnapshot =>
invoiceSnapshotPath != null && invoiceSnapshotPath!.isNotEmpty;
/// Pengeluaran wajib foto barang & invoice. Pemasukan selalu dianggap lengkap.
bool get isComplete => !isPengeluaran || (hasFotoBarang && hasInvoice);
/// Status badge attachment untuk pengeluaran: 'complete', 'partial', atau 'missing'
String get attachmentStatus {
if (!isPengeluaran) return 'not_required';
if (hasFotoBarang && hasInvoice) return 'complete';
if (hasFotoBarang || hasInvoice) return 'partial';
return 'missing';
}
ReportTransaction copyWith({
String? id,
DateTime? date,
String? description,
double? amount,
String? direction,
String? counterpartyName,
List<String>? tags,
String? transactionGroupId,
String? transactionJournalId,
String? fotoBarangPath,
String? fotoBarangName,
String? invoicePath,
String? invoiceName,
String? invoiceType,
String? invoiceSnapshotPath,
}) {
return ReportTransaction(
id: id ?? this.id,
date: date ?? this.date,
description: description ?? this.description,
amount: amount ?? this.amount,
direction: direction ?? this.direction,
counterpartyName: counterpartyName ?? this.counterpartyName,
tags: tags ?? List<String>.from(this.tags),
transactionGroupId: transactionGroupId ?? this.transactionGroupId,
transactionJournalId: transactionJournalId ?? this.transactionJournalId,
fotoBarangPath: fotoBarangPath ?? this.fotoBarangPath,
fotoBarangName: fotoBarangName ?? this.fotoBarangName,
invoicePath: invoicePath ?? this.invoicePath,
invoiceName: invoiceName ?? this.invoiceName,
invoiceType: invoiceType ?? this.invoiceType,
invoiceSnapshotPath: invoiceSnapshotPath ?? this.invoiceSnapshotPath,
);
}
factory ReportTransaction.fromJson(Map<String, dynamic> json) {
List<String> parsedTags = [];
if (json['tags'] is List) {
parsedTags = (json['tags'] as List).map((e) => e.toString()).toList();
}
return ReportTransaction(
id: json['id']?.toString() ?? '',
date: DateTime.tryParse(json['date']?.toString() ?? '') ?? DateTime.now(),
description: json['description']?.toString() ?? '-',
amount: (json['amount'] is num)
? (json['amount'] as num).toDouble()
: double.tryParse(json['amount']?.toString() ?? '0') ?? 0.0,
direction: json['direction']?.toString() ?? 'pengeluaran',
counterpartyName: json['counterpartyName']?.toString() ?? '-',
tags: parsedTags,
transactionGroupId: json['transactionGroupId']?.toString(),
transactionJournalId: json['transactionJournalId']?.toString(),
fotoBarangPath: json['fotoBarangPath']?.toString(),
fotoBarangName: json['fotoBarangName']?.toString(),
invoicePath: json['invoicePath']?.toString(),
invoiceName: json['invoiceName']?.toString(),
invoiceType: json['invoiceType']?.toString(),
invoiceSnapshotPath: json['invoiceSnapshotPath']?.toString(),
);
}
Map<String, dynamic> toJson() {
return {
'id': id,
'date': date.toIso8601String(),
'description': description,
'amount': amount,
'direction': direction,
'counterpartyName': counterpartyName,
'tags': tags,
'transactionGroupId': transactionGroupId,
'transactionJournalId': transactionJournalId,
'fotoBarangPath': fotoBarangPath,
'fotoBarangName': fotoBarangName,
'invoicePath': invoicePath,
'invoiceName': invoiceName,
'invoiceType': invoiceType,
'invoiceSnapshotPath': invoiceSnapshotPath,
};
}
}