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.
 
 
 
 
 

579 righe
21 KiB

<?php
$configPath = substr(__DIR__, 0, strpos(__DIR__, "/public_html")) . "/config.php";
require_once $configPath;
require_once __DIR__ . "/../inc/npa_import.class.php";
//define("__VERBOSE", 1);
$modulo_riferimento = $_REQUEST["modulo_riferimento"] ?? null;
$moduli_supportati = ["gare", "concorsi"];
if (!in_array($modulo_riferimento, $moduli_supportati)) {
swalDie("Sono supportati solo " . implode(', ', $moduli_supportati));
}
$filterAppalto = [];
$userCF = $saCF = $saAUSA = "";
if (isset($_SESSION["utente"]) && isset($_SESSION["ente"]) && (!defined("__CMDS_JOB_EXEC") || empty(__CMDS_JOB_EXEC))) {
$userCF = $_SESSION["utente"]->getInfo()["cf"];
$ente = (!empty($_SESSION["utente"]->codice_ente)) ? $_SESSION["utente"]->codice_ente : $_SESSION["ente"]->codice;
if (!empty($ente)) {
$ente = Ente::getInfoFromID($ente);
if (!empty($ente)) {
$ente = reset($ente);
if (!empty($ente["cf"]) && !empty($ente["codice_ausa"]) && $ente["cf"] != $saCF) {
$saCF = $ente["cf"];
$saAUSA = $ente["codice_ausa"];
}
}
}
}
$hasClaimsData = !empty($_REQUEST["codiceFiscale"]) && !empty($_REQUEST["codiceAusa"]);
$claimData = [
"userCodiceFiscale" => $userCF,
"codiceFiscale" => !empty($_REQUEST["codiceFiscale"]) ? $_REQUEST["codiceFiscale"] : $saCF,
"codiceAusa" => !empty($_REQUEST["codiceAusa"]) ? $_REQUEST["codiceAusa"] : $saAUSA,
];
// Possibili ricerche per appalto
foreach (["cig", "codiceAppalto"] as $term) {
if (empty($_REQUEST[$term])) continue;
$filterAppalto[$term] = trim($_REQUEST[$term]);
$cacheKey = $term;
$cacheValue = $filterAppalto[$term];
break;
}
if (empty($filterAppalto) || !$hasClaimsData) {
// Mostriamo la UI di ricerca
require __DIR__ . "/../inc/components/import/search.php";
die();
}
$appalto = null;
// Usiamo un backup se è stato chiesto all'utente di integrare la procedura da poco
if (($_SESSION["npa_import"]["expiration"] ?? 0) > time() && (($_SESSION["npa_import"][$cacheKey] ?? "") == $cacheValue)) {
$appalto = $_SESSION["npa_import"]["appalto"];
}
// Inizializziamo ANAC
$npa = NuovaPiattaformaAppalti::initStatic();
$npa->initFakeOggetto($modulo_riferimento);
$npa->overrideStazioneAppaltante = $claimData;
if ($appalto === null) {
// Cerchiamo l'appalto
$response_ricerca_appalto = $npa->apiCall("comunicaAppalto", "search", $filterAppalto);
$response_ricerca_appalto = json_decode($response_ricerca_appalto);
if (!isset($response_ricerca_appalto->result)) {
swalDie("Risposta non valida dai server ANAC. Verifica di essere RP e prova più tardi.");
}
if (empty($response_ricerca_appalto->result)) {
swalDie("Impossibile trovare l'appalto. Verifica che il CF e Codice Ausa della Stazione Appaltante siano corretti.");
}
$appalto = $response_ricerca_appalto->result[0];
if (empty($appalto->idAppalto)) {
swalDie("L'appalto non possiede un idAppalto.");
}
// Otteniamo le schede
$response_schede = $npa->apiCall("comunicaPostPubblicazione", "search", ["idAppalto" => $appalto->idAppalto]);
$response_schede = json_decode($response_schede);
if (empty($response_schede->result)) {
swalDie("Impossibile trovare le schede legate a questo appalto.");
}
$appalto->schede = $response_schede->result;
// Prendiamo solo l'ultima versione CONF di schede non ripetibili
$appalto->schede = array_filter($appalto->schede, function ($scheda) {
return $scheda->stato->codice == "CONF";
});
$esiti_request = [
"idAppalto" => $appalto->idAppalto,
"tipoOperazione" => "SC_CONF",
"tipoRicerca" => "TUTTI_ESITI",
];
$esiti = $npa->apiCall("serviziComuni", "result", $esiti_request);
$esiti = json_decode($esiti);
// Ricerca idContratto
foreach($appalto->schede as &$scheda) {
foreach($esiti->listaEsiti ?? [] as $esito) {
if($esito->idScheda != $scheda->_idScheda || empty($esito->idContratto)) continue;
$scheda->body->anacForm->idContratto = $esito->idContratto;
// Cerchiamo il CIG
$anacForm = object_to_array($scheda->body->anacForm);
$cig = recursive_array_key_search_first("cig", $anacForm);
$lotIdentifier = recursive_array_key_search_first("lotIdentifier", $anacForm);
if(!empty($cig) || !empty($lotIdentifier)) {
foreach ($appalto->lotti as $index => &$lotto) {
if($lotto->cig == $cig || $lotto->lotIdentifier == $lotIdentifier) {
$lotto->idContratto[] = $esito->idContratto;
}
}
}
break;
}
}
unset($scheda);
unset($lotto);
// Otteniamo le pubblicazioni
$response_pubblicazioni = $npa->apiCall("pubblicazioneAvvisi", "search", ["idAppalto" => $appalto->idAppalto]);
$response_pubblicazioni = json_decode($response_pubblicazioni);
foreach ($response_pubblicazioni->result as $r) {
$result = $npa->apiCall("pubblicazioneAvvisi", "read", ["idAvviso" => $r->idAvviso]);
$result = json_decode($result);
foreach ($appalto->schede as &$scheda) {
if ($scheda->_idScheda == $result->scheda->_idScheda) {
$scheda->pubblicazione = $result->avviso;
}
}
}
// Otteniamo la scheda principale
$response_appalto = $npa->apiCall(
"comunicaAppalto",
"read",
["idAppalto" => $appalto->idAppalto]
);
$response_appalto = json_decode($response_appalto);
if (!isset($response_appalto->appalto->scheda)) {
swalDie("Impossibile determinare la scheda iniziale");
}
$appalto->schedaPrincipale = $response_appalto->appalto->scheda;
}
vdump("Appalto secondo ANAC:", $appalto);
if(!DEVELOP_ENV) {
// Verifichiamo che l'appalto non sia già presente in questo tenant
foreach($appalto->lotti as $lotto) {
if(!empty(NuovaPiattaformaAppalti::fetchLotti(["*"], ["cig" => $lotto->cig], true))) {
swalDie("Un lotto con CIG {$lotto->cig} è già presente in piattaforma");
}
}
if(!empty(NuovaPiattaformaAppalti::fetchDossier(["*"], ["id_appalto" => $appalto->idAppalto]))) {
swalDie("Un fascicolo ANAC con idAppalto {$appalto->idAppalto} è già presente in piattaforma");
}
}
// Cerchiamo di determinare il match-moduli
$codice_prima_scheda = $appalto->schedaPrincipale->codice->codice;
$match_moduli = NuovaPiattaformaAppalti::getCategorizedCardsList();
// Cerchiamo questa scheda nel match moduli
$risultati = recursive_array_search_all($codice_prima_scheda, $match_moduli);
$risultati_compatibili = array_filter($risultati, function ($item) use ($modulo_riferimento) {
return $item[0] == $modulo_riferimento;
});
if (empty($risultati_compatibili)) {
#sostituire la throw con un messaggio che ritorni i moduli compatibili
throw new Exception("Questa gara non è compatibile con il modulo {$modulo_riferimento}");
}
$procedura = null;
$settoreRiferimento = null;
// Ottenimento della procedura
if ($modulo_riferimento === "gare") {
// Vediamo se l'utente ha specificato manualmente una procedura
$procedura = $_REQUEST["procedura"] ?? null;
if (empty($procedura)) {
$procedura = NPA_Import::getProcedura($appalto->schedaPrincipale, $risultati_compatibili);
// Se ci è stata ritornata più di una procedura (O nessuna)...
if (is_array($procedura)) {
// Prendiamo quelle compatibili
if (empty($procedura)) {
$procedura = array_keys($match_moduli[$modulo_riferimento]["procedure"]);
$procedura = array_filter($procedura, function ($item) {
return $item != "*";
});
}
// Facciamo un backup dell'appalto per non dover ricontattare ANAC
$_SESSION["npa_import"] = [
"appalto" => $appalto,
"expiration" => time() + 5 * 60,
$cacheKey => $cacheValue
];
// E chiediamo all'utente
require __DIR__ . "/../inc/components/import/procedura.php";
die();
}
}
// Vediamo se l'utente ha specificato manualmente un settoreRiferimento
$settoreRiferimento = $_REQUEST["settoreRiferimento"] ?? null;
if (empty($settoreRiferimento)) {
$settoreRiferimento = NPA_Import::getSettoreRiferimento($appalto->schedaPrincipale);
// Se ci è stata ritornata più di una procedura (O nessuna)...
if (is_array($settoreRiferimento)) {
// Prendiamo quelle compatibili
if (empty($settoreRiferimento)) {
$settoreRiferimento = ["ordinario", "speciale", "sicurezza"];
}
// Facciamo un backup dell'appalto per non dover ricontattare ANAC
$_SESSION["npa_import"] = [
"appalto" => $appalto,
"expiration" => time() + 5 * 60,
$cacheKey => $cacheValue
];
// E chiediamo all'utente
require __DIR__ . "/../inc/components/import/settoreRiferimento.php";
die();
}
}
$codiceCPV = $_REQUEST["cpv"] ?? [];
// CPV Autoselezionata
if(empty($codiceCPV)) {
foreach ($appalto->lotti as $index => &$lotto) {
$infoLotto = NPA_Import::getInfoLotto($appalto->schede, $lotto);
if(!empty($infoLotto["cpvPrevalente"])) {
$cpvPrevalente = $pdo->go("SELECT codice FROM b_cpv WHERE codice = :codice", [":codice" => $infoLotto["cpvPrevalente"]])->fetch(PDO::FETCH_ASSOC);
if(!empty($cpvPrevalente)) {
$codiceCPV[] = $cpvPrevalente["codice"];
}
}
}
if(empty($codiceCPV)) {
// Facciamo un backup dell'appalto per non dover ricontattare ANAC
$_SESSION["npa_import"] = [
"appalto" => $appalto,
"expiration" => time() + 5 * 60,
$cacheKey => $cacheValue
];
// E chiediamo all'utente
require __DIR__ . "/../inc/components/import/cpv.php";
die();
}
// CPV Ottenute dall'utente
} else {
$userCPV = $codiceCPV;
$codiceCPV = [];
foreach($userCPV as $codice) {
$cpv = $pdo->go("SELECT codice FROM b_cpv WHERE codice = :codice", [":codice" => $codice])->fetch(PDO::FETCH_ASSOC);
if(!empty($cpv)) {
$codiceCPV[] = $cpv["codice"];
}
}
}
}
$hasPartecipanti = false;
$hasAggiudicatari = false;
// Creazione dell'oggetto
switch ($modulo_riferimento) { //crea il fascicolo<
case 'gare':
//$extraInfo section
$nuts = NPA_Import::getNuts($appalto->schede);
$norma_riferimento = NPA_Import::getNormaRiferimento($appalto->schede);
$importi = NPA_Import::getImporti($appalto->schedaPrincipale);
$tipologia = NPA_Import::getTipologia($appalto->schedaPrincipale);
// Tentativo di recupero da affidamento diretto
if(empty($importi)) {
$importoAggiudicazioniLotto = 0;
foreach ($appalto->lotti as $index => &$lotto) {
$infoLotto = NPA_Import::getInfoLotto($appalto->schede, $lotto);
$importoAggiudicazioniLotto += $infoLotto["importoPartecipanti"] ?? 0;
}
$tipoImporto = "servizi";
switch ($tipologia) {
case "L":
$tipoImporto = "lavori";
break;
case "F":
$tipoImporto = "forniture";
break;
default:
break;
}
$importi[$tipoImporto] = $importoAggiudicazioniLotto;
}
$rinnovi = $importi["rinnovi"] ?? 0;
unset($importi["rinnovi"]);
$somma_amministrazione = $importi["sommeAmministrazione"] ?? 0;
unset($importi["sommeAmministrazione"]);
$enteBeneficiario = NPA_Import::getEnteBeneficiario($appalto->schedaPrincipale);
$enteCodiceAusa = $enteBeneficiario["codiceAusa"] ?? "";
$enteCodiceFiscale = $enteBeneficiario["codiceFiscale"] ?? "";
if(!empty($enteCodiceAusa)) {
// Proviamo prima a cercarlo tramite codiceAusa
$ente = ente::fetchEnti(["*"], [
"codice_ausa" => $enteCodiceAusa,
], false);
}
// Proviamo poi a cercerlo tramite codiceFiscale
if(empty($ente) && !empty($codiceFiscale)) {
$ente = ente::fetchEnti(["*"], [
"cf" => $enteCodiceFiscale,
], false);
}
if(empty($ente)) {
swalDie("Impossibile trovare l'ente beneficiario con CF: {$enteCodiceFiscale} o AUSA: {$enteCodiceAusa}");
}
$codicePEC = getPec($_SESSION["ente"]->codice);
#IMPORTA LA GARA
//$id = compilato dalla funzione save della gara
$data_gara = [
"importata" => "BDNCP",
"oggetto" => "[Importazione BDNCP] " . $appalto->oggetto,
"anno" => substr($appalto->dataCreazione, 0, 4),
"stato" => 10, // Viene poi compilato più avanti
"invito_programmato" => "N",
"private_verified" => "N",
"email_chiave" => null,
"codice_ente" => $ente["codice"],
"codice_pec" => $codicePEC,
"procedura" => $procedura,
"modalita" => "extra",
"tipologia" => $tipologia,
"accordo_quadro" => NPA_Import::getAccordoQuadro($appalto->schede) ? "S" : "N",
"derivazione" => null,
"fase_attiva" => 1,
"prezzoRiferimento" => NPA_Import::getPrezzoRiferimento($appalto->schedaPrincipale),
"contributoSUA" => 0,
"contributoSUAVersato" => 0,
"extraInfo" => [
"nuts" => $nuts,
"normaRiferimento" => $norma_riferimento,
"importi" => $importi,
"rinnovi" => $rinnovi,
"sommeAmministrazione" => $somma_amministrazione
],
];
if(!empty($codiceCPV)) {
$data_gara["cpv"] = $codiceCPV;
}
vdump("Creazione gara:", $data_gara);
$gara = gara::save($data_gara);
$codice_gara = $gara->info["codice"];
if (empty($gara)) {
swalDie("Problema tecnico al salvataggio della gara.");
}
// Creiamo i permessi della gara
$permesso = [];
$permesso["sezione"] = "gare";
$permesso["codice_elemento"] = $codice_gara;
$permesso["funzione"] = "0";
$permesso["codice_gestore"] = $_SESSION["ente"]->codice;
$permesso["codice_utente"] = $_SESSION["utente"]->codice;
$salva = new salva();
$salva->debug = false;
$salva->nome_tabella = "r_permessi";
$salva->operazione = "INSERT";
$salva->oggetto = $permesso;
if(empty($salva->save())) {
swalDie("Problema tecnico al salvataggio dei permessi della gara.");
}
$oggetto = $gara;
// Importiamo il RUP
$user_info = $_SESSION["utente"]->getInfo();
$incaricato["codice_fiscale"] = trim(strtoupper($user_info["cf"]));
$incaricato["extraInfo"] = [
"cognome" => $user_info["cognome"],
"nome" => $user_info["nome"],
"email" => $user_info["email"],
];
$incaricato["extraInfo"] = simple_encrypt(json_encode($incaricato["extraInfo"]), $config["simple_encrypt"]["incaricati"]);
$incaricato["modulo"] = $modulo_riferimento;
$incaricato["codice_elemento"] = $oggetto->info["codice"];
$incaricato["ruolo"] = 14;
$salva = new salva();
$salva->debug = defined('__VERBOSE');
$salva->nome_tabella = "b_incaricati";
$salva->operazione = "INSERT";
$salva->oggetto = $incaricato;
if (empty($salva->save())) {
swalDie("Problema tecnico alla creazione del RUP.");
}
// Colleghiamo l'oggetto al fascicolo NPA
$npa->initOggetto($modulo_riferimento, $oggetto->info["codice"]);
// Creiamo il fascicolo NPA
$npa_data = [
"codice_ente" => $_SESSION["ente"]->codice,
"modulo_riferimento" => $modulo_riferimento,
"id_riferimento" => $oggetto->info["codice"],
"id_appalto" => $appalto->idAppalto
];
vdump("Creazione fascicolo NPA", $npa_data);
$npa->save($npa_data, false);
if (empty($npa->fascicolo["codice"])) {
swalDie("Impossibile creare il fascicolo ANAC");
}
$npa->updateFascicolo(["id_appalto" => $appalto->idAppalto]);
$user_info = $_SESSION["utente"]->getInfo();
$user_cf = strtoupper(trim($user_info["cf"]));
// Importazione base dei lotti
foreach ($appalto->lotti as $index => &$lotto) {
$infoLotto = NPA_Import::getInfoLotto($appalto->schede, $lotto);
$data_lot = [
"codice_gara" => $oggetto->info["codice"],
"stato" => 0,
"numero" => $index+1,
"cig" => $lotto->cig,
"cup" => $infoLotto["cupLotto"] ?? "",
"cpv" => $infoLotto["cpvPrevalente"] ?? "",
"criterio" => ($infoLotto["criteriAggiudicazione"] ?? null) != "quality" ? "prezzo" : "vantaggiosa",
"oggetto" => $lotto->oggetto,
"descrizione" => $lotto->oggetto,
"importoBase" => $infoLotto["importoBase"] ?? 0,
"importoManodopera" => $infoLotto["importoManodopera"] ?? 0,
"importoOpzioni" => $infoLotto["importoOpzioni"] ?? 0,
"oneriNoRibasso" => $infoLotto["importoOneri"] ?? 0,
"importoAggiudicazione" => $infoLotto["importoAggiudicazione"] ?? 0,
"sogliaAnomalia" => null,
"extraInfo" => null,
"utente_creazione" => null,
"timestamp_creazione" => null,
"utente_modifica" => $_SESSION["utente"]->codice,
"timestamp" => date('Y-m-d H:i:s')
];
vdump("Creazione Lotto", $data_lot);
$salva = new salva();
$salva->debug = defined('__VERBOSE');
$salva->nome_tabella = "b_gare_lotti";
$salva->operazione = "INSERT";
$salva->oggetto = $data_lot;
$lotto->codice_lotto_oggetto = $salva->save();
//importa i lotti di npa
$salva = new salva();
$salva->debug = defined('__VERBOSE');
$salva->nome_tabella = "b_npa_lotti";
$salva->operazione = "INSERT";
$salva->oggetto = [
"codice_npa" => $npa->fascicolo["codice"],
"lotto_riferimento" => $lotto->codice_lotto_oggetto,
"cig" => $lotto->cig,
"utente_modifica" => $_SESSION["utente"]->codice,
];
$salva->ignore = ["extraInfo", "stato"];
$lotto->codice_lotto_npa = $salva->save();
}
unset($lotto);
$fasi = $gara->getProcedura()["fasi"] ?? null;
if (!empty($fasi)) {
foreach ($fasi as $id => $fase) {
if ($fase["obbligatoria"]) {
if ($gara->inizializzaFase($id, $fase)) {
$error = false;
break;
}
}
}
}
$gara = $oggetto = null;
$oggetto = gara::init($codice_gara);
$elaborazione = [
"settoreRiferimento" => $settoreRiferimento,
"concessione" => NPA_Import::isConcessione($appalto->schedaPrincipale) ? "S" : "N"
];
$oggetto->saveExtraInfo("elaborazione",json_encode($elaborazione, JSON_PRETTY_PRINT), "round");
break;
case 'concorsi':
#TODO: scrivere la init Static del concorso;
#$oggetto = concorso::initStatic();
break;
default:
break;
}
// Importazione dei partecipanti
foreach ($appalto->lotti as $index => &$lotto) {
if(NPA_Import::isDeserta($appalto->schede, $lotto)) {
$oggetto->setLotto($lotto->codice_lotto_oggetto);
$oggetto->updateStatoLotto(95);
$oggetto->addToLog("DESERTA",__("Lotto") . " " . $oggetto->lotto["numero"]);
$oggetto->lotto = null;
} else {
// Importiamo i partecipanti
$partecipanti = NPA_Import::importaPartecipanti($appalto->schede, $oggetto, $lotto);
if (!empty($partecipanti)) {
$hasPartecipanti = true;
}
if (NPA_Import::importaAggiudicatari($appalto->schede, $oggetto, $lotto, $partecipanti)) {
$oggetto->setLotto($lotto->codice_lotto_oggetto);
$oggetto->updateStatoLotto(35);
$oggetto->lotto = null;
$hasAggiudicatari = true;
}
}
// Importiamo le schede di lotto
NPA_Import::importaSchede($appalto->schede, $npa, $lotto);
}
// Importiamo le schede generali
NPA_Import::importaSchede($appalto->schede, $npa);
if ($hasAggiudicatari) {
$oggetto->valutaStatoGenerale(true);
} elseif ($hasPartecipanti) {
$oggetto->updateStato(21);
}
?>
<script>
Swal({
title: "Procedura importata con successo",
html: "La procedura è stata importata con successo!",
type: "success",
}).then(() => {
<?php if(!defined("__VERBOSE")): ?>
window.location.reload();
<?php endif; ?>
})
</script>