using GMW_data;
using SteamWare;
using System;
using System.Web.UI;

namespace GMW.WebUserControls
{
  /// <summary>
  /// Pagina liquidi DT
  /// </summary>
  public partial class mod_PostLiq_DT : GMW_data.UserControlBCodeMan
  {
#if false
    /// <summary>
    /// Oggetto locale gestione classe datamatrix...
    /// </summary>
    protected DataMatrix DataMatrix_mgr = new DataMatrix(); 
#endif
    /// <summary>
    /// Imposta variabili specifiche classe
    /// </summary>
    public override void setupVariabili()
    {
      flusso = "FI";
      flussoAnc = "TT";
      // temporaneo TL (Trattati/Liquidi)
      flussoTemp = "TL";
      statoUDC = "Fin";
      statoUDC_pre = "Tratt";
      eventoUDC = "UDC_TL_DT"; //UDC_FINWIP ???
      eventoUDC_qta = "UDC_QTY";
      eventoUDC_temp = "UDC_TRATT";
      codLineaKo = "W8200";
      QtaImballoStd = memLayer.ML.cdvi("QtaImballoFiniti");
      CodImballoStd = memLayer.ML.cdv("CodImballoFiniti");


      tipoUdcLinea = "Finito";
      IdxPosizioneIn = memLayer.ML.cdvi("IdxPosizioneTrattati");
      IdxPosizioneOut = memLayer.ML.cdvi("IdxPosizioneFiniti");
      IdxPosizioneOutTempName = "IdxPosizioneFinTemp";
      sVarIdxCella = "IdxCellaLineaFiniti";
      IdxPosizioneOutTemp = memLayer.ML.cdvi(IdxPosizioneOutTempName);
      tipoCartCurr = tipoCartellino.cartFiniti;
      enableBCodeParticolare = false;
    }
    /// <summary>
    /// Codice AL in carico
    /// </summary>
    public override string sourceAL
    {
      get
      {
        string answ = "";
        // cerco su controllo
        answ = lblAL.Text.Trim();
        // se vuoto cerco in sessione (ed eventualmente aggiorno
        if (string.IsNullOrEmpty(answ))
        {
          answ = memLayer.ML.StringSessionObj(string.Format("sourceAL_{0}", uid));
          lblAL.Text = answ;
        }
        // restituisco!
        return answ;
      }
      set
      {
        // salvo in sessione
        memLayer.ML.setSessionVal(string.Format("sourceAL_{0}", uid), value);
        // salvo su controllo
        lblAL.Text = value;
      }
    }
    /// <summary>
    /// Codice AL della cella corrente
    /// </summary>
    public override string destAL
    {
      get
      {
        return lblDestAL.Text.Trim();
      }
      set
      {
        lblDestAL.Text = value;
      }
    }
    /// <summary>
    /// qta pezzi x UDC
    /// </summary>
    public override int qta
    {
      get
      {
        int qta = 0;
        try
        {
          qta = Convert.ToInt32(txtQta.Text.Trim());
        }
        catch
        { }
        return qta;
      }
      set
      {
        txtQta.Text = value.ToString();
      }
    }
    /// <summary>
    /// valore barcode
    /// </summary>
    public override string barcodeIn
    {
      get
      {
        return txtBarcode.Text.Trim();
      }
      set
      {
        txtBarcode.Text = value;
      }
    }
    /// <summary>
    /// caricamento pagina
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    public override void Page_Load(object sender, EventArgs e)
    {
      // inizializzazione base!
      base.Page_Load(sender, e);
      // inizializzazione custom...
      if (!Page.IsPostBack)
      {
        currUDC = "";
        forceDelete = false;
        setDefaultVal();
        odsAL.DataBind();
        grViewSource.DataBind();
      }
    }
    /// <summary>
    /// imposta i valori di default all'avvio
    /// </summary>
    private void setDefaultVal()
    {
      if (string.IsNullOrEmpty(sourceAL))
      {
        sourceAL = currAL != "" ? currAL : "";
      }
      destAL = AlByCella;
    }
    /// <summary>
    /// Sistema css del panel AL
    /// </summary>
    /// <param name="tipoPanel"></param>
    private void fixCssAL(string tipoPanel)
    {
      divAL.Attributes.Remove("class");
      divAL.Attributes.Add("class", string.Format("panel panel-{0} small", tipoPanel));
    }
    /// <summary>
    /// sistema modalità input
    /// </summary>
    public override void setVisibility()
    {
      bool showBtn = false;
      if (sourceAL != "" && string.IsNullOrEmpty(currAL))
      {
        showBtn = true;
        fixCssAL("warning");
      }
      else
      {
        fixCssAL("success");
      }
      lbtPrendeCaricoAL.Visible = showBtn;
      // X btn chiusura: solo chiudo SOLO se c'è AL in carico..
      lbtChiudiAL.Visible = (currAL != "");
      // ora controllo btn quantità
      showBtn = false;
      if (grViewDest.SelectedIndex >= 0)
      {
        showBtn = true;
      }
      divQta.Visible = showBtn;
      divImballi.Visible = showBtn;
      if (showBtn)
      {
        selezionaImballo();
      }
    }
    /// <summary>
    /// reset maschera...
    /// </summary>
    protected void doReset()
    {
      // resetta
      fixCssAL("warning");
      lastBarcodeIn = "";
      Postazione.messaggiText = "";
      Postazione.warningText = "";
      Postazione.CssClass = cssAtt;
      doUpdate();
    }
    /// <summary>
    /// Verifica l'AL se sia ok x procedere:
    /// - Attivo
    /// </summary>
    /// <param name="AL"></param>
    /// <param name="Tipo">T/L</param>
    /// <returns></returns>
    protected bool checkAL(string AL, string tipo)
    {
      bool answ = false;
      try
      {
        answ = MagClass.magazzino.taEA.getByAL_TipoAttivo(AL, tipo).Rows.Count > 0;
      }
      catch
      { }
      if (answ)
      {
        Postazione.warningText = "";
        Postazione.CssClass = cssOk;
      }
      else
      {
        Postazione.warningText = traduci("ErroreAlNonTtAttivo");
        Postazione.CssClass = cssErr;
      }

      return answ;
    }
    /// <summary>
    /// Verifica l'AL se abbia datamatrix
    /// </summary>
    /// <param name="AL"></param>
    /// <returns></returns>
    protected bool checkDtxAL(string AL)
    {
      bool answ = false;
      try
      {
        answ = DataMatrix_mgr.taDtx2UDC.getByAL(AL).Rows.Count > 0;
      }
      catch
      { }
      if (!answ)
      {
        Postazione.warningText = traduci("ErroreAlNonDtx");
        Postazione.CssClass = cssErr;
      }
      else
      {
        Postazione.warningText = "";
        Postazione.CssClass = cssOk;
      }
      return answ;
    }
    /// <summary>
    /// controlla se ci sia un barcode e cosa farne...
    /// </summary>
    public override void checkBarcode()
    {
      // solo se ho una NUOVA chiamata...
      TimeSpan ritardo = DateTime.Now.Subtract(lastCall);
      if (ritardo.TotalMinutes > 1 || DateTime.Now.Subtract(lastCall).Milliseconds > memLayer.ML.CRI("minWaitProcMs"))
      {
        lastCall = DateTime.Now;
        if (barcodeIn != "")
        {
          Postazione.messaggiText = string.Format("{0}: {1}", traduci("BCodeIns"), barcodeIn);
          tipoCodiceBarcode tipoBC = MagClass.tipoBCode_L5(barcodeIn);
          // per prima cosa: SE NON HO AL SELEZIONATO e non ho sparato un AL o un imballo sollevo errore...
          if (!(tipoBC == tipoCodiceBarcode.AL || tipoBC == tipoCodiceBarcode.Imballo) && string.IsNullOrEmpty(currAL))
          {
            // sollevo errore, in primis va definito AL sorgente...
            Postazione.warningText = traduci("ERR-ALT-001");
            Postazione.CssClass = cssErr;
            sendUpdateTablet("ND", "-", traduci("ERR-ALT-001"), "-", "-", "-", cssErr, cssErr, cssErr);
            lastBarcodeIn = "";
          }
          else
          {
            switch (tipoBC)
            {
              case tipoCodiceBarcode.Imballo:
                // cerco di selezionare!
                try
                {
                  ddlImballi.SelectedValue = barcodeIn;
                  lastBarcodeIn = "";
                }
                catch
                {
                  Postazione.warningText = traduci("ERR-IMB-001");
                  Postazione.CssClass = cssErr;
                }
                break;
              case tipoCodiceBarcode.Comando:
                // se è reset cancello tutto!
                if (barcodeIn == memLayer.ML.cdv("cmdReset"))
                {
                  doReset();
                  lastBarcodeIn = "";
                }
                else if (barcodeIn == memLayer.ML.cdv("cmdCloseAL"))
                {
                  // forza reset linea
                  currAL = "";
                  sourceAL = "";
                  lastBarcodeIn = "";
                  // resetta!
                  doReset();
                }
                break;
              case tipoCodiceBarcode.UDC:
                // controllo di avere destAL valido, sennò ricarico pagina...
                if (destAL.Length > 5)
                {
                  // controllo se sia un UDC valido...
                  if (MagClass.magazzino.checkUDC(barcodeIn))
                  {
                    // controllo se sia un UDC di finiti LIQ in posizione 4...
                    DS_magazzino.ElencoCartelliniRow cartUDC = MagClass.magazzino.taCartellini.getByUdc(barcodeIn)[0];
                    if (cartUDC.CodStato == statoUDC && cartUDC.IdxPosizione == memLayer.ML.cdvi("IdxPosizioneFiniti"))
                    {
                      // controllo NON ci sia già un UDC di pari particolare caricato nella postazione corrente (non posso avere 2 UDC a pari particolare da riempire...)
                      if (MagClass.magazzino.taCartellini.getByParticolareAL(cartUDC.Particolare, destAL).Rows.Count == 0)
                      {
                        // controllo NON abbia blocco x FinDtx...
                        if (MagClass.magazzino.udcHasAttr(barcodeIn, "BL"))
                        {
                          Postazione.messaggiText = "";
                          Postazione.warningText = traduci("ERR-LIQ-006");
                          Postazione.CssClass = cssErr;
                        }
                        else
                        {
                          // controllo NON sia UDC in LDP e già PRELEVATO
                          if (MagClass.magazzino.taRigheListePrelievo.getByUdc(barcodeIn).Select("Prelevato = 1").Length == 0)
                          {
                            // se è ok RICARICO UDC in posizione corrente...
                            bool fatto = MagClass.magazzino.liquidiRiprendiInCaricoUDC(barcodeIn, MagClass.magazzino.CodSoggCurrUser, destAL, Postazione.currIdxCella);
                            if (fatto)
                            {
                              Postazione.messaggiText = traduci("RiCaricatoUdcLiq");
                              Postazione.warningText = "";
                              Postazione.CssClass = cssOk;
                              checkUpdateTablet(barcodeIn);
                            }
                            else
                            {
                              Postazione.messaggiText = "";
                              Postazione.warningText = traduci("ERR-LIQ-001");
                              Postazione.CssClass = cssErr;
                            }
                          }
                          else
                          {
                            Postazione.messaggiText = "";
                            Postazione.warningText = traduci("ERR-LIQ-005");
                            Postazione.CssClass = cssErr;
                          }
                        }
                      }
                      else
                      {
                        Postazione.messaggiText = "";
                        Postazione.warningText = traduci("ERR-LIQ-004");
                        Postazione.CssClass = cssErr;
                      }
                    }
                    else
                    {
                      Postazione.messaggiText = "";
                      Postazione.warningText = traduci("ERR-LIQ-002");
                      Postazione.CssClass = cssErr;
                    }
                  }
                  else
                  {
                    Postazione.messaggiText = "";
                    Postazione.warningText = traduci("ERR-LIQ-003");
                    Postazione.CssClass = cssErr;
                  }
                }
                else
                {
                  Postazione.messaggiText = "";
                  Postazione.warningText = traduci("ERR-ALF-001");
                  Postazione.CssClass = cssErr;
                }
                break;
              case tipoCodiceBarcode.AL:
                // se linea libera...
                if (string.IsNullOrEmpty(currAL))
                {
                  // verifico barcode valido
                  if (checkAL(barcodeIn, "T"))
                  {
                    // verifico AL sia con datamatrix...
                    if (checkDtxAL(barcodeIn))
                    {
                      // controllo: se avevo già letto lo steso AL è conferma presa in carico...
                      if (sourceAL == barcodeIn)
                      {
                        presaCaricoAL();
                      }
                      else
                      {
                        // mostro AL sorgente
                        sourceAL = barcodeIn;
                        fixCssAL("warning");
                        // sistemo grafica
                        Postazione.messaggiText = traduci("ConfermareAL");
                        Postazione.warningText = "";
                        Postazione.CssClass = cssOk;
                      }
                    }
                    else
                    {
                      sourceAL = "";
                    }
                  }
                  else
                  {
                    sourceAL = "";
                  }
                }
                else
                {
                  Postazione.messaggiText = "";
                  Postazione.warningText = traduci("ERR-ALT-002");
                  Postazione.CssClass = cssErr;
                }
                break;
              case tipoCodiceBarcode.DataMatrixTrovato:
                string OldUDC = "";
                int IdxPosizione = 0;
                string NewUDC = "";
                // verifica preliminare: se OK procedo, se è KO NON LO CONSIDERO PROPRIO
                bool isOk = false;
                try
                {
                  isOk = DataMatrix_mgr.taVerifica.GetData(barcodeIn)[0].StatoDtx == "OK";
                }
                catch
                { }
                if (!isOk)
                {
                  // non accetto Dtx e mostro errore
                  Postazione.messaggiText = barcodeIn;
                  Postazione.warningText = traduci("ERR-DTX-012");
                  Postazione.CssClass = cssErr;
                }
                else // PROCEDO!!!
                {
                  // verifico DTX sia in quelli dell'AL sorgente
                  if (DataMatrix_mgr.taDtx2UDC.getByDtxAl(sourceAL, barcodeIn).Rows.Count > 0)
                  {
                    // cerco se ci sia UDC di destinazione
                    DateTime adesso = DateTime.Now;
                    try
                    {
                      OldUDC = DataMatrix_mgr.taDtx2UDC.getByDtxAl(sourceAL, barcodeIn)[0].UDC;
                      IdxPosizione = MagClass.magazzino.taCartellini.getByUdc(OldUDC)[0].IdxPosizione;
                      currParticolare = MagClass.magazzino.taCartellini.getByUdc(OldUDC)[0].Particolare;
                    }
                    catch
                    {
                      currParticolare = "";
                    }
                    if (currParticolare != "")
                    {
                      try
                      {
                        NewUDC = MagClass.magazzino.taCartellini.getByParticolareAL(currParticolare, destAL)[0].UDC;
                      }
                      catch
                      {
                        NewUDC = "";
                      }
                      if (string.IsNullOrEmpty(NewUDC))
                      {
                        // CASO 01: DTX in AL sorgente, particolare OK, NON C'E' UDC dest
                        procDtx_Caso01(ref OldUDC, ref NewUDC, adesso);
                      }
                      else
                      {
                        // CASO 02: DTX in AL sorgente, particolare OK, C'E' UDC dest
                        OldUDC = procDtx_Caso02(OldUDC, NewUDC);
                      }
                      checkUpdateTablet(NewUDC);
                    }
                    else
                    {
                      Postazione.messaggiText = barcodeIn;
                      Postazione.warningText = traduci("UdcNonTrovato");
                      Postazione.CssClass = cssErr;
                    }
                  }
                  // se non lo trovo in AL sorgente...
                  else
                  {
                    // faccio ulteriore verifica: se il datamatrix sia "libero" o già tra i "Missing In Action"..
                    if (DataMatrix_mgr.taDtxAvailFree.GetData(barcodeIn).Rows.Count > 0)
                    {
                      // CASO 03: DTX NON in sorgente ma libero/missing in action
                      NewUDC = procDtx_Caso03(NewUDC);
                    }
                    else
                    {
                      // CASO 04: DTX NON in sorgente e NON libero/missing in action
                      procDTX_Caso04(ref OldUDC, ref IdxPosizione, ref NewUDC);
                    }
                  }
                }
                break;
              default:
                Postazione.warningText = traduci("ERR-BCD-001");
                Postazione.CssClass = cssErr;
                lastBarcodeIn = "";
                break;
            }
          }
          barcodeIn = "";
        }
        doUpdate();
      }
      txtBarcode.Focus();
    }

