package dao;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.math.BigDecimal;
import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Types;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

import javax.persistence.ParameterMode;

import org.hibernate.Criteria;
import org.hibernate.Query;
import org.hibernate.SQLQuery;
import org.hibernate.Session;
import org.hibernate.criterion.Restrictions;
import org.hibernate.engine.jdbc.connections.spi.ConnectionProvider;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.jdbc.ReturningWork;
import org.hibernate.jdbc.Work;
import org.hibernate.procedure.ProcedureCall;
import org.hibernate.result.Output;
import org.hibernate.result.Outputs;
import org.hibernate.result.ResultSetOutput;
import org.hibernate.result.UpdateCountOutput;
import org.hibernate.transform.AliasToBeanResultTransformer;
import org.hibernate.transform.Transformers;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.CallableStatementCreator;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.SqlParameter;
import org.springframework.stereotype.Repository;
import org.springframework.util.MultiValueMap;

import com.fasterxml.jackson.databind.ObjectMapper;

import bean.AnnullaDistintaBean;
import bean.AppVariables;
import bean.LogModificheBean;
import bean.ModificaContoDistintaBean;
import bean.ModificaDataDisposizioneBean;
import bean.StoredProcResult;
import bean.filters.DistinteFilterBean;
import bean.query.DistintaBancaBean;
import common.bean.UserData;
import common.dao.GenericDAO;
import common.dao.IDAO;
import common.utility.DateUtils;
import common.utility.StringUtilities;
import sicura.entities.DisposizioniAea;
import sicura.entities.DisposizioniBonifici;
import sicura.entities.DisposizioniRid;
import sicura.entities.DistintaBanca;
import utils.ConvalidaClass;
import utils.DettaglioErrori;

@Repository
public class DistintaBancaDAO extends GenericDAO<DistintaBanca, Integer> implements IDAO<DistintaBanca, Integer> {

//	@Autowired
//	private JdbcTemplate jdbcTemplate;
//	
	@Autowired
	DisposizioneAeaDAO disposizioniAeaDAO;

	@Autowired
	DisposizioniRidDAO disposizioniRidDAO;
	
	@Autowired
	DisposizioniBonificiDAO disposizioniBonificiDAO;

	@Autowired
	ConvalidaClass convalidaClass;
	
	private enum StatiValidazione {OK, OtherError, ErrorConflict, RecordDeleted, NoMoreItems}
	
	public List<DistintaBancaBean> getDistinteBanca(AppVariables appVariables, DistinteFilterBean filterBean, Integer startFrom, Integer length) {
		return getDistinteBanca(appVariables, filterBean, startFrom, length, false);
	}
		
	public DistintaBanca getByIdDistintaBanca(Integer idDistintaBanca) {
		boolean tx = startTransaction();
		try {
			Criteria crit = currentSession().createCriteria(DistintaBanca.class).add(Restrictions.eq("iddistintaBanca", idDistintaBanca));
			
			List<DistintaBanca> res = crit.list();
	
			if (res.size()>0)
				return res.get(0);
			else
				return null;
		} finally {
			if (tx)
				commit();
			
		}
	}
	
	public DistintaBanca getByIdDistintaBancaNoTransaction(Integer idDistintaBanca) {
		boolean tx = startTransaction();
		try {
			Criteria crit = currentSession().createCriteria(DistintaBanca.class).add(Restrictions.eq("iddistintaBanca", idDistintaBanca));
			
			List<DistintaBanca> res = crit.list();
	
			if (res.size()>0)
				return res.get(0);
			else
				return null;
		} finally {
			if (tx)
				commit();
			
		}
	}

	public List<DistintaBancaBean> getDistinteBanca(AppVariables appVariables, DistinteFilterBean filterBean, Integer startFrom, Integer length, boolean daEsportare) {
		boolean tx = startTransaction();
		try {
			String sql = getQuery(appVariables, filterBean, false, daEsportare);
			
			if (filterBean.getOrderField()==null || "".equals(filterBean.getOrderField()))
				sql += " ORDER BY ID DESC";
			else
				sql += getSQLOrderBy(filterBean.getOrderField());
			
			SQLQuery q = currentSession().createSQLQuery(sql);
			if (sql.contains(":userId"))
				q.setParameter("userId", appVariables.getUserId());
			
			
			if (sql.contains(":daDataCreazione"))
					q.setParameter("daDataCreazione", filterBean.getDaDataCreazione());
			if (sql.contains(":aDataCreazione"))
				q.setParameter("aDataCreazione", filterBean.getaDataCreazione());
			
			if (sql.contains(":daDataValuta"))
				q.setParameter("daDataValuta", filterBean.getDaDataValuta());
			if (sql.contains(":aDataValuta"))
				q.setParameter("aDataValuta", filterBean.getaDataValuta());
	
			if (startFrom!=null)
				q.setFirstResult(startFrom);
			if (length!=null)
				q.setMaxResults(length);
			
			q
				.addScalar("GiorniScadenza")
				.addScalar("id")
				.addScalar("iddistintaBanca")
				.addScalar("iddistintaFlussoInput")
				.addScalar("insertReference")
				.addScalar("codiceSocietà")
				.addScalar("dataCreazione")
				.addScalar("provenienzaR2")
				.addScalar("dataEmissioneFlusso")
				.addScalar("tipologia")
				.addScalar("tipologiaDbgrid")
				.addScalar("userIdcreazione")
				.addScalar("userIddelegatoFirma")
				.addScalar("denominazioneDelegatoFirma")
				.addScalar("CodiceAbiOrdinante")
				.addScalar("cabOrdinante")
				.addScalar("contoOrdinante")
				.addScalar("divisaContoOrdinante")
				.addScalar("coordinateIbanordinante")
				.addScalar("codiceBicordinante")
				.addScalar("descrizioneConto")
				.addScalar("dataValutaDestinatario")
				.addScalar("numeroDisposizioni")
				.addScalar("importoDisposizioni")
				.addScalar("importoDisposizioniDecimal")
				.addScalar("divisaImporto")
				.addScalar("divisa")
				.addScalar("statoDistinta")
				.addScalar("statoValidazione")
				.addScalar("flagStampa")
				.addScalar("flagBir")
				.addScalar("trasferimentoPosizioneRid")
				.addScalar("lastSaved")
				.addScalar("contoPerCassa")
				.addScalar("flagGrandine")
				.addScalar("flagNas")
				.addScalar("flagDanni")
				.addScalar("pathFlussoPerFirmaDigitale")
				.addScalar("nomeSupportoFlussoPerFirmaDigitale")
				.addScalar("serialNumberCertificatoFd")
				.addScalar("hashCodeCertificatoFd")
				.addScalar("flagChiusuraPartitaSep")
				.addScalar("dataChiusuraPartitaSep")
				.addScalar("numDisposizioniPagatePartitaSep")
				.addScalar("impDisposizioniPagatePartitaSep")
				.addScalar("numDisposizioniInsolutePartitaSep")
				.addScalar("impDisposizioniiInsolutePartitaSep")
				.addScalar("tpflusso")
				.addScalar("prefissoFlusso")
				.addScalar("requiresFirmatario")
				.addScalar("tipoSequenzaRid")
				.addScalar("userIdfirmatario1")
				.addScalar("userIdfirmatario2")
				.addScalar("nomeSupportoCBI")
				.addScalar("msgId")
			;
			q.setResultTransformer(new AliasToBeanResultTransformer(DistintaBancaBean.class));
	
			
			List<DistintaBancaBean> res=null;
			try  {
					res = q.list();
			} catch(Exception ex) {
				ex.printStackTrace();
			}
			
			return res;
		} finally {
			if (tx)
				tx = commit();
		}
		
	}
	
