Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import com.fasterxml.jackson.annotation.JsonFormat;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.Min;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.PastOrPresent;
import jakarta.validation.constraints.Pattern;
Expand Down Expand Up @@ -53,5 +54,9 @@ public record ApplicationRequest(
String note,

@Schema(description = "Platform or job board where the vacancy was found", example = "LinkedIn")
String platform
String platform,

@Schema(description = "Number of interviews held for this application", example = "2")
@Min(0)
Integer interviewCount
) {}
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,8 @@ public record ApplicationResponse(
@Schema(description = "Timestamp when the latest Google Docs resume was generated", example = "2024-06-11T14:45:00")
@JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss")
LocalDateTime driveResumeGeneratedAt,
@Schema(description = "Number of interviews held for this application", example = "2")
int interviewCount,
@Schema(description = "Record creation timestamp", example = "2024-06-01T10:00:00")
@JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss")
LocalDateTime createdAt,
Expand Down
6 changes: 6 additions & 0 deletions src/main/java/com/jobtracker/entity/JobApplication.java
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,9 @@ public class JobApplication {
@Column(name = "interview_scheduled", nullable = false)
private boolean interviewScheduled;

@Column(name = "interview_count", nullable = false)
private int interviewCount = 0;

@Column(name = "next_step_date_time")
private LocalDateTime nextStepDateTime;

Expand Down Expand Up @@ -147,6 +150,9 @@ protected void onUpdate() {
public boolean isInterviewScheduled() { return interviewScheduled; }
public void setInterviewScheduled(boolean interviewScheduled) { this.interviewScheduled = interviewScheduled; }

public int getInterviewCount() { return interviewCount; }
public void setInterviewCount(int interviewCount) { this.interviewCount = interviewCount; }

public LocalDateTime getNextStepDateTime() { return nextStepDateTime; }
public void setNextStepDateTime(LocalDateTime nextStepDateTime) { this.nextStepDateTime = nextStepDateTime; }

Expand Down
1 change: 1 addition & 0 deletions src/main/java/com/jobtracker/mapper/ApplicationMapper.java
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ public ApplicationResponse toResponse(JobApplication app) {
app.getDriveResumeFileName(),
app.getDriveResumeDocumentUrl(),
app.getDriveResumeGeneratedAt(),
app.getInterviewCount(),
app.getCreatedAt(),
app.getUpdatedAt()
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,8 @@ public ApplicationResponse createApplication(
status,
recruiterDmReminderEnabled != null ? recruiterDmReminderEnabled : Boolean.FALSE,
note,
platform));
platform,
null));
}

@McpTool(
Expand Down Expand Up @@ -181,7 +182,8 @@ public ApplicationResponse updateApplication(
status,
recruiterDmReminderEnabled != null ? recruiterDmReminderEnabled : Boolean.FALSE,
note,
platform));
platform,
null));
}

@McpTool(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@ public interface ApplicationRepository extends JpaRepository<JobApplication, UUI

long countByUserIdAndArchivedFalse(UUID userId);

@Query("SELECT COALESCE(SUM(a.interviewCount), 0) FROM JobApplication a WHERE a.user.id = :userId AND a.archived = false")
long sumInterviewCountByUserId(@Param("userId") UUID userId);

long countByUserIdAndInterviewScheduledTrueAndArchivedFalse(UUID userId);

@Query("SELECT COUNT(a) FROM JobApplication a WHERE a.user.id = :userId AND a.status = :status AND a.archived = false")
Expand Down
3 changes: 3 additions & 0 deletions src/main/java/com/jobtracker/service/ApplicationService.java
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,9 @@ private void mapRequestToEntity(ApplicationRequest request, JobApplication app)
app.setRecruiterDmReminderEnabled(Boolean.TRUE.equals(request.recruiterDmReminderEnabled()));
app.setNote(normalizeOptionalText(request.note()));
app.setPlatform(request.platform());
if (request.interviewCount() != null) {
app.setInterviewCount(request.interviewCount());
}
}

private void applyStatusChange(JobApplication app, ApplicationStatus newStatus) {
Expand Down
31 changes: 6 additions & 25 deletions src/main/java/com/jobtracker/service/InterviewMetricsService.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,9 @@

import com.jobtracker.entity.InterviewEvent;
import com.jobtracker.entity.JobApplication;
import com.jobtracker.entity.User;
import com.jobtracker.entity.UserInterviewMetrics;
import com.jobtracker.entity.enums.ApplicationStatus;
import com.jobtracker.repository.ApplicationRepository;
import com.jobtracker.repository.InterviewEventRepository;
import com.jobtracker.repository.UserInterviewMetricsRepository;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

Expand All @@ -27,12 +25,12 @@ public class InterviewMetricsService {
ApplicationStatus.RH_NEGOCIACAO
);

private final UserInterviewMetricsRepository metricsRepository;
private final ApplicationRepository applicationRepository;
private final InterviewEventRepository eventRepository;

public InterviewMetricsService(UserInterviewMetricsRepository metricsRepository,
public InterviewMetricsService(ApplicationRepository applicationRepository,
InterviewEventRepository eventRepository) {
this.metricsRepository = metricsRepository;
this.applicationRepository = applicationRepository;
this.eventRepository = eventRepository;
}

Expand Down Expand Up @@ -63,13 +61,8 @@ public void recordStatusTransition(JobApplication application,
return;
}

User user = application.getUser();
UserInterviewMetrics metrics = findOrCreateMetrics(user);
metrics.setInterviewCount(metrics.getInterviewCount() + 1);
metricsRepository.save(metrics);

InterviewEvent event = new InterviewEvent();
event.setUser(user);
event.setUser(application.getUser());
event.setApplication(application);
event.setOldStatus(oldStatus);
event.setNewStatus(newStatus);
Expand All @@ -79,18 +72,6 @@ public void recordStatusTransition(JobApplication application,

@Transactional(readOnly = true)
public long getInterviewCount(UUID userId) {
return metricsRepository.findById(userId)
.map(UserInterviewMetrics::getInterviewCount)
.orElseGet(() -> eventRepository.countByUser_Id(userId));
}

private UserInterviewMetrics findOrCreateMetrics(User user) {
return metricsRepository.findByUser_Id(user.getId())
.orElseGet(() -> {
UserInterviewMetrics created = new UserInterviewMetrics();
created.setUser(user);
created.setInterviewCount(0);
return created;
});
return applicationRepository.sumInterviewCountByUserId(userId);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
ALTER TABLE job_applications
ADD COLUMN interview_count INT NOT NULL DEFAULT 0 AFTER interview_scheduled;
Loading