feat: finish #3 #4

This commit is contained in:
2024-10-16 08:38:12 +01:00
parent 62961363f3
commit f257bce4b0
9 changed files with 391 additions and 44 deletions

View File

@@ -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() }

View File

@@ -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

View 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
}
}

View File

@@ -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
);