refactor: Migrate from monolithic to modular architecture
### **Service-Implementation** - [ ] **Tag 1**: Members-Service REST-API implementieren - [ ] **Tag 2**: Database-Migrations und Repository-Layer - [ ] **Tag 3**: Event-Publishing nach Kafka aktivieren - [ ] **Tag 4**: Horses-Service analog implementieren - [ ] **Tag 5**: Integration-Tests für beide Services - [ ] **Tag 6-7**: Events-Service und Masterdata-Service
This commit is contained in:
@@ -6,5 +6,6 @@ dependencies {
|
||||
implementation(projects.members.membersDomain)
|
||||
implementation(projects.core.coreDomain)
|
||||
implementation(projects.core.coreUtils)
|
||||
implementation(projects.infrastructure.messaging.messagingClient)
|
||||
testImplementation(projects.platform.platformTesting)
|
||||
}
|
||||
|
||||
+239
@@ -0,0 +1,239 @@
|
||||
package at.mocode.members.application.usecase
|
||||
|
||||
import at.mocode.core.domain.model.ApiResponse
|
||||
import at.mocode.core.domain.model.ErrorDto
|
||||
import at.mocode.members.domain.model.Member
|
||||
import at.mocode.members.domain.repository.MemberRepository
|
||||
import at.mocode.members.domain.events.MemberCreatedEvent
|
||||
import at.mocode.infrastructure.messaging.client.EventPublisher
|
||||
import at.mocode.core.utils.validation.ValidationResult
|
||||
import at.mocode.core.utils.validation.ValidationError
|
||||
import com.benasher44.uuid.uuid4
|
||||
import kotlinx.datetime.Clock
|
||||
import kotlinx.datetime.LocalDate
|
||||
|
||||
/**
|
||||
* Use case for creating new members.
|
||||
*
|
||||
* This use case handles the business logic for creating members,
|
||||
* including validation and persistence.
|
||||
*/
|
||||
class CreateMemberUseCase(
|
||||
private val memberRepository: MemberRepository,
|
||||
private val eventPublisher: EventPublisher
|
||||
) {
|
||||
|
||||
/**
|
||||
* Request data for creating a new member.
|
||||
*/
|
||||
data class CreateMemberRequest(
|
||||
val firstName: String,
|
||||
val lastName: String,
|
||||
val email: String,
|
||||
val phone: String? = null,
|
||||
val dateOfBirth: LocalDate? = null,
|
||||
val membershipNumber: String,
|
||||
val membershipStartDate: LocalDate,
|
||||
val membershipEndDate: LocalDate? = null,
|
||||
val isActive: Boolean = true,
|
||||
val address: String? = null,
|
||||
val emergencyContact: String? = null
|
||||
)
|
||||
|
||||
/**
|
||||
* Response data containing the created member.
|
||||
*/
|
||||
data class CreateMemberResponse(
|
||||
val member: Member
|
||||
)
|
||||
|
||||
/**
|
||||
* Executes the create member use case.
|
||||
*
|
||||
* @param request The request containing member data
|
||||
* @return ApiResponse with the created member or error information
|
||||
*/
|
||||
suspend fun execute(request: CreateMemberRequest): ApiResponse<CreateMemberResponse> {
|
||||
return try {
|
||||
// Validate the request
|
||||
val validationResult = validateRequest(request)
|
||||
if (!validationResult.isValid()) {
|
||||
val errors = (validationResult as ValidationResult.Invalid).errors
|
||||
return ApiResponse(
|
||||
success = false,
|
||||
error = ErrorDto(
|
||||
code = "VALIDATION_ERROR",
|
||||
message = "Invalid input data",
|
||||
details = errors.associate { it.field to it.message }
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
// Check for duplicate membership number
|
||||
if (memberRepository.existsByMembershipNumber(request.membershipNumber)) {
|
||||
return ApiResponse(
|
||||
success = false,
|
||||
error = ErrorDto(
|
||||
code = "DUPLICATE_MEMBERSHIP_NUMBER",
|
||||
message = "Membership number already exists"
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
// Check for duplicate email
|
||||
if (memberRepository.existsByEmail(request.email)) {
|
||||
return ApiResponse(
|
||||
success = false,
|
||||
error = ErrorDto(
|
||||
code = "DUPLICATE_EMAIL",
|
||||
message = "Email address already exists"
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
// Create the domain object
|
||||
val member = Member(
|
||||
firstName = request.firstName.trim(),
|
||||
lastName = request.lastName.trim(),
|
||||
email = request.email.trim().lowercase(),
|
||||
phone = request.phone?.trim(),
|
||||
dateOfBirth = request.dateOfBirth,
|
||||
membershipNumber = request.membershipNumber.trim(),
|
||||
membershipStartDate = request.membershipStartDate,
|
||||
membershipEndDate = request.membershipEndDate,
|
||||
isActive = request.isActive,
|
||||
address = request.address?.trim(),
|
||||
emergencyContact = request.emergencyContact?.trim(),
|
||||
createdAt = Clock.System.now(),
|
||||
updatedAt = Clock.System.now()
|
||||
)
|
||||
|
||||
// Validate the domain object
|
||||
val domainValidationErrors = member.validate()
|
||||
if (domainValidationErrors.isNotEmpty()) {
|
||||
return ApiResponse(
|
||||
success = false,
|
||||
error = ErrorDto(
|
||||
code = "DOMAIN_VALIDATION_ERROR",
|
||||
message = "Domain validation failed",
|
||||
details = domainValidationErrors.mapIndexed { index, error ->
|
||||
"error_$index" to error
|
||||
}.toMap()
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
// Save the member
|
||||
val savedMember = memberRepository.save(member)
|
||||
|
||||
// Publish member created event
|
||||
try {
|
||||
val event = MemberCreatedEvent(
|
||||
eventId = uuid4().toString(),
|
||||
memberId = savedMember.memberId,
|
||||
timestamp = Clock.System.now(),
|
||||
firstName = savedMember.firstName,
|
||||
lastName = savedMember.lastName,
|
||||
email = savedMember.email,
|
||||
membershipNumber = savedMember.membershipNumber,
|
||||
membershipStartDate = savedMember.membershipStartDate,
|
||||
isActive = savedMember.isActive
|
||||
)
|
||||
eventPublisher.publishEvent("member-events", savedMember.memberId.toString(), event)
|
||||
} catch (e: Exception) {
|
||||
// Log the error but don't fail the operation
|
||||
// In a production system, you might want to use a dead letter queue or retry mechanism
|
||||
println("Failed to publish member created event: ${e.message}")
|
||||
}
|
||||
|
||||
ApiResponse(
|
||||
success = true,
|
||||
data = CreateMemberResponse(savedMember)
|
||||
)
|
||||
|
||||
} catch (e: Exception) {
|
||||
ApiResponse(
|
||||
success = false,
|
||||
error = ErrorDto(
|
||||
code = "INTERNAL_ERROR",
|
||||
message = "Failed to create member: ${e.message}"
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates the create member request.
|
||||
*/
|
||||
private fun validateRequest(request: CreateMemberRequest): ValidationResult {
|
||||
val errors = mutableListOf<ValidationError>()
|
||||
|
||||
// Validate first name
|
||||
if (request.firstName.isBlank()) {
|
||||
errors.add(ValidationError("firstName", "First name is required"))
|
||||
} else if (request.firstName.length > 100) {
|
||||
errors.add(ValidationError("firstName", "First name must not exceed 100 characters"))
|
||||
}
|
||||
|
||||
// Validate last name
|
||||
if (request.lastName.isBlank()) {
|
||||
errors.add(ValidationError("lastName", "Last name is required"))
|
||||
} else if (request.lastName.length > 100) {
|
||||
errors.add(ValidationError("lastName", "Last name must not exceed 100 characters"))
|
||||
}
|
||||
|
||||
// Validate email
|
||||
if (request.email.isBlank()) {
|
||||
errors.add(ValidationError("email", "Email is required"))
|
||||
} else if (!isValidEmail(request.email)) {
|
||||
errors.add(ValidationError("email", "Email format is invalid"))
|
||||
} else if (request.email.length > 255) {
|
||||
errors.add(ValidationError("email", "Email must not exceed 255 characters"))
|
||||
}
|
||||
|
||||
// Validate membership number
|
||||
if (request.membershipNumber.isBlank()) {
|
||||
errors.add(ValidationError("membershipNumber", "Membership number is required"))
|
||||
} else if (request.membershipNumber.length > 50) {
|
||||
errors.add(ValidationError("membershipNumber", "Membership number must not exceed 50 characters"))
|
||||
}
|
||||
|
||||
// Validate membership dates
|
||||
request.membershipEndDate?.let { endDate ->
|
||||
if (endDate < request.membershipStartDate) {
|
||||
errors.add(ValidationError("membershipEndDate", "Membership end date cannot be before start date"))
|
||||
}
|
||||
}
|
||||
|
||||
// Validate phone
|
||||
request.phone?.let { phone ->
|
||||
if (phone.length > 50) {
|
||||
errors.add(ValidationError("phone", "Phone number must not exceed 50 characters"))
|
||||
}
|
||||
}
|
||||
|
||||
// Validate address
|
||||
request.address?.let { address ->
|
||||
if (address.length > 500) {
|
||||
errors.add(ValidationError("address", "Address must not exceed 500 characters"))
|
||||
}
|
||||
}
|
||||
|
||||
// Validate emergency contact
|
||||
request.emergencyContact?.let { contact ->
|
||||
if (contact.length > 255) {
|
||||
errors.add(ValidationError("emergencyContact", "Emergency contact must not exceed 255 characters"))
|
||||
}
|
||||
}
|
||||
|
||||
return if (errors.isEmpty()) {
|
||||
ValidationResult.Valid
|
||||
} else {
|
||||
ValidationResult.Invalid(errors)
|
||||
}
|
||||
}
|
||||
|
||||
private fun isValidEmail(email: String): Boolean {
|
||||
return email.contains("@") && email.contains(".") && email.indexOf("@") < email.lastIndexOf(".")
|
||||
}
|
||||
}
|
||||
+84
@@ -0,0 +1,84 @@
|
||||
package at.mocode.members.application.usecase
|
||||
|
||||
import at.mocode.core.domain.model.ApiResponse
|
||||
import at.mocode.core.domain.model.ErrorDto
|
||||
import at.mocode.members.domain.repository.MemberRepository
|
||||
import com.benasher44.uuid.Uuid
|
||||
|
||||
/**
|
||||
* Use case for deleting members.
|
||||
*
|
||||
* This use case handles the business logic for deleting members
|
||||
* from the system.
|
||||
*/
|
||||
class DeleteMemberUseCase(
|
||||
private val memberRepository: MemberRepository
|
||||
) {
|
||||
|
||||
/**
|
||||
* Request data for deleting a member.
|
||||
*/
|
||||
data class DeleteMemberRequest(
|
||||
val memberId: Uuid
|
||||
)
|
||||
|
||||
/**
|
||||
* Response data for delete operation.
|
||||
*/
|
||||
data class DeleteMemberResponse(
|
||||
val success: Boolean,
|
||||
val message: String
|
||||
)
|
||||
|
||||
/**
|
||||
* Executes the delete member use case.
|
||||
*
|
||||
* @param request The request containing member ID to delete
|
||||
* @return ApiResponse with the result or error information
|
||||
*/
|
||||
suspend fun execute(request: DeleteMemberRequest): ApiResponse<DeleteMemberResponse> {
|
||||
return try {
|
||||
// Check if member exists
|
||||
val existingMember = memberRepository.findById(request.memberId)
|
||||
if (existingMember == null) {
|
||||
return ApiResponse(
|
||||
success = false,
|
||||
error = ErrorDto(
|
||||
code = "MEMBER_NOT_FOUND",
|
||||
message = "Member not found"
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
// Delete the member
|
||||
val deleted = memberRepository.delete(request.memberId)
|
||||
|
||||
if (deleted) {
|
||||
ApiResponse(
|
||||
success = true,
|
||||
data = DeleteMemberResponse(
|
||||
success = true,
|
||||
message = "Member deleted successfully"
|
||||
)
|
||||
)
|
||||
} else {
|
||||
ApiResponse(
|
||||
success = false,
|
||||
error = ErrorDto(
|
||||
code = "DELETE_FAILED",
|
||||
message = "Failed to delete member"
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
} catch (e: Exception) {
|
||||
ApiResponse(
|
||||
success = false,
|
||||
error = ErrorDto(
|
||||
code = "INTERNAL_ERROR",
|
||||
message = "Failed to delete member: ${e.message}"
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
+131
@@ -0,0 +1,131 @@
|
||||
package at.mocode.members.application.usecase
|
||||
|
||||
import at.mocode.core.domain.model.ApiResponse
|
||||
import at.mocode.core.domain.model.ErrorDto
|
||||
import at.mocode.members.domain.model.Member
|
||||
import at.mocode.members.domain.repository.MemberRepository
|
||||
import com.benasher44.uuid.Uuid
|
||||
|
||||
/**
|
||||
* Use case for retrieving members.
|
||||
*
|
||||
* This use case handles the business logic for retrieving members
|
||||
* by various criteria.
|
||||
*/
|
||||
class GetMemberUseCase(
|
||||
private val memberRepository: MemberRepository
|
||||
) {
|
||||
|
||||
/**
|
||||
* Request data for getting a member by ID.
|
||||
*/
|
||||
data class GetMemberRequest(
|
||||
val memberId: Uuid
|
||||
)
|
||||
|
||||
/**
|
||||
* Response data containing the retrieved member.
|
||||
*/
|
||||
data class GetMemberResponse(
|
||||
val member: Member
|
||||
)
|
||||
|
||||
/**
|
||||
* Executes the get member use case.
|
||||
*
|
||||
* @param request The request containing member ID
|
||||
* @return ApiResponse with the member or error information
|
||||
*/
|
||||
suspend fun execute(request: GetMemberRequest): ApiResponse<GetMemberResponse> {
|
||||
return try {
|
||||
val member = memberRepository.findById(request.memberId)
|
||||
|
||||
if (member != null) {
|
||||
ApiResponse(
|
||||
success = true,
|
||||
data = GetMemberResponse(member)
|
||||
)
|
||||
} else {
|
||||
ApiResponse(
|
||||
success = false,
|
||||
error = ErrorDto(
|
||||
code = "MEMBER_NOT_FOUND",
|
||||
message = "Member not found"
|
||||
)
|
||||
)
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
ApiResponse(
|
||||
success = false,
|
||||
error = ErrorDto(
|
||||
code = "INTERNAL_ERROR",
|
||||
message = "Failed to retrieve member: ${e.message}"
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a member by membership number.
|
||||
*/
|
||||
suspend fun getByMembershipNumber(membershipNumber: String): ApiResponse<GetMemberResponse> {
|
||||
return try {
|
||||
val member = memberRepository.findByMembershipNumber(membershipNumber)
|
||||
|
||||
if (member != null) {
|
||||
ApiResponse(
|
||||
success = true,
|
||||
data = GetMemberResponse(member)
|
||||
)
|
||||
} else {
|
||||
ApiResponse(
|
||||
success = false,
|
||||
error = ErrorDto(
|
||||
code = "MEMBER_NOT_FOUND",
|
||||
message = "Member not found"
|
||||
)
|
||||
)
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
ApiResponse(
|
||||
success = false,
|
||||
error = ErrorDto(
|
||||
code = "INTERNAL_ERROR",
|
||||
message = "Failed to retrieve member: ${e.message}"
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a member by email address.
|
||||
*/
|
||||
suspend fun getByEmail(email: String): ApiResponse<GetMemberResponse> {
|
||||
return try {
|
||||
val member = memberRepository.findByEmail(email)
|
||||
|
||||
if (member != null) {
|
||||
ApiResponse(
|
||||
success = true,
|
||||
data = GetMemberResponse(member)
|
||||
)
|
||||
} else {
|
||||
ApiResponse(
|
||||
success = false,
|
||||
error = ErrorDto(
|
||||
code = "MEMBER_NOT_FOUND",
|
||||
message = "Member not found"
|
||||
)
|
||||
)
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
ApiResponse(
|
||||
success = false,
|
||||
error = ErrorDto(
|
||||
code = "INTERNAL_ERROR",
|
||||
message = "Failed to retrieve member: ${e.message}"
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
+226
@@ -0,0 +1,226 @@
|
||||
package at.mocode.members.application.usecase
|
||||
|
||||
import at.mocode.core.domain.model.ApiResponse
|
||||
import at.mocode.core.domain.model.ErrorDto
|
||||
import at.mocode.members.domain.model.Member
|
||||
import at.mocode.members.domain.repository.MemberRepository
|
||||
import at.mocode.core.utils.validation.ValidationResult
|
||||
import at.mocode.core.utils.validation.ValidationError
|
||||
import com.benasher44.uuid.Uuid
|
||||
import kotlinx.datetime.LocalDate
|
||||
|
||||
/**
|
||||
* Use case for updating existing members.
|
||||
*
|
||||
* This use case handles the business logic for updating members,
|
||||
* including validation and persistence.
|
||||
*/
|
||||
class UpdateMemberUseCase(
|
||||
private val memberRepository: MemberRepository
|
||||
) {
|
||||
|
||||
/**
|
||||
* Request data for updating a member.
|
||||
*/
|
||||
data class UpdateMemberRequest(
|
||||
val memberId: Uuid,
|
||||
val firstName: String,
|
||||
val lastName: String,
|
||||
val email: String,
|
||||
val phone: String? = null,
|
||||
val dateOfBirth: LocalDate? = null,
|
||||
val membershipNumber: String,
|
||||
val membershipStartDate: LocalDate,
|
||||
val membershipEndDate: LocalDate? = null,
|
||||
val isActive: Boolean = true,
|
||||
val address: String? = null,
|
||||
val emergencyContact: String? = null
|
||||
)
|
||||
|
||||
/**
|
||||
* Response data containing the updated member.
|
||||
*/
|
||||
data class UpdateMemberResponse(
|
||||
val member: Member
|
||||
)
|
||||
|
||||
/**
|
||||
* Executes the update member use case.
|
||||
*
|
||||
* @param request The request containing updated member data
|
||||
* @return ApiResponse with the updated member or error information
|
||||
*/
|
||||
suspend fun execute(request: UpdateMemberRequest): ApiResponse<UpdateMemberResponse> {
|
||||
return try {
|
||||
// Check if member exists
|
||||
val existingMember = memberRepository.findById(request.memberId)
|
||||
if (existingMember == null) {
|
||||
return ApiResponse(
|
||||
success = false,
|
||||
error = ErrorDto(
|
||||
code = "MEMBER_NOT_FOUND",
|
||||
message = "Member not found"
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
// Validate the request
|
||||
val validationResult = validateRequest(request)
|
||||
if (!validationResult.isValid()) {
|
||||
val errors = (validationResult as ValidationResult.Invalid).errors
|
||||
return ApiResponse(
|
||||
success = false,
|
||||
error = ErrorDto(
|
||||
code = "VALIDATION_ERROR",
|
||||
message = "Invalid input data",
|
||||
details = errors.associate { it.field to it.message }
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
// Check for duplicate membership number (excluding current member)
|
||||
if (memberRepository.existsByMembershipNumber(request.membershipNumber, request.memberId)) {
|
||||
return ApiResponse(
|
||||
success = false,
|
||||
error = ErrorDto(
|
||||
code = "DUPLICATE_MEMBERSHIP_NUMBER",
|
||||
message = "Membership number already exists"
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
// Check for duplicate email (excluding current member)
|
||||
if (memberRepository.existsByEmail(request.email, request.memberId)) {
|
||||
return ApiResponse(
|
||||
success = false,
|
||||
error = ErrorDto(
|
||||
code = "DUPLICATE_EMAIL",
|
||||
message = "Email address already exists"
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
// Update the member
|
||||
val updatedMember = existingMember.copy(
|
||||
firstName = request.firstName.trim(),
|
||||
lastName = request.lastName.trim(),
|
||||
email = request.email.trim().lowercase(),
|
||||
phone = request.phone?.trim(),
|
||||
dateOfBirth = request.dateOfBirth,
|
||||
membershipNumber = request.membershipNumber.trim(),
|
||||
membershipStartDate = request.membershipStartDate,
|
||||
membershipEndDate = request.membershipEndDate,
|
||||
isActive = request.isActive,
|
||||
address = request.address?.trim(),
|
||||
emergencyContact = request.emergencyContact?.trim()
|
||||
).withUpdatedTimestamp()
|
||||
|
||||
// Validate the domain object
|
||||
val domainValidationErrors = updatedMember.validate()
|
||||
if (domainValidationErrors.isNotEmpty()) {
|
||||
return ApiResponse(
|
||||
success = false,
|
||||
error = ErrorDto(
|
||||
code = "DOMAIN_VALIDATION_ERROR",
|
||||
message = "Domain validation failed",
|
||||
details = domainValidationErrors.mapIndexed { index, error ->
|
||||
"error_$index" to error
|
||||
}.toMap()
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
// Save the updated member
|
||||
val savedMember = memberRepository.save(updatedMember)
|
||||
|
||||
ApiResponse(
|
||||
success = true,
|
||||
data = UpdateMemberResponse(savedMember)
|
||||
)
|
||||
|
||||
} catch (e: Exception) {
|
||||
ApiResponse(
|
||||
success = false,
|
||||
error = ErrorDto(
|
||||
code = "INTERNAL_ERROR",
|
||||
message = "Failed to update member: ${e.message}"
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates the update member request.
|
||||
*/
|
||||
private fun validateRequest(request: UpdateMemberRequest): ValidationResult {
|
||||
val errors = mutableListOf<ValidationError>()
|
||||
|
||||
// Validate first name
|
||||
if (request.firstName.isBlank()) {
|
||||
errors.add(ValidationError("firstName", "First name is required"))
|
||||
} else if (request.firstName.length > 100) {
|
||||
errors.add(ValidationError("firstName", "First name must not exceed 100 characters"))
|
||||
}
|
||||
|
||||
// Validate last name
|
||||
if (request.lastName.isBlank()) {
|
||||
errors.add(ValidationError("lastName", "Last name is required"))
|
||||
} else if (request.lastName.length > 100) {
|
||||
errors.add(ValidationError("lastName", "Last name must not exceed 100 characters"))
|
||||
}
|
||||
|
||||
// Validate email
|
||||
if (request.email.isBlank()) {
|
||||
errors.add(ValidationError("email", "Email is required"))
|
||||
} else if (!isValidEmail(request.email)) {
|
||||
errors.add(ValidationError("email", "Email format is invalid"))
|
||||
} else if (request.email.length > 255) {
|
||||
errors.add(ValidationError("email", "Email must not exceed 255 characters"))
|
||||
}
|
||||
|
||||
// Validate membership number
|
||||
if (request.membershipNumber.isBlank()) {
|
||||
errors.add(ValidationError("membershipNumber", "Membership number is required"))
|
||||
} else if (request.membershipNumber.length > 50) {
|
||||
errors.add(ValidationError("membershipNumber", "Membership number must not exceed 50 characters"))
|
||||
}
|
||||
|
||||
// Validate membership dates
|
||||
request.membershipEndDate?.let { endDate ->
|
||||
if (endDate < request.membershipStartDate) {
|
||||
errors.add(ValidationError("membershipEndDate", "Membership end date cannot be before start date"))
|
||||
}
|
||||
}
|
||||
|
||||
// Validate phone
|
||||
request.phone?.let { phone ->
|
||||
if (phone.length > 50) {
|
||||
errors.add(ValidationError("phone", "Phone number must not exceed 50 characters"))
|
||||
}
|
||||
}
|
||||
|
||||
// Validate address
|
||||
request.address?.let { address ->
|
||||
if (address.length > 500) {
|
||||
errors.add(ValidationError("address", "Address must not exceed 500 characters"))
|
||||
}
|
||||
}
|
||||
|
||||
// Validate emergency contact
|
||||
request.emergencyContact?.let { contact ->
|
||||
if (contact.length > 255) {
|
||||
errors.add(ValidationError("emergencyContact", "Emergency contact must not exceed 255 characters"))
|
||||
}
|
||||
}
|
||||
|
||||
return if (errors.isEmpty()) {
|
||||
ValidationResult.Valid
|
||||
} else {
|
||||
ValidationResult.Invalid(errors)
|
||||
}
|
||||
}
|
||||
|
||||
private fun isValidEmail(email: String): Boolean {
|
||||
return email.contains("@") && email.contains(".") && email.indexOf("@") < email.lastIndexOf(".")
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user