    #region metodi processing DataMatrix letto da BarCode

    /// <summary>
    /// CASO 01: DTX in AL sorgente, particolare OK, NON C'E' UDC dest
    /// </summary>
    /// <param name="OldUDC"></param>
    /// <param name="NewUDC"></param>
    /// <param name="adesso"></param>
    private void procDtx_Caso01(ref string OldUDC, ref string NewUDC, DateTime adesso)
    {
      // verifico che NON sia modalità "rimozione" datamatrix 
      if (!chkDtxMode.Checked)
      {
        // scambio UDC e prendo quello TT
        OldUDC = OldUDC.Replace(flussoTemp, flussoAnc);
        // calcolo codImballo

        string codImballo = "";
        try
        {
          codImballo = ddlImballi.SelectedValue;
        }
        catch
        {
          codImballo = memLayer.ML.cdv("CodImballoFiniti");
        }
        // se NON HA selezionato prendo default...
        if (string.IsNullOrEmpty(codImballo) || codImballo == "-")
        {
          codImballo = memLayer.ML.cdv("CodImballoFiniti");
        }
        // controllo se devo usare chiamata a stored unica (UDC + aggancio AL + cella corretta) o due chiamate
        if (memLayer.ML.confReadBool("useStoredLiqSP"))
        {
          // nuova stored con AL e cella......
          NewUDC = MagClass.magazzino.creaUdcWithAlCella(destAL, sourceAL, barcodeIn, statoUDC, Postazione.currCodCella, flusso, "", currParticolare, "", "", "", "", OldUDC, 0, codImballo, "U", MagClass.magazzino.CodSoggCurrUser, pezziUdc, 0, 0, adesso, 0, statoUDC, memLayer.ML.cdvi("IdxPosizioneFinTemp"), "IdxPosizioneFinTemp", eventoUDC, "", "", adesso.Year, Request.UserHostName);
          // registro creazione nuovo UDC
          MagClass.magazzino.taSAO.insertQuery(adesso, MagClass.magazzino.CodSoggCurrUser, Postazione.name, Postazione.IP, NewUDC, currParticolare, "creaUDC", string.Format("Creato nuovo UDC PostLiquidi DT, qta: {0} {1}", qta, ""));
        }
        else
        {
          // oppure lo creo...
          NewUDC = MagClass.magazzino.creaUdc(flusso, "", currParticolare, "", "", "", "", OldUDC, 0, codImballo, "U", MagClass.magazzino.CodSoggCurrUser, pezziUdc, 0, 0, adesso, 0, statoUDC, memLayer.ML.cdvi("IdxPosizioneFinTemp"), "IdxPosizioneFinTemp", eventoUDC, "", "", adesso.Year, Request.UserHostName);
          // registro creazione nuovo UDC
          MagClass.magazzino.taSAO.insertQuery(adesso, MagClass.magazzino.CodSoggCurrUser, Postazione.name, Postazione.IP, NewUDC, currParticolare, "creaUDC", string.Format("Creato nuovo UDC PostLiquidi DT, qta: {0} {1}", qta, ""));
          // lo associo all'AL!
          MagClass.magazzino.taAL2UDC.Insert(destAL, NewUDC, adesso, MagClass.magazzino.CodSoggCurrUser);


          DataMatrix_mgr.taDtx2UDC.UpdateUDC(NewUDC, barcodeIn, statoUDC, DateTime.Now, MagClass.magazzino.CodSoggCurrUser, false, false);
          // disattivo AL (se non era già disattivo...) x evitare si possa togliere senza chiudere...
          MagClass.magazzino.taEA.DisattivaAL(sourceAL);
          // fix messaggi
          Postazione.messaggiText = traduci("ConfermatoDtx");
          Postazione.warningText = "";
          Postazione.CssClass = cssAtt;
        }
      }
      else
      {
        Postazione.messaggiText = barcodeIn;
        Postazione.warningText = traduci("UdcNonTrovato");
        Postazione.CssClass = cssErr;
      }
    }
    /// <summary>
    /// CASO 02: DTX in AL sorgente, particolare OK, C'E' UDC dest
    /// </summary>
    /// <param name="OldUDC"></param>
    /// <param name="NewUDC"></param>
    /// <returns></returns>
    private string procDtx_Caso02(string OldUDC, string NewUDC)
    {
      // verifico se sia modalità "rimozione" datamatrix x cui tolgo i datamatrix dall'UDC finale..
      if (chkDtxMode.Checked)
      {
        // chiamo stored di verifica spostabilità (ovvero: dato Dtx è nell'UDC di dest e UDC TL è ancora in carico ad AL sorgente...)
        bool dtxInUdcDest = false;
        bool udcSourceOk = false;
        try
        {
          dtxInUdcDest = DataMatrix_mgr.taDtx2UDC.getByDtx(barcodeIn).Select(string.Format("UDC = '{0}'", NewUDC)).Length > 0;
          // ricalcolo vecchio UDC
          OldUDC = ((DS_DataMatrix.Dtx2UDCRow)DataMatrix_mgr.taDtx2UDC.getByDtx(barcodeIn).Select(string.Format("CodStato = '{0}'", statoUDC_pre))[0]).UDC.Replace(flussoAnc, flussoTemp);
          // verifico SE sia in carico ad AL...
          if (OldUDC != "")
          {
            if (MagClass.magazzino.taAL2UDC.getByAL(sourceAL).Select(string.Format("UDC = '{0}'", OldUDC)).Length > 0)
            {
              udcSourceOk = true;
            }
          }
        }
        catch
        { }
        if (dtxInUdcDest && udcSourceOk)
        {
          // tolgo da AL (se caricato), faccio update e sposto su UDC sorgente...  
          DataMatrix_mgr.taDtx2UDC.UpdateUDC(OldUDC, barcodeIn, statoUDC, DateTime.Now, MagClass.magazzino.CodSoggCurrUser, false, false);
          // fix messaggi
          Postazione.messaggiText = traduci("ToltoDtxDaDest");
          Postazione.warningText = "";
          Postazione.CssClass = cssAtt;
        }
        else
        {
          if (dtxInUdcDest)
          {
            // segno che NON posso spostare DTX
            Postazione.messaggiText = "";
            Postazione.warningText = traduci("ERR-DTX-010");
            Postazione.CssClass = cssAtt;
          }
          else
          {
            // segno che NON posso spostare DTX
            Postazione.messaggiText = "";
            Postazione.warningText = traduci("ERR-DTX-011");
            Postazione.CssClass = cssAtt;
          }
        }
      }
      else
      {
        // se lo trovo chiamo procedura di spostamento Dtx tra UDC sorgente --> dest (con eventuale creazione dest)
        DataMatrix_mgr.taDtx2UDC.UpdateUDC(NewUDC, barcodeIn, statoUDC, DateTime.Now, MagClass.magazzino.CodSoggCurrUser, false, false);
        // fix messaggi
        Postazione.messaggiText = traduci("ConfermatoDtx");
        Postazione.warningText = "";
        Postazione.CssClass = cssAtt;
      }
      // disattivo AL (se non era già disattivo...) x evitare si possa togliere senza chiudere...
      MagClass.magazzino.taEA.DisattivaAL(sourceAL);
      return OldUDC;
    }
    /// <summary>
    /// CASO 03: DTX NON in sorgente ma libero/missing in action
    /// </summary>
    /// <param name="NewUDC"></param>
    /// <returns></returns>
    private string procDtx_Caso03(string NewUDC)
    {
      // verifico se sia modalità "rimozione" --> ERRORE!!!
      if (chkDtxMode.Checked)
      {
        Postazione.messaggiText = "";
        Postazione.warningText = traduci("ERR-DTX-018");
        Postazione.CssClass = cssErr;
      }
      else
      {
        // controllo se sia seconda conferma
        if (barcodeIn == lastBarcodeIn)
        {
          lastBarcodeIn = "";
          // in questo caso aggiungo Dtx con la catena della storia precedente
          try
          {
            // vers 2.9 modifica per multi-datamatrix
            currParticolare = partByDtmx(true);
            // vers vecchia
            //currParticolare = DataMatrix_mgr.taDecode.GetData(barcodeIn, "")[0].Particolare;
          }
          catch
          {
            currParticolare = "";
          }
          if (currParticolare != "")
          {
            try
            {
              NewUDC = MagClass.magazzino.taCartellini.getByParticolareAL(currParticolare, destAL)[0].UDC;
            }
            catch
            {
              NewUDC = "";
            }
            if (NewUDC != "")
            {

              // sono in caso di forzatura Dtx, quindi controllo se l'UDC di destinazione esista e abbia qta DataMatrix associati > 0 
              if (DataMatrix_mgr.taDtx2UDC.getByUDC(NewUDC).Rows.Count > 0)
              {
                // riassocio (se possibile) UDC alla nuova storia (se era un DTX x prove dimensionali post TT non cambio la sua storia ma aggiungo relazioni UDC...)
                DataMatrix_mgr.taDtx2UDC.RiassociaDtx(NewUDC, barcodeIn, DateTime.Now, MagClass.magazzino.CodSoggCurrUser);
                // fix messaggi
                Postazione.messaggiText = traduci("ConfermatoDtx");
                Postazione.warningText = "";
                Postazione.CssClass = cssAtt;
                checkUpdateTablet(NewUDC);
              }
              else
              {
                // errore! UDC dest con qta == 0
                Postazione.messaggiText = "";
                Postazione.warningText = traduci("ERR-DTX-005");
                Postazione.CssClass = cssErr;
              }
            }
            else
            {
              Postazione.messaggiText = "";
              Postazione.warningText = traduci("ERR-DTX-001");
              Postazione.CssClass = cssErr;
            }
          }
          else
          {
            Postazione.messaggiText = "";
            Postazione.warningText = traduci("ERR-DTX-002");
            Postazione.CssClass = cssErr;
          }
        }
        // salvo prima conferma del dtx x insert
        else
        {
          lastBarcodeIn = barcodeIn;
          Postazione.messaggiText = traduci("plsConfDtxLoad");
          Postazione.warningText = traduci("ERR-DTX-003");
          Postazione.CssClass = cssAdd;
        }
      }
      return NewUDC;
    }
    /// <summary>
    /// CASO 04: DTX NON in sorgente e NON libero/missing in action
    /// </summary>
    /// <param name="OldUDC"></param>
    /// <param name="IdxPosizione"></param>
    /// <param name="NewUDC"></param>
    private void procDTX_Caso04(ref string OldUDC, ref int IdxPosizione, ref string NewUDC)
    {
      // verifico se sia modalità "rimozione" datamatrix x cui tolgo i datamatrix dall'UDC finale..
      if (chkDtxMode.Checked)
      {
        // chiamo stored di verifica spostabilità (ovvero: dato Dtx è nell'UDC di dest e UDC TL è ancora in carico ad AL sorgente...)
        bool dtxInUdcDest = false;
        bool udcSourceOk = false;
        try
        {
          // ricalcolo vecchio UDC
          OldUDC = ((DS_DataMatrix.Dtx2UDCRow)DataMatrix_mgr.taDtx2UDC.getByDtx(barcodeIn).Select(string.Format("CodStato = '{0}'", statoUDC_pre))[0]).UDC.Replace(flussoAnc, flussoTemp);
          IdxPosizione = MagClass.magazzino.taCartellini.getByUdc(OldUDC)[0].IdxPosizione;
          currParticolare = MagClass.magazzino.taCartellini.getByUdc(OldUDC)[0].Particolare;
          NewUDC = DataMatrix_mgr.taDtx2UDC.getByDtxAl(destAL, barcodeIn)[0].UDC;
          // verifico SE sia in carico ad AL...
          if (OldUDC != "")
          {
            if (MagClass.magazzino.taAL2UDC.getByAL(sourceAL).Select(string.Format("UDC = '{0}'", OldUDC)).Length > 0)
            {
              udcSourceOk = true;
            }
          }
          dtxInUdcDest = DataMatrix_mgr.taDtx2UDC.getByDtx(barcodeIn).Select(string.Format("UDC = '{0}'", NewUDC)).Length > 0;
        }
        catch
        { }
        if (dtxInUdcDest && udcSourceOk)
        {
          // tolgo da AL (se caricato), faccio update e sposto su UDC sorgente...  
          DataMatrix_mgr.taDtx2UDC.UpdateUDC(OldUDC, barcodeIn, statoUDC, DateTime.Now, MagClass.magazzino.CodSoggCurrUser, false, false);
          // fix messaggi
          Postazione.messaggiText = traduci("ToltoDtxDaDest");
          Postazione.warningText = "";
          Postazione.CssClass = cssAtt;
        }
        else
        {
          // segno che NON posso spostare DTX
          Postazione.messaggiText = "";
          Postazione.warningText = traduci("ERR-DTX-010");
          Postazione.CssClass = cssAtt;
        }
      }
      else
      {
        // devo distinguere tra il caso dei Dtx già spostati (quindi segnalare che è già in destinazione)

        // verifico DTX sia in quelli dell'AL destinazione
        if (DataMatrix_mgr.taDtx2UDC.getByDtxAl(destAL, barcodeIn).Rows.Count > 0)
        {
          try
          {
            // vers 2.9 modifica per multi-datamatrix
            currParticolare = partByDtmx(true);
            // vers vecchia
            //currParticolare = DataMatrix_mgr.taDecode.GetData(barcodeIn, "")[0].Particolare;
          }
          catch
          {
            currParticolare = "";
          }
          NewUDC = MagClass.magazzino.taCartellini.getByParticolareAL(currParticolare, destAL)[0].UDC;
          Postazione.messaggiText = barcodeIn;
          Postazione.warningText = traduci("ERR-DTX-006");
          Postazione.CssClass = cssWait;
          // update tablet!
          checkUpdateTablet(NewUDC);
        }
        // ... dal caso generico di un Dtx NON accettabile
        else
        {
          // volendo qui si potrebbe distinguere tra Dtx già con stato Fin e Dtx di RX/TT non ancora preso in carico ai Liquidi
          // errore generico!
          Postazione.messaggiText = barcodeIn;
          Postazione.warningText = traduci("ERR-DTX-004");
          Postazione.CssClass = cssErr;
        }
      }
    }

