Added TimeCardsReporting

This commit is contained in:
Giancarlo Panichi 2021-12-10 14:25:32 +01:00
parent 3ef43f206f
commit 2efd1bcaee
9 changed files with 506 additions and 19 deletions

View File

@ -7,7 +7,10 @@ public final class Constants {
// Regex for acceptable logins
public static final String LOGIN_REGEX = "^(?>[a-zA-Z0-9!$&*+=?^_`{|}~.-]+@[a-zA-Z0-9-]+(?:\\.[a-zA-Z0-9-]+)*)|(?>[_.@A-Za-z0-9-]+)$";
// Regex valid number
public static final String VALID_NUMBER_REGEX="^[0-9]+$";
public static final String SYSTEM_ACCOUNT = "system";
public static final String DEFAULT_LANGUAGE = "en";
public static final String ANONYMOUS_USER = "anonymoususer";

View File

@ -0,0 +1,104 @@
package it.cnr.isti.epasmed.domain;
import java.io.Serializable;
import java.time.LocalDateTime;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.SequenceGenerator;
import javax.persistence.Table;
import javax.validation.constraints.NotNull;
/**
* A user.
*/
@Entity
@Table(name = "timecardsreporting")
public class TimeCardsReporting implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "timecardsreportingSequenceGenerator")
@SequenceGenerator(name = "timecardsreportingSequenceGenerator", allocationSize = 1)
private Long id;
@NotNull
@Column(nullable = false)
public Integer year;
@NotNull
public Integer month;
@NotNull
public Long idFlusso;
@NotNull
@Column(columnDefinition = "TIMESTAMP")
private LocalDateTime lastUpdate;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public Integer getYear() {
return year;
}
public void setYear(Integer year) {
this.year = year;
}
public Integer getMonth() {
return month;
}
public void setMonth(Integer month) {
this.month = month;
}
public Long getIdFlusso() {
return idFlusso;
}
public void setIdFlusso(Long idFlusso) {
this.idFlusso = idFlusso;
}
public LocalDateTime getLastUpdate() {
return lastUpdate;
}
public void setLastUpdate(LocalDateTime lastUpdate) {
this.lastUpdate = lastUpdate;
}
public static long getSerialversionuid() {
return serialVersionUID;
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (!(o instanceof TimeCardsReporting)) {
return false;
}
return id != null && id.equals(((TimeCardsReporting) o).id);
}
@Override
public String toString() {
return "TimeCardsReporting [id=" + id + ", year=" + year + ", month=" + month + ", idFlusso=" + idFlusso
+ ", lastUpdate=" + lastUpdate + "]";
}
}

View File

@ -0,0 +1,20 @@
package it.cnr.isti.epasmed.repository;
import java.util.Optional;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import it.cnr.isti.epasmed.domain.TimeCardsReporting;
import it.cnr.isti.epasmed.domain.User;
/**
* Spring Data JPA repository for the {@link User} entity.
*/
@Repository
public interface TimeCardsReportingRepository extends JpaRepository<TimeCardsReporting, Long> {
Optional<TimeCardsReporting> findOneByYearAndMonth(Integer year, Integer month);
Optional<TimeCardsReporting> findFirstByOrderByIdDesc();
}

View File