	public Integer getCountDistinteBanca(AppVariables appVariables, DistinteFilterBean filterBean) {
		boolean tx = startTransaction();
		try {
			String sql = getQuery(appVariables, filterBean, true, false);
					
			SQLQuery q = currentSession().createSQLQuery(sql);
			if (sql.contains(":userId"))
				q.setParameter("userId", appVariables.getUserId().trim());
					
			if (sql.contains(":daDataCreazione"))
				q.setParameter("daDataCreazione", filterBean.getDaDataCreazione());
		if (sql.contains(":aDataCreazione"))
			q.setParameter("aDataCreazione", filterBean.getaDataCreazione());
		
		if (sql.contains(":daDataValuta"))
			q.setParameter("daDataValuta", filterBean.getDaDataValuta());
		if (sql.contains(":aDataValuta"))
			q.setParameter("aDataValuta", filterBean.getaDataValuta());

		
			Integer res = (Integer)q.uniqueResult();
			
			return res;
		} finally {
			if (tx)
				tx = commit();
		}
		
	}

	private String getQuery(AppVariables appVariables, DistinteFilterBean filterBean,boolean isCount, boolean daEsportare) {
		
		String sql  = "";
		if (isCount)
			sql = "SELECT count(*)";
		else
			sql = "SELECT " + 
					"dbo.DayBeforeValueDate( data_valuta_destinatario, FlagDanni, 1, DistintaBanca.StatoDistinta ) as GiorniScadenza,DistintaBanca.ID id, IDDistintaBanca iddistintaBanca, IDDistintaFlussoInput iddistintaFlussoInput, InsertReference insertReference, DistintaBanca.CodiceSocietà codiceSocietà, DistintaBanca.DataCreazione dataCreazione, " + 
					"ProvenienzaR2 provenienzaR2, DataEmissioneFlusso dataEmissioneFlusso, DistintaBanca.tipologia, DistintaBanca.tipologiaDbgrid, DistintaBanca.userIdcreazione, userIddelegatoFirma, denominazioneDelegatoFirma, Codice_Abi_Ordinante codiceAbiOrdinante, Cab_Ordinante cabOrdinante, Conto_Ordinante contoOrdinante, Divisa_Conto_Ordinante divisaContoOrdinante, CoordinateIBANordinante coordinateIbanordinante, codiceBicordinante, descrizioneConto, Data_Valuta_Destinatario dataValutaDestinatario, DistintaBanca.numeroDisposizioni, DistintaBanca.importoDisposizioni, importoDisposizioniDecimal,Divisa_Importo divisaImporto, " + 
					"DistintaBanca.divisa, DistintaBanca.statoDistinta, statoValidazione, DistintaBanca.flagStampa, flagBIR, trasferimentoPosizioneRID, DistintaBanca.lastSaved, contoPerCassa, flagGrandine, flagNas, flagDanni, pathFlussoPerFirmaDigitale, nomeSupportoFlussoPerFirmaDigitale, serialNumberCertificatoFD, hashCodeCertificatoFD, flagChiusuraPartitaSep, dataChiusuraPartitaSep, " + 
					"numDisposizioniPagatePartitaSep,impDisposizioniPagatePartitaSep, numDisposizioniInsolutePartitaSep, impDisposizioniiInsolutePartitaSep, tpflusso, prefissoFlusso, " + 
					"DistintaBanca.requiresFirmatario, tipoSequenzaRid, userIdfirmatario1, userIdfirmatario2, msgId, nomeSupportoCBI"  
					
					
					
//					"dbo.DayBeforeValueDate( DistintaBanca.data_valuta_destinatario, DistintaBanca.FlagDanni, 1, DistintaBanca.StatoDistinta ) as GiorniScadenza," + 
//					"DistintaBanca.ID id, DistintaBanca.IDDistintaBanca iddistintaBanca, DistintaBanca.IDDistintaFlussoInput iddistintaFlussoInput, DistintaBanca.InsertReference insertReference, "+
//					"DistintaBanca.CodiceSocietà codiceSocietà, DistintaBanca.DataCreazione dataCreazione,"+
//					" DistintaBanca.ProvenienzaR2 provenienzaR2, DistintaBanca.DataEmissioneFlusso dataEmissioneFlusso, "+
//					"DistintaBanca.tipologia, DistintaBanca.tipologiaDbgrid, DistintaBanca.userIdcreazione, DistintaBanca.userIddelegatoFirma, DistintaBanca.denominazioneDelegatoFirma, DistintaBanca.Codice_Abi_Ordinante DistintaBanca.codiceAbiOrdinante, "+
//					"DistintaBanca.Cab_Ordinante cabOrdinante, DistintaBanca.Conto_Ordinante contoOrdinante, DistintaBanca.Divisa_Conto_Ordinante DistintaBanca.divisaContoOrdinante, DistintaBanca.CoordinateIBANordinante DistintaBanca.coordinateIbanordinante, "+
//					"DistintaBanca.codiceBicordinante, DistintaBanca.descrizioneConto, DistintaBanca.Data_Valuta_Destinatario DistintaBanca.dataValutaDestinatario, DistintaBanca.numeroDisposizioni, DistintaBanca.importoDisposizioni, DistintaBanca.importoDisposizioniDecimal,"+
//					"DistintaBanca.Divisa_Importo divisaImporto, DistintaBanca.divisa, DistintaBanca.statoDistinta, DistintaBanca.statoValidazione, DistintaBanca.flagStampa, DistintaBanca.flagBIR, DistintaBanca.trasferimentoPosizioneRID, DistintaBanca.lastSaved, "+
//					"DistintaBanca.contoPerCassa, DistintaBanca.flagGrandine, DistintaBanca.flagNas, DistintaBanca.flagDanni, DistintaBanca.pathFlussoPerFirmaDigitale, DistintaBanca.nomeSupportoFlussoPerFirmaDigitale, DistintaBanca.serialNumberCertificatoFD, "+
//					"DistintaBanca.hashCodeCertificatoFD, DistintaBanca.flagChiusuraPartitaSep, DistintaBanca.dataChiusuraPartitaSep, DistintaBanca.numDisposizioniPagatePartitaSep, DistintaBanca.impDisposizioniPagatePartitaSep, "+
//					"DistintaBanca.numDisposizioniInsolutePartitaSep, DistintaBanca.impDisposizioniiInsolutePartitaSep, DistintaBanca.tpflusso, DistintaBanca.prefissoFlusso, DistintaBanca.requiresFirmatario, DistintaBanca.tipoSequenzaRid, "+
//					"DistintaBanca.userIdfirmatario1, DistintaBanca.userIdfirmatario2, DistintaBanca.msgId, DistintaFlussiInput.nomeSupportoCBI";
				
				;	
		//sql += " from DistintaBanca WITH (NOLOCK) ";
		sql += " from vDistinteBanca as DistintaBanca WITH (NOLOCK) ";
		sql += " left join DistintaFlussiInput on DistintaFlussiInput.IDDistintaFlusso = DistintaBanca.IDDistintaFlussoInput ";
		
		sql += " WHERE 1=1 " ;

		if (daEsportare)
			sql += " and FlagChiusuraPartitaSep=0";
		
		if(filterBean.getVistaGenerale()) {
			if ("DF".equals(appVariables.getProfiloLocale())) {
				sql += " and ISNUlL(UserIDFirmatario1,'')<>:userId and IsNULL(userIdfirmatario2,'')<>:userId  ";
			}
		} else {		
			if ("TO".equals(appVariables.getProfiloLocale())|| "TR".equals(appVariables.getProfiloLocale())|| "VI".equals(appVariables.getProfiloLocale())) {
				sql += " and (DistintaBanca.StatoDistinta='Predisposta' OR DistintaBanca.StatoDistinta='Autorizzata' OR DistintaBanca.StatoDistinta='Validata' OR DistintaBanca.StatoDistinta='Emessa' OR DistintaBanca.StatoDistinta='Disposta' OR DistintaBanca.StatoDistinta='Scartata' OR DistintaBanca.StatoDistinta='In Generazione')";
			} else if ("DF".equals(appVariables.getProfiloLocale())) {
				sql += " and DistintaBanca.StatoDistinta='Validata'";
				sql += " and ISNUlL(DistintaBanca.UserIDFirmatario1,'')<>:userId and IsNULL(DistintaBanca.userIdfirmatario2,'')<>:userId and DistintaBanca.RequiresFirmatario=1 ";
			}
		}			
		
		
		if(!StringUtilities.empty(filterBean.getProvenienza())) {
			if ("Formula".equals(filterBean.getProvenienza()))
				sql += " and ProvenienzaR2=1";
			else if ("Nas".equals(filterBean.getProvenienza()))
				sql += " and FlagNas=1";
			else if ("Danni".equals(filterBean.getProvenienza()))
				sql += " and FlagDanni=1";
			else if ("Grandine".equals(filterBean.getProvenienza()))
				sql += " and FlagGrandine=1";
			else if ("BIR".equals(filterBean.getProvenienza()))
				sql += " and FlagBIR=1";
		}
		
		if (filterBean.getFlagAbilitaDaDataCreazione()!=null && filterBean.getFlagAbilitaDaDataCreazione() && filterBean.getDaDataCreazione()!=null)
			sql += " and DistintaBanca.DataCreazione>=:daDataCreazione";
			
		if (filterBean.getFlagAbilitaADataCreazione() !=null && filterBean.getFlagAbilitaADataCreazione() && filterBean.getaDataCreazione()!=null)
			sql += " and DistintaBanca.DataCreazione<=:aDataCreazione";
			
		if (!StringUtilities.empty(filterBean.getNomeSupportoCBI()))
			sql += " and nomeSupportoCBI like '%" + filterBean.getNomeSupportoCBI() + "%' "; 
			
		if (filterBean.getFlagAbilitaDaDataValuta() !=null && filterBean.getFlagAbilitaDaDataValuta() && filterBean.getaDataValuta()!=null)
			sql += " and DistintaBanca.Data_Valuta_Destinatario>=:daDataValuta";
			
		if (filterBean.getFlagAbilitaADataValuta() !=null && filterBean.getFlagAbilitaADataValuta() && filterBean.getaDataValuta()!=null)
			sql += " and DistintaBanca.Data_Valuta_Destinatario<=:aDataValuta";
			
		
		if (!StringUtilities.empty(filterBean.getNomeSupportoCBI()))
			sql += " and nomeSupportoCBI like '%" + filterBean.getNomeSupportoCBI() + "%' "; 

		String importo = toDouble(filterBean.getDaImporto());
		if (!"0".equals(importo))
			sql += " and importoDisposizioniDecimal >= " + importo.replace(',','.');
		
		importo = toDouble(filterBean.getaImporto());
		if (!"0".equals(importo))
			sql += " and importoDisposizioniDecimal <= " + importo.replace(',','.');

		if (!StringUtilities.empty(filterBean.getDaDistinta()))
			sql += " and IDDistintaBanca >=" + filterBean.getDaDistinta(); 

		if (!StringUtilities.empty(filterBean.getaDistinta()))
			sql += " and IDDistintaBanca <=" + filterBean.getaDistinta(); 

		if (!StringUtilities.empty(filterBean.getContoOrdinante()))
			sql += " and Conto_Ordinante like '%" + filterBean.getContoOrdinante() + "%'";
		
		if (!StringUtilities.empty(filterBean.getStatoDisposizione()))
			sql += " and DistintaBanca.StatoDistinta='"  + filterBean.getStatoDisposizione() +"'";
		
		List<String> filters=new ArrayList<String>();
		//if (filterBean.getSdd() || filterBean.getSeda()||filterBean.getSct()||filterBean.getDom()||filterBean.getSct_int()) {
			if (filterBean.getSdd())
				//filters.add(" DistintaBanca.Tipologia='RID'");
				filters.add(" DistintaBanca.TipologiaDBGRID='SDD'");
			if (filterBean.getSeda())
				filters.add(" DistintaBanca.Tipologia='AEA'");
			if (filterBean.getSct())
				filters.add(" DistintaBanca.TipologiaDBGRID='SCT'");
			if (filterBean.getDom())
				filters.add(" DistintaBanca.TipologiaDBGRID='DOM'");
			if (filterBean.getSct_int())
				filters.add(" DistintaBanca.TipologiaDBGRID='SCT_INT'");
			if (filterBean.getSct_inps())
				filters.add(" DistintaBanca.TipologiaDBGRID='SCT_INPS'");
			if (filterBean.getAssegni())
				filters.add(" DistintaBanca.TipologiaDBGRID='ASSEGNI'");
			if (filterBean.getSct_esteri())
				filters.add(" DistintaBanca.TipologiaDBGRID='SCT_ESTERI'");
			if (filterBean.getAssegni())
				filters.add(" DistintaBanca.TipologiaDBGRID='ASSEGNI_INTESA'");
			if (filterBean.getSdd_esteri())
				filters.add(" DistintaBanca.TipologiaDBGRID='SDD_ESTERI'");
			//}
		
		if (filters.size()>0) {
			sql += " and (";
			for (int i=0;i<filters.size();i++)
				sql += filters.get(i) + (i<filters.size()-1?" or ": "");
			sql += ")";
		}
		return sql;
	}

	
	public String toDouble(String importo) {
		DecimalFormat df = new DecimalFormat("#.00"); 
		try {
			Double dbl = Double.parseDouble(importo.replace(",","."));
			String res = df.format(dbl);
			return res.replace(".", ",");
		} catch (Exception ex) {
			return "0";
		}
	}
	
