Browse Source

* Some fix with AS400

Giancarlo Voci 8 years ago
parent
commit
03faf9b933

+ 2 - 0
cfg/config - dimatec.ini

@@ -34,3 +34,5 @@ pass=ZrgzkvJrOKnNSCnPnGz3u{A6eHSNXVvs
 MV_ADDRESS=192.168.253.130
 MV_ADDRESS=192.168.253.130
 DB2_ADDRESS=192.168.0.100
 DB2_ADDRESS=192.168.0.100
 
 
+[FINDBOXSERVICE]
+SLEEPTIME=1

+ 1 - 1
cfg/config.bin

@@ -1 +1 @@
-eJx1kVmPmzAUhd8t+T+gqA+tqrJmnchSCbjADEvEEo06GiFCHIICmAJJZxLlv9dkMu1DWyQjsM+5/s69T1lB10nRPkOgRqFne6qOBm2TCgMINFUzMYe40I8wBJGFDrkAgY4XkYFkCLCrebrlGmgQhd++TJnBtAzTZitEW1aSQHCv+jx5qfOGoPO5y0vy8dNnRRopY1EULxdWK3DRoHxtfxR3O9p2qKBpUvRf85o2HVIUcTzfrKukJIiWRV7t2SWb9aElDWoo7fqfOmlblOVJlSZNQSGY37Y8x5hNp3Q7/QDB0lzGSzU0kXYnVFlevQj1rp70L0bHMB31MV7YlvsQh5aD4wBrSJJFCFg1bpl0OwgWaoAj30bCGwYEgRViV3Uw0vMy6UgKge0ZXqxFQeg52Gdxv948l4vA+sZUGWmFm9qmGeXrKoPA0jw37q1R+D9PwcSH7k3eEwWkIGnH/dzl6Y5LD21HS9JwacFSc6RK1gVL9M5xRdy8I0LwpHk+5rdrNu5rw6WZzEvjKS/x0pAFvnZ9JA6HCgR78oo08c8jScPJUJQVcTRhwr7F35vstD/eN95D5QZatayMk3I4q2NiBu7j6theL1xhP7Q01WY8vmrg5z6Bk2TJ6ZRXlDuSpsvZzAnHNA47c1axqus+DoLfbCKvzNiM/j6QRwovKQxbX8j/cEnidYS/AOy/18o=
+eJx1kWtvmzAUhr9b8n9A0T5smsYl5NrI0gi4QMsl4hJFiypEiENQAVMgWZso/30mTbcP25CMwH7f4+c9Z53mdBPnzRMEShi4lqtoqNfUidCDQFVUA3OIC7wQQxCa6JAJEGh4HuqoDwF2VFczHR31wuD+24QZDFM3LLYCtGMlCQQPiseT1yqrCTqf26wgn798laWhPBJF8XJhtXwH9Yq35iW/29OmRTlN4rz7mlW0bpEsi6PZdlPGBUG0yLPymV2y3RwaUqOa0rb7qeKmQWkWl0lc5xSC2W3LtfXpZEJ3k08QLIxFtFACA6l3Qplm5atQ7atx92J0DNNWVtHcMp3HKDBtHPlYRVJfhIBV4xZxu4dgrvg49CwkvGNA4JsBdhQbIy0r4pYkEFiu7kZq6AeujT0W9/vNc7kIrG9MlZJGuKktmlK+KlMITNV1os4aBv/z5Ex8aN/lHZFPcpK03M99luy55NC0tCA1l+QsNUfKeJOzRB8cV8TtByIEa9X1ML/bsHFfGy5N+7w0mvASLw1Y4GvXh+JgIEPwTN6QKv55JGkwHoh9WRyOmbBr8Y86PT0fH2r3sXR8tVyU+kk+nJURMXxntTw21wuX2AtMVbEYj6fo+KlLYMdpfDplJeWOpG4zNnPCMY3NzuxlpGiah33/N5vIy1M2o78P+kOZl2SGrc37/3BJ4nWE63vT0ebuysfe0lQ7AN/CeNFNGkkQ/AKcAt/h

+ 3 - 2
src/Modules/Dimatec/Dimatec.php

@@ -14,10 +14,11 @@ class Dimatec extends PluginStrategy
 {
 {
   public function __construct()
   public function __construct()
   {
   {
-    if (\F3::get('CUSTOMERNAME') != 'dimatec')
+    global $f3;
+    if ($f3->get('CUSTOMERNAME') != 'dimatec')
       return;
       return;
 
 
-    \F3::config('cfg/labels.ini', true);
+    $f3->config('cfg/labels.ini', true);
 
 
     $this->AddRoute('GET|POST /pick2light/@step', __NAMESPACE__ . '\Pages->Pick2Light');
     $this->AddRoute('GET|POST /pick2light/@step', __NAMESPACE__ . '\Pages->Pick2Light');
     $this->AddRoute("GET|POST /bind", __NAMESPACE__ . '\Pages->Bind');
     $this->AddRoute("GET|POST /bind", __NAMESPACE__ . '\Pages->Bind');

+ 2 - 3
src/Modules/Dimatec/Distinta.php

@@ -7,8 +7,6 @@
 
 
 namespace Modules\Dimatec;
 namespace Modules\Dimatec;
 
 
-use OpenMind\System\Soap;
-
 class Distinta
 class Distinta
 {
 {
   /** @var \DB\SQL $dbHandle */
   /** @var \DB\SQL $dbHandle */
@@ -72,7 +70,8 @@ class Distinta
    */
    */
   public function MarkBarcodeAsAnomalia(string $barcode): array
   public function MarkBarcodeAsAnomalia(string $barcode): array
   {
   {
-    $CORE_SETTINGS = \F3::get('CORE.fb');
+    global $f3;
+    $CORE_SETTINGS = $f3->get('CORE.fb');
     $findBoxCore = new FindBoxCoreSystem(...array_values($CORE_SETTINGS));
     $findBoxCore = new FindBoxCoreSystem(...array_values($CORE_SETTINGS));
     $lblId = $this->GetLabelIdFromBarcode($barcode);
     $lblId = $this->GetLabelIdFromBarcode($barcode);
     $label = new SmartESL($findBoxCore, [$lblId]);
     $label = new SmartESL($findBoxCore, [$lblId]);

+ 180 - 27
src/Modules/Dimatec/MigrationData.php

@@ -10,11 +10,29 @@ namespace Modules\Dimatec;
 
 
 use DB\SQL;
 use DB\SQL;
 
 
+// DB2 Connection
+define('DB2DSN', "odbc:Driver={iSeries Access ODBC Driver};DefaultLibraries=SMEDAT_DIM;SYSTEM=");
+define('DB2UID', 'icam');
+define('DB2PWD', 'icam');
+
+// MAV DB Connection
+define('MAVDBDSN', "sqlsrv:Database=icamdbstore;Encrypt=false;TrustServerCertificate=false;Server=");
+define('MAVDBUID', 'sa');
+define('MAVDBPWD', 'sa');
+
 class MigrationData
 class MigrationData
 {
 {
+
+  const STATUS_NEW = 0;
+  CONST STATUS_PENDING = 50;
+  CONST STATUS_DONE = 80;
+
   /** @var SQL $dbHandle DB2 */
   /** @var SQL $dbHandle DB2 */
   private $dbHandle;
   private $dbHandle;
 
 
+  /** @var SQL $dbHandle MSSQL Server */
+  private $dbMAVHandle;
+
   /** @var \SoapClient $soapClient MAV client */
   /** @var \SoapClient $soapClient MAV client */
   private $soapClient;
   private $soapClient;
 
 
@@ -25,6 +43,15 @@ class MigrationData
   private $finalXml;
   private $finalXml;
   private $listXml;
   private $listXml;
 
 
+  // The ids of current articles to move from DB2 to MAV
+  private $db2RowsId = [];
+
+  public function ClearCachedIDs()
+  {
+    global $System;
+    $System->getCache()->clear('db2RowsId');
+  }
+
   /**
   /**
    * Create the connection client to a SOAP server
    * Create the connection client to a SOAP server
    * @param string $serverAddress IP Address
    * @param string $serverAddress IP Address
@@ -38,26 +65,78 @@ class MigrationData
     ));
     ));
   }
   }
 
 
+  /**
+   * Get all missions from DB2 without status 0
+   * @param string $operationType
+   */
+  public function selectAvailableMissions(string $operationType)
+  {
+    global $System;
+
+    $filter = $this->fixOperationTypeValue($operationType);
+
+    $this->db2RowsId = array_column($this->query("SELECT MXIDDM FROM SMEDAT_DIM.INTMAV0F WHERE $filter AND MXSTAT=0"), 'MXIDDM');
+    $System->getCache()->set('db2RowsId', $this->db2RowsId);
+
+  }
+
+  /**
+   * Set mission status on AS400
+   * @param int $status
+   * @param $listaId
+   */
+  public function MarkMissions(int $status, $listaId)
+  {
+    global $System;
+
+    $this->db2RowsId = $System->getCache()->get('db2RowsId');
+    $ids = join(", ", $this->db2RowsId);
+    $this->query("UPDATE SMEDAT_DIM.INTMAV0F SET MXSTAT=$status, MXNOLS='$listaId' WHERE MXIDDM IN ($ids)");
+  }
+
+  public function SetMissionsBarcodes(string $barcode, string $commessa)
+  {
+    global $System;
+
+    $this->db2RowsId = $System->getCache()->get('db2RowsId');
+    $ids = join(", ", $this->db2RowsId);
+    $this->query("UPDATE SMEDAT_DIM.INTMAV0F SET MXNCON='$barcode' WHERE MXCORD='$commessa' AND MXIDDM IN ($ids)");
+  }
+
+
+  /**
+   * MAV DB constructor.
+   * @param string $serverAddress IP Address
+   */
+  public function MAVDatabaseConnector()
+  {
+    global $f3;
+    $this->dbMAVHandle = new SQL(
+      MAVDBDSN . $f3->get('VERTICALSTORAGE.MV_ADDRESS'),
+      MAVDBUID, MAVDBPWD,
+      array(\PDO::ATTR_ERRMODE => \PDO::ERRMODE_EXCEPTION));
+  }
+
   /**
   /**
    * PDO constructor.
    * PDO constructor.
    * @param string $serverAddress IP Address
    * @param string $serverAddress IP Address
    */
    */
-  public function DatabaseConnector(string $serverAddress)
+  public function DB2Connector()
   {
   {
+    global $f3;
     $this->dbHandle = new SQL(
     $this->dbHandle = new SQL(
-      "odbc:Driver={iSeries Access ODBC Driver};DefaultLibraries=SMEDAT_DIM;SYSTEM=$serverAddress;",
+      DB2DSN . $f3->get('VERTICALSTORAGE.DB2_ADDRESS'),
       'icam', 'icam',
       'icam', 'icam',
       array(\PDO::ATTR_ERRMODE => \PDO::ERRMODE_EXCEPTION));
       array(\PDO::ATTR_ERRMODE => \PDO::ERRMODE_EXCEPTION));
   }
   }
 
 
   /**
   /**
    * @param $sql
    * @param $sql
-   * @param int $mode default \PDO::FETCH_ASSOC
    * @return array
    * @return array
    */
    */
-  public function query($sql, $mode = \PDO::FETCH_ASSOC): array
+  public function query($sql)
   {
   {
-    return $this->dbHandle->exec($sql, $mode);
+    return $this->dbHandle->exec($sql);
   }
   }
 
 
   /**
   /**
@@ -113,9 +192,9 @@ EOF;
    */
    */
   public function copyAllToAS400($data): bool
   public function copyAllToAS400($data): bool
   {
   {
-    $this->dbHandle->exec("TRUNCATE TABLE INTMUB0F");
+    $this->dbHandle->exec("TRUNCATE TABLE SMEDAT_DIM.INTMUB0F");
     foreach($data as $key => $value) {
     foreach($data as $key => $value) {
-      $this->dbHandle->exec("INSERT INTO INTMUB0F (UXSTAT, UXCOAP, UXQTGC, UXQTMA) VALUES (10, '${value['UXCOAP']}', ${value['UXQTGC']}, ${value['UXQTMA']})");
+      $this->dbHandle->exec("INSERT INTO SMEDAT_DIM.INTMUB0F (UXSTAT, UXCOAP, UXQTGC, UXQTMA) VALUES (10, '${value['UXCOAP']}', ${value['UXQTGC']}, ${value['UXQTMA']})");
     }
     }
   }
   }
 
 
@@ -140,14 +219,48 @@ EOF;
   {
   {
     $filter = $this->fixOperationTypeValue($operationType);
     $filter = $this->fixOperationTypeValue($operationType);
 
 
+    $status = MigrationData::STATUS_NEW;
     return <<<EOF
     return <<<EOF
 SELECT MXCORD, MXARTI, MXDESC, MXRIFC, SUM(MXQTMI) AS QTY
 SELECT MXCORD, MXARTI, MXDESC, MXRIFC, SUM(MXQTMI) AS QTY
 FROM SMEDAT_DIM.INTMAV0F
 FROM SMEDAT_DIM.INTMAV0F
-WHERE $filter AND MXSTAT<>80
+WHERE $filter AND MXSTAT=$status
 GROUP BY MXARTI, MXCORD, MXDESC, MXRIFC
 GROUP BY MXARTI, MXCORD, MXDESC, MXRIFC
 ORDER BY MXCORD, MXARTI
 ORDER BY MXCORD, MXARTI
 EOF;
 EOF;
+  }
+
+  /**
+   * Ritorna la query di massificazione (raggruppamento delle quantità per codice articolo ignorando la prebolla) dalla tabella INTMAVOF
+   *
+   * @param string $operationType values: 'CARICO' or 'SCARICO'
+   * @return string
+   */
+  public function strQueryPerMAV(string $operationType): string
+  {
+    $filter = $this->fixOperationTypeValue($operationType);
+
+    $status = MigrationData::STATUS_NEW;
+    return <<<EOF
+SELECT MXARTI, MXDESC, SUM(MXQTMI) AS QTY
+FROM (SELECT * FROM SMEDAT_DIM.INTMAV0F ORDER BY MXCORD) AS tbl
+WHERE $filter AND MXSTAT={$status}
+GROUP BY MXARTI, MXDESC
+EOF;
+  }
 
 
+  /**
+   * Query da eseguire sul database di OM-Link, ottiene una lista massificata per quantità articolo, UDS e ordinata per esso
+   *
+   * @return string
+   */
+  public function strQueryMassificazioneByUDS(): string
+  {
+    return <<<EOF
+SELECT `uds`, `barcode`, `descrizione`, SUM(`qta_prelevare`) AS `qta`
+FROM `distinte`
+GROUP BY `barcode`
+ORDER BY `uds`
+EOF;
   }
   }
 
 
   /**
   /**
@@ -155,8 +268,9 @@ EOF;
    *
    *
    * @param string $operationType values: 'CARICO' or 'SCARICO'
    * @param string $operationType values: 'CARICO' or 'SCARICO'
    * @param iterable $data
    * @param iterable $data
+   * @return string return id list
    */
    */
-  public function soapCompileFrom(iterable $data, string $operationType)
+  public function soapCompileFrom(iterable $data, string $operationType): string
   {
   {
     $idList = 'ID-' . uniqid();
     $idList = 'ID-' . uniqid();
     $dateTime = date("d/m/Y H:i:s");
     $dateTime = date("d/m/Y H:i:s");
@@ -166,10 +280,10 @@ EOF;
 
 
       // List Head
       // List Head
       $this->soapAddHead($idList, $operationType, "Lista di $operationType da as400 del $dateTime", '');
       $this->soapAddHead($idList, $operationType, "Lista di $operationType da as400 del $dateTime", '');
-      $descArti = trim($row['MXDESC']); // trim($row['MXCORD']) . ' ' . trim(substr($row['MXRIFC'], 7)) . ' ' . trim($row['MXDESC']);
+      $descArti = trim($row['descrizione']); // trim($row['commessa']) . ' ' . trim(substr($row['codcliente'], 7)) . ' ' . trim($row['descrizione']);
 
 
       // List Article
       // List Article
-      $this->soapAddArticle($row['MXARTI'], $row['QTY'], $descArti);
+      $this->soapAddArticle($row['barcode'], $row['qta_prelevare'], $descArti);
     }
     }
 
 
     $this->finalXml = <<<EOF
     $this->finalXml = <<<EOF
@@ -189,6 +303,7 @@ $this->listXml
 </soapenv:Envelope>
 </soapenv:Envelope>
 EOF;
 EOF;
 
 
+    return $idList;
   }
   }
 
 
   /**
   /**
@@ -208,33 +323,71 @@ EOF;
   }
   }
 
 
   /**
   /**
-   * Importa la distinta sul database di OM-Link
+   * Prepara la distinta da importare sul database di OM-Link
    *
    *
    * @param $dataRows
    * @param $dataRows
-   * @return int number of rows imported
+   * @param array $uds
+   * @return array
    */
    */
-  public function saveDistinta($dataRows): int
+  public function prepareDistinta($dataRows, array $uds)
   {
   {
     global $f3;
     global $f3;
-    /** @var SQL $db */
-    $db = $f3->get('DB');
+
+    $ret = [];
 
 
     $idUtente = $f3->get('USER')->id;
     $idUtente = $f3->get('USER')->id;
 
 
-    $distinta = new SQL\Mapper($db, 'distinte');
+    $cols = array_column($uds, 'item_id');
     foreach($dataRows as $count => $data) {
     foreach($dataRows as $count => $data) {
+      $container_id = '';
+      $colId = array_search(trim($data['MXARTI']), $cols);
+      if ($colId !== false)
+        $container_id = $uds[$colId]['container_id'];
+
+      $ret[] = [
+        'idUtente' => $idUtente,
+        'origine' => $data['MXUBIC'],
+        'consegna' => $data['MXIDDM'],
+        'commessa' => trim($data['MXCORD']),  // Codice prebolla
+        'codcliente' => trim(substr($data['MXRIFC'], 7)),
+        'barcode' => trim($data['MXARTI']),
+        'descrizione' => trim($data['MXDESC']),
+        'qta_prelevare' => $data['QTY'],
+        'qta_mancante' => 0,
+        'uds' => $container_id // posizione UDS
+      ];
+    }
+    // Sort menus buy 'order' option
+    usort($ret, function ($obj1, $obj2) {
+      return $obj1['uds'] <=> $obj2['uds'];
+    });
+    return $ret;
+  }
+
+  /**
+   * Importa la distinta sul database di OM-Link
+   *
+   * @param array $data
+   */
+  public function saveDistinta(array $data)
+  {
+    global $f3;
+
+    $distinta = new SQL\Mapper($f3->get('DB'), 'distinte');
+    foreach($data as $row) {
       $distinta->reset();
       $distinta->reset();
-      $distinta->idUtente = $idUtente;
-      $distinta->origine = $data['MXUBIC'];
-      $distinta->consegna = $data['MXIDDM'];
-      $distinta->commessa = trim($data['MXCORD']);
-      $distinta->codcliente = trim(substr($data['MXRIFC'], 7));
-      $distinta->barcode = trim($data['MXARTI']);
-      $distinta->descrizione = trim($data['MXDESC']);
-      $distinta->qta_prelevare = $data['QTY'];
-      $distinta->qta_mancante = 0;
+      $distinta->copyfrom($row);
       $distinta->save();
       $distinta->save();
     }
     }
-    return $count;
   }
   }
+
+  /**
+   * Get all UDS positions of MAV articles
+   * @return array
+   */
+  public function getUDSs(): array
+  {
+    return $this->dbMAVHandle->exec('SELECT item_id, container_id, subcontainer_id from dbo.vw_item_positions');
+  }
+
 }
 }

+ 54 - 21
src/Modules/Dimatec/Pages.php

@@ -57,6 +57,12 @@ class Pages extends Controller
     }
     }
   }
   }
 
 
+  /**
+   * MAIN CORE OF PROJECT: VENTILAZIONE ARTICOLI NELLE CESTE
+   *
+   * @param object $f3
+   * @param array $args
+   */
   public function Pick2Light(object $f3, array $args)
   public function Pick2Light(object $f3, array $args)
   {
   {
     $stepValues = array_map('strtoupper', $this->getSanitizedPostRequest());
     $stepValues = array_map('strtoupper', $this->getSanitizedPostRequest());
@@ -111,18 +117,22 @@ class Pages extends Controller
           $f3->set('INFOTEXT', "Ventilazione terminata");
           $f3->set('INFOTEXT', "Ventilazione terminata");
           $f3->set('RESTART_VENTILAZIONE', TRUE);
           $f3->set('RESTART_VENTILAZIONE', TRUE);
         }
         }
-        /*        foreach($commesse as $commessa) {
-                  $labelid = $distinta->GetLabelIdFromBarcode($commessa['commessa']);
-                  if ($labelid == null) {
-                    $f3->set('INFOTEXT', "Alcune etichette non accenderano il led in quanto non associate.");
-                    continue;
-                  }
-
-                }*/
+/*        foreach($commesse as $commessa) {
+          $labelid = $distinta->GetLabelIdFromBarcode($commessa['commessa']);
+          if ($labelid == null) {
+            $f3->set('INFOTEXT', "Alcune etichette non accenderano il led in quanto non associate.");
+            continue;
+          }
+        }*/
         $f3->set('COMMESSE', $commesse);
         $f3->set('COMMESSE', $commesse);
         break;
         break;
     }
     }
 
 
+    $migData = new MigrationData();
+    $sql = $migData->strQueryMassificazioneByUDS();
+    $listaProdotti = $this->dbHandle->exec($sql);
+
+    $f3->set('PRODUCTS', $listaProdotti);
     $f3->set('CONTENT', 'pick2light.tpl');
     $f3->set('CONTENT', 'pick2light.tpl');
     echo \Template::instance()->render('masterpage.tpl');
     echo \Template::instance()->render('masterpage.tpl');
   }
   }
