@@ -15,8 +15,8 @@ java { toolchain { languageVersion = JavaLanguageVersion.of(17) } }
|
||||
repositories { mavenCentral() }
|
||||
|
||||
dependencies {
|
||||
implementation("org.postgresql:postgresql")
|
||||
implementation("org.springframework.security:spring-security-crypto:6.0.3")
|
||||
implementation("org.postgresql:postgresql")
|
||||
implementation("org.springframework.security:spring-security-crypto:6.0.3")
|
||||
implementation("org.springframework.boot:spring-boot-starter-data-jpa")
|
||||
implementation("org.springframework.boot:spring-boot-starter-mustache")
|
||||
implementation("org.springframework.boot:spring-boot-starter-web")
|
||||
@@ -32,20 +32,14 @@ dependencies {
|
||||
implementation("org.bouncycastle:bcprov-jdk18on:1.76")
|
||||
}
|
||||
|
||||
springBoot {
|
||||
mainClass.set("com.andr3h3nriqu3s.applications.ApplicationsApplicationKt")
|
||||
}
|
||||
springBoot { mainClass.set("com.andr3h3nriqu3s.applications.ApplicationsApplicationKt") }
|
||||
|
||||
kotlin {
|
||||
compilerOptions {
|
||||
freeCompilerArgs.addAll("-Xjsr305=strict")
|
||||
}
|
||||
compilerOptions { freeCompilerArgs.addAll("-Xjsr305=strict") }
|
||||
|
||||
jvmToolchain(17)
|
||||
jvmToolchain(17)
|
||||
}
|
||||
|
||||
tasks.withType<Test> { useJUnitPlatform() }
|
||||
|
||||
tasks.withType<Test> {
|
||||
useJUnitPlatform()
|
||||
}
|
||||
tasks.withType<Test> { useJUnitPlatform() }
|
||||
|
||||
@@ -42,6 +42,7 @@ data class Application(
|
||||
var create_time: String,
|
||||
var flairs: List<Flair>,
|
||||
var views: List<View>,
|
||||
var events: List<Event>,
|
||||
) {
|
||||
companion object : RowMapper<Application> {
|
||||
override public fun mapRow(rs: ResultSet, rowNum: Int): Application {
|
||||
@@ -64,6 +65,7 @@ data class Application(
|
||||
rs.getString("create_time"),
|
||||
emptyList(),
|
||||
emptyList(),
|
||||
emptyList(),
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -94,6 +96,7 @@ class ApplicationsController(
|
||||
val applicationService: ApplicationService,
|
||||
val flairService: FlairService,
|
||||
val viewService: ViewService,
|
||||
val eventService: EventService,
|
||||
) {
|
||||
|
||||
@GetMapping(path = ["/cv/{id}"], produces = [MediaType.APPLICATION_JSON_VALUE])
|
||||
@@ -106,6 +109,7 @@ class ApplicationsController(
|
||||
|
||||
if (user == null) {
|
||||
viewService.create(application.id)
|
||||
eventService.create(application.id, EventType.View)
|
||||
}
|
||||
|
||||
val flairs = application.flairs.map { it.toFlairSimple() }
|
||||
@@ -141,6 +145,7 @@ class ApplicationsController(
|
||||
"",
|
||||
emptyList(),
|
||||
emptyList(),
|
||||
emptyList(),
|
||||
)
|
||||
|
||||
if (!applicationService.createApplication(user, application)) {
|
||||
@@ -268,6 +273,7 @@ class ApplicationsController(
|
||||
"",
|
||||
emptyList(),
|
||||
emptyList(),
|
||||
emptyList(),
|
||||
)
|
||||
}
|
||||
|
||||
@@ -311,21 +317,13 @@ class ApplicationsController(
|
||||
throw NotFound()
|
||||
}
|
||||
|
||||
if (application.status == info.status) {
|
||||
return application;
|
||||
}
|
||||
|
||||
application.status = info.status
|
||||
val status_string = "${info.status}"
|
||||
var status_history = application.status_history.split(",").filter { it.length >= 1 }
|
||||
if (status_history.indexOf(status_string) == -1) {
|
||||
status_history = status_history.plus("${info.status}")
|
||||
}
|
||||
|
||||
application.status_history = status_history.joinToString(",") { it }
|
||||
|
||||
if (info.status == 4) {
|
||||
val sdf = SimpleDateFormat("dd/MM/yyyy hh:mm:ss")
|
||||
application.application_time = sdf.format(Date())
|
||||
}
|
||||
|
||||
applicationService.update(application)
|
||||
applicationService.updateStatus(application)
|
||||
|
||||
return application
|
||||
}
|
||||
@@ -460,7 +458,8 @@ class ApplicationsController(
|
||||
class ApplicationService(
|
||||
val db: JdbcTemplate,
|
||||
val flairService: FlairService,
|
||||
val viewService: ViewService
|
||||
val viewService: ViewService,
|
||||
val eventService: EventService,
|
||||
) {
|
||||
|
||||
public fun findApplicationByUrl(user: UserDb, url: String, unique_url: String?): Application? {
|
||||
@@ -510,6 +509,7 @@ class ApplicationService(
|
||||
|
||||
application.flairs = flairService.listFromLinkApplicationId(application.id)
|
||||
application.views = viewService.listFromApplicationId(application.id)
|
||||
application.events = eventService.listFromApplicationId(application.id).toList()
|
||||
|
||||
return application
|
||||
}
|
||||
@@ -524,7 +524,7 @@ class ApplicationService(
|
||||
|
||||
var application = applications[0]
|
||||
|
||||
// Views are not needed for this request
|
||||
// Views / Events are not needed for this request
|
||||
application.flairs = flairService.listFromLinkApplicationId(application.id)
|
||||
|
||||
return application
|
||||
@@ -555,6 +555,8 @@ class ApplicationService(
|
||||
application.application_time,
|
||||
)
|
||||
|
||||
eventService.create(application.id, EventType.Creation)
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
@@ -594,10 +596,39 @@ class ApplicationService(
|
||||
return iter.toList()
|
||||
}
|
||||
|
||||
// Update the stauts on the application object before giving it to this function
|
||||
public fun updateStatus(application: Application): Application {
|
||||
|
||||
val status_string = "${application.status}"
|
||||
var status_history = application.status_history.split(",").filter { it.length >= 1 }
|
||||
if (status_history.indexOf(status_string) == -1) {
|
||||
status_history = status_history.plus(status_string)
|
||||
}
|
||||
|
||||
application.status_history = status_history.joinToString(",") { it }
|
||||
|
||||
if (application.status == 4) {
|
||||
val sdf = SimpleDateFormat("dd/MM/yyyy hh:mm:ss")
|
||||
application.application_time = sdf.format(Date())
|
||||
}
|
||||
|
||||
eventService.create(application.id, EventType.StatusUpdate, application.status)
|
||||
|
||||
db.update(
|
||||
"update applications set status=?, status_history=?, application_time=? where id=?",
|
||||
application.status,
|
||||
application.status_history,
|
||||
application.application_time,
|
||||
application.id,
|
||||
)
|
||||
return application
|
||||
}
|
||||
|
||||
// Note this does not update status
|
||||
public fun update(application: Application): Application {
|
||||
// I don't want ot update create_time
|
||||
db.update(
|
||||
"update applications set url=?, original_url=?, unique_url=?, title=?, user_id=?, extra_data=?, payrange=?, status=?, company=?, recruiter=?, message=?, linked_application=?, status_history=?, application_time=? where id=?",
|
||||
"update applications set url=?, original_url=?, unique_url=?, title=?, user_id=?, extra_data=?, payrange=?, company=?, recruiter=?, message=?, linked_application=? where id=?",
|
||||
application.url,
|
||||
application.original_url,
|
||||
application.unique_url,
|
||||
@@ -605,13 +636,10 @@ class ApplicationService(
|
||||
application.user_id,
|
||||
application.extra_data,
|
||||
application.payrange,
|
||||
application.status,
|
||||
application.company,
|
||||
application.recruiter,
|
||||
application.message,
|
||||
application.linked_application,
|
||||
application.status_history,
|
||||
application.application_time,
|
||||
application.id,
|
||||
)
|
||||
return application
|
||||
|
||||
117
api/src/main/kotlin/com/andr3h3nriqu3s/applications/Events.kt
Normal file
117
api/src/main/kotlin/com/andr3h3nriqu3s/applications/Events.kt
Normal file
@@ -0,0 +1,117 @@
|
||||
package com.andr3h3nriqu3s.applications
|
||||
|
||||
import java.sql.ResultSet
|
||||
import java.sql.Timestamp
|
||||
import java.util.Date
|
||||
import java.util.UUID
|
||||
import org.springframework.jdbc.core.JdbcTemplate
|
||||
import org.springframework.jdbc.core.RowMapper
|
||||
import org.springframework.stereotype.Service
|
||||
import org.springframework.web.bind.annotation.RestController
|
||||
import org.springframework.web.bind.annotation.ControllerAdvice
|
||||
import org.springframework.web.bind.annotation.RequestMapping
|
||||
import org.springframework.web.bind.annotation.GetMapping
|
||||
import org.springframework.web.bind.annotation.PathVariable
|
||||
import org.springframework.web.bind.annotation.RequestHeader
|
||||
import org.springframework.http.MediaType
|
||||
|
||||
enum class EventType(val value: Int) {
|
||||
Creation(0),
|
||||
StatusUpdate(1),
|
||||
View(2)
|
||||
}
|
||||
|
||||
data class Event(
|
||||
var id: String,
|
||||
var application_id: String,
|
||||
var event_type: Int,
|
||||
var new_status: Int?,
|
||||
var time: Timestamp
|
||||
) {
|
||||
companion object : RowMapper<Event> {
|
||||
override public fun mapRow(rs: ResultSet, rowNum: Int): Event {
|
||||
return Event(
|
||||
rs.getString("id"),
|
||||
rs.getString("application_id"),
|
||||
rs.getInt("event_type"),
|
||||
rs.getInt("new_status"),
|
||||
rs.getTimestamp("time"),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@RestController
|
||||
@ControllerAdvice
|
||||
@RequestMapping("/api/events")
|
||||
class EventController(
|
||||
val sessionService: SessionService,
|
||||
val applicationService: ApplicationService,
|
||||
val eventService: EventService
|
||||
) {
|
||||
|
||||
@GetMapping(path = ["/{id}"], produces = [MediaType.APPLICATION_JSON_VALUE])
|
||||
public fun getCV(@PathVariable id: String, @RequestHeader("token") token: String): List<Event> {
|
||||
val user = sessionService.verifyTokenThrow(token)
|
||||
|
||||
val application = applicationService.findApplicationById(user, id)
|
||||
|
||||
if (application == null) {
|
||||
throw NotFound()
|
||||
}
|
||||
|
||||
return application.events;
|
||||
}
|
||||
}
|
||||
|
||||
// Note I decided that events are read+delete only
|
||||
@Service
|
||||
public class EventService(val db: JdbcTemplate) {
|
||||
|
||||
public fun listFromApplicationId(id: String): Iterable<Event> =
|
||||
db.query("select * from events where application_id=? order by time asc;", arrayOf(id), Event)
|
||||
|
||||
public fun getById(id: String): Event? {
|
||||
val items = db.query("select * from events where id=?;", arrayOf(id), Event)
|
||||
if (items.size == 0) {
|
||||
return null
|
||||
}
|
||||
return items.first()
|
||||
}
|
||||
|
||||
public fun deleteById(id: String): Event {
|
||||
val event = this.getById(id)
|
||||
if (event == null) {
|
||||
throw NotFound()
|
||||
}
|
||||
|
||||
db.update("delete from events where id=?", id)
|
||||
|
||||
return event
|
||||
}
|
||||
|
||||
public fun create(
|
||||
application_id: String,
|
||||
event_type: EventType,
|
||||
new_status: Int? = null
|
||||
): Event {
|
||||
val id = UUID.randomUUID().toString()
|
||||
|
||||
if (event_type == EventType.StatusUpdate && new_status == null) {
|
||||
throw Exception("When event_type == StatusUpdate new_status must be set")
|
||||
}
|
||||
|
||||
var new_event =
|
||||
Event(id, application_id, event_type.value, new_status, Timestamp(Date().getTime()))
|
||||
|
||||
db.update(
|
||||
"insert into events (id, application_id, event_type, new_status) values (?, ?, ? ,?)",
|
||||
new_event.id,
|
||||
new_event.application_id,
|
||||
new_event.event_type,
|
||||
new_event.new_status,
|
||||
)
|
||||
|
||||
return new_event
|
||||
}
|
||||
}
|
||||
@@ -49,3 +49,21 @@ create table if not exists flair_link (
|
||||
application_id text not null,
|
||||
flair_id text not null
|
||||
);
|
||||
|
||||
create table if not exists events (
|
||||
id text primary key,
|
||||
application_id text not null,
|
||||
--
|
||||
-- Event Types
|
||||
--
|
||||
--
|
||||
-- Creation(0),
|
||||
-- StatusUpdate(1),
|
||||
-- Page(2)
|
||||
event_type integer not null,
|
||||
|
||||
-- This only matters when event_type == 1
|
||||
new_status integer,
|
||||
|
||||
time timestamp default current_timestamp
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user