@ -0,0 +1,138 @@
package it.cnr.isti.epasmed.service;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Optional;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.convert.ConversionService;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import it.cnr.isti.epasmed.domain.TabsSI;
import it.cnr.isti.epasmed.domain.TimeCardsReporting;
import it.cnr.isti.epasmed.repository.TabsSIRepository;
import it.cnr.isti.epasmed.repository.TimeCardsReportingRepository;
/**
* Service class for managing users.
*/
@Service
@Transactional("epasMedTransactionManager")
public class TimeCardsReportingService {
private final Logger log = LoggerFactory.getLogger(TimeCardsReportingService.class);
private final TimeCardsReportingRepository timeCardsReportingRepository;
@Autowired
ConversionService conversionService;
// @Autowired
// FormattingConversionService conversionDateTimeService;
public TimeCardsReportingService(TimeCardsReportingRepository timeCardsReportingRepository) {
this.timeCardsReportingRepository = timeCardsReportingRepository;
}
@Transactional(value = "epasMedTransactionManager", readOnly = true)
public Page<TimeCardsReporting> getAllTimeCardsReporting(Pageable pageable) {
log.debug("TimeCardsReportingService getAllTimeCardsReporting(): {}", pageable);
timeCardsReportingRepository.findAll();
return timeCardsReportingRepository.findAll(pageable);
}
@Transactional(value = "epasMedTransactionManager", readOnly = true)
public List<TimeCardsReporting> getAllTimeCardsReporting() {
log.debug("TimeCardsReportingService getAllTimeCardsReporting()");
return timeCardsReportingRepository.findAll();
}
@Transactional(value = "epasMedTransactionManager", readOnly = true)
public Optional<TimeCardsReporting> getTimeCardsReportingById(Long id) {
return timeCardsReportingRepository.findById(id);
}
@Transactional(value = "epasMedTransactionManager", readOnly = true)
public Optional<TimeCardsReporting> getLastTimeCardsReporting() {
return timeCardsReportingRepository.findFirstByOrderByIdDesc();
}
/**
* Create a new TimeCards Reporting
*
* @param timeCardsReportingsDTO
* @return TimeCardsReporting
*/
public TimeCardsReporting createTimeCardsReporting(TimeCardsReporting timeCardsReportingsDTO) {
log.debug("Creating new TimeCardsReporting: {}", timeCardsReportingsDTO);
TimeCardsReporting timeCardsReporting = new TimeCardsReporting();
timeCardsReporting.setYear(timeCardsReportingsDTO.getYear());
timeCardsReporting.setMonth(timeCardsReportingsDTO.getMonth());
timeCardsReporting.setIdFlusso(timeCardsReportingsDTO.getIdFlusso());
timeCardsReporting.setLastUpdate(timeCardsReportingsDTO.getLastUpdate());
timeCardsReportingRepository.save(timeCardsReporting);
log.debug("Created TimeCardsReporting: {}", timeCardsReporting);
return timeCardsReporting;
}
/**
* Update all information for a specific timecards reporting.
*
* @param timeCardsReporting
* @return
*/
public Optional<TimeCardsReporting> updateTimeCardsReporting(TimeCardsReporting timeCardsReporting) {
Optional<TimeCardsReporting> tcR = timeCardsReportingRepository.findById(timeCardsReporting.getId());
if (tcR.isPresent()) {
TimeCardsReporting timeCardsR = tcR.get();
timeCardsR.setYear(timeCardsReporting.getYear());
timeCardsR.setMonth(timeCardsReporting.getMonth());
timeCardsR.setIdFlusso(timeCardsReporting.getIdFlusso());
timeCardsR.setLastUpdate(timeCardsReporting.getLastUpdate());
timeCardsR = timeCardsReportingRepository.save(timeCardsR);
log.debug("Changed Information for TimeCardsReporting: {}", timeCardsR);
return Optional.of(timeCardsR);
} else {
return tcR;
}
}
public void deleteTimeCardsReporting(Long id) {
timeCardsReportingRepository.findById(id).ifPresent(tcR -> {
timeCardsReportingRepository.delete(tcR);
log.debug("Deleted TimeCardsReporting: {}", tcR);
});
}
/**
* Update TimeCardsReporting information (id, year, month, id flusso, last update).
*
* @param id Identify
* @param year Year
* @param month Month
* @param idFlusso Id Flusso
* @param lastUpdate Last Update
*/
public void updateTimeCardsReporting(String id, Integer year, Integer month, String idFlusso, String lastUpdate) {
LocalDateTime lastU = conversionService.convert(lastUpdate, LocalDateTime.class);
// LocalDateTime lastU=conversionDateTimeService.convert(lastUpdate,
// LocalDateTime.class);
Optional.of(timeCardsReportingRepository.findById(Long.valueOf(id))).filter(Optional::isPresent).map(Optional::get)
.map(tcR -> {
tcR.setYear(year);
tcR.setMonth(month);
tcR.setIdFlusso(Long.valueOf(idFlusso));
tcR.setLastUpdate(lastU);
log.debug("Changed Information for TimeCardsReporting: {}", tcR);
return tcR;
});
}
}

