feat: implement final Experience API
This commit is contained in:
parent
ab40e9a497
commit
9f5306545e
@ -1,7 +1,13 @@
|
||||
package com.pablotj.portfolio.application.experience;
|
||||
|
||||
import com.pablotj.portfolio.domain.experience.Achievement;
|
||||
import com.pablotj.portfolio.domain.experience.Experience;
|
||||
import com.pablotj.portfolio.domain.experience.Skill;
|
||||
import com.pablotj.portfolio.domain.experience.port.ExperienceRepositoryPort;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import java.time.LocalDate;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class CreateExperienceUseCase {
|
||||
|
||||
@ -14,13 +20,35 @@ public class CreateExperienceUseCase {
|
||||
public Experience handle(Command cmd) {
|
||||
var experience = Experience.builder()
|
||||
.id(null)
|
||||
.title(cmd.title())
|
||||
.position(cmd.position())
|
||||
.company(cmd.company())
|
||||
.startDate(cmd.startDate())
|
||||
.endDate(cmd.endDate())
|
||||
.city(cmd.city())
|
||||
.region(cmd.region())
|
||||
.country(cmd.country())
|
||||
.remote(cmd.remote())
|
||||
.description(cmd.description())
|
||||
.url(cmd.url())
|
||||
.skills(new ArrayList<>())
|
||||
.achievements(new ArrayList<>())
|
||||
.build();
|
||||
cmd.skills.forEach(name -> experience.getSkills().add(Skill.builder().id(null).name(name).build()));
|
||||
cmd.achievements.forEach(description -> experience.getAchievements().add(Achievement.builder().id(null).description(description).build()));
|
||||
return repository.save(experience);
|
||||
}
|
||||
|
||||
public record Command(String title, String description, String url) {
|
||||
public record Command(
|
||||
String position,
|
||||
String company,
|
||||
LocalDate startDate,
|
||||
LocalDate endDate,
|
||||
String city,
|
||||
String region,
|
||||
String country,
|
||||
Boolean remote,
|
||||
String description,
|
||||
List<String> skills,
|
||||
List<String> achievements
|
||||
) {
|
||||
}
|
||||
}
|
@ -11,6 +11,7 @@ spring:
|
||||
properties:
|
||||
hibernate.transaction.jta.platform: org.hibernate.engine.transaction.jta.platform.internal.NoJtaPlatform
|
||||
hibernate:
|
||||
dialect: org.hibernate.dialect.H2Dialect
|
||||
format_sql: true
|
||||
show-sql: true
|
||||
|
||||
@ -37,7 +38,8 @@ spring:
|
||||
on-profile: default
|
||||
|
||||
datasource:
|
||||
url: jdbc:h2:mem:portfolio_db;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE
|
||||
url: jdbc:h2:file:./portfolio-db
|
||||
driver-class-name: org.h2.Driver
|
||||
username: sa
|
||||
password:
|
||||
|
||||
|
@ -0,0 +1,12 @@
|
||||
package com.pablotj.portfolio.domain.experience;
|
||||
|
||||
import java.time.LocalDate;
|
||||
import lombok.Builder;
|
||||
import lombok.Getter;
|
||||
|
||||
@Getter
|
||||
@Builder
|
||||
public class Achievement {
|
||||
private final ArchivementId id;
|
||||
private String description;
|
||||
}
|
@ -0,0 +1,7 @@
|
||||
package com.pablotj.portfolio.domain.experience;
|
||||
|
||||
public record ArchivementId(Long value) {
|
||||
public ArchivementId {
|
||||
if (value != null && value < 0) throw new IllegalArgumentException("ArchivementId must be positive");
|
||||
}
|
||||
}
|
@ -1,5 +1,7 @@
|
||||
package com.pablotj.portfolio.domain.experience;
|
||||
|
||||
import java.time.LocalDate;
|
||||
import java.util.List;
|
||||
import lombok.Builder;
|
||||
import lombok.Getter;
|
||||
|
||||
@ -7,7 +9,15 @@ import lombok.Getter;
|
||||
@Builder
|
||||
public class Experience {
|
||||
private final ExperienceId id;
|
||||
private final String title;
|
||||
private final String position;
|
||||
private final String company;
|
||||
private final LocalDate startDate;
|
||||
private final LocalDate endDate;
|
||||
private final String city;
|
||||
private final String region;
|
||||
private final String country;
|
||||
private final Boolean remote;
|
||||
private final String description;
|
||||
private final String url;
|
||||
private final List<Skill> skills;
|
||||
private final List<Achievement> achievements;
|
||||
}
|
@ -0,0 +1,12 @@
|
||||
package com.pablotj.portfolio.domain.experience;
|
||||
|
||||
import java.time.LocalDate;
|
||||
import lombok.Builder;
|
||||
import lombok.Getter;
|
||||
|
||||
@Getter
|
||||
@Builder
|
||||
public class Skill {
|
||||
private final SkillId id;
|
||||
private String name;
|
||||
}
|
@ -0,0 +1,7 @@
|
||||
package com.pablotj.portfolio.domain.experience;
|
||||
|
||||
public record SkillId(Long value) {
|
||||
public SkillId {
|
||||
if (value != null && value < 0) throw new IllegalArgumentException("SkillId must be positive");
|
||||
}
|
||||
}
|
@ -0,0 +1,21 @@
|
||||
package com.pablotj.portfolio.infrastructure.persistence.experience.entity;
|
||||
|
||||
import jakarta.persistence.*;
|
||||
import lombok.*;
|
||||
|
||||
@Entity
|
||||
@Table(name = "experience_achievements")
|
||||
@Getter
|
||||
@Setter
|
||||
@NoArgsConstructor(access = AccessLevel.PROTECTED)
|
||||
@AllArgsConstructor(access = AccessLevel.PRIVATE)
|
||||
@Builder
|
||||
public class ExperienceAchievementJpaEntity {
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
private Long id;
|
||||
|
||||
@Column(columnDefinition = "text")
|
||||
private String description;
|
||||
}
|
@ -1,29 +1,55 @@
|
||||
package com.pablotj.portfolio.infrastructure.persistence.experience.entity;
|
||||
|
||||
import jakarta.persistence.CascadeType;
|
||||
import jakarta.persistence.Column;
|
||||
import jakarta.persistence.Entity;
|
||||
import jakarta.persistence.GeneratedValue;
|
||||
import jakarta.persistence.GenerationType;
|
||||
import jakarta.persistence.Id;
|
||||
import jakarta.persistence.JoinColumn;
|
||||
import jakarta.persistence.OneToMany;
|
||||
import jakarta.persistence.Table;
|
||||
import java.time.LocalDate;
|
||||
import java.util.List;
|
||||
import lombok.AccessLevel;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.Setter;
|
||||
|
||||
@Entity
|
||||
@Table(name = "experiences")
|
||||
@Getter
|
||||
@Setter
|
||||
@NoArgsConstructor(access = AccessLevel.PROTECTED)
|
||||
@AllArgsConstructor(access = AccessLevel.PRIVATE)
|
||||
@Builder
|
||||
public class ExperienceJpaEntity {
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
private Long id;
|
||||
|
||||
@Column(nullable = false)
|
||||
private String title;
|
||||
private String position;
|
||||
private String company;
|
||||
|
||||
private LocalDate startDate;
|
||||
private LocalDate endDate;
|
||||
|
||||
private String city;
|
||||
private String region;
|
||||
private String country;
|
||||
private Boolean remote;
|
||||
|
||||
@Column(columnDefinition = "text")
|
||||
private String description;
|
||||
|
||||
private String url;
|
||||
@OneToMany(cascade = CascadeType.ALL, orphanRemoval = true)
|
||||
@JoinColumn(name = "experience_id")
|
||||
private List<ExperienceSkillJpaEntity> skills;
|
||||
|
||||
@OneToMany(cascade = CascadeType.ALL, orphanRemoval = true)
|
||||
@JoinColumn(name = "experience_id")
|
||||
private List<ExperienceAchievementJpaEntity> achievements;
|
||||
}
|
@ -0,0 +1,20 @@
|
||||
package com.pablotj.portfolio.infrastructure.persistence.experience.entity;
|
||||
|
||||
import jakarta.persistence.*;
|
||||
import lombok.*;
|
||||
|
||||
@Entity
|
||||
@Table(name = "experience_skills")
|
||||
@Getter
|
||||
@Setter
|
||||
@NoArgsConstructor(access = AccessLevel.PROTECTED)
|
||||
@AllArgsConstructor(access = AccessLevel.PRIVATE)
|
||||
@Builder
|
||||
public class ExperienceSkillJpaEntity {
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
private Long id;
|
||||
|
||||
private String name;
|
||||
}
|
@ -1,8 +1,11 @@
|
||||
package com.pablotj.portfolio.infrastructure.persistence.experience.mapper;
|
||||
|
||||
import com.pablotj.portfolio.domain.experience.Achievement;
|
||||
import com.pablotj.portfolio.domain.experience.Experience;
|
||||
import com.pablotj.portfolio.domain.experience.ExperienceId;
|
||||
import com.pablotj.portfolio.domain.experience.Skill;
|
||||
import com.pablotj.portfolio.infrastructure.persistence.experience.entity.ExperienceAchievementJpaEntity;
|
||||
import com.pablotj.portfolio.infrastructure.persistence.experience.entity.ExperienceJpaEntity;
|
||||
import com.pablotj.portfolio.infrastructure.persistence.experience.entity.ExperienceSkillJpaEntity;
|
||||
import org.mapstruct.Mapper;
|
||||
import org.mapstruct.Mapping;
|
||||
|
||||
@ -13,5 +16,20 @@ public interface ExperienceJpaMapper {
|
||||
ExperienceJpaEntity toEntity(Experience domain);
|
||||
|
||||
@Mapping(target = "id.value", source = "id")
|
||||
Experience toDomain(ExperienceJpaEntity e);
|
||||
Experience toDomain(ExperienceJpaEntity entity);
|
||||
|
||||
|
||||
@Mapping(target = "id", ignore = true)
|
||||
ExperienceAchievementJpaEntity toEntity(Achievement entity);
|
||||
|
||||
@Mapping(target = "id.value", source = "id")
|
||||
Achievement toDomain(ExperienceAchievementJpaEntity entity);
|
||||
|
||||
@Mapping(target = "id", ignore = true)
|
||||
ExperienceSkillJpaEntity toEntity(Skill entity);
|
||||
|
||||
@Mapping(target = "id.value", source = "id")
|
||||
Skill toDomain(ExperienceSkillJpaEntity entity);
|
||||
|
||||
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
package com.pablotj.portfolio.infrastructure.rest.about.controller;
|
||||
package com.pablotj.portfolio.infrastructure.rest.about;
|
||||
|
||||
import com.pablotj.portfolio.application.about.CreateAboutUseCase;
|
||||
import com.pablotj.portfolio.application.about.GetAboutUseCase;
|
@ -1,4 +1,4 @@
|
||||
package com.pablotj.portfolio.infrastructure.rest.certification.controller;
|
||||
package com.pablotj.portfolio.infrastructure.rest.certification;
|
||||
|
||||
import com.pablotj.portfolio.application.certification.CreateCertificationUseCase;
|
||||
import com.pablotj.portfolio.application.certification.GetCertificationUseCase;
|
@ -1,4 +1,4 @@
|
||||
package com.pablotj.portfolio.infrastructure.rest.contact.controller;
|
||||
package com.pablotj.portfolio.infrastructure.rest.contact;
|
||||
|
||||
import com.pablotj.portfolio.application.contact.CreateContactUseCase;
|
||||
import com.pablotj.portfolio.application.contact.GetContactUseCase;
|
@ -1,4 +1,4 @@
|
||||
package com.pablotj.portfolio.infrastructure.rest.education.controller;
|
||||
package com.pablotj.portfolio.infrastructure.rest.education;
|
||||
|
||||
import com.pablotj.portfolio.application.education.CreateEducationUseCase;
|
||||
import com.pablotj.portfolio.application.education.GetEducationUseCase;
|
@ -1,4 +1,4 @@
|
||||
package com.pablotj.portfolio.infrastructure.rest.experience.controller;
|
||||
package com.pablotj.portfolio.infrastructure.rest.experience;
|
||||
|
||||
import com.pablotj.portfolio.application.experience.CreateExperienceUseCase;
|
||||
import com.pablotj.portfolio.application.experience.GetExperienceUseCase;
|
||||
@ -46,9 +46,17 @@ public class ExperienceController {
|
||||
@PostMapping
|
||||
public ResponseEntity<ExperienceDto> create(@Valid @RequestBody CreateExperienceRequest request) {
|
||||
var cmd = new CreateExperienceUseCase.Command(
|
||||
request.title(),
|
||||
request.position(),
|
||||
request.company(),
|
||||
request.startDate(),
|
||||
request.endDate(),
|
||||
request.city(),
|
||||
request.region(),
|
||||
request.country(),
|
||||
request.remote(),
|
||||
request.description(),
|
||||
request.url()
|
||||
request.skills(),
|
||||
request.achievements()
|
||||
);
|
||||
var created = createUC.handle(cmd);
|
||||
var body = mapper.toDto(created);
|
@ -1,10 +1,19 @@
|
||||
package com.pablotj.portfolio.infrastructure.rest.experience.dto;
|
||||
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import java.time.LocalDate;
|
||||
import java.util.List;
|
||||
|
||||
public record CreateExperienceRequest(
|
||||
@NotBlank String title,
|
||||
@NotBlank String position,
|
||||
String company,
|
||||
LocalDate startDate,
|
||||
LocalDate endDate,
|
||||
String city,
|
||||
String region,
|
||||
String country,
|
||||
Boolean remote,
|
||||
String description,
|
||||
String url
|
||||
) {
|
||||
}
|
||||
List<String> skills,
|
||||
List<String> achievements
|
||||
) {}
|
@ -1,6 +1,20 @@
|
||||
package com.pablotj.portfolio.infrastructure.rest.experience.dto;
|
||||
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import java.time.LocalDate;
|
||||
import java.util.List;
|
||||
|
||||
public record ExperienceDto(Long id, @NotBlank String title, String description, String url) {
|
||||
}
|
||||
public record ExperienceDto(
|
||||
Long id,
|
||||
@NotBlank String position,
|
||||
String company,
|
||||
LocalDate startDate,
|
||||
LocalDate endDate,
|
||||
String city,
|
||||
String region,
|
||||
String country,
|
||||
Boolean remote,
|
||||
String description,
|
||||
List<String> skills,
|
||||
List<String> achievements
|
||||
) {}
|
@ -1,7 +1,10 @@
|
||||
package com.pablotj.portfolio.infrastructure.rest.experience.mapper;
|
||||
|
||||
import com.pablotj.portfolio.domain.experience.Achievement;
|
||||
import com.pablotj.portfolio.domain.experience.Experience;
|
||||
import com.pablotj.portfolio.domain.experience.Skill;
|
||||
import com.pablotj.portfolio.infrastructure.rest.experience.dto.ExperienceDto;
|
||||
import java.util.List;
|
||||
import org.mapstruct.Mapper;
|
||||
import org.mapstruct.Mapping;
|
||||
|
||||
@ -9,5 +12,19 @@ import org.mapstruct.Mapping;
|
||||
public interface ExperienceRestMapper {
|
||||
|
||||
@Mapping(target = "id", source = "id.value")
|
||||
@Mapping(target = "skills", source = "skills")
|
||||
@Mapping(target = "achievements", source = "achievements")
|
||||
ExperienceDto toDto(Experience domain);
|
||||
|
||||
default List<String> mapSkills(List<Skill> skills) {
|
||||
return skills == null ? List.of() : skills.stream()
|
||||
.map(Skill::getName)
|
||||
.toList();
|
||||
}
|
||||
|
||||
default List<String> mapAchievements(List<Achievement> achievements) {
|
||||
return achievements == null ? List.of() : achievements.stream()
|
||||
.map(Achievement::getDescription)
|
||||
.toList();
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
package com.pablotj.portfolio.infrastructure.rest.project.controller;
|
||||
package com.pablotj.portfolio.infrastructure.rest.project;
|
||||
|
||||
import com.pablotj.portfolio.application.project.CreateProjectUseCase;
|
||||
import com.pablotj.portfolio.application.project.GetProjectUseCase;
|
@ -1,4 +1,4 @@
|
||||
package com.pablotj.portfolio.infrastructure.rest.resume.controller;
|
||||
package com.pablotj.portfolio.infrastructure.rest.resume;
|
||||
|
||||
import com.pablotj.portfolio.application.resume.CreateResumeUseCase;
|
||||
import com.pablotj.portfolio.application.resume.GetResumeUseCase;
|
@ -1,4 +1,4 @@
|
||||
package com.pablotj.portfolio.infrastructure.rest.skill.controller;
|
||||
package com.pablotj.portfolio.infrastructure.rest.skill;
|
||||
|
||||
import com.pablotj.portfolio.application.skill.CreateSkillUseCase;
|
||||
import com.pablotj.portfolio.application.skill.GetSkillUseCase;
|
Loading…
x
Reference in New Issue
Block a user