Merge branch '81-custom-endpoints' into 'master'
Resolve "Custom endpoints" Closes #81 See merge request marcel.schwarz/2020ss-qbc-geofence-timetracking!59
This commit is contained in:
commit
ed284da1ac
@ -0,0 +1,60 @@
|
|||||||
|
package de.hft.geotime.controllers;
|
||||||
|
|
||||||
|
import de.hft.geotime.entities.RecordType;
|
||||||
|
import de.hft.geotime.entities.TimeRecord;
|
||||||
|
import de.hft.geotime.entities.TimetrackAccount;
|
||||||
|
import de.hft.geotime.repositories.RecordRepository;
|
||||||
|
import de.hft.geotime.repositories.TimetrackAccountRepository;
|
||||||
|
import org.springframework.data.domain.Page;
|
||||||
|
import org.springframework.http.HttpStatus;
|
||||||
|
import org.springframework.http.ResponseEntity;
|
||||||
|
import org.springframework.security.core.Authentication;
|
||||||
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestParam;
|
||||||
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
|
@RestController
|
||||||
|
public class RecordController {
|
||||||
|
|
||||||
|
private final RecordRepository recordRepository;
|
||||||
|
private final TimetrackAccountRepository accountRepository;
|
||||||
|
|
||||||
|
public RecordController(RecordRepository recordRepository, TimetrackAccountRepository accountRepository) {
|
||||||
|
this.recordRepository = recordRepository;
|
||||||
|
this.accountRepository = accountRepository;
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping("/track")
|
||||||
|
public ResponseEntity<TimeRecord> track(@RequestParam String account, Authentication authentication) {
|
||||||
|
if (account == null || account.isEmpty()) {
|
||||||
|
return new ResponseEntity<>(HttpStatus.BAD_REQUEST);
|
||||||
|
}
|
||||||
|
|
||||||
|
TimetrackAccount selectedAccount = accountRepository.findByUser_UsernameAndName(authentication.getName(), account);
|
||||||
|
|
||||||
|
if (selectedAccount == null) {
|
||||||
|
return new ResponseEntity<>(HttpStatus.NOT_FOUND);
|
||||||
|
}
|
||||||
|
|
||||||
|
Page<TimeRecord> entires = recordRepository.findAllByEnddateIsNull(null);
|
||||||
|
Optional<TimeRecord> collect = entires.stream()
|
||||||
|
.filter(timeRecord -> timeRecord.getAccount().equals(selectedAccount))
|
||||||
|
.findFirst();
|
||||||
|
|
||||||
|
if (collect.isPresent()) {
|
||||||
|
collect.get().setEnddate(LocalDateTime.now());
|
||||||
|
recordRepository.save(collect.get());
|
||||||
|
return new ResponseEntity<>(collect.get(), HttpStatus.OK);
|
||||||
|
} else {
|
||||||
|
TimeRecord newRecord = new TimeRecord();
|
||||||
|
newRecord.setType(RecordType.PAID);
|
||||||
|
newRecord.setStartdate(LocalDateTime.now());
|
||||||
|
newRecord.setAccount(accountRepository.findByUser_UsernameAndName(authentication.getName(), account));
|
||||||
|
recordRepository.save(newRecord);
|
||||||
|
return new ResponseEntity<>(newRecord, HttpStatus.CREATED);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -5,8 +5,8 @@ import lombok.Data;
|
|||||||
import lombok.NoArgsConstructor;
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
import javax.persistence.*;
|
import javax.persistence.*;
|
||||||
import java.time.Duration;
|
import java.time.LocalDateTime;
|
||||||
import java.util.Date;
|
import java.time.temporal.ChronoUnit;
|
||||||
|
|
||||||
@Data
|
@Data
|
||||||
@NoArgsConstructor
|
@NoArgsConstructor
|
||||||
@ -17,11 +17,24 @@ public class TimeRecord {
|
|||||||
@Id
|
@Id
|
||||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||||
private long id;
|
private long id;
|
||||||
@OneToOne(fetch = FetchType.LAZY)
|
|
||||||
|
@ManyToOne
|
||||||
private TimetrackAccount account;
|
private TimetrackAccount account;
|
||||||
private Date startdate;
|
|
||||||
private Date enddate;
|
@Column(columnDefinition = "TIMESTAMP")
|
||||||
private Duration time;
|
private LocalDateTime startdate;
|
||||||
|
|
||||||
|
@Column(columnDefinition = "TIMESTAMP")
|
||||||
|
private LocalDateTime enddate;
|
||||||
|
|
||||||
private RecordType type;
|
private RecordType type;
|
||||||
|
|
||||||
|
public long getDuration() {
|
||||||
|
if (enddate == null) {
|
||||||
|
return 0;
|
||||||
|
} else {
|
||||||
|
return startdate.until(enddate, ChronoUnit.MINUTES);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
package de.hft.geotime.entities;
|
package de.hft.geotime.entities;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonBackReference;
|
||||||
import lombok.AllArgsConstructor;
|
import lombok.AllArgsConstructor;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import lombok.NoArgsConstructor;
|
import lombok.NoArgsConstructor;
|
||||||
@ -18,6 +19,7 @@ public class TimetrackAccount {
|
|||||||
private double revenue;
|
private double revenue;
|
||||||
private String name;
|
private String name;
|
||||||
private String description;
|
private String description;
|
||||||
|
|
||||||
@ManyToOne
|
@ManyToOne
|
||||||
private TimetrackUser user;
|
private TimetrackUser user;
|
||||||
|
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package de.hft.geotime.entities;
|
package de.hft.geotime.entities;
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonManagedReference;
|
||||||
import lombok.AllArgsConstructor;
|
import lombok.AllArgsConstructor;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import lombok.NoArgsConstructor;
|
import lombok.NoArgsConstructor;
|
||||||
@ -28,12 +29,9 @@ public class TimetrackUser {
|
|||||||
|
|
||||||
private String lastname;
|
private String lastname;
|
||||||
|
|
||||||
@OneToOne(fetch = FetchType.EAGER)
|
@ManyToOne(fetch = FetchType.EAGER)
|
||||||
private Role role;
|
private Role role;
|
||||||
|
|
||||||
@OneToMany(mappedBy = "user", fetch = FetchType.LAZY, cascade = CascadeType.ALL)
|
|
||||||
private List<TimetrackAccount> accounts;
|
|
||||||
|
|
||||||
@ManyToOne
|
@ManyToOne
|
||||||
private Location location;
|
private Location location;
|
||||||
|
|
||||||
|
@ -0,0 +1,27 @@
|
|||||||
|
package de.hft.geotime.entities.projections;
|
||||||
|
|
||||||
|
import de.hft.geotime.entities.TimeRecord;
|
||||||
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
|
import org.springframework.data.rest.core.config.Projection;
|
||||||
|
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
|
||||||
|
@Projection(name = "overview", types = TimeRecord.class)
|
||||||
|
public interface RecordOverviewProjection {
|
||||||
|
|
||||||
|
LocalDateTime getStartdate();
|
||||||
|
|
||||||
|
LocalDateTime getEnddate();
|
||||||
|
|
||||||
|
long getDuration();
|
||||||
|
|
||||||
|
@Value("#{target.type.name()}")
|
||||||
|
String getType();
|
||||||
|
|
||||||
|
@Value("#{target.account.name}")
|
||||||
|
String getAccount();
|
||||||
|
|
||||||
|
@Value("#{target.account.user.username}")
|
||||||
|
String getUsername();
|
||||||
|
|
||||||
|
}
|
@ -1,11 +1,15 @@
|
|||||||
package de.hft.geotime.repositories;
|
package de.hft.geotime.repositories;
|
||||||
|
|
||||||
import de.hft.geotime.entities.TimeRecord;
|
import de.hft.geotime.entities.TimeRecord;
|
||||||
import org.springframework.data.repository.CrudRepository;
|
import org.springframework.data.domain.Page;
|
||||||
|
import org.springframework.data.domain.Pageable;
|
||||||
|
import org.springframework.data.jpa.repository.Query;
|
||||||
import org.springframework.data.repository.PagingAndSortingRepository;
|
import org.springframework.data.repository.PagingAndSortingRepository;
|
||||||
import org.springframework.data.rest.core.annotation.RepositoryRestResource;
|
import org.springframework.data.rest.core.annotation.RepositoryRestResource;
|
||||||
|
import org.springframework.data.rest.core.annotation.RestResource;
|
||||||
|
import org.springframework.format.annotation.DateTimeFormat;
|
||||||
|
|
||||||
import java.util.List;
|
import java.time.LocalDateTime;
|
||||||
|
|
||||||
@RepositoryRestResource(
|
@RepositoryRestResource(
|
||||||
path = "records",
|
path = "records",
|
||||||
@ -14,4 +18,37 @@ import java.util.List;
|
|||||||
)
|
)
|
||||||
public interface RecordRepository extends PagingAndSortingRepository<TimeRecord, Long> {
|
public interface RecordRepository extends PagingAndSortingRepository<TimeRecord, Long> {
|
||||||
|
|
||||||
|
@RestResource(rel = "allBetween", path = "allBetween")
|
||||||
|
Page<TimeRecord> findAllByStartdateBetween(
|
||||||
|
@DateTimeFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss") LocalDateTime start,
|
||||||
|
@DateTimeFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss") LocalDateTime end,
|
||||||
|
Pageable pageable
|
||||||
|
);
|
||||||
|
|
||||||
|
@RestResource(rel = "allBetweenAndUser", path = "allBetweenAndUser")
|
||||||
|
Page<TimeRecord> findAllByStartdateBetweenAndAccount_User_Username(
|
||||||
|
LocalDateTime start,
|
||||||
|
LocalDateTime end,
|
||||||
|
String username,
|
||||||
|
Pageable pageable
|
||||||
|
);
|
||||||
|
|
||||||
|
@RestResource(rel = "allForUser", path = "allForUser")
|
||||||
|
Page<TimeRecord> findAllByAccount_User_Username(String username, Pageable pageable);
|
||||||
|
|
||||||
|
@RestResource(rel = "allForUserAndAccount", path = "allForUserAndAccount")
|
||||||
|
Page<TimeRecord> findAllByAccount_User_UsernameAndAccount_Name(String username, String account, Pageable pageable);
|
||||||
|
|
||||||
|
@RestResource(rel = "allFrom", path = "allFrom")
|
||||||
|
Page<TimeRecord> findAllByStartdateGreaterThanEqual(
|
||||||
|
@DateTimeFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss") LocalDateTime date,
|
||||||
|
Pageable pageable
|
||||||
|
);
|
||||||
|
|
||||||
|
@Query("SELECT record from TimeRecord record where record.account.user.username = :#{principal} AND record.startdate > (current_date-1)")
|
||||||
|
Page<TimeRecord> today(Pageable pageable);
|
||||||
|
|
||||||
|
@RestResource(rel = "openEntries", path = "openEntries")
|
||||||
|
Page<TimeRecord> findAllByEnddateIsNull(Pageable pageable);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,7 @@ package de.hft.geotime.repositories;
|
|||||||
import de.hft.geotime.entities.TimetrackAccount;
|
import de.hft.geotime.entities.TimetrackAccount;
|
||||||
import org.springframework.data.repository.PagingAndSortingRepository;
|
import org.springframework.data.repository.PagingAndSortingRepository;
|
||||||
import org.springframework.data.rest.core.annotation.RepositoryRestResource;
|
import org.springframework.data.rest.core.annotation.RepositoryRestResource;
|
||||||
|
import org.springframework.data.rest.core.annotation.RestResource;
|
||||||
|
|
||||||
@RepositoryRestResource(
|
@RepositoryRestResource(
|
||||||
path = "accounts",
|
path = "accounts",
|
||||||
@ -11,4 +12,7 @@ import org.springframework.data.rest.core.annotation.RepositoryRestResource;
|
|||||||
)
|
)
|
||||||
public interface TimetrackAccountRepository extends PagingAndSortingRepository<TimetrackAccount, Long> {
|
public interface TimetrackAccountRepository extends PagingAndSortingRepository<TimetrackAccount, Long> {
|
||||||
|
|
||||||
|
@RestResource(rel = "findByUsernameAndName", path = "findByUsernameAndName")
|
||||||
|
TimetrackAccount findByUser_UsernameAndName(String username, String account);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,14 @@
|
|||||||
|
package de.hft.geotime.security;
|
||||||
|
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.data.spel.spi.EvaluationContextExtension;
|
||||||
|
|
||||||
|
@Configuration
|
||||||
|
class SecurityConfiguration {
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
EvaluationContextExtension securityExtension() {
|
||||||
|
return new SecurityEvaluationContextExtension();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,21 @@
|
|||||||
|
package de.hft.geotime.security;
|
||||||
|
|
||||||
|
import org.springframework.data.spel.spi.EvaluationContextExtension;
|
||||||
|
import org.springframework.security.access.expression.SecurityExpressionRoot;
|
||||||
|
import org.springframework.security.core.Authentication;
|
||||||
|
import org.springframework.security.core.context.SecurityContextHolder;
|
||||||
|
|
||||||
|
public class SecurityEvaluationContextExtension implements EvaluationContextExtension {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getExtensionId() {
|
||||||
|
return "security";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SecurityExpressionRoot getRootObject() {
|
||||||
|
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
|
||||||
|
return new SecurityExpressionRoot(authentication) {
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
@ -20,8 +20,15 @@ INSERT INTO timetrack_user (id, firstname, lastname, password, username, role_id
|
|||||||
(3, 'Tim', 'Zieger' ,'$2y$10$pYGHZhoaelceImO7aIN4nOkWJBp.oqNGFYaRAonHkYF4u9ljqPelC', 'ziti', 1, 1),
|
(3, 'Tim', 'Zieger' ,'$2y$10$pYGHZhoaelceImO7aIN4nOkWJBp.oqNGFYaRAonHkYF4u9ljqPelC', 'ziti', 1, 1),
|
||||||
(4, 'Simon', 'Kellner' ,'$2y$10$Puzm/Nr/Dyq3nQxlkXGIfubS5JPtXJSOf2e6mrQ6HhVYQN9YiQQsC', 'kesi', 1, 1);
|
(4, 'Simon', 'Kellner' ,'$2y$10$Puzm/Nr/Dyq3nQxlkXGIfubS5JPtXJSOf2e6mrQ6HhVYQN9YiQQsC', 'kesi', 1, 1);
|
||||||
|
|
||||||
INSERT INTO timetrack_account (description, `name`, revenue, user_id) VALUES
|
INSERT INTO timetrack_account (id, description, `name`, revenue, user_id) VALUES
|
||||||
('Gleitzeit Marcel', 'Primary Marcel', 16.0, 1),
|
(1, 'Gleitzeit Marcel', 'Primary', 16.0, 1),
|
||||||
('Festgeld Marcel', 'Secondary Marcel', 25.0, 1);
|
(2, 'Festgeld Marcel', 'Secondary', 25.0, 1),
|
||||||
|
(3, 'Festgeld Tim', 'Primary', 25.0, 3);
|
||||||
|
|
||||||
|
INSERT INTO time_record (id, enddate, startdate, `type`, account_id) VALUES
|
||||||
|
(1, '2020-05-10 16:00:00', '2020-05-10 12:00:00', 0, 1),
|
||||||
|
(2, '2020-05-09 16:00:00', '2020-05-09 12:00:00', 1, 1),
|
||||||
|
(3, '2020-05-20 16:00:00', '2020-05-20 00:00:00', 1, 2),
|
||||||
|
(4, '2020-05-11 16:00:00', '2020-05-11 12:00:00', 1, 3);
|
||||||
|
|
||||||
SET FOREIGN_KEY_CHECKS=1;
|
SET FOREIGN_KEY_CHECKS=1;
|
Loading…
Reference in New Issue
Block a user