Skip to content
Open
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
38 changes: 38 additions & 0 deletions documents/Zoom-care.postman_collection.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
{
"info": {
"_postman_id": "815913fd-1f1e-481c-aff4-02121dde4d02",
"name": "Zoom-care",
"schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json",
"_exporter_id": "24706689"
},
"item": [
{
"name": "Get Top Employees",
"request": {
"method": "GET",
"header": []
},
"response": []
},
{
"name": "Get Employee by Id",
"request": {
"method": "GET",
"header": [],
"url": {
"raw": "http://localhost:8080/employee/1",
"protocol": "http",
"host": [
"localhost"
],
"port": "8080",
"path": [
"employee",
"1"
]
}
},
"response": []
}
]
}
12 changes: 12 additions & 0 deletions documents/development-notes.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
Development notes:

This challenge was solved by creating two GET API calls:

This will be returning all top employee
{host}/employee
This will be returning a specific employee by providing the id into the url
{host}/employee/{id}
Please see on /documents folder, I did include a PostMan Collection with API calls examples
File: Zoom-care.postman_collection.json

Notes: I did face some issues with browser cache data, in order to perform further test I did add some extra test data on /src/main/db/migration/ V2__initial_data_structures.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package com.zoomcare.candidatechallenge.controller;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;

import com.zoomcare.candidatechallenge.employee.EmployeeJdbc;
/**
* @author Pabel Lopez
*/

@RestController
public class EmployeeController {

@Autowired
EmployeeJdbc repository;

@GetMapping("employee/{id}")
public List getEmployeeById (@PathVariable final long id){
return repository.getEmployeeById(id);
}

@GetMapping("employee/")
public List getTopLevelEmployees (){
return repository.getTopLevelEmployees();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package com.zoomcare.candidatechallenge.employee;

import java.util.List;
import java.util.Map;
/**
* @author Pabel Lopez
*/

public class EmployeeBean {
private long id;
private List<Map<String,String>> properties;
private List<List<Map<String,String>>> reportList ;
public EmployeeBean (){
}

public EmployeeBean(long id, List<Map<String, String>> properties) {
this.id = id;
this.properties = properties;
}

public long getId() {
return id;
}

public List<Map<String, String>> getProperties() {
return properties;
}

public List<List<Map<String, String>>> getReportList() {
return reportList;
}

public void setId(long id) {
this.id = id;
}

public void setProperties(List<Map<String, String>> properties) {
this.properties = properties;
}

public void setReportList(List<List<Map<String, String>>> reportList) {
this.reportList = reportList;
}

@Override
public String toString() {
return "EmployeeBean [id=" + id + ", properties=" + properties + ", reportList=" + reportList + "]";
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
package com.zoomcare.candidatechallenge.employee;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Repository;
/**
* @author Pabel Lopez
*/

@Repository
public class EmployeeJdbc {
@Autowired
JdbcTemplate jdbcTemplate;

private String SELECT_EMPLOYEE_BY_ID ="select * from employee where id=?";
private String SELECT_CATEGORIES = "select * from property where employee_id=?";
private String SELECT_REPORT_STRUCTURE = "select id from employee where supervisor_id=?";
private String SELECT_TOP_EMPLOYEES = "select id from employee where supervisor_id is null";

/**
* <p> Return all top level employees</p>
@return A list wit all top level Employees
*/
public List <EmployeeBean> getTopLevelEmployees (){
List<EmployeeBean> topEmpList = new ArrayList<>();
List<Map<String,Object>> list = jdbcTemplate.queryForList(SELECT_TOP_EMPLOYEES);
for (int i=0; i<list.size();i++){
Map<String,Object> topEmployee= list.get(i);
EmployeeBean employee = getEmployeeById((Long)topEmployee.get("id")).get(0);
topEmpList.add(employee);
}
return topEmpList;
}

/**
* <p> Return a specific Employee based on provided id</p>
@param id The id of the employee to be retrieved
@return A list of employee properties and nested reporting structure
*/
public List <EmployeeBean> getEmployeeById(long id){
List<Map<String,Object>> list = jdbcTemplate.queryForList(SELECT_EMPLOYEE_BY_ID, id);
List<EmployeeBean> empList = new ArrayList<>();

list.forEach(item -> {
List<Map<String,String>> propertyList = new ArrayList<>();
List<List<Map<String,String>>> reportLi;
EmployeeBean employee = new EmployeeBean();

employee.setId((Long)item.get("id"));
propertyList = getProperties(id);
reportLi = getNestedReport(id);
if (reportLi.size()>0){
employee.setReportList(reportLi);
}
if (propertyList.size()>0){
employee.setProperties(propertyList);
}
empList.add(employee);
});
return empList;
}

/**
* <p> Return all the properties of one employee based on provided id</p>
@param id The id of the employee to be retrieved
@return A list containing the map<key,value> of all properties of employee
*/
private List<Map<String,String>> getProperties (long id){
List<Map<String,String>> properties = new ArrayList<>();
List<Map<String,Object>> propertiesList = jdbcTemplate.queryForList(SELECT_CATEGORIES, id);

propertiesList.forEach(property ->{
Map <String,String> map = new HashMap<String,String>();
map.put("key", (String) property.get("key"));
map.put("value", (String) property.get("value"));
properties.add(map);
});

return properties;
}

/**
* <p> Return a list with all nested employee related to the provided supervidor</p>
@param id The id of the supervisor to get the nested organization
@return A list containing the map<key,value> of all reported employees of the supervisor provided
*/
private List<List<Map<String,String>>> getNestedReport (long id){
List<List<Map<String,String>>> reportList = new ArrayList<List<Map<String,String>>>();
List<Map<String,Object>> list = jdbcTemplate.queryForList(SELECT_REPORT_STRUCTURE, id);
if (list.size()>0){
list.forEach(item ->{
List<List<Map<String,String>>> innerReportList;
List<Map<String,String>> subReport = new ArrayList<Map<String,String>>();
Map <String,String> map = new HashMap<String,String>();
map.put("supervisor_id", String.valueOf(id));
map.put("employee_id", String.valueOf(item.get("id")));
subReport.add(map);
reportList.add(subReport);
innerReportList = getNestedReport ((Long)item.get("id"));
if (innerReportList.size()>0){
innerReportList.forEach(sub ->{
for (int i=0; i<sub.size();i++){
subReport.add(sub.get(i));
}
});
}

});
}
return reportList;
}
}
4 changes: 4 additions & 0 deletions src/main/resources/application.properties
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# Enabling H2 Console
spring.h2.console.enabled=true
#set JDBC path to DB
spring.datasource.url=jdbc:h2:mem:testdb
15 changes: 14 additions & 1 deletion src/main/resources/db/migration/V2__initial_data_structures.sql
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@ insert into employee values ();
select @ceo := scope_identity();
insert into property (employee_id, key, value) values (@ceo, 'title', 'CEO');

insert into employee values ();
select @cio := scope_identity();
insert into property (employee_id, key, value) values (@cio, 'title', 'CIO');

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');
Expand Down Expand Up @@ -36,4 +40,13 @@ insert into property (employee_id, key, value) values (@namarketing, 'region', '
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');
insert into property (employee_id, key, value) values (@eumarketing, 'region', 'Europe');

insert into employee(supervisor_id) values (@cio);
select @latamketing := scope_identity();
insert into property (employee_id, key, value) values (@latamketing, 'title', 'Regional Director of Marketing');
insert into property (employee_id, key, value) values (@latamketing, 'region', 'Latin America');

insert into employee values ();
select @inversor := scope_identity();
insert into property (employee_id, key, value) values (@inversor, 'title', 'Investment Director');