Files
worker/lib/features/projects/domain/entities/project_submission.dart
2025-10-24 11:31:48 +07:00

248 lines
6.0 KiB
Dart

/// Domain Entity: Project Submission
///
/// Represents a completed project submitted for loyalty points.
library;
/// Project type enum
enum ProjectType {
/// Residential project
residential,
/// Commercial project
commercial,
/// Industrial project
industrial,
/// Public infrastructure
infrastructure,
/// Other type
other;
/// Get display name for project type
String get displayName {
switch (this) {
case ProjectType.residential:
return 'Residential';
case ProjectType.commercial:
return 'Commercial';
case ProjectType.industrial:
return 'Industrial';
case ProjectType.infrastructure:
return 'Infrastructure';
case ProjectType.other:
return 'Other';
}
}
}
/// Submission status enum
enum SubmissionStatus {
/// Submitted, pending review
pending,
/// Under review
reviewing,
/// Approved, points awarded
approved,
/// Rejected
rejected;
/// Get display name for status
String get displayName {
switch (this) {
case SubmissionStatus.pending:
return 'Pending';
case SubmissionStatus.reviewing:
return 'Reviewing';
case SubmissionStatus.approved:
return 'Approved';
case SubmissionStatus.rejected:
return 'Rejected';
}
}
}
/// Project Submission Entity
///
/// Contains information about a completed project:
/// - Project details
/// - Before/after photos
/// - Invoice documentation
/// - Review status
/// - Points earned
class ProjectSubmission {
/// Unique submission identifier
final String submissionId;
/// User ID who submitted
final String userId;
/// Project name
final String projectName;
/// Project address/location
final String? projectAddress;
/// Project value/cost
final double projectValue;
/// Project type
final ProjectType projectType;
/// Before photos URLs
final List<String> beforePhotos;
/// After photos URLs
final List<String> afterPhotos;
/// Invoice/receipt URLs
final List<String> invoices;
/// Submission status
final SubmissionStatus status;
/// Review notes from admin
final String? reviewNotes;
/// Rejection reason (if rejected)
final String? rejectionReason;
/// Points earned (if approved)
final int? pointsEarned;
/// Submission timestamp
final DateTime submittedAt;
/// Review timestamp
final DateTime? reviewedAt;
/// ID of admin who reviewed
final String? reviewedBy;
const ProjectSubmission({
required this.submissionId,
required this.userId,
required this.projectName,
this.projectAddress,
required this.projectValue,
required this.projectType,
required this.beforePhotos,
required this.afterPhotos,
required this.invoices,
required this.status,
this.reviewNotes,
this.rejectionReason,
this.pointsEarned,
required this.submittedAt,
this.reviewedAt,
this.reviewedBy,
});
/// Check if submission is pending
bool get isPending => status == SubmissionStatus.pending;
/// Check if submission is under review
bool get isReviewing => status == SubmissionStatus.reviewing;
/// Check if submission is approved
bool get isApproved => status == SubmissionStatus.approved;
/// Check if submission is rejected
bool get isRejected => status == SubmissionStatus.rejected;
/// Check if submission has been reviewed
bool get isReviewed =>
status == SubmissionStatus.approved || status == SubmissionStatus.rejected;
/// Check if submission has before photos
bool get hasBeforePhotos => beforePhotos.isNotEmpty;
/// Check if submission has after photos
bool get hasAfterPhotos => afterPhotos.isNotEmpty;
/// Check if submission has invoices
bool get hasInvoices => invoices.isNotEmpty;
/// Get total number of photos
int get totalPhotos => beforePhotos.length + afterPhotos.length;
/// Get review duration
Duration? get reviewDuration {
if (reviewedAt == null) return null;
return reviewedAt!.difference(submittedAt);
}
/// Copy with method for immutability
ProjectSubmission copyWith({
String? submissionId,
String? userId,
String? projectName,
String? projectAddress,
double? projectValue,
ProjectType? projectType,
List<String>? beforePhotos,
List<String>? afterPhotos,
List<String>? invoices,
SubmissionStatus? status,
String? reviewNotes,
String? rejectionReason,
int? pointsEarned,
DateTime? submittedAt,
DateTime? reviewedAt,
String? reviewedBy,
}) {
return ProjectSubmission(
submissionId: submissionId ?? this.submissionId,
userId: userId ?? this.userId,
projectName: projectName ?? this.projectName,
projectAddress: projectAddress ?? this.projectAddress,
projectValue: projectValue ?? this.projectValue,
projectType: projectType ?? this.projectType,
beforePhotos: beforePhotos ?? this.beforePhotos,
afterPhotos: afterPhotos ?? this.afterPhotos,
invoices: invoices ?? this.invoices,
status: status ?? this.status,
reviewNotes: reviewNotes ?? this.reviewNotes,
rejectionReason: rejectionReason ?? this.rejectionReason,
pointsEarned: pointsEarned ?? this.pointsEarned,
submittedAt: submittedAt ?? this.submittedAt,
reviewedAt: reviewedAt ?? this.reviewedAt,
reviewedBy: reviewedBy ?? this.reviewedBy,
);
}
@override
bool operator ==(Object other) {
if (identical(this, other)) return true;
return other is ProjectSubmission &&
other.submissionId == submissionId &&
other.userId == userId &&
other.projectName == projectName &&
other.projectValue == projectValue &&
other.status == status;
}
@override
int get hashCode {
return Object.hash(
submissionId,
userId,
projectName,
projectValue,
status,
);
}
@override
String toString() {
return 'ProjectSubmission(submissionId: $submissionId, projectName: $projectName, '
'projectValue: $projectValue, projectType: $projectType, status: $status, '
'pointsEarned: $pointsEarned)';
}
}