Skip to content

Commit

Permalink
Merge pull request #39 from consiglionazionaledellericerche/38-utiliz…
Browse files Browse the repository at this point in the history
…zo-di-un-contatore-incrementale-per-linserimento-delle-marcature

Gestito contatore incrementale per inseriremento marcature.
  • Loading branch information
criluc authored Mar 21, 2024
2 parents 55158fc + a34480c commit 0956c7f
Show file tree
Hide file tree
Showing 5 changed files with 47 additions and 26 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ public class SyncJob {
void syncAllEveryDay() {
log.info("Sincronizzazione giornaliera via quartz avviata");
syncService.syncAll();
syncService.loadDetails();
log.info("Sincronizzazione giornaliera via quartz terminata");
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@
*/
package it.cnr.iit.epas.timesheet.ugovpj.repo;

import java.util.Optional;

import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.repository.JpaRepository;
Expand Down Expand Up @@ -58,4 +60,6 @@ public interface PersonTimeDetailRepo
@Query(value = "call P_CARICA_MARCATURE_JOB", nativeQuery = true)
void loadDetailsJobNative();

@Query(value = "SELECT MAX(ptd.id) FROM PersonTimeDetail ptd")
Optional<Long> findMaxid();
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.atomic.AtomicLong;

import org.springframework.stereotype.Service;

Expand Down Expand Up @@ -62,12 +63,11 @@ public class SyncService {

private final MeterRegistry meterRegistry;

private final Long ID_OFFSET = 100000000L;

/**
* Sincronizza il dato del tempo a lavoro di una persona in un giorno specifico.
*/
private Optional<PersonTimeDetail> syncPersonDayTimeAtWork(PersonShowTerseDto person, PersonDayShowTerseDto personDay) {
private Optional<PersonTimeDetail> syncPersonDayTimeAtWork(
PersonShowTerseDto person, PersonDayShowTerseDto personDay, AtomicLong counter) {
//Inserimento resoconto tempo a lavoro da timbrature
if (personDay.getTimeAtWork() == 0) {
log.trace("PersonDay id={} person.number={} ignored time at work, it's zero",
Expand All @@ -76,7 +76,7 @@ private Optional<PersonTimeDetail> syncPersonDayTimeAtWork(PersonShowTerseDto pe
}
val personTimeDetail =
PersonTimeDetail.builder()
.id(personDay.getId())
.id(counter.incrementAndGet())
.date(personDay.getDate()).minutes(personDay.getTimeAtWork())
.number(person.getNumber())
.type(timesheetConfig.getStampingsType())
Expand All @@ -89,7 +89,8 @@ private Optional<PersonTimeDetail> syncPersonDayTimeAtWork(PersonShowTerseDto pe
/**
* Sincronizza i dati delle assenze di una persona in un giorno specifico.
*/
private List<PersonTimeDetail> syncPersonDayAbsences(PersonShowTerseDto person, PersonDayShowTerseDto personDay) {
private List<PersonTimeDetail> syncPersonDayAbsences(
PersonShowTerseDto person, PersonDayShowTerseDto personDay, AtomicLong counter) {
Map<String, Integer> absenceMap = Maps.newHashMap();
val timeDetailType = typeService.timeDetailTypes();
personDay.getAbsences().stream()
Expand All @@ -107,7 +108,7 @@ private List<PersonTimeDetail> syncPersonDayAbsences(PersonShowTerseDto person,
//Inserimento resoconto tempo giustificato per l'assenza
val personTimeDetail =
PersonTimeDetail.builder()
.id(personTimeDetailId(personDay, absenceGroup))
.id(counter.incrementAndGet())
.date(personDay.getDate())
.minutes(absenceMap.get(absenceGroup))
.number(person.getNumber())
Expand All @@ -123,31 +124,34 @@ private List<PersonTimeDetail> syncPersonDayAbsences(PersonShowTerseDto person,
/**
* Sincronizza i dati di presenze e assenze di una persona in un giorno specifico.
*/
public List<PersonTimeDetail> syncPersonDay(PersonShowTerseDto person, PersonDayShowTerseDto personDay) {
public List<PersonTimeDetail> syncPersonDay(
PersonShowTerseDto person, PersonDayShowTerseDto personDay, AtomicLong counter) {
log.trace("Sincronizzazione personDay {}", personDay);
List<PersonTimeDetail> details = Lists.newArrayList();
//Inserimento resoconto tempo a lavoro da timbrature
val timeAtWorkDetail = syncPersonDayTimeAtWork(person, personDay);
val timeAtWorkDetail = syncPersonDayTimeAtWork(person, personDay, counter);
if (timeAtWorkDetail.isPresent()) {
details.add(timeAtWorkDetail.get());
}
//Inserimento delle assenze con externalGroupId rilevante, raggruppate per externalGroupId
details.addAll(syncPersonDayAbsences(person, personDay));
details.addAll(syncPersonDayAbsences(person, personDay, counter));
return details;
}

/**
* Sincronizzata i dati di presenze e assenze di una persona in un mese.
*/
public List<PersonTimeDetail> syncPersonMonth(PersonMonthRecapDto monthRecap, Optional<LocalDate> notBefore) {
public List<PersonTimeDetail> syncPersonMonth(
PersonMonthRecapDto monthRecap, Optional<LocalDate> notBefore,
AtomicLong counter) {
List<PersonTimeDetail> details = Lists.newArrayList();
if (Strings.isNullOrEmpty(monthRecap.getPerson().getNumber())) {
log.info("Ignorata persona {} perché senza matricola", monthRecap.getPerson());
return details;
}
monthRecap.getPersonDays().forEach(personDay -> {
if (notBefore.isEmpty() || !personDay.getDate().isBefore(notBefore.get())) {
details.addAll(syncPersonDay(monthRecap.getPerson(), personDay));
details.addAll(syncPersonDay(monthRecap.getPerson(), personDay, counter));
}
});
return details;
Expand All @@ -158,15 +162,16 @@ public List<PersonTimeDetail> syncPersonMonth(PersonMonthRecapDto monthRecap, Op
* di un ufficio nel mese indicato.
*/
public List<PersonTimeDetail> syncOfficeMonth(
long officeId, YearMonth yearMonth, Optional<LocalDate> notBefore) {
long officeId, YearMonth yearMonth, Optional<LocalDate> notBefore,
AtomicLong counter) {
log.debug("Inizio sincronizzazione dell'ufficio id={} del {}, notBefore={}",
officeId, yearMonth, notBefore);
long startTime = System.currentTimeMillis();
Timer.Sample timer = Timer.start(meterRegistry);
List<PersonTimeDetail> details = Lists.newArrayList();
val monthRecaps = epasClient.getMonthRecap(officeId, yearMonth.getYear(), yearMonth.getMonthValue());
monthRecaps.forEach(monthRecap -> {
details.addAll(syncPersonMonth(monthRecap, notBefore));
details.addAll(syncPersonMonth(monthRecap, notBefore, counter));
});
log.info("Terminata sincronizzazione dell'ufficio id={} del {} in {} secondi",
officeId, yearMonth, ((System.currentTimeMillis() - startTime) / 1000));
Expand All @@ -182,11 +187,12 @@ public List<PersonTimeDetail> syncOfficeMonth(
* Sincronizza i dati di presenze ed assenze del mese passato come parametro per tuti i
* dipendenti presenti in ePAS.
*/
public List<PersonTimeDetail> syncMonth(YearMonth yearMonth, Optional<LocalDate> notBefore) {
public List<PersonTimeDetail> syncMonth(YearMonth yearMonth, Optional<LocalDate> notBefore,
AtomicLong counter) {
List<PersonTimeDetail> details = Lists.newArrayList();
val offices = epasClient.getActiveOffices(yearMonth.atDay(1));
offices.forEach(office -> {
details.addAll(syncOfficeMonth(office.getId(), yearMonth, notBefore));
details.addAll(syncOfficeMonth(office.getId(), yearMonth, notBefore, counter));
});
return details;
}
Expand All @@ -201,8 +207,10 @@ public List<PersonTimeDetail> syncAll() {
if (timesheetConfig.isDeleteBeforeSyncAll()) {
deleteAllPersonTimeDetails();
}
Long startingId = repo.findMaxid().orElse(0L);
AtomicLong counter = new AtomicLong(startingId);
while (!yearMonth.isAfter(YearMonth.from(LocalDate.now()))) {
details.addAll(syncMonth(yearMonth, Optional.of(startingDate)));
details.addAll(syncMonth(yearMonth, Optional.of(startingDate), counter));
yearMonth = yearMonth.plusMonths(1);
}
Gauge.builder("epas_synch_details_count", () -> details.size())
Expand Down Expand Up @@ -235,13 +243,4 @@ public void loadDetailsNative() {
repo.loadDetailsJobNative();
}

/**
* Genera un ID univoco per le righe di marcatura di un dipendente di un
* giorno. Per ogni absenceGroup viene generato un ID basato sul suo hashcode
* a cui viene sommato un offset.
*/
public Long personTimeDetailId(PersonDayShowTerseDto personDay, String absenceGroup) {
return personDay.getId() + ID_OFFSET + absenceGroup.hashCode();
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.responses.ApiResponses;
import io.swagger.v3.oas.annotations.tags.Tag;
import it.cnr.iit.epas.timesheet.ugovpj.repo.PersonTimeDetailRepo;
import it.cnr.iit.epas.timesheet.ugovpj.service.CachingService;
import it.cnr.iit.epas.timesheet.ugovpj.service.SyncService;
import it.cnr.iit.epas.timesheet.ugovpj.v1.ApiRoutes;
Expand All @@ -29,6 +30,7 @@
import java.time.YearMonth;
import java.util.List;
import java.util.Optional;
import java.util.concurrent.atomic.AtomicLong;
import java.util.stream.Collectors;
import lombok.RequiredArgsConstructor;
import lombok.val;
Expand All @@ -55,6 +57,7 @@
public class AdminController {

private final SyncService syncService;
private final PersonTimeDetailRepo personTimeDetailRepo;
private final CachingService cachingService;
private final PersonTimeDetailMapper mapper;

Expand Down Expand Up @@ -128,7 +131,10 @@ public ResponseEntity<Void> loadDetailsNative() {
public ResponseEntity<List<PersonTimeDetailDto>> syncOfficeMonthRecap(
@RequestParam("officeId") Long officeId, @RequestParam("year") int year, @RequestParam("month") int month) {
log.info("Ricevuta richiesta aggiornamento del riepilogo mensile per ufficio id={} {}/{}", officeId, month, year);
val details = syncService.syncOfficeMonth(officeId, YearMonth.of(year, month), Optional.empty());
Long startingId = personTimeDetailRepo.findMaxid().orElse(0L);
val details =
syncService.syncOfficeMonth(
officeId, YearMonth.of(year, month), Optional.empty(), new AtomicLong(startingId));
return ResponseEntity.ok().body(details.stream().map(mapper::convert).collect(Collectors.toList()));
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -158,4 +158,15 @@ public ResponseEntity<TimesheetConfigDto> config() {
return ResponseEntity.ok().body(mapper.convert(timesheetConfig));
}

@Operation(
summary = "Visualizzazione del massimo id presente nella tabella delle marcature")
@ApiResponses(value = {
@ApiResponse(responseCode = "200",
description = "Restituiti il massimo id della tabella IE_PJ_MARCATURE.")
})
@GetMapping("/maxId")
public ResponseEntity<Long> maxId() {
log.debug("Ricevuta richiesta max id tabelle marcature");
return ResponseEntity.ok().body(personTimeDetailRepo.findMaxid().orElse(0L));
}
}

0 comments on commit 0956c7f

Please sign in to comment.