Skip to content

Commit 60dddc5

Browse files
committed
implementa issue #2
1 parent 98bc663 commit 60dddc5

11 files changed

Lines changed: 640 additions & 102 deletions

File tree

DEMO.md

Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -110,19 +110,15 @@ Execute os testes relevantes, informe os comandos executados, o resultado e a co
110110

111111
### Prompt 4: Gerar o fechamento final
112112

113+
Antes faça:
114+
- altere a branch para `feature/tabela`
115+
- git add e git commit das mudanças
116+
- git push
117+
113118
```text
114119
Use a skill `pr-summary` #file:.github/skills/pr-summary/SKILL.md para gerar o fechamento técnico desta execução.
115-
116-
Quero um resumo final com:
117-
- issue atendida
118-
- o que foi alterado
119-
- classes principais afetadas
120-
- testes criados ou ajustados
121-
- comandos executados
122-
- resultado dos testes
123-
- cobertura JaCoCo
124-
- riscos e limitações
125-
- um resumo curto pronto para PR
120+
O commit e push já foi feito, mapeie a branch atual e seguida para próxima tarefa.
121+
Faça o PR dessa branch para a main, usando via GitHub MCP, usando o resumo curto gerado e referenciando a issue #2.
126122
```
127123

128124
## O que observar durante a apresentação

src/main/java/br/com/devsuperior/dev_xp_ai/entity/DeveloperEntity.java renamed to src/main/java/br/com/devsuperior/dev_xp_ai/entity/DeveloperExperienceEntity.java

Lines changed: 10 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -4,23 +4,14 @@
44
import org.springframework.data.relational.core.mapping.Column;
55
import org.springframework.data.relational.core.mapping.Table;
66