@@ -133,11 +143,11 @@ class Pages extends Controller
     $distinta = new Distinta();
     $distinta = new Distinta();
 
 
     if (count($params)) {
     if (count($params)) {
-      $bindData = array_map('strtoupper', $this->getSanitizedPostRequest());
+      $bindData = array_map('strtoupper', $params);
       //$err = $this->findBoxCore->Bind($bindData['labelid'], $bindData['labelid']);
       //$err = $this->findBoxCore->Bind($bindData['labelid'], $bindData['labelid']);
       $label = new SmartESL($this->findBoxCore, [$bindData['labelid']]);
       $label = new SmartESL($this->findBoxCore, [$bindData['labelid']]);
 
 
-      $labelTemplateId = \F3::get("LABELS.TEMPLATES.DT31");
+      $labelTemplateId = $f3->get("LABELS.TEMPLATES.DT31");
 
 
       $err = $label->Display($labelTemplateId, $bindData['labelid']);
       $err = $label->Display($labelTemplateId, $bindData['labelid']);
       $eslData = array(
       $eslData = array(
@@ -157,6 +167,10 @@ class Pages extends Controller
       $label->descrizione = $bindData['codcliente'];
       $label->descrizione = $bindData['codcliente'];
       $label->save();
       $label->save();
 
 
+      $md = new MigrationData();
+      $md->DB2Connector();
+      $md->SetMissionsBarcodes($bindData['labelid'], $bindData['commessa']);
+
       /*      $this->dbHandle->exec("DELETE FROM label_bindings WHERE label_id='{$bindData['labelid']}'");
       /*      $this->dbHandle->exec("DELETE FROM label_bindings WHERE label_id='{$bindData['labelid']}'");
             $this->dbHandle->exec(
             $this->dbHandle->exec(
               "INSERT INTO label_bindings (label_id, barcode, template_id, esl_datafields, descrizione) VALUES " .
               "INSERT INTO label_bindings (label_id, barcode, template_id, esl_datafields, descrizione) VALUES " .
@@ -164,7 +178,6 @@ class Pages extends Controller
             );*/
             );*/
     }
     }
 
 
-
     $liste = $distinta->getListeToBind();
     $liste = $distinta->getListeToBind();
     $f3->set('ORDINE', $liste[0]['commessa']);
     $f3->set('ORDINE', $liste[0]['commessa']);
     $f3->set('LISTE', $liste);
     $f3->set('LISTE', $liste);
@@ -211,21 +224,41 @@ class Pages extends Controller
   public function ImportFromAS400($f3)
   public function ImportFromAS400($f3)
   {
   {
     $migData = new MigrationData();
     $migData = new MigrationData();
+    $migData->ClearCachedIDs();
 
 
     $migData->SoapConnector($f3->get('VERTICALSTORAGE.MV_ADDRESS'));
     $migData->SoapConnector($f3->get('VERTICALSTORAGE.MV_ADDRESS'));
-    $migData->DatabaseConnector($f3->get('VERTICALSTORAGE.DB2_ADDRESS'));
+    $migData->DB2Connector();
+    $migData->MAVDatabaseConnector();
 
 
-    // Get lists from as400
-    $data = $migData->query($migData->strQueryMassificata('SCARICO'));
+    // Get all articles UDS
+    $mavUDS = $migData->getUDSs();
 
 
-    // Compile xml for SOAP
-    $migData->soapCompileFrom($data, 'SCARICO');
-    if (!$migData->sendToIcam())
-      $f3->set('IMPORT_RESULT', "Errore durante l'invio della lista al Magazzino Verticale.<br/><br/>Controllare la console ICAM per gli errori.");
+    // Sum by article quantity for MAV
+    $dataFullMaxed = $migData->query($migData->strQueryPerMAV('SCARICO'));
+    if (count($dataFullMaxed) == 0)
+      $f3->set('IMPORT_RESULT', "Non ci sono nuove missioni da elaborare.");
     else {
     else {
-      // Importo la lista nel database di OM-Link solamente se non ci sono stati errori nell'invio al Magazzino Verticale
-      $count = $migData->saveDistinta($data);
-      $f3->set('IMPORT_RESULT', "Liste inviate correttamente al Magazzino Verticale<br/><br/>Righe con massimizzazione importate: $count");
+      $dataFullMaxed_Elaborata = $migData->prepareDistinta($dataFullMaxed, $mavUDS);
+
+      // Compile xml for SOAP
+      $idList = $migData->soapCompileFrom($dataFullMaxed_Elaborata, 'SCARICO');
+
+      if (false/*!$migData->sendToIcam()*/) {
+        $f3->set('IMPORT_RESULT', "Errore durante l'invio della lista al Magazzino Verticale.<br/><br/>Controllare la console ICAM per gli errori.");
+      } else {
+        // Importo la lista nel database di OM-Link solamente se non ci sono stati errori nell'invio al Magazzino Verticale
+
+        // Get lists from as400
+        $dataOMLINK = $migData->query($migData->strQueryMassificata('SCARICO'));
+        $dataOMLINK_elaborata = $migData->prepareDistinta($dataOMLINK, $mavUDS);
+
+        $migData->saveDistinta($dataOMLINK_elaborata);
+        $count = count($dataFullMaxed_Elaborata);
+        $f3->set('IMPORT_RESULT', "Liste inviate correttamente al Magazzino Verticale<br/><br/>Righe con massimizzazione importate: $count");
+
+        $migData->selectAvailableMissions('SCARICO');
+        $migData->MarkMissions(50, $idList);
+      }
     }
     }
 
 
     $f3->set('CONTENT', 'import.tpl');
     $f3->set('CONTENT', 'import.tpl');

+ 1 - 3
src/OpenMind/FindBox/FindBoxService.php

@@ -100,7 +100,6 @@ class FindBoxService
       //echo 'Label in cache: ' . count($this->labelToBlink) . "     \n";
       //echo 'Label in cache: ' . count($this->labelToBlink) . "     \n";
       foreach($this->labelToBlink as $labelId => $label) {
       foreach($this->labelToBlink as $labelId => $label) {
 
 
-
         // Priority 1
         // Priority 1
         // ----------
         // ----------
         // Force exit and blink off if run time script > MAX_BLINK_TIME_SEC
         // Force exit and blink off if run time script > MAX_BLINK_TIME_SEC
@@ -129,11 +128,10 @@ class FindBoxService
         }
         }
       }
       }
 
 
-      sleep(1);
       //echo "Restart loop                  \n";
       //echo "Restart loop                  \n";
       ob_flush();
       ob_flush();
       flush();
       flush();
-
+      sleep($f3->get('FINDBOXSERVICE.SLEEPTIME'));
     }
     }
 
 
     return;
     return;

