diff --git a/backend/src/main/java/at/ac/tuwien/sepm/assignment/individual/endpoint/dto/HorseDto.java b/backend/src/main/java/at/ac/tuwien/sepm/assignment/individual/endpoint/dto/HorseDto.java index f5be27f..892feb3 100644 --- a/backend/src/main/java/at/ac/tuwien/sepm/assignment/individual/endpoint/dto/HorseDto.java +++ b/backend/src/main/java/at/ac/tuwien/sepm/assignment/individual/endpoint/dto/HorseDto.java @@ -1,5 +1,7 @@ package at.ac.tuwien.sepm.assignment.individual.endpoint.dto; +import at.ac.tuwien.sepm.assignment.individual.enums.ERace; + import java.time.LocalDateTime; import java.util.Objects; import java.sql.Date; @@ -10,25 +12,28 @@ public class HorseDto extends BaseDto { private String name; private String description; private short score; + private ERace race; private Date birthday; private Long owner; public HorseDto() {} - public HorseDto(String name, String description, short score, Date birthday, Long owner) { + public HorseDto(String name, String description, short score, Date birthday, ERace race, Long owner) { this.name = name; this.description = description; this.score = score; this.birthday = birthday; + this.race = race; this.owner = owner; } - public HorseDto(Long id, String name, String description, short score, Date birthday, LocalDateTime created, LocalDateTime updated, Long owner) { + public HorseDto(Long id, String name, String description, short score, Date birthday, ERace race, LocalDateTime created, LocalDateTime updated, Long owner) { super(id, created, updated); this.name = name; this.description = description; this.score = score; this.birthday = birthday; + this.race = race; this.owner = owner; } @@ -64,6 +69,14 @@ public class HorseDto extends BaseDto { this.birthday = birthday; } + public ERace getRace() { + return race; + } + + public void setRace(ERace race) { + this.race = race; + } + public Long getOwner() { return owner; } @@ -77,8 +90,13 @@ public class HorseDto extends BaseDto { if (this == o) return true; if (!(o instanceof HorseDto)) return false; if (!super.equals(o)) return false; - HorseDto horseDto = (HorseDto) o; - return Objects.equals(name, horseDto.name); + HorseDto h = (HorseDto) o; + return Objects.equals(name, h.name) && + Objects.equals(description, h.description) && + Objects.equals(score, h.score) && + Objects.equals(birthday, h.birthday) && + Objects.equals(race, h.race) && + Objects.equals(owner, h.owner); } @Override @@ -94,6 +112,7 @@ public class HorseDto extends BaseDto { ", description='" + description + '\'' + ", score='" + score + '\'' + ", birthday='" + df.format(birthday) + '\'' + + ", race='" + race + '\'' + ", owner_id='" + owner + '\''; } diff --git a/backend/src/main/java/at/ac/tuwien/sepm/assignment/individual/endpoint/mapper/HorseMapper.java b/backend/src/main/java/at/ac/tuwien/sepm/assignment/individual/endpoint/mapper/HorseMapper.java index 6a2d0eb..f4470ac 100644 --- a/backend/src/main/java/at/ac/tuwien/sepm/assignment/individual/endpoint/mapper/HorseMapper.java +++ b/backend/src/main/java/at/ac/tuwien/sepm/assignment/individual/endpoint/mapper/HorseMapper.java @@ -8,10 +8,10 @@ import org.springframework.stereotype.Component; @Component public class HorseMapper { public HorseDto entityToDto(Horse horse) { - return new HorseDto(horse.getId(), horse.getName(), horse.getDescription(), horse.getScore(), horse.getBirthday(), horse.getCreatedAt(), horse.getUpdatedAt(), horse.getOwner()); + return new HorseDto(horse.getId(), horse.getName(), horse.getDescription(), horse.getScore(), horse.getBirthday(), horse.getRace(), horse.getCreatedAt(), horse.getUpdatedAt(), horse.getOwner()); } public Horse dtoToEntity(HorseDto horse) { - return new Horse(horse.getId(), horse.getName(), horse.getDescription(), horse.getScore(), horse.getBirthday(), horse.getOwner()); + return new Horse(horse.getId(), horse.getName(), horse.getDescription(), horse.getScore(), horse.getBirthday(), horse.getRace(), horse.getOwner()); } } diff --git a/backend/src/main/java/at/ac/tuwien/sepm/assignment/individual/entity/Horse.java b/backend/src/main/java/at/ac/tuwien/sepm/assignment/individual/entity/Horse.java index ab0f85a..25868d3 100644 --- a/backend/src/main/java/at/ac/tuwien/sepm/assignment/individual/entity/Horse.java +++ b/backend/src/main/java/at/ac/tuwien/sepm/assignment/individual/entity/Horse.java @@ -5,39 +5,44 @@ import java.text.SimpleDateFormat; import java.time.LocalDateTime; import java.sql.Date; import java.util.Objects; +import at.ac.tuwien.sepm.assignment.individual.enums.ERace; public class Horse extends BaseEntity { private String name; private String description; private short score; + private ERace race; private Date birthday; private Long owner; public Horse() {} - public Horse(String name, String description, short score, Date birthday, Long owner) { + public Horse(String name, String description, short score, Date birthday, ERace race,Long owner) { this.name = name; this.description = description; this.score = score; this.birthday = birthday; + this.race = race; this.owner = owner; } - public Horse(Long id, String name, String description, short score, Date birthday, Long owner) { + public Horse(Long id, String name, String description, short score, Date birthday, ERace race, Long owner) { super(id); this.name = name; this.description = description; this.score = score; this.birthday = birthday; + this.race = race; this.owner = owner; } - public Horse(Long id, String name, String description, short score, Date birthday, Long owner, LocalDateTime created, LocalDateTime updated) { + public Horse(Long id, String name, String description, short score, Date birthday, ERace race, Long owner, LocalDateTime created, LocalDateTime updated) { super(id, created, updated); this.name = name; this.description = description; this.score = score; this.birthday = birthday; + this.race = race; this.owner = owner; } @@ -73,6 +78,14 @@ public class Horse extends BaseEntity { this.birthday = birthday; } + public ERace getRace() { + return race; + } + + public void setRace(ERace race) { + this.race = race; + } + public Long getOwner() { return owner; } @@ -86,8 +99,13 @@ public class Horse extends BaseEntity { if (this == o) return true; if (!(o instanceof Horse)) return false; if (!super.equals(o)) return false; - Horse Horse = (Horse) o; - return Objects.equals(name, Horse.name); + Horse h = (Horse) o; + return Objects.equals(name, h.name) && + Objects.equals(description, h.description) && + Objects.equals(score, h.score) && + Objects.equals(birthday, h.birthday) && + Objects.equals(race, h.race) && + Objects.equals(owner, h.owner); } @Override @@ -103,6 +121,7 @@ public class Horse extends BaseEntity { "description='" + description + '\'' + ", score='" + score + '\'' + ", birthday='" + df.format(birthday) + '\'' + + ", race='" + race + '\'' + ", owner='" + owner + '\''; } diff --git a/backend/src/main/java/at/ac/tuwien/sepm/assignment/individual/persistence/impl/HorseJdbcDao.java b/backend/src/main/java/at/ac/tuwien/sepm/assignment/individual/persistence/impl/HorseJdbcDao.java index a713182..6df00f3 100644 --- a/backend/src/main/java/at/ac/tuwien/sepm/assignment/individual/persistence/impl/HorseJdbcDao.java +++ b/backend/src/main/java/at/ac/tuwien/sepm/assignment/individual/persistence/impl/HorseJdbcDao.java @@ -1,11 +1,13 @@ package at.ac.tuwien.sepm.assignment.individual.persistence.impl; import at.ac.tuwien.sepm.assignment.individual.entity.Horse; +import at.ac.tuwien.sepm.assignment.individual.enums.ERace; import at.ac.tuwien.sepm.assignment.individual.exception.NotFoundException; import at.ac.tuwien.sepm.assignment.individual.persistence.HorseDao; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.dao.DataAccessException; +import org.springframework.dao.DataIntegrityViolationException; import org.springframework.dao.DataRetrievalFailureException; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate; @@ -48,9 +50,13 @@ public class HorseJdbcDao implements HorseDao { @Override public Horse addHorse(Horse horse) throws DataAccessException { LOGGER.trace("Add horse {}", horse.toString()); - String sql = "INSERT INTO " + TABLE_NAME + "(name, description, score, birthday, owner_id, created_at, updated_at) VALUES(?, ?, ?, ?, ?, ?, ?)"; + String sql = "INSERT INTO " + TABLE_NAME + "(name, description, score, birthday, race, owner_id, created_at, updated_at) VALUES(?, ?, ?, ?, ?, ?, ?, ?)"; try { + // Check if the constraints are violated + if(horse.getName() == null || horse.getScore() == 0 || horse.getBirthday() == null || horse.getRace() == null) + throw new DataIntegrityViolationException("Required parameters for horse missing"); + LocalDateTime currentTime = LocalDateTime.now(); horse.setCreatedAt(currentTime); @@ -61,18 +67,20 @@ public class HorseJdbcDao implements HorseDao { int changes = jdbcTemplate.update(connection -> { PreparedStatement ps = connection.prepareStatement(sql, PreparedStatement.RETURN_GENERATED_KEYS); + ps.setString(1, horse.getName()); ps.setString(2, horse.getDescription()); ps.setInt(3, horse.getScore()); ps.setDate(4, horse.getBirthday()); + ps.setString(5, horse.getRace().toString()); // Convert to string to be able to save in DB if(horse.getOwner() == null || horse.getOwner() == 0) - ps.setNull(5, Types.NULL); + ps.setNull(6, Types.NULL); else - ps.setObject(5, horse.getOwner()); + ps.setObject(6, horse.getOwner()); - ps.setObject(6, horse.getCreatedAt()); - ps.setObject(7, horse.getUpdatedAt()); + ps.setObject(7, horse.getCreatedAt()); + ps.setObject(8, horse.getUpdatedAt()); return ps; }, keyHolder); @@ -97,7 +105,10 @@ public class HorseJdbcDao implements HorseDao { horse.setDescription(resultSet.getString("description")); horse.setScore(resultSet.getShort("score")); horse.setBirthday(resultSet.getDate("birthday")); + horse.setRace(ERace.valueOf(resultSet.getString("race"))); // Convert to Enum for usage in objects horse.setOwner(resultSet.getLong("owner_id")); + horse.setCreatedAt(resultSet.getTimestamp("created_at").toLocalDateTime()); + horse.setUpdatedAt(resultSet.getTimestamp("updated_at").toLocalDateTime()); return horse; } } diff --git a/backend/src/main/java/at/ac/tuwien/sepm/assignment/individual/util/Validator.java b/backend/src/main/java/at/ac/tuwien/sepm/assignment/individual/util/Validator.java index ebf8d97..523c960 100644 --- a/backend/src/main/java/at/ac/tuwien/sepm/assignment/individual/util/Validator.java +++ b/backend/src/main/java/at/ac/tuwien/sepm/assignment/individual/util/Validator.java @@ -16,8 +16,8 @@ public class Validator { } public void validateNewHorse(Horse horse) throws ValidationException { - if(horse.getName() == null || horse.getScore() == 0 || horse.getBirthday() == null || horse.getDescription() == null){ - throw new ValidationException("All or some required values missing: name, description, score, birthday"); + if(horse.getName() == null || horse.getScore() == 0 || horse.getBirthday() == null || horse.getRace() == null){ + throw new ValidationException("All or some required values missing: name, score, birthday, race"); } if(horse.getScore() > 5 || horse.getScore() < 1) { throw new ValidationException("Score value " + horse.getScore() + " not allowed. The score must be an integer between 1 and 5"); diff --git a/backend/src/main/resources/sql/createSchema.sql b/backend/src/main/resources/sql/createSchema.sql index d85b0bb..4b1d5b2 100644 --- a/backend/src/main/resources/sql/createSchema.sql +++ b/backend/src/main/resources/sql/createSchema.sql @@ -6,6 +6,9 @@ CREATE TABLE IF NOT EXISTS owner updated_at DATETIME NOT NULL ); +-- Create enum for the race +CREATE TYPE IF NOT EXISTS RACE AS ENUM('ARABIAN', 'MORGAN', 'PAINT', 'APPALOOSA'); + CREATE TABLE IF NOT EXISTS horse ( id BIGINT AUTO_INCREMENT PRIMARY KEY, @@ -13,9 +16,11 @@ CREATE TABLE IF NOT EXISTS horse description TEXT, score TINYINT NOT NULL CHECK(score >= 1 AND score <= 5), birthday DATE NOT NULL, + race RACE NOT NULL, created_at DATETIME NOT NULL, updated_at DATETIME NOT NULL ); +-- Add nullable owner foreign key ALTER TABLE horse ADD IF NOT EXISTS owner_id BIGINT NULL; ALTER TABLE horse ADD CONSTRAINT IF NOT EXISTS FL_OWNER FOREIGN KEY (owner_id) REFERENCES owner(id); diff --git a/backend/src/test/java/at/ac/tuwien/sepm/assignment/individual/integration/HorseEndpointTest.java b/backend/src/test/java/at/ac/tuwien/sepm/assignment/individual/integration/HorseEndpointTest.java index 89f683b..973b5a7 100644 --- a/backend/src/test/java/at/ac/tuwien/sepm/assignment/individual/integration/HorseEndpointTest.java +++ b/backend/src/test/java/at/ac/tuwien/sepm/assignment/individual/integration/HorseEndpointTest.java @@ -3,6 +3,7 @@ package at.ac.tuwien.sepm.assignment.individual.integration; import static org.junit.jupiter.api.Assertions.*; import at.ac.tuwien.sepm.assignment.individual.endpoint.dto.HorseDto; +import at.ac.tuwien.sepm.assignment.individual.enums.ERace; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.springframework.boot.test.context.SpringBootTest; @@ -30,7 +31,7 @@ public class HorseEndpointTest { @DisplayName("Adding a new horse with the correct parameters will return HTTP 201 and the new HorseDto") public void addingNewHorse_correctParameters_shouldReturnStatus201AndHorse() { String birthday = "2020-01-01"; - HorseDto newHorse = new HorseDto("Zephyr", "Nice horse", (short) 4, Date.valueOf(birthday), null); + HorseDto newHorse = new HorseDto("Zephyr", "Nice horse", (short) 4, Date.valueOf(birthday), ERace.APPALOOSA, null); HttpEntity request = new HttpEntity<>(newHorse); ResponseEntity response = REST_TEMPLATE diff --git a/backend/src/test/java/at/ac/tuwien/sepm/assignment/individual/unit/persistence/HorseDaoTestBase.java b/backend/src/test/java/at/ac/tuwien/sepm/assignment/individual/unit/persistence/HorseDaoTestBase.java index 571edf4..27e99f5 100644 --- a/backend/src/test/java/at/ac/tuwien/sepm/assignment/individual/unit/persistence/HorseDaoTestBase.java +++ b/backend/src/test/java/at/ac/tuwien/sepm/assignment/individual/unit/persistence/HorseDaoTestBase.java @@ -3,6 +3,7 @@ package at.ac.tuwien.sepm.assignment.individual.unit.persistence; import static org.junit.jupiter.api.Assertions.*; import at.ac.tuwien.sepm.assignment.individual.entity.Horse; +import at.ac.tuwien.sepm.assignment.individual.enums.ERace; import at.ac.tuwien.sepm.assignment.individual.persistence.HorseDao; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; @@ -20,7 +21,7 @@ public abstract class HorseDaoTestBase { @DisplayName("Adding a new horse with the correct parameters should return the horse") public void addingNewHorse_correctParameters_shouldReturnHorse() { String birthday = "2020-01-01"; - Horse newHorse = new Horse("Zephyr", "Nice horse", (short) 4, Date.valueOf(birthday), null); + Horse newHorse = new Horse("Zephyr", "Nice horse", (short) 4, Date.valueOf(birthday), ERace.APPALOOSA, null); Horse savedHorse = horseDao.addHorse(newHorse); assertEquals(newHorse, savedHorse); } @@ -29,7 +30,7 @@ public abstract class HorseDaoTestBase { @DisplayName("Adding a new horse with the incorrect parameters should throw DataAccessException") public void addingNewHorse_incorrectParameters_shouldThrowDataAccess() { String birthday = "2020-01-01"; - Horse newHorse = new Horse("Zephyr", "Nice horse", (short) 80, Date.valueOf(birthday), null); + Horse newHorse = new Horse("Zephyr", "Nice horse", (short) 80, Date.valueOf(birthday), null, null); assertThrows(DataAccessException.class, () -> horseDao.addHorse(newHorse)); } diff --git a/backend/src/test/java/at/ac/tuwien/sepm/assignment/individual/unit/service/HorseServiceTest.java b/backend/src/test/java/at/ac/tuwien/sepm/assignment/individual/unit/service/HorseServiceTest.java index 0dcae82..a229d05 100644 --- a/backend/src/test/java/at/ac/tuwien/sepm/assignment/individual/unit/service/HorseServiceTest.java +++ b/backend/src/test/java/at/ac/tuwien/sepm/assignment/individual/unit/service/HorseServiceTest.java @@ -3,6 +3,7 @@ package at.ac.tuwien.sepm.assignment.individual.unit.service; import static org.junit.jupiter.api.Assertions.*; import at.ac.tuwien.sepm.assignment.individual.entity.Horse; +import at.ac.tuwien.sepm.assignment.individual.enums.ERace; import at.ac.tuwien.sepm.assignment.individual.service.HorseService; import at.ac.tuwien.sepm.assignment.individual.util.ValidationException; import org.junit.jupiter.api.DisplayName; @@ -28,7 +29,7 @@ public class HorseServiceTest { @DisplayName("Adding a new horse with the correct parameters will return the new horse") public void addingNewHorse_correctParameters_shouldReturnHorse() { String birthday = "2020-01-01"; - Horse newHorse = new Horse("Zephyr", "Nice horse", (short) 4, Date.valueOf(birthday), null); + Horse newHorse = new Horse("Zephyr", "Nice horse", (short) 4, Date.valueOf(birthday), ERace.APPALOOSA, null); Horse savedHorse = horseService.addHorse(newHorse); assertEquals(newHorse, savedHorse); } @@ -37,7 +38,7 @@ public class HorseServiceTest { @DisplayName("Adding a new horse with the incorrect parameters will throw a ValidationException") public void addingNewHorse_incorrectParameters_shouldThrowValidation() { String birthday = "2020-01-01"; - Horse newHorse = new Horse("Zephyr", "Nice horse", (short) 80, Date.valueOf(birthday), null); + Horse newHorse = new Horse("Zephyr", "Nice horse", (short) 80, Date.valueOf(birthday), null, null); assertThrows(ValidationException.class, () -> horseService.addHorse(newHorse)); } } diff --git a/frontend/wendys-friends/src/app/dto/horse.ts b/frontend/wendys-friends/src/app/dto/horse.ts index 7caa2cc..983db33 100644 --- a/frontend/wendys-friends/src/app/dto/horse.ts +++ b/frontend/wendys-friends/src/app/dto/horse.ts @@ -5,6 +5,14 @@ export class Horse { public description: string, public score: number, public birthday: Date, + public race: ERace, public owner: number) { } } + +enum ERace { + ARABIAN, + MORGAN, + PAINT, + APPALOOSA +}