	public Boolean annullaDistinta(final AnnullaDistintaBean annullaDistintaBean, final AppVariables appVariables) throws Exception {
		boolean tx = startTransaction();
		boolean res = false;
		try {
			
			SQLQuery q = currentSession().createSQLQuery("exec spAnnullaDistinta :SecurityUserId, :SecurityGuid, :IDDistinta, :IDDistintaBanca, :UserID, :Utente, :LastSaved, :Tipologia, :FromCBI");
			
			q
				.setParameter("SecurityUserId", appVariables.getUserId())
				.setParameter("SecurityGuid", appVariables.getGuid())
				.setParameter("IDDistinta",annullaDistintaBean.getId())
				.setParameter("IDDistintaBanca", annullaDistintaBean.getIdDistintaBanca())
				.setParameter("UserID", appVariables.getUserId())
				.setParameter("Utente", appVariables.getDenominazioneUtente())
				.setParameter("LastSaved", annullaDistintaBean.getLastSaved())
				.setParameter("Tipologia", annullaDistintaBean.getTipologia())
				.setParameter("FromCBI", annullaDistintaBean.isFlagDanni())
				.setResultTransformer(Transformers.aliasToBean(StoredProcResult.class))
			;
			
			Integer r = q.executeUpdate();
			
			res = r>0;

	//		annullaDistintaBean.setId(-100009);
/*			
			
			ProcedureCall call = currentSession().createStoredProcedureCall("spAnnullaDistinta");
			
			call.registerParameter("SecurityUserId", String.class, ParameterMode.IN).bindValue(appVariables.getUserId());
			call.registerParameter("SecurityGuid", String.class, ParameterMode.IN).bindValue(appVariables.getGuid());	
			call.registerParameter("IDDistinta", Integer.class, ParameterMode.IN).bindValue(annullaDistintaBean.getId());
			call.registerParameter("IDDistintaBanca", Integer.class, ParameterMode.IN).bindValue(annullaDistintaBean.getIdDistintaBanca());
			call.registerParameter("UserId", String.class, ParameterMode.IN).bindValue(appVariables.getUserId());
			call.registerParameter("Utente", String.class, ParameterMode.IN).bindValue(appVariables.getDenominazioneUtente());
			call.registerParameter("Tipologia", String.class, ParameterMode.IN).bindValue(annullaDistintaBean.getTipologia());
			call.registerParameter("FromCBI", Boolean.class, ParameterMode.IN).bindValue(annullaDistintaBean.isFlagDanni());
			call.registerParameter("LastSaved", byte[].class, ParameterMode.IN).bindValue(annullaDistintaBean.getLastSaved());
			
	//		call.registerParameter("RETURN_VALUE", Integer.class, ParameterMode.OUT);
			
			Outputs outputs = call.getOutputs();		
			
			//call.getParameterRegistration("RETURN_VALUE");
			
			Output output = outputs.getCurrent();
			if (output instanceof UpdateCountOutput) {
				res = ((UpdateCountOutput) output).getUpdateCount()>0;
			}
			if (output.isResultSet()) {
				ResultSetOutput resultSetOutput = (org.hibernate.result.ResultSetOutput) output;
				
				List<Object> result = resultSetOutput.getResultList();
	            
			}StatiValidazione
*/			
			
		} catch (Exception ex) {
			if (tx)
				tx = rollback();
			throw ex;
			
		} finally {
			if (tx)
				commit();
		}
		return res;
	}
	
