feat: Implement full certificate management with upload, upsert, delete, and new domain models for staff certificates and their statuses.

This commit is contained in:
Achintha Isuru
2026-02-26 23:28:59 -05:00
parent ca0ba258e2
commit 425bf19a9b
27 changed files with 1525 additions and 210 deletions

View File

@@ -78,6 +78,10 @@ export 'src/adapters/financial/bank_account/bank_account_adapter.dart';
// Profile
export 'src/entities/profile/staff_document.dart';
export 'src/entities/profile/document_verification_status.dart';
export 'src/entities/profile/staff_certificate.dart';
export 'src/entities/profile/compliance_type.dart';
export 'src/entities/profile/staff_certificate_status.dart';
export 'src/entities/profile/staff_certificate_validation_status.dart';
export 'src/entities/profile/attire_item.dart';
export 'src/entities/profile/attire_verification_status.dart';
export 'src/entities/profile/relationship_type.dart';

View File

@@ -0,0 +1,25 @@
/// Represents the broad category of a compliance certificate.
enum ComplianceType {
backgroundCheck('BACKGROUND_CHECK'),
foodHandler('FOOD_HANDLER'),
rbs('RBS'),
legal('LEGAL'),
operational('OPERATIONAL'),
safety('SAFETY'),
training('TRAINING'),
license('LICENSE'),
other('OTHER');
const ComplianceType(this.value);
/// The string value expected by the backend.
final String value;
/// Creates a [ComplianceType] from a string.
static ComplianceType fromString(String value) {
return ComplianceType.values.firstWhere(
(ComplianceType e) => e.value == value,
orElse: () => ComplianceType.other,
);
}
}

View File

@@ -0,0 +1,120 @@
import 'package:equatable/equatable.dart';
import 'compliance_type.dart';
import 'staff_certificate_status.dart';
import 'staff_certificate_validation_status.dart';
/// Represents a staff's compliance certificate record.
class StaffCertificate extends Equatable {
const StaffCertificate({
required this.id,
required this.staffId,
required this.name,
this.description,
this.expiryDate,
required this.status,
this.certificateUrl,
this.icon,
required this.certificationType,
this.issuer,
this.certificateNumber,
this.validationStatus,
this.createdAt,
this.updatedAt,
});
/// The unique identifier of the certificate record.
final String id;
/// The ID of the staff member.
final String staffId;
/// The display name of the certificate.
final String name;
/// A description or details about the certificate.
final String? description;
/// The expiration date of the certificate.
final DateTime? expiryDate;
/// The current state of the certificate.
final StaffCertificateStatus status;
/// The URL of the stored certificate file/image.
final String? certificateUrl;
/// An icon to display for this certificate type.
final String? icon;
/// The category of compliance this certificate fits into.
final ComplianceType certificationType;
/// The issuing body or authority.
final String? issuer;
/// Document number or reference.
final String? certificateNumber;
/// Recent validation/verification results.
final StaffCertificateValidationStatus? validationStatus;
/// Creation timestamp.
final DateTime? createdAt;
/// Last update timestamp.
final DateTime? updatedAt;
@override
List<Object?> get props => <Object?>[
id,
staffId,
name,
description,
expiryDate,
status,
certificateUrl,
icon,
certificationType,
issuer,
certificateNumber,
validationStatus,
createdAt,
updatedAt,
];
/// Creates a copy of this [StaffCertificate] with updated fields.
StaffCertificate copyWith({
String? id,
String? staffId,
String? name,
String? description,
DateTime? expiryDate,
StaffCertificateStatus? status,
String? certificateUrl,
String? icon,
ComplianceType? certificationType,
String? issuer,
String? certificateNumber,
StaffCertificateValidationStatus? validationStatus,
DateTime? createdAt,
DateTime? updatedAt,
}) {
return StaffCertificate(
id: id ?? this.id,
staffId: staffId ?? this.staffId,
name: name ?? this.name,
description: description ?? this.description,
expiryDate: expiryDate ?? this.expiryDate,
status: status ?? this.status,
certificateUrl: certificateUrl ?? this.certificateUrl,
icon: icon ?? this.icon,
certificationType: certificationType ?? this.certificationType,
issuer: issuer ?? this.issuer,
certificateNumber: certificateNumber ?? this.certificateNumber,
validationStatus: validationStatus ?? this.validationStatus,
createdAt: createdAt ?? this.createdAt,
updatedAt: updatedAt ?? this.updatedAt,
);
}
}

View File

@@ -0,0 +1,23 @@
/// Represents the current validity status of a staff certificate.
enum StaffCertificateStatus {
current('CURRENT'),
expiringSoon('EXPIRING_SOON'),
completed('COMPLETED'),
pending('PENDING'),
expired('EXPIRED'),
expiring('EXPIRING'),
notStarted('NOT_STARTED');
const StaffCertificateStatus(this.value);
/// The string value expected by the backend.
final String value;
/// Creates a [StaffCertificateStatus] from a string.
static StaffCertificateStatus fromString(String value) {
return StaffCertificateStatus.values.firstWhere(
(StaffCertificateStatus e) => e.value == value,
orElse: () => StaffCertificateStatus.notStarted,
);
}
}

View File

@@ -0,0 +1,22 @@
/// Represents the verification or review state for a staff certificate.
enum StaffCertificateValidationStatus {
approved('APPROVED'),
pendingExpertReview('PENDING_EXPERT_REVIEW'),
rejected('REJECTED'),
aiVerified('AI_VERIFIED'),
aiFlagged('AI_FLAGGED'),
manualReviewNeeded('MANUAL_REVIEW_NEEDED');
const StaffCertificateValidationStatus(this.value);
/// The string value expected by the backend.
final String value;
/// Creates a [StaffCertificateValidationStatus] from a string.
static StaffCertificateValidationStatus fromString(String value) {
return StaffCertificateValidationStatus.values.firstWhere(
(StaffCertificateValidationStatus e) => e.value == value,
orElse: () => StaffCertificateValidationStatus.manualReviewNeeded,
);
}
}