+ 16 - 18
src/OpenMind/System/Notifications.php

@@ -12,10 +12,9 @@ use DB\SQL\Mapper;
 
 
 class Notifications extends Mapper
 class Notifications extends Mapper
 {
 {
-  private $f3;
+  const FB_NOTALIVE = 11;
 
 
-  // Used internally
-  private $initLoad;
+  private $f3;
 
 
   public function __construct()
   public function __construct()
   {
   {
@@ -23,21 +22,6 @@ class Notifications extends Mapper
     $this->f3 = $f3;
     $this->f3 = $f3;
 
 
     parent::__construct($f3->get('DB'), 'notifications');
     parent::__construct($f3->get('DB'), 'notifications');
-    $this->count = 'count(code)';
-  }
-
-  /**
-   * Retrieve notifications
-   *
-   * @return array|FALSE
-   */
-  public function check()
-  {
-    if (!$this->initLoad) {
-      $this->initLoad = true;
-      $this->load();
-    }
-    return $this->dry();
   }
   }
 
 
   /**
   /**
@@ -49,6 +33,12 @@ class Notifications extends Mapper
     $this->erase(['code=?', $code]);
     $this->erase(['code=?', $code]);
   }
   }
 
 
+  public function check(int $code)
+  {
+    $this->load(['code=?', $code]);
+    return $this->dry();
+  }
+
   /**
   /**
    * Truncate all table
    * Truncate all table
    */
    */
@@ -57,4 +47,12 @@ class Notifications extends Mapper
     $this->f3->get('DB')->exec('TRUNCATE TABLE notifications');
     $this->f3->get('DB')->exec('TRUNCATE TABLE notifications');
   }
   }
 
 
