using GMW_data;
using SteamWare;
using System;
using System.Data;
using System.Linq;
using System.Web.UI;
namespace GMW.WebUserControls
{
  public partial class mod_post_B48 : System.Web.UI.UserControl
  {
    /// <summary>
    /// Oggetto locale gestione classe datamatrix...
    /// </summary>
    protected DataMatrix DataMatrix_mgr = new DataMatrix();
    /// <summary>
    /// flusso associato (hard coded) a FI
    /// </summary>
    protected string flusso = "FI";
    /// <summary>
    /// stato associato (hard coded) a RX in GitterBox
    /// </summary>
    protected string statoUdcOut = "FinRx";
    /// <summary>
    /// codice evento dell'UDC che si crea
    /// </summary>
    protected string codEventoUdcOut = "UDC_RXF_DT";
    /// <summary>
    /// Qta imbalo desiderato
    /// </summary>
    protected int QtaImballoRXFin
    {
      get
      {
        return memLayer.ML.cdvi("QtaImballoRXFin");
      }
    }
    /// <summary>
    /// stringa UID univoca
    /// </summary>
    public string uid
    {
      get
      {
        return this.UniqueID.Replace("$", "_").Replace("-", "_");
      }
    }
    /// <summary>
    /// flusso associato (hard coded) ad ancestor TT (Trattati)
    /// </summary>
    protected string flussoAnc = "TT";
    /// <summary>
    /// flusso associato (hard coded) a temporaneo TL (Trattati/Liquidi)
    /// </summary>
    protected string flussoTemp = "TL";
    /// <summary>
    /// stato associato (hard coded) a UDC in IN: Trattato da travaso AL
    /// </summary>
    protected string statoUdcIn = "Tratt";
    /// <summary>
    /// codice evento dell'UDC temporaneo (IN) che si crea
    /// </summary>
    protected string codEventoUdcIn = "UDC_TRATT";
    protected string cssOk = "stileComandoOk";
    protected string cssErr = "stileComandoKo";
    protected string cssWait = "stileComandoND";
    protected string cssAtt = "stileAttesa";
    protected string cssWarn = "stileComandoWarn";
    protected string cssAdd = "stileComandoAdd";
    public event EventHandler eh_reqUpdate;
    /// <summary>
    /// ultimo valore barcode letto (x confronto conferme doppio input...)
    /// </summary>
    protected string lastBarcodeIn
    {
      get
      {
        return memLayer.ML.StringSessionObj(string.Format("lastBCode_{0}", uid));
      }
      set
      {
        memLayer.ML.setSessionVal(string.Format("lastBCode_{0}", uid), value, false);
      }
    }
    /// <summary>
    /// Codice AL della cella corrente
    /// </summary>
    protected string destAL
    {
      get
      {
        return lblDestAL.Text.Trim();
      }
      set
      {
        lblDestAL.Text = value;
      }
    }
    /// <summary>
    /// Codice AL associato alla cella corrente...
    /// </summary>
    protected string AlByCella
    {
      get
      {
        string answ = "";
        try
        {
          answ = string.Format("ALF00{0}", Postazione.currCodCella);
          // controllo se esista AL sennò lo creo...
          if (MagClass.magazzino.taEA.getByAL(answ).Rows.Count == 0)
          {
            MagClass.magazzino.taEA.Insert(answ, true, DateTime.Now, MagClass.magazzino.CodSoggCurrUser, "", "", "", 0);
          }
        }
        catch
        { }
        return answ;
      }
    }
    /// <summary>
    /// indica il codice articolo correntemente selezionato
    /// </summary>
    protected string currParticolare
    {
      get
      {
        return memLayer.ML.StringSessionObj(string.Format("currParticolare_{0}", uid));
      }
      set
      {
        memLayer.ML.setSessionVal(string.Format("currParticolare_{0}", uid), value, memLayer.ML.confReadBool("keepParticolareSel"));
      }
    }
    /// <summary>
    /// indica UDC correntemente selezionato
    /// </summary>
    protected string currUDC
    {
      get
      {
        return memLayer.ML.StringSessionObj(string.Format("UDC_{0}", uid));
      }
      set
      {
        memLayer.ML.setSessionVal(string.Format("UDC_{0}", uid), value, memLayer.ML.confReadBool("keepParticolareSel"));
      }
    }
    /// <summary>
    ///  num pezzi dell'ultimo UDC di uguale particolare e stato fatto...
    /// </summary>
    public int pezziUdc
    {
      get
      {
        int answ = 0;
        try
        {
          answ = (int)MagClass.magazzino.taCartellini.getLastByParticolareStatoConImb(memLayer.ML.StringSessionObj("CodCS"), currParticolare, statoUdcOut)[0].Qta;
        }
        catch
        {
          answ = memLayer.ML.cdvi("QtaImballoFiniti");
        }
        return answ;
      }
    }
    /// <summary>
    /// cod imballo dell'ultimo UDC del particolare generato
    /// </summary>
    public string lastCodImb
    {
      get
      {
        string answ = "";
        try
        {
          answ = MagClass.magazzino.taCartellini.getLastByParticolareStatoConImb(memLayer.ML.StringSessionObj("CodCS"), currParticolare, statoUdcOut)[0].CodImballo;
        }
        catch
        {
          answ = memLayer.ML.cdv("CodImballoFiniti");
        }
        return answ;
      }
    }
    /// <summary>
    /// qta pezzi x UDC
    /// </summary>
    public int qta
    {
      get
      {
        int qta = 0;
        try
        {
          qta = Convert.ToInt32(txtQta.Text.Trim());
        }
        catch
        { }
        return qta;
      }
      set
      {
        txtQta.Text = value.ToString();
      }
    }
    /// <summary>
    /// Cod contenitore corrente
    /// </summary>
    public string codContCurr
    {
      get
      {
        return txtCodCont.Text.Trim();
      }
      set
      {
        txtCodCont.Text = value.Trim();
      }
    }
    /// <summary>
    /// Cod contenitore salvato su DB
    /// </summary>
    public string codContSaved
    {
      get
      {
        string codCont = "";
        // cerco attributi UDC
        DS_magazzino.Attr2UDCDataTable tabAttributi = MagClass.magazzino.taAtt2UDC.getByUdc(currUDC);
        if (tabAttributi.Rows.Count > 0)
        {
          try
          {
            var dataRow = tabAttributi.AsEnumerable().Where(x => x.Field<string>("CodAttr") == "CC").FirstOrDefault();
            codCont = dataRow.ValAttr;
          }
          catch
          { }
        }
        // restituisco codice...
        return codCont;
      }
    }
    /// <summary>
    /// wrapper traduzione
    /// </summary>
    /// <param name="lemma"></param>
    /// <returns></returns>
    public string traduci(object lemma)
    {
      return user_std.UtSn.Traduci(lemma.ToString());
    }
    /// <summary>
    /// indica se i caratteri vadano forzati a maiuscoli
    /// </summary>
    public bool forceUppercase
    {
      get
      {
        return memLayer.ML.confReadBool("forceUppercase");
      }
    }
    /// <summary>
    /// Formato Datamatrix della linea selezionata
    /// </summary>
    protected string FormatoDtmxLinea
    {
      get
      {
        string answ = "";
        try
        {
          answ = MagClass.magazzino.taAL.getByKey(Postazione.currCodLinea)[0].FormatoDtmx;
        }
        catch
        { }
        return answ;
      }
    }
    /// <summary>
    /// Formato Datamatrix dell'ultimo barcode letto
    /// </summary>
    protected string FormatoDtmxBarcode
    {
      get
      {
        string answ = "";
        try
        {
          answ = DataMatrix_mgr.taVerifica.GetData(barcodeIn)[0].FormatoDtmx;
        }
        catch
        { }
        return answ;
      }
    }
    /// <summary>
    /// codice particolare da datamatrix
    /// </summary>
    /// <param name="byTable">bollean:
    /// true = utilizza lookUp su tabella dati acquisiti
    /// false = prova a decodificare (da formato Dtmx linea)</param>
    /// <returns></returns>
    protected string partByDtmx(bool byTable)
    {
      string answ = "";
      if (byTable)
      {
        answ = DataMatrix_mgr.taDtxAcquisiti.getByKey(barcodeIn)[0].Particolare; // Decode.GetData(barcodeIn, FormatoDtmxLinea)[0].Particolare;
      }
      else
      {
        answ = DataMatrix_mgr.taDecode.GetData(barcodeIn, FormatoDtmxLinea)[0].Particolare;
      }
      return answ;
    }
    /// <summary>
    /// valore barcode
    /// </summary>
    public string barcodeIn
    {
      get
      {
        return txtBarcode.Text.Trim();
      }
      set
      {
        txtBarcode.Text = value;
      }
    }
    /// <summary>
    /// caricamento pagina
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    protected void Page_Load(object sender, EventArgs e)
    {
      if (!Page.IsPostBack)
      {
        Postazione.messaggiText = "";
        Postazione.warningText = "";
        qta = 0;
        currUDC = "";
        forceDelete = false;
        setDefaultVal();
        checkNumKeyIn();
      }
      setVisibility(!Page.IsPostBack);
      checkBarcode();
    }
    /// <summary>
    /// verifico se ci sia in sessione un input da NumKeyb e nel caso lometto in barcodeIn e processo...
    /// </summary>
    private void checkNumKeyIn()
    {
      if (memLayer.ML.isInSessionObject("numKeyIn"))
      {
        barcodeIn = memLayer.ML.StringSessionObj("numKeyIn");
        // svuoto valore in sessione...
        memLayer.ML.emptySessionVal("numKeyIn");
        // controllo barcode...
        checkBarcode();
      }
    }
    /// <summary>
    /// imposta i valori di default ad avvio
    /// </summary>
    private void setDefaultVal()
    {
      destAL = AlByCella;
    }
    /// <summary>
    /// sistema modalità input
    /// </summary>
    /// <param name="forceReloadImb">forza reload imballo?</param>
    private void setVisibility(bool forceReloadImb)
    {
      bool showBtn = false;
      // controllo btn quantità
      if (grViewDest.SelectedIndex >= 0)
      {
        showBtn = true;
      }
      divQta.Visible = showBtn;
      divImballi.Visible = showBtn;
      divConten.Visible = showBtn;
      if (showBtn && forceReloadImb)
      {
        // sistemo CodContenitore
        tryFixCodCont();
        // verifico se sistemare imballo
        if (forceReloadImb)
        {
          selezionaImballo();
        }
      }
    }
    protected void tryFixCodCont()
    {
      // imposto codice da quello salvato (SE C'E')...
      codContCurr = codContSaved;
      lbtUpdateCodCont.Visible = false;
    }
    /// <summary>
    /// reset maschera...
    /// </summary>
    public void doReset()
    {
      // rimuovo selezione eventuale UDC
      grViewDest.SelectedIndex = -1;
      codContCurr = "";
      // resetta
      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 = "stileComandoOk";
      }
      else
      {
        Postazione.warningText = traduci("ErroreAlNonTtAttivo");
        Postazione.CssClass = "stileComandoKo";
      }
      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 = "stileComandoKo";
      }
      else
      {
        Postazione.warningText = "";
        Postazione.CssClass = "stileComandoOk";
      }
      return answ;
    }
    /// <summary>
    /// controlla se ci sia un barcode e cosa farne...
    /// </summary>
    private void checkBarcode()
    {
      if (barcodeIn != "")
      {
        Postazione.messaggiText = string.Format("{0}: {1}", traduci("BCodeIns"), barcodeIn);
        tipoCodiceBarcode tipoBC = MagClass.tipoBCode_L5(barcodeIn);
        switch (tipoBC)
        {
          case tipoCodiceBarcode.Operatore:
            // calcolo matricola utente
            int MatrUtente = -1;
            string preCodSogg = memLayer.ML.AppConf["prefCodSogg"];
            if (barcodeIn.StartsWith(preCodSogg))
            {
              MatrUtente = DataProxy.obj.taTrascSogg.getByKey(barcodeIn, 0)[0].CodMatricola;
            }
            else
            {
              MatrUtente = Convert.ToInt32(barcodeIn);
            }
            if (MatrUtente >= 0)
            {
              // salvo in sessione operatore con AUTH
              OpAuth.startOpAuth(MatrUtente);
              // mostro che ho autorizzato...
              Postazione.messaggiText += traduci("userAuthRec");
              Postazione.CssClass = "stileComandoOk";
              Response.Redirect(user_std.pagCorrente);
            }
            else
            {
              Postazione.messaggiText += " - codice <b>non riconosciuto</b>!";
              Postazione.CssClass = "stileComandoND";
            }
            break;
          case tipoCodiceBarcode.Imballo:
            // cerco di selezionare!
            try
            {
              ddlImballi.SelectedValue = barcodeIn;
            }
            catch
            {
              Postazione.warningText = traduci("ERR-IMB-001");
              Postazione.CssClass = "stileComandoKo";
            }
            break;
          case tipoCodiceBarcode.Comando:
            // se è reset cancello tutto!
            if (barcodeIn == memLayer.ML.cdv("cmdReset"))
            {
              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 == statoUdcOut && 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 sia UDC in LDP e già PRELEVATO
                    if (MagClass.magazzino.taRigheListePrelievo.getByUdc(barcodeIn).Select("Prelevato = 1").Length == 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
                      {
                        // se è ok RICARICO UDC in posizione corrente...
                        bool fatto = MagClass.magazzino.finRxRiprendiInCaricoUDC(barcodeIn, MagClass.magazzino.CodSoggCurrUser, destAL, Postazione.currIdxCella);
                        if (fatto)
                        {
                          Postazione.messaggiText = traduci("RiCaricatoUdcLiq");
                          Postazione.warningText = "";
                          Postazione.CssClass = cssOk;
                        }
                        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.DataMatrixTrovato:
            // ciclo controllo x B48
            string NewUDC = "";
            // verifica preliminare: se Dtx OK procedo, se è KO NON LO CONSIDERO PROPRIO
            bool isOk = false;
            // controllo anche NC
            bool isOkNc = false;
            // controllo sia libero (= non assegnato)
            bool isFree = false;
            try
            {
              isOk = DataMatrix_mgr.taVerifica.GetData(barcodeIn)[0].StatoDtx == "OK";
            }
            catch
            { }
            try
            {
              isOkNc = DataMatrix_mgr.taAtt2Dtx.getByDtx(barcodeIn).Select("CodAttr = 'XF'").Length == 0;
            }
            catch
            { }
            try
            {
              isFree = DataMatrix_mgr.taDtx2UDC.getByDtx(barcodeIn).Rows.Count == 0;
            }
            catch
            { }
            // controlli x procedere
            if (!isOkNc && !chkDtxMode.Checked)
            {
              // non accetto Dtx e mostro errore
              Postazione.messaggiText = barcodeIn;
              Postazione.warningText = traduci("ERR-DTX-016");
              Postazione.CssClass = cssErr;
            }
            else if (!isOk && !chkDtxMode.Checked)
            {
              // non accetto Dtx e mostro errore
              Postazione.messaggiText = barcodeIn;
              Postazione.warningText = traduci("ERR-DTX-012");
              Postazione.CssClass = cssErr;
            }
            else if (!isFree && !chkDtxMode.Checked)
            {
              // non accetto Dtx e mostro errore
              Postazione.messaggiText = barcodeIn;
              Postazione.warningText = traduci("ERR-DTX-017");
              Postazione.CssClass = cssErr;
            }
            else if (isFree && chkDtxMode.Checked)
            {
              // non accetto Dtx e mostro errore
              Postazione.messaggiText = barcodeIn;
              Postazione.warningText = traduci("ERR-DTX-018");
              Postazione.CssClass = cssErr;
            }
            else // PROCEDO!!!
            {
              // controllo formato datamatrix sia impostato sulla linea (altrimenti errore linea "non battezzata")
              if (string.IsNullOrEmpty(FormatoDtmxLinea))
              {
                // errore poiché non è stato non specificato tipo Dtmx assegnato alla linea!
                Postazione.messaggiText = barcodeIn;
                Postazione.warningText = traduci("ERR-DTX-013");
                Postazione.CssClass = "stileComandoKo";
              }
              else
              {
                // verifico formato datamatrix letto sia quello della linea...
                if (FormatoDtmxBarcode != FormatoDtmxLinea)
                {
                  // errore corrispondenza formato Dtmx
                  Postazione.messaggiText = barcodeIn;
                  Postazione.warningText = traduci("ERR-DTX-014");
                  Postazione.CssClass = "stileComandoKo";
                }
                else
                {
                  // calcolo particolare + UDC dest
                  try
                  {
                    currParticolare = partByDtmx(true);
                    // se non ho UDC lo creo...
                    checkCreaUDC();
                    // verifico se ho UDC...
                    NewUDC = MagClass.magazzino.taCartellini.getByParticolareAL(currParticolare, destAL)[0].UDC;
                  }
                  catch (Exception exc)
                  {
                    logger.lg.scriviLog(string.Format("Errore in decodifica particolare da DataMatrix:{0}dtx:{1}{0}Eccezione:{0}{2}", Environment.NewLine, barcodeIn, exc), tipoLog.EXCEPTION);
                    NewUDC = "";
                  }
                  // ora proseguo...
                  if (currParticolare != "" && NewUDC != "")
                  {
                    // chiamo procedure aggiunta/rimozione secondo caso di selezione ADD/REM Dtx
                    if (!chkDtxMode.Checked)
                    {
                      Postazione.messaggiText = string.Format("{0}: {1}", traduci("DtxAdd"), barcodeIn);
                      Postazione.CssClass = "stileComandoOk";
                      procDtx_add(ref NewUDC);
                    }
                    // modalità "rimozione" datamatrix 
                    else
                    {
                      Postazione.messaggiText = string.Format("{0}: {1}", traduci("DtxRem"), barcodeIn);
                      Postazione.CssClass = "stileComandoWarn";
                      procDtx_rem(ref NewUDC);
                    }
                  }
                }
              }
            }
            break;
          default:
            Postazione.warningText = traduci("ERR-BCD-001");
            Postazione.CssClass = cssErr;
            break;
        }
        barcodeIn = "";
      }
      doUpdate();
    }
    /// <summary>
    /// crea eventualmente UDC per particolare
    /// </summary>
    /// <param name="qty"></param>
    /// <param name="particolare"></param>
    private void checkCreaUDC()
    {
      string newUdcChild = "";
      string noteTrim = "";
      DateTime adesso = DateTime.Now;
      // verifico se ho già quel particolare tra quelli inseriti in linea...
      try
      {
        newUdcChild = DataProxy.obj.taCartellini.getByParticolareIdxPosIdxCella(currParticolare, memLayer.ML.cdvi("IdxPosizioneRxFinTemp"), Postazione.currIdxCella)[0].UDC;
      }
      catch
      {
        newUdcChild = "";
      }
      if (string.IsNullOrEmpty(newUdcChild))
      {
        // controllo NON ci siano troppi UDC in posizione... da capienza ed assegnati
        DS_magazzino.V_statoCelleCapienzaAssegnatiRow riga;
        bool piena = false;
        try
        {
          riga = MagClass.magazzino.taStatoCelle.getByIdxCella(Postazione.currIdxCella)[0];
          if (riga.UdcAssegnati >= riga.Capienza)
          {
            piena = true;
          }
        }
        catch
        {
        }
        if (!piena)
        {
          try
          {
            // forzo qta a 0 x generare nuovo UDC
            qta = 0;
            // creo nuovo UDC RX
            newUdcChild = MagClass.magazzino.creaUdc(flusso, "", currParticolare, "", "", "", "", "", 0, memLayer.ML.cdv("CodImballoRX"), "U", MagClass.magazzino.CodSoggCurrUser, qta, 0, 0, adesso, 0, statoUdcOut, memLayer.ML.cdvi("IdxPosizioneRxFinTemp"), "IdxPosizioneRxFinTemp", codEventoUdcOut, noteTrim, "", adesso.Year, Request.UserHostName);
            // lo associo all'AL...
            MagClass.magazzino.taAL2UDC.Insert(destAL, newUdcChild, adesso, MagClass.magazzino.CodSoggCurrUser);
          }
          catch (Exception exc)
          {
            logger.lg.scriviLog(string.Format("Errore in creazione UDC temp RX Fin: {0}{1}", Environment.NewLine, exc));
          }
        }
        else
        {
          Postazione.warningText = traduci("ErroreAL-Full");
          doUpdate();
        }
      }
      if (newUdcChild != "")
      {
        // lo posiziono nella cella corrente...
        MagClass.magazzino.spostaUDC(memLayer.ML.StringSessionObj("CodCS"), newUdcChild, Postazione.currIdxCella, memLayer.ML.confReadBool("spostaUdcResettaLdp"), Request.UserHostName);
        Postazione.CssClass = "stileAttesa";
        Postazione.warningText = "";
        Postazione.messaggiText = traduci("partAdded");
        doUpdate();
      }
    }


    #region metodi processing DataMatrix letto da BarCode
    /// <summary>
    /// processa aggiunta datamatrix (SE POSSIBILE)
    /// </summary>
    /// <param name="NewUDC"></param>
    private void procDtx_add(ref string NewUDC)
    {
      // genera eventuale UDC del particolare su cella/posizione corrente
      qta = 1; // tanto poi si ricalcola...
      checkCreaUDC();
      // controllo che il DTX non sia già assegnato...
      if (DataMatrix_mgr.taDtx2UDC.getByDtx(barcodeIn).Rows.Count == 0)
      {
        // verifico NON CI SIANO attributi DC pendenti (nel qual caso memorizzo primo comando e poi chiedo conferma... !!!FARE!!!
        bool hasXQ = false;
        if (DataMatrix_mgr.taAtt2Dtx.getByDtx(barcodeIn).Rows.Count > 0)
        {
          // cerco se abbia "XQ"...
          if (DataMatrix_mgr.taAtt2Dtx.getByDtx(barcodeIn).Select("CodAttr = 'XQ'").Length > 0)
          {
            hasXQ = true;
          }
        }
        if (hasXQ)
        {
          // verifico se c'è già in sessione la lettura di questo DataMatrix...
          if (memLayer.ML.StringSessionObj("prevDmtx") == barcodeIn)
          {
            // è seconda lettura: allora procedo
            hasXQ = false;
            // svuoto da sessione
            memLayer.ML.emptySessionVal("prevDmtx");
          }
        }
        // se non ho pendenze...
        if (!hasXQ)
        {
          // chiamo la stored che associa Dtx a UDC
          DataMatrix_mgr.taDtx2UDC.RxSetDtx2Udc(barcodeIn, MagClass.magazzino.CodSoggCurrUser, statoUdcOut, memLayer.ML.cdvi("IdxPosizioneRxFinTemp"), Postazione.currIdxCella);
        }
        else
        {
          // mostro messaggio che chiede  seconda lettura conferma e salvo in sessione...
          Postazione.messaggiText = barcodeIn;
          Postazione.warningText = traduci("B48_ReadTwiceToConfirm");
          Postazione.CssClass = "stileComandoWarn";
          // salvo in sessione dmtx x conferma
          memLayer.ML.setSessionVal("prevDmtx", barcodeIn);
        }
      }
    }
    /// <summary>
    /// processa rimozione datamatrix (se possibile)
    /// </summary>
    /// <param name="NewUDC"></param>
    private void procDtx_rem(ref string NewUDC)
    {
      // verifico sia nell'UDC dest
      if (DataMatrix_mgr.taDtx2UDC.getByDtxAl(destAL, barcodeIn).Rows.Count != 0)
      {
        // rimuovo Dtx
        DataMatrix_mgr.taDtx2UDC.deleteQuery(DataMatrix_mgr.taDtx2UDC.getByDtxAl(destAL, barcodeIn)[0].UDC, barcodeIn, MagClass.magazzino.CodSoggCurrUser, memLayer.ML.cdvi("IdxPosizioneRxFinTemp"), Postazione.currIdxCella);
        // assegno Attributo x indicare che è stato rimosso...
        DataMatrix_mgr.taAtt2Dtx.insertAndProc(barcodeIn, true, "XQ", "Rim. UDC B48", DateTime.Now, MagClass.magazzino.CodSoggCurrUser);
      }
    }
    #endregion
    /// <summary>
    /// aggiorna tabella + focus a barcode
    /// </summary>
    public void doUpdate()
    {
      // refresh!
      setDefaultVal();
      setVisibility(!Page.IsPostBack);
      grViewDest.DataBind();
      // raise dell'evento
      if (eh_reqUpdate != null)
      {
        eh_reqUpdate(this, new EventArgs());
      }
      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 = "stileComandoOk";
      setVisibility(true);
      doUpdate();
      // fisso focus su note!
      txtNote.Focus();
    }
    /// <summary>
    /// prende in carico AL selezionato
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    protected void lbtPrendeCaricoAL_Click(object sender, EventArgs e)
    {
      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>
    protected void btnReset_Click(object sender, EventArgs e)
    {
      grViewDest.SelectedIndex = -1;
      qta = 0;
      currUDC = "";
      setVisibility(false);
      doUpdate();
    }
    /// <summary>
    /// update Qty x UDC selezionato...
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    protected void lbtUpdQty_Click(object sender, EventArgs e)
    {
      MagClass.magazzino.taCartellini.updateQty(currUDC, MagClass.magazzino.CodSoggCurrUser, "U", codEventoUdcOut, qta);
      currUDC = "";
      currParticolare = "";
      grViewDest.SelectedIndex = -1;
      doUpdate();
    }
    /// <summary>
    /// update cod contenitore x UDC selezionato
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    protected void lbtUpdateCodCont_Click(object sender, EventArgs e)
    {
      // sistemo attributi UDC           
      DateTime adesso = DateTime.Now;
      // elimino eventuale PRECEDENTE valore... 
      MagClass.magazzino.taAtt2UDC.deleteByPar(currUDC, "CC");
      MagClass.magazzino.taAtt2UDC.upsertVal(currUDC, "CC", codContCurr, adesso, MagClass.magazzino.CodSoggCurrUser);
      lbtUpdateCodCont.Visible = false;
      verificaBtnStampa();
    }
    /// <summary>
    /// richiesta (ri)stampa UDC
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    public void ristampa()
    {
      bool fatto = false;
      fatto = MagClass.magazzino.ristampaUdc(udcReq, Postazione.printer, Request.UserHostName);
      // registro ri-stampa UDC
      if (fatto)
      {
        MagClass.magazzino.taSAO.insertQuery(DateTime.Now, MagClass.magazzino.CodSoggCurrUser, Postazione.name, Postazione.IP, udcReq, "", "stampaUDC", string.Format("Ri-Stampato UDC Dtx {0} su linea {1}", currUDC, Postazione.currCodLinea));
      }
    }
    /// <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 && (qtaUDC <= QtaImballoRXFin))
        {
          // se il cod contenitore != ""
          if (codContCurr != "" && codContSaved != "")
          {
            // 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) && (qtaUDC == QtaImballoRXFin))
      {
        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 != "")
      {
        // 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.Udc_B48_FullUpdate(currUDC, ddlImballi.SelectedValue, noteTrim, MagClass.magazzino.CodSoggCurrUser);
        }
        catch
        { }
        if (fatto)
        {
          // lancio stampa
          MagClass.magazzino.stampaUdc(currUDC, Postazione.printer, tipoCartellino.cartFinitiRxSP, 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 RxFin {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);
          // 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>
    /// udc da stampare
    /// </summary>
    protected string udcReq
    {
      get
      {
        return memLayer.ML.StringSessionObj("udcSelSAO");
      }
    }
    /// <summary>
    /// preseleziono (se possibile) imballo...
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    protected void ddlImballi_DataBound(object sender, EventArgs e)
    {
      selezionaImballo();
    }
    /// <summary>
    /// seleziona imballo corretto
    /// </summary>
    private void selezionaImballo()
    {
      string codImb = "";
      // cerco se c'è un imballo x particolare corrente...
      if (currParticolare != "")
      {
        codImb = lastCodImb;
      }
      else
      {
        codImb = memLayer.ML.cdv("CodImballoFiniti");
      }
      try
      {
        // preseleziono
        ddlImballi.SelectedValue = codImb;
      }
      catch
      { }
    }
    protected void txtCodCont_TextChanged(object sender, EventArgs e)
    {
      lbtUpdateCodCont.Visible = true;
    }
  }
}