	public List<LogModificheBean> logStati(Integer id) {
		boolean tx = startTransaction();
		
		try {
			String sql = "select id, userId, data, ora, utente,cast(campoPostModifica as varchar) as campoPostModifica " +
						" from LogDistintaBanca where IDDistintaBanca=:id "+
						" order by Data, Ora, id";
					
			Query q = currentSession().createSQLQuery(sql);
			q.setResultTransformer(new AliasToBeanResultTransformer(LogModificheBean.class));
			
			q.setParameter("id", id);	
			@SuppressWarnings("unchecked")
			List<LogModificheBean> res = q.list();
			
			return res;
		} finally {
			if (tx)
				tx = commit();
		}
	}

	public Boolean modificaContoDistinta(final ModificaContoDistintaBean modificaContoDistintaBean, final AppVariables appVariables) throws Throwable {
		boolean tx = startTransaction();
		boolean res = false;
		try {
			
			SQLQuery q = currentSession().createSQLQuery("exec spModificaContoAddebito :SecurityUserId, :SecurityGuid, :IDDistintaBanca, :LastSaved, :UserID, :Utente, :IDContoOrdinante, :Tipologia");
			
			q
				.setParameter("SecurityUserId", appVariables.getUserId())
				.setParameter("SecurityGuid", appVariables.getGuid())
				.setParameter("IDDistintaBanca", modificaContoDistintaBean.getIdDistintaBanca())
				.setParameter("UserID", appVariables.getUserId())
				.setParameter("Utente", appVariables.getDenominazioneUtente() + " su distinta")
				.setParameter("LastSaved", modificaContoDistintaBean.getLastSaved())
				.setParameter("IDContoOrdinante",modificaContoDistintaBean.getIdContoOrdinante())
				.setParameter("Tipologia", modificaContoDistintaBean.getTipologia())
			;
			
			Integer r = q.executeUpdate();
			
			res = r>0;
	
		} catch (Exception ex) {
			if (tx)
				tx = rollback();
			// hack per estrarre il vero motivo dell'errore
			if ("could not execute statement".equalsIgnoreCase(ex.getMessage()))
				throw ex.getCause();
			else
				throw ex;
			
		} finally {
			if (tx)
				commit();
		}
		return res;
	}

	public Boolean modificaDataValuta(ModificaDataDisposizioneBean modificaDataValutaBean, UserData userData, AppVariables appVariables) throws Throwable {
			boolean tx = startTransaction();
			boolean res = false;
			try {
				// TODO Auto-generated method stub
				SQLQuery q = currentSession().createSQLQuery("exec spModificaValutaBeneficiario :SecurityUserId, :SecurityGuid, :IDDistintaBanca, :LastSaved, :UserID, :Utente, :inserMultiData");
				
				q
					.setParameter("SecurityUserId", appVariables.getUserId())
					.setParameter("SecurityGuid", appVariables.getGuid())
					.setParameter("IDDistintaBanca", modificaDataValutaBean.getIdDistintaBanca())
					.setParameter("UserID", appVariables.getUserId())
					.setParameter("Utente", appVariables.getDenominazioneUtente() + " su distinta")
					.setParameter("LastSaved", modificaDataValutaBean.getLastSaved())
					.setParameter("inserMultiData",modificaDataValutaBean.getData())
					;
				
				Integer r = q.executeUpdate();
				
				res = r>0;
				
				if (r>0) {
					DistintaBanca distinta = getByIdDistintaBancaNoTransaction(modificaDataValutaBean.getIdDistintaBanca());
					if (distinta!=null) {
						if ("BONIFICI".equalsIgnoreCase(distinta.getTipologia()))
							updateBonifici(modificaDataValutaBean.getIdDistintaBanca(), userData, appVariables);
						else if ("AEA".equalsIgnoreCase(distinta.getTipologia()))
							updateSeda(modificaDataValutaBean.getIdDistintaBanca(), userData, appVariables);
						else if ("RID".equalsIgnoreCase(distinta.getTipologia()))
							updateRid(modificaDataValutaBean.getIdDistintaBanca(), userData, appVariables);
								
					}
				}
				
		
			} catch (Exception ex) {
				if (tx)
					tx = rollback();
				// hack per estrarre il vero motivo dell'errore
				if ("could not execute statement".equalsIgnoreCase(ex.getMessage()))
					throw ex.getCause();
				else
					throw ex;
				
			} finally {
				if (tx)
					commit();
			}
			return res;
	}
	