7-
@Table("tb_developer")
8-
public class DeveloperEntity {
7+
@Table("tb_developer_experience")
8+
public class DeveloperExperienceEntity {
99

1010
@Id
1111
private Long id;
1212

13-
@Column("full_name")
14-
private String fullName;
15-
16-
@Column("email")
17-
private String email;
18-
19-
@Column("nickname")
20-
private String nickname;
21-
22-
@Column("uf")
23-
private String uf;
13+
@Column("user_id")
14+
private Long userId;
2415

2516
@Column("years_of_experience")
2617
private Integer yearsOfExperience;
@@ -34,17 +25,13 @@ public class DeveloperEntity {
3425
@Column("skills")
3526
private String skills;
3627

37-
public DeveloperEntity() {
28+
public DeveloperExperienceEntity() {
3829
}
3930

40-
public DeveloperEntity(Long id, String fullName, String email, String nickname,
41-
String uf, Integer yearsOfExperience, String primaryLanguage,
42-
Boolean interestedInAi, String skills) {
31+
public DeveloperExperienceEntity(Long id, Long userId, Integer yearsOfExperience,
32+
String primaryLanguage, Boolean interestedInAi, String skills) {
4333
this.id = id;
44-
this.fullName = fullName;
45-
this.email = email;
46-
this.nickname = nickname;
47-
this.uf = uf;
34+
this.userId = userId;
4835
this.yearsOfExperience = yearsOfExperience;
4936
this.primaryLanguage = primaryLanguage;
5037
this.interestedInAi = interestedInAi;
@@ -54,17 +41,8 @@ public DeveloperEntity(Long id, String fullName, String email, String nickname,
5441
public Long getId() { return id; }
5542
public void setId(Long id) { this.id = id; }
5643

57-
public String getFullName() { return fullName; }
58-
public void setFullName(String fullName) { this.fullName = fullName; }
59-
60-
public String getEmail() { return email; }
61-
public void setEmail(String email) { this.email = email; }
62-
63-
public String getNickname() { return nickname; }
64-
public void setNickname(String nickname) { this.nickname = nickname; }
65-
66-
public String getUf() { return uf; }
67-
public void setUf(String uf) { this.uf = uf; }
44+
public Long getUserId() { return userId; }
45+
public void setUserId(Long userId) { this.userId = userId; }
6846

6947
public Integer getYearsOfExperience() { return yearsOfExperience; }
7048
public void setYearsOfExperience(Integer yearsOfExperience) { this.yearsOfExperience = yearsOfExperience; }
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
package br.com.devsuperior.dev_xp_ai.entity;
2+
3+
import org.springframework.data.annotation.Id;
4+
import org.springframework.data.relational.core.mapping.Column;
5+
import org.springframework.data.relational.core.mapping.Table;
6+
7+
@Table("tb_developer")
8+
public class DeveloperUserEntity {
9+
10+
@Id
11+
private Long id;
12+
13+
@Column("full_name")
14+
private String fullName;
15+
16+
@Column("email")
17+
private String email;
18+
19+
@Column("nickname")
20+
private String nickname;
21+
22+
@Column("uf")
23+
private String uf;
24+
25+
public DeveloperUserEntity() {
26+
}
27+
28+
public DeveloperUserEntity(Long id, String fullName, String email, String nickname, String uf) {
29+
this.id = id;
30+
this.fullName = fullName;
31+
this.email = email;
32+
this.nickname = nickname;
33+
this.uf = uf;
34+
}
35+
36+
public Long getId() { return id; }
37+
public void setId(Long id) { this.id = id; }
38+
39+
public String getFullName() { return fullName; }
40+
public void setFullName(String fullName) { this.fullName = fullName; }
41+
42+
public String getEmail() { return email; }
43+
public void setEmail(String email) { this.email = email; }
44+
45+
public String getNickname() { return nickname; }
46+
public void setNickname(String nickname) { this.nickname = nickname; }
47+
48+
public String getUf() { return uf; }
49+
public void setUf(String uf) { this.uf = uf; }
50+
}
51+
52+
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
package br.com.devsuperior.dev_xp_ai.repository;
2+
3+
import br.com.devsuperior.dev_xp_ai.entity.DeveloperExperienceEntity;
4+
import org.springframework.data.jdbc.repository.query.Query;
5+
import org.springframework.data.repository.CrudRepository;
6+
import org.springframework.data.repository.query.Param;
7+
import org.springframework.stereotype.Repository;
8+
9+
import java.util.List;
10+
import java.util.Optional;
11+
12+
@Repository
13+
public interface DeveloperExperienceRepository extends CrudRepository<DeveloperExperienceEntity, Long> {
14+
15+
Optional<DeveloperExperienceEntity> findByUserId(Long userId);
16+
17+
@Query("""
18+
SELECT e.* FROM tb_developer_experience e
19+
INNER JOIN tb_developer u ON u.id = e.user_id
20+
WHERE (:uf IS NULL OR u.uf = :uf)
21+
AND (:language IS NULL OR LOWER(e.primary_language) = LOWER(:language))
22+
ORDER BY u.id
23+
""")
24+
List<DeveloperExperienceEntity> findAllByFilters(@Param("uf") String uf, @Param("language") String language);
25+
}
26+
27+

src/main/java/br/com/devsuperior/dev_xp_ai/repository/DeveloperRepository.java

Lines changed: 0 additions & 21 deletions
This file was deleted.
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
package br.com.devsuperior.dev_xp_ai.repository;
2+
3+
import br.com.devsuperior.dev_xp_ai.entity.DeveloperUserEntity;
4+
import org.springframework.data.repository.CrudRepository;
5+
import org.springframework.stereotype.Repository;
6+
7+
@Repository
8+
public interface DeveloperUserRepository extends CrudRepository<DeveloperUserEntity, Long> {
9+
10+
boolean existsByEmailIgnoreCase(String email);
11+
12+
boolean existsByNicknameIgnoreCase(String nickname);
13+
}
14+

src/main/java/br/com/devsuperior/dev_xp_ai/service/DeveloperService.java

Lines changed: 66 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,12 @@
33
import br.com.devsuperior.dev_xp_ai.dto.DeveloperCreateRequest;
44
import br.com.devsuperior.dev_xp_ai.dto.DeveloperResponse;
55
import br.com.devsuperior.dev_xp_ai.dto.UpdateExperienceRequest;
6-
import br.com.devsuperior.dev_xp_ai.entity.DeveloperEntity;
6+
import br.com.devsuperior.dev_xp_ai.entity.DeveloperExperienceEntity;
7+
import br.com.devsuperior.dev_xp_ai.entity.DeveloperUserEntity;
78
import br.com.devsuperior.dev_xp_ai.exception.ConflictException;
89
import br.com.devsuperior.dev_xp_ai.exception.DeveloperNotFoundException;
9-
import br.com.devsuperior.dev_xp_ai.repository.DeveloperRepository;
10+
import br.com.devsuperior.dev_xp_ai.repository.DeveloperExperienceRepository;
11+
import br.com.devsuperior.dev_xp_ai.repository.DeveloperUserRepository;
1012
import br.com.devsuperior.dev_xp_ai.util.TextNormalizer;
1113
import org.slf4j.Logger;
1214
import org.slf4j.LoggerFactory;
@@ -32,10 +34,13 @@ public class DeveloperService {
3234
"RR", "SC", "SP", "SE", "TO"
3335
);
3436

35-
private final DeveloperRepository developerRepository;
37+
private final DeveloperUserRepository developerUserRepository;
38+
private final DeveloperExperienceRepository developerExperienceRepository;
3639

37-
public DeveloperService(DeveloperRepository developerRepository) {
38-
this.developerRepository = developerRepository;
40+
public DeveloperService(DeveloperUserRepository developerUserRepository,
41+
DeveloperExperienceRepository developerExperienceRepository) {
42+
this.developerUserRepository = developerUserRepository;
43+
this.developerExperienceRepository = developerExperienceRepository;
3944
}
4045

4146
public DeveloperResponse createDeveloper(DeveloperCreateRequest request) {
@@ -56,32 +61,39 @@ public DeveloperResponse createDeveloper(DeveloperCreateRequest request) {
5661
.toList();
5762
String skillsCsv = TextNormalizer.serializeSkills(normalizedSkillsList);
5863

59-
if (developerRepository.existsByEmailIgnoreCase(normalizedEmail)) {
64+
if (developerUserRepository.existsByEmailIgnoreCase(normalizedEmail)) {
6065
throw new ConflictException("Email ja cadastrado",
6166
List.of("Ja existe um desenvolvedor com este email."));
6267
}
6368

64-
if (developerRepository.existsByNicknameIgnoreCase(normalizedNickname)) {
69+
if (developerUserRepository.existsByNicknameIgnoreCase(normalizedNickname)) {
6570
throw new ConflictException("Nickname ja cadastrado",
6671
List.of("Ja existe um desenvolvedor com este nickname."));
6772
}
6873

69-
DeveloperEntity entity = new DeveloperEntity(
74+
DeveloperUserEntity userEntity = new DeveloperUserEntity(
7075
null,
7176
normalizedName,
7277
normalizedEmail,
7378
normalizedNickname,
74-
normalizedUf,
79+
normalizedUf
80+
);
81+
DeveloperUserEntity savedUser = developerUserRepository.save(userEntity);
82+
log.info("[correlationId={}] Dados de usuario persistidos: id={}", MDC.get("correlationId"), savedUser.getId());
83+
84+
DeveloperExperienceEntity experienceEntity = new DeveloperExperienceEntity(
85+
null,
86+
savedUser.getId(),
7587
request.yearsOfExperience(),
7688
normalizedLanguage,
7789
request.interestedInAi(),
7890
skillsCsv
7991
);
92+
DeveloperExperienceEntity savedExperience = developerExperienceRepository.save(experienceEntity);
93+
log.info("[correlationId={}] Dados de experiencia persistidos: userId={}", MDC.get("correlationId"), savedUser.getId());
8094

81-
DeveloperEntity saved = developerRepository.save(entity);
82-
83-
log.info("[correlationId={}] Developer criado com sucesso: id={}", MDC.get("correlationId"), saved.getId());
84-
return toResponse(saved);
95+
log.info("[correlationId={}] Developer criado com sucesso: id={}", MDC.get("correlationId"), savedUser.getId());
96+
return toResponse(savedUser, savedExperience);
8597
}
8698

8799
public List<DeveloperResponse> listDevelopers(String uf, String language) {
@@ -97,10 +109,15 @@ public List<DeveloperResponse> listDevelopers(String uf, String language) {
97109

98110
String normalizedLanguage = (language != null && !language.isBlank()) ? language.trim() : null;
99111

100-
List<DeveloperResponse> result = developerRepository
101-
.findAllByFilters(normalizedUf, normalizedLanguage)
102-
.stream()
103-
.map(this::toResponse)
112+
List<DeveloperExperienceEntity> experiences = developerExperienceRepository
113+
.findAllByFilters(normalizedUf, normalizedLanguage);
114+
115+
List<DeveloperResponse> result = experiences.stream()
116+
.map(exp -> {
117+
DeveloperUserEntity user = developerUserRepository.findById(exp.getUserId())
118+
.orElseThrow(() -> new DeveloperNotFoundException(exp.getUserId()));
119+
return toResponse(user, exp);
120+
})
104121
.toList();
105122

106123
log.info("[correlationId={}] Listagem concluida: {} resultado(s)", MDC.get("correlationId"), result.size());
@@ -110,11 +127,14 @@ public List<DeveloperResponse> listDevelopers(String uf, String language) {
110127
public DeveloperResponse getDeveloperById(Long id) {
111128
log.info("[correlationId={}] Buscando developer por id={}", MDC.get("correlationId"), id);
112129

113-
DeveloperEntity entity = developerRepository.findById(id)
130+
DeveloperUserEntity user = developerUserRepository.findById(id)
131+
.orElseThrow(() -> new DeveloperNotFoundException(id));
132+
133+
DeveloperExperienceEntity experience = developerExperienceRepository.findByUserId(id)
114134
.orElseThrow(() -> new DeveloperNotFoundException(id));
115135

116136
log.info("[correlationId={}] Developer encontrado: id={}", MDC.get("correlationId"), id);
117-
return toResponse(entity);
137+
return toResponse(user, experience);
118138
}
119139

120140
public DeveloperResponse updateExperience(Long id, UpdateExperienceRequest request) {
@@ -125,16 +145,24 @@ public DeveloperResponse updateExperience(Long id, UpdateExperienceRequest reque
125145
throw new IllegalArgumentException(String.join("; ", errors));
126146
}
127147

128-
DeveloperEntity entity = developerRepository.findById(id)
148+
DeveloperUserEntity user = developerUserRepository.findById(id)
149+
.orElseThrow(() -> new DeveloperNotFoundException(id));
150+
151+
DeveloperExperienceEntity experience = developerExperienceRepository.findByUserId(id)
129152
.orElseThrow(() -> new DeveloperNotFoundException(id));
130153

131-
entity.setYearsOfExperience(request.yearsOfExperience());
132-
DeveloperEntity updated = developerRepository.save(entity);
154+
experience.setYearsOfExperience(request.yearsOfExperience());
155+
DeveloperExperienceEntity updatedExperience = developerExperienceRepository.save(experience);
133156

134-
log.info("[correlationId={}] Experiencia atualizada para id={}: yearsOfExperience={}", MDC.get("correlationId"), id, updated.getYearsOfExperience());
135-
return toResponse(updated);
157+
log.info("[correlationId={}] Experiencia atualizada para id={}: yearsOfExperience={}",
158+
MDC.get("correlationId"), id, updatedExperience.getYearsOfExperience());
159+
return toResponse(user, updatedExperience);
136160
}
137161

162+
// -------------------------------------------------------------------------
163+
// Validações
164+
// -------------------------------------------------------------------------
165+
138166
private List<String> validateCreateRequest(DeveloperCreateRequest request) {
139167
List<String> errors = new ArrayList<>();
140168
if (request == null) {
@@ -190,22 +218,25 @@ private List<String> validateExperienceUpdate(UpdateExperienceRequest request) {
190218
return errors;
191219
}
192220

193-
private DeveloperResponse toResponse(DeveloperEntity entity) {
221+
// -------------------------------------------------------------------------
222+
// Mapeamento
223+
// -------------------------------------------------------------------------
224+
225+
private DeveloperResponse toResponse(DeveloperUserEntity user, DeveloperExperienceEntity experience) {
194226
return new DeveloperResponse(
195-
entity.getId(),
196-
entity.getFullName(),
197-
entity.getEmail(),
198-
entity.getNickname(),
199-
entity.getUf(),
200-
entity.getYearsOfExperience(),
201-
entity.getPrimaryLanguage(),
202-
entity.getInterestedInAi(),
203-
TextNormalizer.deserializeSkills(entity.getSkills())
227+
user.getId(),
228+
user.getFullName(),
229+
user.getEmail(),
230+
user.getNickname(),
231+
user.getUf(),
232+
experience.getYearsOfExperience(),
233+
experience.getPrimaryLanguage(),
234+
experience.getInterestedInAi(),
235+
TextNormalizer.deserializeSkills(experience.getSkills())
204236
);
205237
}
206238

207239
private boolean hasText(String value) {
208240
return value != null && !value.trim().isEmpty();
209241
}
210242
}
211-

0 commit comments

Comments
 (0)