+  public function notify(int $code, string $caption, $link = '/')
+  {
+    $this->reset();
+    $this->code = $code;
+    $this->caption = $caption;
+    $this->link = $link;
+    $this->save();
+  }
 }
 }

+ 20 - 1
src/OpenMind/System/OMUtils.php

@@ -92,13 +92,14 @@ class OMUtils
    */
    */
   public function LoadEncryptedConfig(string $path)
   public function LoadEncryptedConfig(string $path)
   {
   {
+    global $f3;
     if (!file_exists($path))
     if (!file_exists($path))
       throw new \Exception('Config file not found');
       throw new \Exception('Config file not found');
 
 
     $tmpFilepath = tempnam(sys_get_temp_dir(), 'om');
     $tmpFilepath = tempnam(sys_get_temp_dir(), 'om');
     $config = gzuncompress(base64_decode(file_get_contents($path)));
     $config = gzuncompress(base64_decode(file_get_contents($path)));
     file_put_contents($tmpFilepath, $config);
     file_put_contents($tmpFilepath, $config);
-    \F3::config($tmpFilepath, true);
+    $f3->config($tmpFilepath, true);
     unlink($tmpFilepath);
     unlink($tmpFilepath);
   }
   }
 
 
@@ -107,4 +108,22 @@ class OMUtils
     if (version_compare(PHP_VERSION, '7.2') != 1)
     if (version_compare(PHP_VERSION, '7.2') != 1)
       throw new \Exception('PHP 7.2+ is need to run the project');
       throw new \Exception('PHP 7.2+ is need to run the project');
   }
   }
