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.
1082 righe
39 KiB
1082 righe
39 KiB
<?php |
|
|
|
require_once dirname(__DIR__, 2) . "/inc/traits/api.trait.php"; |
|
require_once dirname(__DIR__, 2) . "/inc/traits/deleghe.trait.php"; |
|
require_once dirname(__DIR__, 2) . "/inc/traits/npalogger.trait.php"; |
|
require_once dirname(__DIR__, 2) . "/inc/traits/render.trait.php"; |
|
require_once __DIR__ . "/fvoe.document.class.php"; |
|
require_once __DIR__ . "/fvoe.documents.collection.class.php"; |
|
|
|
class FVOEInizializationType { |
|
const CODICE_FVOE = "codice_fvoe"; |
|
const UUID_PARTECIPANTE_E_MODULO = "uuid_partecipante_e_modulo"; |
|
const CODICE_LOTTO_E_CODICE_OPERATORE = "codice_lotto_e_codice_operatore"; |
|
const UUID_PARTECIPANTE_CF_E_CODICE_LOTTO = "uuid_partecipante_cf_e_codice_lotto"; |
|
const CF_E_CODICE_LOTTO = "codice_fiscale_azienda_e_codice_lotto_npa"; |
|
} |
|
|
|
class FVOE { |
|
|
|
use API, Deleghe, NpaLogger, NuovaPiattaformaAppaltiRenderTrait; |
|
|
|
/** |
|
* Fascicolo NPA |
|
* |
|
* @var array |
|
*/ |
|
public $fascicolo; |
|
|
|
/** |
|
* Lotto NPA |
|
* |
|
* @var array |
|
*/ |
|
private $lotto; |
|
|
|
/** |
|
* Operatore Economico |
|
* |
|
* @var array |
|
*/ |
|
private $operatoreEconomico; |
|
|
|
/** |
|
* documents |
|
* |
|
* @var array |
|
*/ |
|
private $documents; |
|
|
|
/** |
|
* Configurazione API |
|
* |
|
* @var mixed |
|
*/ |
|
private $api_config; |
|
|
|
/** |
|
* Informazioni del fascicolo dell'Operatore Economico |
|
* |
|
* @var array |
|
*/ |
|
public $info; |
|
|
|
/** |
|
* stati |
|
* |
|
* @var array |
|
*/ |
|
public $stati; |
|
|
|
/** |
|
* tipologia documenti |
|
* |
|
* @var array |
|
*/ |
|
public $tipologia_documenti; |
|
|
|
/** |
|
* Definisce quali sezioni sono inibite dall'utente |
|
*/ |
|
public $locked_sections = []; |
|
|
|
/** |
|
* Definisce quali elementi sono inibiti per l'utente |
|
* |
|
* @var array |
|
*/ |
|
public $locked_fields = []; |
|
|
|
// Query Statements |
|
private static PDOStatement $stmUUID; |
|
private static PDOStatement $stmOperatore; |
|
private static PDOStatement $stmPartecipanteGareFromUUID; |
|
private static PDOStatement $stmPartecipanteGareFromCodice; |
|
private static PDOStatement $stmFascicolo; |
|
private static PDOStatement $stmLottoFromCodice; |
|
private static PDOStatement $stmLottoFromCodiceRiferimentoAndModulo; |
|
private static PDOStatement $stmUUIDPartecipanteCodiceLotto; |
|
private static PDOStatement $stmFVOE; |
|
private static PDOStatement $stmCFeCodiceLotto; |
|
private static PDOStatement $stmPartecipanteGareFromCodiceFiscale; |
|
|
|
private static string $datetimeFormat; |
|
|
|
/** |
|
* Formato della data |
|
* |
|
* @var string |
|
*/ |
|
private const DATE_FORMAT = "Y-m-d\TH:i:s\Z"; |
|
|
|
/** |
|
* Query initialization |
|
* |
|
* @var bool |
|
*/ |
|
private static bool $queryInitialized = false; |
|
|
|
/** |
|
* Class constructor |
|
* |
|
* @return void |
|
*/ |
|
private function __construct() { |
|
|
|
self::$datetimeFormat = "Y-m-d H:i:s"; |
|
$this->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[] = "<strong>{$errorInfo["codice"]}</strong> - {$errorInfo["descrizione"]["it"]}"; |
|
} |
|
} |
|
} |
|
|
|
if(! empty($list)) { |
|
$list = implode("</li><li class='list-group-item bg-transparent'>", $list); |
|
$message = "<strong>Attenzione</strong> si sono verificati i seguenti errori:<ul class='list-group'><li class='list-group-item bg-transparent'>{$list}</li></ul>"; |
|
} |
|
|
|
return false; |
|
|
|
} |
|
|
|
global $pdo; |
|
|
|
$stm = $pdo->prepare(<<<SQL |
|
INSERT INTO b_fvoe_documenti (codice_fvoe, id_documento, tipo_documento, oggetto, data_creazione, stato_comprova, stato_utilizzo, data_inserimento, data_emissione, data_fine_validita, numero_protocollo, utente_modifica) |
|
VALUES (:codice_fvoe, :id_documento, :tipo_documento, :oggetto, :data_creazione, :stato_comprova, :stato_utilizzo, :data_inserimento, :data_emissione, :data_fine_validita, :numero_protocollo, :utente_modifica) |
|
ON DUPLICATE KEY UPDATE |
|
data_creazione = :data_creazione, |
|
stato_comprova = :stato_comprova, |
|
stato_utilizzo = :stato_utilizzo, |
|
data_inserimento = :data_inserimento, |
|
data_emissione = :data_emissione, |
|
data_fine_validita = :data_fine_validita, |
|
numero_protocollo = :numero_protocollo, |
|
utente_modifica = :utente_modifica |
|
SQL); |
|
$stm->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; |
|
|
|
} |
|
|
|
}
|
|
|