	private void updateRid(Integer idDistintaBanca, UserData userData, AppVariables appVariables) {
		List<DisposizioniRid> disposizioni = disposizioniRidDAO.listByDistintaBancaNoTransaction(idDistintaBanca);
		for(DisposizioniRid disposizioneRid: disposizioni) {
			ObjectMapper oMapper = new ObjectMapper();
			Map<String, Object> disposizione = oMapper.convertValue(disposizioneRid, Map.class);
			
			try {
				DettaglioErrori errori = convalidaClass.eseguiConvalida(appVariables, 1, "RID",disposizione, true, false);
				 disposizioneRid = oMapper.convertValue(disposizione, DisposizioniRid.class);
			} catch (Exception e) {
				// TODO Auto-generated catch block  disposizione.get("importo")   disposizione.get("flagImporto") disposizioneRid.isFlagImporto()
				e.printStackTrace();
			}
			
			int res = disposizioniRidDAO.saveDisposizione(disposizioneRid, userData, appVariables);
		}
	}

	private void updateSeda(Integer idDistintaBanca, UserData userData, AppVariables appVariables) {
		List<DisposizioniAea> disposizioni = disposizioniAeaDAO.listByDistintaBancaNoTransaction(idDistintaBanca);
		for(DisposizioniAea disposizione: disposizioni) {
			ObjectMapper oMapper = new ObjectMapper();
			Map<String, Object> DisposizioniAea = oMapper.convertValue(disposizione, Map.class);
			
			try {
				DettaglioErrori errori = convalidaClass.eseguiConvalida(appVariables, 1, "AEA",DisposizioniAea, true, false);
				 disposizione = oMapper.convertValue(DisposizioniAea, DisposizioniAea.class);
			} catch (Exception e) {
				// TODO Auto-generated catch block  disposizione.get("importo")   disposizione.get("flagImporto") disposizioneRid.isFlagImporto()
				e.printStackTrace();
			}
			
			int res = disposizioniAeaDAO.save(disposizione, userData, appVariables);
		}
		
	}

	private void updateBonifici(Integer idDistintaBanca, UserData userData, AppVariables appVariables) {
		List<DisposizioniBonifici> disposizioni = disposizioniBonificiDAO.listByDistintaBancaNoTransaction(idDistintaBanca);
		for(DisposizioniBonifici disposizioneBonifici: disposizioni) {
			ObjectMapper oMapper = new ObjectMapper();
			Map<String, Object> disposizione = oMapper.convertValue(disposizioneBonifici, Map.class);
			
			try {
				DettaglioErrori errori = convalidaClass.eseguiConvalida(appVariables, 1, "BONIFICI",disposizione, true, false);
				 disposizioneBonifici = oMapper.convertValue(disposizione, DisposizioniBonifici.class);
			} catch (Exception e) {
				// TODO Auto-generated catch block  disposizione.get("importo")   disposizione.get("flagImporto") disposizioneRid.isFlagImporto()
				e.printStackTrace();
			}
			
			
			disposizioniBonificiDAO.saveDisposizione(disposizioneBonifici, userData, appVariables, convalidaClass);
			
		}
		
	}

	public Boolean modificaDataEsecuzione(ModificaDataDisposizioneBean modificaDataValutaBean, UserData userData, AppVariables appVariables) throws Throwable {
		boolean tx = startTransaction();
		boolean res = false;
		try {
			
			SQLQuery q = currentSession().createSQLQuery("exec spModificaDataEsecuzione :SecurityUserId, :SecurityGuid, :IDDistintaBanca, :LastSaved, :UserID, :Utente, :inserMultiData");
			
			q
				.setParameter("SecurityUserId", appVariables.getUserId())
				.setParameter("SecurityGuid", appVariables.getGuid())
				.setParameter("IDDistintaBanca", modificaDataValutaBean.getIdDistintaBanca())
				.setParameter("UserID", appVariables.getUserId())
				.setParameter("Utente", appVariables.getDenominazioneUtente() + " su distinta")
				.setParameter("LastSaved", modificaDataValutaBean.getLastSaved())
				.setParameter("inserMultiData",modificaDataValutaBean.getData())
				;
			
			Integer r = q.executeUpdate();
			
			res = r>0;
			
			if (r>0) {
				DistintaBanca distinta = getByIdDistintaBancaNoTransaction(modificaDataValutaBean.getIdDistintaBanca());
				if (distinta!=null) {
					if ("BONIFICI".equalsIgnoreCase(distinta.getTipologia()))
						updateBonifici(modificaDataValutaBean.getIdDistintaBanca(), userData, appVariables);
					else if ("AEA".equalsIgnoreCase(distinta.getTipologia()))
						updateSeda(modificaDataValutaBean.getIdDistintaBanca(), userData, appVariables);
					else if ("RID".equalsIgnoreCase(distinta.getTipologia()))
						updateRid(modificaDataValutaBean.getIdDistintaBanca(), userData, appVariables);
							
				}
			}

	
		} catch (Exception ex) {
			if (tx)
				tx = rollback();
			// hack per estrarre il vero motivo dell'errore
			if ("could not execute statement".equalsIgnoreCase(ex.getMessage())||
				"could not execute native bulk manipulation query".equalsIgnoreCase(ex.getMessage()))
				throw ex.getCause();
			else
				throw ex;
			
		} finally {
			if (tx)
				commit();
		}
		return res;
	}

	public String validaEGenera(Integer id,AppVariables appVariables) {
		String res = null;

		boolean tx = startTransaction();
		try {		
			DistintaBanca distinta = readNoTransaction(id);
			
			if (!"Autorizzata".equals(distinta.getStatoDistinta())) 
				return "Distinta in stato non congruente con l'attività di validazione";
			
			int resValidazione = validaDistinta(distinta, appVariables);
		    
			if (tx) {
				if (resValidazione==0)
					tx = commit();
				else
					tx = rollback();
			}
			
		    switch (resValidazione) {
		    case 0:
		    	return "Generazione Flusso Attivata";
		    case 1:
		    	return "";
		    case 4:
		    	return "La distinta è stata modificata da un altro utente";
		    case 5:
		    	return "I dati della distinta sono stati eliminati da un altro utente";
		    case 6:
		    	return "La distinta si trova in uno stato non congruente con l'attività di validazione";
		    			
		    }
			return null;
		
		} finally {
			if (tx)
				tx = commit();
		}
	}

