diff --git a/pom.xml b/pom.xml index ce3b16d12..066f98790 100644 --- a/pom.xml +++ b/pom.xml @@ -161,6 +161,11 @@ com.mysql mysql-connector-j + + + org.hibernate.orm + hibernate-spatial + diff --git a/src/main/java/com/ays/assignment/model/Assignment.java b/src/main/java/com/ays/assignment/model/Assignment.java new file mode 100644 index 000000000..f32045701 --- /dev/null +++ b/src/main/java/com/ays/assignment/model/Assignment.java @@ -0,0 +1,32 @@ +package com.ays.assignment.model; + +import com.ays.assignment.model.enums.AssignmentStatus; +import com.ays.common.model.AysPhoneNumber; +import com.ays.common.model.BaseDomainModel; +import com.ays.institution.model.Institution; +import com.ays.user.model.User; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.experimental.SuperBuilder; + +/** + * Assignment Domain Model to perform data transfer from service layer to controller + */ +@Data +@EqualsAndHashCode(callSuper = true) +@SuperBuilder +public class Assignment extends BaseDomainModel { + + private String id; + private String description; + private String firstName; + private String lastName; + private AysPhoneNumber phoneNumber; + private Double latitude; + private Double longitude; + private AssignmentStatus status; + + private User user; + private Institution institution; + +} diff --git a/src/main/java/com/ays/assignment/model/dto/request/AssignmentListRequest.java b/src/main/java/com/ays/assignment/model/dto/request/AssignmentListRequest.java new file mode 100644 index 000000000..c7a35f0a5 --- /dev/null +++ b/src/main/java/com/ays/assignment/model/dto/request/AssignmentListRequest.java @@ -0,0 +1,79 @@ +package com.ays.assignment.model.dto.request; + +import com.ays.assignment.model.enums.AssignmentStatus; +import com.ays.common.model.dto.request.AysFilteringRequest; +import com.ays.common.model.dto.request.AysPagingRequest; +import com.ays.common.util.validation.EnumValidation; +import com.fasterxml.jackson.annotation.JsonIgnore; +import jakarta.validation.constraints.AssertTrue; +import lombok.Builder; +import lombok.Data; +import org.springframework.data.jpa.domain.Specification; + +import java.util.EnumSet; +import java.util.Set; + +/** + * Represents a request object for fetching a list of user assignment with pagination,sorting and filtering options + * This class extends the {@link AysPagingRequest} class and adds additional validation rules for sorting. + */ +@Data +@Builder +public class AssignmentListRequest extends AysPagingRequest implements AysFilteringRequest { + + private AssignmentStatus status; + + /** + * Checks if the assignment status is valid. + * + * @return true if the assignment status is valid or null, false otherwise. + */ + @AssertTrue(message = "IS ASSIGNMENT STATUS NOT ACCEPTED") + private boolean isStatusAccepted() { + + if (this.status == null) { + return true; + } + + EnumSet acceptedAssignmentStatuses = EnumSet.of(AssignmentStatus.AVAILABLE, + AssignmentStatus.RESERVED, + AssignmentStatus.ASSIGNED, + AssignmentStatus.IN_PROGRESS, + AssignmentStatus.DONE + ); + return EnumValidation.anyOf(this.status, acceptedAssignmentStatuses); + } + + /** + * Overrides the {@link AysPagingRequest#isSortPropertyAccepted()} method to validate sorting options + * and ensures that no unsupported sorting property is used in the request. + * + * @return true if the sorting property is accepted, false otherwise. + */ + @JsonIgnore + @AssertTrue + @Override + public boolean isSortPropertyAccepted() { + final Set acceptedFilterFields = Set.of(); + return this.isPropertyAccepted(acceptedFilterFields); + } + + /** + * Converts the request into a JPA Specification that filters assignments based on the specified status, + * if it is provided. + * + * @param clazz the class type of the specification. + * @return the generated JPA Specification based on the request filters. + */ + @Override + public Specification toSpecification(Class clazz) { + Specification specification = Specification.where(null); + if (status != null) { + specification = specification.and((root, query, builder) -> + builder.equal(root.get("status"), status)); + } + // Add more filter conditions if needed + return specification; + } + +} diff --git a/src/main/java/com/ays/assignment/model/dto/request/AssignmentSearchRequest.java b/src/main/java/com/ays/assignment/model/dto/request/AssignmentSearchRequest.java new file mode 100644 index 000000000..2c8ce0f49 --- /dev/null +++ b/src/main/java/com/ays/assignment/model/dto/request/AssignmentSearchRequest.java @@ -0,0 +1,21 @@ +package com.ays.assignment.model.dto.request; + +import lombok.Builder; +import lombok.Getter; + +/** + * A DTO class representing the request data for searching assignment with respect to user's location. + *

+ * This class provides getters and setters for the latitude, and longitude fields. + * It also includes a builder pattern implementation for constructing instances of this class with optional parameters. + *

+ * The purpose of this class is to encapsulate the request data related to searching assignment with respect to user's location, allowing for easy + * transfer of the data between different layers of the application. + */ +@Getter +@Builder +public class AssignmentSearchRequest { + + private Double latitude; + private Double longitude; +} diff --git a/src/main/java/com/ays/assignment/model/dto/response/AssignmentResponse.java b/src/main/java/com/ays/assignment/model/dto/response/AssignmentResponse.java new file mode 100644 index 000000000..15131dbe1 --- /dev/null +++ b/src/main/java/com/ays/assignment/model/dto/response/AssignmentResponse.java @@ -0,0 +1,25 @@ +package com.ays.assignment.model.dto.response; + +import com.ays.common.model.dto.response.BaseResponse; +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.experimental.SuperBuilder; + +/** + * A DTO (Data Transfer Object) representing a list of user assignment in a paginated response. + */ +@Getter +@EqualsAndHashCode(callSuper = true) +@SuperBuilder +public class AssignmentResponse extends BaseResponse { + + private String id; + private String description; + private String firstName; + private String lastName; + private Double longitude; + private Double latitude; + + private AssignmentSearchResponse assignmentSearchResponse; + +} diff --git a/src/main/java/com/ays/assignment/model/dto/response/AssignmentSearchResponse.java b/src/main/java/com/ays/assignment/model/dto/response/AssignmentSearchResponse.java new file mode 100644 index 000000000..3c5f092fe --- /dev/null +++ b/src/main/java/com/ays/assignment/model/dto/response/AssignmentSearchResponse.java @@ -0,0 +1,32 @@ +package com.ays.assignment.model.dto.response; + +import com.ays.common.model.AysPhoneNumber; +import com.ays.common.model.dto.response.BaseResponse; +import com.ays.institution.model.dto.response.InstitutionResponse; +import com.ays.user.model.enums.UserRole; +import com.ays.user.model.enums.UserStatus; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.experimental.SuperBuilder; + +/** + * This class represents the response for a user with assignment. + * It includes information such as the user's username, first and last name, email, institution, role and status. + */ +@Data +@EqualsAndHashCode(callSuper = true) +@SuperBuilder +public class AssignmentSearchResponse extends BaseResponse { + + private String id; + private String username; + private String firstName; + private String lastName; + private String email; + private UserRole role; + private UserStatus status; + private AysPhoneNumber phoneNumber; + + private InstitutionResponse institution; + +} diff --git a/src/main/java/com/ays/assignment/model/entity/AssignmentEntity.java b/src/main/java/com/ays/assignment/model/entity/AssignmentEntity.java new file mode 100644 index 000000000..4be00a77f --- /dev/null +++ b/src/main/java/com/ays/assignment/model/entity/AssignmentEntity.java @@ -0,0 +1,99 @@ +package com.ays.assignment.model.entity; + +import com.ays.assignment.model.enums.AssignmentStatus; +import com.ays.common.model.entity.BaseEntity; +import com.ays.institution.model.entity.InstitutionEntity; +import com.ays.user.model.entity.UserEntity; +import jakarta.persistence.*; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; +import org.locationtech.jts.geom.Coordinate; +import org.locationtech.jts.geom.GeometryFactory; +import org.locationtech.jts.geom.Point; + +/** + * Assignment entity, which holds the information regarding assignment. + */ +@Entity +@Data +@EqualsAndHashCode(callSuper = true) +@SuperBuilder +@NoArgsConstructor +@AllArgsConstructor +@Table(name = "AYS_ASSIGNMENT") +public class AssignmentEntity extends BaseEntity { + + @Id + @Column(name = "ID") + private String id; + + @Column(name = "INSTITUTION_ID") + private String institutionId; + + @Column(name = "USER_ID") + private String userId; + + @Column(name = "DESCRIPTION") + private String description; + + @Column(name = "FIRST_NAME") + private String firstName; + + @Column(name = "LAST_NAME") + private String lastName; + + @Column(name = "COUNTRY_CODE") + private String countryCode; + + @Column(name = "LINE_NUMBER") + private String lineNumber; + + @Column(name = "POINT", columnDefinition = "ST_GeomFromText(Point, 4326)") + private Point point; + + @Enumerated(EnumType.STRING) + @Column(name = "ASSIGNMENT_STATUS") + private AssignmentStatus status; + + @OneToOne + @JoinColumn(name = "INSTITUTION_ID", referencedColumnName = "ID", insertable = false, updatable = false) + private InstitutionEntity institution; + + @OneToOne + @JoinColumn(name = "USER_ID", referencedColumnName = "ID", insertable = false, updatable = false) + private UserEntity user; + + public void setPoint(double latitude, double longitude) { + Coordinate coordinate = new Coordinate(latitude, longitude); + GeometryFactory geometryFactory = new GeometryFactory(); + this.point = geometryFactory.createPoint(coordinate); + } + + public boolean isAvailable() { + return AssignmentStatus.AVAILABLE.equals(this.status); + } + + public boolean isReserved() { + return AssignmentStatus.RESERVED.equals(this.status); + } + + public boolean isAssigned() { + return AssignmentStatus.ASSIGNED.equals(this.status); + } + + public boolean isInProgress() { + return AssignmentStatus.IN_PROGRESS.equals(this.status); + } + + public boolean isDone() { + return AssignmentStatus.DONE.equals(this.status); + } + + public void updateAssignmentStatus(AssignmentStatus assignmentStatus) { + this.status = assignmentStatus; + } + +} diff --git a/src/main/java/com/ays/assignment/model/enums/AssignmentStatus.java b/src/main/java/com/ays/assignment/model/enums/AssignmentStatus.java new file mode 100644 index 000000000..c525ce031 --- /dev/null +++ b/src/main/java/com/ays/assignment/model/enums/AssignmentStatus.java @@ -0,0 +1,14 @@ +package com.ays.assignment.model.enums; + +/** + * Enumeration keeping assignment status. + */ +public enum AssignmentStatus { + + AVAILABLE, + RESERVED, + ASSIGNED, + IN_PROGRESS, + DONE + +} diff --git a/src/main/java/com/ays/assignment/model/mapper/AssignmentEntityToAssignmentMapper.java b/src/main/java/com/ays/assignment/model/mapper/AssignmentEntityToAssignmentMapper.java new file mode 100644 index 000000000..45113a863 --- /dev/null +++ b/src/main/java/com/ays/assignment/model/mapper/AssignmentEntityToAssignmentMapper.java @@ -0,0 +1,63 @@ +package com.ays.assignment.model.mapper; + +import com.ays.assignment.model.Assignment; +import com.ays.assignment.model.entity.AssignmentEntity; +import com.ays.common.model.mapper.BaseMapper; +import org.locationtech.jts.geom.Point; +import org.mapstruct.Mapper; +import org.mapstruct.Mapping; +import org.mapstruct.factory.Mappers; + +import java.util.Optional; + +/** + * AssignmentEntityToAssignmentMapper is an interface that defines the mapping between an {@link AssignmentEntity} and an {@link Assignment}. + * This interface uses the MapStruct annotation @Mapper to generate an implementation of this interface at compile-time. + *

The class provides a static method {@code initialize()} that returns an instance of the generated mapper implementation. + *

The interface extends the MapStruct interface {@link BaseMapper}, which defines basic mapping methods. + * The interface adds no additional mapping methods, but simply defines the types to be used in the mapping process. + */ +@Mapper +public interface AssignmentEntityToAssignmentMapper extends BaseMapper { + + @Override + @Mapping(target = "phoneNumber.countryCode", source = "source.countryCode") + @Mapping(target = "phoneNumber.lineNumber", source = "source.lineNumber") + @Mapping(target = "latitude", expression = "java(mapToLatitude(source.getPoint()))") + @Mapping(target = "longitude", expression = "java(mapToLongitude(source.getPoint()))") + Assignment map(AssignmentEntity source); + + /** + * Initializes the mapper. + * + * @return the initialized mapper object. + */ + static AssignmentEntityToAssignmentMapper initialize() { + return Mappers.getMapper(AssignmentEntityToAssignmentMapper.class); + } + + /** + * Maps a Point object to latitude. + * + * @param point The Point object. + * @return The latitude coordinate. + */ + default Double mapToLatitude(Point point) { + return Optional.ofNullable(point) + .map(Point::getY) + .orElse(null); + } + + /** + * Maps a Point object to longitude. + * + * @param point The Point object. + * @return The longitude coordinate. + */ + default Double mapToLongitude(Point point) { + return Optional.ofNullable(point) + .map(Point::getX) + .orElse(null); + } + +} diff --git a/src/main/java/com/ays/assignment/model/mapper/AssignmentToAssignmentEntityMapper.java b/src/main/java/com/ays/assignment/model/mapper/AssignmentToAssignmentEntityMapper.java new file mode 100644 index 000000000..b2efb9547 --- /dev/null +++ b/src/main/java/com/ays/assignment/model/mapper/AssignmentToAssignmentEntityMapper.java @@ -0,0 +1,57 @@ +package com.ays.assignment.model.mapper; + +import com.ays.assignment.model.Assignment; +import com.ays.assignment.model.entity.AssignmentEntity; +import com.ays.common.model.mapper.BaseMapper; +import org.locationtech.jts.geom.Coordinate; +import org.locationtech.jts.geom.GeometryFactory; +import org.locationtech.jts.geom.Point; +import org.mapstruct.Mapper; +import org.mapstruct.Mapping; +import org.mapstruct.factory.Mappers; + +/** + * AssignmentToAssignmentEntityMapper is an interface that defines the mapping between an {@link Assignment} and an {@link AssignmentEntity}. + * This interface uses the MapStruct annotation @Mapper to generate an implementation of this interface at compile-time. + *

The class provides a static method {@code initialize()} that returns an instance of the generated mapper implementation. + *

The interface extends the MapStruct interface {@link BaseMapper}, which defines basic mapping methods. + * The interface adds no additional mapping methods, but simply defines the types to be used in the mapping process. + */ +@Mapper +public interface AssignmentToAssignmentEntityMapper extends BaseMapper { + + /** + * Maps UserAssignment to UserAssignmentEntity. + * + * @param assignment the UserAssignment object + * @return the mapped UserAssignmentEntity object + */ + @Mapping(target = "point", expression = "java(mapToPoint(assignment.getLatitude(), assignment.getLongitude()))") + AssignmentEntity map(Assignment assignment); + + + /** + * Initializes the mapper. + * + * @return the initialized mapper object. + */ + static AssignmentToAssignmentEntityMapper initialize() { + return Mappers.getMapper(AssignmentToAssignmentEntityMapper.class); + } + + /** + * Maps latitude and longitude to the point field. + * + * @param latitude the latitude value + * @param longitude the longitude value + * @return the mapped Point object + */ + default Point mapToPoint(Double latitude, Double longitude) { + if (latitude != null && longitude != null) { + Coordinate coordinate = new Coordinate(latitude, longitude); + GeometryFactory geometryFactory = new GeometryFactory(); + return geometryFactory.createPoint(coordinate); + } + return null; + } +} diff --git a/src/main/java/com/ays/assignment/model/mapper/AssignmentToAssignmentResponseMapper.java b/src/main/java/com/ays/assignment/model/mapper/AssignmentToAssignmentResponseMapper.java new file mode 100644 index 000000000..2739a28f7 --- /dev/null +++ b/src/main/java/com/ays/assignment/model/mapper/AssignmentToAssignmentResponseMapper.java @@ -0,0 +1,28 @@ +package com.ays.assignment.model.mapper; + +import com.ays.assignment.model.Assignment; +import com.ays.assignment.model.dto.response.AssignmentResponse; +import com.ays.common.model.mapper.BaseMapper; +import org.mapstruct.Mapper; +import org.mapstruct.factory.Mappers; + +/** + * AssignmentToAssignmentResponseMapper is an interface that defines the mapping between an {@link Assignment} and an {@link AssignmentResponse}. + * This interface uses the MapStruct annotation @Mapper to generate an implementation of this interface at compile-time. + *

The class provides a static method {@code initialize()} that returns an instance of the generated mapper implementation. + *

The interface extends the MapStruct interface {@link BaseMapper}, which defines basic mapping methods. + * The interface adds no additional mapping methods, but simply defines the types to be used in the mapping process. + */ +@Mapper +public interface AssignmentToAssignmentResponseMapper extends BaseMapper { + + /** + * Initializes the mapper. + * + * @return the initialized mapper object. + */ + static AssignmentToAssignmentResponseMapper initialize() { + return Mappers.getMapper(AssignmentToAssignmentResponseMapper.class); + } + +} diff --git a/src/main/java/com/ays/assignment/repository/AssignmentEntityRepository.java b/src/main/java/com/ays/assignment/repository/AssignmentEntityRepository.java new file mode 100644 index 000000000..9a9b45207 --- /dev/null +++ b/src/main/java/com/ays/assignment/repository/AssignmentEntityRepository.java @@ -0,0 +1,11 @@ +package com.ays.assignment.repository; + +import com.ays.assignment.model.entity.AssignmentEntity; +import org.springframework.data.jpa.repository.JpaRepository; + +/** + * Repository interface for performing CRUD operations on UserAssignmentEntity objects. + */ +public interface AssignmentEntityRepository extends JpaRepository { + +} diff --git a/src/main/java/com/ays/assignment/util/exception/AysAssignmentAlreadyAssignedException.java b/src/main/java/com/ays/assignment/util/exception/AysAssignmentAlreadyAssignedException.java new file mode 100644 index 000000000..908eef7e5 --- /dev/null +++ b/src/main/java/com/ays/assignment/util/exception/AysAssignmentAlreadyAssignedException.java @@ -0,0 +1,27 @@ +package com.ays.assignment.util.exception; + +import com.ays.common.util.exception.AysAlreadyException; + +import java.io.Serial; + +/** + * Exception thrown when a user assignment is assigned and attempting to perform an action that requires an assigned assignment. + */ +public class AysAssignmentAlreadyAssignedException extends AysAlreadyException { + + /** + * Unique identifier for serialization. + */ + @Serial + private static final long serialVersionUID = -4641308511630291631L; + + /** + * Constructs a new {@code AysAssignmentAlreadyAssignedException} with the specified id. + * + * @param id the id of the assignment which is already assigned + */ + public AysAssignmentAlreadyAssignedException(String id) { + super("ASSIGNMENT IS ALREADY ASSIGNED! id:" + id); + } + +} diff --git a/src/main/java/com/ays/assignment/util/exception/AysAssignmentAlreadyAvailableException.java b/src/main/java/com/ays/assignment/util/exception/AysAssignmentAlreadyAvailableException.java new file mode 100644 index 000000000..ab47bd6de --- /dev/null +++ b/src/main/java/com/ays/assignment/util/exception/AysAssignmentAlreadyAvailableException.java @@ -0,0 +1,27 @@ +package com.ays.assignment.util.exception; + +import com.ays.common.util.exception.AysAlreadyException; + +import java.io.Serial; + +/** + * Exception thrown when a user assignment is available and attempting to perform an action that requires an assignment which is already available. + */ +public class AysAssignmentAlreadyAvailableException extends AysAlreadyException { + + /** + * Unique identifier for serialization. + */ + @Serial + private static final long serialVersionUID = 7742901037914306311L; + + /** + * Constructs a new {@code AysAssignmentAlreadyAvailableException} with the specified id. + * + * @param id the id of the assignment which is already available + */ + public AysAssignmentAlreadyAvailableException(String id) { + super("ASSIGNMENT IS ALREADY AVAILABLE! id:" + id); + } + +} diff --git a/src/main/java/com/ays/assignment/util/exception/AysAssignmentAlreadyDoneException.java b/src/main/java/com/ays/assignment/util/exception/AysAssignmentAlreadyDoneException.java new file mode 100644 index 000000000..05549b182 --- /dev/null +++ b/src/main/java/com/ays/assignment/util/exception/AysAssignmentAlreadyDoneException.java @@ -0,0 +1,27 @@ +package com.ays.assignment.util.exception; + +import com.ays.common.util.exception.AysAlreadyException; + +import java.io.Serial; + +/** + * Exception thrown when a user assignment is done and attempting to perform an action that requires an assignment which is already done. + */ +public class AysAssignmentAlreadyDoneException extends AysAlreadyException { + + /** + * Unique identifier for serialization. + */ + @Serial + private static final long serialVersionUID = 4457246038851186682L; + + /** + * Constructs a new {@code AysAssignmentAlreadyDoneException} with the specified id. + * + * @param id the id of the assignment which is already done + */ + public AysAssignmentAlreadyDoneException(String id) { + super("ASSIGNMENT IS ALREADY DONE! id:" + id); + } + +} diff --git a/src/main/java/com/ays/assignment/util/exception/AysAssignmentAlreadyInProgressException.java b/src/main/java/com/ays/assignment/util/exception/AysAssignmentAlreadyInProgressException.java new file mode 100644 index 000000000..c1baaa6c0 --- /dev/null +++ b/src/main/java/com/ays/assignment/util/exception/AysAssignmentAlreadyInProgressException.java @@ -0,0 +1,28 @@ +package com.ays.assignment.util.exception; + +import com.ays.common.util.exception.AysAlreadyException; + +import java.io.Serial; + +/** + * Exception thrown when a user assignment is in progress and attempting to perform an action that requires an assignment which is already in progress. + */ +public class AysAssignmentAlreadyInProgressException extends AysAlreadyException { + + /** + * Unique identifier for serialization. + */ + @Serial + private static final long serialVersionUID = -3095992510410240081L; + + /** + * Constructs a new {@code AysAssignmentAlreadyInProgressException} with the specified id. + * + * @param id the id of the assignment which is already in progress + */ + public AysAssignmentAlreadyInProgressException(String id) { + super("ASSIGNMENT IS ALREADY IN PROGRESS! id:" + id); + } + +} + diff --git a/src/main/java/com/ays/assignment/util/exception/AysAssignmentAlreadyReservedException.java b/src/main/java/com/ays/assignment/util/exception/AysAssignmentAlreadyReservedException.java new file mode 100644 index 000000000..d997ced54 --- /dev/null +++ b/src/main/java/com/ays/assignment/util/exception/AysAssignmentAlreadyReservedException.java @@ -0,0 +1,26 @@ +package com.ays.assignment.util.exception; + +import com.ays.common.util.exception.AysAlreadyException; + +import java.io.Serial; + +/** + * Exception thrown when a user assignment is reserved and attempting to perform an action that requires an assignment which is already reserved. + */ +public class AysAssignmentAlreadyReservedException extends AysAlreadyException { + + /** + * Unique identifier for serialization. + */ + @Serial + private static final long serialVersionUID = 5516025383665844979L; + + /** + * Constructs a new {@code AysAssignmentAlreadyReservedException} with the specified id. + * + * @param id the id of the assignment which is already reserved + */ + public AysAssignmentAlreadyReservedException(String id) { + super("ASSIGNMENT IS ALREADY RESERVED! id:" + id); + } +} diff --git a/src/main/java/com/ays/assignment/util/exception/AysAssignmentNotExistByIdException.java b/src/main/java/com/ays/assignment/util/exception/AysAssignmentNotExistByIdException.java new file mode 100644 index 000000000..8366f9e25 --- /dev/null +++ b/src/main/java/com/ays/assignment/util/exception/AysAssignmentNotExistByIdException.java @@ -0,0 +1,27 @@ +package com.ays.assignment.util.exception; + +import com.ays.common.util.exception.AysNotExistException; + +import java.io.Serial; + +/** + * Exception to be thrown when a user assignment with a given ID does not exist. + */ +public class AysAssignmentNotExistByIdException extends AysNotExistException { + + /** + * Unique serial version ID. + */ + @Serial + private static final long serialVersionUID = -1656529656159558925L; + + /** + * Constructs a new AysAssignmentNotExistByIdException with the specified assignment ID. + * + * @param id the ID of the assignment that does not exist + */ + public AysAssignmentNotExistByIdException(String id) { + super("ASSIGNMENT NOT EXIST! id:" + id); + } + +} diff --git a/src/main/java/com/ays/location/model/UserLocation.java b/src/main/java/com/ays/location/model/UserLocation.java new file mode 100644 index 000000000..960042711 --- /dev/null +++ b/src/main/java/com/ays/location/model/UserLocation.java @@ -0,0 +1,19 @@ +package com.ays.location.model; + +import com.ays.common.model.BaseDomainModel; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.experimental.SuperBuilder; +import org.locationtech.jts.geom.Point; + +/** + * Location Domain Model to perform data transfer from service layer to controller + */ +@Data +@EqualsAndHashCode(callSuper = true) +@SuperBuilder +public class UserLocation extends BaseDomainModel { + + private Long id; + private Point point; +} diff --git a/src/main/java/com/ays/location/model/dto/request/UserLocationRequest.java b/src/main/java/com/ays/location/model/dto/request/UserLocationRequest.java new file mode 100644 index 000000000..499bca3f0 --- /dev/null +++ b/src/main/java/com/ays/location/model/dto/request/UserLocationRequest.java @@ -0,0 +1,22 @@ +package com.ays.location.model.dto.request; + +import lombok.Builder; +import lombok.Data; + +/** + * A DTO class representing the request data for updating user location. + *

+ * This class provides getters and setters for the latitude, and longitude fields. + * It also includes a builder pattern implementation for constructing instances of this class with optional parameters. + *

+ * The purpose of this class is to encapsulate the request data related to updating user location, allowing for easy + * transfer of the data between different layers of the application. + */ +@Data +@Builder +public class UserLocationRequest { + + private Double latitude; + private Double longitude; + +} diff --git a/src/main/java/com/ays/location/model/entity/UserLocationEntity.java b/src/main/java/com/ays/location/model/entity/UserLocationEntity.java new file mode 100644 index 000000000..30fb893ea --- /dev/null +++ b/src/main/java/com/ays/location/model/entity/UserLocationEntity.java @@ -0,0 +1,48 @@ +package com.ays.location.model.entity; + +import com.ays.common.model.entity.BaseEntity; +import com.ays.user.model.entity.UserEntity; +import jakarta.persistence.*; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; +import org.locationtech.jts.geom.Coordinate; +import org.locationtech.jts.geom.GeometryFactory; +import org.locationtech.jts.geom.Point; + +/** + * User Location entity, which holds the information regarding location. + */ +@Entity +@Data +@EqualsAndHashCode(callSuper = true) +@SuperBuilder +@NoArgsConstructor +@AllArgsConstructor +@Table(name = "AYS_USER_LOCATION") +public class UserLocationEntity extends BaseEntity { + + @Id + @Column(name = "ID") + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @Column(name = "USER_ID") + private String userId; + + @Column(name = "POINT", columnDefinition = "ST_GeomFromText(Point, 4326)") + private Point point; + + @OneToOne + @JoinColumn(name = "USER_ID", referencedColumnName = "ID", insertable = false, updatable = false) + private UserEntity user; + + public void setPoint(double latitude, double longitude) { + Coordinate coordinate = new Coordinate(latitude, longitude); + GeometryFactory geometryFactory = new GeometryFactory(); + this.point = geometryFactory.createPoint(coordinate); + } + +} diff --git a/src/main/java/com/ays/location/model/mapper/UserLocationEntityToUserLocationMapper.java b/src/main/java/com/ays/location/model/mapper/UserLocationEntityToUserLocationMapper.java new file mode 100644 index 000000000..81f1ccb37 --- /dev/null +++ b/src/main/java/com/ays/location/model/mapper/UserLocationEntityToUserLocationMapper.java @@ -0,0 +1,28 @@ +package com.ays.location.model.mapper; + +import com.ays.common.model.mapper.BaseMapper; +import com.ays.location.model.UserLocation; +import com.ays.location.model.entity.UserLocationEntity; +import org.mapstruct.Mapper; +import org.mapstruct.factory.Mappers; + +/** + * UserLocationEntityToUserLocationMapper is an interface that defines the mapping between an {@link UserLocationEntity} and an {@link UserLocation}. + * This interface uses the MapStruct annotation @Mapper to generate an implementation of this interface at compile-time. + *

The class provides a static method {@code initialize()} that returns an instance of the generated mapper implementation. + *

The interface extends the MapStruct interface {@link BaseMapper}, which defines basic mapping methods. + * The interface adds no additional mapping methods, but simply defines the types to be used in the mapping process. + */ +@Mapper +public interface UserLocationEntityToUserLocationMapper extends BaseMapper { + + /** + * Initializes the mapper. + * + * @return the initialized mapper object. + */ + static UserLocationEntityToUserLocationMapper initialize() { + return Mappers.getMapper(UserLocationEntityToUserLocationMapper.class); + } + +} diff --git a/src/main/java/com/ays/location/model/mapper/UserLocationToUserLocationEntityMapper.java b/src/main/java/com/ays/location/model/mapper/UserLocationToUserLocationEntityMapper.java new file mode 100644 index 000000000..e7159ef4c --- /dev/null +++ b/src/main/java/com/ays/location/model/mapper/UserLocationToUserLocationEntityMapper.java @@ -0,0 +1,28 @@ +package com.ays.location.model.mapper; + +import com.ays.common.model.mapper.BaseMapper; +import com.ays.location.model.UserLocation; +import com.ays.location.model.entity.UserLocationEntity; +import org.mapstruct.Mapper; +import org.mapstruct.factory.Mappers; + +/** + * UserLocationToUserLocationEntityMapper is an interface that defines the mapping between an {@link UserLocation} and an {@link UserLocationEntity}. + * This interface uses the MapStruct annotation @Mapper to generate an implementation of this interface at compile-time. + *

The class provides a static method {@code initialize()} that returns an instance of the generated mapper implementation. + *

The interface extends the MapStruct interface {@link BaseMapper}, which defines basic mapping methods. + * The interface adds no additional mapping methods, but simply defines the types to be used in the mapping process. + */ +@Mapper +public interface UserLocationToUserLocationEntityMapper extends BaseMapper { + + /** + * Initializes the mapper. + * + * @return the initialized mapper object. + */ + static UserLocationToUserLocationEntityMapper initialize() { + return Mappers.getMapper(UserLocationToUserLocationEntityMapper.class); + } + +} diff --git a/src/main/java/com/ays/location/repository/UserLocationRepository.java b/src/main/java/com/ays/location/repository/UserLocationRepository.java new file mode 100644 index 000000000..7e35939f8 --- /dev/null +++ b/src/main/java/com/ays/location/repository/UserLocationRepository.java @@ -0,0 +1,11 @@ +package com.ays.location.repository; + +import com.ays.location.model.entity.UserLocationEntity; +import org.springframework.data.jpa.repository.JpaRepository; + +/** + * Repository interface for performing CRUD operations on UserLocationEntity objects. + */ +public interface UserLocationRepository extends JpaRepository { + +} diff --git a/src/main/java/com/ays/location/util/exception/AysUserLocationNotExistByIdException.java b/src/main/java/com/ays/location/util/exception/AysUserLocationNotExistByIdException.java new file mode 100644 index 000000000..64c55396e --- /dev/null +++ b/src/main/java/com/ays/location/util/exception/AysUserLocationNotExistByIdException.java @@ -0,0 +1,27 @@ +package com.ays.location.util.exception; + +import com.ays.common.util.exception.AysNotExistException; + +import java.io.Serial; + +/** + * Exception to be thrown when a user location with a given ID does not exist. + */ +public class AysUserLocationNotExistByIdException extends AysNotExistException { + + /** + * Unique serial version ID. + */ + @Serial + private static final long serialVersionUID = 2448425046125508633L; + + /** + * Constructs a new AysLocationNotExistByIdException with the specified assignment ID. + * + * @param id the ID of the location that does not exist + */ + public AysUserLocationNotExistByIdException(String id) { + super("USER LOCATION NOT EXIST! id:" + id); + } + +}