Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

#105 | Create Assignment And Location Domain #112

Merged
merged 38 commits into from
Jul 27, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
0d7469b
Add AssignmentEntity and LocationEntity
Rapter1990 Jul 3, 2023
2a93a68
Add AssignmentStatus
Rapter1990 Jul 3, 2023
656ef4e
Add Hibernate Spatial dependency in pom.xml
Rapter1990 Jul 3, 2023
4831e55
Add Assignment and Location Domain
Rapter1990 Jul 3, 2023
d65458f
Add AssignmentResponse
Rapter1990 Jul 3, 2023
f9be0b2
Add UserAssignmentRequest and UserLocationRequest
Rapter1990 Jul 3, 2023
dcde53c
Add AssignmentRepository and LocationRepository
Rapter1990 Jul 3, 2023
93004af
Add Mapper process for Assignment
Rapter1990 Jul 3, 2023
c3f4284
Add Mapper process for Location
Rapter1990 Jul 3, 2023
eeb477e
Add Exception Handling for Assignment
Rapter1990 Jul 3, 2023
b7f412d
Add Exception Handling for Location
Rapter1990 Jul 3, 2023
6cf9040
Rename files as AssignmentListRequest and LocationUserRequest
Rapter1990 Jul 16, 2023
eb0806c
Create AssignmentLocationRequest
Rapter1990 Jul 16, 2023
6ee17ac
Revise UserAssignmentEntity
Rapter1990 Jul 16, 2023
4efdf31
Revise UserAssignment
Rapter1990 Jul 16, 2023
99153de
Revise UserAssignmentListRequest, UserAssignmentResponse and UserAssi…
Rapter1990 Jul 16, 2023
85639bb
Revise UserAssignmentEntityToAssignmentMapper, UserAssignmentToUserAs…
Rapter1990 Jul 16, 2023
12ab3ca
Revise UserLocationEntity
Rapter1990 Jul 16, 2023
3ce1bbc
Revise UserLocationRequest
Rapter1990 Jul 16, 2023
9295a0c
Revise AysUserLocationNotExistByIdException
Rapter1990 Jul 16, 2023
94571ef
Revise LocationEntityToLocationMapper and LocationToLocationEntityMapper
Rapter1990 Jul 16, 2023
d02cafd
Revise UserLocation
Rapter1990 Jul 16, 2023
ea00b74
Revise UserAssignmentRepository and UserLocationRepository
Rapter1990 Jul 16, 2023
4c34c1d
Revise UserLocationEntityToUserLocationMapper and UserLocationToUserL…
Rapter1990 Jul 16, 2023
4581f1f
Revise Java Docs for Assignment domain
Rapter1990 Jul 16, 2023
1201226
Revise Java Docs for Location domain
Rapter1990 Jul 16, 2023
92e47ac
Create AssignmentSearchResponse
Rapter1990 Jul 23, 2023
46d8f89
Revise Assignment and AssignmentEntity
Rapter1990 Jul 23, 2023
1f74ace
Revise AssignmentListRequest, AssignmentSearchRequest and AssignmentR…
Rapter1990 Jul 23, 2023
5fdfd37
Revise AssignmentEntityRepository
Rapter1990 Jul 23, 2023
206eda2
Revise AssignmentEntityToAssignmentMapper, AssignmentToAssignmentEnti…
Rapter1990 Jul 23, 2023
2aefc95
Revise AysAssignmentAlreadyAssignedException, AysAssignmentAlreadyAva…
Rapter1990 Jul 23, 2023
0366d16
Revise AssignmentToAssignmentEntityMapper and AssignmentEntityToAssig…
Rapter1990 Jul 23, 2023
e0d67d4
Revise Assignment and AssignmentEntity
Rapter1990 Jul 23, 2023
cbe6e49
Revise AssignmentToAssignmentEntityMapper
Rapter1990 Jul 23, 2023
d1d99bd
Revise UserLocationEntity
Rapter1990 Jul 23, 2023
fa213b5
Revise AssignmentEntity
Rapter1990 Jul 23, 2023
b1ba1da
Revise AssignmentResponse
Rapter1990 Jul 26, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,11 @@
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
</dependency>

<dependency>
<groupId>org.hibernate.orm</groupId>
<artifactId>hibernate-spatial</artifactId>
</dependency>
<!-- ===================== -->
<!-- database dependencies -->
<!-- ===================== -->
Expand Down
32 changes: 32 additions & 0 deletions src/main/java/com/ays/assignment/model/Assignment.java
Original file line number Diff line number Diff line change
@@ -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;

}
Original file line number Diff line number Diff line change
@@ -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<AssignmentStatus> 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<String> 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 <C> Specification<C> toSpecification(Class<C> clazz) {
Specification<C> 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;
}

}
Original file line number Diff line number Diff line change
@@ -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.
* <p>
* 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.
* <p>
* 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;
}
Original file line number Diff line number Diff line change
@@ -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;

}
Original file line number Diff line number Diff line change
@@ -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;

}
Original file line number Diff line number Diff line change
@@ -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;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package com.ays.assignment.model.enums;

/**
* Enumeration keeping assignment status.
*/
public enum AssignmentStatus {

AVAILABLE,
RESERVED,
ASSIGNED,
IN_PROGRESS,
DONE

}
Original file line number Diff line number Diff line change
@@ -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.
* <p>The class provides a static method {@code initialize()} that returns an instance of the generated mapper implementation.
* <p>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<AssignmentEntity, Assignment> {

@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);
}

}
Loading