Skip to content

Commit

Permalink
Introduce StatisticValue entity and repository
Browse files Browse the repository at this point in the history
Added StatisticValue entity to track statistics, including required DDL.
Updated StatisticService to handle statistics for created, updated, and deleted time reports.
Implemented methods to update or save statistics and ensure persistence in database.
  • Loading branch information
KlausRicharz committed Nov 27, 2024
1 parent 880dc7f commit d429bb7
Show file tree
Hide file tree
Showing 5 changed files with 277 additions and 23 deletions.
44 changes: 40 additions & 4 deletions src/main/java/org/tb/favorites/domain/Favorite.java
Original file line number Diff line number Diff line change
@@ -1,32 +1,68 @@
package org.tb.favorites.domain;

import static lombok.AccessLevel.PRIVATE;

import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.Lob;
import java.util.Objects;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import org.springframework.data.domain.Persistable;

@Builder
@Data
@Entity
@NoArgsConstructor
@Getter
@Setter
@AllArgsConstructor
public class Favorite {
@NoArgsConstructor
public class Favorite implements Persistable<Long> {

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Setter(PRIVATE)
private Long id;

private Long employeeId;

private Long employeeorderId;

private Integer hours;

private Integer minutes;

@Lob
@Column(columnDefinition = "text")
private String comment;

@Override
public boolean isNew() {
return id == null;
}

@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
if(id == null) return false;
Favorite that = (Favorite) o;
return Objects.equals(id, that.id);
}

@Override
public int hashCode() {
if(id == null) return 0;
return Objects.hash(id);
}

}
111 changes: 111 additions & 0 deletions src/main/java/org/tb/statistic/domain/StatisticValue.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
package org.tb.statistic.domain;

import static jakarta.persistence.AccessType.FIELD;
import static lombok.AccessLevel.PRIVATE;

import jakarta.persistence.Access;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.Index;
import jakarta.persistence.Table;
import java.time.Duration;
import java.util.Objects;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import org.springframework.data.domain.Persistable;

@Entity
@Access(FIELD)
@Table(name = "statistic_value", indexes = {
@Index(name = "idx_main", columnList = "category, key, object_id")
})
@NoArgsConstructor(access = PRIVATE)
public class StatisticValue implements Persistable<Long> {

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Getter
private Long id;

@Getter
private String category;

@Column(name = "`key`")
@Getter
private String key;

@Getter
@Column(name = "object_id")
private long objectId;

@Setter
private long value;

@Column(length = 4000)
@Getter
@Setter
private String comment;

public StatisticValue(String category, String key, long objectId, Duration value, String comment) {
this.category = category;
this.key = key;
this.objectId = objectId;
this.comment = comment;
this.value = value.toMinutes();
}

public Duration getAsDuration() {
return Duration.ofMinutes(value);
}

public void setValue(Duration value) {
this.value = value.toMinutes();
}

@Override
public boolean isNew() {
return id == null;
}

@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
if (id == null) {
return false;
}
StatisticValue that = (StatisticValue) o;
return Objects.equals(id, that.id);
}

@Override
public int hashCode() {
if (id == null) {
return 0;
}
return Objects.hash(id);
}

}

// Corresponding DDL:

/*
CREATE TABLE statistic_value (
id BIGINT AUTO_INCREMENT PRIMARY KEY,
category VARCHAR(255),
key VARCHAR(255),
object_id BIGINT,
value BIGINT,
comment VARCHAR(4000),
INDEX idx_main (category, key, object_id)
);
*/
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package org.tb.statistic.persistence;

import java.util.Optional;
import org.springframework.data.repository.CrudRepository;
import org.springframework.stereotype.Repository;
import org.tb.statistic.domain.StatisticValue;

@Repository
public interface StatisticValueRepository extends CrudRepository<StatisticValue, Long> {

Optional<StatisticValue> findByCategoryAndKeyAndObjectId(String category, String key, long objectId);

}
93 changes: 74 additions & 19 deletions src/main/java/org/tb/statistic/service/StatisticService.java
Original file line number Diff line number Diff line change
@@ -1,15 +1,19 @@
package org.tb.statistic.service;

import static java.time.Duration.ofMinutes;
import static java.time.LocalDateTime.now;

import java.time.Duration;
import java.time.LocalDate;
import java.time.YearMonth;
import java.util.LinkedList;
import java.util.List;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.tb.common.domain.AuditedEntity;
import org.tb.common.util.DurationUtils;
import org.tb.dailyreport.domain.TimereportDTO;
import org.tb.dailyreport.event.TimereportsCreatedOrUpdatedEvent;
import org.tb.dailyreport.event.TimereportsDeletedEvent;
Expand All @@ -20,6 +24,8 @@
import org.tb.order.service.CustomerorderService;
import org.tb.order.service.EmployeeorderService;
import org.tb.order.service.SuborderService;
import org.tb.statistic.domain.StatisticValue;
import org.tb.statistic.persistence.StatisticValueRepository;

