gestione gare pubbliche
Non puoi selezionare più di 25 argomenti Gli argomenti devono iniziare con una lettera o un numero, possono includere trattini ('-') e possono essere lunghi fino a 35 caratteri.
 
 
 
 
 

696 righe
22 KiB

<?php
/**
* Gestore delle deleghe ANAC NPA
*/
trait Deleghe
{
public function verifyDelega()
{
global $beRoot;
$utente = $_SESSION["utente"] ?? null;
if(!$utente) {
swalDie("Utente non valido.", "Attenzione", "reload", "error", false);
}
// Otteniamo le info utente
$userInfo = method_exists($utente, "getInfo") ? $utente->getInfo() : [];
// Prendiamo il CF dell'utente
$cf = $userInfo["cf"] ?? null;
if (!$cf) {
swalDie("Utente non valido.", "Attenzione", "reload", "error", false);
}
$delega = $this->getFullDelegaInfo($cf);
// L'utente ha già una collaborazione
if(!empty($delega["sa_cf"]) && !empty($delega["sa_ausa"])) {
return;
}
// STEP 1. Cerchiamo di recuperare la collaobrazione dall'ultimo JWT valido
// TODO Implementare
// STEP 2. Chiediamo all'utente di stabilire la collaborazione
if(!empty($this->fascicolo["stazioni_appaltanti"])) {
$sceltaSA = json_decode($this->fascicolo["stazioni_appaltanti"], true);
}
if(empty($sceltaSA) && !empty($this->scheda["dati"]) && valid_json($this->scheda["dati"], $dati, true)) {
$sceltaSA = DotPath::get($dati, "anacForm.stazioniAppaltanti");
if(!empty($sceltaSA))
$sceltaSA = array_values($sceltaSA);
}
if(empty($sceltaSA)) {
swalDie("Impossibile trovare Stazioni Appaltanti per la collaborazione.", "Attenzione", "reload", "error", false);
}
// Ora che abbiamo le scelte
if(count($sceltaSA) > 1) {
$sceltaUtente = $_REQUEST["scelta_sa"] ?? null;
if($sceltaUtente === null || !is_numeric($sceltaUtente)) {
$requestType = $_SERVER['REQUEST_METHOD'];
$requestUrl = $_SERVER['REQUEST_URI'];
$params = $requestType === 'POST' ? $_POST : $_GET;
// Convertiamo i dati in query string per passarli nell'URL
$paramsQuery = http_build_query(['params' => $params]);
$choicesQuery = http_build_query(['stazioni_appaltanti' => $sceltaSA]);
$modalUrl = "/backend/npa/ajax/request_collaborazione.php?requestType={$requestType}&requestUrl=" . urlencode($requestUrl) . "&{$paramsQuery}&{$choicesQuery}";
// Interrompiamo l'esecuzione dello script PHP e mostriamo la modale
die("showModalWithURL('$modalUrl');");
}
} else {
$sceltaUtente = 0;
}
$stazioneAppaltante = $sceltaSA[$sceltaUtente] ?? null;
if(empty($stazioneAppaltante)) {
swalDie("Impossibile trovare la Stazione Appaltante selezionata.", "Attenzione", "reload", "error", false);
}
$this->overrideStazioneAppaltante = $stazioneAppaltante;
}
/**
* Interroga il database per ottenere la delega utente in base al suo CF e al codice NPA (o il CF a partire dalla delega)
*
* @param ?string $cf Codice fiscale per cui cercare. Non indicare se si vuole cercare un CF in base al ruolo.
* @param ?string $role Ruolo per cui cercare. Non indicare se si vuole cercare un ruolo in base al CF
* @param integer $codice Codice NPA
* @return array|null Ritorna un array contenente l'intera row trovata o null se non c'è
*/
public static function fullEntryFromDB(?string $cf = null, ?string $role = null, int $codice)
{
if (($cf === null && $role === null) || ($cf !== null && $role !== null)) {
throw new Exception("searchFromDB va chiamato con SOLO cf o role");
}
/**
* @var \myPDO $pdo
*/
global $pdo;
if ($role === null) {
return $pdo->go(
"SELECT * FROM b_npa_deleghe d WHERE d.codice_npa = :codice AND cf = :cf",
[":cf" => $cf, ":codice" => $codice]
)->fetch(PDO::FETCH_ASSOC);
}
if (!in_array($role, DelegheRoles::VALID_ROLES)) return null;
return $pdo->go(
"SELECT * FROM b_npa_deleghe d WHERE d.codice_npa = :codice AND role = :role",
[":role" => $role, ":codice" => $codice]
)->fetch(PDO::FETCH_ASSOC) ?? null;
}
/**
* Interroga il database per ottenere la delega utente in base al suo CF e al codice NPA (o il CF a partire dalla delega)
*
* @param ?string $cf Codice fiscale per cui cercare. Non indicare se si vuole cercare un CF in base al ruolo.
* @param ?string $role Ruolo per cui cercare. Non indicare se si vuole cercare un ruolo in base al CF
* @param integer $codice Codice NPA
* @return string|null ritorna RP, DRP1, DRP2, DRP3 o null o un codice fiscale
*/
public static function searchFromDB(?string $cf = null, ?string $role = null, int $codice)
{
if (($cf === null && $role === null) || ($cf !== null && $role !== null)) {
throw new Exception("searchFromDB va chiamato con SOLO cf o role");
}
/**
* @var \myPDO $pdo
*/
global $pdo;
// Ritorniamo un role
if ($role === null) {
$role = $pdo->go(
"SELECT d.role FROM b_npa_deleghe d WHERE d.codice_npa = :codice AND cf = :cf",
[":cf" => $cf, ":codice" => $codice]
)->fetch(PDO::FETCH_ASSOC)["role"] ?? null;
// Verifichiamo la validità del ruolo
if (!$role || !in_array($role, DelegheRoles::VALID_ROLES)) return null;
return $role;
}
// Ritorniamo un cf
if (!in_array($role, DelegheRoles::VALID_ROLES)) return null;
return $pdo->go(
"SELECT d.cf FROM b_npa_deleghe d WHERE d.codice_npa = :codice AND role = :role",
[":role" => $role, ":codice" => $codice]
)->fetch(PDO::FETCH_ASSOC)["cf"] ?? null;
}
/**
* Metodo per rimuovre una delega da un fascicolo anac sul DB
*
* @param string|null $role Ruolo da rimuovere
* @param integer $codice Codice NPA
* @return void
*/
private static function deleteUserRoleFromDB(string $role, int $codice)
{
/**
* @var \myPDO $pdo
*/
global $pdo;
$pdo->go(
"DELETE FROM `b_npa_deleghe` WHERE `role` = :role AND `codice_npa` = :codice",
[":role" => $role, ":codice" => $codice]
);
}
/**
* Metodo per aggiornare il ruolo di un utente sul DB. Non chiede ad ANAC
*
* @param string $cf Codice fiscale del soggetto
* @param string|null $role Ruolo da assegnare
* @param integer $codice Codice NPA
* @return bool True se tutto va bene
*/
private static function setUserRoleToDB(string $cf, string $role, int $codice, ?string $sa_cf = null, ?string $sa_ausa = null)
{
/**
* @var \myPDO $pdo
*/
global $pdo;
if ($role === DelegheRoles::UNAUTHORIZED)
return true;
$data = [
"cf" => $cf,
"role" => $role,
"codice_npa" => $codice,
];
if(!empty($sa_cf)) {
$data["sa_cf"] = $sa_cf;
}
if(!empty($sa_ausa)) {
$data["sa_ausa"] = $sa_ausa;
}
$bind = [];
$fields_str = $values_str = $update_str = "";
$i = 0;
foreach($data as $key => $value) {
$bind[":{$key}"] = $value;
$comma = ($i > 0 ? ", " : "");
$fields_str .= "{$comma} {$key}";
$values_str .= "{$comma} :{$key}";
$update_str .= "{$comma} {$key} = :{$key}";
$i++;
}
$query = <<<SQL
INSERT INTO `b_npa_deleghe` ({$fields_str})
VALUES ({$values_str})
ON DUPLICATE KEY UPDATE
{$update_str}
SQL;
$exec = $pdo->go($query, $bind);
return $exec->rowCount() > 0;
}
/**
* Interroga i server anac per ottenere il ruolo dell'utente attuale
*
* @param ?string $cf Codice fiscale per cui cercare. Non indicare se si vuole cercare un CF in base al ruolo.
* @param ?string $role Ruolo per cui cercare. Non indicare se si vuole cercare un ruolo in base al CF
* @return string|null ritorna RP, DRP1, DRP2, DRP3, UNAUTHORIZED o null
*/
public function searchFromANAC(?string $cf = null, ?string $role = null)
{
date_default_timezone_set('Europe/Rome');
if (($cf === null && $role === null) || ($cf !== null && $role !== null)) {
throw new Exception("searchFromDB va chiamato con SOLO cf o role");
}
// Vediamo se abbiamo un idAppalto
if (empty($this->fascicolo) || empty($this->fascicolo["id_appalto"])) {
return null;
}
$idAppalto = $this->fascicolo["id_appalto"];
$searchTerms = [
"idAppalto" => $idAppalto,
//"dataInizioA" => (new \DateTime("-15 seconds"))->format('Y-m-d\TH:i:s') . "+00:00", // Non ancora scaduto
"dataFineDa" => (new \DateTime("+15 seconds"))->format('Y-m-d\TH:i:s') . "+00:00", // Non ancora scaduto
];
if ($cf !== null) {
$cf = strtoupper(trim($cf));
if (empty($cf)) return null;
$searchTerms["codiceFiscale"] = $cf;
}
if ($role !== null) {
$role = strtoupper(trim($role));
if (empty($role)) return null;
}
$result_str = $this->apiCall(
"gestioneUtenti",
"ricerca-soggetti",
$searchTerms,
);
// Verifichiamo la risposta
if (empty($result_str) || !valid_json($result_str, $result_list, TRUE)) {
return null;
};
// Se non ci sono risultati ritorniamo null per la ricerca del ruolo o UNAUTHORIZED per la ricerca per CF
if (empty($result_list["result"])) {
return $cf === null ? null : DelegheRoles::UNAUTHORIZED;
}
foreach ($result_list["result"] as $result) {
if ($cf !== null && trim(strtoupper($result["codiceFiscale"])) === $cf) {
// Ritorniamo un ruolo
$role = strtoupper($result["ruolo"]["codice"]);
// Verifichiamo sia valido
if (!$role || !in_array($role, DelegheRoles::VALID_ROLES)) return null;
return $role;
} elseif ($role !== null && $result["ruolo"]["codice"] === $role) {
return trim(strtoupper($result["codiceFiscale"]));
}
}
return null;
}
/**
* Imposta il ruolo di un utente
*
* @param ?string $cf Codice fiscale dell'utente in questione. Non usato per remove
* @param string $role Ruolo da assegnare/rimuovere (vedi DelegheRoles)
* @param string $remove Se true, rimuove il ruolo dal soggetto
* @param string|null $message Eventuale messaggio di fallimento
* @param bool $recursive Per uso interno
* @return bool Ritorna true se tutto va bene
*/
public function setUserRole(?string $cf, string $role, ?string $sa_cf, ?string $sa_ausa, bool $remove = false, ?string &$message = null, bool $recursive = false)
{
date_default_timezone_set('Europe/Rome');
// Vediamo se abbiamo un idAppalto
if (empty($this->fascicolo) || empty($this->fascicolo["id_appalto"])) {
$message = "Questo appalto non è pronto ad accettare deleghe.";
return false;
}
$idAppalto = $this->fascicolo["id_appalto"];
$endpoint = "gestioneUtenti";
if ($cf !== null)
$cf = strtoupper(trim($cf));
if ($role == DelegheRoles::RP) {
// Per settare un nuovo RP possiamo farlo solo per l'utente corrente
$utente = $_SESSION["utente"] ?? null;
// Verifichiamo il livello di autenticazione
if (!$utente || $utente->authenticationLevel < 2) {
$message = "Impossibile prendere carico della gara. Permessi insufficienti.";
return false;
}
if(!$this->canCurrentUserTakeOver()) {
$message = "Impossibile prendere il carico della gara. Non sei nominato come RUP.";
return false;
}
// Otteniamo le info utente
$userInfo = method_exists($utente, "getInfo") ? $utente->getInfo() : [];
// Prendiamo il CF dell'utente
$current_cf = $userInfo["cf"] ?? null;
if (!$current_cf) {
$message = "Impossibile prendere carico della gara. Codice Fiscale non impostato.";
return false;
}
$cf = strtoupper(trim($current_cf));
// Creiamo l'authorization personalizzata
$apiConfig = $this->api_config[$endpoint];
$method = "presa-carico";
$claims = $this->getAnacJwsCustomClaims(
$apiConfig["endpoint"],
$this->getUUID(),
$cf,
DelegheRoles::RP,
$sa_cf,
$sa_ausa
);
// Effettuiamo la presa carico
$apiMessage = null;
$response_str = $this->apiCall($endpoint, $method, ["idAppalto" => $idAppalto], $claims, [], $apiMessage);
// Verifichiamo ci sia una risposta
if (empty($response_str) || !valid_json($response_str, $response, TRUE)) {
$message = empty($apiMessage) ? __("Errore durante la richiesta di presa carico.") : __($apiMessage);
return false;
}
// Verifichiamo ci sia un errore
if ($response["status"] !== 200) {
if (isset($response["errori"][0]["codice"])) {
$dictionary = $this->getErrorsDictionary();
$codice_errore = $response["errori"][0]["codice"];
$message = $dictionary[$response["errori"][0]["codice"]]["descrizione"]["it"] ?? null;
}
$message = $message == null ? __("Errore durante nella risposta per la richiesta di delega.") : $message;
return false;
}
// Aggiorniamo il RUP nel fascicolo
if(isset($this->fascicolo["data"]) ) {
$data = unserialize($this->fascicolo["data"]);
$data["rup"]["codice_fiscale"] = $cf;
$salva = new Salva();
$salva->debug = false;
$salva->operazione = "UPDATE";
$salva->nome_tabella = "b_npa";
$salva->ignore = ["timestamp"];
$salva->ignore_versione = true;
$salva->oggetto = ["codice" => $this->fascicolo["codice"], "data" => serialize($data)];
if(!$salva->save()) {
$message = __("Errore durante l'aggiornamento del RUP");
return false;
}
}
return self::setUserRoleToDB($cf, $role, $this->fascicolo["codice"], $sa_cf, $sa_ausa);
}
$method = $remove ? "elimina-soggetto" : "aggiungi-soggetto";
// Campo in comune per entrambe le richieste
$query = [
"idAppalto" => $idAppalto,
"ruolo" => [
"idTipologica" => "tipoRuolo",
"codice" => $role,
],
];
// La delega richiede una data di inizio
if ($method === "aggiungi-soggetto") {
$query["dataInizio"] = (new \DateTime())->format(\DateTime::ATOM);
$query["codiceFiscale"] = $cf;
}
$apiMessage = null;
$response_str = $this->apiCall($endpoint, $method, $query, null, [], $apiMessage);
// Verifichiamo ci sia una risposta
if (empty($response_str) || !valid_json($response_str, $response, TRUE)) {
$message = empty($apiMessage) ? __("Errore durante la richiesta di delega.") : __($apiMessage);
return false;
}
// Verifichiamo ci sia un errore
if ($response["status"] !== 200) {
if (isset($response["errori"][0]["codice"])) {
$dictionary = $this->getErrorsDictionary();
$codice_errore = $response["errori"][0]["codice"];
$message = $dictionary[$response["errori"][0]["codice"]]["descrizione"]["it"] ?? null;
// Gestione situazioni di desync
if (!$recursive) {
// In questa situazione c'è già un delegato che non era sincronizzato con il DB
if ($codice_errore === "ERR80" && !$remove) {
// Eliminiamo il precedente e ricreiamo
if ($this->setUserRole(null, $role, $sa_cf, $sa_ausa, true, $message, true)) {
if ($this->setUserRole($cf, $role, $sa_cf, $sa_ausa, false, $message, true)) {
return self::setUserRoleToDB($cf, $role, $this->fascicolo["codice"], $sa_cf, $sa_ausa);
}
}
}
// Tentativo di rimozione di un delegato già rimosso
elseif ($codice_errore == "AUT10" && $remove) {
// Rimuoviamo dal db e basta
$this->deleteUserRoleFromDB($role, $this->fascicolo["codice"]);
return true;
}
}
}
$message = $message == null ? __("Errore durante nella risposta per la richiesta di delega.") : $message;
return false;
}
// Le chiamate ricorsive non toccano il db
if ($recursive) return true;
// Aggiorniamo il db
if ($remove) {
$this->deleteUserRoleFromDB($role, $this->fascicolo["codice"]);
return true;
}
return self::setUserRoleToDB($cf, $role, $this->fascicolo["codice"], $sa_cf, $sa_ausa);
}
public function getFullDelegaInfo(string $cf)
{
return self::fullEntryFromDB($cf, null, $this->fascicolo["codice"]);
}
/**
* Ottiene un codice fiscale in base al ruolo specificato
*
* @param string|array $role
* @param int $syncBehaviour
* @return string|null|array Ritorna un CF o null
*/
public function getUserFromRole($role, int $syncBehaviour = RoleSyncBehaviour::NEVER_SYNC)
{
if(is_array($role)) {
foreach ($role as $r) {
$retVal[] = $this->getUserFromRole($r, $syncBehaviour);
}
return $retVal;
}
$retVal = null;
// Determiniamo se dobbiamo chiedere ad anac
$syncFromAnac = $syncBehaviour == RoleSyncBehaviour::ALWAYS_SYNC;
// Vediamo se abbiamo un codice
if (empty($this->fascicolo)) {
return null;
}
// Verifichiamo di avere un ruolo nel DB
if(empty($this->fascicolo["codice"]))
$retVal = $db_cf = null;
else
$retVal = $db_cf = self::searchFromDB(null, $role, $this->fascicolo["codice"]);
if ($db_cf == null) {
// Il RUP al primo caricamento viene preso dal fascicolo
if ($role == DelegheRoles::RP && !empty($this->fascicolo["data"])) {
// Prendiamo il CF del RUP nel caso stiamo cercando un RP
$cf_npa = unserialize($this->fascicolo["data"])["rup"]["codice_fiscale"] ?? null;
if (!empty($cf_npa)) {
$retVal = $cf_npa;
}
}
// Determiniamo se ora dobbiamo sincronizzare da ANAC
$syncFromAnac = $syncFromAnac || $syncBehaviour == RoleSyncBehaviour::SYNC_ON_NULL;
}
// Se dobbiamo sincronizzare scarichiamo anac
if ($syncFromAnac) {
$anac_cf = $this->searchFromANAC(null, $role);
// Se è diverso, sincronizziamo il db
if ($anac_cf !== null) {
$retVal = $anac_cf;
}
}
// Se il risultato è diverso, sincronizziamo sul db
if ($retVal !== $db_cf && !empty($this->fascicolo["codice"])) {
self::setUserRoleToDB($retVal, $role, $this->fascicolo["codice"]);
}
return empty($retVal) ? $retVal : trim(strtoupper($retVal));
}
/**
* Determina se l'utente corrente può diventare il nuovo RP essendo RUP dell'oggetto
*
* @return boolean
*/
public function canCurrentUserTakeOver() {
$rup_cf = null;
if(isset($this->oggetto) && method_exists($this->oggetto, "getRup")) {
$rup_cf = $this->oggetto->getRup()["codice_fiscale"] ?? null;
}
if($rup_cf === null) return false;
$utente = $_SESSION["utente"] ?? null;
// Verifichiamo il livello di autenticazione
if (!$utente || $utente->authenticationLevel < 2) return false;
// Otteniamo le info utente
$userInfo = method_exists($utente, "getInfo") ? $utente->getInfo() : [];
// Prendiamo il CF dell'utente
$cf = $userInfo["cf"] ?? null;
if($cf === null) return false;
return trim(strtoupper($rup_cf)) === trim(strtoupper($cf));
}
public function getCurrentUserRole(int $syncBehaviour = RoleSyncBehaviour::NEVER_SYNC)
{
$utente = $_SESSION["utente"] ?? null;
// Verifichiamo il livello di autenticazione
if (!$utente || $utente->authenticationLevel < 2) {
return DelegheRoles::UNAUTHORIZED;
}
// Otteniamo le info utente
$userInfo = method_exists($utente, "getInfo") ? $utente->getInfo() : [];
// Prendiamo il CF dell'utente
$cf = trim(strtoupper($userInfo["cf"])) ?? null;
if (!$cf) {
return DelegheRoles::UNAUTHORIZED;
}
return $this->getUserRole($cf, null, $syncBehaviour);
}
/**
* Verifica il ruolo dell'utente corrente nell'ambito della scheda attule
*
* @param string $cf Codice fiscale da verificare
* @param array|null $preferredRoles Se impostato, il sync viene ignorato e viene cercato sulla base dei ruoli scelti
* @param int $syncBehaviour Definisce il comportamento per sincronizzarsi dai server ANAC
*
* @return string|null ritorna RP, DRP1, DRP2, DRP3 o null
*/
public function getUserRole(string $cf, ?array $preferredRoles = null, int $syncBehaviour = RoleSyncBehaviour::NEVER_SYNC)
{
$cf = trim(strtoupper($cf));
$retVal = DelegheRoles::UNAUTHORIZED;
// Determiniamo se dobbiamo chiedere ad anac
$syncFromAnac = $syncBehaviour == RoleSyncBehaviour::ALWAYS_SYNC;
// Vediamo se abbiamo un codice
if (empty($this->fascicolo)) {
return null;
}
// Se abbiamo dei ruoli preferiti, cerchiamo per quelli
if (!empty($preferredRoles)) {
if ($syncBehaviour !== RoleSyncBehaviour::NEVER_SYNC) {
throw new Exception("Se \$preferredRoles !== null, \$syncBehaviour deve essere NEVER_SYNC");
}
foreach ($preferredRoles as $preferredRole) {
if (in_array($preferredRole, DelegheRoles::ANY)) {
if(empty($this->fascicolo["codice"]))
$preferredRoleOwner = null;
else
$preferredRoleOwner = self::searchFromDB(null, $preferredRole, $this->fascicolo["codice"]);
// Se lo abbiamo trovato
if ($preferredRoleOwner === $cf) {
return $preferredRole;
}
}
}
}
// Verifichiamo di avere un ruolo nel DB
if(empty($this->fascicolo["codice"]))
$retVal = $db_role = null;
else
$retVal = $db_role = self::searchFromDB($cf, null, $this->fascicolo["codice"]);
if ($db_role == null) {
// Prendiamo il CF del RUP, se è uguale al CF passato forziamo il ruolo RP
$cf_npa = unserialize($this->fascicolo["data"])["rup"]["codice_fiscale"] ?? null;
if (!empty($cf_npa)) {
if (trim(strtoupper($cf)) === trim(strtoupper($cf_npa))) {
$retVal = DelegheRoles::RP;
}
}
// Determiniamo se ora dobbiamo sincronizzare da ANAC
$syncFromAnac = $syncFromAnac || $syncBehaviour == RoleSyncBehaviour::SYNC_ON_NULL;
}
// Se dobbiamo sincronizzare
if ($syncFromAnac) {
$anac_role = $this->searchFromANAC($cf, null);
if ($anac_role !== null) {
$retVal = $anac_role;
}
}
// Se il risultato è diverso sincronizziamo
if ($retVal !== $db_role && !empty($this->fascicolo["codice"])) {
self::setUserRoleToDB($cf, $retVal, $this->fascicolo["codice"]);
}
return $retVal;
}
}
class DelegheRoles
{
// Ruoli
/**
* Responsabile del progetto
*/
const RP = "RP";
/**
* Delegato responsabile Programmazione
*/
const DRP1 = "DRP1";
/**
* Delegato responsabile Affidamento
*/
const DRP2 = "DRP2";
/**
* Delegato responsabile Esecuzione (viva la france)
*/
const DRP3 = "DRP3";
/**
* Nessun permesso trovato
*/
const UNAUTHORIZED = "UNAUTHORIZED";
/**
* Permesso speciale che viene usato per la presa-carico
*/
const NO_AUTH = ["NO_AUTH"];
/**
* Ruoli validi
*/
const VALID_ROLES = [self::RP, self::DRP1, self::DRP2, self::DRP3, self::UNAUTHORIZED];
const DRPs = [self::DRP1, self::DRP2, self::DRP3];
/**
* Qualunque ruolo
*/
const ANY = [self::RP, self::DRP1, self::DRP2, self::DRP3];
const Nomi = [
self::RP => "Responsabile Progetto",
self::DRP1 => "Delegato Pubblicazione",
self::DRP2 => "Delegato Affidamento",
self::DRP3 => "Delegato Esecuzione"
];
}
/**
* Comportamenti di richiesta della delega
*/
class RoleSyncBehaviour
{
/**
* Usa solo il risultato del DB
*/
const NEVER_SYNC = 0;
/**
* Se il risultato del db è null, chiedi ad ANAC e sincronizza il risultato su DB
*/
const SYNC_ON_NULL = 1;
/**
* Verifica sempre il risultato su ANAC e sincronizzalo sul DB se diverso da quello attuale
*/
const ALWAYS_SYNC = 2;
}