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.
5456 righe
204 KiB
5456 righe
204 KiB
<? |
|
|
|
class gara |
|
{ |
|
|
|
public $info; |
|
public $round; |
|
public $lotto; |
|
public $activeRound; |
|
public $quickAvailable; |
|
public $quickPanel; |
|
public $db; |
|
public $commissario; |
|
public $normaRiferimento; |
|
protected $managerAvvisi; |
|
protected $managerCommissione; |
|
protected $managerIncarichi; |
|
protected $managerDGUE; |
|
protected $managerRichieste; |
|
protected $managerPubblicita; |
|
public $privata; |
|
public $printSelectLottiConditions; |
|
public $npa; |
|
public $extender; |
|
public $error_rda; |
|
|
|
static function getTipologie($filters = null) |
|
{ |
|
$moduli = self::getModuli($filters); |
|
$tmp = []; |
|
foreach ($moduli as $modulo) { |
|
$tmp[] = $modulo["tipo"]; |
|
} |
|
$tmp = array_unique($tmp); |
|
if (!empty($tmp)) { |
|
$tipologie = []; |
|
global $config; |
|
$conf = jsonToArray($config["jsonFolder"] . "/gare-tipologie.json"); |
|
foreach ($tmp as $tipo) { |
|
$tipologie[$tipo] = $conf[$tipo]; |
|
} |
|
return $tipologie; |
|
} else { |
|
return false; |
|
} |
|
} |
|
|
|
private static function extensionExists() { |
|
if (isset($_SESSION["ente"])) { |
|
$pathExtender = $_SESSION["ente"]->getExtensionPath() . DIRECTORY_SEPARATOR . "gara.extender.class.php"; |
|
$extenderName = "GaraExtender{$_SESSION["ente"]->codice}"; |
|
if (file_exists($pathExtender)) { |
|
include_once $pathExtender; |
|
return $extenderName; |
|
} |
|
} |
|
} |
|
|
|
private function __construct() |
|
{ |
|
global $pdo; |
|
$this->commissario = false; |
|
$this->db = $pdo; |
|
} |
|
|
|
public static function riferimentiNormativi() { |
|
return [ |
|
"2016-50" => [ |
|
"label" => "D.lgs 50/2016", |
|
"inizio" => null, |
|
"fine" => '2023-06-30 23:59:59' |
|
], |
|
"2023-36" => [ |
|
"label" => "D.lgs 36/2023", |
|
"inizio" => '2023-07-01 00:00:00', |
|
"fine" => null |
|
], |
|
]; |
|
} |
|
|
|
public static function interpretazioniArt41() : Array { |
|
return [ |
|
"complessivo" => "Offerta complessiva: L'operatore economico esprimerà un'offerta complessiva inclusiva di eventuali costi della manodopera differenti", |
|
"scorporato" => "Valutazione separata: L'operatore economico esprimerà un'offerta sulla componente base a cui si sommeranno i costi della manodopera da lui indicati per il calcolo del ribasso complessivo" |
|
]; |
|
} |
|
|
|
public static function statiTermineProcedura() { |
|
return [ |
|
"35", // "Aggiudicazione definitiva" |
|
"50", // "Inviato esito" |
|
"90", // "Annullato" |
|
"95", // "Deserto" |
|
"99", // "Non aggiudicato" |
|
"100" // "Completo" |
|
]; |
|
} |
|
|
|
public function updateStato($stato) |
|
{ |
|
if ($this->info["fase_attiva"] == $this->round["numero"] && $this->info["stato"] < $stato) { |
|
$this->db->go("UPDATE b_gare SET stato = :stato WHERE codice = :codice", [":stato" => $stato, ":codice" => $this->info["codice"]]); |
|
$this->info["stato"] = $stato; |
|
if (in_array($stato,static::statiTermineProcedura()) !== false) { |
|
$b = settingsManager::getValue("pubblicazioneSuConclusione"); |
|
if ($b >= 0 && !$this->privata) { |
|
$this->db->go("UPDATE b_gare_round SET pubblica = :pubblica WHERE codice = :codice", [":pubblica" => $b, ":codice" => $this->round["codice"]]); |
|
$this->round["pubblica"] = $b; |
|
if (empty($this->round["pubblicazione"])) { |
|
$this->db->go("UPDATE b_gare_round SET pubblicazione = NOW() WHERE codice = :codice", [":codice" => $this->round["codice"]]); |
|
$this->round["pubblicazione"] = date("Y-m-d H:i:s"); |
|
} |
|
} |
|
} |
|
$this->calcolaContributo(); |
|
$this->updateBadges(); |
|
} |
|
$this->triggerUpdates(); |
|
|
|
// se la gara è collegata a un'rda, aggiorna lo stato dell'rda |
|
$this->updateStateRda(); |
|
} |
|
|
|
public function triggerUpdates() { |
|
if (isset($_SESSION["ente"])) { |
|
$_SESSION["ente"]->manageUpdates("gare", $this->info["codice"], $this); |
|
$_SESSION["ente"]->checkConservazione("gare", $this->info["codice"], $this->info["stato"], $this->info["codice_ente"]); |
|
try { |
|
ProcurePlus\Out::sendGara($this); |
|
} catch(\Throwable $t) { /* Niente */ } |
|
} |
|
} |
|
|
|
public function updateStatoLotto(int $stato,bool $force = false) |
|
{ |
|
if (!empty($this->lotto) && ($this->info["fase_attiva"] == $this->round["numero"] && ($this->lotto["stato"] < $stato || $force))) { |
|
$this->db->go("UPDATE b_gare_lotti SET stato = :stato WHERE codice = :codice", [":stato" => $stato, ":codice" => $this->lotto["codice"]]); |
|
$this->valutaStatoGenerale($force); |
|
} |
|
} |
|
|
|
public function calcolaContributo() { |
|
if ($this->info["codice"] != $_SESSION["ente"]->codice) { |
|
$infoContributo = Ente::getContributiSUA($_SESSION["ente"]->codice,$this->info["prezzoRiferimento"]); |
|
if (!empty($infoContributo["quote"]) && ($infoContributo["all"] || !empty($this->getModalita()["online"]))) { |
|
if (($infoContributo["tipo"] == "2" && $this->info["stato"] == 20) || ($infoContributo["tipo"] == "1" && $this->info["stato"] == 35)) { |
|
$riferimento = $this->info["prezzoRiferimento"]; |
|
if ($infoContributo["tipo"] != "2") { |
|
$lotti = $this->getLotti(); |
|
$riferimento = 0; |
|
foreach($lotti AS $lotto) { |
|
$riferimento += $lotto["importoAggiudicazione"]; |
|
} |
|
} |
|
if (!empty($riferimento)) { |
|
$contributo = 0; |
|
foreach($infoContributo["quote"] AS $quota) { |
|
if($quota["tipo"] == "fisso") { |
|
$contributo += $quota["valore"]; |
|
} else if ($quota["tipo"] == "percentuale") { |
|
$contributo += $riferimento * ($quota["valore"]/100); |
|
} |
|
} |
|
if (!empty($contributo)) { |
|
$this->db->go("UPDATE b_gare SET contributoSUA = :contributo WHERE codice = :codice", [":contributo" => $contributo, ":codice" => $this->info["codice"]]); |
|
$this->info["contributo"] = $contributo; |
|
} |
|
} |
|
} |
|
} |
|
} |
|
} |
|
|
|
public function getManagerRegistro() |
|
{ |
|
return new registriManager("gare", $this->info["codice"]); |
|
} |
|
|
|
public function configurazioneBusteConfermata() |
|
{ |
|
if ($this->info["stato"] <= 10) { |
|
$extraInfo = $this->getExtraInfo()["round"] ?? []; |
|
if (isset($extraInfo["conferma_buste"]) && $extraInfo["conferma_buste"] === true) { |
|
return true; |
|
} |
|
return false; |
|
} |
|
return true; |
|
} |
|
public function sedutaAperta() |
|
{ |
|
$extraInfo = $this->getExtraInfo()["round"] ?? []; |
|
if (isset($extraInfo["seduta_aperta"]) && $extraInfo["seduta_aperta"] === true) { |
|
return true; |
|
} |
|
return false; |
|
} |
|
|
|
public function showPunteggiTecnici() |
|
{ |
|
$extraInfo = $this->getExtraInfo()["round"] ?? []; |
|
if (isset($extraInfo["esponi_tecnici"]) && $extraInfo["esponi_tecnici"] === true) { |
|
return true; |
|
} |
|
return false; |
|
} |
|
|
|
public function showPunteggiEconomici() |
|
{ |
|
$extraInfo = $this->getExtraInfo()["round"] ?? []; |
|
if (isset($extraInfo["esponi_economici"]) && $extraInfo["esponi_economici"] === true) { |
|
return true; |
|
} |
|
return false; |
|
} |
|
|
|
public function addToLog($operazione, $oggetto) |
|
{ |
|
return $this->getManagerRegistro()->addToLog($operazione, $oggetto); |
|
} |
|
|
|
public function getLog($start = 0, $length = -1) |
|
{ |
|
return $this->getManagerRegistro()->getLog($start, $length); |
|
} |
|
|
|
public function saveExtraInfo($chiave, $valore, $ambito = "gara") |
|
{ |
|
$extraInfo = $this->getExtraInfo(); |
|
$extraInfo[$ambito][$chiave] = $valore; |
|
if ($ambito == "gara") { |
|
$codice = $this->info["codice"]; |
|
$tabella = "b_gare"; |
|
$this->info["extraInfo"] = json_encode($extraInfo["gara"]); |
|
} else if ($ambito == "round") { |
|
$codice = $this->round["codice"]; |
|
$tabella = "b_gare_round"; |
|
$this->round["extraInfo"] = json_encode($extraInfo["round"]); |
|
} else if ($ambito == "lotto") { |
|
$codice = $this->lotto["codice"]; |
|
$tabella = "b_gare_lotti"; |
|
$this->lotto["extraInfo"] = json_encode($extraInfo["lotto"]); |
|
} |
|
if (!empty($codice) && !empty($tabella)) { |
|
$extraInfo = json_encode($extraInfo[$ambito]); |
|
$salva = new salva(); |
|
$salva->debug = false; |
|
|
|
$salva->nome_tabella = $tabella; |
|
$salva->operazione = "UPDATE"; |
|
$salva->oggetto = ["codice" => $codice, "extraInfo" => $extraInfo]; |
|
if (!empty($salva->save())) { |
|
return true; |
|
} |
|
} |
|
return false; |
|
} |
|
|
|
public static function save($data) |
|
{ |
|
|
|
global $pdo; |
|
$return = false; |
|
$operazione_generale = $operazione = empty($data["codice"]) ? "INSERT" : "UPDATE"; |
|
$expect = ["codice", "id", "oggetto", "modalita", "tipologia", "accordo_quadro", "procedura", "prezzoRiferimento", "codice_pec", "email_chiave", "codice_ente", "utente_creazione", "timestamp_creazione"]; |
|
$solare = false; |
|
$affix = ""; |
|
if ($_SESSION["ente"]->getInfo()["numerazione"] == "solare") { |
|
$solare = true; |
|
$expect[] = "anno"; |
|
$affix = $data["anno"] . "/"; |
|
} |
|
$canClone = false; |
|
if ($operazione == "INSERT") { |
|
$canClone = true; |
|
$data["id"] = 1; |
|
$where = ""; |
|
$bind = []; |
|
if ($solare) { |
|
$where = " WHERE anno = :anno "; |
|
$bind[":anno"] = $data["anno"]; |
|
} |
|
$sql = "SELECT id FROM b_gare {$where} ORDER BY codice DESC LIMIT 0,1 "; |
|
$ris = $pdo->go($sql,$bind); |
|
if ($ris->rowCount() === 1) { |
|
$rec = $ris->fetch(PDO::FETCH_ASSOC); |
|
if ($solare) { |
|
$tmp = explode("/",$rec["id"]); |
|
if (!empty($tmp[1])) { |
|
$rec["id"] = $tmp[1]; |
|
} |
|
} |
|
$data["id"] = (int)$rec["id"] + 1; |
|
} |
|
$data["id"] = $affix . $data["id"]; |
|
$data["utente_creazione"] = $_SESSION["utente"]->codice; |
|
$data["timestamp_creazione"] = date('Y-m-d H:i:s'); |
|
} else { |
|
$checkRound = $pdo->go("SELECT codice FROM b_gare_round WHERE codice_gara = :codice",[":codice"=>$data["codice"]]); |
|
if ($checkRound->rowCount() > 0) { |
|
$expect = ["codice", "id", "oggetto", "modalita", "accordo_quadro", "prezzoRiferimento", "codice_pec", "email_chiave", "codice_ente", "utente_creazione", "timestamp_creazione"]; |
|
} |
|
} |
|
|
|
if(!empty($data["importata"])) { |
|
$expect[] = "importata"; |
|
} |
|
|
|
$salva = new salva(); |
|
$salva->debug = false; |
|
|
|
$salva->nome_tabella = "b_gare"; |
|
$salva->operazione = $operazione; |
|
$salva->oggetto = $data; |
|
$salva->expect = $expect; |
|
$codice = $salva->save(); |
|
if ($codice !== false) { |
|
if ($operazione_generale == "INSERT") { |
|
if ($_SESSION["utente"]->gerarchia > 15) { |
|
$utenti = [$_SESSION["utente"]->codice]; |
|
} |
|
if (!empty($utenti)) { |
|
foreach ($utenti as $utente) { |
|
$permesso = []; |
|
$permesso["sezione"] = "gare"; |
|
$permesso["codice_elemento"] = $codice; |
|
$permesso["funzione"] = "0"; |
|
$permesso["codice_gestore"] = $_SESSION["ente"]->codice; |
|
$permesso["codice_utente"] = $utente; |
|
$salva = new salva(); |
|
$salva->debug = false; |
|
|
|
$salva->nome_tabella = "r_permessi"; |
|
$salva->operazione = "INSERT"; |
|
$salva->oggetto = $permesso; |
|
$salva->save(); |
|
} |
|
} |
|
} |
|
|
|
|
|
$bind = array(":codice" => $codice); |
|
$strsql = "DELETE FROM r_cpv_gare WHERE codice_gara = :codice"; |
|
$pdo->go($strsql, $bind); |
|
scriviLog("r_cpv_gare", "DELETE", $pdo->getSQL()); |
|
|
|
if (!empty($data["cpv"])) { |
|
$data["cpv"] = array_unique($data["cpv"]); |
|
foreach ($data["cpv"] as $codice_categoria) { |
|
if ($codice_categoria != "") { |
|
$bind = array(":codice" => $codice, ":codice_categoria" => $codice_categoria, ":codice_utente" => $_SESSION["utente"]->codice); |
|
$strsql = "INSERT INTO r_cpv_gare (codice_gara,codice,utente_modifica) VALUES (:codice,:codice_categoria,:codice_utente)"; |
|
$pdo->go($strsql, $bind); |
|
scriviLog("r_cpv_gare", "INSERT", $pdo->getSQL()); |
|
} |
|
} |
|
} |
|
|
|
$bind = array(); |
|
$bind[":codice"] = $codice; |
|
|
|
$strsql = "SELECT * FROM b_gare WHERE codice = :codice"; |
|
$risultato = $pdo->go($strsql, $bind); |
|
if ($risultato->rowCount() > 0) { |
|
$record = $risultato->fetch(PDO::FETCH_ASSOC); |
|
if (empty($record["public_key"]) && getModalita()[$record["modalita"]]["online"]) { |
|
$email = $data["email_chiave"] ?? ""; |
|
$public = P7Manager::generateKeys("gare-{$record["id"]}", $record["oggetto"], $email); |
|
if (!empty($public)) { |
|
if (!$pdo->go("UPDATE b_gare SET public_key = :public_key WHERE codice = :codice", [":public_key" => $public, ":codice" => $record["codice"]])) { |
|
$error_key = true; |
|
} |
|
} else { |
|
$error_key = true; |
|
} |
|
} |
|
if (!isset($error_key)) { |
|
$return = gara::init($record["codice"]); |
|
if (!empty($return)) { |
|
foreach ($data["extraInfo"] as $chiave => $valore) { |
|
$return->saveExtraInfo($chiave, $valore, "gara"); |
|
} |
|
$return->addToLog($operazione_generale, "Dati preliminari"); |
|
if ($canClone) { |
|
$return->clone(); |
|
} |
|
} |
|
} else { |
|
$return = -1; |
|
if ($operazione == "INSERT") { |
|
$pdo->go("DELETE FROM b_gare WHERE codice = :codice", [":codice" => $codice]); |
|
} |
|
} |
|
} |
|
|
|
// salva relazione con rda se esiste |
|
if(!empty($return->info['codice']) && !empty($data['codici_rda'])){ |
|
foreach ($data['codici_rda'] as $codice_rda) { |
|
|
|
$bind = array(":codice_gara" => $codice, ":codice_rda" => $codice_rda, ":codice_utente" => $_SESSION["utente"]->codice); |
|
$strsql = "INSERT INTO r_gara_rda (codice_gara,codice_rda,utente_modifica) VALUES (:codice_gara,:codice_rda,:codice_utente)"; |
|
$ris = $pdo->go($strsql, $bind); |
|
scriviLog("r_gara_rda", "INSERT", $pdo->getSQL()); |
|
|
|
if($ris->rowCount() === 1){ |
|
|
|
// controlla se esiste lo stato 20 |
|
$codice_stato = StatoRda::getStati(null, 20); |
|
|
|
if(!empty($codice_stato)){ |
|
$codice_stato = reset($codice_stato); |
|
$bind = array(":codice" => $codice_rda, ":codice_stato" => $codice_stato['codice'], ":utente_modifica" => $_SESSION["utente"]->codice); |
|
$strsql = "UPDATE b_rda SET codice_stato = :codice_stato, utente_modifica = :utente_modifica WHERE codice = :codice"; |
|
$ris = $pdo->go($strsql, $bind); |
|
scriviLog("b_rda", "UPDATE", $pdo->getSQL()); |
|
}else{ |
|
$rda = rda::init($codice_rda); |
|
$return->error_rda[] = __("Errore creazione Gara da RDA #{$rda->info['codice']} - {$rda->info['oggetto']} "); |
|
} |
|
} |
|
} |
|
} |
|
|
|
|
|
} |
|
return $return; |
|
} |
|
|
|
public function setLotto($codice) { |
|
if (!empty($codice)) { |
|
$dbLotto = $this->getLotti($codice)[0] ?? false; |
|
if (!empty($dbLotto)) { |
|
$dbLotto = static::getImportiBaseAsta($dbLotto,$this->normaRiferimento); |
|
$this->lotto = $dbLotto; |
|
return true; |
|
} |
|
} |
|
return false; |
|
} |
|
|
|
public function pubblicaPartecipanti($codiceLotto = NULL) { |
|
if (!empty($this->round)) { |
|
if (!empty($codiceLotto)) { |
|
$lotto = $this->getLotti($codiceLotto)[0] ?? false; |
|
} else if (!empty($this->lotto)) { |
|
$lotto = $this->lotto; |
|
} |
|
if ($lotto["stato"] >= 30) { |
|
$extraInfo = json_decode($lotto["extraInfo"],true); |
|
return $extraInfo["showPartecipanti-{$this->round["codice"]}"] ?? false; |
|
} |
|
} |
|
return false; |
|
} |
|
|
|
public function pubblicaAtti($codiceLotto = NULL) { |
|
if (!empty($this->round)) { |
|
if (!empty($codiceLotto)) { |
|
$lotto = $this->getLotti($codiceLotto)[0] ?? false; |
|
} else if (!empty($this->lotto)) { |
|
$lotto = $this->lotto; |
|
} |
|
if (isset($lotto)) { |
|
if ($lotto["stato"] >= 50) { |
|
$extraInfo = json_decode($lotto["extraInfo"],true); |
|
return $extraInfo["showAtti-{$this->round["codice"]}"] ?? false; |
|
} |
|
} |
|
} |
|
return false; |
|
} |
|
|
|
public function forceAccessoAttiAmministrativa() : Bool { |
|
$rispostaForce = $this->getRisposteElaborazione()["accessoArt36ForceAmministrativa"] ?? "N"; |
|
return ($rispostaForce == "S"); |
|
} |
|
|
|
/** |
|
* amministrativaSecretabile |
|
* |
|
* @param string $dataPubblicazione |
|
* @param string $force |
|
* @return Bool |
|
*/ |
|
public static function amministrativaSecretabile(?String $dataPubblicazione = "1970-01-01", Bool $force = false) : Bool { |
|
return ($force || strtotime($dataPubblicazione) > strtotime(date("2024-04-04"))); |
|
} |
|
|
|
public function getRichiestePubblicabili() { |
|
$richieste = $this->getRichieste(); |
|
$return = []; |
|
if (!empty($richieste)) { |
|
foreach($richieste AS $richiesta) { |
|
if ($richiesta["busta"] != "amministrativa" || self::amministrativaSecretabile($this->round["pubblicazione"],$this->forceAccessoAttiAmministrativa())) { |
|
$return[] = $richiesta; |
|
} |
|
} |
|
} |
|
return $return; |
|
} |
|
|
|
public function getBustaAccesso(int $richiesta,int $partecipante,bool $content = false) { |
|
$busta = $this->getBusta($partecipante,$richiesta,false,$content); |
|
if (!empty($busta)) { |
|
$pubblica = $busta["pubblica"]; |
|
$origine = "busta"; |
|
$oscurata = false; |
|
$emendamento = $this->getEmendamento($partecipante,$richiesta,$content); |
|
if (!empty($emendamento) && $emendamento["accettata"] == "S") { |
|
$busta = $emendamento; |
|
$origine = "emendamento"; |
|
if ($emendamento["segreta"] == "S") { |
|
$tmp = $this->getBustaSecretata($partecipante,$richiesta,"emendamento",$content); |
|
if (!empty($tmp) && $tmp["accettata"] == "S") { |
|
$oscurata = true; |
|
$busta = $tmp; |
|
} |
|
} else { |
|
if (empty($pubblica)) { |
|
$this->modificaPubblicazioneBusta("S",$partecipante,$richiesta); |
|
$pubblica = "S"; |
|
} |
|
} |
|
} else { |
|
if ($busta["segreta"] == "S") { |
|
$tmp = $this->getBustaSecretata($partecipante,$richiesta,"busta",$content); |
|
if (!empty($tmp) && $tmp["accettata"] == "S") { |
|
$oscurata = true; |
|
$busta = $tmp; |
|
} |
|
} else { |
|
if (empty($pubblica)) { |
|
$this->modificaPubblicazioneBusta("S",$partecipante,$richiesta); |
|
$pubblica = "S"; |
|
} |
|
} |
|
} |
|
$busta["origine"] = $origine; |
|
$busta["oscurata"] = $oscurata; |
|
$busta["pubblica"] = $pubblica; |
|
} |
|
return $busta; |
|
} |
|
|
|
public function modificaPubblicazioneBusta(string $esito,int $partecipante,int $richiesta) { |
|
$busta = $this->getBusta($partecipante,$richiesta); |
|
if (!empty($busta)) { |
|
$richiesta = $this->getRichiesta($richiesta); |
|
if ($richiesta["busta"] != "amministrativa" || self::amministrativaSecretabile($this->round["pubblicazione"],$this->forceAccessoAttiAmministrativa())) { |
|
$salva = new salva(); |
|
$salva->debug = false; |
|
$salva->nome_tabella = "b_gare_buste"; |
|
$salva->operazione = "UPDATE"; |
|
$salva->oggetto = ["codice"=>$busta["codice"],"pubblica"=>$esito]; |
|
$salva->save(); |
|
return true; |
|
} |
|
} |
|
} |
|
|
|
public function getBusteSoggetteAccesso() { |
|
$richieste = $this->getRichiestePubblicabili(); |
|
$partecipanti = $this->getPartecipanti(); |
|
$return = []; |
|
if (!empty($richieste) && !empty($partecipanti)) { |
|
foreach($partecipanti AS $partecipante) { |
|
if ($partecipante["escluso"] == "N") { |
|
$return[$partecipante["codice"]] = []; |
|
foreach($richieste AS $richiesta) { |
|
$return[$partecipante["codice"]][$richiesta["codice"]] = $this->getBustaAccesso($richiesta["codice"],$partecipante["codice"]); |
|
} |
|
} |
|
} |
|
} |
|
return $return; |
|
} |
|
|
|
public function saveLotto($data) { |
|
$operazione = (empty($data["codice"])) ? "INSERT" : "UPDATE"; |
|
if ($operazione == "INSERT") { |
|
$lotti = $this->getLotti(); |
|
if (!empty($lotti)) { |
|
$data["numero"] = count($lotti) + 1; |
|
} else { |
|
$data["numero"] = 1; |
|
} |
|
} |
|
$data["codice_gara"] = $this->info["codice"]; |
|
$salva = new salva(); |
|
$salva->debug = false; |
|
$salva->nome_tabella = "b_gare_lotti"; |
|
$salva->operazione = $operazione; |
|
$salva->oggetto = $data; |
|
$salva->ignore = ["extraInfo","stato"]; |
|
$codice = $salva->save(); |
|
if (!empty($codice)) { |
|
if ($this->setLotto($codice)) { |
|
if (!empty($data["extraInfo"])) { |
|
foreach($data["extraInfo"] AS $key => $value) { |
|
$this->saveExtraInfo($key,$value,"lotto"); |
|
} |
|
} |
|
return $codice; |
|
} |
|
} |
|
return false; |
|
} |
|
|
|
public function soloEconomica() { |
|
return (empty($this->getLottiOEPV())) ? true : false; |
|
} |
|
|
|
public function getLottiMP() { |
|
$lotti = $this->getLotti(); |
|
$return = []; |
|
if (!empty($lotti)) { |
|
foreach($lotti AS $lotto) { |
|
if ($lotto["criterio"] == "prezzo") { |
|
$return[] = $lotto; |
|
} |
|
} |
|
} |
|
return $return; |
|
} |
|
|
|
public function getLottiOEPV() { |
|
$lotti = $this->getLotti(); |
|
$return = []; |
|
if (!empty($lotti)) { |
|
foreach($lotti AS $lotto) { |
|
if ($lotto["criterio"] != "prezzo") { |
|
$return[] = $lotto; |
|
} |
|
} |
|
} |
|
return $return; |
|
} |
|
|
|
public function getIdAppalto() { |
|
return $this->info["codice"]; // TODO: Restituire l'id appalto rilasciato da ANAC |
|
} |
|
|
|
public function getExtraInfo() |
|
{ |
|
$return = []; |
|
if (!empty($this->info["extraInfo"])) { |
|
$return["gara"] = json_decode($this->info["extraInfo"], true); |
|
} |
|
if (!empty($this->round["extraInfo"])) { |
|
$return["round"] = json_decode($this->round["extraInfo"], true); |
|
} |
|
if (!empty($this->lotto["extraInfo"])) { |
|
$return["lotto"] = json_decode($this->lotto["extraInfo"], true); |
|
} |
|
return $return; |
|
} |
|
|
|
public static function getStati() |
|
{ |
|
return jsonToArray(__DIR__ . "/stati.json"); |
|
} |
|
|
|
/** |
|
* Restituisce la configurazione delle buste |
|
* |
|
* @param String|null $dataPubblicazione - Indicare la data di pubblicazione |
|
* @return Array |
|
*/ |
|
public static function tipologieBusta(String $dataPubblicazione = "1970-01-01") : Array |
|
{ |
|
$return = []; |
|
$return["amministrativa"] = ["titolo" => "Busta Amministrativa","emendabile"=>false,"secretabile"=>self::amministrativaSecretabile($dataPubblicazione)]; |
|
$return["tecnica"] = ["titolo" => "Busta Tecnica","emendabile"=>true,"secretabile"=>true]; |
|
$return["economica"] = ["titolo" => "Busta Economica","emendabile"=>true,"secretabile"=>true]; |
|
return $return; |
|
} |
|
|
|
public function busteDisponibili() { |
|
$return = self::tipologieBusta(); |
|
if (empty($this->getLottiOEPV()) || (isset($this->lotto) && $this->lotto["criterio"] == "prezzo")) { |
|
unset($return["tecnica"]); |
|
} |
|
return $return; |
|
} |
|
|
|
public function getRichieste($busta = NULL) |
|
{ |
|
$bind = [":codice_round" => $this->round["codice"]]; |
|
$sql = "SELECT b_gare_richieste.* FROM b_gare_richieste "; |
|
if (!empty($this->lotto)) { |
|
$sql .= " JOIN r_gare_richieste_lotti ON b_gare_richieste.codice = r_gare_richieste_lotti.codice_richiesta "; |
|
} |
|
|
|
$sql .= " WHERE codice_round = :codice_round "; |
|
if (!empty($this->lotto)) { |
|
$sql .= " AND (r_gare_richieste_lotti.codice_lotto = 0 OR r_gare_richieste_lotti.codice_lotto = :lotto ) "; |
|
if ($this->lotto["criterio"] == "prezzo") { |
|
$sql .= " AND b_gare_richieste.busta <> 'tecnica' "; |
|
} |
|
$bind[":lotto"] = $this->lotto["codice"]; |
|
} |
|
if (!empty($busta)) { |
|
$bind[":busta"] = $busta; |
|
$sql .= " AND b_gare_richieste.busta = :busta "; |
|
} |
|
$sql .= " ORDER BY b_gare_richieste.ordinamento, b_gare_richieste.codice "; |
|
return $this->db->go($sql, $bind)->fetchAll(PDO::FETCH_ASSOC); |
|
} |
|
|
|
public function getRichiesta($codice) { |
|
$richieste = $this->getRichieste(); |
|
if (!empty($richieste)) { |
|
foreach($richieste AS $richiesta) { |
|
if ($richiesta["codice"] == $codice) { |
|
return $richiesta; |
|
} |
|
} |
|
} |
|
return false; |
|
} |
|
|
|
public function getRounds($codice = null) |
|
{ |
|
$bind = [":codice_gara" => $this->info["codice"]]; |
|
$sql = "SELECT * FROM b_gare_round WHERE codice_gara = :codice_gara "; |
|
if ($codice !== null) { |
|
$bind[":codice"] = $codice; |
|
$sql .= " AND codice = :codice "; |
|
} |
|
return $this->db->go($sql . " ORDER BY numero", $bind)->fetchAll(PDO::FETCH_ASSOC); |
|
} |
|
|
|
public function fasiSuccessive() { |
|
$return = []; |
|
$procedura = $this->getProcedura(); |
|
if (!empty($procedura["fasi"])) { |
|
$found = false; |
|
foreach($procedura["fasi"] AS $key => $info) { |
|
if ($key == $this->round["id"]) { |
|
$found = true; |
|
if ($info["ripetibile"]) { |
|
$return[$key] = $info; |
|
} |
|
} else { |
|
if ($found) { |
|
$return[$key] = $info; |
|
break; |
|
} |
|
} |
|
} |
|
} |
|
return $return; |
|
} |
|
|
|
/** |
|
* getInmportiBaseAsta |
|
* |
|
* Aggiunge al lotto passato alla funzione le chiavi importoRibassabile e importoNonRibassabile in base alla configurazione del lotto |
|
* |
|
* @param Array $lotto |
|
* @param ?String $norma |
|
* @return Array |
|
*/ |
|
public static function getImportiBaseAsta(Array $lotto, String $norma = null ) : Array { |
|
$lotto["importoRibassabile"] = (!empty($lotto["importoBase"])) ? $lotto["importoBase"] : 0; |
|
if ($norma != "2016-50") { |
|
$lotto["importoRibassabile"] += (!empty($lotto["importoManodopera"])) ? $lotto["importoManodopera"] : 0; |
|
} |
|
$lotto["importoNonRibassabile"] = (!empty($lotto["oneriNoRibasso"])) ? $lotto["oneriNoRibasso"] : 0; |
|
return $lotto; |
|
} |
|
|
|
public static function formatLotto($lotto,$niceNumbers = false) { |
|
$decimale = "."; |
|
$migliaia = ""; |
|
if ($niceNumbers) { |
|
$decimale = ","; |
|
$migliaia = "."; |
|
} |
|
if (!isset($lotto["importoRibassabile"])) { |
|
$lotto = static::getImportiBaseAsta($lotto); |
|
} |
|
if (!empty($lotto["importoRibassabile"])) { $lotto["importoRibassabile"] = number_format($lotto["importoRibassabile"],2,$decimale,$migliaia); } |
|
if (!empty($lotto["importoNonRibassabile"])) { $lotto["importoNonRibassabile"] = number_format($lotto["importoNonRibassabile"],2,$decimale,$migliaia); } |
|
if (!empty($lotto["importoBase"])) { $lotto["importoBase"] = number_format($lotto["importoBase"],2,$decimale,$migliaia); } |
|
if (!empty($lotto["importoManodopera"])) { $lotto["importoManodopera"] = number_format($lotto["importoManodopera"],2,$decimale,$migliaia); } |
|
if (!empty($lotto["oneriNoRibasso"])) { $lotto["oneriNoRibasso"] = number_format($lotto["oneriNoRibasso"],2,$decimale,$migliaia); } |
|
if (!empty($lotto["importoOpzioni"])) { $lotto["importoOpzioni"] = number_format($lotto["importoOpzioni"],2,$decimale,$migliaia); } |
|
$lotto["extraInfo"] = json_decode($lotto["extraInfo"],true); |
|
return $lotto; |
|
} |
|
|
|
public function getLotti($codice = null) |
|
{ |
|
$bind = [":codice_gara" => $this->info["codice"]]; |
|
$sql = "SELECT * FROM b_gare_lotti WHERE codice_gara = :codice_gara "; |
|
if ($codice !== null) { |
|
$bind[":codice"] = $codice; |
|
$sql .= " AND codice = :codice "; |
|
} |
|
return $this->db->go($sql . " ORDER BY numero", $bind)->fetchAll(PDO::FETCH_ASSOC); |
|
} |
|
|
|
public function getAsta($object = false) { |
|
if (!empty($this->lotto)) { |
|
$bind = [":codice_lotto"=>$this->lotto["codice"],":codice_round"=>$this->round["codice"]]; |
|
$sql = "SELECT * FROM b_gare_aste WHERE codice_lotto = :codice_lotto AND codice_round = :codice_round"; |
|
$asta = $this->db->go($sql, $bind)->fetch(PDO::FETCH_ASSOC); |
|
if (!empty($asta)) { |
|
if ($object) { |
|
$asta = new asta($this,$asta); |
|
} |
|
return $asta; |
|
} |
|
} |
|
} |
|
|
|
public function getCategorieMerceologiche() |
|
{ |
|
$codici_categoria = []; |
|
$sql_categoria = "SELECT codice FROM r_cpv_gare WHERE codice_gara = :codice "; |
|
$ris_custom = $this->db->go($sql_categoria, array(":codice" => $this->info["codice"])); |
|
if ($ris_custom->rowCount() > 0) { |
|
while ($categoria = $ris_custom->fetch(PDO::FETCH_ASSOC)) { |
|
if (!empty($categoria)) { |
|
$codici_categoria[] = $categoria["codice"]; |
|
} |
|
} |
|
} |
|
$codici_categoria = array_unique($codici_categoria); |
|
return $codici_categoria; |
|
} |
|
|
|
public static function getFormule() |
|
{ |
|
return tuttogareMath::getFormule(); |
|
} |
|
|
|
public static function initStatic() |
|
{ |
|
$gara = new self(); |
|
$gara->info = get_campi("b_gare"); |
|
return $gara; |
|
} |
|
|
|
public static function init($codice, $codice_round = NULL, $valutazione = NULL) |
|
{ |
|
if (! empty($codice) && (defined("__CMDS_JOB_EXEC") || (! empty($_SESSION["utente"]) && ! empty($_SESSION["ente"])))) { |
|
global $pdo; |
|
$bind = [":codice" => $codice]; |
|
$sql = "SELECT * FROM b_gare WHERE codice = :codice "; |
|
if (! defined("__CMDS_JOB_EXEC") && ! $_SESSION["utente"]->fromHere() && !isset($valutazione)) { |
|
$sql .= " AND codice_ente = :codice_ente"; |
|
$bind[":codice_ente"] = $_SESSION["utente"]->codice_ente; |
|
} |
|
$gara = $pdo->go($sql, $bind)->fetch(PDO::FETCH_ASSOC); |
|
if (! empty($gara)) { |
|
$continua = false; |
|
$commissario = false; |
|
if ($valutazione !== NULL) { |
|
$check = $pdo->go( |
|
"SELECT r_commissione.codice, b_commissioni.scadenza FROM r_commissione JOIN b_commissioni ON r_commissione.codice_commissione = b_commissioni.codice |
|
WHERE r_commissione.codice_utente = :codice_utente AND b_commissioni.codice_elemento = :codice_round |
|
AND b_commissioni.modulo = \"gare\" AND b_commissioni.tipologia = :tipologia ", |
|
[":codice_utente" => $_SESSION["utente"]->codice, ":codice_round" => $codice_round, ":tipologia" => "commissione"] |
|
); |
|
if ($check->rowCount() == 1) { |
|
$check = $check->fetch(PDO::FETCH_ASSOC); |
|
if (($valutazione == "commissione" && ($gara["stato"] == "21" || $gara["stato"] == "25") && strtotime($check["scadenza"]) > time())) { |
|
$continua = true; |
|
$commissario = true; |
|
} |
|
} |
|
} else { |
|
if (!defined("__CMDS_JOB_EXEC")) { |
|
$continua = $_SESSION["utente"]->permission("gare",$gara["codice"],"0",true); |
|
if ($continua) { |
|
if ($_SESSION["utente"]->gerarchia > 9 && $_SESSION["utente"]->codice_ente != $gara["codice_ente"] && $_SESSION["utente"]->codice_ente != $_SESSION["ente"]->codice) { |
|
$continua = false; |
|
} |
|
} |
|
} else { |
|
$continua = true; |
|
} |
|
} |
|
if ($continua) { |
|
$continua = false; |
|
$extensionClass= self::extensionExists(); |
|
if (!empty($extensionClass)) { |
|
$instance = new $extensionClass(); |
|
} else { |
|
$instance = new gara(); |
|
} |
|
$instance->info = $gara; |
|
$instance->commissario = $commissario; |
|
$instance->activeRound = false; |
|
$instance->quickAvailable = false; |
|
$instance->quickPanel = false; |
|
$instance->privata = false; |
|
$enteBeneficiario = Ente::getInfoFromID($gara["codice_ente"])[0] ?? null; |
|
if (isset($enteBeneficiario["soggettoPrivato"]) && $enteBeneficiario["soggettoPrivato"] == "S") { |
|
$instance->privata = true; |
|
} |
|
if ($instance->info["modalita"] == "extra" && $instance->getProcedura()["quick-extra"]) { |
|
$instance->quickAvailable = true; |
|
$instance->quickPanel = false; |
|
$quickPanel = $instance->getExtraInfo()["gara"]["quickPanel"] ?? null; |
|
if (isset($quickPanel) && $quickPanel == "S") { |
|
$instance->quickPanel = true; |
|
} |
|
} |
|
$rounds = $instance->getRounds(); |
|
$first = true; |
|
$timeRiferimentoNormativo = time(); |
|
if (!empty($rounds)) { |
|
foreach($rounds AS $round) { |
|
if ($first) { |
|
if (!empty($round["pubblicazione"])) { |
|
$timeRiferimentoNormativo = strtotime($round["pubblicazione"]); |
|
} |
|
$first = false; |
|
} |
|
if ($round["codice"] === $codice_round) { |
|
$instance->round = $round; |
|
} |
|
} |
|
if (empty($instance->round)) { |
|
$instance->round = $round; |
|
} |
|
$instance->round["infoFase"] = $instance->getProcedura()["fasi"][$instance->round["id"]] ?? []; |
|
} else { |
|
$instance->round = get_campi("b_gare_round"); |
|
$instance->round["numero"] = 1; |
|
} |
|
if ($instance->round["numero"] == $gara["fase_attiva"]) { |
|
$instance->activeRound = true; |
|
} |
|
if ($instance->round["numero"] < $gara["fase_attiva"]) { |
|
$instance->info["stato"] = 100; |
|
} |
|
if (isset($round) && $gara["stato"] == 20 && strtotime($round["scadenza"]) < time() && $instance->activeRound) { |
|
$instance->updateStato(21); |
|
} |
|
$extraInfo = $instance->getExtraInfo()["gara"] ?? null; |
|
if (!empty($extraInfo["normaRiferimento"]) && !empty(self::riferimentiNormativi()[$extraInfo["normaRiferimento"]])) { |
|
$instance->normaRiferimento = $extraInfo["normaRiferimento"]; |
|
} |
|
if (empty($instance->normaRiferimento)) { |
|
$instance->normaRiferimento = self::findRiferimentoNormativo($timeRiferimentoNormativo); |
|
} |
|
return $instance; |
|
} |
|
} |
|
} |
|
return false; |
|
} |
|
|
|
|
|
public static function findRiferimentoNormativo($time = null) { |
|
if (empty($time)) { |
|
return "2023-36"; |
|
} else { |
|
$versions = self::riferimentiNormativi(); |
|
if (!empty($versions)) { |
|
foreach($versions AS $key => $version) { |
|
$start = null; |
|
$end = null; |
|
if (!empty($version["inizio"])) { |
|
$start = strtotime($version["inizio"]); |
|
} |
|
if (!empty($version["fine"])) { |
|
$end = strtotime($version["fine"]); |
|
} |
|
if ((empty($start) || $start < $time) && (empty($end) || $end > $time)) { |
|
return $key; |
|
} |
|
} |
|
} |
|
} |
|
} |
|
|
|
public function getPublicExternalURL() { |
|
return "https://{$_SESSION["ente"]->getInfo()["dominio"]}/gare/dettaglio.php?codice={$this->info["codice"]}"; |
|
} |
|
|
|
public function getHubData() { |
|
if ($this->info["fase_attiva"] > 1 || $this->round['pubblica'] > 0) { |
|
|
|
$lotti = $this->getLotti(); |
|
$extraInfo = $this->getExtraInfo(); |
|
$return = [ |
|
'b_hub_centrale' => [ |
|
'codice_gestore'=> $_SESSION["ente"]->codice, |
|
'codice_ente'=> $this->info["codice_ente"], |
|
'codice_interno'=> $this->info["codice"], |
|
'stato'=> $this->info["stato"], |
|
'pubblica'=> $this->round["pubblica"], |
|
'invito'=> (!$this->round["infoFase"]["aperta"]) ? "S" : "N", |
|
'ambito'=> "gare", |
|
'lotti'=> count($lotti), |
|
'oggetto'=> $this->info["oggetto"], |
|
'url'=> $this->getPublicExternalURL(), |
|
'procedura'=> $this->info["procedura"], |
|
'tipologia'=> $this->info["tipologia"], |
|
'pubblicazione'=> mysql2datetime($this->round["pubblicazione"]), |
|
'scadenza'=> mysql2datetime($this->round["scadenza"]), |
|
'chiarimenti'=> mysql2datetime($this->round["chiarimenti"]), |
|
'apertura'=> mysql2datetime($this->round["apertura"]), |
|
'importo'=> $this->info["prezzoRiferimento"], |
|
'nuts'=> $extraInfo["gara"]["nuts"], |
|
] |
|
]; |
|
if (!empty($lotti)) { |
|
$return['b_hub_cig'] = []; |
|
$return['b_hub_cup'] = []; |
|
foreach($lotti AS $lotto) { |
|
if (!empty($lotto["cig"])) { |
|
$return['b_hub_cig'][] = [ |
|
'cig'=> $lotto["cig"], |
|
'oggetto'=> $lotto["oggetto"], |
|
'importo'=> $lotto["importoBase"] + $lotto["importoOpzioni"] + $lotto["importoManodopera"] + $lotto["oneriNoRibasso"], |
|
'criterio'=> $lotto["criterio"] |
|
]; |
|
} |
|
if (!empty($lotto["cup"])) { |
|
$return['b_hub_cup'][] = [ |
|
'cup'=> $lotto["cup"], |
|
]; |
|
} |
|
} |
|
} |
|
|
|
$cpv = $this->getCategorieMerceologiche(); |
|
if (!empty($cpv)) { |
|
$return['r_hub_cpv'] = []; |
|
foreach($cpv AS $categoria) { |
|
$return['r_hub_cpv'][] = [ |
|
'codice' => $categoria, |
|
]; |
|
} |
|
} |
|
|
|
$soa = $this->getSOA(); |
|
if (!empty($soa)) { |
|
$return['r_hub_soa'] = []; |
|
foreach($soa AS $categoria) { |
|
$return['r_hub_soa'][] = [ |
|
'codice_categoria' => $categoria["codice_categoria"], |
|
]; |
|
} |
|
} |
|
return $return; |
|
} |
|
} |
|
|
|
public function getProcedura() |
|
{ |
|
$return = getProcedure(true, null, $this->info["timestamp_creazione"])[$this->info["procedura"]]; |
|
if ($this->info["accordo_quadro"] == "S") { |
|
$return["aggiudicazioneMultipla"] = true; |
|
} |
|
$return["key"] = $this->info["procedura"]; |
|
return $return; |
|
} |
|
|
|
public function getModalita() { |
|
return getModalita()[$this->info["modalita"]]; |
|
} |
|
|
|
public function getTotaleImporti() { |
|
$totale = self::getTotaleImportiFromTipologie($this->getExtraInfo()["gara"]["importi"]); |
|
return $totale; |
|
} |
|
public static function getTotaleImportiFromTipologie($tipologie) |
|
{ |
|
$totale = 0; |
|
foreach ($tipologie as $importo) { |
|
$totale += $importo; |
|
} |
|
return $totale; |
|
} |
|
|
|
public function getInterpretazioneArt41() : String { |
|
$return = ""; |
|
if ($this->normaRiferimento == "2023-36") { |
|
$return = settingsManager::getValue("interpretazioneArt41"); |
|
if ($return == "chiedi") { |
|
$return = $this->getExtraInfo()["gara"]["interpretazioneArt41"] ?? "complessivo"; |
|
} |
|
} |
|
return $return; |
|
} |
|
|
|
public function updateBadges() |
|
{ |
|
$badge = 0; |
|
$sql_bad = "SELECT b_gare_chiarimenti.codice |
|
FROM b_gare_chiarimenti JOIN b_gare_round ON b_gare_chiarimenti.codice_round = b_gare_round.codice |
|
JOIN b_gare ON b_gare_round.codice_gara = b_gare.codice |
|
WHERE b_gare_round.scadenza >= now() |
|
AND b_gare_chiarimenti.attivo = 'N' |
|
AND b_gare.codice = :codice "; |
|
|
|
$ris_badge = $this->db->go($sql_bad, [":codice" => $this->info["codice"]]); |
|
$badge += $ris_badge->rowCount(); |
|
|
|
$sql_bad = "SELECT b_gare_sopralluogo.codice |
|
FROM b_gare_sopralluogo JOIN b_gare_round ON b_gare_sopralluogo.codice_round = b_gare_round.codice |
|
JOIN b_gare ON b_gare_round.codice_gara = b_gare.codice |
|
WHERE b_gare_round.scadenza >= now() |
|
AND b_gare_sopralluogo.attivo = 'P' |
|
AND b_gare.codice = :codice "; |
|
|
|
$ris_badge = $this->db->go($sql_bad, [":codice" => $this->info["codice"]]); |
|
$badge += $ris_badge->rowCount(); |
|
|
|
$this->db->go("UPDATE b_gare SET badge = :badge WHERE codice = :codice", [":badge" => $badge, ":codice" => $this->info["codice"]]); |
|
} |
|
|
|
public function printOfferEconomica($edit = true, $bozza = true, $data = false) |
|
{ |
|
if (!empty($this->lotto)) { |
|
$model = new editorManager("economica-gare", "gare-preview-" . $this->round["codice"]); |
|
if (!empty($model)) { |
|
$criteriEconomici = $this->getCriteriEconomici(); |
|
if (!empty($criteriEconomici)) { |
|
$inputs = []; |
|
$first = true; |
|
global $beRoot; |
|
$receveidData = $data; |
|
if (!empty($data) && is_numeric($data)) { |
|
$dettagli = $this->db->prepare("SELECT offerta,codice_partecipante FROM b_dettaglio_offerte_gare WHERE codice_offerta = :codice_offerta AND codice_dettaglio = :codice_dettaglio AND offerta IS NOT NULL"); |
|
$dettagli->bindValue(":codice_offerta", $data); |
|
} |
|
foreach($criteriEconomici AS $criterio) { |
|
if (!empty($criterio["auto"])) { |
|
ob_start(); |
|
if ($criterio["tipologia"] != "E") { |
|
$this->printOfferCriterio($criterio["codice"],$edit,$bozza,$data); |
|
} else { |
|
$elencoPrezzi = $this->getElencoPrezzi($criterio["codice"]); |
|
if (!empty($elencoPrezzi)) { |
|
ob_start(); |
|
include($beRoot . "/common/criteri/inputs/ep-input.php"); |
|
$inputs[] = ob_get_clean(); |
|
} else { |
|
alertManager::printAlertBox($criterio["denominazione"],__("Errore configurazione")); |
|
} |
|
} |
|
$inputs[] = ob_get_clean(); |
|
if ($first) { |
|
$parentCriteria = $criterio; |
|
$first = false; |
|
} |
|
} |
|
} |
|
if (!empty($parentCriteria)) { |
|
$model->vocabolario["gare"] = $this->info; |
|
$model->vocabolario["fase"] = $this->round; |
|
$formattedLotto = self::formatLotto($this->lotto,true); |
|
$model->vocabolario["lotto"] = $formattedLotto; |
|
if ($this->normaRiferimento == "2016-50") { |
|
$importi = __("Prezzo a base") . ": € " . $formattedLotto["importoBase"]; |
|
if ($this->lotto["importoManodopera"] > 0) { |
|
$importi .= " " . strtolower(__("di cui")) . " € " . $formattedLotto["importoManodopera"] . " " . strtolower(__("per costi della manodopera")); |
|
} |
|
$importi .= "<br>" . __("oneri per la sicurezza") . ": € " . $formattedLotto["oneriNoRibasso"]; |
|
} else if ($this->normaRiferimento == "2023-36") { |
|
if ($this->getInterpretazioneArt41() === "complessivo") { |
|
$importi = "Importo posto a base di gara: € " . $formattedLotto["importoRibassabile"]. ": <ul>"; |
|
$importi .= "<li>" . __(getTipologieAffidamento(false, $this->info["timestamp_creazione"])[$this->info["tipologia"]]["titolo"]) . ": € " . $formattedLotto["importoBase"] . "</li>"; |
|
if ($this->lotto["importoManodopera"] > 0) { |
|
$importi .= "<li>" . __("Costi della manodopera") . " € " . $formattedLotto["importoManodopera"] . "</li>"; |
|
} |
|
$importi .= "</ul>"; |
|
$importi .= __("oneri per la sicurezza") . ": € " . $formattedLotto["oneriNoRibasso"]; |
|
} else { |
|
$importi = "<ul>"; |
|
$importi .= "<li>" . __(getTipologieAffidamento(false, $this->info["timestamp_creazione"])[$this->info["tipologia"]]["titolo"]) . ": € " . $formattedLotto["importoBase"] . "</li>"; |
|
if ($this->lotto["importoManodopera"] > 0) { |
|
$importi .= "<li>" . __("Costi della manodopera") . " € " . $formattedLotto["importoManodopera"] . "</li>"; |
|
} |
|
$importi .= "<li>" . __("oneri per la sicurezza") . ": € " . $formattedLotto["oneriNoRibasso"] . "</li>"; |
|
$importi .= "</ul>"; |
|
} |
|
} |
|
$model->vocabolario["lotto"]["importi"] = $importi; |
|
if (!empty($receveidData) && is_numeric($receveidData)) { |
|
$dettagli->bindValue(":codice_dettaglio", $parentCriteria["codice"] . ".01"); |
|
$dettagli->execute(); |
|
if ($dettagli->rowCount() > 0) { |
|
$det = $dettagli->fetch(PDO::FETCH_ASSOC); |
|
$partecipante = $this->getPartecipante($det["codice_partecipante"]); |
|
$list_partecipanti = $this->listPartecipanti($partecipante["codice"]); |
|
$valore_sicurezza = $det["offerta"]; |
|
} |
|
$dettagli->bindValue(":codice_dettaglio", $parentCriteria["codice"] . ".02"); |
|
$dettagli->execute(); |
|
if ($dettagli->rowCount() > 0) { |
|
$valore_manodopera = $dettagli->fetch(PDO::FETCH_ASSOC)["offerta"]; |
|
} |
|
|
|
$data = []; |
|
$tmpCriterio["codice"] = $parentCriteria["codice"] . ".01"; |
|
$data[$tmpCriterio["codice"]] = $valore_sicurezza ?? ""; |
|
$tmpCriterio["codice"] = $parentCriteria["codice"] . ".02"; |
|
$data[$tmpCriterio["codice"]] = $valore_manodopera ?? ""; |
|
$data["partecipanti"] = $list_partecipanti; |
|
} |
|
|
|
$criterio = []; |
|
$criterio["denominazione"] = "ONERI SICUREZZA AZIENDALE"; |
|
$criterio["descrizione"] = "(esprimere il valore in cifre al netto di IVA)"; |
|
$criterio["codice"] = $parentCriteria["codice"] . ".01"; |
|
$criterio["decimali"] = $parentCriteria["decimali"]; |
|
$criterio["auto"] = ""; |
|
$criterio["vincoli"] = ""; |
|
ob_start(); |
|
include($beRoot . "/common/criteri/inputs/offer-input.php"); |
|
$inputs[] = ob_get_clean(); |
|
|
|
$criterio = []; |
|
$criterio["denominazione"] = "COSTO DELLA MANODOPERA"; |
|
$criterio["descrizione"] = "(esprimere il valore in cifre al netto di IVA)"; |
|
$criterio["codice"] = $parentCriteria["codice"] . ".02"; |
|
$criterio["decimali"] = $parentCriteria["decimali"]; |
|
$criterio["auto"] = ""; |
|
$criterio["vincoli"] = ""; |
|
ob_start(); |
|
include($beRoot . "/common/criteri/inputs/offer-input.php"); |
|
$inputs[] = ob_get_clean(); |
|
|
|
if (isset($data["partecipanti"])) { |
|
$model->vocabolario["partecipanti"] = $data["partecipanti"]; |
|
} |
|
} |
|
if (!empty($inputs)) { |
|
$inputs = implode("",$inputs); |
|
} |
|
} |
|
$criteriTecnici = $this->getCriteriTecnici(); |
|
if (!empty($criteriTecnici)) { |
|
if (!empty($receveidData)) { |
|
$data = $receveidData; |
|
} |
|
$inputsTecnici = []; |
|
foreach($criteriTecnici AS $criterio) { |
|
if (!empty($criterio["auto"]) && $criterio["busta"] == "economica") { |
|
ob_start(); |
|
$this->printOfferCriterio($criterio["codice"],$edit,$bozza,$data); |
|
$inputsTecnici[] = ob_get_clean(); |
|
} |
|
} |
|
if (!empty($inputsTecnici)) { |
|
$inputsTecnici = "<br><br><h2>" . __("ELEMENTI NON ECONOMICI DELL'OFFERTA") . "</h2><br><br>" . implode("",$inputsTecnici); |
|
if (empty($inputs)) { |
|
$inputs = $inputsTecnici; |
|
} else { |
|
$inputs .= $inputsTecnici; |
|
} |
|
} |
|
} |
|
if (!empty($inputs)) { |
|
$model->vocabolario["inputs"] = $inputs; |
|
$model = $model->getModello(); |
|
echo $model; |
|
} |
|
} |
|
} |
|
} |
|
|
|
public function printOfferCriterio($codice_criterio, $edit = true, $bozza = true, $data = false,$annotazioni = null) |
|
{ |
|
$criterio = $this->getCriteri($codice_criterio)[0]; |
|
$criterio["vincoli"] = ""; |
|
if (!empty($criterio["auto"])) { |
|
if (!empty($data) && is_numeric($data)) { |
|
$dettagli = $this->db->prepare("SELECT offerta FROM b_dettaglio_offerte_gare WHERE codice_offerta = :codice_offerta AND codice_dettaglio = :codice_dettaglio AND offerta IS NOT NULL"); |
|
$dettagli->bindValue(":codice_offerta", $data); |
|
} |
|
global $beRoot; |
|
include($beRoot . "/common/criteri/inputs/offer-input.php"); |
|
} |
|
} |
|
|
|
public function printFormCriterio($codice_criterio, $edit = true, $bozza = true, $data = 0) |
|
{ |
|
$criterio = $this->getCriteri($codice_criterio)[0]; |
|
$form = $this->getFormCriterio($codice_criterio); |
|
if (!empty($form)) { |
|
$attachID = "gare-form"; |
|
$dataSql = "SELECT codice, content FROM b_gare_form_data WHERE codice_input = :input AND codice_offerta = :offerta "; |
|
$viewFormAttachPath = "/backend/gare/open/viewFormAttachment.php"; |
|
global $beRoot; |
|
include($beRoot . "/common/criteri/inputs/form-input.php"); |
|
} |
|
} |
|
|
|
public function getLottiFromCriterio($codice_criterio) { |
|
if (!empty($this->getCriteri($codice_criterio))) { |
|
return $this->db->go("SELECT codice_lotto FROM r_gare_criteri_lotti WHERE codice_criterio = :criterio",[":criterio"=>$codice_criterio])->fetchAll(PDO::FETCH_COLUMN); |
|
} |
|
} |
|
|
|
public function getLottiFromRichiesta($codice_richiesta) { |
|
if (!empty($this->getRichiesta($codice_richiesta))) { |
|
return $this->db->go("SELECT codice_lotto FROM r_gare_richieste_lotti WHERE codice_richiesta = :richiesta",[":richiesta"=>$codice_richiesta])->fetchAll(PDO::FETCH_COLUMN); |
|
} |
|
} |
|
|
|
public function getCriteriEconomici() |
|
{ |
|
return $this->returnCriteri($this->round["codice"], ["economico" => "S"]); |
|
} |
|
|
|
public function getCriteriTecnici() |
|
{ |
|
return $this->returnCriteri($this->round["codice"], ["economico" => "N"]); |
|
} |
|
|
|
public function getCriteriValutabili($codice_criterio = NULL) |
|
{ |
|
$tmpCriteri = $this->getCriteri($codice_criterio); |
|
$criteri = []; |
|
if (count($tmpCriteri) > 0) { |
|
foreach ($tmpCriteri as $criterio) { |
|
if (empty($this->getSubCriteri($criterio["codice"]))) { |
|
$criteri[] = $criterio; |
|
} |
|
} |
|
} |
|
return $criteri; |
|
} |
|
|
|
public function getCriteriTecniciValutabili() |
|
{ |
|
$tmp = $this->getCriteriValutabili(); |
|
$criteri = []; |
|
foreach ($tmp as $criterio) { |
|
if ($criterio["economico"] == "N") { |
|
$criteri[] = $criterio; |
|
} |
|
} |
|
return $criteri; |
|
} |
|
|
|
public function getCriteriEconomiciValutabili() |
|
{ |
|
$tmp = $this->getCriteriValutabili(); |
|
$criteri = []; |
|
foreach ($tmp as $criterio) { |
|
if ($criterio["economico"] == "S") { |
|
$criteri[] = $criterio; |
|
} |
|
} |
|
return $criteri; |
|
} |
|
|
|
public function returnCriteri($codice_round, $filters = []) |
|
{ |
|
if (!empty($this->getRounds($codice_round))) { |
|
$bind = [":codice_round" => $codice_round]; |
|
$keysFilters = array_keys(get_campi("b_gare_criteri_valutazione")); |
|
$sql = "SELECT b_gare_criteri_valutazione.* FROM b_gare_criteri_valutazione "; |
|
if (!empty($this->lotto) && empty($filters["ignore-lotto"])) { |
|
$sql .= " JOIN r_gare_criteri_lotti ON b_gare_criteri_valutazione.codice = r_gare_criteri_lotti.codice_criterio "; |
|
} |
|
|
|
$sql .= " WHERE b_gare_criteri_valutazione.codice_round = :codice_round "; |
|
if (!empty($this->lotto) && empty($filters["ignore-lotto"])) { |
|
$sql .= " AND (r_gare_criteri_lotti.codice_lotto = 0 OR r_gare_criteri_lotti.codice_lotto = :lotto ) "; |
|
if ($this->lotto["criterio"] == "prezzo") { |
|
$sql .= " AND b_gare_criteri_valutazione.economico = 'S' "; |
|
} |
|
$bind[":lotto"] = $this->lotto["codice"]; |
|
} |
|
foreach ($filters as $key => $value) { |
|
if (in_array($key, $keysFilters, true) !== false) { |
|
$bind[":{$key}"] = $value; |
|
$sql .= " AND b_gare_criteri_valutazione.{$key} = :{$key} "; |
|
} else { |
|
if ($key != "ignore-lotto") { |
|
return null; |
|
} |
|
} |
|
} |
|
$sql .= " GROUP BY b_gare_criteri_valutazione.codice ORDER BY b_gare_criteri_valutazione.ordinamento, b_gare_criteri_valutazione.codice "; |
|
return $this->db->go($sql, $bind)->fetchAll(PDO::FETCH_ASSOC); |
|
} |
|
} |
|
|
|
public function getElencoPrezzi($codice_criterio) { |
|
return $this->db->go("SELECT * FROM b_gare_ep WHERE codice_criterio = :criterio ORDER BY ordinamento,codice",[":criterio"=>$codice_criterio])->fetchAll(PDO::FETCH_ASSOC); |
|
} |
|
|
|
public function printCriteriaTable() |
|
{ |
|
$criteri = $this->getMacroCriteri(); |
|
if (!empty($criteri)) { |
|
global $beRoot; |
|
include($beRoot . "/common/criteri/model-table.php"); |
|
} |
|
} |
|
|
|
public function getDestinatariInterni(bool $onlyCode = false) { |
|
return $this->getManagerRegistro()->getUtentiCoinvoltiConRuolo("USR",$onlyCode); |
|
} |
|
|
|
public function chooseLotto($input,$target,$stati = []) { |
|
$lotti = $this->getLotti(); |
|
if (!empty($lotti)) { |
|
if (count($lotti) > 1) { |
|
if (!empty($input)) { |
|
$setLotto = $input; |
|
} |
|
} else { |
|
$setLotto = $lotti[0]["codice"]; |
|
} |
|
if (!empty($setLotto)) { |
|
if ($this->setLotto($setLotto)) { |
|
return true; |
|
} |
|
} else { |
|
$this->printSelectLotto($target,false,$stati); |
|
return false; |
|
} |
|
} |
|
return false; |
|
} |
|
|
|
public function printSelectLotto($target,$allOption = false,$stati = []) { |
|
include(__DIR__."/lotti/selectView.php"); |
|
} |
|
|
|
public function valutaStatoGenerale(?bool $force = false) { |
|
$lotti = $this->getLotti(); |
|
$stati = []; |
|
$lottiCompleti = 0; |
|
foreach($lotti AS $lotto) { |
|
//if ($lotto["stato"] > 0) { |
|
if (in_array($lotto["stato"],self::statiTermineProcedura())) { |
|
$lottiCompleti++; |
|
} |
|
$stati[] = $lotto["stato"]; |
|
//} |
|
} |
|
|
|
if (!empty($stati) && count($stati) == count($lotti)) { |
|
$stati = array_unique($stati); |
|
if (count($stati) === 1) { |
|
$this->updateStato($stati[0],$force); |
|
} else { |
|
$stato = 25; |
|
if (count($lotti) == $lottiCompleti) { |
|
$stato = 100; |
|
} |
|
$this->updateStato($stato,$force); |
|
} |
|
} |
|
} |
|
public static function ruoloAvvalimento(int $index) { |
|
return ["Requisito", "Miglioramento d'offerta"][$index-1] ?? "SCONOSCIUTO"; |
|
} |
|
public function savePartecipante($partecipante) { |
|
if (!empty($partecipante["codice"]) || !$this->getModalita()["online"]) { |
|
$continua = false; |
|
if (!empty($partecipante["codice"])) { |
|
if (!empty($this->getPartecipante($partecipante["codice"],true))) { |
|
$continua = true; |
|
unset($partecipante["codice_operatore"]); |
|
} |
|
} else { |
|
if (!isset($partecipante["codice_operatore"])) { |
|
$partecipante["codice_operatore"] = 0; |
|
} |
|
$partecipante["conferma"] = "S"; |
|
$continua = true; |
|
} |
|
if ($continua) { |
|
$partecipante["ruolo"] = (!empty($partecipante["raggruppamento"])) ? "04-CAPOGRUPPO" : ""; |
|
$partecipante["codice_lotto"] = $this->lotto["codice"]; |
|
$partecipante["codice_round"] = $this->round["codice"]; |
|
$salva = new salva(); |
|
$salva->debug = false; |
|
|
|
$salva->nome_tabella = "r_partecipanti_gare"; |
|
$salva->operazione = empty($partecipante["codice"]) ? "INSERT" : "UPDATE"; |
|
|
|
$salva->oggetto = $partecipante; |
|
if($salva->operazione === "INSERT") { |
|
$salva->oggetto["uuid"] = uuidgen_v4(); |
|
} |
|
$codice = $salva->save(); |
|
if ($codice > 0) { |
|
$this->db->go("DELETE FROM r_raggruppamenti_gare WHERE codice_padre = :codice",[":codice"=>$codice]); |
|
if (!empty($partecipante["raggruppamento"])) { |
|
foreach($partecipante["raggruppamento"] as $sub) { |
|
$sub["codice_padre"] = $codice; |
|
$salva = new salva(); |
|
$salva->debug = false; |
|
|
|
$salva->nome_tabella = "r_raggruppamenti_gare"; |
|
$salva->operazione = "INSERT"; |
|
$salva->oggetto = $sub; |
|
$salva->save(); |
|
} |
|
} |
|
$this->db->go("DELETE FROM r_avvalimenti_gare WHERE codice_padre = :codice",[":codice"=>$codice]); |
|
if (!empty($partecipante["avvalimento"])) { |
|
foreach($partecipante["avvalimento"] as $sub) { |
|
if(empty($sub["identifier_raggruppamento"]) || $sub["identifier_raggruppamento"] === "PARENT") { |
|
$sub["identifier_raggruppamento"] = null; |
|
} |
|
$sub["codice_padre"] = $codice; |
|
$salva = new salva(); |
|
$salva->debug = false; |
|
|
|
$salva->nome_tabella = "r_avvalimenti_gare"; |
|
$salva->operazione = "INSERT"; |
|
$salva->oggetto = $sub; |
|
$salva->save(); |
|
} |
|
} |
|
$this->addToLog(empty($partecipante["codice"]) ? "INSERT" : "UPDATE",__("Partecipante") . " #" . $codice); |
|
return $codice; |
|
} |
|
} |
|
return false; |
|
} |
|
} |
|
|
|
public function saveCriterio($criterio) { |
|
if (!empty($this->round)) { |
|
$continua = true; |
|
if (!empty($criterio["codice_padre"])) { |
|
$check = $this->getCriteri($criterio["codice_padre"]); |
|
if (!empty($check)) { |
|
$check = $check[0]; |
|
if (!empty($check["auto"])) { |
|
$continua = false; |
|
} else { |
|
$form = $this->getFormCriterio($check["codice"]); |
|
if (!empty($form)) { |
|
$continua = false; |
|
} |
|
} |
|
} |
|
} |
|
if ($continua) { |
|
$criterio["codice_round"] = $this->round["codice"]; |
|
if ($criterio["tipologia"] == "Q") { |
|
$criterio["auto"] = ""; |
|
$criterio["options"] = ""; |
|
} else { |
|
if (isset($criterio["auto"]) && !empty(($criterio["options"][$criterio["auto"]]))) { |
|
$criterio["options"] = json_encode($criterio["options"][$criterio["auto"]]); |
|
} else { |
|
$criterio["options"] = ""; |
|
} |
|
} |
|
if ($criterio["economico"] == "S") { |
|
$criterio["busta"] = "economica"; |
|
} |
|
$operazione = (is_numeric($criterio["codice"])) ? "UPDATE" : "INSERT"; |
|
$salva = new salva(); |
|
$salva->debug = false; |
|
$salva->nome_tabella = "b_gare_criteri_valutazione"; |
|
$salva->operazione = $operazione; |
|
$salva->ignore = ["timestamp_modifica"]; |
|
$salva->oggetto = $criterio; |
|
$codice = $salva->save(); |
|
if ($codice !== false) { |
|
if ($operazione == "INSERT") { |
|
$this->bindCriterio($codice); |
|
} |
|
if ($criterio["tipologia"] != "Q") { |
|
$this->db->go("DELETE FROM b_gare_form WHERE codice_criterio = :codice",[":codice"=>$codice]); |
|
scriviLog("b_gare_form","DELETE",$this->db->getSQL(),$codice); |
|
} |
|
$subCriteri = $this->getSubCriteri($codice); |
|
if (!empty($subCriteri)) { |
|
foreach($subCriteri AS $sub) { |
|
$salva = new salva(); |
|
$salva->debug = false; |
|
$salva->nome_tabella = "b_gare_criteri_valutazione"; |
|
$salva->operazione = "UPDATE"; |
|
$salva->oggetto = [ |
|
"codice" => $sub["codice"], |
|
"decimali" => $criterio["decimali"], |
|
"economico" => $criterio["economico"], |
|
"tipologia" => $criterio["tipologia"], |
|
]; |
|
$salva->save(); |
|
} |
|
} |
|
$this->checkRichiesteOnEditCriteri(); |
|
return $codice; |
|
} |
|
} |
|
} |
|
return false; |
|
} |
|
|
|
public function deleteCriterio(Int $codice) { |
|
$lock = $this->checkLock("criteri"); |
|
if (!$lock) { |
|
if (!empty($this->getCriteri($codice))) { |
|
$bind = array(":codice"=>$codice); |
|
$sql = "DELETE FROM b_gare_criteri_valutazione WHERE codice_padre = :codice "; |
|
$ris = $this->db->go($sql,$bind); |
|
$sql = "DELETE FROM b_gare_criteri_valutazione WHERE codice = :codice "; |
|
$ris = $this->db->go($sql,$bind); |
|
if ($ris->rowCount() === 1) { |
|
scriviLog("b_gare_criteri_valutazione","DELETE",$this->db->getSQL(),$codice); |
|
$error = false; |
|
$this->addToLog("DELETE",__("Criterio") . "#" . $codice); |
|
$this->checkRichiesteOnEditCriteri(); |
|
return true; |
|
} |
|
} |
|
} |
|
return false; |
|
} |
|
|
|
public function bindCriterio($criterio,$lotti = 0) { |
|
$this->db->go("DELETE FROM r_gare_criteri_lotti WHERE codice_criterio = :codice",[":codice"=>$criterio]); |
|
$insert = $this->db->prepare("INSERT INTO r_gare_criteri_lotti (codice_criterio,codice_lotto) VALUES (:criterio,:lotto)"); |
|
$insert->bindValue(":criterio",$criterio); |
|
$return = true; |
|
if (is_array($lotti)) { |
|
$ok = 0; |
|
foreach($lotti AS $lotto) { |
|
$insert->bindValue(":lotto",$lotto); |
|
$insert->execute(); |
|
if ($insert->rowCount() === 1) { |
|
$ok++; |
|
} |
|
} |
|
if (count($lotti) != $ok) { |
|
$return = false; |
|
} |
|
} else { |
|
$insert->bindValue(":lotto",0); |
|
$insert->execute(); |
|
if ($insert->rowCount() !== 1) { |
|
$return = false; |
|
} |
|
} |
|
if ($return) { |
|
$sub = $this->getSubCriteri($criterio); |
|
if (!empty($sub)) { |
|
foreach($sub AS $c) { |
|
$this->bindCriterio($c["codice"],$lotti); |
|
} |
|
} |
|
} |
|
$this->checkRichiesteOnEditCriteri(); |
|
return $return; |
|
} |
|
|
|
public function saveVociEP($criterio,$voci) { |
|
$codici = []; |
|
$error_input = ""; |
|
$salva = new salva(); |
|
$salva->debug = false; |
|
|
|
$salva->nome_tabella = "b_gare_ep"; |
|
$ordinamento = 0; |
|
if (!empty($voci)) { |
|
foreach($voci AS $codice_input => $input) { |
|
if (is_numeric($codice_input)) { $input["codice"] = $codice_input; } |
|
if (empty($input["ordinamento"]) && !is_numeric($codice_input)) { |
|
$input["ordinamento"] = $ordinamento; |
|
} |
|
$input["codice_criterio"] = $criterio; |
|
$salva->operazione = (is_numeric($codice_input)) ? "UPDATE" : "INSERT"; |
|
$salva->oggetto = $input; |
|
$cod_input = $salva->save(); |
|
$codici[] = $cod_input; |
|
if (empty($cod_input)) { |
|
$error_input .= "<br>Error: " . $input["titolo"]; |
|
} |
|
$ordinamento++; |
|
} |
|
} |
|
if (empty($error_input)) { |
|
$codici = implode(",",$codici); |
|
$this->db->go("DELETE FROM b_gare_ep WHERE codice_criterio = :criterio AND codice NOT IN (".$codici.")",[":criterio"=>$criterio]); |
|
$this->addToLog("UPDATE",__("Elenco prezzi") . " - " . __("Criterio") . " #" . $criterio); |
|
} |
|
$this->checkRichiesteOnEditCriteri(); |
|
return $error_input; |
|
} |
|
|
|
public function saveRichiesta($richiesta) { |
|
if (!empty($this->busteDisponibili($richiesta["busta"]))) { |
|
if (empty($richiesta["codice"])) { |
|
$richiesta["ordinamento"] = count($this->getRichieste($richiesta["busta"])); |
|
} |
|
$richiesta["codice_round"] = $this->round["codice"]; |
|
$salva = new salva(); |
|
$salva->debug = false; |
|
|
|
$salva->nome_tabella = "b_gare_richieste"; |
|
$salva->operazione = (!empty($richiesta["codice"])) ? "UPDATE" : "INSERT"; |
|
$salva->oggetto = $richiesta; |
|
$codice = $salva->save(); |
|
if (!empty($codice)) { |
|
if (empty($richiesta["codice"])) { |
|
$this->bindRichiesta($codice); |
|
} |
|
if (isset($richiesta["allegato-public"])) { |
|
foreach($richiesta["allegato-public"] as $allegato) { |
|
filesManager::saveFile($allegato["filename"],$codice,"gare-richiesta",$allegato["nome"] ?? "","A",$allegato["classificazione"] ?? ""); |
|
} |
|
} |
|
$this->addToLog($salva->operazione,__("Richiesta").": " . $richiesta["titolo"]); |
|
return $codice; |
|
} |
|
} |
|
return false; |
|
} |
|
|
|
public function deleteRichiesta($richiesta) { |
|
$richiesta = $this->getRichiesta($richiesta); |
|
if (!empty($richiesta) && $richiesta["locked"] == "N") { |
|
$sql = "DELETE FROM b_gare_richieste WHERE codice = :codice "; |
|
$ris = $this->db->go($sql,[":codice"=>$richiesta["codice"]]); |
|
if ($ris->rowCount() === 1) { |
|
scriviLog("b_gare_richieste","DELETE",$this->db->getSQL(),$richiesta["codice"]); |
|
$this->addToLog("DELETE",__("Richiesta").": " . $richiesta["titolo"]); |
|
return true; |
|
} |
|
} |
|
return false; |
|
} |
|
|
|
public function bindRichiesta($richiesta,$lotti = 0) { |
|
$this->db->go("DELETE FROM r_gare_richieste_lotti WHERE codice_richiesta = :codice",[":codice"=>$richiesta]); |
|
$check = $this->db->prepare("SELECT codice FROM r_gare_richieste_lotti WHERE codice_richiesta = :richiesta AND (codice_lotto = :lotto OR codice_lotto = 0)"); |
|
$insert = $this->db->prepare("INSERT INTO r_gare_richieste_lotti (codice_richiesta,codice_lotto) VALUES (:richiesta,:lotto)"); |
|
$insert->bindValue(":richiesta",$richiesta); |
|
$check->bindValue(":richiesta",$richiesta); |
|
if (is_array($lotti)) { |
|
$ok = 0; |
|
foreach($lotti AS $lotto) { |
|
$insert->bindValue(":lotto",$lotto); |
|
$check->bindValue(":lotto",$lotto); |
|
$check->execute(); |
|
if ($check->rowCount() === 0) { |
|
$insert->execute(); |
|
if ($insert->rowCount() === 1) { |
|
$ok++; |
|
} |
|
} else { |
|
$ok++; |
|
} |
|
} |
|
if (count($lotti) == $ok) { |
|
return true; |
|
} |
|
} else { |
|
$insert->bindValue(":lotto",0); |
|
$check->bindValue(":lotto",0); |
|
$check->execute(); |
|
if ($check->rowCount() === 0) { |
|
$insert->execute(); |
|
if ($insert->rowCount() === 1) { |
|
return true; |
|
} |
|
} else { |
|
return true; |
|
} |
|
} |
|
return false; |
|
} |
|
|
|
public function checkRichiesteOnEditCriteri() |
|
{ |
|
if ($this->getModalita()["online"]) { |
|
$lottoSelezionato = $this->lotto; |
|
$this->lotto = null; |
|
$criteri = $this->getAllCriteri(); |
|
$binds = []; |
|
$tipologie = self::tipologieBusta(); |
|
$tipologie = array_keys($tipologie); |
|
$allLotti = $this->getLotti(); |
|
if (!empty($criteri)) { |
|
foreach ($criteri as $criterio) { |
|
$sub = $this->getSubCriteri($criterio["codice"]); |
|
if (empty($sub)) { |
|
$type = null; |
|
$lotti = $this->getLottiFromCriterio($criterio["codice"]); |
|
if (!empty($lotti)) { |
|
if (!empty($criterio["auto"])) { |
|
if ($criterio["economico"] == "S" || $criterio["busta"] == "economica") { |
|
$type = "economica"; |
|
} else if ($criterio["economico"] == "N") { |
|
$type = "tecnica"; |
|
} |
|
} else if ($criterio["tipologia"] == "Q" && !empty($this->getFormCriterio($criterio["codice"]))) { |
|
$type = "tecnica"; |
|
} |
|
if (!empty($type)) { |
|
if (!isset($binds[$type])) { |
|
$binds[$type] = []; |
|
} |
|
$binds[$type] = array_merge($binds[$type],$lotti); |
|
} |
|
} |
|
} |
|
} |
|
} |
|
foreach ($tipologie as $busta) { |
|
$bind = []; |
|
$bind[":codice_round"] = $this->round["codice"]; |
|
$bind[":busta"] = $busta; |
|
if (isset($binds[$busta])) { |
|
$check = $this->db->go("SELECT codice FROM b_gare_richieste WHERE codice_round = :codice_round AND busta = :busta AND locked = 'S'", $bind); |
|
if ($check->rowCount() == 0) { |
|
$richiesta = []; |
|
$richiesta["codice_round"] = $this->round["codice"]; |
|
$richiesta["busta"] = $busta; |
|
$richiesta["titolo"] = __("Offerta {$busta}"); |
|
$richiesta["descrizione"] = __("Caricare il file generato dal sistema in merito alla compilazione dell'offerta {$busta}"); |
|
$richiesta["controllo"] = "F"; |
|
$richiesta["ordinamento"] = 0; |
|
$richiesta["locked"] = "S"; |
|
$codiceRichiesta = $this->saveRichiesta($richiesta); |
|
} else { |
|
$codiceRichiesta = $check->fetch(PDO::FETCH_COLUMN); |
|
} |
|
if (count($binds[$busta]) == count($allLotti)) { |
|
$lotti = 0; |
|
} else { |
|
$lotti = $binds[$busta]; |
|
} |
|
$this->bindRichiesta($codiceRichiesta,$lotti); |
|
} else { |
|
$this->db->go("DELETE FROM b_gare_richieste WHERE busta = :busta AND locked = 'S' AND codice_round = :codice_round",[":busta"=>$busta,":codice_round"=>$this->round["codice"]]); |
|
scriviLog("b_gare_richieste", "DELETE", $this->db->getSQL()); |
|
} |
|
} |
|
$this->lotto = $lottoSelezionato; |
|
} |
|
} |
|
public function getCPVLotto(int $codice_lotto) : ?string |
|
{ |
|
$res = $this->db->go( |
|
"SELECT cpv FROM b_gare_lotti WHERE codice_gara = :codice AND codice = :codice_lotto LIMIT 1", |
|
[":codice" => $this->info["codice"], ":codice_lotto" => $codice_lotto] |
|
); |
|
if ($res->rowCount() < 1) return null; |
|
$categoria = $res->fetch(PDO::FETCH_ASSOC)["cpv"] ?? ""; |
|
if(empty($categoria)) return null; |
|
|
|
return str_pad($categoria, 8, "0", STR_PAD_RIGHT); |
|
} |
|
|
|
public function getSOASerialize($codice_lotto = null) |
|
{ |
|
$soaLotto = $this->getSOA($codice_lotto); |
|
$categorie = getCategorieSOA(); |
|
foreach($soaLotto as $key => $soa ) { |
|
$soaLotto[$key]["categoria"] = $categorie[$soa["codice_categoria"]]["id"]; |
|
unset($soaLotto[$key]["codice_categoria"]); |
|
$soaLotto[$key]["prevalente"] = $soa["prevalente"] == "S"; |
|
} |
|
return $soaLotto; |
|
} |
|
public function getSOA($codice_lotto = null) { |
|
if (!isset($codice_lotto) && !empty($this->lotto)) { |
|
$codice_lotto = $this->lotto["codice"]; |
|
} |
|
if (!empty($codice_lotto)) { |
|
return $this->db->go("SELECT * FROM b_gare_soa WHERE codice_lotto = :lotto",[":lotto"=>$codice_lotto])->fetchAll(PDO::FETCH_ASSOC); |
|
} |
|
} |
|
|
|
public function getDettaglioSOA($forceAll = false) { |
|
$prevalenti = []; |
|
$scorporabili = []; |
|
$totale_sios = 0; |
|
$sios = []; |
|
$qo = []; |
|
$no_qo = []; |
|
$sios_30 = []; |
|
$sios_no_30 = []; |
|
$tutelate = []; |
|
$scorporabili = []; |
|
$og11 = []; |
|
$vincoli_soa = []; |
|
$flag_sios = false; |
|
$categorie = getCategorieSOA(); |
|
$classifica = $this->db->prepare("SELECT * FROM b_classifiche_soa WHERE attivo = 'S' AND minimo <= :importo AND (massimo >= :importo OR massimo = 0)"); |
|
if (empty($this->lotto) || $forceAll) { |
|
$lottiCheck = $this->getLotti(); |
|
} else { |
|
$lottiCheck = [$this->lotto]; |
|
} |
|
foreach($lottiCheck AS $lotto) { |
|
$soa = $this->getSOA($lotto["codice"]); |
|
if (!empty($soa)) { |
|
$vincoli_soa[] = 11; |
|
foreach($soa AS $categoria) { |
|
if ($categoria["prevalente"] == "S") { |
|
$variabile = &$prevalenti; |
|
} else { |
|
$variabile = &$scorporabili; |
|
} |
|
if (!isset($variabile[$categoria["codice_categoria"]])) { |
|
$variabile[$categoria["codice_categoria"]] = 0; |
|
} |
|
$variabile[$categoria["codice_categoria"]] += $categoria["importo"]; |
|
} |
|
} |
|
} |
|
if (!empty($scorporabili)) { |
|
foreach($scorporabili AS $id => $importo) { |
|
$categoria = $categorie[$id] ?? null; |
|
if (!empty($categoria)) { |
|
if ($categoria["sios"] == "S") { |
|
if ((($importo * 100) / $this->info["prezzoRiferimento"]) > 15) { |
|
$flag_sios = true; |
|
$vincoli_soa[] = 1; |
|
$sios[] = $categoria["id"]; |
|
$totale_sios += $importo; |
|
$classifica->bindValue(":importo",$importo); |
|
$classifica->execute(); |
|
if ($classifica->rowCount() > 0) { |
|
$cl = $classifica->fetch(PDO::FETCH_ASSOC); |
|
$classifica->bindValue(":importo",$importo * 0.7); |
|
$classifica->execute(); |
|
if ($classifica->rowCount() > 0) { |
|
$cl_ridotta = $classifica->fetch(PDO::FETCH_ASSOC); |
|
if ($cl_ridotta["id"] != $cl["id"]) { |
|
$sios_30[] = $categoria["id"]; |
|
$vincoli_soa[] = 2; |
|
} else { |
|
$sios_no_30[] = $categoria["id"]; |
|
$vincoli_soa[] = 3; |
|
} |
|
} |
|
} |
|
} |
|
} |
|
if ($categoria["obbligo_qualificazione"] == "S" && !$flag_sios) { |
|
if (((($importo*100)/$this->info["prezzoRiferimento"]) > 10) || $importo > 150000) { |
|
$vincoli_soa[] = 6; |
|
$qo[] = $categoria["id"]; |
|
} |
|
} |
|
if ($categoria["obbligo_qualificazione"] == "N") { |
|
$vincoli_soa[] = 7; |
|
$no_qo[] = $categoria["id"]; |
|
} |
|
if ($categoria["tutelate"] == "N") { |
|
$vincoli_soa[] = 8; |
|
$tutelate[] = $categoria["id"]; |
|
} |
|
if ($categoria["id"] == "OG 11") { |
|
$vincoli_soa[] = 9; |
|
} |
|
if (($categoria["id"] == "OS 3") || ($categoria["id"] == "OS 28") || ($categoria["id"] == "OS 30")) { |
|
if (!isset($og11[$categoria["id"]])) { |
|
$og11[$categoria["id"]] = 0; |
|
} |
|
$og11[$categoria["id"]] += $categoria["importo_base"]; |
|
} |
|
} |
|
} |
|
} else { |
|
$vincoli_soa[] = 10; |
|
} |
|
if (empty($tutelate)) { |
|
$vincoli_soa[]=13; |
|
} |
|
if (count($og11)==3) { |
|
$flag = 0; |
|
foreach($og11 AS $key=>$importo) { |
|
switch($key) { |
|
case "OS 3": |
|
if ((($importo*100)/$this->info["prezzoRiferimento"]) >= 10) { $flag++; } |
|
break; |
|
case "OS 28": |
|
if ((($importo*100)/$this->info["prezzoRiferimento"]) >= 25) { $flag++; } |
|
break; |
|
case "OS 30": |
|
if ((($importo*100)/$this->info["prezzoRiferimento"]) >= 25) { $flag++; } |
|
break; |
|
} |
|
} |
|
if ($flag == 3) { |
|
$vincoli_soa[]=9; |
|
} |
|
} |
|
if ($totale_sios>0) { |
|
if (($this->info["prezzoRiferimento"] - ($totale_sios*0.7))>20658000) { |
|
$vincoli_soa[] = 4; |
|
} else { |
|
$vincoli_soa[] = 5; |
|
} |
|
} else { |
|
$vincoli_soa[] = 12; |
|
} |
|
$vincoli_soa = array_unique($vincoli_soa); |
|
$sios = implode(",",$sios); |
|
$qo = implode(",",$qo); |
|
$no_qo = implode(",",$no_qo); |
|
$sios_30 = implode(",",$sios_30); |
|
$sios_no_30 = implode(",",$sios_no_30); |
|
$tutelate = implode(",",$tutelate); |
|
return ["vincoli_soa" => $vincoli_soa, |
|
"sios" => $sios, |
|
"qo" => $qo, |
|
"no_qo" => $no_qo, |
|
"sios_30" => $sios_30, |
|
"sios_no_30" => $sios_no_30, |
|
"tutelate" => $tutelate, |
|
"prevalenti" => $prevalenti, |
|
"scorporabili" => $scorporabili]; |
|
} |
|
|
|
public function getProgettazione($codice_lotto = null) { |
|
if (!isset($codice_lotto) && !empty($this->lotto)) { |
|
$codice_lotto = $this->lotto["codice"]; |
|
} |
|
if (!empty($codice_lotto)) { |
|
$where = " codice_lotto = :lotto "; |
|
$bind = [":lotto"=>$codice_lotto]; |
|
} else { |
|
$bind = [":gara"=>$this->info["codice"]]; |
|
$where = " codice_lotto IN (SELECT codice FROM b_gare_lotti WHERE codice_gara = :gara) "; |
|
} |
|
if (!empty($where)) { |
|
return $this->db->go("SELECT * FROM b_gare_progettazione WHERE {$where}",$bind)->fetchAll(PDO::FETCH_ASSOC); |
|
} |
|
} |
|
|
|
public function getCriteri($codice = NULL) |
|
{ |
|
$filters = []; |
|
if (!empty($codice)) { |
|
$filters = ["codice" => $codice]; |
|
} |
|
return $this->returnCriteri($this->round["codice"], $filters); |
|
} |
|
|
|
public function getAllCriteri($codice = NULL) |
|
{ |
|
$filters = ["ignore-lotto"=>true]; |
|
if (!empty($codice)) { |
|
$filters = ["codice" => $codice]; |
|
} |
|
return $this->returnCriteri($this->round["codice"], $filters); |
|
} |
|
|
|
public function getMacroCriteri() |
|
{ |
|
return $this->returnCriteri($this->round["codice"], ["codice_padre" => 0]); |
|
} |
|
|
|
public function getSubCriteri($codice_padre) |
|
{ |
|
return $this->returnCriteri($this->round["codice"], ["codice_padre" => $codice_padre]); |
|
} |
|
|
|
public function getFormCriterio($codice_criterio) |
|
{ |
|
$risultato = $this->db->go("SELECT * FROM b_gare_form WHERE codice_criterio = :codice_criterio ORDER BY ordinamento, codice", array(":codice_criterio" => $codice_criterio)); |
|
if ($risultato->rowCount() > 0) { |
|
return $risultato->fetchAll(PDO::FETCH_ASSOC); |
|
} |
|
return false; |
|
} |
|
|
|
private static function defaultAutenticationLevel() { |
|
return $_SESSION["ente"]->defaultAutenticationLevel(); |
|
} |
|
|
|
public function checkLock($id_cmd,$checkStato = null) |
|
{ |
|
$return = true; |
|
$stato = $this->info["stato"]; |
|
if (!empty($this->lotto) && $this->lotto["stato"] > 0) { |
|
$stato = $this->lotto["stato"]; |
|
} |
|
if (!empty($checkStato)) { |
|
$stato = $checkStato; |
|
} |
|
if ($_SESSION["utente"]->readOnly) { |
|
return true; |
|
} else { |
|
if ($_SESSION["utente"]->hasSuperPowers()) { |
|
$return = false; |
|
} else { |
|
if (($stato >= 0) && !empty($id_cmd) && $_SESSION["utente"]->unlockSupporto()) { |
|
$cmd = self::getInfoModulo($id_cmd); |
|
if ($cmd !== false) { |
|
$loa = $cmd["authenticationLevel"] ?? self::defaultAutenticationLevel(); |
|
if ($_SESSION["utente"]->authenticationLevel < $loa) { |
|
return true; |
|
} |
|
if (isset($this->round)) { |
|
if ($this->round["numero"] >= $this->info["fase_attiva"]) { |
|
if (!$this->quickPanel) { |
|
if (($stato >= $cmd["stato_minimo"] || $cmd["stato_minimo"] == null) && ($stato <= $cmd["stato_massimo"] || $cmd["stato_massimo"] === null)) { |
|
$return = false; |
|
} |
|
if (!$return) { |
|
if ($cmd["apertura"] && time() < strtotime($this->round["apertura"])) { |
|
$return = true; |
|
} |
|
if ($cmd["scaduta"] && time() < strtotime($this->round["scadenza"])) { |
|
$return = true; |
|
} |
|
} |
|
} else { |
|
$return = false; |
|
} |
|
} |
|
} else { |
|
$return = false; |
|
} |
|
} |
|
} |
|
} |
|
} |
|
if ($return) { |
|
if($id_cmd == "partecipanti") { |
|
$npa = $this->getNpaInstance(); |
|
if(!empty($npa)) { |
|
$return = $npa->hasLockOnPartecipanti(false); |
|
} |
|
} |
|
if($id_cmd == "definitiva") { |
|
$npa = $this->getNpaInstance(); |
|
if(!empty($npa)) { |
|
$return = $npa->hasLockOnPartecipanti(true); |
|
} else if (!$this->usaGraduatoria()) { |
|
$return = false; |
|
} |
|
} |
|
} |
|
if ($id_cmd == "lotti" || $id_cmd == "criteri" || $id_cmd == "buste") { |
|
if ((($this->checkPartecipantiPresenti() && !$_SESSION["utente"]->hasSuperPowers()) || $this->info["stato"] > 20) && !$this->quickPanel) { |
|
$return = true; |
|
} |
|
if ($id_cmd == "lotti") { |
|
$npa = $this->getNpaInstance(); |
|
if (!empty($npa)) { |
|
$return = (!empty($npa->fascicolo["id_appalto"]) || !empty($npa->fascicolo["id_pianificazione"])); |
|
// Se sarebbe bloccato, verifichiamo che non ci siano modifiche/rettifiche in corso |
|
if($return) { |
|
$return = !$npa->hasPendingRettificheOrModifiche(null, ["CM1", "CM2"]); |
|
} |
|
} |
|
} |
|
} |
|
/*if ($id_cmd == "partecipanti") { |
|
$npa = $this->getNpaInstance(); |
|
if (!empty($npa)) { |
|
$return = $npa->hasConfirmedParticipantsCards(); |
|
} |
|
}*/ |
|
if ($id_cmd == "inviti" && $this->round["numero"] > 1 && !$_SESSION["utente"]->hasSuperPowers() && (!$this->round["infoFase"]["estrazione"] ?? true)) { |
|
$return = true; |
|
} |
|
if ($id_cmd == "preliminari" && !empty($this->getRounds())) { |
|
$return = true; |
|
} |
|
if(in_array($id_cmd, ["provvisoria", "definitiva"], true) && $return) { |
|
$npa = $this->getNpaInstance(); |
|
if(!empty($npa)) { |
|
$return = !$npa->hasPendingRettificheOrModifiche(null, ["S4"]); |
|
} |
|
} |
|
return $return; |
|
} |
|
|
|
public function alertModifichePericolose($id_cmd) { |
|
if ($id_cmd == "lotti" || $id_cmd == "criteri" || $id_cmd == "buste") { |
|
if ($this->checkPartecipantiPresenti() && $_SESSION["utente"]->hasSuperPowers()) { |
|
include __DIR__ . "/misc/alertModifichePericolose.php"; |
|
} |
|
} |
|
} |
|
public function checkOpeningPermission($partecipante, $richiesta, $aggiuntive = false) |
|
{ |
|
$return = false; |
|
if (!empty($this->lotto)) { |
|
if (!empty($partecipante) && !empty($richiesta)) { |
|
if ((!empty($this->getRisposteElaborazione()["inversioneProcedimentale"])) && $this->getRisposteElaborazione()["inversioneProcedimentale"] == "S") { |
|
$return = true; // Se non c'è l'apertura sequenziale permetto l'apertura |
|
} else { |
|
$busta = $this->getBusta($partecipante, $richiesta, $aggiuntive); // controllo che la busta esista |
|
if (!empty($busta)) { |
|
if ($busta["open"] == "S") { // se è già aperta posso procedere all'apertura |
|
$return = true; |
|
} else { |
|
if (!$this->activeRound || !$this->checkLock("open")) { // Blocco se è l'ultimo round di lavorazione o se il comando è locked |
|
$infoPartecipante = $this->getPartecipante($partecipante); |
|
if ($infoPartecipante["escluso"] == "N" || $infoPartecipante["escluso"] == "P") { |
|
$tipologie = array_keys(self::tipologieBusta()); |
|
$tipologia = $this->db->go("SELECT busta FROM b_gare_richieste WHERE codice = :codice", [":codice" => $richiesta])->fetch(PDO::FETCH_ASSOC); |
|
if (!empty($tipologia)) { |
|
$tipologia = $tipologia["busta"]; |
|
$checkSeduta = $this->db->go("SELECT data FROM b_gare_sedute WHERE codice_round = :round AND busta = :busta ORDER BY codice DESC LIMIT 0,1", [":round" => $this->round["codice"], ":busta" => $tipologia]); |
|
$continua = true; |
|
if ($checkSeduta->rowCount() === 1) { |
|
$dataSeduta = $checkSeduta->fetch(PDO::FETCH_ASSOC)["data"]; |
|
$continua = false; |
|
if (strtotime($dataSeduta) < time()) { |
|
$continua = true; |
|
} |
|
} |
|
if ($continua) { |
|
$block = false; // la variabile sarà utilizzata per determinare l'esito dopo il ciclo foreach |
|
$buste = []; |
|
foreach ($tipologie as $tipo) { |
|
$buste[] = $tipo; |
|
if ($tipo == $tipologia) { |
|
break; |
|
} |
|
} |
|
if (count($buste) > 1) { |
|
$inBuste = implode("','", $buste); |
|
} else { |
|
$inBuste = $buste[0]; |
|
} |
|
$check = $this->db->go( |
|
"SELECT MIN(r_partecipanti_gare.codice) AS firstPartecipante, b_gare_richieste.busta |
|
FROM r_partecipanti_gare JOIN b_gare_buste ON r_partecipanti_gare.codice = b_gare_buste.codice_partecipante |
|
JOIN b_gare_richieste ON b_gare_buste.codice_richiesta = b_gare_richieste.codice |
|
WHERE r_partecipanti_gare.codice_round = :codice_round AND r_partecipanti_gare.conferma =\"S\" AND (r_partecipanti_gare.escluso = \"N\" OR r_partecipanti_gare.escluso = \"P\") |
|
AND b_gare_buste.open = 'N' |
|
AND r_partecipanti_gare.codice_lotto = :codice_lotto |
|
AND b_gare_richieste.busta IN ('{$inBuste}') |
|
GROUP BY b_gare_richieste.busta ", |
|
[":codice_round" => $this->round["codice"],":codice_lotto"=>$this->lotto["codice"]] |
|
); |
|
// si controlla che non ci siano buste chiuse di partecipanti ammessi precedenti a quella del concorrente attuale |
|
if ($check->rowCount() == 1) { |
|
$check = $check->fetch(PDO::FETCH_ASSOC); |
|
if ($check["firstPartecipante"] != $partecipante || $check["busta"] != $tipologia) { |
|
$block = true; |
|
} |
|
} else { |
|
$block = true; |
|
} |
|
if (!$block) { |
|
$return = true; |
|
} |
|
} |
|
} |
|
} |
|
} |
|
} |
|
} |
|
} |
|
} |
|
if ($return && $this->commissario) { |
|
$tipologia = $this->db->go("SELECT busta FROM b_gare_richieste WHERE codice = :codice", [":codice" => $richiesta])->fetch(PDO::FETCH_ASSOC); |
|
$return = false; |
|
if (!empty($tipologia)) { |
|
$tipologia = $tipologia["busta"]; |
|
if ($tipologia != "amministrativa") { |
|
$criteri = $this->getCriteri(); |
|
foreach ($criteri as $criterio) { |
|
if ($criterio["tipologia"] == "Q" && (($criterio["economico"] == "S" && $tipologia == "economica") || ($criterio["economico"] == "N" && $tipologia == "tecnica"))) { |
|
$return = true; |
|
break; |
|
} |
|
} |
|
} |
|
} |
|
} |
|
} |
|
return $return; |
|
} |
|
|
|
public function checkSoglie() |
|
{ |
|
$partecipanti = $this->getPartecipanti("ALL"); |
|
if (!empty($partecipanti)) { |
|
$codici_partecipanti = []; |
|
foreach($partecipanti AS $partecipante) { |
|
$codici_partecipanti[] = (int) $partecipante["codice"]; |
|
} |
|
$codici_partecipanti = implode(",",$codici_partecipanti); |
|
$punteggio = $this->db->prepare("SELECT b_gare_punteggi_partecipanti.codice, b_gare_punteggi_partecipanti.codice_partecipante, b_gare_punteggi_partecipanti.valore |
|
FROM b_gare_punteggi_partecipanti WHERE codice_criterio = :criterio AND codice_partecipante IN (".$codici_partecipanti.")"); |
|
$macro = $this->getMacroCriteri(); |
|
$esclusi = []; |
|
$checkSoglia = $this->getRisposteElaborazione()["sogliaMinima"] ?? false; |
|
if (!empty($checkSoglia) && $checkSoglia != "N") { |
|
foreach ($macro as $padre) { |
|
$sub = $this->getSubCriteri($padre["codice"]); |
|
if (!empty($sub)) { |
|
$somma = []; |
|
foreach ($sub as $s) { |
|
$punteggio->bindValue(":criterio", $s["codice"]); |
|
$punteggio->execute(); |
|
if ($punteggio->rowCount() > 0) { |
|
while ($punt = $punteggio->fetch(PDO::FETCH_ASSOC)) { |
|
if (!isset($somma[$punt["codice_partecipante"]])) { |
|
$somma[$punt["codice_partecipante"]] = 0; |
|
} |
|
$somma[$punt["codice_partecipante"]] += $punt["valore"]; |
|
if ($s["soglia"] > 0 && $punt["valore"] < $s["soglia"]) { |
|
$esclusi[] = ["partecipante" => $punt["codice_partecipante"], "codice_relazione" => $s["codice"], "criterio" => $s["denominazione"], "soglia" => $s["soglia"], "valore" => $punt["valore"]]; |
|
} |
|
} |
|
} |
|
} |
|
} else { |
|
$somma = []; |
|
$punteggio->bindValue(":criterio", $padre["codice"]); |
|
$punteggio->execute(); |
|
if ($punteggio->rowCount() > 0) { |
|
while ($punt = $punteggio->fetch(PDO::FETCH_ASSOC)) { |
|
if (!isset($somma[$punt["codice_partecipante"]])) { |
|
$somma[$punt["codice_partecipante"]] = 0; |
|
} |
|
$somma[$punt["codice_partecipante"]] += $punt["valore"]; |
|
} |
|
} |
|
} |
|
if (!empty($somma)) { |
|
foreach ($somma as $codice_partecipante => $valore) { |
|
if ($padre["soglia"] > 0 && $valore < $padre["soglia"]) { |
|
$esclusi[] = ["partecipante" => $codice_partecipante, "codice_relazione" => $padre["codice"], "criterio" => $padre["denominazione"], "soglia" => $padre["soglia"], "valore" => $valore]; |
|
} |
|
} |
|
} |
|
} |
|
if (!empty($esclusi)) { |
|
if ($checkSoglia == "E") { |
|
$partecipanti = []; |
|
foreach ($esclusi as $info) { |
|
if (!isset($partecipanti[$info["partecipante"]])) { |
|
$partecipanti[$info["partecipante"]] = __("Soglia minima non superata"); |
|
} |
|
$partecipanti[$info["partecipante"]] .= "<br>" . $info["criterio"] . " - " . __("Soglia") . ": " . $info["soglia"] . " - Punteggio: " . $info["valore"]; |
|
} |
|
$salva = new salva(); |
|
$salva->debug = false; |
|
|
|
$salva->nome_tabella = "r_partecipanti_gare"; |
|
foreach ($partecipanti as $codice => $motivazione) { |
|
$salva->operazione = "UPDATE"; |
|
$salva->oggetto = ["codice" => $codice, "escluso" => "S", "motivazione" => $motivazione]; |
|
$salva->save(); |
|
} |
|
} else if ($checkSoglia == "A") { |
|
$updatePunteggio = $this->db->prepare("UPDATE b_gare_punteggi_partecipanti SET valore = 0 WHERE codice = :codice"); |
|
foreach ($esclusi as $info) { |
|
$updatePunteggio->bindValue(":codice",$info["codice_relazione"]); |
|
$updatePunteggio->execute(); |
|
} |
|
} |
|
} |
|
} |
|
return $esclusi; |
|
} |
|
} |
|
|
|
public function updateTotalePunteggi() |
|
{ |
|
$this->checkSoglie(); |
|
$return = false; |
|
$partecipanti = $this->getPartecipanti("ALL"); |
|
$totali = []; |
|
$tecnici = []; |
|
$economici = []; |
|
$sommaMacroTecnici = []; |
|
$sommaMacroEconomici = []; |
|
if (!empty($partecipanti)) { |
|
$sql_punteggi = "SELECT r_partecipanti_gare.codice, b_gare_punteggi_partecipanti.valore, b_gare_criteri_valutazione.economico, b_gare_criteri_valutazione.codice AS codice_criterio, b_gare_criteri_valutazione.codice_padre |
|
FROM b_gare_punteggi_partecipanti JOIN r_partecipanti_gare ON b_gare_punteggi_partecipanti.codice_partecipante = r_partecipanti_gare.codice |
|
JOIN b_gare_criteri_valutazione ON b_gare_punteggi_partecipanti.codice_criterio = b_gare_criteri_valutazione.codice |
|
WHERE r_partecipanti_gare.codice_round = :codice AND r_partecipanti_gare.codice_lotto = :lotto"; |
|
$ris_punteggi = $this->db->go($sql_punteggi, array(":codice" => $this->round["codice"],":lotto"=>$this->lotto["codice"])); |
|
if ($ris_punteggi->rowCount() > 0) { |
|
$riparametra = $this->getRisposteElaborazione()["riparametrazioneMacroCriteri"] ?? null; |
|
$riparametra = ($riparametra === "S"); |
|
while ($punteggio = $ris_punteggi->fetch(PDO::FETCH_ASSOC)) { |
|
if ($riparametra) { |
|
$riferimento = (!empty($punteggio["codice_padre"])) ? $punteggio["codice_padre"] : $punteggio["codice_criterio"]; |
|
if ($punteggio["economico"] == "S") { |
|
if (!isset($sommaMacroEconomici[$riferimento])) { |
|
$sommaMacroEconomici[$riferimento] = []; |
|
} |
|
if (!isset($sommaMacroEconomici[$riferimento][$punteggio["codice"]])) { |
|
$sommaMacroEconomici[$riferimento][$punteggio["codice"]] = 0; |
|
} |
|
$sommaMacroEconomici[$riferimento][$punteggio["codice"]] += $punteggio["valore"]; |
|
} else { |
|
if (!isset($sommaMacroTecnici[$riferimento])) { |
|
$sommaMacroTecnici[$riferimento] = []; |
|
} |
|
if (!isset($sommaMacroTecnici[$riferimento][$punteggio["codice"]])) { |
|
$sommaMacroTecnici[$riferimento][$punteggio["codice"]] = 0; |
|
} |
|
$sommaMacroTecnici[$riferimento][$punteggio["codice"]] += $punteggio["valore"]; |
|
} |
|
} else { |
|
if ($punteggio["economico"] == "S") { |
|
if (!isset($economici[$punteggio["codice"]])) { |
|
$economici[$punteggio["codice"]] = 0; |
|
} |
|
$economici[$punteggio["codice"]] += $punteggio["valore"]; |
|
} else { |
|
if (!isset($tecnici[$punteggio["codice"]])) { |
|
$tecnici[$punteggio["codice"]] = 0; |
|
} |
|
$tecnici[$punteggio["codice"]] += $punteggio["valore"]; |
|
} |
|
if (!isset($totali[$punteggio["codice"]])) { |
|
$totali[$punteggio["codice"]] = 0; |
|
} |
|
$totali[$punteggio["codice"]] += $punteggio["valore"]; |
|
} |
|
} |
|
if ($riparametra) { |
|
if (!empty($sommaMacroTecnici)) { |
|
foreach($sommaMacroTecnici AS $criterio => $punteggi) { |
|
$criterio = $this->getCriteri($criterio)[0]; |
|
$normalizzati = tuttogareMath::proporzionale($punteggi,$criterio["peso"],$criterio["decimali"]); |
|
foreach($normalizzati AS $partecipante => $punteggio) { |
|
if (!isset($tecnici[$partecipante])) { |
|
$tecnici[$partecipante] = 0; |
|
} |
|
$tecnici[$partecipante] += $punteggio; |
|
if (!isset($totali[$partecipante])) { |
|
$totali[$partecipante] = 0; |
|
} |
|
$totali[$partecipante] += $punteggio; |
|
} |
|
} |
|
} |
|
if (!empty($sommaMacroEconomici)) { |
|
foreach($sommaMacroEconomici AS $criterio => $punteggi) { |
|
$criterio = $this->getCriteri($criterio)[0]; |
|
$normalizzati = tuttogareMath::proporzionale($punteggi,$criterio["peso"],$criterio["decimali"]); |
|
foreach($normalizzati AS $partecipante => $punteggio) { |
|
if (!isset($economici[$partecipante])) { |
|
$economici[$partecipante] = 0; |
|
} |
|
$economici[$partecipante] += $punteggio; |
|
if (!isset($totali[$partecipante])) { |
|
$totali[$partecipante] = 0; |
|
} |
|
$totali[$partecipante] += $punteggio; |
|
} |
|
} |
|
} |
|
} |
|
} |
|
$return = true; |
|
$salva = new salva(); |
|
$salva->debug = false; |
|
|
|
foreach ($partecipanti as $partecipante) { |
|
$totale = $totali[$partecipante["codice"]] ?? null; |
|
$totaleTecnico = $tecnici[$partecipante["codice"]] ?? null; |
|
$totaleEconomico = $economici[$partecipante["codice"]] ?? null; |
|
$partecipante["totale"] = number_format($totale, 5); |
|
$partecipante["totaleTecnico"] = number_format($totaleTecnico, 5); |
|
$partecipante["totaleEconomico"] = number_format($totaleEconomico, 5); |
|
$salva->nome_tabella = "r_partecipanti_gare"; |
|
$salva->operazione = "UPDATE"; |
|
$salva->oggetto = $partecipante; |
|
$salva->save(); |
|
} |
|
} |
|
return $return; |
|
} |
|
|
|
public function importScore($economici, $ammessi = TRUE) |
|
{ |
|
$return = false; |
|
$asta = ($economici === "asta"); |
|
if ($asta) { |
|
$criteri = $this->getCriteriValutabili(); |
|
} else { |
|
$criteri = ($economici) ? $this->getCriteriEconomiciValutabili() : $this->getCriteriTecniciValutabili(); |
|
} |
|
if (!empty($criteri)) { |
|
$partecipanti = $this->getPartecipanti($ammessi); |
|
if (!empty($partecipanti)) { |
|
$salva = new salva(); |
|
$salva->debug = false; |
|
|
|
$ris_check = $this->db->prepare("SELECT * FROM b_gare_punteggi_partecipanti WHERE codice_partecipante = :codice_partecipante AND codice_criterio = :codice_criterio "); |
|
$errori_importazione = []; |
|
foreach ($criteri as $criterio) { |
|
$punteggi = []; |
|
$auto = false; |
|
if (!empty($criterio["auto"])) { |
|
$auto = true; |
|
$offerte = $this->getOfferte($criterio["codice"], TRUE, $ammessi, $asta); |
|
if (!empty($offerte)) { |
|
$options = json_decode($criterio["options"], true); |
|
if ($economici && count($criteri) === 1 && $this->getInterpretazioneArt41() === "scorporato") { |
|
$offerte = $this->getRibassoComplessivoArt41($offerte); |
|
} |
|
if ($this->lotto["formato"] === "assoluto" && tuttogareMath::getFormule()[$criterio["auto"]]["diretta"]) { |
|
$offerte = tuttogareMath::convertInversaForScore($offerte,$this->lotto["importoRibassabile"]); |
|
} |
|
if ($criterio["peso"] == 100 && $criterio["auto"] == "P" && $criterio["economico"] == "S" && $this->lotto["formato"] !== "r-assoluto") { |
|
$punteggi = $offerte; |
|
} else { |
|
switch ($criterio["auto"]) { |
|
case "I": |
|
$punteggi = tuttogareMath::inversamenteProporzionale($offerte, $criterio["peso"], $criterio["decimali"]); |
|
break; |
|
case "L": |
|
$punteggi = tuttogareMath::lineareSemplice($offerte, $criterio["peso"], $criterio["decimali"], $options); |
|
break; |
|
case "H": |
|
$punteggi = tuttogareMath::incrementoLineare($offerte, $criterio["peso"], $criterio["decimali"]); |
|
break; |
|
case "P": |
|
$punteggi = tuttogareMath::proporzionale($offerte, $criterio["peso"], $criterio["decimali"]); |
|
break; |
|
case "O": |
|
$punteggi = tuttogareMath::onOff($offerte, $criterio["peso"]); |
|
break; |
|
case "S": |
|
$punteggi = tuttogareMath::tabellare($offerte, $options,$criterio["peso"], $criterio["decimali"]); |
|
break; |
|
case "B": |
|
$punteggi = tuttogareMath::bilineare($offerte, $criterio["peso"], $criterio["decimali"], $options); |
|
break; |
|
case "Q": |
|
$punteggi = tuttogareMath::quadratica($offerte, $criterio["peso"], $criterio["decimali"], $options); |
|
break; |
|
default: |
|
return false; |
|
} |
|
} |
|
} |
|
} else if ($criterio["tipologia"] == "Q") { |
|
$auto = true; |
|
$punteggi = $this->getSommaMediaPunteggiCoefficienti($criterio["codice"], NULL, "punteggi"); |
|
} |
|
if (!empty($punteggi)) { |
|
foreach ($punteggi as $partecipante => $valore) { |
|
if (is_numeric($valore)) { |
|
$punteggio = array(); |
|
$punteggio["codice_partecipante"] = $partecipante; |
|
$punteggio["codice_criterio"] = $criterio["codice"]; |
|
$punteggio["valore"] = number_format($valore, $criterio["decimali"]); |
|
$ris_check->bindValue(":codice_partecipante", $punteggio["codice_partecipante"], PDO::PARAM_INT); |
|
$ris_check->bindValue(":codice_criterio", $punteggio["codice_criterio"], PDO::PARAM_INT); |
|
$ris_check->execute(); |
|
$operazione = "INSERT"; |
|
$continua = true; |
|
if ($ris_check->rowCount() == 1) { |
|
$old = $ris_check->fetch(PDO::FETCH_ASSOC); |
|
$operazione = "UPDATE"; |
|
$punteggio["codice"] = $old["codice"]; |
|
if ($old["valore"] == $valore) { |
|
$continua = false; |
|
} |
|
} |
|
if ($continua) { |
|
$salva->nome_tabella = "b_gare_punteggi_partecipanti"; |
|
$salva->operazione = $operazione; |
|
$salva->oggetto = $punteggio; |
|
$salva->save(); |
|
} |
|
} |
|
} |
|
} else if ($auto) { |
|
$errori_importazione[] = $criterio["denominazione"]; |
|
} |
|
} |
|
$return = $this->updateTotalePunteggi(); |
|
if ($return && !empty($errori_importazione)) { |
|
$return = $errori_importazione; |
|
} |
|
} |
|
} |
|
return $return; |
|
} |
|
|
|
public static function algoritmiAnomalie() { |
|
global $config; |
|
return jsonToArray($config["jsonFolder"]."/gare-algoritimiAnomalia.json"); |
|
} |
|
|
|
public static function domandeStandardAnomalia() { |
|
$domande = []; |
|
$domande["decimali"] = ["label"=>"Decimali","options"=>[0,1,2,3,4,5,6,7,8,9]]; |
|
$domande["arrotondamento"] = ["label"=>"Arrotondamento","options"=>["S"=>"Si","N"=>"No"]]; |
|
$domande["soloSoglia"] = ["label"=>"Applicazione decimali e arrotondamenti","options"=>["S"=>"Solo soglia","N"=>"Tutti i passaggi"]]; |
|
return $domande; |
|
} |
|
|
|
public function getAnomaliaSorteggiata() { |
|
$extraInfo = $this->getExtraInfo(); |
|
if (isset($this->lotto) && !empty($extraInfo["lotto"]["anomaliaSorteggiata"])) { |
|
return $extraInfo["lotto"]["anomaliaSorteggiata"]; |
|
} |
|
} |
|
|
|
public function getRispostaElaborazioneAlgoritmoAnomalia() : ?String { |
|
$risposta = $this->getRisposteElaborazione()["esclusioneAutomaticaDlgs36"] ?? null; |
|
if (empty($risposta)) { |
|
$risposta = $this->getRisposteElaborazione()["anomaliaSoprasogliaDlgs36"] ?? null; |
|
} |
|
return $risposta; |
|
} |
|
|
|
public function getAlgoritmoAnomalia($excludeSorteggio = false) { |
|
$algoritmi = self::algoritmiAnomalie(); |
|
$return = []; |
|
if (!empty($this->lotto) && !empty($algoritmi) && !$this->privata) { |
|
$partecipanti = count($this->getPartecipantiForAnomalia()); |
|
$firstRound = $this->getRounds()[0] ?? false; |
|
if (!empty($partecipanti) && !empty($firstRound)) { |
|
$anomaliaSorteggiata = $this->getAnomaliaSorteggiata(); |
|
if (!empty($anomaliaSorteggiata)) { |
|
if (!empty($algoritmi[$anomaliaSorteggiata])) { |
|
$algoritmi = [$anomaliaSorteggiata => $algoritmi[$anomaliaSorteggiata]]; |
|
} else { |
|
$algoritmi = []; |
|
} |
|
} |
|
if (!empty($algoritmi)) { |
|
foreach($algoritmi AS $idAlgo => $algoritmo) { |
|
if ( |
|
(in_array($this->normaRiferimento,$algoritmo["idNormeApplicazione"]) !== false) && |
|
(in_array($this->lotto["criterio"],$algoritmo["criteri"]) !== false) && |
|
(in_array($this->info["procedura"],$algoritmo["procedureEscluse"]) === false) && |
|
(empty($algoritmo["inizio"]) || (strtotime($algoritmo["inizio"]) <= strtotime($firstRound["pubblicazione"]))) && |
|
(empty($algoritmo["fine"]) || (strtotime($algoritmo["fine"]) >= strtotime($firstRound["pubblicazione"]))) && |
|
(empty($algoritmo["partecipantiMinimi"]) || ($algoritmo["partecipantiMinimi"] <= $partecipanti)) && |
|
(empty($algoritmo["partecipantiMassimi"]) || ($algoritmo["partecipantiMassimi"] >= $partecipanti)) && |
|
(empty($algoritmo["tipologia"]) || in_array($this->info["tipologia"],$algoritmo["tipologia"]) !== false) && |
|
(!$excludeSorteggio || !$algoritmo["algoritmoSorteggio"]) |
|
) |
|
{ |
|
$include = true; |
|
$path = __DIR__."/provvisoria/calcoloAnomalie/{$idAlgo}/check.php"; |
|
if (file_exists($path)) { |
|
$include = false; |
|
include($path); |
|
} |
|
if($include) { |
|
$return[$idAlgo] = $algoritmo; |
|
} |
|
} |
|
} |
|
} |
|
} |
|
} |
|
return $return; |
|
} |
|
|
|
public function calcolaAnomalia($algo,$settings) { |
|
$errors = __("Errore generale nel calcolo"); |
|
foreach($this->getAlgoritmoAnomalia() AS $idAlgo => $algoritmo) { |
|
if ($idAlgo == $algo) { |
|
$path = __DIR__."/provvisoria/calcoloAnomalie/{$idAlgo}/calcolo.php"; |
|
if (file_exists($path)) { |
|
$soloSoglia = ($settings["soloSoglia"] == "S"); |
|
$arrotondamento = ($settings["arrotondamento"] == "S"); |
|
$decimali = (int) $settings["decimali"]; |
|
$this->db->go("UPDATE r_partecipanti_gare SET anomalia = 'N', motivazione_anomalia = '' WHERE codice_round = :round AND codice_lotto = :lotto AND a_verificata = 'N' AND a_facoltativa = 'N'",[":round"=>$this->round["codice"],":lotto"=>$this->lotto["codice"]]); |
|
$this->db->go("UPDATE r_partecipanti_gare SET escluso = 'N', motivazione = '', esclusione_automatica = 'N' WHERE codice_round = :round AND codice_lotto = :lotto AND esclusione_automatica = 'S'",[":round"=>$this->round["codice"],":lotto"=>$this->lotto["codice"]]); |
|
include($path); |
|
if (isset($extraInfo)) { |
|
foreach($extraInfo AS $key => $value) { |
|
$this->saveExtraInfo($key,$value,"lotto"); |
|
} |
|
} |
|
if (isset($soglia_anomalia)) { |
|
$this->db->go("UPDATE b_gare_lotti SET sogliaAnomalia = :soglia WHERE codice = :codice",[":soglia"=>$soglia_anomalia,":codice"=>$this->lotto["codice"]]); |
|
} |
|
} else { |
|
$errors = __("Impossibile eseguire calcolo dell'anomalia"); |
|
} |
|
break; |
|
} |
|
} |
|
return $errors; |
|
} |
|
|
|
public function aggiudica($aggiudicatari = 1) { |
|
if (!empty($this->lotto)) { |
|
$requestedAggiudicatari = $aggiudicatari; |
|
$salva = new salva(); |
|
$salva->debug = false; |
|
|
|
$sql = "UPDATE r_partecipanti_gare SET aggiudicatario = 'N', posizione = 0 WHERE codice_round = :codice AND codice_lotto = :lotto "; |
|
$this->db->go($sql,array(":codice"=>$this->round["codice"],":lotto"=>$this->lotto["codice"])); |
|
$sql = "SELECT * FROM r_partecipanti_gare WHERE codice_round = :codice AND codice_lotto = :lotto AND conferma = 'S' AND escluso = 'N' ORDER BY totale DESC"; |
|
$ris_partecipanti = $this->db->go($sql,array(":codice"=>$this->round["codice"],":lotto"=>$this->lotto["codice"])); |
|
$partecipanti = $ris_partecipanti->fetchAll(PDO::FETCH_ASSOC); |
|
$current = null; |
|
$riparametrazioneAssoluta = $this->getRisposteElaborazione()["riparametrazioneAssoluta"] ?? "N"; |
|
if ($riparametrazioneAssoluta === "S") { |
|
$criteriTecnici = $this->getMacroCriteri(); |
|
$punteggioMassimo = 0; |
|
$decimali = 3; |
|
foreach($criteriTecnici AS $criterio) { |
|
if ($criterio["economico"] == "N") { |
|
$punteggioMassimo += $criterio["peso"]; |
|
if ($decimali < $criterio["decimali"]) { |
|
$decimali = $criterio["decimali"]; |
|
} |
|
} |
|
} |
|
$punteggi = []; |
|
foreach($partecipanti AS $partecipante) { |
|
$punteggi[$partecipante["codice"]] = $partecipante["totaleTecnico"]; |
|
} |
|
$punteggi = tuttogareMath::proporzionale($punteggi,$punteggioMassimo,$decimali); |
|
reset($partecipanti); |
|
foreach($partecipanti AS $ind => $partecipante) { |
|
$partecipante["totaleTecnico"] = $punteggi[$partecipante["codice"]]; |
|
$partecipante["totale"] = $partecipante["totaleTecnico"] + $partecipante["totaleEconomico"]; |
|
$partecipanti[$ind] = $partecipante; |
|
} |
|
usort($partecipanti, function($a, $b) { |
|
return $b["totale"] > $a["totale"]; |
|
}); |
|
reset($partecipanti); |
|
} |
|
$count = 0; |
|
$posizione = 0; |
|
foreach($partecipanti AS $partecipante) { |
|
$count++; |
|
if ($current != $partecipante["totale"]) { |
|
$posizione = $count; |
|
} |
|
if ($aggiudicatari > 0 || $current == $partecipante["totale"]) { |
|
$partecipante["aggiudicatario"] = "S"; |
|
$partecipante["posizione"] = $posizione; |
|
if ($current != $partecipante["totale"]) { |
|
$aggiudicatari--; |
|
} |
|
$current = $partecipante["totale"]; |
|
} else { |
|
$partecipante["posizione"] = $posizione; |
|
$partecipante["aggiudicatario"] = "N"; |
|
} |
|
$salva->nome_tabella = "r_partecipanti_gare"; |
|
$salva->operazione = "UPDATE"; |
|
$salva->oggetto = $partecipante; |
|
$salva->save(); |
|
} |
|
$this->saveExtraInfo("aggiudicatari-{$this->round["codice"]}",$requestedAggiudicatari,"lotto"); |
|
} |
|
} |
|
|
|
public function getCostiManodoperaPartecipanti() : ?Array { |
|
$criteri = $this->getCriteriEconomiciValutabili(); |
|
$partecipanti = $this->getPartecipanti("ALL"); |
|
if (!empty($criteri) && !empty($partecipanti)) { |
|
$first = reset($criteri); |
|
$tmp = $this->getDettaglioOfferta("N",["{$first["codice"]}.02"],$partecipanti); |
|
if (!empty($tmp)) { |
|
$return = []; |
|
foreach ($tmp as $partecipante => $costo) { |
|
$return[$partecipante] = reset($costo); |
|
} |
|
return $return; |
|
} |
|
} |
|
return null; |
|
} |
|
|
|
public function getRibassoComplessivoArt41(Array $offerte, Bool $importoAssoluto = false) : ? Array { |
|
$costi = $this->getCostiManodoperaPartecipanti(); |
|
$formato = $this->lotto["formato"]; |
|
if (!empty($costi)) { |
|
$tmp = []; |
|
foreach($offerte AS $partecipante => $offerta) { |
|
if ($formato == "assoluto" || $formato == "r-assoluto") { |
|
$offerta = $offerta + ($costi[$partecipante] ?? 0); |
|
} else { |
|
if ($formato == "ribasso" || $formato == "nulla") { |
|
$offerta = $this->lotto["importoBase"] * $offerta / 100; |
|
$offerta = $this->lotto["importoBase"] - $offerta; |
|
$offerta += $costi[$partecipante] ?? 0; |
|
} else if ($formato == "rialzo") { |
|
$offerta = $this->lotto["importoBase"] * $offerta / 100; |
|
$offerta = $this->lotto["importoBase"] + $offerta; |
|
$offerta += $costi[$partecipante] ?? 0; |
|
} |
|
if (!$importoAssoluto) { |
|
$offerta = 100 - ($offerta * 100 / $this->lotto["importoRibassabile"]); |
|
} |
|
} |
|
$tmp[$partecipante] = $offerta; |
|
} |
|
$offerte = $tmp; |
|
} |
|
return (empty($offerte)) ? null : $offerte; |
|
} |
|
|
|
private function getDettaglioOfferta(String $tipologia, Array $codici_dettaglio, Array $partecipanti, ?String $busta = null) : ?Array { |
|
$return = []; |
|
$filtroTipologia = ""; |
|
if (!empty($busta)) { |
|
$filtroTipologia = " AND tipo = :tipoOfferta AND verificata = 'S'"; |
|
} else { |
|
$asta = $this->getAsta(true); |
|
$filtroTipologia = " AND verificata <> 'P'"; |
|
if (!empty($asta->info) && $asta->getScadenza(true)) { |
|
$filtroTipologia = " AND verificata = 'S'"; |
|
} |
|
} |
|
$sql = "SELECT offerta FROM b_dettaglio_offerte_gare |
|
WHERE codice_dettaglio = :dettaglio AND codice_partecipante = :partecipante AND offerta IS NOT NULL AND tipo = :tipologia AND codice_offerta IN |
|
(SELECT MAX(codice) AS last_offer FROM b_offerte_gare WHERE codice_partecipante = :partecipante {$filtroTipologia})"; |
|
$getOffer = $this->db->prepare($sql); |
|
$getOffer->bindValue(":tipologia", $tipologia); |
|
if (!empty($busta)) { |
|
$getOffer->bindValue(":tipoOfferta", $busta); |
|
} |
|
foreach ($partecipanti as $partecipante) { |
|
if (!empty($codici_dettaglio)) { |
|
$found = false; |
|
foreach ($codici_dettaglio as $dettaglio) { |
|
$quantita = 1; |
|
if (is_array($dettaglio)) { |
|
$quantita = $dettaglio["quantita"]; |
|
$dettaglio = $dettaglio["codice"]; |
|
} |
|
$getOffer->bindValue(":dettaglio", $dettaglio); |
|
$getOffer->bindValue(":partecipante", $partecipante["codice"]); |
|
$getOffer->execute(); |
|
if ($getOffer->rowCount() == 1) { |
|
$found = true; |
|
$tmpOfferta = $getOffer->fetch(PDO::FETCH_COLUMN); |
|
if ($tmpOfferta !== false) { |
|
$dettagli[$dettaglio] = ($tmpOfferta * $quantita); |
|
} |
|
} |
|
} |
|
if ($found) { |
|
$return[$partecipante["codice"]] = $dettagli; |
|
} |
|
} |
|
} |
|
return (empty($return)) ? null : $return; |
|
} |
|
|
|
public function getOfferte($codice_criterio, $totale = true, $ammessi = TRUE, $asta = false) |
|
{ |
|
$criterio = $this->getCriteri($codice_criterio); |
|
if (!empty($criterio)) { |
|
$criterio = $criterio[0]; |
|
$partecipanti = $this->getPartecipanti($ammessi); |
|
$offerte = []; |
|
$codici_dettaglio = [$codice_criterio]; |
|
if ($criterio["tipologia"] == "E") { |
|
$codici_dettaglio = []; |
|
$voci = $this->getElencoPrezzi($criterio["codice"]); |
|
if (!empty($voci)) { |
|
foreach($voci AS $voce) { |
|
$codice_d = $criterio["codice"] . "." . $voce["codice"]; |
|
$codici_dettaglio[] = ["codice"=>$codice_d,"quantita"=>$voce["quantita"]]; |
|
} |
|
} |
|
} |
|
$dettagli = $this->getDettaglioOfferta($criterio["tipologia"],$codici_dettaglio,$partecipanti, (empty($asta)) ? $criterio["busta"] : null); |
|
if (!empty($dettagli)) { |
|
if (!$totale) { |
|
$offerte = $dettagli; |
|
} else { |
|
foreach($dettagli AS $partecipante => $ds) { |
|
foreach($ds AS $d) { |
|
if (!isset($offerte[$partecipante])) $offerte[$partecipante] = 0; |
|
$offerte[$partecipante] += $d; |
|
} |
|
} |
|
} |
|
} |
|
return $offerte; |
|
} |
|
return false; |
|
} |
|
|
|
public function getCoefficientiValutazione($codice_criterio = NULL, $codice_utente = NULL) |
|
{ |
|
$tmp = $this->getManagerCommissione("commissione")->getCoefficientiValutazione($codice_criterio, $codice_utente); |
|
$coefficienti = []; |
|
$partecipanti = $this->getPartecipanti(); |
|
if (!empty($partecipanti)) { |
|
$codiciPartecipanti = []; |
|
foreach($partecipanti AS $par) { |
|
$codiciPartecipanti[] = $par["codice"]; |
|
} |
|
if (!empty($tmp) && !empty($partecipanti)) { |
|
if ((!empty($codice_criterio)) && (!empty($codice_utente))) { |
|
foreach($tmp AS $codicePart => $coef) { |
|
if (in_array($codicePart,$codiciPartecipanti) !== false) { |
|
$coefficienti[$codicePart] = $coef; |
|
} |
|
} |
|
} else if (!empty($codice_utente)) { |
|
foreach($tmp AS $codiceCriterio => $coefP) { |
|
foreach($coefP AS $codicePart => $coef) { |
|
if (in_array($codicePart,$codiciPartecipanti) !== false) { |
|
$coefficienti[$codiceCriterio][$codicePart] = $coef; |
|
} |
|
} |
|
} |
|
} else if (!empty($codice_criterio)) { |
|
foreach($tmp AS $codiceUtente => $coefP) { |
|
foreach($coefP AS $codicePart => $coef) { |
|
if (in_array($codicePart,$codiciPartecipanti) !== false) { |
|
$coefficienti[$codiceUtente][$codicePart] = $coef; |
|
} |
|
} |
|
} |
|
} else { |
|
foreach($tmp AS $codiceCriterio => $coefU) { |
|
foreach($coefU AS $codiceUtente => $coefP) { |
|
foreach($coefP AS $codicePart => $coef) { |
|
if (in_array($codicePart,$codiciPartecipanti) !== false) { |
|
$coefficienti[$codiceCriterio][$codiceUtente][$codicePart] = $coef; |
|
} |
|
} |
|
} |
|
} |
|
} |
|
} |
|
} |
|
return $coefficienti; |
|
} |
|
|
|
public function getSommaMediaPunteggiCoefficienti($codice_criterio, $codice_utente = NULL, $output = NULL) |
|
{ |
|
$valutazioni = $this->getCoefficientiValutazione($codice_criterio); |
|
$criterio = $this->getCriteri($codice_criterio)[0]; |
|
$commissari = $this->getCommissari("commissione", $codice_utente); |
|
$settings = $this->getManagerCommissione("commissione")->getInfo(); |
|
$partecipanti = $this->getPartecipanti(TRUE); |
|
$somme = []; |
|
$medie = []; |
|
$normalizzazione = []; |
|
$count = 0; |
|
if (!empty($commissari)) { |
|
foreach ($commissari as $commissario) { |
|
foreach ($partecipanti as $partecipante) { |
|
if (isset($valutazioni[$commissario["codice_utente"]][$partecipante["codice"]])) { |
|
$count++; |
|
if (!isset($somme[$partecipante["codice"]])) { |
|
$somme[$partecipante["codice"]] = 0; |
|
} |
|
$somme[$partecipante["codice"]] += $valutazioni[$commissario["codice_utente"]][$partecipante["codice"]]; |
|
} |
|
} |
|
} |
|
if ($count == count($commissari) * count($partecipanti)) { |
|
foreach ($partecipanti as $partecipante) { |
|
$medie[$partecipante["codice"]] = $somme[$partecipante["codice"]] / count($commissari); |
|
if ($settings["riparametra"] == "S") { |
|
$normalizzazione = tuttogareMath::proporzionale($medie, 1, null); |
|
} else { |
|
$normalizzazione = $medie; |
|
} |
|
} |
|
if (!empty($normalizzazione)) { |
|
foreach ($normalizzazione as $partecipante => $coef) { |
|
if ($settings["arrotonda"] == "S") { |
|
$punteggi[$partecipante] = number_format($coef * $criterio["peso"], $criterio["decimali"]); |
|
} else { |
|
$punteggi[$partecipante] = truncate($coef * $criterio["peso"], $criterio["decimali"]); |
|
} |
|
} |
|
switch ($output) { |
|
case "somme": |
|
$return = $somme; |
|
break; |
|
case "medie": |
|
$return = $medie; |
|
break; |
|
case "normalizzazione": |
|
$return = $normalizzazione; |
|
break; |
|
case "punteggi": |
|
$return = $punteggi; |
|
break; |
|
default: |
|
$return = ["somme" => $somme, "medie" => $medie, "normalizzazione" => $normalizzazione, "punteggi" => $punteggi]; |
|
} |
|
} |
|
} |
|
} |
|
return $return ?? false; |
|
} |
|
|
|
public function getManagerAvvisi() |
|
{ |
|
if (empty($this->managerAvvisi)) { |
|
$avvisiProcedura = new avvisiProcedura($_SESSION["ente"]->codice, "gare", $this->info["codice"], $this->round["codice"]); |
|
if (!empty($avvisiProcedura)) { |
|
$this->managerAvvisi = $avvisiProcedura; |
|
} |
|
} |
|
return $this->managerAvvisi; |
|
} |
|
|
|
public function getManagerCommissione($tipologia) |
|
{ |
|
$manager = new Commissione("gare", $this->round["codice"], $tipologia); |
|
if (!empty($manager)) { |
|
$this->managerCommissione = $manager; |
|
} |
|
return $this->managerCommissione; |
|
} |
|
|
|
public function getManagerIncarichi() |
|
{ |
|
$manager = new Incarichi("gare", $this->info["codice"]); |
|
if (!empty($manager)) { |
|
$this->managerIncarichi = $manager; |
|
} |
|
return $this->managerIncarichi; |
|
} |
|
|
|
public function getManagerDGUE() |
|
{ |
|
$manager = new DGUE("gare", $this->round["codice"]); |
|
if (!empty($manager)) { |
|
$this->managerDGUE = $manager; |
|
} |
|
return $this->managerDGUE; |
|
} |
|
|
|
public function getDestinatari($ignoreStato = false) { |
|
$return = []; |
|
if (!empty($this->lotto)) { |
|
$lotti = [$this->lotto]; |
|
} else { |
|
$lotti = $this->getLotti(); |
|
} |
|
foreach($lotti AS $lotto) { |
|
if ($this->setLotto($lotto["codice"])) { |
|
$destinatari = $this->getPartecipanti() ?? []; |
|
if ($this->info["stato"] < 21 || $ignoreStato) { |
|
$destinatari = array_merge($destinatari, ($this->getInvitati() ?? [])); |
|
} |
|
$tmp = array_column($destinatari,"codice_operatore"); |
|
if (!empty($tmp)) { |
|
$return = array_merge($return,$tmp); |
|
} |
|
if ($this->info["stato"] < 21 || $ignoreStato) { |
|
$manuali = $this->getInvitatiManuali(); |
|
if (!empty($manuali)) { |
|
$return = array_merge($return,array_column($manuali,"pec")); |
|
} |
|
} |
|
} |
|
} |
|
if (count($lotti) > 1) { |
|
$this->lotto = null; |
|
} |
|
$return = array_unique($return); |
|
return $return; |
|
} |
|
|
|
public function addDGUERequest() |
|
{ |
|
if (!$this->checkLock("buste") && |
|
$this->db->go("SELECT codice FROM b_gare_richieste WHERE titolo = 'DGUE' AND codice_round = :codice_round AND busta = 'amministrativa'", [":codice_round" => $this->round["codice"]]) |
|
->rowCount() == 0 |
|
) { |
|
$richiesta = []; |
|
$richiesta["codice_round"] = $this->round["codice"]; |
|
$richiesta["ordinamento"] = 0; |
|
$richiesta["titolo"] = "DGUE"; |
|
$richiesta["descrizione"] = __("Documento di Gara Unico Europeo"); |
|
$richiesta["controllo"] = "F"; |
|
$richiesta["busta"] = "amministrativa"; |
|
$this->saveRichiesta($richiesta); |
|
} |
|
} |
|
|
|
public function deleteDGUERequest() |
|
{ |
|
if (!$this->checkLock("buste")) { |
|
$this->db->go("DELETE FROM b_gare_richieste WHERE titolo = 'DGUE' AND codice_round = :codice_round AND busta = 'amministrativa'", [":codice_round" => $this->round["codice"]]); |
|
} |
|
} |
|
|
|
|
|
public function lottiMisti() { |
|
return (!empty($this->getLottiMP()) && !empty($this->getLottiOEPV())); |
|
} |
|
|
|
public function getDomandeElaborazione() { |
|
global $config; |
|
$tmp = jsonToArray($config["jsonFolder"]."/gare-elaborazione.json"); |
|
$return = []; |
|
$economici = (!empty($this->getLottiMP())); |
|
$tecnici = (!empty($this->getLottiOEPV())); |
|
$multiLotto = (count($this->getLotti()) > 1); |
|
$soglia = $this->getSogliaGara(); |
|
if (!empty($tmp)) { |
|
foreach($tmp AS $key => $domanda) { |
|
if ((empty($domanda["inizio"]) || strtotime($domanda["inizio"]) <= strtotime($this->info["timestamp_creazione"])) && (empty($domanda["fine"]) || strtotime($domanda["fine"]) >= strtotime($this->info["timestamp_creazione"]))) { |
|
$insert = true; |
|
if (!empty($domanda["procedureEscluse"]) && in_array($this->info["procedura"],$domanda["procedureEscluse"]) !== false) { |
|
$insert = false; |
|
} |
|
if (!empty($domanda["idNormeApplicazione"]) && in_array($this->normaRiferimento,$domanda["idNormeApplicazione"]) === false) { |
|
$insert = false; |
|
} |
|
if ($soglia == "sottosoglia" && !$domanda["sottosoglia"]) { |
|
$insert = false; |
|
} |
|
if ($soglia == "soprasoglia" && !$domanda["soprasoglia"]) { |
|
$insert = false; |
|
} |
|
if (($this->getModalita()["online"] && !$domanda["online"]) || (!$this->getModalita()["online"] && !$domanda["offline"])) { |
|
$insert = false; |
|
} |
|
if (($multiLotto && !$domanda["multi_lotto"]) || (!$multiLotto && !$domanda["mono_lotto"])) { |
|
$insert = false; |
|
} |
|
if (!empty($this->round["infoFase"]) && (($this->round["infoFase"]["graduatoria"] && !$domanda["graduatoria"]) || (!$this->round["infoFase"]["graduatoria"] && !$domanda["istanza_semplice"]))) { |
|
$insert = false; |
|
} |
|
if (!empty($domanda["tipologieEscluse"]) && in_array($this->info["tipologia"],$domanda["tipologieEscluse"]) !== false) { |
|
$insert = false; |
|
} |
|
if (!empty($domanda["criteri"]) && $insert) { |
|
$insert = false; |
|
if ($economici && in_array("prezzo",$domanda["criteri"]) !== false) { |
|
$insert = true; |
|
} |
|
if ($tecnici && in_array("vantaggiosa",$domanda["criteri"]) !== false) { |
|
$insert = true; |
|
} |
|
} |
|
if ($this->privata && !$domanda["privata"]) { |
|
$insert = false; |
|
} |
|
if($this->quickPanel && ! $domanda["quickPanel"]) { |
|
$insert = false; |
|
} |
|
if (!empty($domanda["impostazioneModuloNecessaria"])) { |
|
foreach($domanda["impostazioneModuloNecessaria"] AS $set => $value) { |
|
$v = settingsManager::getValue($set) ?? null; |
|
if (empty($v) || $v !== $value) { |
|
$insert = false; |
|
break; |
|
} |
|
} |
|
} |
|
if ($insert) { |
|
$return[$key] = $domanda; |
|
} |
|
} |
|
} |
|
} |
|
return $return; |
|
} |
|
|
|
public function getDatiMinimi() { |
|
$datiMinimi = $this->db->go("SELECT * FROM b_impostazioni_dati_minimi WHERE attivo = 'S' AND soft_delete = 'N'")->fetchAll(PDO::FETCH_ASSOC); |
|
$return = []; |
|
if (!empty($datiMinimi)) { |
|
foreach($datiMinimi AS $domanda) { |
|
$tipologie = json_decode($domanda["tipologie"],true); |
|
if (in_array($this->info["tipologia"],$tipologie) !== false) { |
|
$return[$domanda["codice"]] = $domanda; |
|
} |
|
} |
|
} |
|
return $return; |
|
} |
|
|
|
public function getRisposteElaborazione() { |
|
return json_decode($this->getExtraInfo()["round"]["elaborazione"] ?? "",true); |
|
} |
|
|
|
public function modalitaLotti() { |
|
return $this->getRisposteElaborazione()["modalita_lotti"] ?? "libera"; |
|
} |
|
|
|
public function getRisposteDatiMinimi() { |
|
return json_decode($this->getExtraInfo()["round"]["datiMinimi"] ?? "",true); |
|
} |
|
|
|
public function accessoAttiAutomatico() { |
|
$risposta = $this->getRisposteElaborazione()["accessoArt36"] ?? "N"; |
|
return ($risposta == "S"); |
|
} |
|
|
|
public function abilitaBusteSecretate() { |
|
return $this->accessoAttiAutomatico(); |
|
} |
|
|
|
public function usaGraduatoria() { |
|
$return = true; |
|
$risposte = $this->getRisposteElaborazione(); |
|
if (!empty($risposte["usaGraduatoria"]) && $risposte["usaGraduatoria"] == "N") { |
|
$return = false; |
|
} |
|
return $return; |
|
} |
|
|
|
public function validaElaborazione() { |
|
$domandeElaborazione = $this->getDomandeElaborazione(); |
|
$return = []; |
|
if (!empty($domandeElaborazione)) { |
|
$risposteElaborazione = $this->getRisposteElaborazione(); |
|
foreach($domandeElaborazione AS $idDomanda => $infoDomanda) { |
|
if ($infoDomanda["obbligatorio"] && (!isset($risposteElaborazione[$idDomanda]) || $risposteElaborazione[$idDomanda] === "")) { |
|
$return[$idDomanda] = $infoDomanda["quesito"]; |
|
} else { |
|
if (!empty($infoDomanda["incompatibilita"])) { |
|
foreach($infoDomanda["incompatibilita"] AS $idIncompatibile => $valoriIncompatibili) { |
|
if (isset($risposteElaborazione[$idIncompatibile])) { |
|
if (!is_array($valoriIncompatibili)) { |
|
$valoriIncompatibili = [$valoriIncompatibili]; |
|
} |
|
if (in_array($risposteElaborazione[$idIncompatibile],$valoriIncompatibili)) { |
|
$return[$idDomanda] = $domandeElaborazione[$idIncompatibile]["quesito"] . ":" . __("Risposta incompatibile"); |
|
} |
|
} |
|
} |
|
} |
|
} |
|
} |
|
} |
|
if (!$_SESSION["utente"]->fromHere() && $_SESSION["ente"]->getInfo()["permit_cross"] == "N") { |
|
$domandeMinimi = $this->getDatiMinimi(); |
|
if (!empty($domandeMinimi)) { |
|
$risposteElaborazione = $this->getRisposteDatiMinimi(); |
|
foreach($domandeMinimi AS $idDomanda => $infoDomanda) { |
|
if ($infoDomanda["obbligatorio"] == "S" && (!isset($risposteElaborazione[$idDomanda]) || $risposteElaborazione[$idDomanda] === "" || (is_array($risposteElaborazione[$idDomanda]) && empty($risposteElaborazione[$idDomanda])))) { |
|
$return[$idDomanda] = $infoDomanda["titolo"]; |
|
} |
|
} |
|
} |
|
} |
|
if (empty($return)) { |
|
$return = true; |
|
} |
|
return $return; |
|
} |
|
|
|
public function inizializzaFase($key,$fase) { |
|
|
|
$continua = true; |
|
$infoRda = $this->getExtraInfo()["gara"]["rda"] ?? null; |
|
$rounds = $this->getRounds(); |
|
if (!$fase["ripetibile"] && !empty($rounds)) { |
|
foreach($rounds AS $round) { |
|
if ($round["id"] == $key) { |
|
$continua = false; |
|
} |
|
} |
|
} |
|
if ($continua) { |
|
$lotti = $this->getLotti(); |
|
if (!empty($lotti) || $this->quickAvailable) { |
|
$numero = 1; |
|
if (!empty($rounds)) { |
|
foreach($rounds AS $round) { |
|
$numero = $round["numero"] + 1; |
|
} |
|
} |
|
$newRound = []; |
|
$newRound["id"] = $key; |
|
$newRound["codice_gara"] = $this->info["codice"]; |
|
$newRound["numero"] = $numero; |
|
$newRound["pubblica"] = 0; |
|
$salva = new salva(); |
|
$salva->debug = false; |
|
|
|
$salva->nome_tabella = "b_gare_round"; |
|
$salva->operazione = "INSERT"; |
|
$salva->oggetto = $newRound; |
|
$codice_round = $salva->save(); |
|
if ($codice_round) { |
|
if ($numero > 1) { |
|
$this->db->go("UPDATE b_gare SET stato = 10 WHERE codice = :codice",[":codice"=>$this->info["codice"]]); |
|
$statiConclusivi = implode(",",self::statiTermineProcedura()); |
|
$this->db->go("UPDATE b_gare_lotti SET stato = 0 WHERE codice_gara = :codice AND stato NOT IN ({$statiConclusivi})",[":codice"=>$this->info["codice"]]); |
|
if (!isset($lotti)) { |
|
$lotti = $this->getLotti(); |
|
} |
|
$invitati = []; |
|
foreach($lotti AS $lotto) { |
|
if (!in_array($lotto["stato"],gara::statiTermineProcedura())) { |
|
$this->setLotto($lotto["codice"]); |
|
$partecipanti = $this->getPartecipanti(TRUE); |
|
if (!empty($partecipanti)) { |
|
$invitati[$lotto["codice"]] = array_column($partecipanti,"codice_operatore"); |
|
$invitati[$lotto["codice"]] = array_filter($invitati[$lotto["codice"]]); |
|
} |
|
} |
|
} |
|
$this->lotto = null; |
|
} |
|
$this->round = $this->getRounds($codice_round)[0] ?? null; |
|
$this->db->go("UPDATE b_gare SET fase_attiva = :numero WHERE codice = :codice",[":numero"=>$numero,":codice"=>$this->info["codice"]]); |
|
if (!empty($invitati)) { |
|
foreach($invitati AS $codice_lotto => $operatori) { |
|
foreach($operatori AS $oe) { |
|
$this->saveInvito($codice_lotto,$oe,"N",false); |
|
} |
|
} |
|
} |
|
if ($fase["graduatoria"]) { |
|
$formati = []; |
|
$soloPrezzo = true; |
|
if (!isset($lotti)) { |
|
$lotti = $this->getLotti(); |
|
} |
|
if (!empty($lotti)) { |
|
foreach($lotti AS $lotto) { |
|
$formati[] = $lotto["formato"]; |
|
if ($lotto["criterio"] != "prezzo") { |
|
$soloPrezzo = false; |
|
} |
|
} |
|
$formati = array_unique($formati); |
|
if (count($formati) === 1 && $soloPrezzo) { |
|
$formato = reset($formati); |
|
if (!empty($formato) && $formato != "nulla") { |
|
$criterio = []; |
|
$criterio["codice"] = ""; |
|
$criterio["denominazione"] = __(self::formatiOffertaDisponibili()[$formato] ?? "Ribasso"); |
|
$criterio["descrizione"] = __("{$criterio["denominazione"]} sull'importo a base di gara"); |
|
$criterio["economico"] = "S"; |
|
$criterio["auto"] = (in_array($formato,["ribasso","rialzo"])) ? "P" : "I"; |
|
$criterio["peso"] = "100"; |
|
$criterio["decimali"] = "3"; |
|
$criterio["tipologia"] = "N"; |
|
$this->saveCriterio($criterio); |
|
} |
|
} |
|
} |
|
} |
|
if (!empty($infoRda) && $infoRda["remote"]) { |
|
if (isset($_SESSION["ente"]->erpConnector) && method_exists($_SESSION["ente"]->erpConnector,"aggiungiInfoRDAaGara")) { |
|
$_SESSION["ente"]->erpConnector->aggiungiInfoRDAaGara($this); |
|
} |
|
}elseif($codici_rda = $this->getRda()){ |
|
$this->aggiungiInfoRDAaGara($codici_rda); |
|
} |
|
$this->addToLog("INSERT","Creata fase: " . $key); |
|
return $codice_round; |
|
} |
|
} |
|
} |
|
return false; |
|
} |
|
|
|
public function aggiungiInfoRDAaGara(Array $codici_rda = []) |
|
{ |
|
|
|
if(!empty($codici_rda)){ |
|
|
|
$tmpCriteri = $tmpArticoli = []; |
|
$count = 0; |
|
$criteriDisponibili = $this->getCriteriEconomici(); |
|
|
|
|
|
foreach ($codici_rda as $codice_rda) { |
|
$rda = rda::init($codice_rda, ['articoli', 'criteri']); |
|
|
|
if($rda->info['codice']){ |
|
|
|
if($rda->relazioni['articoli']){ |
|
foreach ($rda->relazioni['articoli'] as $articolo) { |
|
$count++; |
|
$tmpArticoli["i_{$count}"] = [ |
|
"titolo" => $articolo["denominazione"], |
|
"descrizione" => $articolo["denominazione"], |
|
"unita" => "UdM", |
|
"tipo" => "misura", |
|
"quantita" => $articolo["quantita"] |
|
]; |
|
} |
|
} |
|
|
|
if($rda->relazioni['criteri']){ |
|
foreach ($rda->relazioni['criteri'] as $criterio) { |
|
if ($criterio["economico"] == "N") { |
|
$tmpCriteri[] = [ |
|
'codice' => '', |
|
'denominazione' => $criterio['denominazione'], |
|
'descrizione' => '', |
|
'economico' => $criterio['economico'], |
|
'auto' => '', |
|
'peso' => $criterio['peso'], |
|
'decimali' => '3', |
|
'tipologia' => $criterio["economico"] == 'S' ? 'N' : 'Q' |
|
]; |
|
} |
|
} |
|
} |
|
|
|
$rda->relazioni['allegato'] = filesManager::listFiles($rda->info["codice"],"rda","A",0,false); |
|
if (!empty($rda->relazioni["allegato"])) { |
|
foreach($rda->relazioni["allegato"] as $allegato) { |
|
$allegato = filesManager::fileInfo($allegato['codice'], $allegato['name'], $allegato['sourceID'], $allegato['sourceType']); |
|
filesManager::saveFileFromBuffer(NULL, base64_decode($allegato["content"]),$this->round["codice"],"gare-reserved",$allegato["titolo"]); |
|
} |
|
} |
|
} |
|
} |
|
|
|
if(!empty($tmpArticoli)){ |
|
foreach ($criteriDisponibili as $criterio) { |
|
if (!empty($criterio["auto"])) { |
|
$criterio["tipologia"] = "E"; |
|
$this->saveCriterio($criterio); |
|
$this->saveVociEP($criterio["codice"],$tmpArticoli); |
|
break; |
|
} |
|
} |
|
} |
|
|
|
if(!empty($tmpCriteri)){ |
|
foreach ($tmpCriteri as $tmpCriterio) { |
|
$this->saveCriterio($tmpCriterio); |
|
} |
|
} |
|
|
|
} |
|
} |
|
|
|
public function selfFill() { |
|
if ($this->info["stato"] >= 10 && $this->activeRound) { |
|
if (!$this->usaGraduatoria()) { |
|
$criteri = $this->getCriteri(); |
|
if (!empty($criteri)) { |
|
foreach($criteri AS $criterio) { |
|
$this->deleteCriterio($criterio["codice"]); |
|
} |
|
} |
|
} |
|
$risposte = $this->getRisposteElaborazione(); |
|
if (!empty($risposte["slotGiustificativi"])) { |
|
$titolo =__("Giustificativi manodopera"); |
|
$richieste = $this->getRichieste(); |
|
$element = null; |
|
if (!empty($richieste)) { |
|
foreach($richieste AS $tmp) { |
|
if ($tmp["titolo"] == $titolo) { |
|
$element = $tmp["codice"]; |
|
break; |
|
} |
|
} |
|
} |
|
if ($risposte["slotGiustificativi"] === "S" && empty($element)) { |
|
$richiesta = []; |
|
$richiesta["codice_round"] = $this->round["codice"]; |
|
$richiesta["busta"] = "economica"; |
|
$richiesta["titolo"] = $titolo; |
|
$richiesta["descrizione"] = __("Se applicabile, utilizza questo spazio per caricare i tuoi giustificativi per il ribasso della manodopera"); |
|
$richiesta["controllo"] = "N"; |
|
$richiesta["ordinamento"] = 90; |
|
$richiesta["locked"] = "N"; |
|
$this->saveRichiesta($richiesta); |
|
} else if ($risposte["slotGiustificativi"] === "N" && !empty($element)) { |
|
$this->deleteRichiesta($element); |
|
} |
|
} |
|
} |
|
} |
|
|
|
public function getManagerRichieste() |
|
{ |
|
$manager = new richiesteOE("gare", $this->info["codice"], $this->lotto["codice"]); |
|
if (!empty($manager)) { |
|
$this->managerRichieste = $manager; |
|
} |
|
return $this->managerRichieste; |
|
} |
|
|
|
public function getManagerPubblicita() |
|
{ |
|
$manager = new pubblicitaLegale("gare", $this->info["codice"], $this->round["codice"]); |
|
if (!empty($manager)) { |
|
$this->managerPubblicita = $manager; |
|
} |
|
return $this->managerPubblicita; |
|
} |
|
|
|
public function getChiarimenti(int $codice = NULL) |
|
{ |
|
$bind = [":codice_round" => $this->round["codice"]]; |
|
$sql_chiarimenti = "SELECT b_gare_chiarimenti.* |
|
FROM b_gare_chiarimenti |
|
WHERE b_gare_chiarimenti.codice_round = :codice_round "; |
|
if (!empty($codice)) { |
|
$sql_chiarimenti .= " AND b_gare_chiarimenti.codice = :codice "; |
|
$bind[":codice"] = $codice; |
|
} |
|
$sql_chiarimenti .= " ORDER BY b_gare_chiarimenti.timestamp "; |
|
$tmp = $this->db->go($sql_chiarimenti, $bind)->fetchAll(PDO::FETCH_ASSOC); |
|
$return = []; |
|
if (!empty($tmp)) { |
|
$i = 0; |
|
foreach ($tmp as $t) { |
|
$i++; |
|
$t["count"] = $i; |
|
$oeInfo = oeManager::getOE($t["codice_richiedente"]); |
|
if(! empty($oeInfo["ragione_sociale"])) { $t["ragione_sociale"] = $oeInfo["ragione_sociale"]; } |
|
$return[] = $t; |
|
} |
|
} |
|
if (!empty($codice) && !empty($return)) { |
|
$return = $return[0]; |
|
} |
|
return $return; |
|
} |
|
|
|
public function getSopralluoghi(int $codice = NULL) |
|
{ |
|
$bind = [":codice_round" => $this->round["codice"]]; |
|
$sql_sopralluoghi = "SELECT b_gare_sopralluogo.* |
|
FROM b_gare_sopralluogo |
|
WHERE b_gare_sopralluogo.codice_round = :codice_round "; |
|
if (!empty($codice)) { |
|
$sql_sopralluoghi .= " AND b_gare_sopralluogo.codice = :codice "; |
|
$bind[":codice"] = $codice; |
|
} |
|
$sql_sopralluoghi .= " ORDER BY b_gare_sopralluogo.timestamp "; |
|
$tmp = $this->db->go($sql_sopralluoghi, $bind)->fetchAll(PDO::FETCH_ASSOC); |
|
$return = []; |
|
if (!empty($tmp)) { |
|
foreach ($tmp as $t) { |
|
$oeInfo = oeManager::getOE($t["codice_richiedente"]); |
|
$t["ragione_sociale"] = $oeInfo["ragione_sociale"] ?? "Ragione sociale non presente"; |
|
$return[] = $t; |
|
} |
|
} |
|
if (!empty($codice) && !empty($return)) { |
|
$return = $return[0]; |
|
} |
|
return $return; |
|
} |
|
public function getAvvalimento($partecipante) |
|
{ |
|
if (!empty($this->lotto)) { |
|
$bind = [":codice_round" => $this->round["codice"], ":codice_partecipante" => $partecipante,":codice_lotto" => $this->lotto["codice"]]; |
|
$sql = "SELECT r_avvalimenti_gare.*, r_raggruppamenti_gare.ragione_sociale AS nome_padre FROM r_avvalimenti_gare JOIN r_partecipanti_gare |
|
ON r_avvalimenti_gare.codice_padre = r_partecipanti_gare.codice |
|
LEFT JOIN r_raggruppamenti_gare ON r_avvalimenti_gare.identifier_raggruppamento = r_raggruppamenti_gare.identifier |
|
WHERE r_partecipanti_gare.codice_round = :codice_round AND r_partecipanti_gare.codice = :codice_partecipante AND codice_lotto = :codice_lotto"; |
|
return $this->db->go($sql, $bind)->fetchAll(PDO::FETCH_ASSOC); |
|
} |
|
} |
|
public function getRaggruppamento($partecipante) |
|
{ |
|
if (!empty($this->lotto)) { |
|
$bind = [":codice_round" => $this->round["codice"], ":codice_partecipante" => $partecipante,":codice_lotto" => $this->lotto["codice"]]; |
|
$sql = "SELECT r_raggruppamenti_gare.* FROM r_raggruppamenti_gare JOIN r_partecipanti_gare |
|
ON r_raggruppamenti_gare.codice_padre = r_partecipanti_gare.codice |
|
WHERE r_partecipanti_gare.codice_round = :codice_round AND r_partecipanti_gare.codice = :codice_partecipante AND codice_lotto = :codice_lotto"; |
|
return $this->db->go($sql, $bind)->fetchAll(PDO::FETCH_ASSOC); |
|
} |
|
} |
|
|
|
public function getSorgenteInvitati() : String { |
|
$return = __DIR__ . "/inviti/sorgenti/"; |
|
$source = "default.php"; |
|
$derivazione = $this->getProcedura()["derivazione"] ?? null; |
|
if (!empty($derivazione)) { |
|
switch($derivazione) { |
|
case "accordo": |
|
$source = "accordo.php"; |
|
break; |
|
default: |
|
throw new Exception("Derivazione sconosciuta", 404); |
|
break; |
|
} |
|
} else { |
|
if (($this->round["infoFase"]["graduatoria"] ?? false) && $this->round["numero"] > 1) { |
|
$source = "indagine.php"; |
|
} |
|
} |
|
$return .= $source; |
|
return $return; |
|
} |
|
|
|
public function sorteggiaInvitati(String $tokenOE, String $lotto, Int $partecipanti, String $descrizione = "", Array $esclusioni = []) : Bool { |
|
$estrazione = oeManager::getEstrazione("gare", $this->info["codice"], $lotto); |
|
if (empty($estrazione)) { |
|
if (!empty($lotto)) { |
|
$lotti = [$lotto]; |
|
} else { |
|
$lotti = array_column($this->getLotti(), "codice"); |
|
} |
|
$continua = true; |
|
foreach ($lotti as $checkLotto) { |
|
if ($this->setLotto($checkLotto)) { |
|
if (!empty($this->countInvitati()) && $tokenOE != "indagine") { |
|
$continua = false; |
|
break; |
|
} |
|
} else { |
|
$continua = false; |
|
break; |
|
} |
|
} |
|
if ($continua) { |
|
unset($this->lotto); |
|
$continua = false; |
|
$oeManager = new oeManager; |
|
if ($tokenOE == "accordo") { |
|
$accordo = accordiQuadro::init($this->info["derivazione"]); |
|
if (!empty($accordo)) { |
|
$aggiudicatari = $accordo->getAggiudicatari(); |
|
if (!empty($aggiudicatari)) { |
|
$ooee = array_column($aggiudicatari, "codice_operatore"); |
|
$ooee = array_filter($ooee); |
|
if (!empty($ooee)) { |
|
$continua = true; |
|
$oeManager->operatoriSorteggio = $ooee; |
|
} |
|
} |
|
} |
|
} else if ($tokenOE == "indagine") { |
|
$invitati = $this->getInvitati($lotto); |
|
if (!empty($invitati)) { |
|
$ooee = array_column($invitati, "codice_operatore"); |
|
$ooee = array_filter($ooee); |
|
if (!empty($ooee)) { |
|
$continua = true; |
|
$deleteInvitati = true; |
|
$oeManager->operatoriSorteggio = $ooee; |
|
} |
|
} |
|
} else { |
|
$continua = true; |
|
$oeManager->setFilters($_SESSION["exportoperatoriSettings"][$tokenOE]); |
|
} |
|
if ($continua) { |
|
$esito = $oeManager->eseguiEstrazione($_SESSION["ente"]->codice, $partecipanti, $esclusioni, $descrizione, "gare", true, $this->info["codice"], $lotto); |
|
if (is_numeric($esito)) { |
|
if (!empty($_SESSION["exportoperatoriSettings"][$tokenOE]["elenco"])) { |
|
$filtroElenco = explode("|", $_SESSION["exportoperatoriSettings"][$tokenOE]["elenco"]); |
|
if (count($filtroElenco) == 2) { |
|
$sources = oeManager::tipiElenco(); |
|
$tabellePartecipanti = oeManager::tabelleElenco(); |
|
if (in_array($filtroElenco[0], array_keys($sources)) !== false && !empty($tabellePartecipanti[$filtroElenco[0]])) { |
|
$tipo_elenco = $filtroElenco[0]; |
|
$codice_elenco = $filtroElenco[1]; |
|
$this->saveExtraInfo("tipo_elenco_invito", $tipo_elenco, "round"); |
|
$this->saveExtraInfo("codice_elenco_invito", $codice_elenco, "round"); |
|
} |
|
} |
|
} |
|
$estrazione = oeManager::getEstrazione("gare", $this->info["codice"], $lotto); |
|
$relazioni = $oeManager->getRelazioniEstrazione($estrazione["codice"]); |
|
if (!empty($deleteInvitati)) { |
|
$this->db->go("DELETE FROM r_inviti_gare WHERE codice_round = :codice_round AND codice_lotto = :lotto ",[":codice_round"=>$this->round["codice"],":lotto"=>$lotto]); |
|
} |
|
foreach ($relazioni as $relazione) { |
|
if ($relazione["selezionato"] == "S" || $relazione["selezionato"] == "A") { |
|
$this->saveInvito($lotto, $relazione["codice_operatore"], true, true); |
|
} |
|
} |
|
ob_start(); |
|
oeManager::printReportEstrazione($estrazione, $relazioni, true); |
|
$report = ob_get_clean(); |
|
$report = "<html><style>body{font-size:10px;}td,th{padding:5px;border:1pxsolid#AAA}th{background-color:#DDD}tr.odd{background-color:#DDD;}table{width:100%}</style><body>{$report}</body></html>"; |
|
$pdf = documentConverter::getPDFWithWKHTML($report,"A4","landscape"); |
|
$sezione = ($this->accessoAttiAutomatico()) ? "gare-accessoatti" : "gare-reserved"; |
|
filesManager::saveFileFromBuffer(null,$pdf,$this->round["codice"],$sezione,__("Verbale estrazione") . " - " . date("Y-m-d H:i:s")); |
|
return true; |
|
} else { |
|
throw new Exception("Errore nel sorteggio"); |
|
} |
|
} else { |
|
throw new Exception("Errore identificazione Operatori"); |
|
} |
|
} else { |
|
throw new Exception("Invitati già selezionati"); |
|
} |
|
} else { |
|
throw new Exception("Estrazione già presente"); |
|
} |
|
return false; |
|
} |
|
|
|
public function saveInvito($lotto,$operatore,$sorteggio,$updateContatori = true) { |
|
$insert = $this->db->prepare("INSERT INTO r_inviti_gare (codice_operatore,codice_round,codice_lotto,sorteggio,utente_modifica) VALUES (:oe,:fase,:lotto,:sorteggio,:utente) "); |
|
$oe = oeManager::getOE($operatore); |
|
$insert->bindValue(":fase",$this->round["codice"]); |
|
$insert->bindValue(":lotto",$lotto); |
|
$insert->bindValue(":sorteggio",($sorteggio ? "S" : "N")); |
|
$insert->bindValue(":utente",$_SESSION["utente"]->codice ?? -1); |
|
if (!empty($oe)) { |
|
$insert->bindValue(":oe",$oe["codice"]); |
|
$insert->execute(); |
|
$this->addToLog("INSERT",__("Invito operatore") . ":" . $oe["ragione_sociale"]); |
|
if ($updateContatori) { |
|
$invito = []; |
|
$invito["codice_ente"] = $_SESSION["ente"]->codice; |
|
$invito["contesto"] = "gare"; |
|
$invito["codice_elemento"] = $this->round["codice"]; |
|
$invito["data_invito"] = date("d-m-Y"); |
|
$invito["sub_elemento"] = $lotto; |
|
$extraInfo = $this->getExtraInfo(); |
|
if (!empty($extraInfo["round"]["tipo_elenco_invito"])) { |
|
$invito["tipo_elenco"] = $extraInfo["round"]["tipo_elenco_invito"]; |
|
$invito["codice_elenco"] = $extraInfo["round"]["codice_elenco_invito"]; |
|
} |
|
$invito["codice_fiscale_operatore"] = $oe["codice_fiscale_impresa"]; |
|
$soa = []; |
|
$tmpSoa = $this->getSOA(); |
|
if (!empty($tmpSoa)) { |
|
foreach($tmpSoa AS $categoria) { |
|
$classifica = getClassificaSOAFromImporto($categoria["importo"]); |
|
$soa[] = ["categoria"=>$categoria["codice_categoria"],"classifica"=>$classifica]; |
|
} |
|
} |
|
$progettazione = []; |
|
$tmpProg = $this->getProgettazione(); |
|
if (!empty($tmpProg)) { |
|
$progettazione = array_column($tmpProg,"codice_categoria"); |
|
} |
|
oeManager::saveInvito($invito,$this->getCategorieMerceologiche(),$soa,$progettazione); |
|
} |
|
return true; |
|
} |
|
return false; |
|
} |
|
|
|
public function saveTempInvito($lotto,$codice_fiscale,$denominazione,$pec,$updateContatori = true) { |
|
$invito = []; |
|
$invito["contesto"] = "gare"; |
|
$invito["codice_elemento"] = $this->round["codice"]; |
|
$invito["sub_elemento"] = $lotto; |
|
$invito["codice_fiscale_operatore"] = $codice_fiscale; |
|
$invito["denominazione"] = $denominazione; |
|
$invito["pec"] = $pec; |
|
$invito["attivo"] = "S"; |
|
$salva = new salva(); |
|
$salva->debug = false; |
|
$salva->nome_tabella = "temp_inviti"; |
|
$salva->operazione = "INSERT"; |
|
$salva->oggetto = $invito; |
|
$codice_invito = $salva->save(); |
|
if (!empty($codice_invito)) { |
|
$this->addToLog("INSERT",__("Invito operatore manuale") . ":" . $denominazione); |
|
if ($updateContatori) { |
|
$invito = []; |
|
$invito["codice_ente"] = $_SESSION["ente"]->codice; |
|
$invito["contesto"] = "gare"; |
|
$invito["codice_elemento"] = $this->round["codice"]; |
|
$invito["data_invito"] = date("d-m-Y"); |
|
$invito["sub_elemento"] = $lotto; |
|
$invito["codice_fiscale_operatore"] = $codice_fiscale; |
|
oeManager::saveInvito($invito,$this->getCategorieMerceologiche()); |
|
} |
|
return $codice_invito; |
|
} |
|
return false; |
|
|
|
} |
|
|
|
public function inviaInvito($destinatari) { |
|
$this->round = $this->getRounds($this->round["codice"])[0]; |
|
$this->round["infoFase"] = $this->getProcedura()["fasi"][$this->round["id"]] ?? []; |
|
if (strtotime($this->round["pubblicazione"]) < time()) { |
|
$editor = new editorManager("msg-invito-gara",0); |
|
$editor->vocabolario["ragione-sociale"] = $_SESSION["ente"]->getInfo()["denominazione"]; |
|
$editor->vocabolario["fase"] = $this->round; |
|
$editor->vocabolario["gara"] = $this->info; |
|
$editor->vocabolario["link"] = $_SESSION["config"]["link_sito"]."/gare/dettaglio.php?codice=".$this->info["codice"]; |
|
$editor->vocabolario["nome-sito"] = $_SESSION["config"]["nome_sito"]; |
|
$editor->vocabolario["description"] = $this->info["oggetto"]; |
|
$corpo = $editor->getModello(); |
|
$mailer = new Communicator(); |
|
$mailer->oggetto = __('Invito') . " - " . $this->info["oggetto"]; |
|
$mailer->corpo = $corpo; |
|
$mailer->codice_pec = $this->info["codice_pec"]; |
|
$mailer->comunicazione = true; |
|
$mailer->sezione = "gare"; |
|
$mailer->codice_gara = $this->info["codice"]; |
|
$mailer->coda = true; |
|
$mailer->destinatari = $destinatari; |
|
return $mailer->send(); |
|
} else{ |
|
$this->db->go("UPDATE b_gare SET invito_programmato = 'S' WHERE codice = :codice",[":codice"=>$this->info["codice"]]); |
|
return true; |
|
} |
|
} |
|
|
|
public function getInvitati($codice_lotto = null) |
|
{ |
|
$filtro_lotto = null; |
|
if (isset($codice_lotto)) { |
|
$filtro_lotto = $codice_lotto; |
|
} else if (!empty($this->lotto)) { |
|
$filtro_lotto = $this->lotto["codice"]; |
|
} |
|
$bind = [":codice_round" => $this->round["codice"]]; |
|
$sql = "SELECT * FROM r_inviti_gare WHERE codice_round = :codice_round "; |
|
if (isset($filtro_lotto)) { |
|
$bind[":codice_lotto"]=$filtro_lotto; |
|
$sql .= " AND (codice_lotto = :codice_lotto OR codice_lotto = 0) "; |
|
} |
|
return $this->db->go($sql, $bind)->fetchAll(PDO::FETCH_ASSOC); |
|
} |
|
|
|
public function getInvitatiManuali($codice_lotto = null) |
|
{ |
|
$filtro_lotto = null; |
|
if (isset($codice_lotto)) { |
|
$filtro_lotto = $codice_lotto; |
|
} else if (!empty($this->lotto)) { |
|
$filtro_lotto = $this->lotto["codice"]; |
|
} |
|
$bind = [":codice_round" => $this->round["codice"]]; |
|
$sql = "SELECT * FROM temp_inviti WHERE contesto = 'gare' AND attivo = 'S' AND codice_elemento = :codice_round "; |
|
if (isset($filtro_lotto)) { |
|
$bind[":codice_lotto"]=$filtro_lotto; |
|
$sql .= " AND (sub_elemento = :codice_lotto OR sub_elemento = 0) "; |
|
} |
|
return $this->db->go($sql, $bind)->fetchAll(PDO::FETCH_ASSOC); |
|
} |
|
|
|
public function countInvitati($codice_lotto = null) { |
|
return count($this->getInvitati($codice_lotto)) + count($this->getInvitatiManuali($codice_lotto)); |
|
} |
|
|
|
public function checkPartecipantiPresenti() { |
|
return !empty($this->db->go("SELECT codice FROM r_partecipanti_gare WHERE codice_round = :codice_round",[":codice_round"=>$this->round["codice"]])->rowCount()); |
|
} |
|
|
|
public function returnPartecipanti($filters = [],$all = false) { |
|
if (!empty($this->lotto)) { |
|
$bind = [":codice_round" => $this->round["codice"],":codice_lotto" => $this->lotto["codice"]]; |
|
$sql = "SELECT * FROM r_partecipanti_gare WHERE codice_round = :codice_round AND codice_lotto = :codice_lotto "; |
|
if (empty($all)) { |
|
$filters["conferma"] = "S"; |
|
} |
|
$where = []; |
|
$keys = array_keys(get_campi("r_partecipanti_gare")); |
|
foreach($keys AS $key) { |
|
if (isset($filters[$key])) { |
|
$where[] = "$key = :{$key}"; |
|
$bind[":{$key}"] = $filters[$key]; |
|
} |
|
} |
|
if (!empty($where)) { |
|
$sql .= " AND " . implode(" AND ",$where); |
|
} |
|
return $this->db->go($sql, $bind)->fetchAll(PDO::FETCH_ASSOC); |
|
} |
|
} |
|
|
|
public function getPartecipante($codice,$all = false) { |
|
return $this->returnPartecipanti(["codice"=>$codice],$all)[0] ?? null; |
|
} |
|
|
|
public function getPartecipantiForAnomalia() { |
|
$tmps = $this->returnPartecipanti(); |
|
$partecipanti = []; |
|
foreach($tmps AS $tmp) { |
|
if ($tmp["escluso"] == "N" || $tmp["esclusione_automatica"] == "S") { |
|
$partecipanti[] = $tmp; |
|
} |
|
} |
|
return $partecipanti; |
|
} |
|
|
|
public function getPartecipanti($ammessi = NULL,$valutazione = null) |
|
{ |
|
if (!empty($this->lotto)) { |
|
$filters = []; |
|
$all = false; |
|
if ($ammessi === TRUE) { |
|
$filters = ["escluso"=>"N"]; |
|
} else if ($ammessi === "ALL") { |
|
$all = true; |
|
} |
|
$return = $this->returnPartecipanti($filters,$all); |
|
if ($valutazione && !empty($return) && $this->getModalita()["online"]) { |
|
$tmp = $return; |
|
$return = []; |
|
$richieste = $this->getRichieste("tecnica"); |
|
if (!empty($richieste)) { |
|
$checkPunteggio = $this->db->prepare("SELECT b_gare_punteggi_partecipanti.codice FROM b_gare_punteggi_partecipanti |
|
JOIN b_gare_criteri_valutazione ON b_gare_punteggi_partecipanti.codice_criterio = b_gare_criteri_valutazione.codice |
|
WHERE codice_partecipante = :partecipante AND b_gare_criteri_valutazione.economico = 'N'"); |
|
foreach($tmp AS $partecipante) { |
|
$checkPunteggio->execute([":partecipante"=>$partecipante["codice"]]); |
|
if ($checkPunteggio->rowCount() > 0) { |
|
$return[$partecipante["codice"]] = $partecipante; |
|
} else { |
|
foreach($richieste AS $richiesta) { |
|
$busta = $this->getBusta($partecipante["codice"],$richiesta["codice"]); |
|
if (!empty($busta) && $busta["open"] == "S") { |
|
$return[$partecipante["codice"]] = $partecipante; |
|
break; |
|
} |
|
} |
|
} |
|
} |
|
$return = array_values($return); |
|
} |
|
} |
|
return $return; |
|
} |
|
} |
|
|
|
public function getGraduatoria($ammessi = NULL) |
|
{ |
|
$partecipanti = []; |
|
$tmp = $this->getPartecipanti($ammessi); |
|
if (!empty($tmp)) { |
|
$ammessi = []; |
|
$esclusi = []; |
|
foreach($tmp AS $partecipante) { |
|
if ($partecipante["escluso"] == "N") { |
|
$ammessi[] = $partecipante; |
|
} else { |
|
$esclusi[] = $partecipante; |
|
} |
|
} |
|
if (!empty($ammessi)) { |
|
usort($ammessi, "sortPartecipantiTotale"); |
|
} |
|
if (!empty($esclusi)) { |
|
usort($esclusi, "sortPartecipantiTotale"); |
|
} |
|
$partecipanti = array_merge($ammessi,$esclusi); |
|
} |
|
return $partecipanti; |
|
} |
|
|
|
public function checkImported($busta) { |
|
$imported = explode(".", $busta); |
|
if (is_array($imported)) { |
|
$imported = end($imported); |
|
if ($imported == "imported-offer") { |
|
return true; |
|
} |
|
} |
|
return false; |
|
} |
|
|
|
public function downloadBusta(array $busta) { |
|
global $config; |
|
$richiesta = $this->getRichiesta($busta["codice_richiesta"]); |
|
$partecipante = $this->getPartecipante($busta["codice_partecipante"]); |
|
$imported = $this->checkImported($busta["nomeFile"]); |
|
$file_content = $busta["content"]; |
|
if (P7Manager::bustaEstensioneSoloP7M($busta["nomeFile"])) { |
|
$ext = getTypeAndExtension($file_content, true); |
|
$busta["nomeFile"] = str_replace(".p7m", "{$ext["ext"]}", $busta["nomeFile"]); |
|
} |
|
if ($imported === true) { |
|
$ext = getTypeAndExtension($file_content, true); |
|
$busta["nomeFile"] = str_replace(".imported-offer", "{$ext["ext"]}", $busta["nomeFile"]); |
|
} |
|
if (strpos($busta["nomeFile"], ".x-empty") !== false) { |
|
$ext = getTypeAndExtension($file_content, true); |
|
$busta["nomeFile"] = substr($busta["nomeFile"], 0, strpos($busta["nomeFile"], ".x-empty")) . "." . $ext["ext"]; |
|
} |
|
if ($_POST["openP7M"] == "S") { |
|
$path = $config["chunk_folder"] . "/" . $_SESSION["utente"]->codice; |
|
if (!is_dir($path)) { |
|
mkdir($path); |
|
} |
|
$path .= "/" . $busta["nomeFile"]; |
|
file_put_contents($path, $file_content); |
|
$file_content = ""; |
|
if (file_exists($path)) { |
|
$p7m = new P7Manager($path); |
|
if ($p7m !== false) { |
|
$file_content = $p7m->extract(true); |
|
$file_info = new finfo(FILEINFO_MIME_TYPE); |
|
$mime_type = $file_info->buffer($file_content); |
|
$ext = P7manager::extFromMime($mime_type); |
|
$busta["mime"] = $mime_type; |
|
$busta["nomeFile"] = str_replace(".p7m", ".{$ext}", $busta["nomeFile"]); |
|
} |
|
unlink($path); |
|
} |
|
} |
|
if (!empty($file_content)) { |
|
$busta["nomeFile"] = $partecipante["codice_fiscale"] . "-" . $richiesta["busta"] . "-" . $busta["nomeFile"]; |
|
|
|
header('Content-Description: File Transfer'); |
|
header('Content-Disposition: attachment; filename=' . str_replace("-", ".", $busta["nomeFile"])); |
|
header('Content-Type: ' . $busta["mime"]); |
|
header('Content-Transfer-Encoding: binary'); |
|
header('Connection: Keep-Alive'); |
|
header('Expires: 0'); |
|
header('Cache-Control: must-revalidate, post-check=0, pre-check=0'); |
|
header('Pragma: public'); |
|
echo $file_content; |
|
return true; |
|
} |
|
} |
|
|
|
public function decryptBusta(array $busta,string $private,string $type) { |
|
switch ($type) { |
|
case "busta": |
|
$table = "b_gare_buste"; |
|
$decDescrizione = false; |
|
break; |
|
case "emendamento": |
|
$table = "b_gare_emendamenti"; |
|
$decDescrizione = true; |
|
break; |
|
case "segreto": |
|
$table = "b_gare_buste_secretate"; |
|
$decDescrizione = true; |
|
break; |
|
} |
|
$return = __("Errore nella richiesta"); |
|
if (!empty($table)) { |
|
$imported = $this->checkImported($busta["nomeFile"]); |
|
$key = openssl_pkey_get_private($private); |
|
if (@openssl_private_decrypt($busta["salt"],$salt,$key)) { |
|
global $config; |
|
$addSalt = $config["simple_encrypt"]["offer"]; |
|
$busta["content"] = openssl_decrypt($busta["content"],"AES128",$salt,OPENSSL_RAW_DATA,$addSalt); |
|
if ($decDescrizione) { |
|
$busta["descrizione"] = simple_decrypt($busta["descrizione"],$salt); |
|
} |
|
if ($busta["content"] !== false && !empty($busta["password"])) { |
|
if ($imported === true) { |
|
$fileInfo = getTypeAndExtension($busta["content"],true); |
|
$busta["mime"] = $fileInfo["type"]; |
|
$busta["nomeFile"] = str_replace(".imported-offer","",$busta["nomeFile"]) . $fileInfo["ext"]; |
|
} |
|
$content = simple_encrypt($busta["content"],$busta["password"]); |
|
if (!empty($content) && file_put_contents($busta["path"],$content)) { |
|
unset($busta["content"]); |
|
$busta["open"] = "S"; |
|
$busta["utente_decrypt"] = $_SESSION["utente"]->codice; |
|
$busta["timestamp_decrypt"] = date('Y-m-d H:i:s'); |
|
|
|
$salva = new salva(); |
|
$salva->debug = false; |
|
$salva->nome_tabella = $table; |
|
$salva->operazione = "UPDATE"; |
|
$salva->oggetto = $busta; |
|
$salva->expect = array("codice","nomeFile","mime","content","open","utente_decrypt","timestamp_decrypt"); |
|
if ($decDescrizione) { |
|
$salva->expect[] = "descrizione"; |
|
} |
|
$esito = $salva->save(); |
|
if ($esito > 0) { |
|
$return = true; |
|
} |
|
} else { |
|
$return = __("Errore nel salvataggio del contenuto decriptato") . " - #001"; |
|
} |
|
} else { |
|
$return = __("Errore nella decriptazione del contenuto") . " - #001"; |
|
} |
|
} else { |
|
$return = __("Chiave errata") . " - #002"; |
|
} |
|
} |
|
return $return; |
|
} |
|
|
|
public function getBusta($partecipante, $richiesta, $aggiuntive = false, bool $contenuto = false) |
|
{ |
|
$return = false; |
|
$select = "*"; |
|
if (!$aggiuntive) { |
|
$sql = "SELECT {$select} FROM b_gare_buste WHERE codice_partecipante = :partecipante AND codice_richiesta = :richiesta ORDER BY codice DESC"; |
|
} else { |
|
$sql = "SELECT {$select} FROM b_gare_buste_aggiuntive WHERE codice_partecipante = :partecipante AND codice_richiesta = :richiesta ORDER BY codice DESC"; |
|
} |
|
$bind = [":partecipante" => $partecipante, ":richiesta" => $richiesta]; |
|
$return = $this->db->go($sql, $bind)->fetchAll(PDO::FETCH_ASSOC); |
|
if (!empty($return)) { |
|
$return = $return[0]; |
|
$return["path"] = $this->getSpecificBustaPath($return); |
|
if ($contenuto) { |
|
adaptMemoryLimitToFile($return["path"]); |
|
$content = file_get_contents($return["path"]); |
|
if (!empty($content)) { |
|
if ($return["open"] == "S") { |
|
$content = simple_decrypt($content,base64_decode($return["content"])); |
|
} else { |
|
$return["password"] = base64_decode($return["content"]); |
|
} |
|
$return["content"] = $content; |
|
} |
|
} |
|
} |
|
return $return; |
|
} |
|
|
|
public function getSpecificBustaPath($busta) { |
|
return $this->getBustePath($busta["codice_partecipante"])."/{$busta["codice_richiesta"]}-{$busta["sha1"]}"; |
|
} |
|
|
|
public function getBustePath(int $partecipante = null) { |
|
if (!empty($this->lotto) && !empty($this->round)) { |
|
global $config; |
|
$path = "{$config["mediaFolder"]}/{$_SESSION["ente"]->codice}/gare-buste/{$this->info["codice"]}/{$this->round["codice"]}/{$this->lotto["codice"]}"; |
|
if (!file_exists($path)) { |
|
mkdir($path,0777,true); |
|
} |
|
if (is_dir($path)) { |
|
$return = true; |
|
if (!empty($partecipante)) { |
|
$return = false; |
|
$path .= "/{$partecipante}"; |
|
if (!file_exists($path)) { |
|
mkdir($path,0777,true); |
|
} |
|
if (is_dir($path)) { |
|
$return = true; |
|
} |
|
} |
|
if ($return) { |
|
return $path; |
|
} |
|
} |
|
} |
|
} |
|
|
|
public function getBustaSecretata($partecipante, $richiesta, $derivazione, bool $contenuto = false) |
|
{ |
|
$return = false; |
|
$select = "*"; |
|
$sql = "SELECT {$select} FROM b_gare_buste_secretate WHERE derivazione = :derivazione AND codice_partecipante = :partecipante AND codice_richiesta = :richiesta ORDER BY codice DESC"; |
|
$bind = [":partecipante" => $partecipante, ":richiesta" => $richiesta, ":derivazione" => $derivazione]; |
|
$return = $this->db->go($sql, $bind)->fetchAll(PDO::FETCH_ASSOC); |
|
if (!empty($return)) { |
|
$return = $return[0]; |
|
$return["path"] = $this->getSpecificSecretatePath($return); |
|
if ($contenuto) { |
|
adaptMemoryLimitToFile($return["path"]); |
|
$content = file_get_contents($return["path"]); |
|
if (!empty($content)) { |
|
if ($return["open"] == "S") { |
|
$content = simple_decrypt($content,base64_decode($return["content"])); |
|
} else { |
|
$return["password"] = base64_decode($return["content"]); |
|
} |
|
$return["content"] = $content; |
|
} |
|
} |
|
} |
|
return $return; |
|
} |
|
|
|
public function getSpecificSecretatePath($busta) { |
|
return $this->getBustePath($busta["codice_partecipante"])."/{$busta["codice_richiesta"]}-{$busta["derivazione"]}-{$busta["sha1"]}"; |
|
} |
|
|
|
public function getSecretatePath(int $partecipante = null) { |
|
if (!empty($this->lotto) && !empty($this->round)) { |
|
global $config; |
|
$path = "{$config["mediaFolder"]}/{$_SESSION["ente"]->codice}/gare-secretate/{$this->info["codice"]}/{$this->round["codice"]}/{$this->lotto["codice"]}"; |
|
if (!file_exists($path)) { |
|
mkdir($path,0777,true); |
|
} |
|
if (is_dir($path)) { |
|
$return = true; |
|
if (!empty($partecipante)) { |
|
$return = false; |
|
$path .= "/{$partecipante}"; |
|
if (!file_exists($path)) { |
|
mkdir($path,0777,true); |
|
} |
|
if (is_dir($path)) { |
|
$return = true; |
|
} |
|
} |
|
if ($return) { |
|
return $path; |
|
} |
|
} |
|
} |
|
} |
|
|
|
public function getEmendamento($partecipante, $richiesta, bool $contenuto = false) |
|
{ |
|
$return = false; |
|
$select = "*"; |
|
$sql = "SELECT {$select} FROM b_gare_emendamenti WHERE codice_partecipante = :partecipante AND codice_richiesta = :richiesta "; |
|
$bind = [":partecipante" => $partecipante, ":richiesta" => $richiesta]; |
|
$return = $this->db->go($sql, $bind)->fetchAll(PDO::FETCH_ASSOC); |
|
if (!empty($return)) { |
|
$return = $return[0]; |
|
$return["path"] = $this->getSpecificEmendamentoPath($return); |
|
if ($contenuto) { |
|
adaptMemoryLimitToFile($return["path"]); |
|
$content = file_get_contents($return["path"]); |
|
if (!empty($content)) { |
|
if ($return["open"] == "S") { |
|
$content = simple_decrypt($content,base64_decode($return["content"])); |
|
} else { |
|
$return["password"] = base64_decode($return["content"]); |
|
} |
|
$return["content"] = $content; |
|
} |
|
} |
|
} |
|
return $return; |
|
} |
|
|
|
public function getSpecificEmendamentoPath($busta) { |
|
return $this->getEmendamentoPath($busta["codice_partecipante"])."/{$busta["codice_richiesta"]}-{$busta["sha1"]}"; |
|
} |
|
|
|
public function getEmendamentoPath(int $partecipante = null) { |
|
if (!empty($this->lotto) && !empty($this->round)) { |
|
global $config; |
|
$path = "{$config["mediaFolder"]}/{$_SESSION["ente"]->codice}/gare-emendamenti/{$this->info["codice"]}/{$this->round["codice"]}/{$this->lotto["codice"]}"; |
|
if (!file_exists($path)) { |
|
mkdir($path,0777,true); |
|
} |
|
if (is_dir($path)) { |
|
$return = true; |
|
if (!empty($partecipante)) { |
|
$return = false; |
|
$path .= "/{$partecipante}"; |
|
if (!file_exists($path)) { |
|
mkdir($path,0777,true); |
|
} |
|
if (is_dir($path)) { |
|
$return = true; |
|
} |
|
} |
|
if ($return) { |
|
return $path; |
|
} |
|
} |
|
} |
|
} |
|
|
|
public function arrangePartecipantiForANAC($tmp) { |
|
$partecipanti = []; |
|
foreach ($tmp as $partecipante) { |
|
$raggruppamento = $this->getRaggruppamento($partecipante["codice"]); |
|
if (!empty($raggruppamento)) { |
|
$partecipante["raggruppamento"] = $raggruppamento; |
|
} |
|
unset($partecipante["codice"]); |
|
$partecipanti[] = $partecipante; |
|
} |
|
return $partecipanti; |
|
} |
|
|
|
public function updatePartecipantiANAC() |
|
{ |
|
if (!empty($this->lotto["cig"])) { |
|
$tmp = $this->getPartecipanti(); |
|
if (!empty($tmp)) { |
|
$partecipanti = $this->arrangePartecipantiForANAC($tmp); |
|
anac::updatePartecipanti190($this->lotto["cig"], $partecipanti); |
|
} |
|
} |
|
} |
|
|
|
public function creaIstanzaANAC(string $smart_cig = "N") { |
|
$return = false; |
|
$record = $this->info; |
|
$lotti = $this->getLotti(); |
|
$beneficiario = Ente::getInfoFromID($record["codice_ente"])[0]; |
|
$relazioni = anac::relazioniModulo("gare", $this->info["codice"]); |
|
if (empty($relazioni)) { |
|
$gara = []; |
|
$gara["codice"] = 0; |
|
$gara["smart_cig"] = $smart_cig; |
|
$gara["oggetto"] = $record["oggetto"]; |
|
$gara["anno_riferimento"] = date("Y"); |
|
$gara["codice_ente"] = $record["codice_ente"]; |
|
$gara["codice_gestore"] = $_SESSION["ente"]->codice; |
|
$gara["dati"]["cf_sua"] = $beneficiario["cf"]; |
|
$gara["dati"]["denominazione_sua"] = $beneficiario["denominazione"]; |
|
$gara["dati"]["categorie_merc"] = [999]; |
|
if ($smart_cig == "N") { |
|
$gara["dati"]["importo"] = $record["prezzoRiferimento"]; |
|
$gara["dati"]["numero_lotti"] = count($lotti); |
|
$gara["dati"]["tipo_scheda"] = ""; |
|
$gara["dati"]["modo_indizione"] = ""; |
|
$gara["dati"]["allegato_ix"] = ""; |
|
$gara["dati"]["modo_realizzazione"] = ""; |
|
$gara["dati"]["motivo_rich_cig"] = ""; |
|
$gara["dati"]["cig_acc_quadro"] = ""; |
|
$gara["dati"]["durata_accquadro_convenzione_gara"] = ""; |
|
$gara["dati"]["escluso_avcpass"] = ""; |
|
$gara["dati"]["urgenza_dl133"] = ""; |
|
$gara["dati"]["estrema_urgenza"] = ""; |
|
$gara["dati"]["strumento_svolgimento"] = ""; |
|
$gara["dati"]["id_f_delegate"] = ""; |
|
$gara["dati"]["cf_amm_agente_gara"] = ""; |
|
} else { |
|
$lottoDB = $lotti[0]; |
|
$gara["lotto"]["cig"] = $lottoDB["cig"]; |
|
$gara["lotto"]["importo"] = $record["prezzoRiferimento"]; |
|
$gara["dati"]["codiceProceduraSceltaContraente"] = anac::getSceltaContraenteFromGara($record["procedura"],"S",$record["timestamp_creazione"]); |
|
$gara["dati"]["codiceClassificazioneGara"] = ""; |
|
$gara["dati"]["codiceFattispecieContrattuale"] = ""; |
|
$gara["dati"]["cigAccordoQuadro"] = ""; |
|
$gara["cup"] = $lottoDB["cup"]; |
|
$gara["dati"]["motivo_rich_cig_catmerc"] = ""; |
|
} |
|
$anac = new anac(); |
|
$anac->modulo = "gare"; |
|
$esito_gara = $anac->saveGara($gara); |
|
if ($esito_gara["esito"] === true) { |
|
$return["codice_gara_simog"] = $esito_gara["codice"]; |
|
$creazione = true; |
|
$anac = anac::init($esito_gara["codice"]); |
|
if ($smart_cig == "S") { |
|
$relazione = $anac->saveRelazione("gare", $record["codice"], $lottoDB["codice"], $anac->getLotti()[0]["codice"]); |
|
if (empty($relazione)) { |
|
$this->db->go("DELETE FROM b_simog WHERE codice = :codice", [":codice" => $esito_gara["codice"]]); |
|
$return["errore_lotto"] = true; |
|
} |
|
} |
|
} else { |
|
$return["msg"] = ""; |
|
if (!empty($esito_gara["errori"])) { |
|
$return["msg"] = implode("<br>", $esito_gara["errori"]); |
|
} |
|
} |
|
} else { |
|
$relazioni = reset($relazioni); |
|
$return["codice_gara_simog"] = $relazioni["gara_simog"]; |
|
$anac = anac::init($return["codice_gara_simog"]); |
|
} |
|
if (!empty($anac->info) && $anac->info["smart_cig"] == "N") { |
|
foreach ($lotti as $lottoDB) { |
|
$relazioni = anac::relazioniModulo("gare", $record["codice"], $lottoDB["codice"]); |
|
if (empty($relazioni)) { |
|
$lotto = []; |
|
$lotto["codice"] = 0; |
|
$lotto["codice_simog"] = $anac->info["codice"]; |
|
$lotto["oggetto"] = $lottoDB["oggetto"]; |
|
$lotto["cig"] = $lottoDB["cig"]; |
|
$lotto["cup"] = $lottoDB["cup"]; |
|
$lotto["importo"] = $lottoDB["importoBase"]; |
|
$lotto["dati"]["importo_attuazione_sicurezza"] = $lottoDB["oneriNoRibasso"]; |
|
$lotto["cpv"] = [$lottoDB["cpv"]]; |
|
$lotto["id_scelta_contraente"] = anac::getSceltaContraenteFromGara($record["procedura"],"N",$record["timestamp_creazione"]); |
|
$lotto["dati"]["condizioni"] = ""; |
|
$lotto["dati"]["id_aff_riservati"] = ""; |
|
$lotto["dati"]["tipo_contratto"] = ""; |
|
$lotto["dati"]["id_categoria_prevalente"] = ""; |
|
$lotto["dati"]["categoria_merc"] = ""; |
|
$lotto["dati"]["flag_escluso"] = ""; |
|
$lotto["dati"]["id_esclusione"] = ""; |
|
$lotto["dati"]["flag_regime"] = ""; |
|
$lotto["dati"]["art_regime"] = ""; |
|
$lotto["dati"]["luogo_nuts"] = ""; |
|
$lotto["dati"]["flag_dl50"] = ""; |
|
$lotto["dati"]["prima_annualita"] = ""; |
|
$lotto["dati"]["annuale_cui_mininf"] = ""; |
|
$lotto["dati"]["tipoappalto"] = ""; |
|
$lotto["dati"]["id_motivo_coll_cig"] = ""; |
|
$lotto["dati"]["cig_origine_rip"] = ""; |
|
$lotto["dati"]["flag_no_adesione_iniziativa"] = ""; |
|
$lotto["dati"]["flag_sa_non_classificata"] = ""; |
|
$esito_lotto = $anac->saveLotto($lotto,true,true); |
|
if ($esito_lotto["esito"] === true) { |
|
$relazione = $anac->saveRelazione("gare", $record["codice"], $lottoDB["codice"], $esito_lotto["codice"]); |
|
if (empty($relazione) && !empty($creazione)) { |
|
$this->db->go("DELETE FROM b_simog WHERE codice = :codice", [":codice" => $esito_gara["codice"]]); |
|
$return["errore_lotto"] = true; |
|
} |
|
anac::importazioneSuggerimenti190Lotto($lotto); |
|
} else { |
|
$return["msg"] = ""; |
|
$return["errore_lotto"] = true; |
|
if (!empty($esito_lotto["errori"])) { |
|
$return["msg"] = implode("<br>", $esito_lotto["errori"]); |
|
} |
|
} |
|
} |
|
} |
|
} |
|
return $return; |
|
} |
|
|
|
public function selezioneManualeAggiudicatari() { |
|
return ($this->quickPanel || !$this->usaGraduatoria() || (settingsManager::getValue("proponiAggiudicazioneMultiplaManuale") === "S" && ($this->getRisposteElaborazione()["aggiudicazioneManuale"] ?? "N") == "S")); |
|
} |
|
|
|
public function getAggiudicatari($codice_lotto = NULL) |
|
{ |
|
if (!empty($codice_lotto)) { |
|
$lottoSearch = $this->getLotti($codice_lotto)[0] ?? false; |
|
} else if (!empty($this->lotto)) { |
|
$lottoSearch = $this->lotto; |
|
} |
|
if (!empty($lottoSearch)) { |
|
$bind = [":codice_round" => $this->round["codice"],":codice_lotto" => $lottoSearch["codice"]]; |
|
$sql = "SELECT * FROM r_partecipanti_gare WHERE codice_round = :codice_round AND aggiudicatario = 'S' AND codice_lotto = :codice_lotto"; |
|
return $this->db->go($sql, $bind)->fetchAll(PDO::FETCH_ASSOC); |
|
} |
|
} |
|
|
|
public function getAggiudicatario($codice) { |
|
return $this->returnPartecipanti(["codice"=>$codice,"aggiudicatario"=>"S"])[0] ?? ""; |
|
} |
|
|
|
|
|
public function getImportoAggiudicazione() |
|
{ |
|
$aggiudicatari = $this->getImportoAggiudicazionePartecipanti(); |
|
if (!empty($aggiudicatari)) { |
|
$totale = 0; |
|
foreach ($aggiudicatari as $aggiudicatario) { |
|
if (!empty($aggiudicatario["offerta"])) { |
|
$totale += $aggiudicatario["offerta"]; |
|
} |
|
} |
|
return $totale; |
|
} |
|
} |
|
|
|
public static function formatiOffertaDisponibili () { |
|
return [ |
|
"ribasso" => "Ribasso percentuale", |
|
"rialzo" => "Rialzo percentuale", |
|
"assoluto" => "Ribasso con prezzo assoluto", |
|
"r-assoluto" => "Rialzo con prezzo assoluto", |
|
"nulla" => "Non prevista" |
|
]; |
|
} |
|
|
|
public function getImportoAggiudicazionePartecipanti($totale = true, $onlyAggiudicatario = true) |
|
{ |
|
$partecipanti = $this->getGraduatoria(); |
|
$criteri = $this->getCriteriEconomici(); |
|
$formato = $this->lotto["formato"]; |
|
$aggiudicatari = []; |
|
foreach ($partecipanti as $partecipante) { |
|
if (!$onlyAggiudicatario || $partecipante["aggiudicatario"] == "S") { |
|
$aggiudicatari[$partecipante["codice"]] = $partecipante; |
|
} |
|
} |
|
if (!empty($criteri)) { |
|
$extraInfoLotto = $this->getExtraInfo()["lotto"] ?? null; |
|
if (count($criteri) === 1 && !empty($extraInfoLotto["ribassoAggiudicazione-{$this->round["codice"]}"])) { |
|
$criterio = reset($criteri); |
|
$ribasso = number_format($extraInfoLotto["ribassoAggiudicazione-{$this->round["codice"]}"],$criterio["decimali"],".",""); |
|
foreach ($aggiudicatari as $i => $aggiudicatario) { |
|
if ($totale) { |
|
if (!isset($aggiudicatario["offerta"])) { |
|
$aggiudicatario["offerta"] = 0; |
|
} |
|
if ($this->normaRiferimento == "2023-36") { |
|
$offerta = ($this->lotto["importoBase"] + $this->lotto["importoManodopera"]) * $ribasso / 100; |
|
$offerta = ($this->lotto["importoBase"] + $this->lotto["importoManodopera"]) - $offerta; |
|
} else { |
|
$offerta = $this->lotto["importoBase"] * $ribasso / 100; |
|
$offerta = $this->lotto["importoBase"] - $offerta; |
|
} |
|
$offerta += $this->lotto["oneriNoRibasso"]; |
|
$aggiudicatario["offerta"] += $offerta; |
|
$aggiudicatari[$i] = $aggiudicatario; |
|
} else { |
|
$aggiudicatari[$i]["offerta"][$criteri[0]["codice"]] = $ribasso; |
|
} |
|
} |
|
} else { |
|
foreach ($criteri as $criterio) { |
|
$offerte = $this->getOfferte($criterio["codice"], $totale); |
|
if (!empty($offerte)) { |
|
if (count($criteri) === 1 && $this->getInterpretazioneArt41() === "scorporato") { |
|
$offerte = $this->getRibassoComplessivoArt41($offerte,true); |
|
foreach ($aggiudicatari as $i => $aggiudicatario) { |
|
if (!isset($aggiudicatario["offerta"])) { |
|
$aggiudicatario["offerta"] = 0; |
|
} |
|
$offerta = number_format($offerte[$aggiudicatario["codice"]],$criterio["decimali"],".",""); |
|
$offerta += $this->lotto["oneriNoRibasso"]; |
|
$aggiudicatario["offerta"] += $offerta; |
|
$aggiudicatari[$i] = $aggiudicatario; |
|
} |
|
} else { |
|
foreach ($aggiudicatari as $i => $aggiudicatario) { |
|
if ($totale) { |
|
if (!isset($aggiudicatario["offerta"])) { |
|
$aggiudicatario["offerta"] = 0; |
|
} |
|
if (!empty($offerte[$aggiudicatario["codice"]])) { |
|
$offerta = number_format($offerte[$aggiudicatario["codice"]],$criterio["decimali"],".",""); |
|
if ($formato == "ribasso" || $formato == "rialzo" || (($criterio["auto"] == "P" || $criterio["auto"] == "B" || $criterio["auto"] == "Q") && ($offerta < 100))) { |
|
if ($this->normaRiferimento == "2023-36") { |
|
$offerta = ($this->lotto["importoBase"] + $this->lotto["importoManodopera"]) * $offerta / 100; |
|
if ($formato != "rialzo") { |
|
$offerta = ($this->lotto["importoBase"] + $this->lotto["importoManodopera"]) - $offerta; |
|
} else { |
|
$offerta = ($this->lotto["importoBase"] + $this->lotto["importoManodopera"]) + $offerta; |
|
} |
|
} else { |
|
$offerta = $this->lotto["importoBase"] * $offerta / 100; |
|
if ($formato != "rialzo") { |
|
$offerta = $this->lotto["importoBase"] - $offerta; |
|
} else { |
|
$offerta = $this->lotto["importoBase"] + $offerta; |
|
} |
|
} |
|
} |
|
$offerta += $this->lotto["oneriNoRibasso"]; |
|
$aggiudicatario["offerta"] += $offerta; |
|
$aggiudicatari[$i] = $aggiudicatario; |
|
} |
|
} else { |
|
$aggiudicatari[$i]["offerta"][$criterio["codice"]] = $offerte[$aggiudicatario["codice"]] ?? NULL; |
|
} |
|
} |
|
} |
|
} |
|
} |
|
} |
|
} |
|
return $aggiudicatari; |
|
} |
|
|
|
public function getSedute($codice = null) |
|
{ |
|
$bind = [":round" => $this->round["codice"]]; |
|
$sql = "SELECT * FROM b_gare_sedute WHERE codice_round = :round "; |
|
if (!empty($codice)) { |
|
$bind[":codice"] = $codice; |
|
$sql .= " AND codice = :codice "; |
|
} |
|
$sql .= " ORDER BY codice DESC "; |
|
return $this->db->go($sql, $bind)->fetchAll(PDO::FETCH_ASSOC); |
|
} |
|
|
|
public function listPartecipanti($partecipante = null) |
|
{ |
|
if (!empty($partecipante)) { |
|
$partecipante = $this->getPartecipante($partecipante,true); |
|
$raggruppamento = $this->getRaggruppamento($partecipante["codice"]); |
|
$list_partecipanti = ""; |
|
if (!empty($raggruppamento)) { |
|
$list_partecipanti = "<strong>RAGGRUPPAMENTO</strong><br>" . $partecipante["ragione_sociale"] . " - " . $partecipante["codice_fiscale"] . " - 04-CAPOGRUPPO"; |
|
foreach ($raggruppamento as $membro) { |
|
$list_partecipanti .= "<br>" . $membro["ragione_sociale"] . " - " . $membro["codice_fiscale_impresa"] . " - " . $membro["ruolo"]; |
|
} |
|
} |
|
$avvalimento = $this->getAvvalimento($partecipante["codice"]); |
|
if (!empty($avvalimento)) { |
|
$list_partecipanti .= "<br><strong>AVVALIMENTO</strong>"; |
|
foreach ($avvalimento as $membro) { |
|
$list_partecipanti .= "<br>" . $membro["ragione_sociale"] . " - " . $membro["codice_fiscale_impresa"] . " - " . $membro["ruolo"]; |
|
} |
|
} |
|
if (empty($list_partecipanti)) { |
|
$list_partecipanti = $partecipante["ragione_sociale"] . " - " . $partecipante["codice_fiscale"]; |
|
} |
|
return $list_partecipanti; |
|
} else { |
|
return false; |
|
} |
|
} |
|
|
|
|
|
public function getCommissari($tipologia, $codice_utente = NULL) |
|
{ |
|
return $this->getManagerCommissione($tipologia)->getCommissari($codice_utente); |
|
} |
|
|
|
public function getConferences($codice = NULL) |
|
{ |
|
$conference = []; |
|
foreach ($this->getRounds() as $round) { |
|
$tmp = conferenceManager::getMeetingsFromDB("gare", $this->info["codice"], "seduta", $round["codice"]); |
|
if (!empty($tmp)) { |
|
$conference = array_merge($conference, $tmp); |
|
} |
|
$seggio = new Commissione("gare", $round["codice"], "seggio"); |
|
if (!empty($seggio->getInfo())) { |
|
$tmp = conferenceManager::getMeetingsFromDB("commissioni", $seggio->getInfo()["codice"], $seggio->tipologia, 0); |
|
if (!empty($tmp)) { |
|
$conference = array_merge($conference, $tmp); |
|
} |
|
} |
|
$commissione = new Commissione("gare", $round["codice"], "commissione"); |
|
if (!empty($commissione->getInfo())) { |
|
$tmp = conferenceManager::getMeetingsFromDB("commissioni", $commissione->getInfo()["codice"], $commissione->tipologia, 0); |
|
if (!empty($tmp)) { |
|
$conference = array_merge($conference, $tmp); |
|
} |
|
} |
|
} |
|
if (!empty($conference)) { |
|
if (!empty($codice)) { |
|
$tmp = $conference; |
|
$conference = []; |
|
foreach ($tmp as $meet) { |
|
if ($meet["codice"] == $codice) { |
|
$conference = $meet; |
|
break; |
|
} |
|
} |
|
} else { |
|
$timestamp = array_column($conference, 'timestamp'); |
|
array_multisort($timestamp, SORT_DESC, $conference); |
|
} |
|
} |
|
return $conference; |
|
} |
|
|
|
static function getModuli($filters = null, $stato = null, $fase = null, $quick = false) |
|
{ |
|
global $config; |
|
$moduli = jsonToArray($config["jsonFolder"] . "/gare-panel.json"); |
|
$tmp = []; |
|
foreach ($moduli as $id_modulo => $modulo) { |
|
$insert = true; |
|
if (is_array($filters) && !empty($filters)) { |
|
foreach ($filters as $key => $value) { |
|
if ($modulo[$key] !== $value) { |
|
$insert = false; |
|
} |
|
} |
|
} |
|
if ($quick) { |
|
if (!$modulo["quick-panel"]) { |
|
$insert = false; |
|
} |
|
} else { |
|
if ($insert && $stato !== null) { |
|
if ($modulo["stato_minimo"] > $stato) { |
|
$insert = false; |
|
} |
|
if ($insert && $fase !== null) { |
|
if ($modulo["fase_minima"] !== null && $fase < $modulo["fase_minima"]) { |
|
$insert = false; |
|
} |
|
if ($modulo["fase_massima"] !== null && $fase > $modulo["fase_massima"]) { |
|
$insert = false; |
|
} |
|
} |
|
} |
|
} |
|
|
|
if (is_array($modulo["stati_esclusi"]) && in_array($stato, $modulo["stati_esclusi"]) !== false) { |
|
$insert = false; |
|
} |
|
if ($insert) { |
|
$tmp[$id_modulo] = $modulo; |
|
} |
|
$moduli = $tmp; |
|
} |
|
return $moduli; |
|
} |
|
|
|
static function getInfoModulo($radice) |
|
{ |
|
$return = false; |
|
if (!empty($radice)) { |
|
$moduli = self::getModuli(false); |
|
if (!empty($moduli[$radice])) { |
|
$return = $moduli[$radice]; |
|
$return["id"] = $radice; |
|
$return["titolo"] = __($return["titolo"]); |
|
$return["descrizione"] = __($return["descrizione"]); |
|
} |
|
} |
|
return $return; |
|
} |
|
|
|
public function getAvvisi() |
|
{ |
|
return $this->getManagerAvvisi()->getAvvisi("N"); |
|
} |
|
|
|
public function printAvvisi() |
|
{ |
|
return $this->getManagerAvvisi()->printPublic(); |
|
} |
|
|
|
public function getContratti() |
|
{ |
|
return stipula::getContrattiFromModulo("gare", $this->lotto["codice"]); |
|
} |
|
|
|
public function getPubblicazioniGUUE() |
|
{ |
|
global $beRoot; |
|
include_once($beRoot."/guue/class/TedEsender.class.php"); |
|
return TedEsender::getPubblicazioniFromModulo("gare", $this->info["codice"]); |
|
} |
|
|
|
public function getStatoPannello() { |
|
$statoMax = $this->info["stato"]; |
|
$statoMin = null; |
|
foreach($this->getLotti() AS $lotto) { |
|
if ($lotto["stato"] > 0) { |
|
if ($lotto["stato"] > $statoMax) { |
|
$statoMax = $lotto["stato"]; |
|
} |
|
if ($lotto["stato"] < $statoMin || $statoMin === null) { |
|
$statoMin = $lotto["stato"]; |
|
} |
|
} |
|
} |
|
if ($statoMin === null) { |
|
$statoMin = $this->info["stato"]; |
|
} |
|
if (!$this->usaGraduatoria() && $statoMin == 21) { |
|
$statoMin = 21; |
|
$statoMax = 30; |
|
} |
|
return ["min"=>$statoMin,"max"=>$statoMax]; |
|
} |
|
|
|
public function serialize(bool $checkPubblica = true) : ?array { |
|
|
|
if($checkPubblica) { |
|
// TODO Verificare che si trovi in uno stato finale E abbia i CIG, in quel caso possiamo procedere all'invio |
|
// Verifica che sia pubblica per tutti |
|
if($this->round["pubblica"] != 2) { return null; } |
|
// Verifica della data di pubblicazione |
|
$dataPubblicazione = $this->round["pubblicazione"]; |
|
if(strtotime($dataPubblicazione) > time()){ return null; } |
|
|
|
} |
|
global $pdo; |
|
global $config; |
|
$data = []; |
|
|
|
$whitelist = [ |
|
"anno", "stato", "procedura", "modalita", "tipologia", |
|
"accordo_quadro", "oggetto", "fase_attiva", "prezzoRiferimento", |
|
"extraInfo", "timestamp_creazione" |
|
]; |
|
$whitelist_lotto = [ |
|
"cig", "cup", "cpv", "criterio", "formato", |
|
"oggetto", "descrizione", "importoBase", "importoManodopera", |
|
"oneriNoRibasso", "importoOpzioni", "importoAggiudicazione", |
|
"sogliaAnomalia", "extraInfo", "stato" |
|
]; |
|
$whitelist_partecipante = [ |
|
"codice_operatore", "stato", "codice_fiscale", "ragione_sociale", |
|
"escluso", "aggiudicatario", "tipo" |
|
]; |
|
$whitelist_round = [ |
|
"id", "pubblica", "pubblicazione", "chiarimenti", "sopralluogo", "scadenza", "extraInfo", "attivo", "metadata_fase" |
|
]; |
|
$whitelist_allegati = [ |
|
"url", "mime", "name", "titolo" |
|
]; |
|
|
|
|
|
// Dati base |
|
foreach($this->info as $key => $entry) { |
|
if(!in_array($key, $whitelist, true)) continue; |
|
|
|
if(is_string($entry) && valid_json($entry, $entry_data, true)) { |
|
$entry = $entry_data; |
|
} |
|
$data[$key] = $entry; |
|
} |
|
|
|
$data["url"] = $this->getPublicExternalURL(); |
|
|
|
// Stazione Appaltante |
|
$data["ente"] = $this->getEnteBeneficiario(["denominazione"]); |
|
|
|
// Lotti |
|
foreach($this->getLotti() as $lotto) { |
|
$codiceLotto = $lotto['codice']; |
|
|
|
$target = &$data['lotti'][$codiceLotto]; |
|
|
|
$this->setLotto($lotto['codice']); |
|
|
|
foreach($lotto as $key => $entry) { |
|
if(!in_array($key, $whitelist_lotto, true)) continue; |
|
|
|
if(is_string($entry) && valid_json($entry, $entry_data, true)) { |
|
$entry = $entry_data; |
|
} |
|
$target[$key] = $entry; |
|
} |
|
$target['soa'] = $this->getSOASerialize(); |
|
$target['cpv'] = $this->getCPVLotto($lotto['codice']); |
|
$target["id_lotto"] = "{$this->getPublicIdentifier()}-L-{$codiceLotto}"; |
|
|
|
// Partecipanti |
|
if($this->pubblicaPartecipanti($lotto['codice'])) { |
|
foreach($this->getPartecipanti("ALL") ?? [] as $partecipante) { |
|
if(empty($partecipante['uuid'])) { continue; } |
|
$targetP = &$target['partecipanti'][$partecipante['uuid']]; |
|
if($partecipante["codice_operatore"] > 0) { |
|
$oe = oeManager::getOE($partecipante["codice_operatore"]); |
|
if($oe) { |
|
$partecipante["tipo"] = $oe["tipo"]; |
|
} |
|
} |
|
foreach($partecipante as $key => $entry) { |
|
if(!in_array($key, $whitelist_partecipante, true)) { continue; } |
|
if(is_string($entry) && valid_json($entry, $entry_data, true)) { |
|
$entry = $entry_data; |
|
} |
|
$targetP[$key] = $entry; |
|
} |
|
$targetP["raggruppamento"] = array_column($this->getRaggruppamento($partecipante['codice']), null, "identifier"); |
|
$targetP["avvalimento"] = array_column($this->getAvvalimento($partecipante['codice']), null, "identifier"); |
|
|
|
} |
|
} |
|
} |
|
// Allegati |
|
// Round |
|
$rounds = $this->getRounds(); |
|
if(!empty($rounds)) { |
|
$i = 0; |
|
foreach($rounds as $round) { |
|
|
|
if($checkPubblica) { |
|
if($round["pubblica"] != 2) { continue; } |
|
$dataPubblicazione = $round["pubblicazione"]; |
|
if(strtotime($dataPubblicazione) > time()){ continue; } |
|
} |
|
|
|
$round['attivo'] = $round["numero"] == $this->round["numero"]; |
|
$round['metadata_fase'] = $this->getProcedura()["fasi"][$round["id"]] ?? []; |
|
|
|
$target = &$data['round'][$i++]; |
|
foreach($round as $key => $entry) { |
|
if(!in_array($key, $whitelist_round, true)) { continue; } |
|
if(is_string($entry) && valid_json_recursive($entry, $entry_data)) { |
|
$entry = $entry_data; |
|
} |
|
$target[$key] = $entry; |
|
} |
|
$allegati = filesManager::listFilesWithLink(NULL, $round["codice"],"gare-public","A") ?? []; |
|
$link = $config["protocollo"] . getCurrentDomain(); |
|
if(!empty($allegati)) { |
|
foreach($allegati as $index => $allegato) { |
|
$allegato['url'] = $link . filesManager::getAttachURL($allegato, $round["codice"], "gare-public", false); |
|
foreach($allegato as $key => $entry) { |
|
if(!in_array($key, $whitelist_allegati, true)) { continue; } |
|
$target['allegati'][$index][$key] = $entry; |
|
} |
|
} |
|
} |
|
|
|
} |
|
} |
|
array_walk_recursive($data, function(&$val, &$key) use($pdo){ |
|
if($key === "nuts" && !empty($val)) { |
|
$res = $pdo->go( |
|
"SELECT descrizione FROM b_nuts WHERE nuts = :nuts LIMIT 1", [":nuts" => $val] |
|
); |
|
$val = ["id" => $val, "descrizione" => ""]; |
|
if ($res->rowCount() > 0) { |
|
$val["descrizione"] = $res->fetch(PDO::FETCH_ASSOC)["descrizione"]; |
|
} |
|
} |
|
if ($val === "S" || $val === "SI") { $val = true; } |
|
elseif($val === "N" || $val === "NO") { $val = false; } |
|
}); |
|
|
|
|
|
|
|
|
|
recursive_unset($data, ["utente_modifica", "utente_creazione", "codice", "codice_lotto", "timestamp"]); |
|
|
|
$npa = $this->getNpaInstance(); |
|
$data["codice_gara"] = $this->getPublicIdentifier(); |
|
if($npa) { |
|
if(!empty($npa->fascicolo["id_appalto"])) |
|
$data["id_appalto"] = $npa->fascicolo["id_appalto"]; |
|
if(!empty($npa->fascicolo["codice_appalto"])) |
|
$data["codice_appalto"] = $npa->fascicolo["codice_appalto"]; |
|
} |
|
return $data; |
|
|
|
|
|
} |
|
public function getModelli($codice = null) { |
|
$statoMax = $this->getStatoPannello()["max"]; |
|
$lotti = $this->getLotti(); |
|
if (!empty($lotti)) { |
|
$criteri = array_column($lotti,"criterio"); |
|
} |
|
$bind = [ |
|
":norma" => "%\"{$this->normaRiferimento}\"%", |
|
":procedura" => "%\"{$this->info["procedura"]}\"%", |
|
":tipologia" => "%\"{$this->info["tipologia"]}\"%", |
|
":fase"=>$statoMax, |
|
":reservedEnte"=>"__reserved-{$_SESSION["ente"]->codice}-%", |
|
":dataPubblicazione"=>($this->getRounds()[0]["pubblicazione"] ?? date('Y-m-d')) |
|
]; |
|
if (!empty($criteri)) { |
|
$criteri = array_unique($criteri); |
|
if (count($criteri) === 1) { |
|
$criterio = reset($criteri); |
|
$bind[":criterio"] = "%\"{$criterio}\"%"; |
|
} |
|
} |
|
$sql = "SELECT * |
|
FROM b_impostazioni_modelli_gara |
|
WHERE attivo = 'S' |
|
AND soft_delete = 'N' |
|
AND norma LIKE :norma |
|
AND (criterio LIKE :criterio OR criterio IS NULL OR criterio = '') |
|
AND (tipologia LIKE :tipologia OR tipologia IS NULL OR tipologia = '') |
|
AND (procedura LIKE :procedura OR procedura IS NULL OR procedura = '') |
|
AND fase_minima <= :fase AND (tipo NOT LIKE '__reserved-%' OR tipo LIKE :reservedEnte) |
|
AND (dataInizio IS NULL OR dataInizio <= :dataPubblicazione) |
|
AND (dataFine IS NULL OR dataFine >= :dataPubblicazione) "; |
|
|
|
if (!empty($codice)) { |
|
$bind[":codice"] = $codice; |
|
$sql .= " AND codice = :codice"; |
|
} |
|
$sql .= " ORDER BY ordinamento ASC, codice ASC"; |
|
$return = $this->db->go($sql,$bind)->fetchAll(PDO::FETCH_ASSOC); |
|
if (!empty($codice)) { |
|
$return = $return[0]; |
|
} |
|
return $return; |
|
} |
|
|
|
public function checkLockModello($codice) { |
|
$modello = $this->getModelli($codice); |
|
$statoMax = $this->getStatoPannello()["max"]; |
|
if ($statoMax <= $modello["fase_massima"]) { |
|
return false; |
|
} |
|
return true; |
|
} |
|
|
|
public function getDestinatariModello($codice) { |
|
$modello = $this->getModelli($codice); |
|
if (!empty($modello["destinatari"])) { |
|
switch($modello["destinatari"]) { |
|
case "T": |
|
$destinatari = $this->getDestinatari(true); |
|
break; |
|
case "P": // __("Partecipanti") |
|
$destinatari = array_column($this->getPartecipanti(),"codice_operatore"); |
|
break; |
|
case "O": // __("Ammessi") |
|
$partecipanti = $this->getPartecipanti(); |
|
foreach($partecipanti AS $partecipante) { |
|
if ($partecipante["escluso"] == "N") { |
|
$destinatari[] = $partecipante["codice_operatore"]; |
|
} |
|
} |
|
break; |
|
case "N": // __("Esclusi") |
|
$partecipanti = $this->getPartecipanti(); |
|
foreach($partecipanti AS $partecipante) { |
|
if ($partecipante["escluso"] == "S") { |
|
$destinatari[] = $partecipante["codice_operatore"]; |
|
} |
|
} |
|
break; |
|
case "A": // __("Aggiudicatari") |
|
$destinatari = array_column($this->getAggiudicatari(),"codice_operatore"); |
|
break; |
|
case "E": // __("Non aggiudicatari") |
|
$partecipanti = $this->getPartecipanti(); |
|
foreach($partecipanti AS $partecipante) { |
|
if ($partecipante["aggiudicatario"] == "N") { |
|
$destinatari[] = $partecipante["codice_operatore"]; |
|
} |
|
} |
|
break; |
|
} |
|
if (!empty($destinatari)) { |
|
$destinatari = array_unique($destinatari); |
|
$destinatari = array_filter($destinatari); |
|
return $destinatari; |
|
} |
|
} |
|
return false; |
|
} |
|
|
|
/** |
|
* checkCPVServiziArt74 |
|
* |
|
* @param Int $cpv |
|
* @return bool |
|
*/ |
|
function checkCPVServiziArt74(Int $cpv) : bool { |
|
|
|
$cpv = (int) str_pad($cpv, 8, '0', STR_PAD_RIGHT); |
|
if(in_array($cpv, [75200000, 75231200, 75231240, 79611000, 79622000, 79624000, 79625000, 98133100, 98133000, 98200000, 98500000, 85321000, 85322000, 75000000, 75121000, 75122000, 75124000, 79950000, 79951000, 79952000, 79952100, 79953000, 79954000, 79955000, 79956000, 75300000, 75310000, 75311000, 75312000, 75313000, 75313100, 75314000, 75320000, 75330000, 75340000, 98000000, 98120000, 98132000, 98133110, 98130000, 98131000, 55521000, 55521100, 55521200, 55520000, 55522000, 55523000, 55524000, 55510000, 55511000, 55512000, 55523100, 75231100, 75123000, 79430000, 98113100, 79722000, 79723000, 98900000, 98910000, 64000000, 64100000, 64110000, 64111000, 64112000, 64113000, 64114000, 64115000, 64116000, 64122000, 50116510, 71550000])) { |
|
return true; |
|
} |
|
|
|
if($cpv >= 85000000 && $cpv <= 85323000) { |
|
return true; |
|
} |
|
|
|
if($cpv >= 98513000 && $cpv <= 98514000) { |
|
return true; |
|
} |
|
|
|
if($cpv >= 79995000 && $cpv <= 79995200) { |
|
return true; |
|
} |
|
|
|
if($cpv >= 80000000 && $cpv <= 80660000) { |
|
return true; |
|
} |
|
|
|
if($cpv >= 92000000 && $cpv <= 92700000) { |
|
return true; |
|
} |
|
|
|
if($cpv >= 55100000 && $cpv <= 55410000) { |
|
return true; |
|
} |
|
|
|
if($cpv >= 55521000 && $cpv <= 55521200) { |
|
return true; |
|
} |
|
|
|
if($cpv >= 79100000 && $cpv <= 79140000) { |
|
return true; |
|
} |
|
|
|
if($cpv >= 75100000 && $cpv <= 75120000) { |
|
return true; |
|
} |
|
|
|
if($cpv >= 75125000 && $cpv <= 75131000) { |
|
return true; |
|
} |
|
|
|
if($cpv >= 75200000 && $cpv <= 75231000) { |
|
return true; |
|
} |
|
|
|
if($cpv >= 75231210 && $cpv <= 75231230) { |
|
return true; |
|
} |
|
|
|
if($cpv >= 75240000 && $cpv <= 75252000) { |
|
return true; |
|
} |
|
|
|
if($cpv >= 79700000 && $cpv <= 79721000) { |
|
return true; |
|
} |
|
|
|
return false; |
|
|
|
} |
|
|
|
/** |
|
* Get the current bidding threshold. |
|
* |
|
* @return ?string |
|
*/ |
|
function getSogliaGara() : ?string { |
|
|
|
$soglia = "sottosoglia"; |
|
$tipologia_ente = $this->db->go("SELECT tipologia_ente FROM b_enti WHERE codice = :codice_ente", [":codice_ente" => $this->info["codice_ente"]])->fetch(PDO::FETCH_COLUMN, 0); |
|
if(empty($tipologia_ente)) $tipologia_ente = 15; |
|
$tipologia_ente = array_column(ente::tipologieEnte(), null, "codice")[$tipologia_ente]; |
|
$tipologia = $this->info["tipologia"][0]; |
|
$prezzo = $this->info["prezzoRiferimento"]; |
|
$elaborazione = $this->getRisposteElaborazione(); |
|
$concessione = $elaborazione["concessione"] ?? "N"; |
|
$concessione = ($concessione == "S"); |
|
$cpvs = $this->getCategorieMerceologiche(); |
|
$servizi_art74 = false; |
|
if (! empty($cpvs)) { |
|
foreach($cpvs AS $cpv) { |
|
if($this->checkCPVServiziArt74($cpv)) { |
|
$servizi_art74 = true; |
|
break; |
|
} |
|
} |
|
} |
|
if ($concessione) { |
|
if($prezzo >= 5538000.00) { |
|
$soglia = "soprasoglia"; |
|
} |
|
} else { |
|
switch($tipologia) { |
|
case "L": |
|
if($prezzo >= 5538000.00) { |
|
$soglia = "soprasoglia"; |
|
} |
|
break; |
|
case "S": |
|
case "F": |
|
if(!empty($elaborazione) && $elaborazione["settoreRiferimento"] == "speciale") { |
|
if($prezzo >= 443000.00 && (!$servizi_art74 || $prezzo >= 1000000)) { |
|
$soglia = "soprasoglia"; |
|
} |
|
} else { |
|
if ($servizi_art74) { |
|
if ($prezzo >= 750000) { |
|
$soglia = "soprasoglia"; |
|
} |
|
} else { |
|
if($tipologia_ente["centrale"] == "S") { |
|
if($prezzo >= 143000.00) { |
|
$soglia = "soprasoglia"; |
|
} |
|
} else { |
|
if($prezzo >= 221000.00) { |
|
$soglia = "soprasoglia"; |
|
} |
|
} |
|
} |
|
} |
|
break; |
|
} |
|
} |
|
|
|
return $soglia; |
|
|
|
} |
|
|
|
public function getPublicIdentifier() : string { |
|
return generatePublicIdentifier("G", $this->info["codice_ente"], $this->info["codice"]); |
|
} |
|
|
|
/** |
|
* Get a new NuovaPiattaformaAppalti instance for the given tender. |
|
* |
|
* @return NuovaPiattaformaAppalti |
|
*/ |
|
function getNpaInstance() : ?NuovaPiattaformaAppalti { |
|
if($this->npa) return $this->npa; |
|
$sql = "SELECT * FROM b_npa WHERE modulo_riferimento = :modulo_riferimento AND id_riferimento = :codice_riferimento ORDER BY revisione_fascicolo DESC LIMIT 0,1"; |
|
|
|
$bind = [":codice_riferimento" => $this->info["codice"], ":modulo_riferimento" => "gare"]; |
|
|
|
$fascicolo = $this->db->go($sql, $bind)->fetch(PDO::FETCH_ASSOC); |
|
if(! empty($fascicolo["codice"])) { |
|
|
|
$this->npa = NuovaPiattaformaAppalti::init($fascicolo["codice"], null, null, "gare", $this->info["codice"]); |
|
return $this->npa; |
|
|
|
} |
|
|
|
return null; |
|
|
|
} |
|
|
|
public function getRup() : ?Array { |
|
|
|
$incaricati = $this->getManagerIncarichi()->getIncaricati(); |
|
if (!empty($incaricati)) { |
|
$incaricati = array_column($incaricati, null, "ruolo"); |
|
if(! empty($incaricati[14])) { |
|
return $incaricati[14]; |
|
} |
|
} |
|
return null; |
|
|
|
} |
|
|
|
|
|
/** |
|
* Retrieves descendant cards for the given dossier. |
|
* |
|
* @return ?Array |
|
*/ |
|
function getDescendantCards(bool $arrangeByCategory = true) : ?Array { |
|
|
|
$npa = $this->getNpaInstance(); |
|
if(! empty($npa)) { |
|
|
|
$elaborazione = $this->getRisposteElaborazione(); |
|
$soglia = $this->getSogliaGara(); |
|
$schede = $npa->getCardsAndItsDescendantsList($elaborazione["settoreRiferimento"], $soglia, ($elaborazione["concessione"] ?? "N") == "S", false); |
|
$procedura = $this->getProcedura(); |
|
if(count($procedura["fasi"]) < 2) { |
|
$schede = array_filter($schede, function($key) { |
|
return $key != "S1"; |
|
}, ARRAY_FILTER_USE_KEY); |
|
} |
|
|
|
return $arrangeByCategory ? $npa->arrangeCardsByCategory($schede) : $schede; |
|
|
|
} |
|
|
|
return null; |
|
|
|
} |
|
|
|
/** |
|
* Get the list of available cards for the NPA |
|
* |
|
* @return ?Array |
|
*/ |
|
public function getInitialCards() : ?Array { |
|
|
|
$rounds = $this->getRounds(); |
|
$elaborazione = $this->getRisposteElaborazione(); |
|
$soglia = $this->getSogliaGara(); |
|
return NuovaPiattaformaAppalti::getInitialCards("gare", $this->info["procedura"], $rounds[0]["id"], $elaborazione["settoreRiferimento"], $soglia, ($elaborazione["concessione"] ?? "N") == "S") ; |
|
|
|
} |
|
|
|
/** |
|
* Updates the CIG (Contract Identification Code) within the application |
|
* |
|
* @param Int $codice |
|
* @param String $cig |
|
* @return Bool |
|
*/ |
|
public function updateCig(Int $codice, String $cig) : void { |
|
|
|
$this->db->go("UPDATE b_gare_lotti SET cig = :cig WHERE codice = :codice", [":codice" => $codice, ":cig" => $cig]); |
|
$this->triggerUpdates(); |
|
|
|
} |
|
|
|
function getEnteBeneficiario(array $extraFields = []): ?array |
|
{ |
|
if (empty($this->info) || empty($this->info["codice_ente"])) return null; |
|
$tmp = Ente::getInfoFromID($this->info["codice_ente"]); |
|
if (empty($tmp)) return null; |
|
$return = null; |
|
$tmp = reset($tmp); |
|
if (!empty($tmp["cf"])) { |
|
$return = ["codice_fiscale" => $tmp["cf"], "codice_ausa" => $tmp["codice_ausa"]]; |
|
} else { |
|
if (!empty($tmp["sua"]) && $tmp["ufficio"] == "S") { |
|
$tmp = Ente::getInfoFromID($tmp["sua"]); |
|
if (!empty($tmp)) { |
|
$tmp = reset($tmp); |
|
} |
|
} |
|
if (!empty($tmp["cf"])) { |
|
$return = ["codice_fiscale" => $tmp["cf"], "codice_ausa" => $tmp["codice_ausa"]]; |
|
} |
|
} |
|
|
|
if(!empty($return)) { |
|
foreach($extraFields as $extraField) { |
|
$return[$extraField] = $tmp[$extraField] ?? null; |
|
} |
|
} |
|
return $return; |
|
} |
|
|
|
public function deleteRound() : bool { |
|
if ($this->activeRound && $this->round["numero"] > 1 && !$this->checkPartecipantiPresenti()) { |
|
$check = $this->db->go("DELETE FROM b_gare_round WHERE codice_gara = :gara AND codice = :codice",[":gara"=>$this->info["codice"],":codice"=>$this->round["codice"]]); |
|
if ($check->rowCount() > 0) { |
|
$check = $this->db->go("UPDATE b_gare SET fase_attiva = fase_attiva - 1, stato = 21 WHERE codice = :gara",[":gara"=>$this->info["codice"]]); |
|
if ($check->rowCount() > 0) { |
|
return true; |
|
} |
|
} |
|
} |
|
return false; |
|
} |
|
|
|
public function clone() : Bool { |
|
$return = false; |
|
$copyInfo = $this->getExtraInfo()["gara"]["copyInfo"] ?? null; |
|
if (!empty($copyInfo["codice"])) { |
|
$source = self::init($copyInfo["codice"]); |
|
if (!empty($source)) { |
|
$cloner = new CloneGara($source,$this); |
|
return $cloner->clone(); |
|
} |
|
} |
|
return $return; |
|
} |
|
|
|
function getAggiudicazioneProdotti() :?Array |
|
{ |
|
|
|
if(!empty($this->info)){ |
|
|
|
global $pdo; |
|
|
|
$sql = "SELECT r_gara_prodotto.codice_prodotto as codice, |
|
b_prodotti.denominazione, |
|
b_prodotti.codice_oe, |
|
b_prodotti.brand, |
|
b_prodotti.prezzo, |
|
b_prodotti.percIva |
|
FROM r_gara_prodotto |
|
LEFT JOIN b_prodotti ON r_gara_prodotto.codice_prodotto = b_prodotti.codice |
|
WHERE r_gara_prodotto.codice_gara = :codice_gara"; |
|
|
|
$ris = $pdo->go($sql, [':codice_gara' => $this->info['codice']]); |
|
|
|
if($ris->rowCount() > 0){ |
|
return $ris->fetchAll(PDO::FETCH_ASSOC); |
|
} |
|
|
|
} |
|
|
|
return []; |
|
} |
|
public function canAddOrRemovePartecipanti() { |
|
if($this->checkLock("partecipanti")) return false; |
|
$npa = $this->getNpaInstance(); |
|
if($npa !== null) |
|
return !$npa->hasLockOnPartecipanti(false, false); |
|
return true; |
|
} |
|
public function canAddOrRemoveLotti() { |
|
$partecipanti = $this->db->go("SELECT codice FROM r_partecipanti_gare WHERE codice_round IN (SELECT codice FROM b_gare_round WHERE codice_gara = :gara)",[":gara"=>$this->info["codice"]]); |
|
if(!$this->activeRound || $this->checkLock("lotti") || $partecipanti->rowCount() > 0) return false; |
|
$npa = $this->getNpaInstance(); |
|
if($npa !== null) |
|
return empty($npa->fascicolo["id_appalto"]) && empty($npa->fascicolo["id_pianificazione"]); |
|
return true; |
|
} |
|
public function inviteOE(array $selected, ?int $codice_lotto, ?array $invito_manuale = null, bool $delete = false) { |
|
global $pdo; |
|
|
|
$invitati = []; |
|
|
|
if (!empty($codice_lotto)) { |
|
$this->setLotto($codice_lotto); |
|
} |
|
|
|
$invitatiDB = array_column($this->getInvitati(),"codice_operatore"); |
|
if (!empty($selected)) { |
|
foreach($selected AS $oe) { |
|
if (in_array($oe,$invitatiDB) === false) { |
|
if ($this->saveInvito($codice_lotto,$oe,false,true)) { |
|
$invitati[] = $oe; |
|
if ($this->info["stato"] >= 20) { |
|
$this->inviaInvito([$oe]); |
|
} |
|
} |
|
} else { |
|
$invitati[] = $oe; |
|
} |
|
} |
|
} |
|
if($delete) { |
|
$invitatiDB = array_column($this->getInvitati(),"codice_operatore"); |
|
$deleteInvito = $pdo->prepare("DELETE FROM r_inviti_gare WHERE codice_round = :codice_round AND codice_lotto = :lotto AND codice_operatore = :operatore "); |
|
$deleteInvito->bindValue(":codice_round",$this->round["codice"]); |
|
$deleteInvito->bindValue(":lotto",$codice_lotto); |
|
$deleteStoricoInvito = $pdo->prepare("DELETE FROM b_inviti WHERE contesto = 'gare' AND codice_elemento = :codice_round AND sub_elemento = :lotto AND codice_fiscale_operatore = :operatore "); |
|
$deleteStoricoInvito->bindValue(":codice_round",$this->round["codice"]); |
|
$deleteStoricoInvito->bindValue(":lotto",$codice_lotto); |
|
foreach($invitatiDB AS $oe) { |
|
if (in_array($oe,$invitati) === false) { |
|
$deleteInvito->bindValue(":operatore",$oe); |
|
$deleteInvito->execute(); |
|
$oe = oeManager::getOE($oe); |
|
$this->addToLog("DELETE",__("Invito operatore") . ":" . $oe["ragione_sociale"]); |
|
ob_start(); |
|
$deleteInvito->debugDumpParams(); |
|
$dumpParams = ob_get_clean(); |
|
scriviLog("r_inviti_gare","DELETE",$dumpParams); |
|
if (!empty($oe["codice_fiscale_impresa"])) { |
|
$deleteStoricoInvito->bindValue(":operatore",$oe["codice_fiscale_impresa"]); |
|
$deleteStoricoInvito->execute(); |
|
ob_start(); |
|
$deleteStoricoInvito->debugDumpParams(); |
|
$dumpParams = ob_get_clean(); |
|
scriviLog("b_inviti","DELETE",$dumpParams); |
|
} |
|
} |
|
} |
|
if (!empty($invito_manuale)) { |
|
$deleteInvito = $pdo->prepare("DELETE FROM temp_inviti WHERE codice = :codice AND contesto = 'gare' AND attivo = 'S' AND codice_elemento = :codice_round AND sub_elemento = :lotto"); |
|
$deleteInvito->bindValue(":codice_round",$this->round["codice"]); |
|
$deleteInvito->bindValue(":lotto",$codice_lotto); |
|
foreach($invito_manuale AS $codice => $codice_fiscale) { |
|
$deleteInvito->bindValue(":codice",$codice); |
|
$deleteInvito->execute(); |
|
ob_start(); |
|
$deleteInvito->debugDumpParams(); |
|
$dumpParams = ob_get_clean(); |
|
scriviLog("temp_inviti","DELETE",$dumpParams); |
|
if (!empty($codice_fiscale)) { |
|
$deleteStoricoInvito->bindValue(":operatore",$codice_fiscale); |
|
$deleteStoricoInvito->execute(); |
|
ob_start(); |
|
$deleteStoricoInvito->debugDumpParams(); |
|
$dumpParams = ob_get_clean(); |
|
scriviLog("b_inviti","DELETE",$dumpParams); |
|
} |
|
} |
|
} |
|
} |
|
|
|
} |
|
|
|
/** |
|
* getRda |
|
* |
|
* @return array |
|
*/ |
|
public function getRda() |
|
{ |
|
|
|
if(!empty($this->info)){ |
|
global $pdo; |
|
|
|
$sql = "SELECT b_rda.codice |
|
FROM r_gara_rda |
|
LEFT JOIN b_rda ON r_gara_rda.codice_rda = b_rda.codice |
|
WHERE r_gara_rda.codice_gara = :codice_gara"; |
|
|
|
return $pdo->go($sql, [':codice_gara' => $this->info['codice']])->fetchAll(PDO::FETCH_COLUMN) ?? []; |
|
} |
|
} |
|
|
|
/** |
|
* updateStateRda |
|
* |
|
* @return void |
|
*/ |
|
public function updateStateRda() |
|
{ |
|
if(!empty($this->getRda())){ |
|
$statoRda = '0'; |
|
if(in_array($this->info['stato'], ['95', '99'] )){ |
|
$statoRda = '10'; |
|
} |
|
if(in_array($this->info['stato'], ['35', '50'])){ |
|
$statoRda = '30'; |
|
} |
|
if(in_array($this->info['stato'], ['90'])){ |
|
$statoRda = '90'; |
|
} |
|
|
|
if($statoRda > 0){ |
|
$statoRda = StatoRda::getStati(null, $statoRda); |
|
|
|
if(!empty($statoRda)){ |
|
$statoRda = reset($statoRda); |
|
|
|
foreach ($this->getRda() as $rda) { |
|
$rda = Rda::init($rda); |
|
|
|
$rda->moveStatus($statoRda['codice']); |
|
} |
|
} |
|
} |
|
} |
|
} |
|
}
|
|
|