Skip to content

Commit

Permalink
Merge pull request #252 from effectivemade/backendApp/feature/newApiV…
Browse files Browse the repository at this point in the history
…ersion

Backend: new api version
  • Loading branch information
zavyalov-daniil authored Apr 28, 2024
2 parents 7773a21 + e0fe663 commit b025d04
Show file tree
Hide file tree
Showing 40 changed files with 2,078 additions and 624 deletions.
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
package office.effective.common.constants

import office.effective.config
import org.threeten.bp.LocalDateTime
import java.time.Instant
import java.util.*

/**
* Constants for booking
Expand All @@ -15,10 +18,13 @@ object BookingConstants {
val DEFAULT_CALENDAR: String = System.getenv("DEFAULT_CALENDAR")
?: config.propertyOrNull("calendar.defaultCalendar")?.getString()
?: throw Exception("Environment and config file does not contain Google default calendar id")
val WORKSPACE_CALENDAR: String = System.getenv("WORKSPACE_CALENDAR")
val REGULAR_WORKSPACES_CALENDAR: String = System.getenv("WORKSPACE_CALENDAR")
?: config.propertyOrNull("calendar.workspaceCalendar")?.getString()
?: throw Exception("Environment and config file does not contain workspace Google calendar id")
val DEFAULT_TIMEZONE_ID: String = config.propertyOrNull("calendar.defaultTimezone")?.getString()
?: throw Exception("Config file does not contain default timezone id")
val DEFAULT_TIMEZONE_OFFSET_MILLIS: Long = TimeZone.getTimeZone(DEFAULT_TIMEZONE_ID)
.getOffset(Instant.now().toEpochMilli())
.toLong()
const val UNTIL_FORMAT = "yyyyMMdd"
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,13 @@ import kotlinx.serialization.Serializable
import model.RecurrenceDTO

@Serializable
@Deprecated(
message = "Deprecated since 1.0 api version",
replaceWith = ReplaceWith(
expression = "BookingRequestDTO or BookingResponseDTO",
imports = ["office.effective.dto.BookingRequestDTO"]
)
)
data class BookingDTO (
val owner: UserDTO,
val participants: List<UserDTO>,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package office.effective.dto

import kotlinx.serialization.Serializable
import model.RecurrenceDTO

@Serializable
data class BookingRequestDTO (
val ownerEmail: String?,
val participantEmails: List<String>,
val workspaceId: String,
val beginBooking: Long,
val endBooking: Long,
val recurrence: RecurrenceDTO? = null
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package office.effective.dto

import kotlinx.serialization.Serializable
import model.RecurrenceDTO

@Serializable
data class BookingResponseDTO (
val owner: UserDTO?,
val participants: List<UserDTO>,
val workspace: WorkspaceDTO,
val id: String,
val beginBooking: Long,
val endBooking: Long,
val recurrence: RecurrenceDTO? = null,
val recurringBookingId: String? = null
)
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,6 @@ data class WorkspaceDTO(
val name: String,
val utilities: List<UtilityDTO>,
val zone: WorkspaceZoneDTO? = null,
val tag: String
val tag: String,
val bookings: List<BookingResponseDTO>? = null
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,172 @@
package office.effective.features.booking.converters

import model.RecurrenceDTO
import office.effective.common.exception.InstanceNotFoundException
import office.effective.common.exception.MissingIdException
import office.effective.common.utils.UuidValidator
import office.effective.dto.BookingDTO
import office.effective.dto.BookingRequestDTO
import office.effective.dto.BookingResponseDTO
import office.effective.dto.UserDTO
import office.effective.features.user.converters.UserDTOModelConverter
import office.effective.features.user.repository.UserRepository
import office.effective.features.workspace.converters.WorkspaceFacadeConverter
import office.effective.features.workspace.repository.WorkspaceRepository
import office.effective.model.*
import org.slf4j.LoggerFactory
import java.time.Instant

/**
* Converts between [BookingDTO] and [Booking]
*
* Uses [UserDTOModelConverter] and [WorkspaceFacadeConverter] to convert contained users and workspaces
*/
class BookingDtoModelConverter(
private val userConverter: UserDTOModelConverter,
private val workspaceConverter: WorkspaceFacadeConverter,
private val userRepository: UserRepository,
private val workspaceRepository: WorkspaceRepository,
private val uuidValidator: UuidValidator
) {
private val logger = LoggerFactory.getLogger(this::class.java)

/**
* Converts [Booking] to [BookingDTO]
*
* @param booking [Booking] to be converted
* @return The resulting [BookingDTO] object
* @author Daniil Zavyalov, Danil Kiselev
*/
@Deprecated(
message = "Deprecated since 1.0 api version",
replaceWith = ReplaceWith("modelToResponseDto(booking)")
)
fun modelToDto(booking: Booking): BookingDTO {
logger.trace("Converting booking model to dto")
var recurrenceDTO : RecurrenceDTO? = null
if(booking.recurrence != null) {
recurrenceDTO = RecurrenceConverter.modelToDto(booking.recurrence!!)
}
return BookingDTO(
owner = booking.owner?.let { userConverter.modelToDTO(it) }
?: UserDTO("", "", true, "", "", listOf(), "", ""),
participants = booking.participants.map { userConverter.modelToDTO(it) },
workspace = workspaceConverter.modelToDto(booking.workspace),
id = booking.id.toString(),
beginBooking = booking.beginBooking.toEpochMilli(),
endBooking = booking.endBooking.toEpochMilli(),
recurrence = recurrenceDTO
)
}

/**
* Converts [Booking] to [BookingResponseDTO]
*
* @throws [MissingIdException] if [booking] doesn't contain an id
* @param booking [Booking] to be converted
* @return The resulting [BookingResponseDTO] object
* @author Daniil Zavyalov, Danil Kiselev
*/
fun modelToResponseDto(booking: Booking): BookingResponseDTO {
logger.trace("Converting booking model to response dto")
val id = booking.id ?: throw MissingIdException("Booking response must contains an id, but it was missed")
val owner = booking.owner?.let {
owner -> userConverter.modelToDTO(owner)
}
val participants = booking.participants.map {
participant -> userConverter.modelToDTO(participant)
}
val recurrence = booking.recurrence?.let {
recurrenceModel -> RecurrenceConverter.modelToDto(recurrenceModel)
}
return BookingResponseDTO(
owner = owner,
participants = participants,
workspace = workspaceConverter.modelToDto(booking.workspace),
id = id,
beginBooking = booking.beginBooking.toEpochMilli(),
endBooking = booking.endBooking.toEpochMilli(),
recurrence = recurrence,
recurringBookingId = booking.recurringBookingId
)
}

/**
* Converts [BookingDTO] to [Booking]
*
* @param bookingDTO [BookingDTO] to be converted
* @return The resulting [Booking] object
* @author Daniil Zavyalov, Danil Kiselev
*/
@Deprecated(
message = "Deprecated since 1.0 api version",
replaceWith = ReplaceWith("requestDtoToModel(booking)")
)
fun dtoToModel(bookingDTO: BookingDTO): Booking {
logger.trace("Converting booking dto to model")
var recurrenceModel : RecurrenceModel? = null
if(bookingDTO.recurrence != null) {
recurrenceModel = RecurrenceConverter.dtoToModel(bookingDTO.recurrence)
}
return Booking(
owner = userConverter.dTOToModel(bookingDTO.owner),
participants = bookingDTO.participants.map { userConverter.dTOToModel(it) },
workspace = workspaceConverter.dtoToModel(bookingDTO.workspace),
id = bookingDTO.id,
beginBooking = Instant.ofEpochMilli(bookingDTO.beginBooking),
endBooking = Instant.ofEpochMilli(bookingDTO.endBooking),
recurrence = recurrenceModel
)
}

/**
* Converts [BookingDTO] to [Booking]. Users and workspace will be retrieved from database
*
* @param bookingDto [BookingDTO] to be converted
* @param id booking id
* @return The resulting [Booking] object
* @throws [InstanceNotFoundException] if user with the given email or
* workspace with the given id doesn't exist in database
* @author Daniil Zavyalov, Danil Kiselev
*/
fun requestDtoToModel(bookingDto: BookingRequestDTO, id: String? = null): Booking {
logger.trace("Converting booking response dto to model")
val recurrence = bookingDto.recurrence?.let {
recurrenceDto -> RecurrenceConverter.dtoToModel(recurrenceDto)
}
val owner: UserModel? = findOwner(bookingDto.ownerEmail)
val participants = findParticipants(bookingDto.participantEmails)
val workspace = findWorkspace(bookingDto.workspaceId)
return Booking(
owner = owner,
participants = participants,
workspace = workspace,
id = id,
beginBooking = Instant.ofEpochMilli(bookingDto.beginBooking),
endBooking = Instant.ofEpochMilli(bookingDto.endBooking),
recurrence = recurrence,
)
}

private fun findOwner(ownerEmail: String?): UserModel? {
if (ownerEmail != null) {
return userRepository.findByEmail(ownerEmail)
?: throw InstanceNotFoundException(UserModel::class, "User with email $ownerEmail not found")
}
return null
}

private fun findParticipants(participantEmails: List<String>): List<UserModel> {
val users = userRepository.findAllByEmails(participantEmails)
if (users.size < participantEmails.size) {
throw InstanceNotFoundException(UserModel::class, "Participant not found")
}
return users
}

private fun findWorkspace(workspaceUuid: String): Workspace {
return workspaceRepository.findById(
uuidValidator.uuidFromString(workspaceUuid)
) ?: throw InstanceNotFoundException(Workspace::class, "Workspace with id $workspaceUuid not found")
}
}

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import office.effective.common.utils.UuidValidator
import office.effective.features.booking.repository.WorkspaceBookingEntity
import office.effective.features.user.converters.UserModelEntityConverter
import office.effective.features.user.repository.UserEntity
import office.effective.features.user.repository.UsersTagEntity
import office.effective.features.user.repository.users
import office.effective.features.workspace.converters.WorkspaceRepositoryConverter
import office.effective.features.workspace.repository.WorkspaceEntity
Expand Down Expand Up @@ -75,7 +76,16 @@ class BookingRepositoryConverter(private val database: Database,
fun modelToEntity(bookingModel: Booking): WorkspaceBookingEntity {
logger.trace("Converting booking model to entity")
return WorkspaceBookingEntity {
owner = findOwnerEntity(bookingModel.owner)
owner = bookingModel.owner?.let { findOwnerEntity(it) }
?: UserEntity {
id = UUID.randomUUID()
fullName = ""
tag = UsersTagEntity {}
active = false
role = ""
avatarURL = ""
email = ""
}
workspace = findWorkspaceEntity(bookingModel.workspace)
id = bookingModel.id?.let { uuidValidator.uuidFromString(it) }
?: throw MissingIdException("Booking model doesn't have an id")
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package office.effective.features.booking.converters

import com.google.api.client.util.DateTime
import office.effective.common.constants.BookingConstants

/**
* Converts local time to Google [DateTime] in GMT.
*
* Use it for all requests to Google Calendar.
*/
fun Long.toGoogleDateTime(): DateTime {
return DateTime(this - BookingConstants.DEFAULT_TIMEZONE_OFFSET_MILLIS)
}
Loading

0 comments on commit b025d04

Please sign in to comment.