@Slf4j
@Service
Expand All @@ -31,36 +37,61 @@ public class StatisticService {
private final EmployeeorderService employeeorderService;
private final SuborderService suborderService;
private final CustomerorderService customerorderService;
private final StatisticValueRepository statisticValueRepository;

@EventListener
void onTimereportsCreatedOrUpdated(TimereportsCreatedOrUpdatedEvent event) {
var employeeorders = event.getIds().stream()
var timereports = event.getIds().stream()
.map(timereportService::getTimereportById)
.toList();
var minDate = timereports.stream()
.map(TimereportDTO::getReferenceday)
.min(LocalDate::compareTo)
.orElse(LocalDate.now());
var maxDate = timereports.stream()
.map(TimereportDTO::getReferenceday)
.max(LocalDate::compareTo)
.orElse(LocalDate.now());

var employeeorders = timereports.stream()
.map(TimereportDTO::getEmployeeorderId)
.distinct()
.map(employeeorderService::getEmployeeorderById)
.toList();
generateTimereportStatistics(employeeorders);

var comment = "time report(s) created or updated @ %s".formatted(now());

generateOrderStatistics(employeeorders, minDate, maxDate, comment);
}

@EventListener
void onTimereportsDeleted(TimereportsDeletedEvent event) {
var referencedDays = event.getIds().stream()
.map(TimereportDeleteId::getReferenceDay)
.distinct()
.toList();
var minDate = referencedDays.stream()
.min(LocalDate::compareTo)
.orElse(LocalDate.now());
var maxDate = referencedDays.stream()
.max(LocalDate::compareTo)
.orElse(LocalDate.now());

var employeeorders = event.getIds().stream()
.map(TimereportDeleteId::getEmployeeorderId)
.distinct()
.map(employeeorderService::getEmployeeorderById)
.toList();
generateTimereportStatistics(employeeorders);

var comment = "time report(s) deleted @ %s".formatted(now());

generateOrderStatistics(employeeorders, minDate, maxDate, comment);
}

private void generateTimereportStatistics(List<Employeeorder> employeeorders) {
private void generateOrderStatistics(List<Employeeorder> employeeorders, LocalDate min, LocalDate max, String comment) {
employeeorders.forEach(eo -> {
var duration = timereportService.getTotalDurationMinutesForEmployeeOrder(eo.getId());
log.info("EO: Duration for {} of {}: {}",
eo.getSuborder().getCompleteOrderSign(),
eo.getEmployeecontract().getEmployee().getSign(),
DurationUtils.format(ofMinutes(duration))
);
updateStatistic("EMPLOYEEORDER", "timereport.duration.total", eo.getId(), ofMinutes(duration), comment);
});
var suborders = employeeorders.stream()
.map(Employeeorder::getSuborder)
Expand All @@ -70,11 +101,15 @@ private void generateTimereportStatistics(List<Employeeorder> employeeorders) {
.map(suborderService::getSuborderById)
.toList();
suborders.forEach(so -> {
var duration = timereportService.getTotalDurationMinutesForSuborders(List.of(so.getId()));
log.info("SO Duration for {}: {}",
so.getCompleteOrderSign(),
DurationUtils.format(ofMinutes(duration))
);
{
var duration = timereportService.getTotalDurationMinutesForSuborders(List.of(so.getId()));
updateStatistic("SUBORDER", "timereport.duration.total", so.getId(), ofMinutes(duration), comment);
}
var months = getMonths(min, max);
months.forEach(month -> {
var duration = timereportService.getTotalDurationMinutesForSuborder(so.getId(), month.atDay(1), month.atEndOfMonth());
updateStatistic("SUBORDER", "timereport.duration." + month, so.getId(), ofMinutes(duration), comment);
});
});
var customerorders = suborders.stream()
.map(Suborder::getCustomerorder)
Expand All @@ -84,11 +119,31 @@ private void generateTimereportStatistics(List<Employeeorder> employeeorders) {
.toList();
customerorders.forEach(co -> {
var duration = timereportService.getTotalDurationMinutesForCustomerOrder(co.getId());
log.info("CO Duration for {}: {}",
co.getSign(),
DurationUtils.format(ofMinutes(duration))
);
updateStatistic("CUSTOMERORDER", "timereport.duration.total", co.getId(), ofMinutes(duration), comment);
});
}

private List<YearMonth> getMonths(LocalDate min, LocalDate max) {
List<YearMonth> result = new LinkedList<>();

YearMonth current = YearMonth.from(min);
YearMonth end = YearMonth.from(max);

while (!current.isAfter(end)) {
result.add(current);
current = current.plusMonths(1);
}

return result;
}

private void updateStatistic(String category, String key, long objectId, Duration value, String comment) {
var statisticValue = statisticValueRepository
.findByCategoryAndKeyAndObjectId(category, key, objectId)
.orElseGet(() -> new StatisticValue(category, key, objectId, value, comment));
statisticValue.setValue(value);
statisticValue.setComment(comment);
statisticValueRepository.save(statisticValue);
}

}
Loading

0 comments on commit d429bb7

Please sign in to comment.