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 @@ -5,24 +5,37 @@ import com.linkedout.backend.service.JobOfferService
import org.springframework.http.server.reactive.ServerHttpRequest
import org.springframework.web.bind.annotation.GetMapping
import org.springframework.web.bind.annotation.PathVariable
import org.springframework.web.bind.annotation.PostMapping
import org.springframework.web.bind.annotation.RequestMapping
import org.springframework.web.bind.annotation.RestController
import reactor.core.publisher.Flux
import reactor.core.publisher.Mono
import java.security.Principal

@RestController
@RequestMapping("/api/v1/jobOffers")
class JobOffersController(private val jobOffersService: JobOfferService) {
@GetMapping
open fun getJobOffers(request: ServerHttpRequest): Flux<JobOffer> {
return Flux.fromIterable(jobOffersService.findAll(request.id))
open fun getJobOffers(request: ServerHttpRequest, principal: Principal): Flux<JobOffer> {
return Flux.fromIterable(jobOffersService.findAll(request.id, principal.name))
}

@GetMapping("/{id}")
@GetMapping("/{jobOfferId}")
open fun getJobOffer(
@PathVariable id: String,
request: ServerHttpRequest
request: ServerHttpRequest,
principal: Principal,
@PathVariable jobOfferId: String
): Mono<JobOffer> {
return Mono.just(jobOffersService.findOne(request.id, id))
return Mono.just(jobOffersService.findOne(request.id, principal.name, jobOfferId))
}

@PostMapping("/{jobOfferId}/apply")
open fun applyToJobOffer(
request: ServerHttpRequest,
principal: Principal,
@PathVariable jobOfferId: String
): Mono<Unit> {
jobOffersService.applyToJobOffer(request.id, principal.name, jobOfferId)
return Mono.empty()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,52 +7,77 @@ import com.linkedout.common.service.NatsService
import com.linkedout.common.utils.RequestResponseFactory
import com.linkedout.proto.models.JobOfferOuterClass
import com.linkedout.proto.services.Jobs
import com.linkedout.proto.services.Jobs.ApplyToJobOfferRequest
import org.springframework.beans.factory.annotation.Value
import org.springframework.stereotype.Service
import java.time.LocalDate

@Service
class JobOfferService(
private val natsService: NatsService,
@Value("\${app.services.jobOffers.subjects.findAll}") private val findAllSubject: String,
@Value("\${app.services.jobOffers.subjects.findOne}") private val findOneSubject: String
@Value("\${app.services.jobOffers.subjects.findAllForUser}") private val findAllSubject: String,
@Value("\${app.services.jobOffers.subjects.findOneForUser}") private val findOneSubject: String,
@Value("\${app.services.jobOffers.subjects.applyTo}") private val applyToSubject: String
) {
fun findAll(requestId: String): List<JobOffer> {
fun findAll(requestId: String, userId: String): List<JobOffer> {
// Request job offers from the job service
val response = natsService.requestWithReply(findAllSubject, RequestResponseFactory.newRequest(requestId).build())
val request = RequestResponseFactory.newRequest(requestId)
.setGetUserJobOffersRequest(
Jobs.GetUserJobOffersRequest.newBuilder()
.setUserId(userId)
)
.build()

val response = natsService.requestWithReply(findAllSubject, request)

// Handle the response
if (!response.hasGetJobOffersResponse()) {
if (!response.hasGetUserJobOffersResponse()) {
throw Exception("Invalid response")
}

val getJobOffersResponse = response.getJobOffersResponse

// TODO: Implement status with join table
return getJobOffersResponse.jobOffersList.map { jobOffer ->
val getUserJobOffersResponse = response.getUserJobOffersResponse
return getUserJobOffersResponse.jobOffersList.map { jobOffer ->
convertJobOfferFromProto(jobOffer)
}
}

fun findOne(requestId: String, id: String): JobOffer {
fun findOne(requestId: String, userId: String, jobOfferId: String): JobOffer {
// Request the job offer from the job offer service
val request = RequestResponseFactory.newRequest(requestId)
.setGetJobOfferRequest(
Jobs.GetJobOfferRequest.newBuilder()
.setId(id)
.setGetUserJobOfferRequest(
Jobs.GetUserJobOfferRequest.newBuilder()
.setUserId(userId)
.setJobOfferId(jobOfferId)
)
.build()

val response = natsService.requestWithReply(findOneSubject, request)

// Handle the response
if (!response.hasGetJobOfferResponse()) {
if (!response.hasGetUserJobOfferResponse()) {
throw Exception("Invalid response")
}

// TODO: Implement status with join table
val getJobOfferResponse = response.getJobOfferResponse
return convertJobOfferFromProto(getJobOfferResponse.jobOffer)
val getUserJobOfferResponse = response.getUserJobOfferResponse
return convertJobOfferFromProto(getUserJobOfferResponse.jobOffer)
}

fun applyToJobOffer(requestId: String, userId: String, jobOfferId: String) {
// Apply to the job offer using the job offer service
val request = RequestResponseFactory.newRequest(requestId)
.setApplyToJobOfferRequest(
ApplyToJobOfferRequest.newBuilder()
.setUserId(userId)
.setJobOfferId(jobOfferId)
)
.build()

val response = natsService.requestWithReply(applyToSubject, request)

// Handle the response
if (!response.hasApplyToJobOfferResponse()) {
throw Exception("Invalid response")
}
}

private fun convertJobOfferFromProto(source: JobOfferOuterClass.JobOffer): JobOffer {
Expand All @@ -73,7 +98,7 @@ class JobOfferService(
source.company.name
),
source.salary,
source.status
source.statusValue
)
}
}
5 changes: 3 additions & 2 deletions backend/api_gateway/src/main/resources/application.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,9 @@ app:
findOne: jobs.findOne
jobOffers:
subjects:
findAll: jobs.findAllJobOffers
findOne: jobs.findOneJobOffer
findAllForUser: jobs.findAllJobOffersForUser
findOneForUser: jobs.findOneJobOfferForUser
applyTo: jobs.applyToJobOffer
jobCategories:
subjects:
findAll: jobs.findAllCategories
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ inline fun handleRequestError(block: () -> Response): Response {
return try {
block()
} catch (e: Throwable) {
e.printStackTrace()
RequestResponseFactory.newFailedResponse(e.message ?: "Unknown error").build()
}
}
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
package com.linkedout.jobs.converter.jobOffers

import com.linkedout.jobs.dto.JobOfferWithJobAndCompany
import com.linkedout.jobs.dto.JobOfferWithJobAndCompanyAndApplicationStatus
import com.linkedout.proto.models.CompanyOuterClass
import com.linkedout.proto.models.JobOfferOuterClass
import com.linkedout.proto.models.JobOuterClass
import org.springframework.core.convert.converter.Converter

class JobOfferWithJobAndCompanyToProto : Converter<JobOfferWithJobAndCompany, JobOfferOuterClass.JobOffer.Builder> {
override fun convert(source: JobOfferWithJobAndCompany): JobOfferOuterClass.JobOffer.Builder {
class JobOfferWithJobAndCompanyToProto : Converter<JobOfferWithJobAndCompanyAndApplicationStatus, JobOfferOuterClass.JobOffer.Builder> {
override fun convert(source: JobOfferWithJobAndCompanyAndApplicationStatus): JobOfferOuterClass.JobOffer.Builder {
return JobOfferOuterClass.JobOffer.newBuilder()
.setId(source.jobOfferId)
.setTitle(source.title)
Expand All @@ -27,6 +27,5 @@ class JobOfferWithJobAndCompanyToProto : Converter<JobOfferWithJobAndCompany, Jo
.setTitle(source.jobTitle)
.setCategory(source.jobCategoryTitle)
)
.setStatus(source.jobOfferStatus)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ package com.linkedout.jobs.dto
import org.springframework.data.relational.core.mapping.Column
import java.time.LocalDate

data class JobOfferWithJobAndCompany(
data class JobOfferWithJobAndCompanyAndApplicationStatus(
@Column("jobofferid")
val jobOfferId: String,
@Column("jobid")
Expand All @@ -28,6 +28,6 @@ data class JobOfferWithJobAndCompany(
val jobCategoryTitle: String,
@Column("jobtitle")
val jobTitle: String,
@Column("status")
val jobOfferStatus: Int
@Column("jobapplicationstatus")
val jobApplicationStatus: Int
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package com.linkedout.jobs.function.jobOffers

import com.linkedout.common.utils.RequestResponseFactory
import com.linkedout.common.utils.handleRequestError
import com.linkedout.jobs.service.JobApplicationService
import com.linkedout.proto.RequestOuterClass.Request
import com.linkedout.proto.ResponseOuterClass.Response
import com.linkedout.proto.services.Jobs.ApplyToJobOfferResponse
import org.springframework.stereotype.Component
import java.util.*
import java.util.function.Function

@Component
class ApplyToJobOffer(private val jobApplicationService: JobApplicationService) : Function<Request, Response> {
override fun apply(t: Request): Response = handleRequestError {
// Extract the request
val request = t.applyToJobOfferRequest
val userId = UUID.fromString(request.userId)
val jobOfferId = UUID.fromString(request.jobOfferId)

// Apply to the job offer
jobApplicationService.applyTo(userId, jobOfferId).block()

return RequestResponseFactory.newSuccessfulResponse()
.setApplyToJobOfferResponse(ApplyToJobOfferResponse.getDefaultInstance())
.build()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,21 @@ import java.util.UUID
import java.util.function.Function

@Component
class GetJobOffer(private val jobOfferService: JobOfferService) : Function<Request, Response> {
class GetJobOfferForUser(private val jobOfferService: JobOfferService) : Function<Request, Response> {
override fun apply(t: Request): Response = handleRequestError {
// Extract the request
val request = t.getUserJobOfferRequest
val userId = UUID.fromString(request.userId)
val jobOfferId = UUID.fromString(request.jobOfferId)

// Get the job offer from the database
val reactiveResponse = jobOfferService.findOne(UUID.fromString(t.getJobOfferRequest.id))
val reactiveResponse = jobOfferService.findOneForUser(userId, jobOfferId)
.map { jobOffer ->
JobOfferWithJobAndCompanyToProto().convert(jobOffer)
.setStatusValue(jobOffer.jobApplicationStatus)
}
.map { jobOffer ->
Jobs.GetJobOfferResponse.newBuilder()
Jobs.GetUserJobOfferResponse.newBuilder()
.setJobOffer(jobOffer)
.build()
}
Expand All @@ -31,7 +37,7 @@ class GetJobOffer(private val jobOfferService: JobOfferService) : Function<Reque
?: return RequestResponseFactory.newFailedResponse("Job offer not found", HttpStatus.NOT_FOUND).build()

return RequestResponseFactory.newSuccessfulResponse()
.setGetJobOfferResponse(response)
.setGetUserJobOfferResponse(response)
.build()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,18 +8,24 @@ import com.linkedout.proto.RequestOuterClass.Request
import com.linkedout.proto.ResponseOuterClass.Response
import com.linkedout.proto.services.Jobs
import org.springframework.stereotype.Component
import java.util.UUID
import java.util.function.Function

@Component
class GetJobOffers(private val jobOfferService: JobOfferService) : Function<Request, Response> {
class GetJobOffersForUser(private val jobOfferService: JobOfferService) : Function<Request, Response> {
override fun apply(t: Request): Response = handleRequestError {
// Extract the request
val request = t.getUserJobOffersRequest
val userId = UUID.fromString(request.userId)

// Get all the job offers from the database
val reactiveResponse = jobOfferService.findAll()
val reactiveResponse = jobOfferService.findAllForUser(userId)
.map { jobOffer ->
JobOfferWithJobAndCompanyToProto().convert(jobOffer)
.setStatusValue(jobOffer.jobApplicationStatus)
}
.filter { it != null }
.reduce(Jobs.GetJobOffersResponse.newBuilder()) { builder, jobOffer ->
.reduce(Jobs.GetUserJobOffersResponse.newBuilder()) { builder, jobOffer ->
builder.addJobOffers(jobOffer)
builder
}
Expand All @@ -30,11 +36,11 @@ class GetJobOffers(private val jobOfferService: JobOfferService) : Function<Requ
// Block until the response is ready
val response = reactiveResponse.block()
?: return RequestResponseFactory.newSuccessfulResponse()
.setGetJobOffersResponse(Jobs.GetJobOffersResponse.getDefaultInstance())
.setGetUserJobOffersResponse(Jobs.GetUserJobOffersResponse.getDefaultInstance())
.build()

return RequestResponseFactory.newSuccessfulResponse()
.setGetJobOffersResponse(response)
.setGetUserJobOffersResponse(response)
.build()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@ import java.util.UUID
data class JobApplication(
@Id
val id: UUID? = null,
@Column("jobid")
val jobId: UUID,
@Column("offerid")
val jobOfferId: UUID,
@Column("userid")
val userId: UUID,
val status: Boolean
val status: Int
)
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,5 @@ data class JobOffer(
val geographicArea: String,
val job: UUID,
val company: UUID,
val salary: Int,
val status: Int
val salary: Int
)
Original file line number Diff line number Diff line change
@@ -1,6 +1,17 @@
package com.linkedout.jobs.repository

import com.linkedout.jobs.model.JobApplication
import org.springframework.data.r2dbc.repository.Query
import org.springframework.data.repository.reactive.ReactiveCrudRepository
import reactor.core.publisher.Mono
import java.util.UUID

interface JobApplicationRepository : ReactiveCrudRepository<JobApplication, UUID>
interface JobApplicationRepository : ReactiveCrudRepository<JobApplication, UUID> {
@Query(
"""
INSERT INTO jobapplication (userid, offerid)
VALUES (:userId, :offerId)
"""
)
fun saveOneWithUserIdAndOfferId(userId: UUID, offerId: UUID): Mono<Void>
}
Loading