	public String genera(Integer id,AppVariables appVariables) {
		String res = null;

		boolean tx = startTransaction();
		try {
			DistintaBanca distinta = readNoTransaction(id);
			
			if (!"Validata".equals(distinta.getStatoDistinta())) 
				return "Distinta in stato non congruente con l'attività di generazione flusso";
			
			String resValidazione = generaDistinta(distinta, appVariables);
		    
			if (tx) {
				if ("0".equals(resValidazione))
					tx = commit();
				else
					tx = rollback();
			}
			
		    if ("0".equals(resValidazione)) 
		    	return "Generazione Flusso Attivata";
		    else if ("4".equals(resValidazione))
		    	return "La distinta è stata modificata da un altro utente";
		    else if ("5".equals(resValidazione))
		    	return "I dati della distinta sono stati eliminati da un altro utente";
		    else if ("6".equals(resValidazione))
		    	return "La distinta si trova in uno stato non congruente con l'attività di validazione";
		    else
	    		return resValidazione;
	    	
		} finally {
			if (tx)
				tx = commit();
		}
		
	}
	
	private int validaDistinta(final DistintaBanca distinta,final AppVariables appVariables) {

		int res = -1;
		Connection connection = currentSession().doReturningWork(new ReturningWork<Connection>() {
	        @Override
	        public Connection execute(Connection conn) throws SQLException {
	            return conn;
	        }
	    });

			/*
			  CREATE PROCEDURE [dbo].[spValidaDistinta]
					@SecurityUserId VARCHAR(15),
					@SecurityGuid UNIQUEIDENTIFIER,
				
					@IDDistinta int,
					@IDDistintaBanca int,
					@UserID varchar(10),
					@Utente varchar(50),
					@LastSaved TIMESTAMP,
					@UpdateStatoDisposizione bit = 1
			 */
		CallableStatement proc;
		try {
			proc = connection.prepareCall("{? = call spValidaDistinta (?,?,?,?,?,?,?,?)}");
				
			proc.registerOutParameter(1, Types.INTEGER);
			proc.setString(2, appVariables.getUserId());
			proc.setString(3, appVariables.getGuid());
			proc.setObject(4, distinta.getId());
			proc.setObject(5, distinta.getIddistintaBanca());
			proc.setString(6, appVariables.getUserId());
			proc.setString(7,  appVariables.getDenominazioneUtente());
			proc.setBytes(8, distinta.getLastSaved());
			proc.setBoolean(9, true);
			
			proc.execute();
				
			res = proc.getInt(1);
				
			
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			res = -2;
		}
		
		return res;
	}
	
	private String generaDistinta(final DistintaBanca distinta,final AppVariables appVariables) {

		Integer res = -1;
		Connection connection = getConnection();

			/*
			  CREATE PROCEDURE [dbo].[spGenerazioneFlussoDistinta]
				@SecurityUserId VARCHAR(15),
				@SecurityGuid UNIQUEIDENTIFIER,
			
				@IDDistinta int,
				@IDDistintaBanca int,
				@UserID varchar(10),
				@Utente varchar(50),
				@LastSaved TIMESTAMP
			 */
		CallableStatement proc;
		try {
			proc = connection.prepareCall("{? = call spGenerazioneFlussoDistinta (?,?,?,?,?,?,?)}");
				
			proc.registerOutParameter(1, Types.INTEGER);
			proc.setString(2, appVariables.getUserId());
			proc.setString(3, appVariables.getGuid());
			proc.setObject(4, distinta.getId());
			proc.setObject(5, distinta.getIddistintaBanca());
			proc.setString(6, appVariables.getUserId());
			proc.setString(7,  appVariables.getDenominazioneUtente());
			proc.setBytes(8, distinta.getLastSaved());
			
			proc.execute();
				
			res = proc.getInt(1);
				
			
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			return e.getMessage();
		}
		
		return res.toString();
	}

	private String getAppParam (String nomeParametro, AppVariables appVariables) {
		//boolean tx = startTransaction();
		
		try {
			String res = null;
			Connection connection = getConnection();
	
			/*
			  CREATE PROC [dbo].[spGetAppParam]
				@SecurityUserId VARCHAR(15),
				@SecurityGuid UNIQUEIDENTIFIER,
				@Parametro varchar(50)
			 */
			CallableStatement proc;
			try {
				proc = connection.prepareCall("{? = call spGetAppParam (?,?,?)}");
					
				proc.registerOutParameter(1, Types.VARCHAR);
				proc.setString(2, appVariables.getUserId());
				proc.setString(3, appVariables.getGuid());
				proc.setString(4, nomeParametro);
				
				proc.execute();
				
				ResultSet rs = proc.getResultSet();
				rs.next();
				res = rs.getString(1);
//				proc.getMoreResults();
//					
//				res = proc.getString(1);
					
				
			} catch (SQLException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
				return null;
			}
			
			return res;
		} finally {
//			if (tx)
//				tx = commit();
		}
	}
	
	public String getNomeFlusso(String tipologia, Integer idDistintaBanca) {
		//boolean tx = startTransaction();
		try {
			String sql = "SELECT TOP 1 NomeSupportoFlussoInputCBI FROM Disposizioni_" + tipologia + " WHERE IDDistintaBanca=" + idDistintaBanca;
			
			SQLQuery q = currentSession().createSQLQuery(sql);
			String res = (String) q.uniqueResult();
			if (res==null)
				res = "";
			
			if (res.startsWith("0000_EBRXFND6")) {
				sql = "SELECT TOP 1 DenominazioneDestinatario FROM Disposizioni_" + tipologia + " WHERE IDDistintaBanca=" + idDistintaBanca;
				q = currentSession().createSQLQuery(sql);
				res = (String) q.uniqueResult();
			}
			return res.trim();
		} finally {
			//if (tx)
			//	tx = commit();
		}
	}
	
	public List<String> esportaTASC(AppVariables appVariables, DistinteFilterBean filterBean) throws Exception {
		List<DistintaBancaBean> distinte = getDistinteBanca(appVariables, filterBean, null, null, true);

		if (distinte.size()==0)
			return null;
			//throw new Exception("Nessuna distinta da esportare");

		
		boolean tx = startTransaction();
		try {
		
			List<String> res = new ArrayList<String>(); 
			
			try {
				// Genera CSV di esportazione
				
				
				res.add("N° Distinta;Tipologia;ABI;CAB;Conto;Divisa;Valuta Beneficiario;Stato Distinta;N° Disposizioni;Importo;Divisa;Data Creazione;Richiede Firmatario;From CBI;Exported TASC;BIR;# Giorni Scadenza;Nome Supporto;Payment Information ID");
				
				
				SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy");

				String pathExportDistinteTasc = getAppParam("PathExportDistinteTasc", appVariables);
				PrintWriter pw = new PrintWriter(new File(pathExportDistinteTasc, generateExportFileName()));
				
				for(DistintaBancaBean distinta:distinte) {
					String linea = 
							safeString(distinta.getIddistintaBanca().toString())+";"
							+ safeString(distinta.getTipologiaDbgrid()) + ";"
							+ safeString(distinta.getCodiceAbiOrdinante()) + ";"
							+ safeString(distinta.getCabOrdinante()) + ";"
							+ safeString(distinta.getContoOrdinante()) + ";"
							+ safeString(distinta.getDivisaContoOrdinante()) + ";"
							+ (distinta.getDataValutaDestinatario()!=null?sdf.format(distinta.getDataValutaDestinatario()):"") + ";"
							+ safeString(distinta.getStatoDistinta()) + ";"
							+ safeString(distinta.getNumeroDisposizioni().toString())+";"
							+ safeString(distinta.getImportoDisposizioni()) + ";"
							+ (distinta.getDivisa()!=null?distinta.getDivisa():"") + ";"
							+ sdf.format(distinta.getDataCreazione())+";"
							+ (distinta.getRequiresFirmatario()!=0?"Vero":"Falso")+";"
							+ (distinta.isFlagDanni()?"Vero":"Falso")+";"
							+ (distinta.isFlagChiusuraPartitaSep()?"Vero":"Falso")+";"
							+ (distinta.isFlagBir()?"Vero":"Falso")+";"
							+ (distinta.getGiorniScadenza()!=null?distinta.getGiorniScadenza():"")+";"
							+ getNomeFlusso(distinta.getTipologia(), distinta.getIddistintaBanca())+";"
							+ (distinta.getMsgId()!=null?distinta.getMsgId():"");
							
							;
							res.add(linea);
							
							marcaDistintaEsportata(distinta, appVariables);
				}

				try {
					for (String line: res) 
						pw.println(line);
				} finally {
					pw.close();
				}
				
				return res;
			} catch(Exception ex) {
				if (tx)
					rollback();
				tx = false;
				throw ex;
			}
		}
		finally {
			if (tx)
				commit();
		}
			
	}

