stati = jsonToArray(__DIR__ . "/json/stati.json"); $this->tipologia_documenti = jsonToArray(__DIR__ . "/json/tipologia_documenti.json"); $this->api_config = require dirname(__DIR__, 2) . "/inc/configurazione.php"; } /** * Query Initialization * * @return void */ private static function initializeQuery() : void { global $pdo; if (!self::$queryInitialized) { self::$stmUUID = $pdo->prepare("SELECT * FROM b_fvoe WHERE `uuid_partecipante` = :uuid_partecipante AND stato >= 0 LIMIT 0,1"); self::$stmCFeCodiceLotto = $pdo->prepare("SELECT * FROM b_fvoe WHERE `codice_fiscale` = :codice_fiscale AND `codice_lotto_npa` = :codice_lotto_npa AND stato >= 0 LIMIT 0,1"); self::$stmUUIDPartecipanteCodiceLotto = $pdo->prepare("SELECT * FROM b_fvoe WHERE `uuid_partecipante` = :uuid_partecipante AND `codice_lotto_npa` = :codice_lotto_npa AND stato >= 0 LIMIT 0,1"); self::$stmFVOE = $pdo->prepare("SELECT * FROM b_fvoe WHERE `codice` = :codice_fvoe AND stato >= 0 LIMIT 0,1"); self::$stmOperatore = $pdo->prepare("SELECT * FROM b_fvoe WHERE `codice_lotto_npa` = :codice_lotto_npa AND `codice_operatore` = :codice_operatore AND stato >= 0 LIMIT 0,1"); self::$stmPartecipanteGareFromUUID = $pdo->prepare("SELECT * FROM r_partecipanti_gare WHERE `uuid` = :uuid_partecipante LIMIT 0,1"); self::$stmPartecipanteGareFromCodice = $pdo->prepare("SELECT * FROM r_partecipanti_gare WHERE `codice` = :codice LIMIT 0,1"); self::$stmPartecipanteGareFromCodiceFiscale = $pdo->prepare("SELECT * FROM r_partecipanti_gare WHERE `codice_fiscale` = :codice_fiscale AND `codice_lotto` = :codice_lotto LIMIT 0,1"); self::$stmFascicolo = $pdo->prepare("SELECT * FROM b_npa WHERE `codice` = :codice_npa LIMIT 0,1"); self::$stmLottoFromCodice = $pdo->prepare("SELECT `b_npa_lotti`.* FROM `b_npa_lotti` LEFT JOIN `b_npa` ON `b_npa`.`codice` = `b_npa_lotti`.`codice_npa` WHERE `b_npa_lotti`.`codice` = :codice_lotto_npa AND `b_npa`.`id_riferimento` > 0 LIMIT 0,1"); self::$stmLottoFromCodiceRiferimentoAndModulo = $pdo->prepare("SELECT `b_npa_lotti`.* FROM `b_npa_lotti` LEFT JOIN `b_npa` ON `b_npa`.`codice` = `b_npa_lotti`.`codice_npa` WHERE `b_npa_lotti`.`lotto_riferimento` = :lotto_riferimento AND `b_npa`.`modulo_riferimento` = :modulo_riferimento AND `id_riferimento` > 0 LIMIT 0,1"); self::$queryInitialized = true; } } /** * Class initialization * * @param mixed $reference * @param int $type * @return FVOE */ public static function init($reference, string $type): FVOE { self::initializeQuery(); $fvoe = new self(); switch ($type) { case FVOEInizializationType::CODICE_FVOE: // Verifico che in $reference ci sia un numero if (! is_numeric($reference) || $reference <= 0) { throw new InvalidArgumentException("Il riferimento deve essere un numero >= 0 (int) codice_fvoe."); } self::$stmFVOE->execute([':codice_fvoe' => $reference]); $fvoe->info = self::$stmFVOE->fetch(PDO::FETCH_ASSOC); if(empty($fvoe->info["codice"])) { throw new InvalidArgumentException("FVOE non trovato."); } break; case FVOEInizializationType::CF_E_CODICE_LOTTO: // Verifico che in $reference ci siano i valori di cf e codice_lotto_npa if (! is_array($reference) || count($reference) != 2) { throw new InvalidArgumentException("Il riferimento deve essere un array [cf, codice_lotto_npa]."); } list($cf, $codice_lotto_npa) = $reference; self::$stmCFeCodiceLotto->execute([":codice_fiscale" => $cf, ":codice_lotto_npa" => $codice_lotto_npa]); $fvoe->info = self::$stmCFeCodiceLotto->fetch(PDO::FETCH_ASSOC); // Se si tratta di un nuovo fascicolo dell'operatore economico if(empty($fvoe->info["codice"])) { $fvoe->info = get_campi("b_fvoe"); $fvoe->info["stato"] = 0; $fvoe->info["codice_fiscale"] = $cf; $fvoe->info["codice_lotto_npa"] = $codice_lotto_npa; } break; case FVOEInizializationType::UUID_PARTECIPANTE_E_MODULO: // Verifico che in $reference ci siano i valori di uuid_partecipante e modulo_riferimento if (! is_array($reference) || count($reference) != 2) { throw new InvalidArgumentException("Il riferimento deve essere un array [uuid_partecipante, modulo_riferimento]."); } list($uuid_partecipante, $modulo_riferimento) = $reference; if(! in_array($modulo_riferimento, ["gare"])) { throw new InvalidArgumentException("Il valore di modulo_riferimento non è valido."); } // Recupero le informazioni del fascicolo attraverso il codice uuid univoco del partecipante self::$stmUUID->execute([':uuid_partecipante' => $uuid_partecipante]); $fvoe->info = self::$stmUUID->fetch(PDO::FETCH_ASSOC); // Se si tratta di un nuovo fascicolo dell'operatore economico if(empty($fvoe->info["codice"])) { $fvoe->info = get_campi("b_fvoe"); $fvoe->info["stato"] = 0; $fvoe->info["modulo"] = $modulo_riferimento; $fvoe->info["uuid_partecipante"] = $uuid_partecipante; if($fvoe->info["modulo"] == "gare") { // Se il modulo di riferimento è gare recupero il partecipante con il suo codice uuid da r_partecipanti_gare self::$stmPartecipanteGareFromUUID->execute([":uuid_partecipante" => $fvoe->info["uuid_partecipante"]]); $fvoe->operatoreEconomico = self::$stmPartecipanteGareFromUUID->fetch(PDO::FETCH_ASSOC); if(! empty($fvoe->operatoreEconomico["codice_lotto"])) { // Imposto i dati utili nel fascicolo dell'operatore economico $fvoe->info["codice_operatore"] = $fvoe->operatoreEconomico["codice"]; $fvoe->info["codice_fiscale"] = $fvoe->operatoreEconomico["codice_fiscale"]; // Recupero il lotto di riferimento da b_npa_lotti utilizzando il lotto di partecipazione della r_partecipanti_gare self::$stmLottoFromCodiceRiferimentoAndModulo->execute([":lotto_riferimento" => $fvoe->operatoreEconomico["codice_lotto"], ":modulo_riferimento" => $fvoe->info["modulo"]]); $fvoe->lotto = self::$stmLottoFromCodiceRiferimentoAndModulo->fetch(PDO::FETCH_ASSOC); if(! empty($fvoe->lotto["codice"])) { // Imposto il codice del lotto per poter recuperare dopo le info del fascicolo npa $fvoe->info["codice_lotto_npa"] = $fvoe->lotto["codice"]; } } } } break; case FVOEInizializationType::CODICE_LOTTO_E_CODICE_OPERATORE: if (! is_array($reference) || count($reference) != 2) { throw new InvalidArgumentException("Il riferimento deve essere un array [codice_lotto_npa, codice_operatore]."); } list($codice_lotto_npa, $codice_operatore) = $reference; self::$stmOperatore->execute([':codice_lotto_npa' => $codice_lotto_npa, ':codice_operatore' => $codice_operatore]); $fvoe->info = self::$stmOperatore->fetch(PDO::FETCH_ASSOC); // Se si tratta di un nuovo fascicolo dell'operatore economico if(empty($fvoe->info["codice"])) { $fvoe->info = get_campi("b_fvoe"); $fvoe->info["stato"] = 0; // Se disponibile, imposto il codice lotto if(! empty($codice_lotto_npa)) { $fvoe->info["codice_lotto_npa"] = $codice_lotto_npa; } // Se disponibile, imposto il codice dell'operatore economico if(! empty($codice_operatore)) { $fvoe->info["codice_operatore"] = $codice_operatore; } } break; case FVOEInizializationType::UUID_PARTECIPANTE_CF_E_CODICE_LOTTO: // Verifico che in $reference ci siano i valori di uuid_partecipante e codice_lotto_npa if (! is_array($reference) || count($reference) != 3) { throw new InvalidArgumentException("Il riferimento deve essere un array [uuid_partecipante, cf, codice_lotto_npa]."); } if(! preg_match('/^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$/', $reference[0])) { throw new InvalidArgumentException("Il riferimento uuid_partecipante deve essere uno uuid valido."); } list($uuid_partecipante, $cf, $codice_lotto_npa) = $reference; self::$stmUUIDPartecipanteCodiceLotto->execute([':uuid_partecipante' => $uuid_partecipante, ':codice_lotto_npa' => $codice_lotto_npa]); $fvoe->info = self::$stmUUIDPartecipanteCodiceLotto->fetch(PDO::FETCH_ASSOC); // Se si tratta di un nuovo fascicolo dell'operatore economico if(empty($fvoe->info["codice"])) { $fvoe->info = get_campi("b_fvoe"); $fvoe->info["stato"] = 0; $fvoe->info["codice_lotto_npa"] = $codice_lotto_npa; $fvoe->info["uuid_partecipante"] = $uuid_partecipante; } $fvoe->info["codice_fiscale"] = $cf; break; default: throw new InvalidArgumentException("Tipologia di riferimento non valida."); break; } // Recupero le informazioni del lotto if(! empty($fvoe->info["codice_lotto_npa"]) && empty($fvoe->lotto)) { self::$stmLottoFromCodice->execute([":codice_lotto_npa" => $fvoe->info["codice_lotto_npa"]]); $fvoe->lotto = self::$stmLottoFromCodice->fetch(PDO::FETCH_ASSOC); } // Imposto il codice del fascicolo npa (se si tratta di un nuovo fascicolo dell'operatore economico) if(empty($fvoe->info["codice_npa"]) && ! empty($fvoe->lotto["codice_npa"])) { $fvoe->info["codice_npa"] = $fvoe->lotto["codice_npa"]; } // Recupero le informazioni del fascicolo npa if(! empty($fvoe->info["codice_npa"])) { self::$stmFascicolo->execute([":codice_npa" => $fvoe->info["codice_npa"]]); $fvoe->fascicolo = self::$stmFascicolo->fetch(PDO::FETCH_ASSOC); } // Imposto il modulo (se si tratta di un nuovo fascicolo dell'operatore economico) if(empty($fvoe->info["modulo"]) && ! empty($fvoe->fascicolo["modulo_riferimento"])) { $fvoe->info["modulo"] = $fvoe->fascicolo["modulo_riferimento"]; } // // // // // // if($fvoe->info["modulo"] == "gare") { // // Se il modulo di riferimento è gare recupero il partecipante con il suo codice fiscale da r_partecipanti_gare // static::$stmPartecipanteGareFromCodiceFiscale->execute([":codice_fiscale" => $fvoe->info["codice_fiscale", ":codice_lotto" => ""]]); // $fvoe->operatoreEconomico = self::$stmPartecipanteGareFromCodiceFiscale->fetch(PDO::FETCH_ASSOC); // if(! empty($fvoe->operatoreEconomico["codice_lotto"])) { // // Imposto i dati utili nel fascicolo dell'operatore economico // $fvoe->info["codice_operatore"] = $fvoe->operatoreEconomico["codice"]; // $fvoe->info["codice_fiscale"] = $fvoe->operatoreEconomico["codice_fiscale"]; // // Recupero il lotto di riferimento da b_npa_lotti utilizzando il lotto di partecipazione della r_partecipanti_gare // self::$stmLottoFromCodiceRiferimentoAndModulo->execute([":lotto_riferimento" => $fvoe->operatoreEconomico["codice_lotto"], ":modulo_riferimento" => $fvoe->info["modulo"]]); // $fvoe->lotto = self::$stmLottoFromCodiceRiferimentoAndModulo->fetch(PDO::FETCH_ASSOC); // if(! empty($fvoe->lotto["codice"])) { // // Imposto il codice del lotto per poter recuperare dopo le info del fascicolo npa // $fvoe->info["codice_lotto_npa"] = $fvoe->lotto["codice"]; // } // } // } // // // // // $fvoe->operatoreEconomico = get_campi("r_partecipanti_gare"); $fvoe->operatoreEconomico["codice_lotto"] = $fvoe->lotto["lotto_riferimento"] ?? null; $fvoe->operatoreEconomico["codice_fiscale"] = $fvoe->info["codice_fiscale"]; // Recupero le informazioni del partecipante if(! empty($fvoe->info["modulo"]) && $fvoe->info["modulo"] == "gare") { if(! empty($fvoe->lotto["lotto_riferimento"]) && ! empty($fvoe->info["codice_fiscale"])) { static::$stmPartecipanteGareFromCodiceFiscale->execute([":codice_fiscale" => $fvoe->info["codice_fiscale"], ":codice_lotto" => $fvoe->lotto["lotto_riferimento"]]); if(static::$stmPartecipanteGareFromCodiceFiscale->rowCount() == 1) { $fvoe->operatoreEconomico = self::$stmPartecipanteGareFromCodiceFiscale->fetch(PDO::FETCH_ASSOC); } } if(empty($fvoe->operatoreEconomico["codice"]) && ! empty($fvoe->info["codice_operatore"])) { self::$stmPartecipanteGareFromCodice->execute([":codice" => $fvoe->info["codice_operatore"]]); if(self::$stmPartecipanteGareFromCodice->rowCount() == 1) { $fvoe->operatoreEconomico = self::$stmPartecipanteGareFromCodice->fetch(PDO::FETCH_ASSOC); } } if(empty($fvoe->operatoreEconomico["codice"]) && ! empty($fvoe->info["uuid_partecipante"])) { self::$stmPartecipanteGareFromUUID->execute([":uuid_partecipante" => $fvoe->info["uuid_partecipante"]]); if(self::$stmPartecipanteGareFromUUID->rowCount() == 1) { $fvoe->operatoreEconomico = self::$stmPartecipanteGareFromUUID->fetch(PDO::FETCH_ASSOC); } } } if(! empty($fvoe->operatoreEconomico["codice"])) { // Imposto i dati utili nel fascicolo dell'operatore economico $fvoe->info["codice_operatore"] = $fvoe->operatoreEconomico["codice"]; $fvoe->info["codice_fiscale"] = $fvoe->operatoreEconomico["codice_fiscale"]; if(empty($fvoe->lotto["codice"])) { // Recupero il lotto di riferimento da b_npa_lotti utilizzando il lotto di partecipazione della r_partecipanti_gare self::$stmLottoFromCodiceRiferimentoAndModulo->execute([":lotto_riferimento" => $fvoe->operatoreEconomico["codice_lotto"], ":modulo_riferimento" => $fvoe->info["modulo"]]); $fvoe->lotto = self::$stmLottoFromCodiceRiferimentoAndModulo->fetch(PDO::FETCH_ASSOC); } // Imposto il codice del lotto per poter recuperare dopo le info del fascicolo npa $fvoe->info["codice_lotto_npa"] = $fvoe->lotto["codice"]; } return $fvoe; } /** * Verifica se l'utente corrente può accedere al Fascicolo dell'OE * * @return bool */ public function isAccessible() : bool { if(! empty($_SESSION["utente"]) && $_SESSION["utente"]->authenticationLevel >= 2) { $utente = $_SESSION["utente"]->getInfo()["cf"]; if(! empty($this->fascicolo["codice"])) { $npa = NuovaPiattaformaAppalti::init($this->fascicolo["codice"]); $cfs = $npa->getUserFromRole(DelegheRoles::ANY, RoleSyncBehaviour::NEVER_SYNC); if(in_array($utente, $cfs)) { return true; } } } return false; } /** * Richiesta di accesso al FVOE * * @param \DateTime $end * @param mixed $message * @return bool */ public function requestAccess(?\DateTime $authorizationEndDate = null, ?string &$message = "") : bool { if (! $this->getServiceStatusBool(true)) { $message = __("Impossibile completare la richiesta: i server ANAC non sono raggiungibili. Riprova tra qualche minuto."); return false; } if (! NuovaPiattaformaAppalti::hasLockOnPartecipantiStatic($this->fascicolo["codice"])) { $message = __("Impossibile completare la richiesta: E' necessario trasmettere le schede partecipanti."); return false; } if(empty($this->lotto["codice"])) { $message = __("Impossibile completare la richiesta: E' necessario selezionare un lotto."); return false; } // Popoliamo message con qualcosa di generico $message = __("Errore interno sconosciuto"); $operazione = new Salva(); $operazione->debug = false; $operazione->nome_tabella = "b_npa_operazioni_schede"; $operazione->operazione = "INSERT"; $operazione->expect = ["codice_partecipante", "codice_lotto", "operazione"]; $operazione->oggetto = [ "codice_partecipante" => $this->operatoreEconomico["uuid"], "codice_lotto" => $this->lotto["codice"], "operazione" => "ACCESSO-FVOE" ]; $fvoe = new Salva(); $fvoe->debug = false; $fvoe->nome_tabella = "b_fvoe"; $fvoe->operazione = "INSERT"; $fvoe->expect = ["codice_npa", "codice_lotto_npa", "codice_partecipante", "codice_operatore", "codice_fiscale", "uuid_partecipante", "stato", "modulo", "utente_modifica"]; $fvoe->oggetto = &$this->info; date_default_timezone_set('Europe/Rome'); $claims = $this->getAnacJwsCustomClaims($this->api_config["fvoe"]["endpoint"]); // Andiamo a verificare che ci sia un'operazione di richiesta accesso in attesa $richiesta_accesso = NuovaPiattaformaAppalti::fetchLastOperation(null, "ACCESSO-FVOE", null, false, $this->info["codice_lotto_npa"], $this->info["uuid_partecipante"]); // Se c'è if (! empty($richiesta_accesso)) { // Popoliamo il messaggio di errore $message = __("Errore durante la verifica dello stato di accesso al fascicolo"); $fvoe->operazione = "UPDATE"; $fvoe->expect = ["codice", "stato", "data_inizio", "data_fine", "id_richiesta_accesso", "chiave_accesso"]; $operazione->operazione = "UPDATE"; $operazione->expect = ["codice", "esito", "risultato"]; $operazione->oggetto = $richiesta_accesso; // Andiamo a chiedere al server lo stato della richiesta di accesso $request = [ "codiceFiscale" => $this->operatoreEconomico["codice_fiscale"], "idAppalto" => $this->fascicolo["id_appalto"] ]; $apiMessage = ""; $result_str = $this->apiCall("fvoe", "check-access-request", $request, $claims, [], $apiMessage); if (is_json($result_str)) { $message = __("Impossibile verificare l'esito dell'operazione. Contatta l'Help Desk tecnico."); $result = json_decode($result_str); $operazione->oggetto["risultato"] = serialize($result); $operazione->oggetto["esito"] = "KO"; if ($result->status == 200 && ! empty($result->autorizzazione)) { if(empty($result->autorizzazione->chiaveAccesso)) { $message = "INFO - Attendi che l'operatore economico conceda l'accesso al fascicolo"; return false; } global $config; $message = null; $this->info["stato"] = 20; $this->info["data_inizio"] = date('d/m/Y H:i:s', strtotime($result->autorizzazione->dataInizio)); $this->info["data_fine"] = date('d/m/Y H:i:s', strtotime($result->autorizzazione->dataFine)); $this->info["id_richiesta_accesso"] = $result->autorizzazione->richiestaAccesso->idRichiesta; $this->info["chiave_accesso"] = $result->autorizzazione->chiaveAccesso; $this->info["chiave_accesso"] = simple_encrypt($this->info["chiave_accesso"], $config["simple_encrypt"]["chiave_fvoe"]); $fvoe->save(); $operazione->oggetto["esito"] = "OK"; $operazione->save(); return true; } $operazione->save(); return false; } return false; } $dataFineAutorizzazione = date(self::DATE_FORMAT, strtotime('2099/12/31')); if ($authorizationEndDate instanceof DateTime) { $dataFineAutorizzazione = $authorizationEndDate->format(self::DATE_FORMAT); } // Creiamo la richiesta di accesso al Fascicolo $request = [ "dataInizioAutorizzazione" => date(self::DATE_FORMAT, strtotime('now')), "dataFineAutorizzazione" => $dataFineAutorizzazione, "operatoriEconomici" => [ [ "codiceFiscale" => $this->operatoreEconomico["codice_fiscale"] ] ], "appalto" => [ "idAppalto" => $this->fascicolo["id_appalto"], "lotti" => [ [ "cig" => $this->lotto["cig"] ] ] ] ]; // Effettuiamo la richiesta $apiMessage = ""; $claims = $this->getAnacJwsCustomClaims($this->api_config["fvoe"]["endpoint"]); $result_str = $this->apiCall("fvoe", "submit-access-request", $request, $claims, [], $apiMessage); $result = self::manageANACResponse($result_str, $message); if($result === null) { $message = empty($apiMessage) ? $message : $apiMessage; return false; } $message = __("Errore in fase di invio della richiesta."); // Verifichiamo la risposta // Se non ci viene fornita una risposta con successo if ($result->status !== 200) { // Aggiorniamo lo status $operazione->expect[] = "esito"; $operazione->expect[] = "risultato"; $operazione->oggetto["esito"] = "KO"; $operazione->oggetto["risultato"] = serialize($result); $operazione->save(); $message = __("Errore in fase di richiesta accesso FVOE."); if(! empty($result->errori)) { $dictionary = NuovaPiattaformaAppalti::getErrorsDictionary(); foreach ($result->errori as $errore) { $errorInfo = $dictionary[$errore->codice ?? null] ?? []; if(! empty($errorInfo["descrizione"]["it"]) && $errorInfo["codice"]) { $message = "{$errorInfo["codice"]} {$errorInfo["descrizione"]["it"]}"; } } } elseif(! empty($result->title)) { $message = "{$message} {$result->title}"; } $this->info["stato"] = 0; $this->info["modulo"] = $this->fascicolo["modulo_riferimento"]; $fvoe->expect[] = "errori"; $this->info["errori"] = serialize($result->errori ?? $result); if(! empty($this->info["codice"])) { $fvoe->operazione = "UPDATE"; $fvoe->expect[] = "codice"; } $fvoe->save(); return false; } // Conferma andata con successo $operazione->expect[] = "id_richiesta"; $fvoe->expect[] = "errori"; $operazione->oggetto["id_richiesta"] = $result->idRichiesta; $this->info["stato"] = 10; $this->info["modulo"] = $this->fascicolo["modulo_riferimento"]; $this->info["errori"] = ""; if(! empty($this->info["codice"])) { $fvoe->operazione = "UPDATE"; $fvoe->expect[] = "codice"; } if ($operazione->save() && $fvoe->save()) { $message = ""; return true; } return false; } /** * Recupera il documento per la specifica tipologia dal database * * @param mixed $tipologia * @param mixed $cached * @return FVOEDocumentsCollection */ public function fetchDocumentsByType(string $tipologia, bool $cached = true) : FVOEDocumentsCollection { if(! isset($this->documents[$tipologia]) || ! $cached) { $this->documents[$tipologia] = new FVOEDocumentsCollection($this->info["codice"], $tipologia); } return $this->documents[$tipologia]; } /** * Ottieni la lista dei documenti disponibili nel fascicolo dell'operatore economico * * @param mixed $filters * @param mixed $page * @param mixed $message * @return bool */ public function updateDocuments(?array $filters = [], ?string &$message = "") : bool { global $config; if(! empty($_SESSION["fvoe-sync"][$this->info["id_richiesta_accesso"]])) { return true; } // Prevalorizziamo $message $message = __("Errore interno sconosciuto"); // Verifichiamo che i servizi siano disponibili if (! $this->getServiceStatusBool(true)) { $message = __("Impossibile completare la richiesta: i server ANAC non sono raggiungibili. Riprova tra qualche minuto."); return false; } // Creiamo la richiesta di accesso al Fascicolo $request = ["chiaveAccesso" => simple_decrypt($this->info["chiave_accesso"], $config["simple_encrypt"]["chiave_fvoe"])]; // Organizzo i filtri if(! empty($filters)) { $allowedKeys = [ "dataCreazioneA", "dataCreazioneDa", "dataEmissioneA", "dataEmissioneDa", "dataFineValiditaA", "dataFineValiditaDa", "dataInserimentoA", "dataInserimentoDa", "dataProtocolloA", "dataProtocolloDa", "datiAggiuntivi", "numeroProtocollo", "page", "perPage", "stato", "tipo", ]; // Se ci sono date valide le trasformo nel formato ISO 8601 as profiled by RFC 3339 array_walk($filters, function(&$value, $key) { if(strpos($key, "data") !== false && ! empty($value)) { $value = strtotime($value); $value = $value !== false ? gmdate(self::DATE_FORMAT, $value) : null; } }); // Rimuovo gli elementi nulli o non consentiti $filters = array_filter($filters, function($value, $key) use ($allowedKeys, &$filters) { return $value !== null && in_array($key, $allowedKeys); }, ARRAY_FILTER_USE_BOTH); // Imposto i filtri nella richiesta $request += $filters; } $page = $pages = 1; do { $request["page"] = $page; // Effettuiamo la richiesta $apiMessage = ""; $claims = $this->getAnacJwsCustomClaims($this->api_config["fvoe"]["endpoint"]); $result_str = $this->apiCall("fvoe", "search-documents", $request, $claims, [], $apiMessage); $result = self::manageANACResponse($result_str, $message); if($result === null) { $message = empty($apiMessage) ? $message : $apiMessage; return false; } // Verifichiamo la risposta // Se non ci viene fornita una risposta con successo if ($result->status !== 200) { // Verificare la risposta $list = []; if(! empty($result->title)) { $list[] = "{$message} {$result->title}"; } if(! empty($result->errori)) { $dictionary = NuovaPiattaformaAppalti::getErrorsDictionary(); foreach ($result->errori as $errore) { $errorInfo = $dictionary[$errore->codice ?? null] ?? []; if(! empty($errorInfo["descrizione"]["it"]) && $errorInfo["codice"]) { $list[] = "{$errorInfo["codice"]} - {$errorInfo["descrizione"]["it"]}"; } } } if(! empty($list)) { $list = implode("
  • ", $list); $message = "Attenzione si sono verificati i seguenti errori:"; } return false; } global $pdo; $stm = $pdo->prepare(<<bindValue(":codice_fvoe", $this->info["codice"]); $stm->bindValue(":utente_modifica", $_SESSION["utente"]->codice); // Conferma andata con successo $pages = $result->totPages; foreach ($result->result as $document) { // Recuperiamo le informazioni $info = $this->getDocument($document->idDocumento); if(! empty($info->documento->idDocumento)) { if(! empty($info->documento->idDocumento)) { $stm->bindValue(":id_documento", $info->documento->idDocumento); } else { $stm->bindValue(":id_documento", NULL, PDO::PARAM_NULL); } if(! empty($info->documento->tipo)) { $stm->bindValue(":tipo_documento", $info->documento->tipo->codice); } else { $stm->bindValue(":tipo_documento", NULL, PDO::PARAM_NULL); } if(! empty($info->documento->oggetto)) { $stm->bindValue(":oggetto", $info->documento->oggetto); } else { $stm->bindValue(":oggetto", NULL, PDO::PARAM_NULL); } if(! empty($info->documento->dataCreazione)) { $stm->bindValue(":data_creazione", date(self::$datetimeFormat, strtotime($info->documento->dataCreazione))); } else { $stm->bindValue(":data_creazione", NULL, PDO::PARAM_NULL); } if(! empty($info->documento->statoComprova)) { $stm->bindValue(":stato_comprova", $info->documento->statoComprova->codice); } else { $stm->bindValue(":stato_comprova", NULL, PDO::PARAM_NULL); } if(! empty($info->documento->statoUtilizzo)) { $stm->bindValue(":stato_utilizzo", $info->documento->statoUtilizzo->codice); } else { $stm->bindValue(":stato_utilizzo", NULL, PDO::PARAM_NULL); } if(! empty($info->documento->dataInserimento)) { $stm->bindValue(":data_inserimento", date(self::$datetimeFormat, strtotime($info->documento->dataInserimento))); } else { $stm->bindValue(":data_inserimento", NULL, PDO::PARAM_NULL); } if(! empty($info->documento->dataEmissione)) { $stm->bindValue(":data_emissione", date(self::$datetimeFormat, strtotime($info->documento->dataEmissione))); } else { $stm->bindValue(":data_emissione", NULL, PDO::PARAM_NULL); } if(! empty($info->documento->dataFineValidita)) { $stm->bindValue(":data_fine_validita", date(self::$datetimeFormat, strtotime($info->documento->dataFineValidita))); } else { $stm->bindValue(":data_fine_validita", NULL, PDO::PARAM_NULL); } if(! empty($info->documento->numeroProtocollo)) { $stm->bindValue(":numero_protocollo", $info->documento->numeroProtocollo); } else { $stm->bindValue(":numero_protocollo", NULL, PDO::PARAM_NULL); } $stm->execute(); } } $page++; } while ($page <= $pages); $_SESSION["fvoe-sync"][$this->info["id_richiesta_accesso"]] = true; $message = ""; return true; } /** * Ottiene il documento dal fascicolo dell'operatore economico di ANAC * * @param mixed $filters * @param mixed $page * @param mixed $message * @return object */ public function getDocument(string $idDocumento, ?string &$message = "") : ?object { global $config; // Prevalorizziamo $message $message = __("Errore interno sconosciuto"); // Verifichiamo che i servizi siano disponibili if (! $this->getServiceStatusBool(true)) { $message = __("Impossibile completare la richiesta: i server ANAC non sono raggiungibili. Riprova tra qualche minuto."); return null; } // Creiamo la richiesta per l'ottenimento del documento $request = [ "chiaveAccesso" => simple_decrypt($this->info["chiave_accesso"], $config["simple_encrypt"]["chiave_fvoe"]), "idDocumento" => $idDocumento ]; // Effettuiamo la richiesta $apiMessage = ""; $claims = $this->getAnacJwsCustomClaims($this->api_config["fvoe"]["endpoint"]); $result_str = $this->apiCall("fvoe", "get-document", $request, $claims, [], $apiMessage); $result = self::manageANACResponse($result_str, $message); if($result === null) { $message = empty($apiMessage) ? $message : $apiMessage; return false; } // Verifichiamo la risposta // Se non ci viene fornita una risposta con successo if ($result->status !== 200) { // Verificare la risposta if(! empty($result->errori)) { $dictionary = NuovaPiattaformaAppalti::getErrorsDictionary(); foreach ($result->errori as $errore) { $errorInfo = $dictionary[$errore->codice ?? null] ?? []; if(! empty($errorInfo["descrizione"]["it"]) && $errorInfo["codice"]) { $message = "{$errorInfo["codice"]} - {$errorInfo["descrizione"]["it"]}"; } } } elseif(! empty($result->title)) { $message = "{$message} {$result->title}"; } return null; } // Conferma andata con successo $message = ""; return $result; } /** * Ottieni l'anagrafica dell'operatore economico * * @param string $message * @return ?array */ public function getInfoOperatoreEconomico(?string &$message = "") : ?array { global $config; // Prevalorizziamo $message $message = __("Errore interno sconosciuto"); // Verifichiamo che i servizi siano disponibili if (! $this->getServiceStatusBool(true)) { $message = __("Impossibile completare la richiesta: i server ANAC non sono raggiungibili. Riprova tra qualche minuto."); return null; } // Creiamo la richiesta di accesso al Fascicolo $request = ["codiceFiscale" => $this->info["codice_fiscale"]]; // Effettuiamo la richiesta $apiMessage = ""; $claims = $this->getAnacJwsCustomClaims($this->api_config["fvoe"]["endpoint"]); $result_str = $this->apiCall("fvoe", "get-oe-data", $request, $claims, [], $apiMessage); $result = self::manageANACResponse($result_str, $message); if($result === null) { $message = empty($apiMessage) ? $message : $apiMessage; return false; } $message = __("Errore in fase di invio della richiesta."); dump($result); // Verifichiamo la risposta // Se non ci viene fornita una risposta con successo if ($result->status !== 200) { // Verificare la risposta if(! empty($result->errori)) { $dictionary = NuovaPiattaformaAppalti::getErrorsDictionary(); foreach ($result->errori as $errore) { $errorInfo = $dictionary[$errore->codice ?? null] ?? []; if(! empty($errorInfo["descrizione"]["it"]) && $errorInfo["codice"]) { $message = "{$errorInfo["codice"]} {$errorInfo["descrizione"]["it"]}"; } } } elseif(! empty($result->title)) { $message = "{$message} {$result->title}"; } return null; } // Conferma andata con successo $message = ""; return null; } /** * Get the value of fascicolo * * @return array */ public function getFascicolo(): array { return $this->fascicolo; } /** * Get the value of lotto * * @return array */ public function getLotto(): array { return $this->lotto; } /** * Get the value of operatoreEconomico * * @return array */ public function getOperatoreEconomico(): array { return $this->operatoreEconomico; } /** * Fetch last operation * * @param mixed $codice_documento * @param mixed $codice_partecipante * @param mixed $codice_lotto * @param mixed $operazione * @param mixed $esito * @param mixed $multiple * @return array */ public static function fetchLastOperation(?int $codice_documento = null, ?string $codice_partecipante = null, ?int $codice_lotto = null, ?string $operazione = "", $esito = null, ?bool $multiple = false) : ?array { global $pdo; $bind = $where = []; $where["codice_documento"] = "(codice_documento IS NULL OR codice_documento = '')"; if(! empty($codice_documento)) { $where["codice_documento"] = "codice_documento = :codice_documento"; $bind[":codice_documento"] = $codice_documento; } if(! empty($codice_partecipante)) { $where["codice_partecipante"] = "codice_partecipante = :codice_partecipante"; $bind[":codice_partecipante"] = $codice_partecipante; } if(! empty($codice_lotto)) { $where["codice_lotto"] = "codice_lotto = :codice_lotto"; $bind[":codice_lotto"] = $codice_lotto; } if(! empty($operazione)) { $where["operazione"] = "operazione = :operazione"; $bind[":operazione"] = $operazione; } $where["esito"] = "(esito IS NULL OR esito = '' OR esito = 0)"; if((! empty($esito)) && in_array($esito, ['OK', 'KO'])) { $where["esito"] = "esito = :esito"; $bind[":esito"] = $esito; } elseif ($esito === false) { unset($where["esito"], $bind[":esito"]); } $where = implode(" AND ", $where); $sql = "SELECT * FROM b_fvoe_operazioni WHERE ({$where}) ORDER BY `timestamp` DESC"; if(!$multiple) { $sql = "{$sql} LIMIT 0,1"; } $result = $pdo->go($sql, $bind); if ($result->rowCount() > 0) { $operations = $result->fetchAll(PDO::FETCH_ASSOC); return $multiple ? $operations : $operations[0]; } return null; } }