Story 3 and Story 4 finished

This commit is contained in:
Matthias Engelien
2024-09-11 22:43:38 +02:00
parent 97d86cd11a
commit a2164a0eb3
9 changed files with 264 additions and 36 deletions

View File

@@ -3,31 +3,68 @@
*/
package de.etecture.ga.api;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.Optional;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.math.NumberUtils;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.util.Assert;
import de.etecture.ga.dto.Termin;
import de.etecture.ga.dto.TerminRequest;
import de.etecture.ga.dto.mapper.AppointmentTerminMapper;
import de.etecture.ga.model.Appointment;
import de.etecture.ga.service.AppointmentService;
import jakarta.validation.Valid;
import jakarta.validation.constraints.NotNull;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
/**
*
*/
@AllArgsConstructor
@Controller
@Slf4j
public class GarageApiController implements WerkstattApi {
private final AppointmentService appointmentService;
@Override
public ResponseEntity<Termin> getTermin(String werkstattId, String terminId) {
// TODO Auto-generated method stub
return WerkstattApi.super.getTermin(werkstattId, terminId);
public ResponseEntity<Termin> getTermin(@NotNull String werkstattId, @NotNull String terminId) {
Assert.isTrue(NumberUtils.isParsable(werkstattId), "werkstattId ungültig");
Assert.isTrue(NumberUtils.isParsable(terminId), "terminId ungültig");
Optional<Appointment> appointment = appointmentService.getAppointment(Long.parseLong(terminId),
Long.parseLong(werkstattId));
return ResponseEntity.of(appointment.map(AppointmentTerminMapper::toTermin));
}
@Override
public ResponseEntity<List<Termin>> getTermine(String werkstattId, @Valid String von, @Valid String bis,
public ResponseEntity<List<Termin>> getTermine(@NotNull String werkstattId, @Valid String von, @Valid String bis,
@Valid String leistungsId) {
// TODO Auto-generated method stub
return WerkstattApi.super.getTermine(werkstattId, von, bis, leistungsId);
Assert.isTrue(NumberUtils.isParsable(werkstattId), "werkstattId ungültig");
long garageId = Long.parseLong(werkstattId);
Optional<Long> serviceId = NumberUtils.isParsable(leistungsId) ? Optional.of(Long.parseLong(leistungsId))
: Optional.empty();
Optional<Date> appointmentsFrom = Optional.ofNullable(parseLocalDateTime(von));
Optional<Date> appointmentsTill = Optional.ofNullable(parseLocalDateTime(bis));
log.info("Filter appointments by garage {}, serviceId {}, from {}, till {}", garageId, serviceId,
appointmentsFrom, appointmentsTill);
return ResponseEntity
.ok(appointmentService.getAppointments(garageId, serviceId, appointmentsFrom, appointmentsTill).stream()
.map(AppointmentTerminMapper::toTermin).toList());
}
@Override
@@ -43,4 +80,18 @@ public class GarageApiController implements WerkstattApi {
return WerkstattApi.super.postTermin(werkstattId, termin);
}
private Date parseLocalDateTime(String dateTimeString) {
if (StringUtils.isNotBlank(dateTimeString)) {
try {
SimpleDateFormat format = new SimpleDateFormat("dd.MM.yyyy hh:mm");
return format.parse(dateTimeString);
} catch (ParseException e) {
log.error("Invalid data to parse", e);
}
}
return null;
}
}

View File

@@ -0,0 +1,32 @@
package de.etecture.ga.dto.mapper;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import de.etecture.ga.dto.Termin;
import de.etecture.ga.model.Appointment;
import lombok.extern.slf4j.Slf4j;
@Slf4j
public class AppointmentTerminMapper {
public static Termin toTermin(Appointment appointment) {
log.info("Mapping Object {}", appointment);
LocalDateTime appointmentStart = Instant.ofEpochMilli(appointment.appointmentTime().getTime())
.atZone(ZoneId.systemDefault()).toLocalDateTime();
LocalDateTime appointmentEnd = appointmentStart.plus(appointment.duration());
return new Termin()
.id(Long.toString(appointment.id()))
.leistungsId(Long.toString(appointment.serviceId().getId()))
.leistung(appointment.serviceName())
.werkstattName("to_be_set")
.von(appointmentStart.format(DateTimeFormatter.ofPattern("dd.MM.yyyy hh:mm")))
.bis(appointmentEnd.format(DateTimeFormatter.ofPattern("dd.MM.yyyy hh:mm")));
}
}

View File

@@ -20,6 +20,9 @@ public class Appointment {
@Column("GARAGE_ID")
private AggregateReference<Garage, Long> garageId;
@Column("SERVICE_ID")
private AggregateReference<MDService, Long> serviceId;
private String serviceCode;
private String serviceName;

View File

@@ -1,9 +1,22 @@
package de.etecture.ga.repository;
import java.util.List;
import java.util.Optional;
import org.springframework.data.jdbc.repository.query.Query;
import org.springframework.data.repository.CrudRepository;
import de.etecture.ga.model.Appointment;
public interface AppointmentRepository extends CrudRepository<Appointment, Long> {
public Optional<Appointment> findByIdAndGarageId(long id, long garageId);
public List<Appointment> findByGarageId(long garageId);
@Query("select a.* from APPOINTMENT a "
+ "join GARAGE g on g.ID = a.GARAGE_ID "
+ "join MD_SERVICE s on s.ID = a.SERVICE_ID "
+ "where s.CODE = :serviceCode and g.ID = :garageId ")
public List<Appointment> findByServiceCodeAndGarageId(String serviceCode, long garageId);
}

View File

@@ -0,0 +1,50 @@
package de.etecture.ga.service;
import java.util.Date;
import java.util.List;
import java.util.Optional;
import java.util.stream.Stream;
import org.springframework.stereotype.Service;
import de.etecture.ga.model.Appointment;
import de.etecture.ga.repository.AppointmentRepository;
import lombok.AllArgsConstructor;
@Service
@AllArgsConstructor
public class AppointmentService {
private final AppointmentRepository repository;
public Optional<Appointment> getAppointment(long appointmentId) {
return repository.findById(appointmentId);
}
public Optional<Appointment> getAppointment(long appointmentId, long garageId) {
return repository.findByIdAndGarageId(appointmentId, garageId);
}
public List<Appointment> getAppointments(long garageId, Optional<Long> serviceId, Optional<Date> from,
Optional<Date> till) {
Stream<Appointment> appointments = repository.findByGarageId(garageId).stream();
if (serviceId.isPresent()) {
appointments = appointments.filter(a -> serviceId.get().equals(a.serviceId().getId()));
}
if (from.isPresent()) {
appointments = appointments
.filter(a -> a.appointmentTime().equals(from.get()) || a.appointmentTime().after(from.get()));
}
if (till.isPresent()) {
appointments = appointments.filter(a -> a.appointmentTime().before(till.get()));
}
return appointments.toList();
}
}

View File

@@ -15,9 +15,11 @@ import java.util.stream.Stream;
import org.springframework.data.jdbc.core.mapping.AggregateReference;
import org.springframework.stereotype.Service;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.databind.MappingIterator;
import com.fasterxml.jackson.dataformat.csv.CsvMapper;
import com.fasterxml.jackson.dataformat.csv.CsvSchema;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import de.etecture.ga.model.Appointment;
import de.etecture.ga.model.Garage;
@@ -88,6 +90,7 @@ public class GarageImportService {
try {
CsvSchema bootstrapSchema = CsvSchema.emptySchema().withHeader();
CsvMapper mapper = new CsvMapper();
MappingIterator<CSVData> readValues = mapper.readerFor(CSVData.class).with(bootstrapSchema)
.readValues(file.toFile());
@@ -110,9 +113,9 @@ public class GarageImportService {
private Appointment getAppointmentForService(MDService service, Date date, Long garageId) {
return new Appointment().appointmentTime(date).serviceCode(service.code()).serviceName(service.name())
.duration(service.duration()).garageId(AggregateReference.to(garageId));
.duration(service.duration()).garageId(AggregateReference.to(garageId)).serviceId(AggregateReference.to(service.id()));
}
private record CSVData(Date APP_DATE, String SERVICE) {
private record CSVData(@JsonFormat(pattern="yyyy-MM-dd'T'HH:mm'Z'") Date APP_DATE, String SERVICE) {
}
}