View File

@ -5,6 +5,7 @@ import java.time.LocalDateTime;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.List;
import java.util.Optional;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -12,6 +13,7 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import it.cnr.isti.epasmed.domain.TabsSI;
import it.cnr.isti.epasmed.domain.TimeCardsReporting;
import it.cnr.isti.epasmed.epas.dto.EPASAffiliationsDTO;
import it.cnr.isti.epasmed.epas.dto.EPASGroupsDTO;
import it.cnr.isti.epasmed.epas.dto.EPASPersonsDTO;
@ -29,6 +31,7 @@ import it.cnr.isti.epasmed.epas.service.EPASPersonsService;
import it.cnr.isti.epasmed.epas.service.EPASTimeCardsService;
import it.cnr.isti.epasmed.epas.service.EPASValidatesService;
import it.cnr.isti.epasmed.service.TabsSIService;
import it.cnr.isti.epasmed.service.TimeCardsReportingService;
import it.cnr.isti.epasmed.sistemainformativo.model.SIAnagrafico;
import it.cnr.isti.epasmed.sistemainformativo.model.SIEmail;
import it.cnr.isti.epasmed.sistemainformativo.model.SIGruppi;
@ -56,6 +59,8 @@ public class SyncService {
private final SimpleDateFormat sdfDate = new SimpleDateFormat("yyyy-MM-dd");
@Autowired
TabsSIService tabsSIService;
@Autowired
TimeCardsReportingService timeCardsReportingService;
@Autowired
SIMasterLogService siMasterLogService;
@ -678,12 +683,17 @@ public class SyncService {
private void syncCartelliniRendicontazioni(Long idFlux, TabsSI tab) {
if (tab.getIdFlusso() == null || tab.getIdFlusso().longValue() == 0) {
log.info("Invalid Id Flusso for tab: {}", tab);
log.error("Invalid Id Flusso for tab: {}", tab);
return;
}
long maxIdFlusso = 0;
GregorianCalendar lastMonthSent = new GregorianCalendar(2021, 11, 1);
Optional<TimeCardsReporting> lastTcR=timeCardsReportingService.getLastTimeCardsReporting();
if(!lastTcR.isPresent()) {
log.error("Invalid TimeCardsReporting start point: {}", tab);
return;
}
GregorianCalendar nextMonthToSent = new GregorianCalendar();
nextMonthToSent.setTime(lastMonthSent.getTime());
nextMonthToSent.add(GregorianCalendar.MONTH, 1);
@ -696,12 +706,10 @@ public class SyncService {
return;
}
// TODO
log.info("Certifications Validated: [year={}, month={}]", y, m);
for (EPASPersons person : epasValidates.getValidatedPersons()) {
log.info("Writing TimeCard for Person: {}", person);
EPASTimeCards epasTimeCards = epasTimeCardsService.getTimeCardByPersonEmail(person.getEmail(), y, m);
}
}

View File

@ -49,7 +49,7 @@ import it.cnr.isti.epasmed.web.rest.errors.BadRequestAlertException;
@RequestMapping("/api")
public class TabsSIResource {
private static final List<String> ALLOWED_ORDERED_PROPERTIES = Collections
.unmodifiableList(Arrays.asList("id", "login", "firstName", "lastName", "email", "activated", "langKey"));
.unmodifiableList(Arrays.asList("id", "nome", "operazioni", "idFlusso", "lastUpdate"));
private final Logger log = LoggerFactory.getLogger(TabsSIResource.class);
@ -58,11 +58,8 @@ public class TabsSIResource {
private final TabsSIService tabsSIService;
//private final TabsSIRepository tabsSIRepository;
public TabsSIResource(TabsSIService tabsSIService) {
this.tabsSIService = tabsSIService;
//this.tabsSIRepository = tabsSIRepository;
}
@ -94,16 +91,12 @@ public class TabsSIResource {
/**
* {@code POST /tabssi} : Creates a new table for SI.
* <p>
* Creates a new user if the login and email are not already used, and sends an
* mail with an activation link. The user needs to be activated on creation.
*
* @param tabsSIDTO the user to create.
* @param tabsSIDTO table to create.
* @return the {@link ResponseEntity} with status {@code 201 (Created)} and with
* body the new table SI, or with status {@code 400 (Bad Request)} if
* the id is already in use.
* @throws URISyntaxException if the Location URI syntax is incorrect.
* @throws BadRequestAlertException {@code 400 (Bad Request)} if the id is
* already in use.
* @throws URISyntaxException if the Location URI syntax is incorrect.
*/
@PostMapping("/tabssi")
@PreAuthorize("hasAuthority(\"" + AuthoritiesConstants.ADMIN + "\")")
@ -122,7 +115,7 @@ public class TabsSIResource {
}
/**
* {@code PUT /users} : Updates an existing User.
* {@code PUT /tabssi} : Updates an tab SI.
*
* @param tabsSIDTO the table of SI to update.
* @return the {@link ResponseEntity} with status {@code 200 (OK)} and with body
@ -144,9 +137,9 @@ public class TabsSIResource {
*
* @param id the id of the table SI to find.
* @return the {@link ResponseEntity} with status {@code 200 (OK)} and with body
* the "login" user, or with status {@code 404 (Not Found)}.
* the tab SI, or with status {@code 404 (Not Found)}.
*/
@GetMapping("/tabssi/{id:" + Constants.LOGIN_REGEX + "}")
@GetMapping("/tabssi/{id:" + Constants.VALID_NUMBER_REGEX + "}")
public ResponseEntity<TabsSI> getTabsSI(@PathVariable String id) {
log.debug("REST request to get Table SI : {}", id);
return ResponseUtil.wrapOrNotFound(tabsSIService.getTabsSIById(Long.valueOf(id)));
@ -159,9 +152,9 @@ public class TabsSIResource {
* @param id the id of the table SI to delete.
* @return the {@link ResponseEntity} with status {@code 204 (NO_CONTENT)}.
*/
@DeleteMapping("/tabssi/{id:" + Constants.LOGIN_REGEX + "}")
@DeleteMapping("/tabssi/{id:" + Constants.VALID_NUMBER_REGEX + "}")
@PreAuthorize("hasAuthority(\"" + AuthoritiesConstants.ADMIN + "\")")
public ResponseEntity<Void> deleteUser(@PathVariable String id) {
public ResponseEntity<Void> deleteTabsSI(@PathVariable String id) {
log.debug("REST request to delete Table SI id: {}", id);
tabsSIService.deleteTabsSI(Long.valueOf(id));
return ResponseEntity.noContent()

View File

@ -0,0 +1,195 @@
package it.cnr.isti.epasmed.web.rest;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
import javax.validation.Valid;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.support.ServletUriComponentsBuilder;
import io.github.jhipster.web.util.HeaderUtil;
import io.github.jhipster.web.util.PaginationUtil;
import io.github.jhipster.web.util.ResponseUtil;
import it.cnr.isti.epasmed.config.Constants;
import it.cnr.isti.epasmed.domain.TimeCardsReporting;
import it.cnr.isti.epasmed.security.AuthoritiesConstants;
import it.cnr.isti.epasmed.service.TimeCardsReportingService;
import it.cnr.isti.epasmed.web.rest.errors.BadRequestAlertException;
/**
* REST controller for managing TimeCardsReporting.
* <p>
* This class accesses the {@link TimeCardsReporting} entity.
*
*
*/
@RestController
@RequestMapping("/api")
public class TimeCardsReportingResource {
private static final List<String> ALLOWED_ORDERED_PROPERTIES = Collections
.unmodifiableList(Arrays.asList("id", "year", "month", "idFlusso", "lastUpdate"));
private final Logger log = LoggerFactory.getLogger(TimeCardsReportingResource.class);
@Value("${jhipster.clientApp.name}")
private String applicationName;
private final TimeCardsReportingService timeCardsReportingService;
public TimeCardsReportingResource(TimeCardsReportingService timeCardsReportingService) {
this.timeCardsReportingService = timeCardsReportingService;
}
/**
* {@code GET /timecardsreporting} : get all timecards reporting.
*
* @param pageable the pagination information.
* @return the {@link ResponseEntity} with status {@code 200 (OK)} and with body
* all TimeCardsReporting.
*/
@GetMapping("/timecardsreporting")
public ResponseEntity<List<TimeCardsReporting>> getAllTimeCardsReporting(Pageable pageable) {
log.info("REST request to read all TimeCardsReporting : {}", pageable);
if (!onlyContainsAllowedProperties(pageable)) {
return ResponseEntity.badRequest().build();
}
final Page<TimeCardsReporting> page = timeCardsReportingService.getAllTimeCardsReporting(pageable);
HttpHeaders headers = PaginationUtil
.generatePaginationHttpHeaders(ServletUriComponentsBuilder.fromCurrentRequest(), page);
return new ResponseEntity<>(page.getContent(), headers, HttpStatus.OK);
}
private boolean onlyContainsAllowedProperties(Pageable pageable) {
return pageable.getSort().stream().map(Sort.Order::getProperty).allMatch(ALLOWED_ORDERED_PROPERTIES::contains);
}
/**
* {@code POST /timecardsreporting} : Creates a new timecards reporting.
* <p>
*
* @param timeCardsReporting the timecards reporting to create.
* @return TimeCardsReporting the new time cards reporting.
* @throws URISyntaxException if the Location URI syntax is incorrect.
*
*/
@PostMapping("/timecardsreporting")
@PreAuthorize("hasAuthority(\"" + AuthoritiesConstants.ADMIN + "\")")
public ResponseEntity<TimeCardsReporting> createTimeCardsReporting(
@Valid @RequestBody TimeCardsReporting timeCardsReporting) throws URISyntaxException {
log.info("REST request to save TimeCardsReporting : {}", timeCardsReporting);
if (timeCardsReporting.getId() != null) {
throw new BadRequestAlertException("A new timecards reporting already have an ID", "TimeCardsReporting",
"idexists");
} else {
TimeCardsReporting newTcR = timeCardsReportingService.createTimeCardsReporting(timeCardsReporting);
StringBuilder m = new StringBuilder();
m.append(newTcR.getYear());
m.append("/");
m.append(newTcR.getMonth());
return ResponseEntity.created(new URI("/api/timecardsreporting/" + newTcR.getId()))
.headers(HeaderUtil.createAlert(applicationName,
"A timecards reporting is created with identifier " + newTcR.getId(), m.toString()))
.body(newTcR);
}
}
/**
* {@code PUT /timecardsreporting} : Updates an existing timecards reporting.
*
* @param timeCardsReportingDTO the timecards reporting to update.
* @return the {@link ResponseEntity} with status {@code 200 (OK)} and with body
* the updated timecards reporting.
*
*/
@PutMapping("/timecardsreporting")
@PreAuthorize("hasAuthority(\"" + AuthoritiesConstants.ADMIN + "\")")
public ResponseEntity<TimeCardsReporting> updateTimeCardsReporting(
@Valid @RequestBody TimeCardsReporting timeCardsReportingDTO) {
log.debug("REST request to update TimeCards Reporting : {}", timeCardsReportingDTO);
Optional<TimeCardsReporting> updatedTimeCardsReporting = timeCardsReportingService
.updateTimeCardsReporting(timeCardsReportingDTO);
StringBuilder m = new StringBuilder();
if (updatedTimeCardsReporting.isPresent()) {
m.append(updatedTimeCardsReporting.get().getYear());
m.append("/");
m.append(updatedTimeCardsReporting.get().getMonth());
} else {
}
return ResponseUtil.wrapOrNotFound(updatedTimeCardsReporting, HeaderUtil.createAlert(applicationName,
"A timecards reporting is updated with identifier " + timeCardsReportingDTO.getId(), m.toString()));
}
/**
* {@code GET /timecardsreporting/:id} : get timecards reporting by id.
*
* @param id the id of the timecards reporting to find.
* @return the {@link ResponseEntity} with status {@code 200 (OK)} and with body
* the timecards reporting, or with status {@code 404 (Not Found)}.
*/
@GetMapping("/timecardsreporting/{id:" + Constants.VALID_NUMBER_REGEX + "}")
public ResponseEntity<TimeCardsReporting> getTimeCardsReporting(@PathVariable String id) {
log.debug("REST request to get TimeCards Reporting : {}", id);
return ResponseUtil.wrapOrNotFound(timeCardsReportingService.getTimeCardsReportingById(Long.valueOf(id)));
}
/**
* {@code DELETE /timecardsreporting/:id} : delete the timecards reporting by
* id.
*
* @param id the id of the timecards reporting to delete.
* @return the {@link ResponseEntity} with status {@code 204 (NO_CONTENT)}.
*/
@DeleteMapping("/timecardsreporting/{id:" + Constants.VALID_NUMBER_REGEX + "}")
@PreAuthorize("hasAuthority(\"" + AuthoritiesConstants.ADMIN + "\")")
public ResponseEntity<Void> deleteUser(@PathVariable String id) {
log.debug("REST request to delete TimeCards Reporting id: {}", id);
timeCardsReportingService.deleteTimeCardsReporting(Long.valueOf(id));
return ResponseEntity.noContent().headers(
HeaderUtil.createAlert(applicationName, "A timecards reporting is deleted with identifier " + id, id))
.build();
}
/**
* {@code GET /timecardsreporting/last} : get last timecards reporting.
*
* @return the {@link ResponseEntity} with status {@code 200 (OK)} and with body
* the timecards reporting, or with status {@code 404 (Not Found)}.
*/
@GetMapping("/timecardsreporting/last")
public ResponseEntity<TimeCardsReporting> getTimeCardsReporting() {
log.debug("REST request to get Last TimeCards Reporting");
return ResponseUtil.wrapOrNotFound(timeCardsReportingService.getLastTimeCardsReporting());
}
}

View File

@ -197,6 +197,29 @@
<column name="id_flusso" type="numeric" />
<column name="last_update" type="timestamp" />
</loadData>
<createSequence sequenceName="timecardsreporting_sequence_generator"
startValue="17" incrementBy="1" />
<createTable tableName="timecardsreporting">
<column name="id" type="bigint">
<constraints primaryKey="true"
primaryKeyName="timecardsreporting_id" />
</column>
<column name="year" type="int" />
<column name="month" type="int" />
<column name="id_flusso" type="bigint" />
<column name="last_update" type="timestamp" />
</createTable>
<loadData file="config/liquibase/epasmed/data/timecardsreporting.csv"
separator="," tableName="timecardsreporting">
<column name="id" type="numeric" />
<column name="year" type="numeric" />
<column name="month" type="numeric" />
<column name="id_flusso" type="numeric" />
<column name="last_update" type="timestamp" />
</loadData>
</changeSet>
</databaseChangeLog>

View File

@ -0,0 +1,3 @@
id,year,month,id_flusso,last_update
1,2021,9,116002,2020-12-07 06:33:01
2,2021,10,116214,2020-12-14 06:33:01
1 id year month id_flusso last_update
2 1 2021 9 116002 2020-12-07 06:33:01
3 2 2021 10 116214 2020-12-14 06:33:01