    #endregion

    /// <summary>
    /// prende in carico AL indicato...
    /// </summary>
    private void presaCaricoAL()
    {
      // salvo presa in carico AL
      string AL = MagClass.magazzino.creaAssociaAlTL(sourceAL, tipoAL.AL_LI, MagClass.magazzino.CodSoggCurrUser, Postazione.currCodCella);
      if (AL != "NA")
      {
        // salva ed indica nuovo AL selezionato...
        sourceAL = AL;
        currAL = sourceAL;
        // nascondo elenco UDC dell'AL
        fixCssAL("success");
        // sistemo grafica
        Postazione.messaggiText = traduci("CaricatoAL");
        Postazione.warningText = "";
        Postazione.CssClass = cssAtt;
      }
      else
      {
        // sistemo grafica
        Postazione.messaggiText = "";
        Postazione.warningText = traduci("ERR-ALL-001");
        Postazione.CssClass = cssErr;
      }
    }
    /// <summary>
    /// resetta AL sorgente
    /// </summary>
    public void resetSourceAL()
    {
      sourceAL = "";
    }
    /// <summary>
    /// aggiorna tabella + focus a barcode
    /// </summary>
    public override void doUpdate()
    {
      base.doUpdate();
      setDefaultVal();
      grViewSource.DataBind();
      grViewDest.DataBind();
      raiseEvent(ucEvType.ReqUpdateParent);
      verificaBtnStampa();
      txtBarcode.Focus();
    }
    /// <summary>
    /// evento selezione grView destinazione: ricarico dati!
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    protected void grViewDest_SelectedIndexChanged(object sender, EventArgs e)
    {
      // ricarico dati dell'UDC come particolare e quantità...
      currUDC = grViewDest.SelectedDataKey["UDC"].ToString();
      int qtaDtx = 0;
      if (MagClass.magazzino.checkUDC(currUDC))
      {
        currParticolare = DataProxy.obj.taCartellini.stp_getByUdc(currUDC)[0].Particolare;
        qta = Convert.ToInt32(DataProxy.obj.taCartellini.stp_getByUdc(currUDC)[0].Qta);
        qtaDtx = Convert.ToInt32(MagClass.magazzino.taA2U2D.getByUDC(currUDC)[0].QtaDtx);
        // imposto particolare...
        lblPart.Text = currParticolare;
        ddlImballi.DataBind();
      }
      Postazione.messaggiText = traduci("partSelected");
      Postazione.warningText = "";
      Postazione.CssClass = cssOk;
      //setVisibility();
      doUpdate();
      // fisso focus su note!
      txtNote.Focus();
      checkUpdateTablet(currUDC);
    }
    /// <summary>
    /// effettua check e update tablet
    /// </summary>
    /// <param name="UDC"></param>
    private void checkUpdateTablet(string UDC)
    {
      if (memLayer.ML.confReadBool("updateTablet"))
      {
        try
        {
          string particolare = "";
          int qtaDtx = 0;
          int qtaTot = 0;
          if (MagClass.magazzino.checkUDC(UDC))
          {
            DS_Applicazione.ElencoCartelliniRow riga = DataProxy.obj.taCartellini.stp_getByUdc(UDC)[0];
            particolare = string.Format("{0} - {1}", riga.Particolare, riga.DescParticolare);
            qtaTot = Convert.ToInt32(DataProxy.obj.taCartellini.stp_getByUdc(UDC)[0].Qta);
            qtaDtx = Convert.ToInt32(MagClass.magazzino.taA2U2D.getByUDC(UDC)[0].QtaDtx);
          }
          // update tablet
          string css = "";
          string mess = "";
          if (qtaDtx > qtaTot)
          {
            css = cssErr;
            mess = traduci("ERR-QTY-001");
          }
          else if (qtaDtx == qtaTot)
          {
            css = cssOk;
            mess = traduci("Ready4Print");
          }
          else
          {
            css = cssWait;
            mess = "-";
          }
          sendUpdateTablet(UDC, particolare, mess, qtaDtx.ToString(), qtaTot.ToString(), string.Format("({0})", qtaDtx - qtaTot), cssOk, cssAtt, css);
        }
        catch (Exception exc)
        {
          logger.lg.scriviLog(string.Format("Errore in fase di check dati x tablet: {0}{1}", Environment.NewLine, exc));
        }
      }
    }
    /// <summary>
    /// prende in carico AL selezionato
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    protected void lbtPrendeCaricoAL_Click(object sender, EventArgs e)
    {
      presaCaricoAL();
      doUpdate();
    }
    /// <summary>
    /// chiude l'AL in carico
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    protected void lbtChiudiAL_Click(object sender, EventArgs e)
    {
      // controllo se UDC rimasti sono tutti a zero e NON ci sono altri datamatrix
      if (assiemeIsEmpty(sourceAL) || forceDelete)
      {
        // chiamo stored x sistemazione AL: 
        MagClass.magazzino.eliminaEmptyAL(sourceAL, MagClass.magazzino.CodSoggCurrUser);
        Postazione.warningText = "";
        Postazione.messaggiText = "";
        Postazione.CssClass = cssAtt;
        // ricarico forzato!
        Response.Redirect("PostLiquidi_DT");
      }
      else
      {
        // altrimenti chiedo conferma per fase spostamenti forzati...
        forceDelete = true;
        Postazione.warningText = traduci("ConfChiusConAnomDtx");
        Postazione.messaggiText = traduci("RichConfChiusAlDtx");
        Postazione.CssClass = cssErr;
      }
      doUpdate();
    }
    /// <summary>
    /// variabile force delete salvata...
    /// </summary>
    protected bool forceDelete
    {
      get
      {
        return memLayer.ML.BoolSessionObj(string.Format("ForceDelAL_{0}", uid));
      }
      set
      {
        memLayer.ML.setSessionVal(string.Format("ForceDelAL_{0}", uid), value);
      }
    }
    /// <summary>
    /// Verifica se Assieme sia vuoto (no DTX negli UDC)
    /// </summary>
    /// <param name="AL">Codice AL</param>
    /// <returns></returns>
    protected bool assiemeIsEmpty(string AL)
    {
      bool answ = false;
      try
      {
        answ = DataMatrix_mgr.taDtx2UDC.getByAL(AL).Rows.Count == 0;
      }
      catch { }
      return answ;
    }
    /// <summary>
    /// reset della selezione
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    public override void btnReset_Click(object sender, EventArgs e)
    {
      grViewDest.SelectedIndex = -1;
      base.btnReset_Click(sender, e);
    }
    /// <summary>
    /// update Qty x UDC selezionato...
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    public override void lbtUpdQty_Click(object sender, EventArgs e)
    {
      base.lbtUpdQty_Click(sender, e);
      // fix tablet
      checkUpdateTablet(currUDC);
      grViewDest.SelectedIndex = -1;
      doUpdate();
    }
    /// <summary>
    /// verifica visibilità btn stampa UDC
    /// </summary>
    private void verificaBtnStampa()
    {
      bool showBtnStampa = false;
      // se ho selezionato udc...
      if (currUDC != "")
      {
        DS_magazzino.v_A2U2DRow riga;
        int qtaUDC = 0;
        int qtaDtx = 0;
        try
        {
          riga = MagClass.magazzino.taA2U2D.getByUDC(currUDC)[0];
          qtaUDC = Convert.ToInt32(riga.Qta);
          qtaDtx = riga.QtaDtx;
        }
        catch
        { }
        if (qtaUDC > 0)
        {
          // se le qta voluta e dtx sono uguali...
          if (qtaUDC == qtaDtx)
          {
            showBtnStampa = true;
          }
        }
      }
      divNote.Visible = showBtnStampa;
    }
    /// <summary>
    /// fornisce in output la corretta classe css x icona
    /// </summary>
    /// <param name="qta"></param>
    /// <param name="qtaDtx"></param>
    /// <returns></returns>
    public string cssGlyphByQty(object _qta, object _qtaDtx)
    {
      string answ = "fa fa-pencil fa-2x";
      int qtaUDC = 0;
      int qtaDtx = -1;
      try
      {
        qtaUDC = Convert.ToInt32(_qta);
      }
      catch { }
      try
      {
        qtaDtx = Convert.ToInt32(_qtaDtx);
      }
      catch { }
      if (qtaUDC == qtaDtx)
      {
        answ = "fa fa-print fa-2x";
      }
      return answ;
    }
    /// <summary>
    /// effettua processo di sistemazione UDC e stampa
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    protected void lbtStampaUDC_Click(object sender, EventArgs e)
    {
      // verifico postazione sia valida...
      if (Postazione.name != "" && Postazione.IP != "" && Postazione.currCodCella != "")
      {
        // in base ad AL sorgente e destinazione, fa le operazioni di update x UDC e poi lo stampa
        bool fatto = false;
        string noteTrim = txtNote.Text.Trim();
        try
        {
          // update UDC!
          fatto = MagClass.magazzino.liquidiFullUpdate(sourceAL, flussoAnc, currUDC, ddlImballi.SelectedValue, noteTrim, MagClass.magazzino.CodSoggCurrUser);
        }
        catch
        { }
        if (fatto)
        {
          // lancio stampa
          MagClass.magazzino.stampaUdc(currUDC, Postazione.printer, tipoCartellino.cartFinitiSP, Request.UserHostName);
          // registro creazione AL
          MagClass.magazzino.taSAO.insertQuery(DateTime.Now, MagClass.magazzino.CodSoggCurrUser, Postazione.name, Postazione.IP, currUDC, currParticolare, "stampaUDC", string.Format("Stampato UDC Dtx {0} su linea {1}, note: {2} ", currUDC, Postazione.currCodLinea, noteTrim));
          Postazione.CssClass = cssAtt;
          Postazione.warningText = "";
          Postazione.messaggiText = traduci("cartAlStampato");
          // calcolo particolare completo di descrizione
          DS_Applicazione.ElencoCartelliniRow riga = DataProxy.obj.taCartellini.stp_getByUdc(currUDC)[0];
          string particolare = string.Format("{0} - {1}", riga.Particolare, riga.DescParticolare);
          // indico su tablet come fatto
          sendUpdateTablet(currUDC, particolare, traduci("cartAlStampato"), qta.ToString(), qta.ToString(), "", cssOk, cssOk, cssOk);
          // resetto...
          grViewDest.SelectedIndex = -1;
          qta = 0;
          currUDC = "";
        }
        doUpdate();
      }
      else
      {
        // ricarico che mi manca postazione!
        Postazione.CssClass = cssAtt;
        Postazione.warningText = traduci("ERR-POS-001");
        Postazione.messaggiText = "";
        Response.Redirect(user_std.pagCorrente);
      }
    }
    /// <summary>
    /// Effettua update della pagina tablet RT collegata alla postazione liquidi
    /// </summary>
    /// <param name="UDC"></param>
    /// <param name="particolare"></param>
    /// <param name="mess"></param>
    /// <param name="qtaIn"></param>
    /// <param name="qtaTot"></param>
    /// <param name="qtaRim"></param>
    /// <param name="css1"></param>
    /// <param name="css2"></param>
    /// <param name="css3"></param>
    protected void sendUpdateTablet(string UDC, string particolare, string mess, string qtaIn, string qtaTot, string qtaRim, string css1, string css2, string css3)
    {
      if (memLayer.ML.confReadBool("updateTablet"))
      {
        try
        {
          string answ = SteamWare.urlUtils.callUrl(string.Format(@"{0}/MBC.aspx?txt01={1}&txt02={2}&txt03={3}&txt04={4}&txt05={5}&txt06={6}&css1={7}&css2={8}&css3={9}", memLayer.ML.confReadString("urlRT"), UDC, particolare, mess, qtaIn, qtaTot, qtaRim, css1, css2, css3), false);
        }
        catch (Exception exc)
        {
          logger.lg.scriviLog(string.Format("Errore in chiamata a pagina Tablet: {0}{1}", Environment.NewLine, exc));
          barcodeIn = "";
        }
      }
    }
    /// <summary>
    /// Imposta e legge imballo selezionato
    /// </summary>
    public override string imballoSel
    {
      get
      {
        return ddlImballi.SelectedValue;
      }
      set
      {
        ddlImballi.SelectedValue = value;
      }
    }
  }
}