	private void marcaDistintaEsportata(DistintaBancaBean distinta, AppVariables appVariables) {
		
		distinta.setFlagChiusuraPartitaSep(true);
		
		saveDistinta(distinta, appVariables, true);
		
		
	}


	private String generateExportFileName() {
		Date dt = new Date();
		SimpleDateFormat sdf = new SimpleDateFormat("ddmmyyyy_HHmmssSS");
		String filename = sdf.format(new Date());
		filename = filename.substring(0,filename.length()-1);
		return "ExportDistinteTasc_" + filename +".csv";
	
	}

	public String saveDistinta(DistintaBancaBean distinta, AppVariables appVariables, boolean transactionAlreadyActive) {
		boolean tx = false; 
		if (!transactionAlreadyActive)
			tx = startTransaction();
		
		try {
			String res = null;
			Connection connection = getConnection();
	
			/*
				CREATE PROC [dbo].[spModifyDistintaBanca]
					@SecurityUserId VARCHAR(15),
					@SecurityGuid UNIQUEIDENTIFIER,
				
					@ID int,
					@IDDistintaBanca int,
					@IDDistintaFlussoInput int,
					@InsertReference int,
					@CodiceSocietà varchar(3),
					@DataCreazione datetime,
					@ProvenienzaR2 bit,
					@DataEmissioneFlusso datetime,
					@Tipologia varchar(20),
					@TipologiaDBGRID varchar(20),
					@UserIDCreazione varchar(10),
					@UserIDDelegatoFirma varchar(10),
					@DenominazioneDelegatoFirma varchar(50),
					@Codice_Abi_Ordinante varchar(5),
					@Cab_Ordinante varchar(5),
					@Conto_Ordinante varchar(12),
					@Divisa_Conto_Ordinante varchar(3),
					@CoordinateIBANordinante varchar(42),
					@CodiceBICordinante varchar(11),
					@DescrizioneConto varchar(30),
					@Data_Valuta_Destinatario datetime,
					@NumeroDisposizioni int,
					@ImportoDisposizioni varchar(50),
					@ImportoDisposizioniDecimal decimal(18,3),
					@Divisa_Importo varchar(3),
					@Divisa varchar(3),
					@StatoDistinta varchar(15),
					@StatoValidazione varchar(15),
					@FlagStampa bit,
					@FlagBIR bit,
					@TrasferimentoPosizioneRID varchar(1),
					@LastSaved timestamp,
					@ContoPerCassa bit,
					@FlagGrandine bit,
					@FlagNas bit,
					@FlagDanni bit,
					@PathFlussoPerFirmaDigitale varchar(200),
					@NomeSupportoFlussoPerFirmaDigitale varchar(20),
					@SerialNumberCertificatoFD varchar(50),
					@HashCodeCertificatoFD varchar(100),
					@FlagChiusuraPartitaSep bit,
					@DataChiusuraPartitaSep datetime,
					@NumDisposizioniPagatePartitaSep varchar(7),
					@ImpDisposizioniPagatePartitaSep varchar(20),
					@NumDisposizioniInsolutePartitaSep varchar(7),
					@ImpDisposizioniiInsolutePartitaSep varchar(20),
					@TPFlusso int,
					@PrefissoFlusso varchar(255),
					@RequiresFirmatario INT = NULL,
					@TipoSequenzaRID varchar(4) = NULL,
					@UserIDFirmatario1 varchar(10),
					@UserIDFirmatario2 varchar(10),
					@MsgId varchar(35)
							  
			 */
			CallableStatement proc;
			try {
				proc = connection.prepareCall("{? = call spModifyDistintaBanca(" 
					+ "?,?,?,?,?,?,?,?,?,?,"
					+ "?,?,?,?,?,?,?,?,?,?,"
					+ "?,?,?,?,?,?,?,?,?,?,"
					+ "?,?,?,?,?,?,?,?,?,?,"
					+ "?,?,?,?,?,?,?,?,?,?,"
					+ "?,?,?,?,?"
						+ ")}");
				
				proc.registerOutParameter(1, Types.VARCHAR);
				proc.setString(2, appVariables.getUserId()); //@SecurityUserId VARCHAR(15),
				proc.setString(3, appVariables.getGuid());  //@SecurityGuid UNIQUEIDENTIFIER,
				
				proc.setObject(4, distinta.getId()); //@ID int,
				proc.setObject(5, distinta.getIddistintaBanca());// @IDDistintaBanca int,
				proc.setObject(6, distinta.getIddistintaFlussoInput());// @IDDistintaFlussoInput int,
				proc.setObject(7, distinta.getInsertReference());// @InsertReference int,
				proc.setString(8,  distinta.getCodiceSocietà());// @CodiceSocietà varchar(3),
				proc.setDate(9,  dateToSqlDate(distinta.getDataCreazione()));// @DataCreazione datetime,
				proc.setBoolean(10, distinta.isProvenienzaR2());// @ProvenienzaR2 bit,
				proc.setDate(11, dateToSqlDate(distinta.getDataEmissioneFlusso()));// @DataEmissioneFlusso datetime,
				proc.setString(12, distinta.getTipologia());// @Tipologia varchar(20),
				proc.setString(13, distinta.getTipologiaDbgrid());// @TipologiaDBGRID varchar(20),
				proc.setString(14, distinta.getUserIdcreazione());// @UserIDCreazione varchar(10),
				proc.setString(15, distinta.getUserIddelegatoFirma());// @UserIDDelegatoFirma varchar(10),
				proc.setString(16, distinta.getDenominazioneDelegatoFirma());// @DenominazioneDelegatoFirma varchar(50),
				proc.setString(17, distinta.getCodiceAbiOrdinante());// @Codice_Abi_Ordinante varchar(5),
				proc.setString(18, distinta.getCabOrdinante());// @Cab_Ordinante varchar(5),
				proc.setString(19, distinta.getContoOrdinante());// @Conto_Ordinante varchar(12),
				proc.setString(20, distinta.getDivisaContoOrdinante());// @Divisa_Conto_Ordinante varchar(3),
				proc.setString(21, distinta.getCoordinateIbanordinante());// @CoordinateIBANordinante varchar(42),
				proc.setString(22, distinta.getCodiceBicordinante());// @CodiceBICordinante varchar(11),
				proc.setString(23, distinta.getDescrizioneConto());// @DescrizioneConto varchar(30),
				proc.setDate(24, dateToSqlDate(distinta.getDataValutaDestinatario()));// @Data_Valuta_Destinatario datetime,
				proc.setObject(25, distinta.getNumeroDisposizioni());// @NumeroDisposizioni int,
				proc.setString(26, distinta.getImportoDisposizioni());// @ImportoDisposizioni varchar(50),
				proc.setBigDecimal(27, distinta.getImportoDisposizioniDecimal());// @ImportoDisposizioniDecimal decimal(18,3),
				proc.setString(28, distinta.getDivisaImporto());// @Divisa_Importo varchar(3),
				proc.setString(29,  distinta.getDivisa());// @Divisa varchar(3),
				proc.setString(30, distinta.getStatoDistinta());// @StatoDistinta varchar(15),
				proc.setString(31,distinta.getStatoValidazione());// @StatoValidazione varchar(15),
				proc.setBoolean(32, distinta.isFlagStampa());// @FlagStampa bit,
				proc.setBoolean(33,distinta.isFlagBir());// @FlagBIR bit,
				proc.setString(34, distinta.getTrasferimentoPosizioneRid());// @TrasferimentoPosizioneRID varchar(1),
				proc.setBytes(35, distinta.getLastSaved());// @LastSaved timestamp,
				proc.setBoolean(36, distinta.isContoPerCassa());// @ContoPerCassa bit,
				proc.setBoolean(37, distinta.isFlagGrandine());// @FlagGrandine bit,
				proc.setBoolean(38, distinta.isFlagNas());// @FlagNas bit,
				proc.setBoolean(39, distinta.isFlagDanni());// @FlagDanni bit,
				proc.setString(40, distinta.getPathFlussoPerFirmaDigitale());// @PathFlussoPerFirmaDigitale varchar(200),
				proc.setString(41, distinta.getNomeSupportoFlussoPerFirmaDigitale());// @NomeSupportoFlussoPerFirmaDigitale varchar(20),
				proc.setString(42, distinta.getSerialNumberCertificatoFd());// @SerialNumberCertificatoFD varchar(50),
				proc.setString(43, distinta.getHashCodeCertificatoFd());// @HashCodeCertificatoFD varchar(100),
				proc.setBoolean(44, distinta.isFlagChiusuraPartitaSep());// @DataChiusuraPartitaSep datetime,
				proc.setDate(45, dateToSqlDate(distinta.getDataChiusuraPartitaSep()));// @DataChiusuraPartitaSep datetime,
				proc.setString(46, distinta.getNumDisposizioniPagatePartitaSep());// @NumDisposizioniPagatePartitaSep varchar(7),
				proc.setString(47,  distinta.getImpDisposizioniPagatePartitaSep());// @ImpDisposizioniPagatePartitaSep varchar(20),
				proc.setString(48, distinta.getNumDisposizioniInsolutePartitaSep());// @NumDisposizioniInsolutePartitaSep varchar(7),
				proc.setString(49, distinta.getImpDisposizioniiInsolutePartitaSep());// @ImpDisposizioniiInsolutePartitaSep varchar(20),
				proc.setObject(50, distinta.getTpflusso());// @TPFlusso int,
				proc.setString(51, distinta.getPrefissoFlusso());// @PrefissoFlusso varchar(255),
				proc.setObject(52, distinta.getRequiresFirmatario());// @RequiresFirmatario INT = NULL,
				proc.setString(53, distinta.getTipoSequenzaRid());// @TipoSequenzaRID varchar(4) = NULL,
				proc.setString(54, distinta.getUserIdfirmatario1());// @UserIDFirmatario1 varchar(10),
				proc.setString(55, distinta.getUserIdfirmatario2());// @UserIDFirmatario2 varchar(10),
				proc.setString(56, distinta.getMsgId());// @MsgId varchar(35)
				
				proc.execute();
				
				res = proc.getString(1);
					
				
			} catch (SQLException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
				if (tx)
					tx = rollback();
				return null;
			}
			
			return res;
		} finally {
			if (tx)
				tx = commit();
		}
	}