+
+  /**
+   * Check if a port server is opened, return error code of fsockopen function
+   *
+   * @param string $ip
+   * @param int $port
+   * @param int $mstimeout timeout of check in milliseconds
+   * @return int
+   */
+  function isServerAlive(string $ip, int $port, int $mstimeout = 1000): int
+  {
+    try {
+      @fclose($sck = @fsockopen($ip, $port, $errno, $errstr, $mstimeout));
+    } catch (\Exception $e) {
+      die($e->getMessage());
+    }
+    return $errno;
+  }
 }
 }

+ 2 - 1
src/OpenMind/System/PluginStrategy.php

@@ -80,7 +80,8 @@ class PluginStrategy implements IPluginStrategy
    */
    */
   public function AddRoute($pattern, string $handler)
   public function AddRoute($pattern, string $handler)
   {
   {
-    \F3::route($pattern, $handler, 0);  // TTL 60s
+    global $f3;
+    $f3->route($pattern, $handler, 0);  // TTL 60s
   }
   }
 
 
   /**
   /**

+ 18 - 4
src/OpenMind/System/System.php

@@ -60,10 +60,26 @@ class System extends PluginStrategy
     return $this->cache;
     return $this->cache;
   }
   }
 
 
+  /**
+   * AJAX web service for bell notifications and system checking
+   *
+   * @param $f3
+   */
   public function getServerStatus($f3)
   public function getServerStatus($f3)
   {
   {
+    $qs = new QueueSystem('FindBoxService_isAlive');
+    if (!$qs->check()) {
+      $lastUpdate = time() - $qs->command;
+      if ($lastUpdate > $f3->get('FINDBOXSERVICE.SLEEPTIME') + 5) {
+        $omlNotifications = new Notifications();
+        if ($omlNotifications->check(Notifications::FB_NOTALIVE))
+          $omlNotifications->notify(Notifications::FB_NOTALIVE, 'Errore: Servizio di FindBox non disponibile');
+      }
+    }
+
     $ret = [];
     $ret = [];
     $notifications = new Notifications();
     $notifications = new Notifications();
+    $notifications->count = 'count(code)';
     $sqlGroupBy = array(
     $sqlGroupBy = array(
       'order' => 'timestamp DESC',
       'order' => 'timestamp DESC',
       'group' => 'code'
       'group' => 'code'
@@ -75,14 +91,12 @@ class System extends PluginStrategy
 
 
   public function NotificationDelete($f3, $args)
   public function NotificationDelete($f3, $args)
   {
   {
-    global $f3;
-
-    if($args['code']!=0)
+    if ($args['code'] != 0)
       (new Notifications())->Remove($args['code']);
       (new Notifications())->Remove($args['code']);
     else
     else
       (new Notifications())->emptyAll();
       (new Notifications())->emptyAll();
   }
   }
 }
 }
 
 
-/** @var System $System * */
+/** @var System $System **/
 Global $System;
 Global $System;

+ 2 - 0
src/OpenMind/Web/Controller.php

@@ -7,10 +7,12 @@
 
 
 namespace OpenMind\Web;
 namespace OpenMind\Web;
 
 
+use DB\SQL;
 use OpenMind\System\User;
 use OpenMind\System\User;
 
 
 class Controller
 class Controller
 {
 {
+  /** @var SQL $dbHandle OM-Link Database */
   protected $dbHandle;
   protected $dbHandle;
 
 
   /**
   /**

+ 4 - 4
test/conn_odbc_ibm.php

@@ -42,11 +42,11 @@ class MigrationData
 
 
   public function transferData($pdoResult)
   public function transferData($pdoResult)
   {
   {
-    $this->query("TRUNCATE TABLE INTMUB0F");
+    $this->query("TRUNCATE TABLE SMEDAT_DIM.INTMUB0F");
     $count = 0;
     $count = 0;
     foreach($pdoResult as $key => $value) {
     foreach($pdoResult as $key => $value) {
-      echo "INSERT INTO INTMUB0F (UXSTAT, UXCOAP, UXQTGC, UXQTMA) VALUES (10, '${value['UXCOAP']}', ${value['UXQTGC']}, ${value['UXQTMA']})" . PHP_EOL;
-      $success = $this->query("INSERT INTO INTMUB0F (UXSTAT, UXCOAP, UXQTGC, UXQTMA) VALUES (10, '${value['UXCOAP']}', ${value['UXQTGC']}, ${value['UXQTMA']})");
+      echo "INSERT INTO SMEDAT_DIM.INTMUB0F (UXSTAT, UXCOAP, UXQTGC, UXQTMA) VALUES (10, '${value['UXCOAP']}', ${value['UXQTGC']}, ${value['UXQTMA']})" . PHP_EOL;
+      $success = $this->query("INSERT INTO SMEDAT_DIM.INTMUB0F (UXSTAT, UXCOAP, UXQTGC, UXQTMA) VALUES (10, '${value['UXCOAP']}', ${value['UXQTGC']}, ${value['UXQTMA']})");
       if ($success === FALSE) {
       if ($success === FALSE) {
         die('Errore');
         die('Errore');
       }
       }
@@ -61,7 +61,7 @@ try {
   $res = $mav->query('SELECT item_id AS UXCOAP, max_load_unit AS UXQTMA, position_quantity AS UXQTGC FROM vw_item_positions');
   $res = $mav->query('SELECT item_id AS UXCOAP, max_load_unit AS UXQTMA, position_quantity AS UXQTGC FROM vw_item_positions');
 
 
   $db2 = new MigrationData(
   $db2 = new MigrationData(
-    "odbc:Driver={iSeries Access ODBC Driver};DefaultLibraries=SMEDAT_DIM;SYSTEM=192.168.0.100;Uid=icam;Pwd=icam",
+    "odbc:Driver={iSeries Access ODBC Driver};DefaultLibraries=SMEDAT_DIM;SYSTEM=192.168.0.100",
     'icam',
     'icam',
     'icam'
     'icam'
   );
   );

+ 1 - 1
test/omlinkimporter.php

@@ -9,7 +9,7 @@
 require_once 'lib/f3/base.php';
 require_once 'lib/f3/base.php';
 $f3 = \Base::instance();
 $f3 = \Base::instance();
 
 
-\F3::set('ONERROR', function ($f3) {
+$f3->set('ONERROR', function ($f3) {
   print_r($f3->get('ERROR'));
   print_r($f3->get('ERROR'));
 });
 });
 
 

+ 1 - 1
ui/js/omlink.js

@@ -67,5 +67,5 @@ $(function () {
 
 
   setInterval(() => {
   setInterval(() => {
     refreshNotificationArea();
     refreshNotificationArea();
-  }, 60000);
+  }, 10000);
 });
 });

+ 29 - 2
ui/pick2light.tpl

@@ -1,5 +1,5 @@
 <div class="row h-100 justify-content-center w-100">
 <div class="row h-100 justify-content-center w-100">
-	<div class="col-xs-12 col-md-9 col-lg-5 align-self-center">
+	<div class="col-xs-3 col-md-3 col-lg-2 align-self-center">
 		<form class="form" method="post" action="{{@BASEURL}}/pick2light/{{@NEXTSTEP}}">
 		<form class="form" method="post" action="{{@BASEURL}}/pick2light/{{@NEXTSTEP}}">
 			<check if="{{ isset(@INFOTEXT) }}">
 			<check if="{{ isset(@INFOTEXT) }}">
 				<div class="alert alert-danger" role="alert">
 				<div class="alert alert-danger" role="alert">
@@ -32,7 +32,7 @@
 			</check>
 			</check>
 
 
 			{*Barcode prodotto*}
 			{*Barcode prodotto*}
-			<input type="text" name="barcode_mv" {{@PARAMS['step']==2 ? 'disabled' : ''}} {{@PARAMS['step']==1 ? 'autofocus' : ''}} value="{{@SESSION.barcode_mv}}" class="form-control form-control-lg mb-3" placeholder="Codice Prodotto del Magazzino Verticale." required autocomplete="false"/>
+			<input type="text" name="barcode_mv" {{@PARAMS['step']==2 ? 'disabled' : ''}} {{@PARAMS['step']==1 ? 'autofocus' : ''}} value="{{@SESSION.barcode_mv}}" class="form-control form-control-lg mb-3" placeholder="Cod.Art.MAV" required autocomplete="false"/>
 
 
 			{*Codice cesta per la quale mi aspetto che avvenga la ventilazione*}
 			{*Codice cesta per la quale mi aspetto che avvenga la ventilazione*}
 			<check if="{{ @PARAMS['step'] == 2 }}">
 			<check if="{{ @PARAMS['step'] == 2 }}">
@@ -41,6 +41,33 @@
 
 
 		</form>
 		</form>
 	</div>
 	</div>
+	<div class="col-xs-9 col-md-9 col-lg-10 align-self-center">
+		<div class="table-responsive">
+			<table class="table table-striped table-secondary" style="font-size: 10pt;">
+				<thead>
+				<tr style="font-size: 12pt" class="bg-warning">
+					<th class="text-center text-uppercase" colspan="6" scope="col">Articoli da prelevare</th>
+				</tr>
+				<tr style="font-size: 12pt" class="bg-warning">
+					<th scope="col">UDS</th>
+					<th scope="col">Art</th>
+					<th scope="col">Desc</th>
+					<th scope="col">Q.ta</th>
+				</tr>
+				</thead>
+				<tbody>
+				<repeat group="{{ @PRODUCTS }}" value="{{ @PRODUCT }}">
+					<tr <check if="{{trim(@SESSION.barcode_mv)==trim(@PRODUCT.barcode)}}">class="blink bg-primary"</check>>
+						<th scope="row">{{@PRODUCT.uds}}</th>
+						<td>{{@PRODUCT.barcode}}</td>
+						<td>{{@PRODUCT.descrizione}}</td>
+						<td>{{@PRODUCT.qta}}</td>
+					</tr>
+				</repeat>
+				</tbody>
+			</table>
+		</div>
+	</div>
 </div>
 </div>
 
 
 <check if="{{@RESTART_VENTILAZIONE}}">
 <check if="{{@RESTART_VENTILAZIONE}}">