Skip to content
Merged
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
import kernel360.trackyweb.common.sse.GlobalSseEvent;
import kernel360.trackyweb.common.sse.SseEvent;
import kernel360.trackyweb.dashboard.domain.CarStatusTemp;
import kernel360.trackyweb.statistic.application.dto.response.CarStatisticResponse;
import lombok.RequiredArgsConstructor;

@Component
Expand Down Expand Up @@ -68,9 +69,13 @@ public List<CarStatusTemp> getAllGroupedByStatus() {

public Map<Long, Integer> countDailyTotalCar() {
return CarCountWithBizId.toMap(carDomainRepository.getDailyTotalCarCount());
}
}

public List<CarEntity> findAllByAvailableEmulate(String bizUuid) {
return carDomainRepository.availableEmulate(bizUuid);
}
}

public Page<CarStatisticResponse> searchCarStatisticByFilter(Long bizId, String search, Pageable pageable) {
return carDomainRepository.searchCarStatisticByFilter(bizId, search, pageable);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import kernel360.trackycore.core.domain.entity.enums.CarStatus;
import kernel360.trackycore.core.domain.entity.enums.CarType;
import kernel360.trackyweb.car.application.dto.internal.CarCountWithBizId;
import kernel360.trackyweb.statistic.application.dto.response.CarStatisticResponse;

public interface CarDomainRepositoryCustom {
/**
Expand Down Expand Up @@ -42,4 +43,5 @@ List<CarEntity> findAllByBizUuid(

List<CarCountWithBizId> getDailyTotalCarCount();

Page<CarStatisticResponse> searchCarStatisticByFilter(Long bizId, String search, Pageable pageable);
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import static kernel360.trackycore.core.domain.entity.QBizEntity.*;
import static kernel360.trackycore.core.domain.entity.QCarEntity.*;
import static kernel360.trackycore.core.domain.entity.QRentEntity.*;
import static kernel360.trackycore.core.domain.entity.QTimeDistanceEntity.*;

import java.time.LocalDateTime;
import java.util.List;
Expand All @@ -19,6 +20,7 @@
import com.querydsl.core.types.Projections;
import com.querydsl.core.types.dsl.BooleanExpression;
import com.querydsl.core.types.dsl.Expressions;
import com.querydsl.core.types.dsl.NumberExpression;
import com.querydsl.core.types.dsl.NumberTemplate;
import com.querydsl.jpa.impl.JPAQuery;
import com.querydsl.jpa.impl.JPAQueryFactory;
Expand All @@ -27,6 +29,7 @@
import kernel360.trackycore.core.domain.entity.enums.CarStatus;
import kernel360.trackycore.core.domain.entity.enums.CarType;
import kernel360.trackyweb.car.application.dto.internal.CarCountWithBizId;
import kernel360.trackyweb.statistic.application.dto.response.CarStatisticResponse;
import lombok.RequiredArgsConstructor;

@Repository
Expand Down Expand Up @@ -116,24 +119,73 @@ public List<CarCountWithBizId> getDailyTotalCarCount() {
))
.from(carEntity)
.groupBy(carEntity.biz.id)
.fetch();
}

@Override
public List<CarEntity> availableEmulate(String bizUuid) {
LocalDateTime now = LocalDateTime.now();
return queryFactory
.select(carEntity)
.from(carEntity)
.join(rentEntity).on(rentEntity.car.eq(carEntity)) // 반드시 rent가 연결된 경우만
.where(
carEntity.biz.bizUuid.eq(bizUuid),
rentEntity.rentStime.loe(now),
rentEntity.rentEtime.goe(now)
)
.fetch();
}

@Override
public List<CarEntity> availableEmulate(String bizUuid) {
LocalDateTime now = LocalDateTime.now();
return queryFactory
.select(carEntity)
.from(carEntity)
.join(rentEntity).on(rentEntity.car.eq(carEntity)) // 반드시 rent가 연결된 경우만
.where(
carEntity.biz.bizUuid.eq(bizUuid),
rentEntity.rentStime.loe(now),
rentEntity.rentEtime.goe(now)
)
.fetch();
}

// 통계 - 차량별 상세 통계
@Override
public Page<CarStatisticResponse> searchCarStatisticByFilter(Long bizId, String search, Pageable pageable) {

NumberExpression<Integer> totalSeconds = timeDistanceEntity.seconds.sum().coalesce(0);

NumberExpression<Double> totalDistance = timeDistanceEntity.distance.sum().coalesce(0.0);

NumberExpression<Integer> avgSpeed
= totalDistance
.multiply(3.6)
.divide(totalSeconds).intValue();

BooleanBuilder builder = new BooleanBuilder()
.and(carEntity.biz.id.eq(bizId))
.and(carEntity.status.ne(CarStatus.DELETED))
.and(isContainsCarMdnOrCarPlate(search));

List<CarStatisticResponse> carStatisticResponses = queryFactory
.select(Projections.constructor(
CarStatisticResponse.class,
carEntity.mdn,
carEntity.carPlate,
carEntity.carType,
totalSeconds,
totalDistance,
avgSpeed
))
.from(carEntity)
.leftJoin(timeDistanceEntity)
.on(timeDistanceEntity.car.mdn.eq(carEntity.mdn))
.where(builder)
.groupBy(carEntity.mdn)
.orderBy(carPlateSort(search))
.offset(pageable.getOffset())
.limit(pageable.getPageSize())
.fetch();

long total = Optional.ofNullable(
queryFactory
.select(carEntity.mdn.count())
.from(carEntity)
.where(builder)
.fetchOne()
).orElse(0L);

return new PageImpl<>(carStatisticResponses, pageable, total);
}

//검색 조건
private BooleanExpression isContainsCarMdnOrCarPlate(String search) {
if (StringUtils.isBlank(search)) {
Expand Down Expand Up @@ -185,7 +237,7 @@ private OrderSpecifier<?>[] carPlateSort(String search) {
return new OrderSpecifier<?>[] {carEntity.carPlate.asc()};
}

private List<CarEntity> fetchPagedContent(JPAQuery<CarEntity> query, Pageable pageable) {
private <T> List<T> fetchPagedContent(JPAQuery<T> query, Pageable pageable) {
return query
.offset(pageable.getOffset())
.limit(pageable.getPageSize())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,16 @@
import java.util.List;
import java.util.Map;

import kernel360.trackyweb.drive.application.dto.internal.NonOperatedCar;
import kernel360.trackyweb.drive.application.dto.internal.OperationTotalCount;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Component;

import kernel360.trackycore.core.common.exception.ErrorCode;
import kernel360.trackycore.core.common.exception.GlobalException;
import kernel360.trackycore.core.domain.entity.DriveEntity;
import kernel360.trackyweb.drive.application.dto.internal.NonOperatedCar;
import kernel360.trackyweb.drive.application.dto.internal.OperationCarCount;
import kernel360.trackyweb.drive.application.dto.internal.OperationTotalCount;
import kernel360.trackyweb.drive.domain.DriveHistory;
import kernel360.trackyweb.drive.infrastructure.repository.DriveDomainRepository;
import lombok.RequiredArgsConstructor;
Expand All @@ -22,58 +22,58 @@
@RequiredArgsConstructor
public class DriveDomainProvider {

private final DriveDomainRepository driveDomainRepository;
private final DriveDomainRepository driveDomainRepository;

public Page<DriveEntity> searchDrivesByFilter(
String search,
String mdn,
LocalDate startDateTime,
LocalDate endDateTime,
Pageable pageable) {
return driveDomainRepository.searchByFilter(search, mdn, startDateTime, endDateTime, pageable);
}
public Page<DriveEntity> searchDrivesByFilter(
String search,
String mdn,
LocalDate startDateTime,
LocalDate endDateTime,
Pageable pageable) {
return driveDomainRepository.searchByFilter(search, mdn, startDateTime, endDateTime, pageable);
}

public Page<DriveEntity> findRunningDriveList(
String search,
Pageable pageable
) {
return driveDomainRepository.findRunningDriveList(search, pageable);
}
public Page<DriveEntity> findRunningDriveList(
String search,
Pageable pageable
) {
return driveDomainRepository.findRunningDriveList(search, pageable);
}

public DriveEntity findRunningDriveById(Long driveId) {
return driveDomainRepository.findRunningDriveById(driveId)
.orElseThrow(() -> GlobalException.throwError(ErrorCode.NOT_REALTIME_DRIVE));
}
public DriveEntity findRunningDriveById(Long driveId) {
return driveDomainRepository.findRunningDriveById(driveId)
.orElseThrow(() -> GlobalException.throwError(ErrorCode.NOT_REALTIME_DRIVE));
}

public DriveHistory findByDriveId(Long driveId) {
return driveDomainRepository.findByDriveId(driveId)
.orElseThrow(() -> GlobalException.throwError(ErrorCode.DRIVE_NOT_FOUND));
}
public DriveHistory findByDriveId(Long driveId) {
return driveDomainRepository.findByDriveId(driveId)
.orElseThrow(() -> GlobalException.throwError(ErrorCode.DRIVE_NOT_FOUND));
}

public List<DriveEntity> findByMdn(String mdn) {
return driveDomainRepository.findDriveListByMdn(mdn);
}
public List<DriveEntity> findByMdn(String mdn) {
return driveDomainRepository.findDriveListByMdn(mdn);
}

public Double getTotalDriveDistance() {
return driveDomainRepository.getTotalDriveDistance();
}
public Double getTotalDriveDistance() {
return driveDomainRepository.getTotalDriveDistance();
}

public Long getTotalDriveDurationInMinutes() {
return driveDomainRepository.getTotalDriveDurationInMinutes();
}
public Long getTotalDriveDurationInMinutes() {
return driveDomainRepository.getTotalDriveDurationInMinutes();
}

//일일 통계 - 당일 운행 차량 수 (distinct mdn)
public Map<Long, Integer> countDailyOperationCar(LocalDate targetDate) {
return OperationCarCount.toMap(driveDomainRepository.getDailyOperationCar(targetDate));
}
//일일 통계 - 당일 운행 차량 수 (distinct mdn)
public Map<Long, Integer> countDailyOperationCar(LocalDate targetDate) {
return OperationCarCount.toMap(driveDomainRepository.getDailyOperationCar(targetDate));
}

//일일 통계 - 당일 총 운행 수
public Map<Long, Integer> countDailyTotalOperation(LocalDate targetDate) {
return OperationTotalCount.toMap(driveDomainRepository.getDailyTotalOperation(targetDate));
}
//일일 통계 - 당일 총 운행 수
public Map<Long, Integer> countDailyTotalOperation(LocalDate targetDate) {
return OperationTotalCount.toMap(driveDomainRepository.getDailyTotalOperation(targetDate));
}

//월별 통계 - 미운행 차량 수
public Map<Long, Integer> getNonOperatedCars(LocalDate targetDate) {
return NonOperatedCar.toMap(driveDomainRepository.getNonOperatedCars(targetDate));
}
//월별 통계 - 미운행 차량 수
public Map<Long, Integer> getNonOperatedCars(LocalDate targetDate) {
return NonOperatedCar.toMap(driveDomainRepository.getNonOperatedCars(targetDate));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,24 @@

import java.time.LocalDate;
import java.time.YearMonth;
import java.util.ArrayList;
import java.util.List;

import org.springframework.data.domain.Page;
import org.springframework.stereotype.Service;

import kernel360.trackycore.core.common.api.ApiResponse;
import kernel360.trackycore.core.common.api.PageResponse;
import kernel360.trackycore.core.domain.entity.DailyStatisticEntity;
import kernel360.trackycore.core.domain.entity.MonthlyStatisticEntity;
import kernel360.trackycore.core.domain.provider.BizProvider;
import kernel360.trackyweb.car.domain.provider.CarDomainProvider;
import kernel360.trackyweb.statistic.application.dto.request.CarStatisticRequest;
import kernel360.trackyweb.statistic.application.dto.response.CarStatisticResponse;
import kernel360.trackyweb.statistic.application.dto.response.DailyStatisticResponse;
import kernel360.trackyweb.statistic.application.dto.response.MonthlyStatisticResponse;
import kernel360.trackyweb.statistic.domain.provider.DailyStatisticProvider;
import kernel360.trackyweb.statistic.domain.provider.MonthlyStatisticProvider;
import kernel360.trackyweb.timedistance.domain.provider.TimeDistanceDomainProvider;
import lombok.RequiredArgsConstructor;

@Service
Expand All @@ -23,42 +28,55 @@ public class StatisticService {

private final DailyStatisticProvider dailyStatisticProvider;
private final MonthlyStatisticProvider monthlyStatisticProvider;
private final TimeDistanceDomainProvider timeDistanceDomainProvider;
private final BizProvider bizProvider;
private final CarDomainProvider carDomainProvider;

public ApiResponse<DailyStatisticResponse> getDailyStatistic(String bizUuid, LocalDate date) {

Long bizId = bizProvider.getBiz(bizUuid).getId();

DailyStatisticEntity dailyStatistic = dailyStatisticProvider.getDailyStatistic(bizId, date);

List<Integer> list = new ArrayList<>();
for (int i = 0; i < 24; i++) {
list.add(1);
}
DailyStatisticResponse response = DailyStatisticResponse.from(dailyStatistic, list);
long[] hourlyDriveCounts = timeDistanceDomainProvider.getHourlyDriveCounts(bizId, date);

DailyStatisticResponse response = DailyStatisticResponse.from(dailyStatistic, hourlyDriveCounts);

return ApiResponse.success(response);
}

public ApiResponse<MonthlyStatisticResponse> getMonthlyStatistic(String bizUuid, YearMonth date) {
public ApiResponse<MonthlyStatisticResponse> getMonthlyStatistic(String bizUuid, YearMonth date,
YearMonth targetDate) {

if (targetDate == null) {
targetDate = date.minusMonths(11);
}

Long bizId = bizProvider.getBiz(bizUuid).getId();

LocalDate localDate = date.atDay(1);
MonthlyStatisticEntity monthlyStatistic = monthlyStatisticProvider.getMonthlyStatistic(bizId, date.atDay(1));

MonthlyStatisticEntity monthlyStatistic = monthlyStatisticProvider.getMonthlyStatistic(bizId, localDate);
List<MonthlyStatisticResponse.MonthlyStats> monthlyStats = monthlyStatisticProvider.getMonthlyStats(bizId,
date.atDay(1),
targetDate.atDay(1));

List<Integer> list = new ArrayList<>();
for (int i = 0; i < 12; i++) {
list.add(1);
}
List<Long> list2 = new ArrayList<>();
for (int i = 0; i < 12; i++) {
list2.add(1L);
}
MonthlyStatisticResponse response = MonthlyStatisticResponse.from(monthlyStatistic, list, list2);
MonthlyStatisticResponse response = MonthlyStatisticResponse.from(monthlyStatistic, monthlyStats);

return ApiResponse.success(response);
}

public ApiResponse<List<CarStatisticResponse>> getCarStatistic(String bizUuid,
CarStatisticRequest carStatisticRequest) {

Long bizId = bizProvider.getBiz(bizUuid).getId();

Page<CarStatisticResponse> carResponses = carDomainProvider.searchCarStatisticByFilter(
bizId,
carStatisticRequest.search(),
carStatisticRequest.toPageable());

PageResponse pageResponse = PageResponse.from(carResponses);

return ApiResponse.success(carResponses.getContent(), pageResponse);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package kernel360.trackyweb.statistic.application.dto.request;

import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;

public record CarStatisticRequest(
String search,
Integer page,
Integer size
) {
public Pageable toPageable() {
int safePage = page != null ? page : 0;
int safeSize = size != null ? size : 20;
return PageRequest.of(safePage, safeSize);
}
}
Loading