diff --git a/pom.xml b/pom.xml index 17fd7ad..1691ec0 100644 --- a/pom.xml +++ b/pom.xml @@ -1,11 +1,11 @@ + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 org.springframework.boot spring-boot-starter-parent - 2.1.3.RELEASE + 2.7.7 com.zoomcare @@ -23,6 +23,10 @@ org.springframework.boot spring-boot-starter-actuator + + org.springframework.boot + spring-boot-starter-data-jpa + org.springframework.boot spring-boot-starter-data-jdbc @@ -31,19 +35,22 @@ org.springframework.boot spring-boot-starter-web - + + org.springframework.boot + spring-boot-devtools + runtime + true + org.flywaydb flyway-core runtime - com.h2database h2 runtime - org.springframework.boot spring-boot-starter-test @@ -60,4 +67,4 @@ - + \ No newline at end of file diff --git a/src/main/java/com/zoomcare/candidatechallenge/controller/CrudController.java b/src/main/java/com/zoomcare/candidatechallenge/controller/CrudController.java new file mode 100644 index 0000000..e43d554 --- /dev/null +++ b/src/main/java/com/zoomcare/candidatechallenge/controller/CrudController.java @@ -0,0 +1,109 @@ +package com.zoomcare.candidatechallenge.controller; + +import com.zoomcare.candidatechallenge.entity.Employee; +import com.zoomcare.candidatechallenge.entity.Property; +import com.zoomcare.candidatechallenge.exception.EmployeeNotFoundException; +import com.zoomcare.candidatechallenge.exception.PropertyNotFoundException; +import com.zoomcare.candidatechallenge.repository.EmployeeRepository; +import com.zoomcare.candidatechallenge.repository.PropertiesRepository; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; + +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; + +@RestController +public class CrudController { + // , ; + + @Autowired + private EmployeeRepository employeeRepository; + + @Autowired + private PropertiesRepository propertiesRepository; + + // Employee + @PostMapping("/api/employees") + public ResponseEntity createEmployee(@RequestBody Employee employee) { + + Employee _employee = employeeRepository.save(new Employee(employee.getSupervisor_id())); + + return new ResponseEntity<>(_employee, HttpStatus.CREATED); + } + + @GetMapping("/api/employees") + public ResponseEntity> getAllEmployees() { + List lemployees = new ArrayList(); + employeeRepository.findAll().forEach(lemployees::add); + + if (lemployees.isEmpty()) { + return new ResponseEntity<>(HttpStatus.NO_CONTENT); + } + + return new ResponseEntity<>(lemployees, HttpStatus.OK); + } + + @GetMapping("/api/employees/{id}") + public ResponseEntity getEmployeeById(@PathVariable("id") long id) { + + Optional employee = employeeRepository.findById(id); + + if(!employee.isPresent()) { + throw new EmployeeNotFoundException("Book with Id = " + id + " not found"); + } + + return new ResponseEntity(employee.get(), HttpStatus.OK); + } + + @PutMapping("/api/employees/{id}") + public ResponseEntity updateEmployee(@PathVariable("id") long id, @RequestBody Employee employee) { + + Optional _employee = employeeRepository.findById(id); + + if(!_employee.isPresent()) { + throw new EmployeeNotFoundException("Employee with Id = " + id + " not found."); + } + + _employee.get().setSupervisor_id(employee.getSupervisor_id()); + + return new ResponseEntity<>(employeeRepository.save(_employee.get()), HttpStatus.OK); + } + + @DeleteMapping("/api/books/{id}") + public ResponseEntity deleteEmployee(@PathVariable("id") long id) { + + Optional employee = employeeRepository.findById(id); + + if(!employee.isPresent()) { + throw new EmployeeNotFoundException("Employee id = " + id + " not found."); + } + + employeeRepository.deleteById(id); + + return new ResponseEntity<>(HttpStatus.NO_CONTENT); + } + + //Properties + @PostMapping("/api/employees/{employeeId}/properties") + public ResponseEntity createProperty(@PathVariable(value = "employeeId") Long employeeId, @RequestBody Property properties) { + + Property _properties = employeeRepository.findById(employeeId).map(emp -> { // Ojo con el map + properties.setEmployee(emp); + return propertiesRepository.save(properties); + }).orElseThrow(() -> new EmployeeNotFoundException("Not found Book with id = " + employeeId)); + + return new ResponseEntity<>(_properties, HttpStatus.CREATED); + } + + @GetMapping("/api/properties/{id}") + public ResponseEntity getPropertiesById(@PathVariable(value = "id") Long id) { + + Property _properties = propertiesRepository.findById(id) + .orElseThrow(() -> new PropertyNotFoundException("Property not found with id = " + id)); + + return new ResponseEntity<>(_properties, HttpStatus.OK); + } +} diff --git a/src/main/java/com/zoomcare/candidatechallenge/entity/Employee.java b/src/main/java/com/zoomcare/candidatechallenge/entity/Employee.java new file mode 100644 index 0000000..944ad71 --- /dev/null +++ b/src/main/java/com/zoomcare/candidatechallenge/entity/Employee.java @@ -0,0 +1,42 @@ +package com.zoomcare.candidatechallenge.entity; + +import javax.persistence.*; + +@Entity +@Table(name = "employee") +public class Employee { + @Id + @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "employee_generator") + private Long id; + private Long supervisor_id; + + public Employee() {} + + public Employee(Long supervisor_id) { + this.supervisor_id = supervisor_id; + } + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public Long getSupervisor_id() { + return supervisor_id; + } + + public void setSupervisor_id(Long supervisor_id) { + this.supervisor_id = supervisor_id; + } + + @Override + public String toString() { + return "Employee{" + + "id=" + id + + ", supervisor_id=" + supervisor_id + + '}'; + } +} diff --git a/src/main/java/com/zoomcare/candidatechallenge/entity/Property.java b/src/main/java/com/zoomcare/candidatechallenge/entity/Property.java new file mode 100644 index 0000000..ddbf822 --- /dev/null +++ b/src/main/java/com/zoomcare/candidatechallenge/entity/Property.java @@ -0,0 +1,58 @@ +package com.zoomcare.candidatechallenge.entity; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import org.hibernate.annotations.OnDelete; +import org.hibernate.annotations.OnDeleteAction; + +import javax.persistence.*; + +@Entity +@Table(name = "property") +public class Property { + @Id + @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "properties_generator") + private Long property_id; + + @ManyToOne(fetch = FetchType.LAZY, optional = false) + @JoinColumn(name = "employee_id", nullable = false) + @OnDelete(action = OnDeleteAction.CASCADE) + @JsonIgnore + private Employee employee; + + private String mykey; + private String myvalue; + + public Property() {} + + public Long getProperty_id() { + return property_id; + } + + public void setProperty_id(Long property_id) { + this.property_id = property_id; + } + + public String getMykey() { + return mykey; + } + + public void setMykey(String mykey) { + this.mykey = mykey; + } + + public String getMyvalue() { + return myvalue; + } + + public void setMyvalue(String myvalue) { + this.myvalue = myvalue; + } + + public Employee getEmployee() { + return employee; + } + + public void setEmployee(Employee employee) { + this.employee = employee; + } +} diff --git a/src/main/java/com/zoomcare/candidatechallenge/exception/EmployeeNotFoundException.java b/src/main/java/com/zoomcare/candidatechallenge/exception/EmployeeNotFoundException.java new file mode 100644 index 0000000..bc137d0 --- /dev/null +++ b/src/main/java/com/zoomcare/candidatechallenge/exception/EmployeeNotFoundException.java @@ -0,0 +1,11 @@ +package com.zoomcare.candidatechallenge.exception; + +import org.springframework.http.HttpStatus; +import org.springframework.web.bind.annotation.ResponseStatus; + +@ResponseStatus(HttpStatus.NOT_FOUND) +public class EmployeeNotFoundException extends RuntimeException { + public EmployeeNotFoundException(String msg) { + super(msg); + } +} diff --git a/src/main/java/com/zoomcare/candidatechallenge/exception/PropertyNotFoundException.java b/src/main/java/com/zoomcare/candidatechallenge/exception/PropertyNotFoundException.java new file mode 100644 index 0000000..a89db12 --- /dev/null +++ b/src/main/java/com/zoomcare/candidatechallenge/exception/PropertyNotFoundException.java @@ -0,0 +1,11 @@ +package com.zoomcare.candidatechallenge.exception; + +import org.springframework.http.HttpStatus; +import org.springframework.web.bind.annotation.ResponseStatus; + +@ResponseStatus(HttpStatus.NOT_FOUND) +public class PropertyNotFoundException extends RuntimeException { + public PropertyNotFoundException(String msg) { + super(msg); + } +} diff --git a/src/main/java/com/zoomcare/candidatechallenge/repository/EmployeeRepository.java b/src/main/java/com/zoomcare/candidatechallenge/repository/EmployeeRepository.java new file mode 100644 index 0000000..0c1caeb --- /dev/null +++ b/src/main/java/com/zoomcare/candidatechallenge/repository/EmployeeRepository.java @@ -0,0 +1,10 @@ +package com.zoomcare.candidatechallenge.repository; + +import com.zoomcare.candidatechallenge.entity.Employee; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +@Repository +public interface EmployeeRepository extends JpaRepository { + +} diff --git a/src/main/java/com/zoomcare/candidatechallenge/repository/PropertiesRepository.java b/src/main/java/com/zoomcare/candidatechallenge/repository/PropertiesRepository.java new file mode 100644 index 0000000..e560571 --- /dev/null +++ b/src/main/java/com/zoomcare/candidatechallenge/repository/PropertiesRepository.java @@ -0,0 +1,16 @@ +package com.zoomcare.candidatechallenge.repository; + +import com.zoomcare.candidatechallenge.entity.Property; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +import javax.transaction.Transactional; +import java.util.List; + +@Repository +public interface PropertiesRepository extends JpaRepository { + List findByEmployeeId(Long id); + + @Transactional + void deleteByEmployeeId(long id); +} diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties new file mode 100644 index 0000000..8c24bd2 --- /dev/null +++ b/src/main/resources/application.properties @@ -0,0 +1,4 @@ +spring.datasource.url=jdbc:h2:mem:testdb +spring.data.jpa.repositories.bootstrap-mode=default +spring.jpa.show-sql=true +spring.h2.console.enabled=true \ No newline at end of file diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml deleted file mode 100644 index 4408d17..0000000 --- a/src/main/resources/application.yml +++ /dev/null @@ -1,12 +0,0 @@ -spring: - h2: - console: - enabled: true -management: - endpoints: - web: - exposure: - include: "*" - endpoint: - health: - show-details: always \ No newline at end of file diff --git a/src/main/resources/db/migration/V1__init.sql b/src/main/resources/db/migration/V1__init.sql deleted file mode 100644 index 47eb795..0000000 --- a/src/main/resources/db/migration/V1__init.sql +++ /dev/null @@ -1,14 +0,0 @@ -create table employee ( - id bigint(20) not null auto_increment, - supervisor_id bigint(20), - primary key (id), - foreign key (supervisor_id) references employee(id) -); - -create table property ( - employee_id bigint(20) not null, - key varchar(256), - value varchar(256), - primary key (employee_id, key), - foreign key (employee_id) references employee(id) -); \ No newline at end of file diff --git a/src/main/resources/db/migration/V2__initial_data_structures.sql b/src/main/resources/db/migration/V2__initial_data_structures.sql deleted file mode 100644 index a7a0745..0000000 --- a/src/main/resources/db/migration/V2__initial_data_structures.sql +++ /dev/null @@ -1,39 +0,0 @@ -insert into employee values (); -select @ceo := scope_identity(); -insert into property (employee_id, key, value) values (@ceo, 'title', 'CEO'); - -insert into employee (supervisor_id) values (@ceo); -select @vpsales := scope_identity(); -insert into property (employee_id, key, value) values (@vpsales, 'title', 'Vice President of Sales'); - -insert into employee(supervisor_id) values (@vpsales); -select @nasales := scope_identity(); -insert into property (employee_id, key, value) values (@nasales, 'title', 'Regional Director of Sales'); -insert into property (employee_id, key, value) values (@nasales, 'region', 'North America'); - -insert into employee(supervisor_id) values (@nasales); -select @salesrep1 := scope_identity(); -insert into property (employee_id, key, value) values (@salesrep1, 'title', 'Sales Representative'); - -insert into employee(supervisor_id) values (@vpsales); -select @eusales := scope_identity(); -insert into property (employee_id, key, value) values (@eusales, 'title', 'Regional Director of Sales'); -insert into property (employee_id, key, value) values (@eusales, 'region', 'Europe'); - -insert into employee (supervisor_id) values (@ceo); -select @vpp := scope_identity(); -insert into property (employee_id, key, value) values (@vpp, 'title', 'Vice President of People'); - -insert into employee (supervisor_id) values (@ceo); -select @vpm := scope_identity(); -insert into property (employee_id, key, value) values (@vpm, 'title', 'Vice President of Marketing'); - -insert into employee(supervisor_id) values (@vpm); -select @namarketing := scope_identity(); -insert into property (employee_id, key, value) values (@namarketing, 'title', 'Regional Director of Marketing'); -insert into property (employee_id, key, value) values (@namarketing, 'region', 'North America'); - -insert into employee(supervisor_id) values (@vpm); -select @eumarketing := scope_identity(); -insert into property (employee_id, key, value) values (@eumarketing, 'title', 'Regional Director of Marketing'); -insert into property (employee_id, key, value) values (@eumarketing, 'region', 'Europe'); \ No newline at end of file