	public String firmaDistinta(String tipoFirma, Boolean generaFlusso, Integer idDistintaBanca, AppVariables appVariables) {
		
		String res = null;
		boolean tx = startTransaction();
		try {
			Criteria crit = currentSession().createCriteria(DistintaBanca.class);
			crit.add(Restrictions.eq("iddistintaBanca", idDistintaBanca));
			DistintaBanca distinta = (DistintaBanca) crit.uniqueResult(); 
			
			Connection connection = getConnection();
			
			//CREATE PROCEDURE [dbo].[spFirmaDistinta]
			//		@SecurityUserId VARCHAR(15),
			//		@SecurityGuid UNIQUEIDENTIFIER,l
			//
			//		@IDDistinta int,
			//		@IDDistintaBanca int,
			//		@UserID varchar(10),
			//		@Utente varchar(50),
			//		@StepFirma varchar(1),
			//		@EseguiGenerazioneFlusso bit = 0,
			//		@LastSaved TIMESTAMP
	
			
			CallableStatement proc;
			try {
				proc = connection.prepareCall("{? = call spFirmaDistinta(?,?,?,?,?,?,?,?,?)}");
				
				proc.registerOutParameter(1, Types.VARCHAR);
				proc.setString(2, appVariables.getUserId()); //@SecurityUserId VARCHAR(15),
				proc.setString(3, appVariables.getGuid());  //@SecurityGuid UNIQUEIDENTIFIER,
				proc.setObject(4, distinta.getId());
				proc.setObject(5, distinta.getIddistintaBanca());
				proc.setString(6, appVariables.getUserId());
				proc.setString(7, appVariables.getDenominazioneUtente());
				proc.setString(8, tipoFirma);
				proc.setBoolean(9, generaFlusso);
				proc.setBytes(10, distinta.getLastSaved());
	
				proc.execute();
				
				res = proc.getString(1);
						  
				
			} catch (Exception e) {
				res = e.getMessage();
			}
			
			return res;
		} finally {
			if (tx)
				tx = commit();
		}
	}
	
	
	public Integer forzaturaInviata(AppVariables appVariables, Integer idDistintaBanca) {
		boolean tx = startTransaction();
		
		try {
			Connection connection = getConnection();
			CallableStatement proc;
			try {
				proc = connection.prepareCall("{? = call spForzaStatoInviataDistinta (?,?,?)}");
					
				proc.registerOutParameter(1, Types.VARCHAR);
				proc.setObject(2, idDistintaBanca);
				proc.setString(3, appVariables.getUserId());
				proc.setString(4, appVariables.getDenominazioneUtente());
				
				proc.execute();
				proc.getMoreResults();
					
				return proc.getInt(1);
					
			} catch (SQLException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
				return -1;
			}
		} finally {
			if (tx)
				commit();
		}

	}
}

