| @@ -35,11 +35,16 @@ dependencies { | |||||
| implementation group: 'jakarta.validation', name: 'jakarta.validation-api', version: '3.0.2' | implementation group: 'jakarta.validation', name: 'jakarta.validation-api', version: '3.0.2' | ||||
| implementation group: 'com.fasterxml.jackson.dataformat', name: 'jackson-dataformat-yaml', version: '2.15.2' | implementation group: 'com.fasterxml.jackson.dataformat', name: 'jackson-dataformat-yaml', version: '2.15.2' | ||||
| implementation group: 'com.fasterxml.jackson.core', name: 'jackson-databind', version: '2.15.2' | implementation group: 'com.fasterxml.jackson.core', name: 'jackson-databind', version: '2.15.2' | ||||
| implementation group: 'com.fasterxml.jackson.module', name: 'jackson-module-kotlin', version: '2.15.2' | |||||
| implementation group: 'io.jsonwebtoken', name: 'jjwt-api', version: '0.11.5' | implementation group: 'io.jsonwebtoken', name: 'jjwt-api', version: '0.11.5' | ||||
| implementation group: 'io.jsonwebtoken', name: 'jjwt-impl', version: '0.11.5' | implementation group: 'io.jsonwebtoken', name: 'jjwt-impl', version: '0.11.5' | ||||
| implementation group: 'io.jsonwebtoken', name: 'jjwt-jackson', version: '0.11.5' | implementation group: 'io.jsonwebtoken', name: 'jjwt-jackson', version: '0.11.5' | ||||
| implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8" | |||||
| implementation "org.jetbrains.kotlin:kotlin-reflect" | |||||
| compileOnly group: 'jakarta.servlet', name: 'jakarta.servlet-api', version: '6.0.0' | compileOnly group: 'jakarta.servlet', name: 'jakarta.servlet-api', version: '6.0.0' | ||||
| runtimeOnly 'com.mysql:mysql-connector-j' | runtimeOnly 'com.mysql:mysql-connector-j' | ||||
| @@ -47,7 +52,6 @@ dependencies { | |||||
| testImplementation 'org.springframework.boot:spring-boot-starter-test' | testImplementation 'org.springframework.boot:spring-boot-starter-test' | ||||
| testImplementation 'org.springframework.security:spring-security-test' | testImplementation 'org.springframework.security:spring-security-test' | ||||
| implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8" | |||||
| } | } | ||||
| configurations { | configurations { | ||||
| @@ -1,20 +1,24 @@ | |||||
| package com.ffii.tsms.modules.project.entity | package com.ffii.tsms.modules.project.entity | ||||
| import com.ffii.core.entity.BaseEntity | import com.ffii.core.entity.BaseEntity | ||||
| import jakarta.persistence.Column | |||||
| import jakarta.persistence.Entity | |||||
| import jakarta.persistence.Table | |||||
| import jakarta.persistence.* | |||||
| import jakarta.validation.constraints.NotNull | |||||
| import org.hibernate.proxy.HibernateProxy | import org.hibernate.proxy.HibernateProxy | ||||
| @Entity | @Entity | ||||
| @Table(name = "task") | @Table(name = "task") | ||||
| open class Task : BaseEntity<Long>() { | open class Task : BaseEntity<Long>() { | ||||
| @NotNull | |||||
| @Column(name = "name") | @Column(name = "name") | ||||
| open var name: String? = null | open var name: String? = null | ||||
| @Column(name = "description") | @Column(name = "description") | ||||
| open var description: String? = null | open var description: String? = null | ||||
| @ManyToOne | |||||
| @JoinColumn(name = "taskGroupId") | |||||
| open var taskGroup: TaskGroup? = null | |||||
| final override fun equals(other: Any?): Boolean { | final override fun equals(other: Any?): Boolean { | ||||
| if (this === other) return true | if (this === other) return true | ||||
| if (other == null) return false | if (other == null) return false | ||||
| @@ -0,0 +1,13 @@ | |||||
| package com.ffii.tsms.modules.project.entity | |||||
| import com.ffii.core.entity.IdEntity | |||||
| import jakarta.persistence.Column | |||||
| import jakarta.persistence.Entity | |||||
| import jakarta.persistence.Table | |||||
| @Entity | |||||
| @Table(name = "task_group") | |||||
| open class TaskGroup : IdEntity<Long>() { | |||||
| @Column(name = "name") | |||||
| open var name: String? = null | |||||
| } | |||||
| @@ -19,5 +19,6 @@ open class TaskTemplate : IdEntity<Long>() { | |||||
| @JoinTable(name = "task_template_tasks", | @JoinTable(name = "task_template_tasks", | ||||
| joinColumns = [JoinColumn(name = "taskTemplateId")], | joinColumns = [JoinColumn(name = "taskTemplateId")], | ||||
| inverseJoinColumns = [JoinColumn(name = "tasksId")]) | inverseJoinColumns = [JoinColumn(name = "tasksId")]) | ||||
| open var tasks: MutableSet<Task> = mutableSetOf() | |||||
| @OrderBy | |||||
| open var tasks: MutableList<Task> = mutableListOf() | |||||
| } | } | ||||
| @@ -0,0 +1,31 @@ | |||||
| package com.ffii.tsms.modules.project.service | |||||
| import com.ffii.tsms.modules.project.entity.Task | |||||
| import com.ffii.tsms.modules.project.entity.TaskRepository | |||||
| import com.ffii.tsms.modules.project.entity.TaskTemplate | |||||
| import com.ffii.tsms.modules.project.entity.TaskTemplateRepository | |||||
| import org.springframework.stereotype.Service | |||||
| @Service | |||||
| class TasksService( | |||||
| private val taskTemplateRepository: TaskTemplateRepository, | |||||
| private val taskRepository: TaskRepository | |||||
| ) { | |||||
| fun allTasks(): List<Task> { | |||||
| return taskRepository.findAll() | |||||
| } | |||||
| fun allTaskTemplates(): List<TaskTemplate> { | |||||
| return taskTemplateRepository.findAll() | |||||
| } | |||||
| fun saveTaskTemplate(code: String, name: String, taskIds: List<Long>): TaskTemplate { | |||||
| return taskTemplateRepository.save<TaskTemplate>( | |||||
| TaskTemplate().apply { | |||||
| this.name = name | |||||
| this.code = code | |||||
| this.tasks = taskRepository.findAllById(taskIds) | |||||
| } | |||||
| ) | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,14 @@ | |||||
| package com.ffii.tsms.modules.project.web | |||||
| import org.springframework.web.bind.annotation.GetMapping | |||||
| import org.springframework.web.bind.annotation.RequestMapping | |||||
| import org.springframework.web.bind.annotation.RestController | |||||
| @RestController | |||||
| @RequestMapping("/projects") | |||||
| class ProjectsController { | |||||
| @GetMapping | |||||
| fun allProjects() { | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,35 @@ | |||||
| package com.ffii.tsms.modules.project.web | |||||
| import com.ffii.tsms.modules.project.entity.Task | |||||
| import com.ffii.tsms.modules.project.entity.TaskTemplate | |||||
| import com.ffii.tsms.modules.project.service.TasksService | |||||
| import com.ffii.tsms.modules.project.web.models.NewTaskTemplateRequest | |||||
| import jakarta.validation.Valid | |||||
| import org.springframework.web.bind.annotation.GetMapping | |||||
| import org.springframework.web.bind.annotation.PostMapping | |||||
| import org.springframework.web.bind.annotation.RequestBody | |||||
| import org.springframework.web.bind.annotation.RequestMapping | |||||
| import org.springframework.web.bind.annotation.RestController | |||||
| @RestController | |||||
| @RequestMapping("/tasks") | |||||
| class TasksController(private val tasksService: TasksService) { | |||||
| @GetMapping | |||||
| fun allTasks(): List<Task> { | |||||
| return tasksService.allTasks() | |||||
| } | |||||
| @GetMapping("/templates") | |||||
| fun allTaskTemplates(): List<TaskTemplate> { | |||||
| return tasksService.allTaskTemplates() | |||||
| } | |||||
| @PostMapping("/templates/new") | |||||
| fun saveTaskTemplate(@Valid @RequestBody newTaskTemplate: NewTaskTemplateRequest): TaskTemplate { | |||||
| return tasksService.saveTaskTemplate( | |||||
| newTaskTemplate.code, | |||||
| newTaskTemplate.name, | |||||
| newTaskTemplate.taskIds | |||||
| ) | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,11 @@ | |||||
| package com.ffii.tsms.modules.project.web.models | |||||
| import jakarta.validation.constraints.NotBlank | |||||
| data class NewTaskTemplateRequest( | |||||
| @field:NotBlank(message = "code cannot be empty") | |||||
| val code: String, | |||||
| @field:NotBlank(message = "name cannot be empty") | |||||
| val name: String, | |||||
| val taskIds: List<Long> = emptyList() | |||||
| ) | |||||
| @@ -1,6 +1,12 @@ | |||||
| -- liquibase formatted sql | -- liquibase formatted sql | ||||
| -- changeset wayne:task | -- changeset wayne:task | ||||
| CREATE TABLE task_group ( | |||||
| id INT NOT NULL AUTO_INCREMENT, | |||||
| name VARCHAR(255) NULL, | |||||
| CONSTRAINT pk_task_group PRIMARY KEY (id) | |||||
| ); | |||||
| CREATE TABLE task ( | CREATE TABLE task ( | ||||
| id INT NOT NULL AUTO_INCREMENT, | id INT NOT NULL AUTO_INCREMENT, | ||||
| version INT NOT NULL DEFAULT '0', | version INT NOT NULL DEFAULT '0', | ||||
| @@ -9,11 +15,14 @@ CREATE TABLE task ( | |||||
| modified datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, | modified datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, | ||||
| modifiedBy VARCHAR(30) NULL, | modifiedBy VARCHAR(30) NULL, | ||||
| deleted TINYINT(1) NOT NULL DEFAULT '0', | deleted TINYINT(1) NOT NULL DEFAULT '0', | ||||
| name VARCHAR(255) NULL, | |||||
| name VARCHAR(255) NOT NULL, | |||||
| `description` VARCHAR(255) NULL, | `description` VARCHAR(255) NULL, | ||||
| taskGroupId INT NULL, | |||||
| CONSTRAINT pk_task PRIMARY KEY (id) | CONSTRAINT pk_task PRIMARY KEY (id) | ||||
| ); | ); | ||||
| ALTER TABLE task ADD CONSTRAINT FK_TASK_ON_TASKGROUPID FOREIGN KEY (taskGroupId) REFERENCES task_group (id); | |||||
| CREATE TABLE task_template ( | CREATE TABLE task_template ( | ||||
| id INT NOT NULL AUTO_INCREMENT, | id INT NOT NULL AUTO_INCREMENT, | ||||
| code VARCHAR(255) NOT NULL, | code VARCHAR(255) NOT NULL, | ||||
| @@ -0,0 +1,63 @@ | |||||
| -- liquibase formatted sql | |||||
| -- changeset wayne:task_data | |||||
| INSERT | |||||
| INTO | |||||
| task_group | |||||
| (name) | |||||
| VALUES | |||||
| ('1. Design & Cost Planning / Estimating'), | |||||
| ('2. Tender Documentation'), | |||||
| ('3. Tender Analysis & Report & Contract Documentation'), | |||||
| ('4. Construction / Post Construction'), | |||||
| ('5. Miscellaneous'); | |||||
| INSERT | |||||
| INTO | |||||
| task | |||||
| (name, taskGroupId) | |||||
| VALUES | |||||
| ('1.1 Preparation of preliminary Cost Estimate / Cost Plan including Revised & Refined', 1), | |||||
| ('1.2 Cash flow forecast', 1), | |||||
| ('1.3 Cost studies for alternative design solutions', 1), | |||||
| ('1.4 Attend design co-ordination / project review meetings', 1), | |||||
| ('1.5 Prepare / Review RIC', 1), | |||||
| ('2.1 Advise on tendering & contractual arrangement', 2), | |||||
| ('2.2 Drafting / Vetting front-parts (incl. Main Contract, Sub-contracts & Direct Contracts)', 2), | |||||
| ('2.3 Carry out pre-qualification exercise / EOI', 2), | |||||
| ('2.4 Measurement (incl. billing of items) for Works Packages', 2), | |||||
| ('2.5 Measurement (incl. billing of items) for tender addendum for Works Packages', 2), | |||||
| ('2.6 Bulk Checking of Bills of Quantities', 2), | |||||
| ('2.7 Line through drawings & specifications to check against Bills of Quantities / SOR', 2), | |||||
| ('2.8 Update cash flow forecast', 2), | |||||
| ('2.9 Edit tender documents (Incl. Bills of Quantities / SOR)', 2), | |||||
| ('2.10 Preparation of pre-tender estimates', 2), | |||||
| ('2.11 Attend design co-ordination / project review meetings / project meetings', 2), | |||||
| ('3.1 Evaluation of tenders (incl. arithmetical checking, submission checking, etc)', 3), | |||||
| ('3.2 Preparation of 3-rates bills', 3), | |||||
| ('3.3 Preparation of Report on Tenderers (incl. three-rates bills)', 3), | |||||
| ('3.4 Preparation of tender queries', 3), | |||||
| ('3.5 Attend tender interviews', 3), | |||||
| ('3.6 Draft Letter of Acceptance / Award', 3), | |||||
| ('3.7 Preparation of Contract Documents for Works Packages', 3), | |||||
| ('4.1 Check insurance policies, surety bond, guarantee, etc.', 4), | |||||
| ('4.2 Valuation of works completed for progress payment (incl. site visits)', 4), | |||||
| ('4.3 Preparation of financial statements (incl. cash flow forecasts)', 4), | |||||
| ('4.4 Cost check / advice on a alternative design solutions', 4), | |||||
| ('4.5 Cost estimate for draft AIs/EIs/SIs', 4), | |||||
| ('4.6 Advise on contractual issues & evaluate monetary contractual claim', 4), | |||||
| ('4.7 Attend site meetings / project co-ordination meetings / project meetings', 4), | |||||
| ('4.8 Measurement & valuation of variations / prime cost & provisional sums', 4), | |||||
| ('4.9 Negotiation and settlement of final accounts (incl. meetings)', 4), | |||||
| ('4.10 Preparation of Statement of Final Account', 4), | |||||
| ('4.11 Preparation of Cost Analysis for the Completed project', 4), | |||||
| ('4.12 Check / Review draft final bills', 4), | |||||
| ('4.13 Carry out site check for draft final bills', 4), | |||||
| ('5.1 Preparation of Fee Proposal / Expression of Interest', 5), | |||||
| ('5.2 Attend Management Meeting / Management Workshop', 5), | |||||
| ('5.3 Preparation of project budget i.e. manhours vs fee receivables', 5), | |||||
| ('5.4 Attend Local / International Conference / Seminar / Webinar', 5); | |||||
| @@ -0,0 +1,57 @@ | |||||
| -- liquibase formatted sql | |||||
| -- changeset wayne:mock_task_templates | |||||
| INSERT INTO task_template (code,name) VALUES | |||||
| ('Pre-001','Pre-contract Template'), | |||||
| ('Post-001','Post-contract Template'), | |||||
| ('Full-001','Full Project Template'); | |||||
| INSERT INTO task_template_tasks (taskTemplateId,tasksId) VALUES | |||||
| (1,1), | |||||
| (2,1), | |||||
| (3,1), | |||||
| (1,2), | |||||
| (3,2), | |||||
| (1,3), | |||||
| (2,3), | |||||
| (3,3), | |||||
| (3,4), | |||||
| (3,5), | |||||
| (1,6), | |||||
| (3,6), | |||||
| (1,7), | |||||
| (3,7), | |||||
| (3,8), | |||||
| (3,9), | |||||
| (3,10), | |||||
| (3,11), | |||||
| (3,12), | |||||
| (3,13), | |||||
| (3,14), | |||||
| (3,15), | |||||
| (3,16), | |||||
| (3,17), | |||||
| (3,18), | |||||
| (3,19), | |||||
| (3,20), | |||||
| (3,21), | |||||
| (3,22), | |||||
| (3,23), | |||||
| (3,24), | |||||
| (3,25), | |||||
| (3,26), | |||||
| (3,27), | |||||
| (3,28), | |||||
| (3,29), | |||||
| (3,30), | |||||
| (3,31), | |||||
| (3,32), | |||||
| (3,33), | |||||
| (3,34), | |||||
| (3,35), | |||||
| (3,36), | |||||
| (3,37), | |||||
| (3,38), | |||||
| (3,39), | |||||
| (3,40); | |||||