├── config.php ├── .gitignore ├── img ├── delete.png ├── logo.png ├── ajouter.png ├── dispatch.png ├── supprimer.png ├── object_dispatch.png └── object_dispatch.svg ├── samplefiles ├── import_expedition.csv └── import_recep.csv ├── script ├── ajax.delete_line.php ├── get_const.php ├── create-maj-base.php ├── interface_expedition_handler.php ├── interface.php └── interface.php.orig ├── composer.json ├── config.default.php ├── class ├── dispatchasset.class.php ├── dispatchdetail.class.php └── actions_dispatch.class.php ├── lib └── dispatch.lib.php ├── liste_expedition_todo.php ├── ChangeLog.md ├── imp_etiquette.php ├── modele ├── modele1.html └── modele2.html ├── langs ├── de_DE │ └── dispatch.lang ├── en_US │ └── dispatch.lang └── fr_FR │ └── dispatch.lang ├── asset.php ├── admin └── admin.php ├── detail_head.php ├── core ├── triggers │ └── interface_99_modDispatch_DispatchWorkflow.class.php └── modules │ └── moddispatch.class.php └── detail.php /config.php: -------------------------------------------------------------------------------- 1 | Execute($sql); 15 | 16 | return 1; -------------------------------------------------------------------------------- /script/get_const.php: -------------------------------------------------------------------------------- 1 | dolibarr_get_const($db, 'ETIQUETTE_MARGE_LEFT_'.$modele), 14 | 'margetop' => dolibarr_get_const($db, 'ETIQUETTE_MARGE_TOP_'.$modele) 15 | )); -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "atm-consulting/dispatch", 3 | "description": "Define your manufacturing composition, record your production cost", 4 | "type": "dolibarr-module", 5 | "license": "GPL-3.0+", 6 | "authors": [ 7 | { 8 | "name": "ATM Consulting", 9 | "email": "contact@atm-consulting.fr", 10 | "homepage": "https://www.atm-consulting.fr" 11 | } 12 | ], 13 | "support": { 14 | "email": "support@atm-consulting.fr", 15 | "issues": "https://github.com/ATM-Consulting/dolibarr_module_dispatch/issues", 16 | "source": "https://github.com/ATM-Consulting/dolibarr_module_dispatch" 17 | }, 18 | "require": { 19 | "composer/installers": "~1.0" 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /script/create-maj-base.php: -------------------------------------------------------------------------------- 1 | debug=true; 12 | } 13 | else{ 14 | $PDOdb=new TPDOdb; 15 | } 16 | 17 | dol_include_once('/dispatch/class/dispatchdetail.class.php'); 18 | dol_include_once('/dispatch/class/dispatchasset.class.php'); 19 | dol_include_once('/' . ATM_ASSET_NAME . '/class/asset.class.php'); 20 | 21 | $o=new TDispatchDetail; 22 | $o->init_db_by_vars($PDOdb); 23 | 24 | $o=new TRecepDetail; 25 | $o->init_db_by_vars($PDOdb); 26 | 27 | $o=new TRecepBDRDetail; 28 | $o->init_db_by_vars($PDOdb); 29 | 30 | $o=new TRecepBDRDispatch; 31 | $o->init_db_by_vars($PDOdb); 32 | 33 | $o=new TDispatch; 34 | $o->init_db_by_vars($PDOdb); 35 | 36 | $o=new TDispatchAsset; 37 | $o->init_db_by_vars($PDOdb); 38 | -------------------------------------------------------------------------------- /config.default.php: -------------------------------------------------------------------------------- 1 | = 8.0 || dol_is_dir(dol_buildpath('/assetatm')) ? 'assetatm' : 'asset'); 29 | 30 | -------------------------------------------------------------------------------- /class/dispatchasset.class.php: -------------------------------------------------------------------------------- 1 | 'int', 'index'=>true)); 9 | parent::add_champs('type_object',array('length'=>30, 'index'=>true)); 10 | parent::_init_vars(); 11 | parent::start(); 12 | 13 | $this->setChild('TDispatchAsset', 'fk_dispatch'); 14 | } 15 | 16 | function loadByObject(&$PDOdb, $id, $type_object) { 17 | 18 | $this->fk_object = $id; 19 | $this->type_object = $type_object; 20 | 21 | $PDOdb->Execute("SELECT rowid FROM ".$this->get_table()." WHERE fk_object=".$id." AND type_object='".$type_object."' "); 22 | if($obj = $PDOdb->Get_line()) { 23 | return $this->load($PDOdb, $obj->rowid); 24 | 25 | } 26 | else { 27 | return false; 28 | } 29 | 30 | } 31 | } 32 | 33 | class TDispatchAsset extends TObjetStd { 34 | 35 | function __construct() { 36 | global $langs; 37 | 38 | parent::set_table(MAIN_DB_PREFIX.'dispatch_asset'); 39 | parent::add_champs('fk_object,fk_dispatch,fk_asset',array('type'=>'int', 'index'=>true)); 40 | parent::add_champs('type_object',array('length'=>30, 'index'=>true)); 41 | parent::_init_vars(); 42 | parent::start(); 43 | 44 | $this->asset=new TAsset; 45 | } 46 | function load(&$PDOdb, $id, $withChildren = true) { 47 | 48 | parent::load($PDOdb, $id, $withChildren); 49 | 50 | if($this->fk_asset>0) $this->asset->load($PDOdb, $this->fk_asset,false); 51 | 52 | 53 | } 54 | 55 | } 56 | -------------------------------------------------------------------------------- /lib/dispatch.lib.php: -------------------------------------------------------------------------------- 1 | lines) && method_exists($shipment, 'fetch_lines')) 22 | { 23 | $shipment->fetch_lines(); 24 | } 25 | 26 | foreach($shipment->lines as $line) 27 | { 28 | if(empty($line->fk_product)) 29 | { 30 | continue; 31 | } 32 | 33 | $dispatchDetailStatic = new TDispatchDetail; 34 | 35 | $TDetail = $dispatchDetailStatic->LoadAllBy($PDOdb, array('fk_expeditiondet' => $line->id)); 36 | 37 | if(empty($TDetail)) 38 | { 39 | $product = new Product($shipment->db); 40 | $product->fetch($line->fk_product); 41 | 42 | if(empty($product->array_options) && method_exists($product, 'fetch_optionals')) 43 | { 44 | $product->fetch_optionals(); 45 | } 46 | 47 | // Si type d'équipement renseigné pour ce produit, il doit être sérialisé 48 | if(! empty($product->array_options['options_type_asset'])) 49 | { 50 | if (!in_array($langs->transnoentities('ShipmentCannotBeClosedSerializedLinesHaveNoDetail'), $errors)) 51 | $errors[] = $langs->transnoentities('ShipmentCannotBeClosedSerializedLinesHaveNoDetail'); 52 | /*$PDOdb->close(); 53 | 54 | return false;*/ 55 | } 56 | } 57 | else 58 | { 59 | $qty = 0; 60 | 61 | foreach ($TDetail as $dispatchDetail) 62 | { 63 | if (empty($dispatchDetail->is_prepared)) 64 | { 65 | if (!in_array($langs->transnoentities('ShipmentCannotBeClosedAssetsNotPrepared'), $errors)) 66 | $errors[] = $langs->transnoentities('ShipmentCannotBeClosedAssetsNotPrepared'); 67 | /*$PDOdb->close(); 68 | 69 | return false;*/ 70 | } 71 | else $qty += $dispatchDetail->weight_reel; 72 | } 73 | 74 | if($qty < $line->qty) 75 | { 76 | // ShipmentCannotBeClosedQtyDoesntMatch 77 | if (!in_array($langs->transnoentities('ShipmentCannotBeClosedAssetsNotPrepared'), $errors)) 78 | $errors[] = $langs->transnoentities('ShipmentCannotBeClosedAssetsNotPrepared'); 79 | 80 | /*$PDOdb->close(); 81 | 82 | return false;*/ 83 | } 84 | } 85 | } 86 | 87 | $PDOdb->close(); 88 | if (empty($errors)) 89 | { 90 | $return = array(true, ''); 91 | } 92 | else 93 | { 94 | $msg = "\n".implode("\n", $errors); 95 | $return = array(false, $msg); 96 | } 97 | 98 | return $return; 99 | } 100 | -------------------------------------------------------------------------------- /liste_expedition_todo.php: -------------------------------------------------------------------------------- 1 | load("other"); 6 | 7 | llxHeader('',$langs->trans("LIST_SHIPMENTS_TO_PREPARE"),'',''); 8 | 9 | $ATMdb = new TPDOdb; 10 | 11 | $sql = "SELECT s.rowid as soc_id, s.nom as soc_nom, e.rowid as expe_id, e.ref as expe_ref, c.rowid as comm_id, c.ref as comm_ref, "; 12 | $sql.= "p.rowid as prod_id, CONCAT(p.ref, ' ', p.label) as prod_ref, cd.qty, cd.tarif_poids, cd.poids, cd.asset_lot "; 13 | $sql.= "FROM ".MAIN_DB_PREFIX."expedition e "; 14 | $sql.= "LEFT JOIN ".MAIN_DB_PREFIX."expeditiondet ed ON ed.fk_expedition = e.rowid "; 15 | //$sql.= "LEFT JOIN ".MAIN_DB_PREFIX."element_element ee ON ee.fk_target = e.rowid AND ee.targettype = 'shipping' "; 16 | //$sql.= "LEFT JOIN ".MAIN_DB_PREFIX."commande c ON ee.fk_source = c.rowid AND ee.sourcetype = 'commande' "; 17 | $sql.= "LEFT JOIN ".MAIN_DB_PREFIX."commandedet cd ON ed.fk_origin_line = cd.rowid "; 18 | $sql.= "LEFT JOIN ".MAIN_DB_PREFIX."commande c ON cd.fk_commande = c.rowid "; 19 | $sql.= "LEFT JOIN ".MAIN_DB_PREFIX."product p ON cd.fk_product = p.rowid "; 20 | $sql.= "LEFT JOIN ".MAIN_DB_PREFIX."societe s ON c.fk_soc = s.rowid "; 21 | $sql.= "WHERE e.fk_statut = 0 "; 22 | $sql.= "ORDER BY prod_ref, soc_nom"; 23 | 24 | $r = new TListviewTBS('expe'); 25 | 26 | $measuring_units=array(-9=>1,-6=>1,-3=>1,0=>1,3=>1,99=>1,100=>1); 27 | foreach ($measuring_units as $key => $value) { 28 | $TPoids[$key] = measuring_units_string($key,'weight'); 29 | } 30 | 31 | echo $r->render($ATMdb, $sql, array( 32 | 'limit'=>array( 33 | 'nbLine'=>'30' 34 | ) 35 | ,'link'=>array( 36 | 'soc_nom'=>''.img_picto('','object_company.png','',0).' @val@' 37 | ,'expe_ref'=>''.img_picto('','object_sending.png','',0).' @val@' 38 | ,'comm_ref'=>''.img_picto('','object_order.png','',0).' @val@' 39 | ,'prod_ref'=>''.img_picto('','object_product.png','',0).' @val@' 40 | ) 41 | ,'translate'=>array('poids'=>$TPoids) 42 | ,'hide'=>array('soc_id', 'expe_id', 'comm_id', 'prod_id') 43 | ,'type'=>array('tarif_poids'=>'number','qty'=>'number') 44 | ,'liste'=>array( 45 | 'titre'=>$langs->trans("LIST_SHIPMENTS_TO_PREPARE") 46 | ,'image'=>img_picto('','title.png', '', 0) 47 | ,'picto_precedent'=>img_picto('','back.png', '', 0) 48 | ,'picto_suivant'=>img_picto('','next.png', '', 0) 49 | ,'noheader'=> (int)isset($_REQUEST['fk_soc']) | (int)isset($_REQUEST['fk_product']) 50 | ,'messageNothing'=>$langs->trans("LIST_NO_SHIPMENTS") 51 | ,'picto_search'=>img_picto('','search.png', '', 0) 52 | ) 53 | ,'title'=>array( 54 | 'soc_nom'=>$langs->trans('Client') 55 | ,'expe_ref'=>'Expédition' 56 | ,'comm_ref'=>'Commande' 57 | ,'prod_ref'=>$langs->trans('Product') 58 | ,'qty'=>$langs->trans('Quantity') 59 | ,'tarif_poids'=>'Poids' 60 | ,'asset_lot'=>'Lot' 61 | ) 62 | )); 63 | 64 | llxFooter(); -------------------------------------------------------------------------------- /ChangeLog.md: -------------------------------------------------------------------------------- 1 | # Change Log 2 | All notable changes to this project will be documented in this file. 3 | 4 | ## [Unreleased] 5 | 6 | ## Version 3.7 - 2022-03-24 7 | 8 | - FIX : DA023802 - La quantité lors de l'ajout dans le détails d'expédition est maintenant rempli avec la qty de la commande - 3.7.7 - *16/11/2023* 9 | - FIX : Fatal on reception - 3.7.6 - *30/08/2023* 10 | - FIX : Compat v17 (token) - 3.7.5 - *31/03/2023* 11 | - FIX : Missing icon - 3.7.4 - *22/07/2022* 12 | - FIX : compat v16 blooper - 3.7.3 - *30/06/2022* 13 | - FIX : compat v16 - 3.7.2 - *16/06/2022* 14 | - FIX : DA021689 - Gestion de la conf STOCK_CALCULATE_ON_SHIPMENT pour l'affichage des bons équipements - 3.7.1 - *01/04/2022* 15 | - NEW : ajout conf "Réalimenter équipement à la suppression de l'expédition" pour la dissocier de "Retirer l'entrepot de l'équipement à la validation de l'expédition" - 3.7.0 - *24/03/2022* 16 | 17 | ## Version 3.6 - 2021-12-03 18 | 19 | - FIX : il n'était pas possible d'ajouter un équipement avec numéro de série sans numéro de lot dans le détail d'une expédition - 3.6.3 - *27/01/2022* 20 | - FIX : les équipements n'apparaissaient pas dans le select des exped - 3.6.2 - *20/12/2021* 21 | - FIX : detail.php, la quantité ne s'affichait plus automatiquement, erreur de js (ligne commentée) - 3.6.1 - *07/12/2021* 22 | - NEW : Conf permettant d'ignorer la localisation ainsi que d'ajouter un num serie dans une meme exped - 3.6.0 - *03/12/2021* 23 | 24 | ## Version 3.5 - 2021-07-06 25 | 26 | - FIX : warning (looping on null, accessing non-existent indices) - 3.5.14 - *14/04/2023* 27 | - FIX : error qty max detail.php to add a batch - 3.5.12 - *29/06/2022* 28 | - FIX : SQL query doesn't check asset stock management type - 3.5.11 - *01/04/2022* 29 | - FIX : on shipment validate use newref instead of ref - 3.5.10 - *26/11/2021* 30 | - FIX : Js Ajax and form for dispatching new element - 3.5.9 - *17/11/2021* 31 | - FIX : order reception - if DISPATCH_CREATE_NUMSERIE_ON_RECEPTION_IF_LOT activated wwe must give serialnumber to data or it will overide with empty serial number - 3.5.8 - *03/11/2021* 32 | - FIX : expedition detaim - display asset with enough qty - 3.5.7 - *25/10/2021* 33 | - FIX : expedition detaim - hide lot without units - 3.5.6 - *5/10/2021* 34 | - FIX : v14 compatibility - NOSCRFCHECK and selectMeasuringUnits - 3.5.5 - *15/09/2021* 35 | - FIX : v14 compatibility - setDateLivraison -> setDeliveryDate - 3.5.4 - *27/07/2021* 36 | - FIX : display quantity of shipped products on PDF *12/07/2021* - 3.5.3 37 | - FIX : auto-fill of expedition's tab is made with ordered qty and not with the whole lot *29/06/2021* - 3.5.2 38 | - FIX : Add error message if no more available assets for this expedition *31/05/2021* - 3.5.1 39 | - NEW : automatically add all the assets contained in OF with the Add automatically select option *20/05/2021* - 3.5.0 40 | 41 | ## Version 3.4 - 2020-12-10 42 | 43 | ### Added 44 | 45 | - FIX: v13 + v14 compatibility *29/06/2021* - 3.4.3 46 | - FIX: missing en_US translations *22/04/2021* - 3.4.1 47 | - NEW T2966 Affiche une seule ligne par lot au lieu de plusieurs - *24/05/2021* - 3.4.2 48 | - NEW T2476 Ventilation produits/équipement multicompany OFSOM 49 | 50 | ### Changed 51 | 52 | - FIX : Préparations entité A disponibles sur CF entité B doit uniquement afficher celles au statut clôturée 53 | - FIX : Équipement : ajouter code inventaire, VPN, n° logiciel, Notes 54 | - FIX : Manque filtre sur entrepots (getentities) sur écran réception standard 55 | - FIX : Manque filtre entité sur liste des équipements 56 | 57 | ## Version 3.3 - 2020-10-21 58 | 59 | ### Added 60 | 61 | ### Changed 62 | 63 | - FIX error on table naming : the right table name is entity_thirdparty *29/06/2021* - 3.3.1 64 | -------------------------------------------------------------------------------- /imp_etiquette.php: -------------------------------------------------------------------------------- 1 | fetch($_REQUEST['expedition']); 33 | $expedition->fetch_lines(); 34 | 35 | $TetiquettesVides = array(); 36 | $Tetiquettes = array(); 37 | 38 | //création des div vides 39 | for($i=0; $i< $nbVides; $i++){ 40 | $TetiquettesVides[$i] = array($i); 41 | } 42 | 43 | $TPDOdb = new TPDOdb; 44 | 45 | //création des div pleines 46 | foreach($expedition->lines as $ligne){ 47 | 48 | $TPDOdb->Execute("SELECT rowid FROM ".MAIN_DB_PREFIX."expeditiondet_asset WHERE fk_expeditiondet = ".$ligne->rowid); 49 | $TidExepeditiondetAsset = array(); 50 | 51 | while($TPDOdb->Get_line()) { 52 | $TidExepeditiondetAsset[] = $TPDOdb->Get_field('rowid'); 53 | } 54 | 55 | foreach($TidExepeditiondetAsset as $idExpeditiondetAsset){ 56 | $sql = "SELECT p.ref, p.label as nom, p.note as descritpion, eda.tare as tare, a.serial_number as code, a.lot_number as lot, eda.weight_reel as poids, eda.weight_reel_unit as poids_unit, eda.tare_unit as tare_unit 57 | FROM ".MAIN_DB_PREFIX."expeditiondet_asset as eda 58 | LEFT JOIN ".MAIN_DB_PREFIX.ATM_ASSET_NAME." as a ON (a.rowid = eda.fk_asset) 59 | LEFT JOIN ".MAIN_DB_PREFIX."product as p ON (p.rowid = a.fk_product) 60 | WHERE eda.rowid = ".$idExpeditiondetAsset; 61 | 62 | $TPDOdb->Execute($sql); 63 | $TPDOdb->Get_line(); 64 | 65 | $tare_unit = _unit($TPDOdb->Get_field('tare_unit')); 66 | $poids_unit = _unit($TPDOdb->Get_field('poids_unit')); 67 | 68 | //On duplique l'étiquette autant de fois que demandé en paramètre 69 | for($i=0; $i< $nbCopies; $i++){ 70 | $Tetiquettes[] = array( 71 | "ref" => $TPDOdb->Get_field('ref'), 72 | "nom" => $TPDOdb->Get_field('nom'), 73 | "description" => ((int)$TPDOdb->Get_field('description') != 0) ? $TPDOdb->Get_field('description') : "", 74 | "tare" => number_format($TPDOdb->Get_field('tare'),2,',',' '), 75 | "tare_unit" => $tare_unit, 76 | "code" => $TPDOdb->Get_field('code'), 77 | "lot" => $TPDOdb->Get_field('lot'), 78 | "poids" => number_format($TPDOdb->Get_field('poids'),2,',',' '), 79 | "poids_unit" => $poids_unit 80 | ); 81 | } 82 | } 83 | } 84 | 85 | if (!empty($_REQUEST['margetop'])) dolibarr_set_const($db, 'ETIQUETTE_MARGE_TOP_'.$modele, $_REQUEST['margetop'],'chaine',1,'Marge en mm'); 86 | if (!empty($_REQUEST['margeleft'])) dolibarr_set_const($db, 'ETIQUETTE_MARGE_LEFT_'.$modele, $_REQUEST['margeleft'],'chaine',1,'Marge en mm'); 87 | 88 | $TMarges = array( 89 | 'margetop'=> $_REQUEST['margetop'], 90 | 'margeleft'=> $_REQUEST['margeleft'] 91 | ); 92 | 93 | $TBS = new TTemplateTBS(); 94 | 95 | $rendu = $TBS->Render("modele/".$modele, 96 | array('etiquette_vide'=>$TetiquettesVides, 97 | 'etiquette'=>$Tetiquettes 98 | ) 99 | ,array( 100 | 'marge'=>$TMarges 101 | ) 102 | ); 103 | 104 | echo $rendu; 105 | } -------------------------------------------------------------------------------- /modele/modele1.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Impression etiquette 5 | 79 | 80 | 154 | 155 | 156 | 157 |
158 | 159 |
160 | 161 |
162 |
[etiquette.nom;block=((div))]
163 |
[etiquette.description;]
164 |
Tare :
[etiquette.tare] [etiquette.tare_unit]
165 |
Code: 
[etiquette.ref]
166 |
Lot: 
[etiquette.lot]
167 |
Poids Net :
[etiquette.poids] [etiquette.poids_unit]
168 |
169 | 170 | -------------------------------------------------------------------------------- /class/dispatchdetail.class.php: -------------------------------------------------------------------------------- 1 | lines = array(); 33 | $this->nbLines = 0; 34 | } 35 | 36 | //Charges les lignes de flacon associé à la ligne d'expédition passé en paramètre 37 | function loadLines(&$PDOdb, $id_expeditionLine){ 38 | 39 | $sql = "SELECT rowid FROM ".$this->get_table()." WHERE fk_expeditiondet = ".$id_expeditionLine." ORDER BY rang"; 40 | 41 | $TIdExpedet = TRequeteCore::_get_id_by_sql($PDOdb, $sql); 42 | 43 | foreach($TIdExpedet as $idexpedet){ 44 | $dispatchdetail_temp = new TDispatchDetail; 45 | $dispatchdetail_temp->load($PDOdb, $idexpedet); 46 | $this->lines[] = $dispatchdetail_temp; 47 | $this->nbLines = $this->nbLines + 1; 48 | } 49 | } 50 | 51 | function getPoidsExpedie(&$PDOdb,$id_expeditionLine,$product){ 52 | $sql = "SELECT SUM(eda.weight) as Total, eda.weight_reel_unit as Unite 53 | FROM ".MAIN_DB_PREFIX."expeditiondet_asset as eda 54 | LEFT JOIN ".MAIN_DB_PREFIX."expeditiondet as ed ON (eda.fk_expeditiondet = ed.rowid) 55 | LEFT JOIN ".MAIN_DB_PREFIX."commandedet as c ON (c.rowid = ed.fk_origin_line) 56 | WHERE ed.fk_origin_line IN (SELECT fk_origin_line FROM ".MAIN_DB_PREFIX."expeditiondet WHERE rowid = ".$id_expeditionLine.") 57 | GROUP BY Unite"; 58 | 59 | $total = 0; 60 | $PDOdb->Execute($sql); 61 | while($PDOdb->Get_line()){ 62 | $total += $PDOdb->Get_field('Total') * pow(10,$PDOdb->Get_field('Unite')); 63 | } 64 | 65 | return $total * pow(10,-$product->weight_units) ; 66 | } 67 | } 68 | 69 | class TRecepDetail extends TObjetStd { 70 | function __construct() { 71 | global $langs; 72 | 73 | parent::set_table(MAIN_DB_PREFIX.'commande_fournisseurdet_asset'); 74 | parent::add_champs('fk_commandedet,fk_product,fk_warehouse','type=entier;index;'); 75 | parent::add_champs('rang','type=entier;'); 76 | parent::add_champs('lot_number,carton,numerosuivi,imei,firmware,serial_number','type=chaine;'); 77 | parent::add_champs('weight, weight_reel, tare','type=float;'); 78 | parent::add_champs('dluo','type=date;'); 79 | parent::add_champs('weight_unit, weight_reel_unit, tare_unit, already_dispatch','type=entier;'); 80 | 81 | parent::_init_vars(); 82 | parent::start(); 83 | } 84 | } 85 | 86 | class TRecepBDRDetail extends TObjetStd { 87 | function __construct() { 88 | global $langs; 89 | 90 | parent::set_table(MAIN_DB_PREFIX.'bonderetourdet_asset'); 91 | parent::add_champs('fk_bonderetourdet,fk_product,fk_warehouse','type=entier;index;'); 92 | parent::add_champs('rang','type=entier;'); 93 | parent::add_champs('lot_number,carton,numerosuivi,imei,firmware,serial_number','type=chaine;'); 94 | parent::add_champs('weight, weight_reel, tare','type=float;'); 95 | parent::add_champs('dluo','type=date;'); 96 | parent::add_champs('weight_unit, weight_reel_unit, tare_unit','type=entier;'); 97 | 98 | parent::_init_vars(); 99 | parent::start(); 100 | } 101 | 102 | function loadLines(&$PDOdb, $id_bdrLine){ 103 | 104 | $sql = "SELECT rowid FROM ".$this->get_table()." WHERE fk_bonderetourdet = ".$id_bdrLine." ORDER BY rang"; 105 | 106 | $TIdBDRdet = TRequeteCore::_get_id_by_sql($PDOdb, $sql); 107 | 108 | foreach($TIdBDRdet as $idbdrdet){ 109 | $detail_temp = new TRecepBDRDetail; 110 | $detail_temp->load($PDOdb, $idbdrdet); 111 | $this->lines[] = $detail_temp; 112 | $this->nbLines = $this->nbLines + 1; 113 | } 114 | } 115 | } 116 | 117 | class TRecepBDRDispatch extends TObjetStd { 118 | function __construct() 119 | { 120 | parent::set_table(MAIN_DB_PREFIX.'bonderetour_dispatch'); 121 | parent::add_champs('fk_bonderetour,fk_bonderetourdet,fk_product,fk_entrepot','type=entier;index;'); 122 | parent::add_champs('qty','type=float;'); 123 | parent::add_champs('eatby,sellby,batch,comment','type=chaine;'); 124 | 125 | parent::_init_vars(); 126 | parent::start(); 127 | } 128 | } 129 | -------------------------------------------------------------------------------- /modele/modele2.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Impression etiquette 5 | 93 | 94 | 182 | 183 | 184 | 185 |
186 | 187 |
188 | 189 |
190 |
latoxan@latoxan.com - LATOXAN - www.latoxan.fr
191 |
[etiquette.nom;block=((div))]
192 |
[etiquette.description;]
193 |
Code: 
[etiquette.ref]
194 |
Lot: 
[etiquette.lot]
195 |
Poids Net :
[etiquette.poids] [etiquette.poids_unit]
196 |
Distributed by : FUNAKOSHI CO. LTD, 9-7 Hongo 2-Chome-Bunkyo-ku, Tokyo 113, Japan
TEL: +81 3 5684 1622 - FAX: +81 3 5684 1633
197 |
FOR RESEARCH PURPOSES ONLY
198 |
199 | 200 | -------------------------------------------------------------------------------- /langs/de_DE/dispatch.lang: -------------------------------------------------------------------------------- 1 | Module104970Name=Dispatch 2 | Module104970Desc=Verwaltung der Bewegung von Waren beim Empfang, Versand, ... 3 | 4 | DispatchInterfaceDesc=Trigger des spezifischen Latoxan-Versandmoduls 5 | 6 | DispatchMenuTitle="Ready to Ship" 7 | 8 | DispatchSetup=Administration of the Dispatch module 9 | DispatchSetupTitle=Management of Receipt/Shipment details 10 | 11 | UseImportFile=Use file import to create shipping/receiving details 12 | DispatchRecepAutoQuantity=Automatically fill in the quantity ordered when a product is received 13 | DispatchDLUOByDefault=Automatically enter the DLUO with current date + X (X being the addition of day, month or year in sql format ex: +1 year) 14 | SUPPLIER_ORDER_RECEPTION=Supplier order reception 15 | 16 | ShippingDetailsTab=Lieferdetails 17 | ManualReceptionTab=Manueller Wareneingang 18 | EquipmentDetailsTab=Warendetails 19 | ReceptionTab=Wareneingang 20 | 21 | SerializedProduct=Serialisiertes Produkt 22 | SerializeThisProductInfo=Produkt empfangen 23 | SerializedProductInfo=This product is in serialized reception. To receive this product as standard, delete the appropriate lines from the equipment 24 | SerializeThisProduct=Seriennummern erfassen 25 | SerialNumberNeeded=Seriennummer erforderlich! 26 | AssetVentil=Wareneingang quittieren 27 | ProductsSent=Products shipped 28 | ProductsReceived=Products received 29 | 30 | 31 | ErrorSupplierTarif=Quantity price and Total price (if checked) 32 | ErrorSupplierTarifNoConf=Total price 33 | 34 | SupplierQtyPrice=Mini quantity for price 35 | TotalPriceOrdered=Total price payed 36 | GenerateSupplierTarif=Create new price 37 | 38 | DISPATCH_UPDATE_ORDER_PRICE_ON_RECEPTION=Update Supplier Order prices at products reception 39 | DISPATCH_CREATE_SUPPLIER_PRICE=Create supplier price at products reception to stock 40 | DISPATCH_HIDE_DLUO_PDF=Hide DLUO on shipping PDFs 41 | 42 | SaveBeforeVentil=Save your changes before starting the shipment 43 | DISPATCH_CREATE_NUMSERIE_ON_RECEPTION_IF_LOT=Allows you to create equipment with automatic serial number upon receipt if the batch is entered 44 | createNumSerieOnTheFly=Creation of the serial number %s on the fly 45 | 46 | DISPATCH_USE_ONLY_UNIT_ASSET_RECEPTION=Allocate the quantity 47 | DISPATCH_SHOW_UNIT_RECEPTION=Display the unit on the reception screen 48 | 49 | QtyDispatchedShort=Bereits eingegangen 50 | QtyToDispatchShort=Erwartet 51 | 52 | DISPATCH_CREATE_NUMSERIE_ON_RECEPTION_FROM_FIRST_INPUT=Enable asset creation with automatic serial numbers when dispatching, from the first input serial number for a product 53 | CalculateFollowingSerialNumbers=Calculate the others 54 | 55 | DISPATCH_CAN_LINK_ASSET_TO_OBJECT_IN_ANY_STATUS=Enable linking/unlinking assets to objects (order, contrat, etc.) regardless of their status 56 | 57 | NoAssetCreated=No asset created in database 58 | AssetAlreadyLinked=Asset already linked to this shipment 59 | 60 | DISPATCH_SHIPPING_VALIDATE_ALERT_IF_NO_DETAIL=When validating an expedition, display an alert if no asset detail has been set 61 | DispatchExpeditionNoDetail=No asset detail has been set for this shipment 62 | 63 | DISPATCH_SHIPPING_LINES_CAN_BE_CHECKED_PREPARED=Assets in the shipments can be marked as "Prepared" 64 | DISPATCH_BLOCK_SHIPPING_CLOSING_IF_PRODUCTS_NOT_PREPARED=Block shipment closing if there are assets not marked as "Prepared" 65 | AssetMarkedAsPrepared=Line marked as "Prepared" 66 | AssetMarkedAsNotPrepared=Line marked as "Not prepared" 67 | AssetsMarkedAsPrepared=All lines marked as "Prepared" 68 | AssetsMarkedAsNotPrepared=All lines marked as "Not prepared" 69 | NAssetsMarkedCouldNotBeMarked=%s line(s) unmodified 70 | NoShipmentAssetDetail=There are no assets in this shipment 71 | ShipmentCannotBeClosed=This shipment can't be closed : 72 | ShipmentCannotBeClosedAssetsNotPrepared=All assets have not been prepared 73 | ShipmentCannotBeClosedSerializedLinesHaveNoDetail=Some serialized lines don't have assets 74 | ShipmentCannotBeClosedQtyDoesntMatch=The quantity of assets linked to one or more lines is lower than the line's quantity 75 | 76 | NoBDRAssetDetail=No asset in this return voucher 77 | DispatchBonderetour=Receipt of the return form %s 78 | ReceivingForSameBDR=Receipts for this return form 79 | StockMovementAssetStockTransfered=Equipment return %s on return slip %s 80 | BDRCalculateAuto=The shipment is done automatically at the %s of the return slip 81 | BDRValidate=Validate 82 | BDRClose=Close 83 | 84 | DISPATCH_RESET_ASSET_WAREHOUSE_ON_SHIPMENT=Removing the warehouse from the equipment upon shipment validation 85 | DISPATCH_SKIP_SERVICES=Ignoring services 86 | DISPATCH_STOCK_MOVEMENT_BY_ASSET=When there is more than one piece of equipment for the same product upon receipt, ensure that there is one goods movement per piece of equipment, rather than one overall goods movement containing all the equipment 87 | 88 | # Expedition Card 89 | colDispatch=Serial number / batch 90 | 91 | LIST_SHIPMENTS_TO_PREPARE=List of shipments to be prepared 92 | LIST_NO_SHIPMENTS=No shipments to display 93 | COUNT_REL_EQUIPMENT=%s related equipments 94 | AFFECTED_ROW=Affected row 95 | DispatchSelectProduct=Produkt auswählen 96 | DispatchItemCountDispatch=%s Artikel in dieser Sendung 97 | DispatchItemCountReception=%s Artikel in dieser Lieferung 98 | DispatchSerialNumber=Seriennummer 99 | DispatchBatchNumber=Chargennummer 100 | DispatchDateReception=Datum des Wareneingangs 101 | DispatchMsgAssetGen=Asset erstellt / Produkt empfangen -------------------------------------------------------------------------------- /img/object_dispatch.svg: -------------------------------------------------------------------------------- 1 | 2 | image/svg+xml 26 | 27 | 33 | 34 | 36 | 37 | 39 | 40 | 42 | 43 | 45 | 46 | 48 | 49 | 51 | 52 | 54 | 55 | 57 | 58 | 60 | 61 | 63 | 64 | 66 | 67 | 69 | 70 | 72 | 73 | 75 | 76 | -------------------------------------------------------------------------------- /langs/en_US/dispatch.lang: -------------------------------------------------------------------------------- 1 | Module104970Name=Dispatch 2 | Module104970Desc=Management of the movement of equipment on receipt, shipment, ... 3 | 4 | DispatchInterfaceDesc=Trigger of the specific Latoxan shipping moduls 5 | 6 | DispatchMenuTitle=Shipment to be prepared 7 | 8 | DispatchSetup=Administration of the Dispatch module 9 | DispatchSetupTitle=Management of Receipt/Shipment details 10 | 11 | UseImportFile=Use file import to create shipping/receiving details 12 | DispatchRecepAutoQuantity=Automatically fill in the quantity ordered when a product is received 13 | DispatchDLUOByDefault=Automatically enter the BBD with current date + X (X being the addition of day, month or year in sql format ex: +1 year) 14 | SUPPLIER_ORDER_RECEPTION=Supplier order reception 15 | 16 | ShippingDetailsTab=Shipping details 17 | ManualReceptionTab=Manual reception 18 | EquipmentDetailsTab=Equipment details 19 | ReceptionTab=Reception of equipment/products 20 | 21 | SerializedProduct=Serialized product 22 | SerializeThisProductInfo=Receive equipment of this product 23 | SerializedProductInfo=This product is in serialized reception. To receive this product as standard, delete the appropriate lines from the equipment 24 | SerializeThisProduct=Serialize this row 25 | SerialNumberNeeded=Serial number required 26 | AssetVentil=Ship products and create equipment 27 | ProductsSent=Products shipped 28 | ProductsReceived=Products received 29 | 30 | 31 | ErrorSupplierTarif=Quantity price and Total price (if checked) 32 | ErrorSupplierTarifNoConf=Total price 33 | 34 | SupplierQtyPrice=Mini quantity for price 35 | TotalPriceOrdered=Total price payed 36 | GenerateSupplierTarif=Create new price 37 | 38 | DISPATCH_UPDATE_ORDER_PRICE_ON_RECEPTION=Update Supplier Order prices at products reception 39 | DISPATCH_CREATE_SUPPLIER_PRICE=Create supplier price at products reception to stock 40 | DISPATCH_HIDE_DLUO_PDF=Hide BBD on shipping PDFs 41 | 42 | SaveBeforeVentil=Save your changes before starting the shipment 43 | DISPATCH_CREATE_NUMSERIE_ON_RECEPTION_IF_LOT=Allows you to create equipment with automatic serial number upon receipt if the batch is entered 44 | createNumSerieOnTheFly=Creation of the serial number %s on the fly 45 | 46 | DISPATCH_USE_ONLY_UNIT_ASSET_RECEPTION=Allocate the quantity 47 | DISPATCH_SHOW_UNIT_RECEPTION=Display the unit on the reception screen 48 | 49 | QtyDispatchedShort=Already received 50 | QtyToDispatchShort=Awaited 51 | 52 | DISPATCH_CREATE_NUMSERIE_ON_RECEPTION_FROM_FIRST_INPUT=Enable asset creation with automatic serial numbers when dispatching, from the first input serial number for a product 53 | CalculateFollowingSerialNumbers=Calculate the others 54 | 55 | DISPATCH_CAN_LINK_ASSET_TO_OBJECT_IN_ANY_STATUS=Enable linking/unlinking assets to objects (order, contrat, etc.) regardless of their status 56 | 57 | NoAssetCreated=No asset created in database 58 | AssetAlreadyLinked=Asset already linked to this shipment 59 | 60 | DISPATCH_SHIPPING_VALIDATE_ALERT_IF_NO_DETAIL=When validating an expedition, display an alert if no asset detail has been set 61 | DispatchExpeditionNoDetail=No asset detail has been set for this shipment 62 | 63 | DISPATCH_SHIPPING_LINES_CAN_BE_CHECKED_PREPARED=Assets in the shipments can be marked as "Prepared" 64 | DISPATCH_BLOCK_SHIPPING_CLOSING_IF_PRODUCTS_NOT_PREPARED=Block shipment closing if there are assets not marked as "Prepared" 65 | AssetMarkedAsPrepared=Line marked as "Prepared" 66 | AssetMarkedAsNotPrepared=Line marked as "Not prepared" 67 | AssetsMarkedAsPrepared=All lines marked as "Prepared" 68 | AssetsMarkedAsNotPrepared=All lines marked as "Not prepared" 69 | NAssetsMarkedCouldNotBeMarked=%s line(s) unmodified 70 | NoShipmentAssetDetail=There are no assets in this shipment 71 | ShipmentCannotBeClosed=This shipment can't be closed : 72 | ShipmentCannotBeClosedAssetsNotPrepared=All assets have not been prepared 73 | ShipmentCannotBeClosedSerializedLinesHaveNoDetail=Some serialized lines don't have assets 74 | ShipmentCannotBeClosedQtyDoesntMatch=The quantity of assets linked to one or more lines is lower than the line's quantity 75 | 76 | NoBDRAssetDetail=No asset in this return voucher 77 | DispatchBonderetour=Receipt of the return form %s 78 | ReceivingForSameBDR=Receipts for this return form 79 | StockMovementAssetStockTransfered=Equipment return %s on return slip %s 80 | BDRCalculateAuto=The shipment is done automatically at the %s of the return slip 81 | BDRValidate=Validate 82 | BDRClose=Close 83 | 84 | DISPATCH_RESET_ASSET_WAREHOUSE_ON_SHIPMENT=Removing the warehouse from the equipment upon shipment validation 85 | DISPATCH_SKIP_SERVICES=Ignoring services 86 | DISPATCH_STOCK_MOVEMENT_BY_ASSET=When there is more than one piece of equipment for the same product upon receipt, ensure that there is one goods movement per piece of equipment, rather than one overall goods movement containing all the equipment 87 | 88 | # Expedition Card 89 | colDispatch=Serial number / batch 90 | 91 | LIST_SHIPMENTS_TO_PREPARE=List of shipments to be prepared 92 | LIST_NO_SHIPMENTS=No shipments to display 93 | COUNT_REL_EQUIPMENT=%s related equipments 94 | AFFECTED_ROW=Affected row 95 | DispatchSelectProduct=Select a product 96 | DispatchItemCountDispatch=%s item(s) in this delivery 97 | DispatchItemCountReception=%s item(s) in this shipment 98 | DispatchSerialNumber=Serial number 99 | DispatchBatchNumber=Batch number 100 | DispatchDateReception=Date of incoming delivery 101 | DispatchMsgAssetGen=Equipment created / Ventilated products 102 | 103 | 104 | 105 | DISPATCH_ALLOW_DISPATCHING_EXISTING_ASSET = Allow dispatching the same asset several times 106 | ProductHasToBeSerialize = The product %s must be serialized 107 | ShipmentsList = List of unprocessed shipments 108 | SelectShipment = Shipment(s) requiring ventilations 109 | supplierOrderLinkedShipment = Shipment linked with the supplier order 110 | SelectExpe = Process this shipment 111 | NbItemCountInReception = Shipment details 112 | Warehouse = Warehouse 113 | Product = Product 114 | DeletedLine = Deleted line 115 | NoSerialNumber = No serial number: unable to create asset for %s. If you do not wish to serialize this product, please delete the serial number lines and use the standard reception process 116 | DLUO = Best Before Date 117 | IMEI = IMEI 118 | Firmware = Firmware 119 | TreatedExpe = Shipment processed 120 | ShipmentsTreatedList = List of processed shipments 121 | VentilatedExpeditions = Ventilated shipment(s) 122 | ResultSetEquipmentError = An error occurred with the SQL query for fetching assets 123 | ErrorAtResultSet = An error occurred in the %s query 124 | ErrorAtSaveObjectRecepDetail = Unable to save: SQL query error -------------------------------------------------------------------------------- /asset.php: -------------------------------------------------------------------------------- 1 | loadByObject($PDOdb,$id,$type_object); 19 | 20 | $action = GETPOST('action'); 21 | 22 | switch ($action) { 23 | case 'save': 24 | 25 | $TLine = GETPOST('TLine'); 26 | if(!empty($TLine[-1]['serial_number']) && (!empty($TLine[-1]['fk_object']) || GETPOST('type_object') === 'ticketsup')) 27 | // Si type_object == ticketsup on n'empêche pas l'ajout si aucune ligne est sélectionnée car aucun sens d'associer un asset à un message sur un ticket 28 | { 29 | 30 | $asset = new TAsset; 31 | $asset->loadReference($PDOdb, $TLine[-1]['serial_number']); 32 | 33 | if($asset->getId()>0) { 34 | $k=$dispatch->addChild($PDOdb, 'TDispatchAsset'); 35 | $dispatch->TDispatchAsset[$k]->fk_asset = $asset->getId(); 36 | $dispatch->TDispatchAsset[$k]->fk_object = $TLine[-1]['fk_object']; 37 | $dispatch->TDispatchAsset[$k]->type_object = $type_object; 38 | $dispatch->TDispatchAsset[$k]->asset = $asset; 39 | 40 | $dispatch->save($PDOdb); 41 | } 42 | 43 | } 44 | 45 | break; 46 | case 'delete-line': 47 | $k = (int)GETPOST('k'); 48 | $dispatch->TDispatchAsset[$k]->to_delete=true; 49 | 50 | $dispatch->save($PDOdb); 51 | break; 52 | } 53 | 54 | _fiche($PDOdb,$dispatch); 55 | 56 | function _fiche(&$PDOdb,&$dispatch) { 57 | global $db,$conf,$langs; 58 | 59 | llxHeader(); 60 | 61 | $form=new TFormCore('auto','asset','post'); 62 | echo $form->hidden('action', 'save'); 63 | echo $form->hidden('id', $dispatch->fk_object); 64 | echo $form->hidden('type_object', $dispatch->type_object); 65 | 66 | $object = _header($dispatch->fk_object,$dispatch->type_object); 67 | $pListe[0] = "Sélectionnez une ligne"; 68 | foreach($object->lines as $k=>&$line){ 69 | $label = !empty($line->label) ? $line->label : $line->libelle; 70 | if(empty($label) && !empty($line->desc))$label = $line->desc; 71 | 72 | $pListe[$line->id] = ($k+1).'/ '.$label; 73 | } 74 | 75 | print $langs->trans( 'COUNT_REL_EQUIPMENT', count($dispatch->TDispatchAsset) ).'
'; 76 | 77 | ?> 78 | 79 | 80 | ' . $langs->trans('AFFECTED_ROW' ) . ''; 82 | ?> 83 | 84 | global->USE_LOT_IN_OF)) { 86 | ?> 87 | 88 | 89 | 92 | global->clinomadic->enabled){ 94 | ?> 95 | 96 | 97 | 100 | 101 | 102 | 103 | global->DISPATCH_CAN_LINK_ASSET_TO_OBJECT_IN_ANY_STATUS) || $dispatch->type_object == 'contrat' || $object->statut == 0; 106 | 107 | foreach($dispatch->TDispatchAsset as $k=>&$da) { 108 | 109 | if($da->to_delete) continue; 110 | 111 | ?> 112 | '.$pListe[$da->fk_object].''; ?> 113 | 114 | global->USE_LOT_IN_OF)) { 116 | ?> 117 | 118 | 119 | 122 | 123 | 124 | 125 | global->clinomadic->enabled){ 127 | ?> 128 | 129 | 130 | 133 | 138 | 139 | 140 | 151 | '.$form->combo('', 'TLine[-1][fk_object]', $pListe, '').''; ?> 152 | 153 | global->USE_LOT_IN_OF)) { 155 | ?> 158 | 159 | global->clinomadic->enabled){ 161 | ?> 162 | 163 | 164 | 167 | 169 | 174 |
trans('Equipment'); // Equipement ?>trans('DispatchBatchNumber'); ?>trans('EatByDate'); // DLUO ?>IMEIFirmware 
asset->getNomUrl(1,0,1); ?>asset->lot_number; ?>asset->dluo ? dol_print_date($da->asset->dluo) : 'N/A'; ?>IMEIFirmwareid.'&type_object='.$dispatch->type_object.'">'.img_delete().''; 136 | 137 | ?>
texte('','TLine[-1][serial_number]', $newAssetSerialNumber, 30); ?>    Nouveau 168 |
175 | 188 | btsubmit($langs->trans('Save'), 'bt_new'); 191 | 192 | dol_fiche_end(); 193 | 194 | $form->end(); 195 | 196 | llxFooter(); 197 | 198 | 199 | } 200 | function _header($id,$type_object) { 201 | global $db,$langs; 202 | 203 | $langs->load('interventions'); 204 | $langs->load('contracts'); 205 | 206 | if($type_object == 'contrat') { 207 | $object=new Contrat($db); 208 | $object->fetch($id); 209 | dol_include_once('/core/lib/contract.lib.php'); 210 | $head = contract_prepare_head($object); 211 | dol_fiche_head($head, 'dispatchAsset', $langs->trans("Contract"), 0, 'contract'); 212 | 213 | 214 | 215 | } 216 | else if($type_object=='intervention') { 217 | $object=new Fichinter($db); 218 | $object->fetch($id); 219 | dol_include_once('/core/lib/fichinter.lib.php'); 220 | $head = fichinter_prepare_head($object); 221 | dol_fiche_head($head, 'dispatchAsset', $langs->trans("InterventionCard"), 0, 'intervention'); 222 | } 223 | else if($type_object=='ticketsup') { 224 | dol_include_once('/ticketsup/class/ticketsup.class.php'); 225 | dol_include_once('/ticketsup/lib/ticketsup.lib.php'); 226 | $object = new Ticketsup($db); 227 | $object->fetch($id); 228 | $head = ticketsup_prepare_head($object); 229 | dol_fiche_head($head, 'dispatchAsset', $langs->trans("Ticket"), 0, 'ticketsup@ticketsup'); 230 | } 231 | else if($type_object=='commande') { 232 | dol_include_once('/commande/class/commande.class.php'); 233 | dol_include_once('/core/lib/order.lib.php'); 234 | $object = new Commande($db); 235 | $object->fetch($id); 236 | $head = commande_prepare_head($object); 237 | dol_fiche_head($head, 'dispatchAsset', $langs->trans("CustomerOrder"), 0, 'order'); 238 | } 239 | 240 | return $object; 241 | 242 | } 243 | 244 | -------------------------------------------------------------------------------- /langs/fr_FR/dispatch.lang: -------------------------------------------------------------------------------- 1 | Module104970Name=Dispatch 2 | Module104970Desc=Gestion de la ventilation des équipements sur réception, expédition, ... 3 | 4 | DispatchInterfaceDesc=Trigger du module expédtion spécifique Latoxan 5 | 6 | DispatchMenuTitle=Expédition à préparer 7 | 8 | DispatchSetup=Administration du module Dispatch 9 | DispatchSetupTitle=Gestion des détails Réception/Expédidion, à propos 10 | 11 | UseImportFile=Utiliser l'import de fichier pour créer les détails expédition/réception 12 | DispatchRecepAutoQuantity=Renseigné automatiquement la quantité commandé lors de la réception d'un produit 13 | DispatchDLUOByDefault=Renseigner automatiquement la DLUO avec date du jour + X (X étant l'ajout de jour, mois ou année au format sql ex: +1 year) 14 | SUPPLIER_ORDER_RECEPTION=Réception commande fournisseur 15 | 16 | ShippingDetailsTab=Détail expédition 17 | ManualReceptionTab=Réception manuelle 18 | EquipmentDetailsTab=Détail équipement 19 | ReceptionTab=Réception équipements/produits 20 | 21 | SerializedProduct=Produit sérialisé 22 | SerializeThisProductInfo=Réceptionner des équipements de ce produit 23 | SerializedProductInfo=Ce produit est en réception sérialisé. Pour réceptionner ce produit de manière standard, supprimez les lignes adéquates des équipements 24 | SerializeThisProduct=Sérialiser cette ligne 25 | SerialNumberNeeded=Numéro de série requis 26 | AssetVentil=Ventiler les produits et créer les équipements 27 | ProductsSent=Produits expédiés 28 | ProductsReceived=Produits reçus 29 | 30 | 31 | ErrorSupplierTarif=Quantité tarif et Prix Total (si coché) 32 | ErrorSupplierTarifNoConf=Prix Total payé 33 | 34 | SupplierQtyPrice=Qté mini du tarif 35 | TotalPriceOrdered=Prix Total payé 36 | GenerateSupplierTarif=Créer le tarif 37 | 38 | DISPATCH_UPDATE_ORDER_PRICE_ON_RECEPTION=Mettre à jour les prix de la commande lors de la ventillation 39 | DISPATCH_CREATE_SUPPLIER_PRICE=Générer des prix fournisseurs à la réception des produits vers stocks 40 | DISPATCH_HIDE_DLUO_PDF=Cacher la DLUO sur les PDF d'expédition 41 | DISPATCH_GROUP_DETAILS_ON_PDF=Sur une expédition, Grouper les quantités par numéro de lot au lieu de voir les numéros de séries 42 | 43 | SaveBeforeVentil=Sauvegardez vos modifications avant de lancer la ventilation 44 | DISPATCH_CREATE_NUMSERIE_ON_RECEPTION_IF_LOT=Permettre de créer les équipements avec numéro de série automatique lors d'une réception si le lot est saisi 45 | createNumSerieOnTheFly=Création du numéro de série %s à la volée 46 | 47 | DISPATCH_USE_ONLY_UNIT_ASSET_RECEPTION=Ne pas autoriser la saisie de la quantité lors de la ventilation (quantité auto attribuée = 1) 48 | DISPATCH_SHOW_UNIT_RECEPTION=Afficher l'unité sur l'écran de récéption 49 | 50 | QtyDispatchedShort=Déjà ventilé 51 | QtyToDispatchShort=Qté à ventiler 52 | 53 | DISPATCH_CREATE_NUMSERIE_ON_RECEPTION_FROM_FIRST_INPUT=Permettre de créer les équipements avec numéro de série automatique lors d'une réception à partir du premier numéro de série saisi pour chaque produit 54 | CalculateFollowingSerialNumbers=Calculer les suivants 55 | 56 | DISPATCH_CAN_LINK_ASSET_TO_OBJECT_IN_ANY_STATUS=Permettre de lier/délier des équipements à des objets (commande, contrat, etc.) quel que soit leur statut 57 | 58 | NoAssetCreated=Aucun équipement créé en base 59 | AssetAlreadyLinked=Numéro de série déjà réceptionné 60 | 61 | DISPATCH_SHIPPING_VALIDATE_ALERT_IF_NO_DETAIL=Lors de la validation d'une expédition, afficher une alerte si aucun détail des équipements n'a été renseigné 62 | DispatchExpeditionNoDetail=Le détail des équipements n'a pas été renseigné 63 | 64 | DISPATCH_SHIPPING_LINES_CAN_BE_CHECKED_PREPARED=Les équipements présents dans le détail d'expédition peuvent être marqués "préparés" 65 | DISPATCH_BLOCK_SHIPPING_CLOSING_IF_PRODUCTS_NOT_PREPARED=Bloquer la clôture d'une expédition si des équipements sont marqués comme non préparés 66 | AssetMarkedAsPrepared=Ligne marquée 'Préparée' 67 | AssetMarkedAsNotPrepared=Ligne marquée 'Non préparée' 68 | AssetsMarkedAsPrepared=Toutes les lignes marquée 'Préparée' 69 | AssetsMarkedAsNotPrepared=Tout les lignes marquées 'Non préparée' 70 | NAssetsMarkedCouldNotBeMarked=%s ligne(s) non modifiée(s) 71 | NoShipmentAssetDetail=Pas d'équipements dans cette expédition 72 | ShipmentCannotBeClosed=L'expédition ne peut être close : %s 73 | ShipmentCannotBeClosedAssetsNotPrepared=Tous les équipements n'ont pas été préparés 74 | ShipmentCannotBeClosedSerializedLinesHaveNoDetail=Certaines lignes de produits sérializés n'ont pas d'équipement lié 75 | ShipmentCannotBeClosedQtyDoesntMatch=La quantité d'équipements liés est inférieure à la quantité de la ligne associée 76 | 77 | NoBDRAssetDetail=Pas d'équipements dans ce bon de retour 78 | DispatchBonderetour=Réception du bon de retour %s 79 | ReceivingForSameBDR=Réceptions pour ce bon de retour 80 | StockMovementAssetStockTransfered=Retour de l'équipement %s sur bon de retour %s 81 | BDRCalculateAuto=La ventilation est faite automatiquement à la %s du bon de retour 82 | BDRValidate=validation 83 | BDRClose=cloture 84 | 85 | DISPATCH_RESET_ASSET_WAREHOUSE_ON_SHIPMENT=Retirer l'entrepot de l'équipement à la validation de l'expédition 86 | DISPATCH_SKIP_SERVICES=Ignorer les lignes de type service 87 | DISPATCH_STOCK_MOVEMENT_BY_ASSET=Lorsqu'il y a plusieurs équipements pour le même produit lors d'une réception, faire en sorte qu'il y ait un mouvement de stock par équipement, plutôt qu'un mouvement de stock global contenant tous les équipements 88 | DISPATCH_ALLOW_DISPATCHING_EXISTING_ASSET=Permettre de réceptionner plusieurs fois un équipement existant 89 | 90 | AllSerialNumbersAdded=Les numéros de série ont été enregistré automatiquement 91 | NoMoreAssetAvailable=Aucun équipement disponible pour ce numéro de lot 92 | AssetsWithoutLotNumber=Equipements sans numéro de lot 93 | 94 | # Expedition Card 95 | colDispatch=N° de série / lot 96 | 97 | LIST_SHIPMENTS_TO_PREPARE=Liste des expéditions à préparer 98 | LIST_NO_SHIPMENTS=Il n'y a aucunes expédition à afficher 99 | COUNT_REL_EQUIPMENT=%s équipement(s) lié(s) 100 | AFFECTED_ROW=Ligne concernée 101 | DispatchSelectProduct=Sélectionnez un produit 102 | DispatchItemCountDispatch=%s équipement(s) dans votre expédition 103 | DispatchItemCountReception=%s équipement(s) dans votre réception 104 | DispatchSerialNumber=Numéro de série 105 | DispatchBatchNumber=Numéro de Lot 106 | DispatchDateReception=Date de réception 107 | DispatchMsgAssetGen=Equipements créés / produits ventilés 108 | ProductHasToBeSerialize=Le produit %s doit être sérialisé 109 | 110 | # 111 | # T2476 112 | # 113 | ShipmentsList = Liste des expéditions non traitées 114 | SelectShipment = Expédition(s) à ventiler 115 | supplierOrderLinkedShipment = Expédition liée à la commande fournisseur 116 | SelectExpe = Traiter cette expédition 117 | NbItemCountInReception = Détail de l'expédition 118 | Warehouse = Entrepôt 119 | Product = Produit 120 | DeletedLine = Ligne supprimée 121 | NoSerialNumber = Pas de numéro de série : impossible de créer l'équipement pour %s . Si vous ne voulez pas sérialiser ce produit, supprimez les lignes de numéro de série et faites une réception simple 122 | DLUO = DLUO 123 | IMEI = IMEI 124 | Firmware = Firmware 125 | TreatedExpe = Expédition traitée 126 | ShipmentsTreatedList = Liste des expéditions traitées 127 | VentilatedExpeditions = Expédition(s) ventilées 128 | ResultSetEquipmentError = Une erreur est survenue dans la requête des équipements 129 | ErrorAtResultSet = Une erreur est survenue dans la requête de %s 130 | ErrorUnableToFetchLine=Impossible de récupérer la ligne %d 131 | ErrorAtSaveObjectRecepDetail = Une erreur est survenue lors de l'enregistrement en base de données 132 | DISPATCH_ALLOW_DISPATCHING_IGNORING_LOCALISATION=Ignorer la localisation dans le détail des équipements sur une expédition 133 | DISPATCH_ALLOW_SENDING_SAME_PRODUCT_IN_SAME_EXP=Possibilité d'envoyer un numéro de série déjà présent dans une même expédition 134 | 135 | 136 | DISPATCH_RESET_ASSET_QTY_DELETE_SHIPMENT=Réalimenter équipement à la suppression de l'expédition 137 | -------------------------------------------------------------------------------- /admin/admin.php: -------------------------------------------------------------------------------- 1 | load('dispatch@dispatch'); 10 | $langs->load('admin'); 11 | 12 | if (!($user->admin)) accessforbidden(); 13 | 14 | $action=__get('action',''); 15 | 16 | if($action=='save') { 17 | 18 | foreach($_REQUEST['TDispatch'] as $name=>$param) { 19 | 20 | dolibarr_set_const($db, $name, $param, 'chaine', 0, '', $conf->entity); 21 | 22 | } 23 | 24 | setEventMessage("Configuration enregistrée"); 25 | } 26 | 27 | if($action == 'setconst') { 28 | $const = GETPOST('const', 'alpha'); 29 | dolibarr_set_const($db,$const,GETPOST($const,'alpha'),'chaine',0,'',$conf->entity); 30 | } 31 | 32 | 33 | llxHeader('', $langs->trans("DispatchSetupTitle"), ''); 34 | 35 | $linkback = ''.$langs->trans("BackToModuleList").''; 36 | print load_fiche_titre( $langs->trans("DispatchSetup"), $linkback ); 37 | 38 | print ''; 39 | print ''; 40 | print ''."\n"; 41 | print ''; 42 | print ''."\n"; 43 | 44 | $var=!$var; 45 | print ''; 46 | print ''; 47 | print ''; 48 | print ''; 51 | 52 | $var=!$var; 53 | print ''; 54 | print ''; 55 | print ''; 56 | print ''; 59 | 60 | $var=!$var; 61 | print ''; 62 | print ''; 63 | print ''; 64 | print ''; 67 | 68 | $form=new TFormCore; 69 | 70 | print ''; 71 | print ''."\n"; 72 | print ''; 73 | print ''."\n"; 74 | print ''; 75 | 76 | // Champ supplémentaire contenant le code comptable produit pour les ventes CEE 77 | $var=! $var; 78 | $form = new TFormCore($_SERVER["PHP_SELF"],'const_dluo_by_default'); 79 | print $form->hidden('action','setconst'); 80 | print $form->hidden('const','DISPATCH_DLUO_BY_DEFAULT'); 81 | print '\n"; 88 | $form->end(); 89 | 90 | $var=!$var; 91 | print ''; 92 | print ''; 93 | print ''; 94 | print ''; 97 | 98 | $var=!$var; 99 | print ''; 100 | print ''; 101 | print ''; 102 | print ''; 105 | 106 | $var=!$var; 107 | print ''; 108 | print ''; 109 | print ''; 110 | print ''; 113 | 114 | $var=!$var; 115 | print ''; 116 | print ''; 117 | print ''; 118 | print ''; 121 | 122 | $var=!$var; 123 | print ''; 124 | print ''; 125 | print ''; 126 | print ''; 129 | 130 | $var=!$var; 131 | print ''; 132 | print ''; 133 | print ''; 134 | print ''; 137 | 138 | $var=!$var; 139 | print ''; 140 | print ''; 141 | print ''; 142 | print ''; 145 | 146 | $var=!$var; 147 | print ''; 148 | print ''; 149 | print ''; 150 | print ''; 153 | 154 | $var=!$var; 155 | print ''; 156 | print ''; 157 | print ''; 158 | print ''; 161 | 162 | $var=!$var; 163 | print ''; 164 | print ''; 165 | print ''; 166 | print ''; 169 | 170 | $var=!$var; 171 | print ''; 172 | print ''; 173 | print ''; 174 | print ''; 177 | 178 | $var=!$var; 179 | print ''; 180 | print ''; 181 | print ''; 182 | print ''; 185 | 186 | 187 | $var=!$var; 188 | print ''; 189 | print ''; 190 | print ''; 191 | print ''; 194 | 195 | $var=!$var; 196 | print ''; 197 | print ''; 198 | print ''; 199 | print ''; 202 | 203 | $var=!$var; 204 | print ''; 205 | print ''; 206 | print ''; 207 | print ''; 210 | 211 | $var=!$var; 212 | print ''; 213 | print ''; 214 | print ''; 215 | print ''; 218 | 219 | $var=!$var; 220 | print ''; 221 | print ''; 222 | print ''; 223 | print ''; 226 | 227 | $var=!$var; 228 | print ''; 229 | print ''; 230 | print ''; 231 | print ''; 234 | 235 | print "
'.$langs->trans("Parameters").' '.$langs->trans("Value").'
'.$langs->trans("UseImportFile").' '; 49 | print ajax_constantonoff('DISPATCH_USE_IMPORT_FILE'); 50 | print '
'.$langs->trans("DispatchRecepAutoQuantity").' '; 57 | print ajax_constantonoff('DISPATCH_RECEP_AUTO_QUANTITY'); 58 | print '
'.$langs->trans("DISPATCH_HIDE_DLUO_PDF").' '; 65 | print ajax_constantonoff('DISPATCH_HIDE_DLUO_PDF'); 66 | print '
'.$langs->trans("SUPPLIER_ORDER_RECEPTION").' '.$langs->trans("Value").'
'; 82 | print $langs->trans("DispatchDLUOByDefault"); 83 | print ''; 84 | print $form->texte('', 'DISPATCH_DLUO_BY_DEFAULT',$conf->global->DISPATCH_DLUO_BY_DEFAULT,30,255); 85 | print ''; 86 | print ''; 87 | print "
'.$langs->trans("DISPATCH_UPDATE_ORDER_PRICE_ON_RECEPTION").' '; 95 | print ajax_constantonoff("DISPATCH_UPDATE_ORDER_PRICE_ON_RECEPTION"); 96 | print '
'.$langs->trans("DISPATCH_CREATE_SUPPLIER_PRICE").' '; 103 | print ajax_constantonoff("DISPATCH_CREATE_SUPPLIER_PRICE"); 104 | print '
'.$langs->trans("DISPATCH_USE_ONLY_UNIT_ASSET_RECEPTION").' '; 111 | print ajax_constantonoff("DISPATCH_USE_ONLY_UNIT_ASSET_RECEPTION"); 112 | print '
'.$langs->trans("DISPATCH_SHOW_UNIT_RECEPTION").' '; 119 | print ajax_constantonoff("DISPATCH_SHOW_UNIT_RECEPTION"); 120 | print '
'.$langs->trans("DISPATCH_CREATE_NUMSERIE_ON_RECEPTION_IF_LOT").' '; 127 | print ajax_constantonoff('DISPATCH_CREATE_NUMSERIE_ON_RECEPTION_IF_LOT'); 128 | print '
'.$langs->trans('DISPATCH_CREATE_NUMSERIE_ON_RECEPTION_FROM_FIRST_INPUT').' '; 135 | print ajax_constantonoff('DISPATCH_CREATE_NUMSERIE_ON_RECEPTION_FROM_FIRST_INPUT'); 136 | print '
'.$langs->trans('DISPATCH_CAN_LINK_ASSET_TO_OBJECT_IN_ANY_STATUS').' '; 143 | print ajax_constantonoff('DISPATCH_CAN_LINK_ASSET_TO_OBJECT_IN_ANY_STATUS'); 144 | print '
'.$langs->trans('DISPATCH_SHIPPING_VALIDATE_ALERT_IF_NO_DETAIL').' '; 151 | print ajax_constantonoff('DISPATCH_SHIPPING_VALIDATE_ALERT_IF_NO_DETAIL'); 152 | print '
'.$langs->trans('DISPATCH_SHIPPING_LINES_CAN_BE_CHECKED_PREPARED').' '; 159 | print ajax_constantonoff('DISPATCH_SHIPPING_LINES_CAN_BE_CHECKED_PREPARED'); 160 | print '
'.$langs->trans('DISPATCH_BLOCK_SHIPPING_CLOSING_IF_PRODUCTS_NOT_PREPARED').' '; 167 | print ajax_constantonoff('DISPATCH_BLOCK_SHIPPING_CLOSING_IF_PRODUCTS_NOT_PREPARED'); 168 | print '
'.$langs->trans('DISPATCH_RESET_ASSET_WAREHOUSE_ON_SHIPMENT').' '; 175 | print ajax_constantonoff('DISPATCH_RESET_ASSET_WAREHOUSE_ON_SHIPMENT'); 176 | print '
'.$langs->trans('DISPATCH_RESET_ASSET_QTY_DELETE_SHIPMENT').' '; 183 | print ajax_constantonoff('DISPATCH_RESET_ASSET_QTY_DELETE_SHIPMENT'); 184 | print '
'.$langs->trans('DISPATCH_SKIP_SERVICES').' '; 192 | print ajax_constantonoff('DISPATCH_SKIP_SERVICES'); 193 | print '
'.$langs->trans('DISPATCH_STOCK_MOVEMENT_BY_ASSET').' '; 200 | print ajax_constantonoff('DISPATCH_STOCK_MOVEMENT_BY_ASSET'); 201 | print '
'.$langs->trans('DISPATCH_ALLOW_DISPATCHING_EXISTING_ASSET').' '; 208 | print ajax_constantonoff('DISPATCH_ALLOW_DISPATCHING_EXISTING_ASSET'); 209 | print '
'.$langs->trans('DISPATCH_GROUP_DETAILS_ON_PDF').' '; 216 | print ajax_constantonoff('DISPATCH_GROUP_DETAILS_ON_PDF'); 217 | print '
'.$langs->trans('DISPATCH_ALLOW_DISPATCHING_IGNORING_LOCALISATION').' '; 224 | print ajax_constantonoff('DISPATCH_ALLOW_DISPATCHING_IGNORING_LOCALISATION'); 225 | print '
'.$langs->trans('DISPATCH_ALLOW_SENDING_SAME_PRODUCT_IN_SAME_EXP').' '; 232 | print ajax_constantonoff('DISPATCH_ALLOW_SENDING_SAME_PRODUCT_IN_SAME_EXP'); 233 | print '
"; 236 | 237 | dol_fiche_end(); 238 | llxFooter(); 239 | -------------------------------------------------------------------------------- /script/interface_expedition_handler.php: -------------------------------------------------------------------------------- 1 | loadLangs(array("dispatch@dispatch", "other", 'main')); 16 | 17 | header('Content-Type: application/json'); 18 | 19 | // $idexpe = GETPOST('idexpe'); 20 | $idexpe = dol_htmlentitiesbr(GETPOST('idexpe')); 21 | $refexpe = dol_htmlentitiesbr(GETPOST('refexpe')); 22 | $entity = dol_htmlentitiesbr(GETPOST('entity')); 23 | $action = dol_htmlentitiesbr(GETPOST('action')); 24 | $idCommand = dol_htmlentitiesbr(GETPOST('comFourn')); 25 | $idWarehouse = dol_htmlentitiesbr(GETPOST('idWarehouse')); 26 | 27 | $JsonOutput = new stdClass(); 28 | 29 | 30 | // LoadLinesExpedition 31 | if (isset($action) && $action == 'loadExpeLines'){ 32 | 33 | $currentExp = new Expedition($db); 34 | $currentExp->fetch($idexpe); 35 | 36 | $output = load_fiche_titre($langs->trans("NbItemCountInReception" ). ' '.$currentExp->ref); 37 | 38 | $JsonOutput->html = $output; 39 | _getEquipmentsFromSupplier($currentExp, $JsonOutput); 40 | $JsonOutput->html .= '
'; 41 | $JsonOutput->html .= _formatDisplayTableProductsHeader(); 42 | $JsonOutput->html .= _formatDisplayTableProducts($currentExp,$entity, $idCommand, $idWarehouse); 43 | $JsonOutput->html .= '
'; 44 | } 45 | print json_encode($JsonOutput); 46 | 47 | 48 | /** 49 | * La commande client générée automatiquement chez (Entité A) 50 | * depuis une commande fournisseur passée par entité B (pour son founisseur Entité A) 51 | * ne possède pas le descriptif des equipements. 52 | * Nous devons le loader pour exploitation de l'expedition courante 53 | * @var Expedition $currentExpe 54 | * @param $currentExpe 55 | * 56 | */ 57 | function _getEquipmentsFromSupplier(&$currentExpe, &$JsonOutput) 58 | { 59 | global $langs, $db; 60 | 61 | if (!empty($currentExpe->lines)){ 62 | foreach ($currentExpe->lines as $currentLineExp) { 63 | 64 | // On remonte les equipements si l'expedition en possède ... 65 | $sql = "SELECT * FROM " . MAIN_DB_PREFIX . "expeditiondet_asset AS ea "; 66 | $sql .= " INNER JOIN " . MAIN_DB_PREFIX . "assetatm AS at ON ea.fk_asset = at.rowid "; 67 | $sql .= " WHERE ea.fk_expeditiondet = " . $currentLineExp->id; 68 | 69 | $resultsetEquipments = $db->query($sql); 70 | if (!$resultsetEquipments) { 71 | $JsonOutput->error = $langs->trans('ResultSetEquipmentError'); 72 | } 73 | 74 | $num = $db->num_rows($resultsetEquipments); 75 | $i = 0; 76 | $objs = array(); 77 | while ($i < $num) { 78 | $objs[$i]['obj'] = $db->fetch_object($resultsetEquipments); 79 | $i++; 80 | } 81 | // On ajoute les lignes d'infos équipements présents 82 | $currentLineExp->equipement = $objs; 83 | } 84 | } 85 | } 86 | 87 | 88 | /** 89 | * @return string 90 | */ 91 | function _formatDisplayTableProductsHeader(){ 92 | global $conf, $langs,$db; 93 | 94 | $output = ""; 95 | $output .= ""; 96 | $output .=''; 97 | $output .=''; 98 | $output .=''; 99 | if(! empty($conf->global->USE_LOT_IN_OF)) { 100 | $output .=''; 101 | } 102 | $output .=''; 103 | if($conf->global->ASSET_SHOW_DLUO){ 104 | $output .=''; 105 | } 106 | if(empty($conf->global->DISPATCH_USE_ONLY_UNIT_ASSET_RECEPTION)) { 107 | $output .=''; 108 | if ( ! empty($conf->global->DISPATCH_SHOW_UNIT_RECEPTION) ) { 109 | $output .= ''; 110 | } 111 | } 112 | if($conf->global->clinomadic->enabled){ 113 | $output .=''; 114 | $output .=''; 115 | } 116 | 117 | $output .=''; 118 | $output .=''; 119 | 120 | return $output; 121 | 122 | } 123 | 124 | /** 125 | * @param Expedition $currentExp 126 | * @param $entity 127 | * @return string 128 | */ 129 | function _formatDisplayTableProducts(&$currentExp,$entity, $idCommand, $idWarehouse){ 130 | 131 | global $conf, $langs, $db; 132 | 133 | $form = new TFormCore(); 134 | $prod = new Product($db); 135 | $output = ''; 136 | 137 | $TEquipements = array(); 138 | $TStandard = array(); 139 | 140 | if (!empty($currentExp->lines)) { 141 | foreach ($currentExp->lines as $k => $line) { 142 | 143 | if ($line->equipement) { 144 | foreach ($line->equipement as $key => $eq) { 145 | $eq['obj']->ref = $line->ref; 146 | $eq['obj']->qty = 1; 147 | $TEquipements[] = $eq; 148 | } 149 | } else { 150 | $TStandard[] = $line; 151 | } 152 | } 153 | } 154 | 155 | $TAllProductsAndAssets = array_merge($TEquipements, $TStandard); 156 | 157 | foreach ($TAllProductsAndAssets as $key=>$line) { 158 | if (is_array($line)) { 159 | $fk_asset = $line['obj']->fk_asset; 160 | }else $fk_asset = "standardProduct"; 161 | 162 | is_array($line) ? $prod->fetch($line['obj']->fk_product) : $prod->fetch($line->fk_product); 163 | 164 | $output .=""; 165 | $output .=""; 172 | $output .=''; 190 | 191 | // ENTREPOT 192 | $output .=''; 211 | 212 | // QTY 213 | if (is_array($line)) { 214 | $output .= ""; 215 | } 216 | else { 217 | $output .=''; 218 | } 219 | 220 | // LOTS 221 | if(! empty($conf->global->USE_LOT_IN_OF)) { 222 | $output .= ""; 223 | } 224 | 225 | // DLUO 226 | if(!empty($conf->global->ASSET_SHOW_DLUO)){ 227 | $output .=''; 228 | } 229 | 230 | if(empty($conf->global->DISPATCH_USE_ONLY_UNIT_ASSET_RECEPTION)) { 231 | // if(!empty($conf->global->DISPATCH_SHOW_UNIT_RECEPTION)) { 232 | // echo ''; 233 | // } 234 | } 235 | else{ 236 | if (is_array($line)) { 237 | $output .= ""; 238 | } 239 | else { 240 | $output .=''; 241 | } 242 | $output .=$form->hidden('TLine['.$key.'][quantity_unit]',$line->quantity_unit); 243 | } 244 | 245 | if($conf->global->clinomadic->enabled){ 246 | 247 | $output .=''; 248 | $output .=''; 249 | } 250 | 251 | $output .=''; 253 | $output .=''; 254 | $conf->entity = $backupEntity; 255 | } 256 | 257 | 258 | $output .= ''; 259 | $output .= '
'; 260 | $output .= '
'; 261 | $output .= ''; 262 | 263 | 264 | $output .= ''; 280 | $warning_asset = false; 281 | return $output; 282 | 283 | } 284 | -------------------------------------------------------------------------------- /script/interface.php: -------------------------------------------------------------------------------- 1 | fetch($fk_product); 73 | return $formproduct->selectWarehouses($prod->fk_default_warehouse,'TLine[-1][entrepot]','',1,0,$prod->id,'',0,1); 74 | } 75 | 76 | function _serial_number(&$PDOdb, $sn) { 77 | 78 | $sql = "SELECT DISTINCT(rowid) as id, serial_number 79 | FROM ".MAIN_DB_PREFIX.ATM_ASSET_NAME." 80 | WHERE serial_number LIKE '".$sn."%'"; 81 | $PDOdb->Execute($sql); 82 | $Tab=array(); 83 | 84 | while($obj=$PDOdb->Get_line()) { 85 | /* 86 | $Tab[]=array( 87 | 'value'=>$obj->id 88 | ,'label'=>$obj->serial_number 89 | ); 90 | */ 91 | 92 | $Tab[]=$obj->serial_number; 93 | } 94 | 95 | return $Tab; 96 | } 97 | 98 | function _autocomplete_asset(&$PDOdb, $lot_number, $productid, $expeditionID, $expeditionDetID) { 99 | global $db, $conf, $langs; 100 | $langs->load('other'); 101 | 102 | dol_include_once('/core/lib/product.lib.php'); 103 | dol_include_once('/societe/class/societe.class.php'); 104 | dol_include_once('/expedition/class/expedition.class.php'); 105 | 106 | $sql = "SELECT fk_entrepot FROM ".MAIN_DB_PREFIX."expeditiondet WHERE rowid = ".$expeditionDetID." LIMIT 1"; 107 | 108 | $societe = new Societe($db); 109 | $societe->fetch('', $conf->global->MAIN_INFO_SOCIETE_NOM); 110 | 111 | $TWarehouses = $PDOdb->ExecuteAsArray($sql); 112 | $warehouseID = $TWarehouses[0]->fk_entrepot; 113 | 114 | $sql = "SELECT DISTINCT a.rowid 115 | FROM ".MAIN_DB_PREFIX.ATM_ASSET_NAME." a 116 | LEFT JOIN ".MAIN_DB_PREFIX."expeditiondet_asset eda ON (eda.fk_asset = a.rowid) 117 | LEFT JOIN ".MAIN_DB_PREFIX."expeditiondet ed ON (ed.rowid = eda.fk_expeditiondet) 118 | LEFT JOIN ".MAIN_DB_PREFIX."expedition e ON (e.rowid = ed.fk_expedition) 119 | WHERE a.fk_product = ".$productid; 120 | 121 | // On ne prend pas en compte le numéro de lot dans la requête pour les équipements sans numéro de lot 122 | if ($lot_number == -3) $sql .= " AND (a.lot_number IS NULL OR a.lot_number = '')"; 123 | else $sql .= " AND a.lot_number = '".$lot_number."'"; 124 | 125 | if(empty($conf->global->DISPATCH_ALLOW_DISPATCHING_IGNORING_LOCALISATION)) { 126 | // note dans le cas des asset avec gestion de stock quantitatif la notion de localisation n'a généralement pas de sens 127 | // c'est pourquoi il faut désactiver le filtre de localisation sur les gestions quantitative 128 | if(! empty($societe->id)) 129 | { 130 | // Par défaut, dispatch associe un équipement réceptionné par commande fournisseur à une société qui porte le même nom que $mysoc 131 | $sql.= " 132 | AND ( COALESCE(a.fk_societe_localisation, 0) IN (0, ".$societe->id.") OR a.gestion_stock = 'QUANTITY' )"; 133 | } else { 134 | $sql.= " 135 | AND ( COALESCE(a.fk_societe_localisation, 0) = 0 OR a.gestion_stock = 'QUANTITY' )"; 136 | } 137 | } 138 | 139 | if(! empty($warehouseID)) { 140 | $sql.= " 141 | AND a.fk_entrepot = ".$warehouseID; 142 | } 143 | 144 | $sql.= " 145 | GROUP BY a.rowid 146 | HAVING 1=1"; 147 | if(empty($conf->global->DISPATCH_ALLOW_SENDING_SAME_PRODUCT_IN_SAME_EXP)) $sql .= " AND NOT(GROUP_CONCAT(e.rowid) IS NOT NULL AND GROUP_CONCAT(e.rowid, ',') REGEXP '(^|\,)" . $expeditionID . "(\,|$)')"; 148 | //Si l'équipement est attribué à une autre expédition qui a le statut brouillon ou validé, on ne le propose pas 149 | $exp = new Expedition($db); 150 | if(!empty($expeditionID)) { 151 | $exp->fetch($expeditionID); 152 | if($exp->statut == Expedition::STATUS_DRAFT || $exp->statut == Expedition::STATUS_VALIDATED ) { 153 | $fk_statut = 2; 154 | if(!empty($conf->global->STOCK_CALCULATE_ON_SHIPMENT)){ 155 | $fk_statut = 1; 156 | } 157 | $sql.= " AND SUM(a.contenancereel_value) > (SELECT COALESCE(SUM(eda2.weight),0) FROM ".MAIN_DB_PREFIX."expeditiondet_asset as eda2 LEFT JOIN ".MAIN_DB_PREFIX."expeditiondet as ed2 ON (ed2.rowid = eda2.fk_expeditiondet) LEFT JOIN ".MAIN_DB_PREFIX."expedition as e2 ON (e2.rowid = ed2.fk_expedition) WHERE e2.fk_statut < ".$fk_statut." AND eda2.fk_asset = a.rowid)"; 158 | } 159 | } 160 | 161 | 162 | $PDOdb->Execute($sql); 163 | $TAssetIds = $PDOdb->Get_All(); 164 | $totalAssets = count($TAssetIds); 165 | 166 | $Tres = array(); 167 | foreach ($TAssetIds as $res) 168 | { 169 | $asset = new TAsset; 170 | $asset->load($PDOdb, $res->rowid); 171 | $asset->load_asset_type($PDOdb); 172 | 173 | if($asset->contenancereel_value > 0) 174 | { 175 | $Tres[$asset->serial_number]['serial_number'] = $asset->serial_number; 176 | $Tres[$asset->serial_number]['qty'] = $asset->contenancereel_value; 177 | $Tres[$asset->serial_number]['unite_string'] = ($asset->assetType->measuring_units == 'unit') ? 'unité(s)' : measuring_units_string($asset->contenancereel_units, $asset->assetType->measuring_units); 178 | $Tres[$asset->serial_number]['unite'] = ($asset->assetType->measuring_units == 'unit') ? 'unité(s)' : $asset->contenancereel_units; 179 | $Tres[$asset->serial_number]['measuring_units'] = $asset->assetType->measuring_units; 180 | $Tres['DispatchTotalAssetsNumberInOF'] = $totalAssets; 181 | } 182 | } 183 | return $Tres; 184 | } 185 | 186 | function _autocomplete_lot_number(&$PDOdb, $productid) { 187 | global $db, $conf, $langs; 188 | $langs->load('other'); 189 | dol_include_once('/core/lib/product.lib.php'); 190 | 191 | $sql = "SELECT DISTINCT(lot_number),rowid, SUM(contenancereel_value) as qty, contenancereel_units as unit 192 | FROM ".MAIN_DB_PREFIX.ATM_ASSET_NAME." 193 | WHERE fk_product = ".$productid." GROUP BY lot_number,contenancereel_units,rowid HAVING SUM(contenancereel_value) != 0"; 194 | $PDOdb->Execute($sql); 195 | 196 | $TLotNumber = array('no_lot_number' => array('lot_number' => -3, 'label' => $langs->transnoentitiesnoconv('AssetsWithoutLotNumber'))); 197 | $PDOdb->Execute($sql); 198 | $Tres = $PDOdb->Get_All(); 199 | foreach($Tres as $res){ 200 | 201 | $asset = new TAsset; 202 | $asset->load($PDOdb, $res->rowid); 203 | $asset->load_asset_type($PDOdb); 204 | //pre($asset,true);exit; 205 | $TLotNumber[$res->lot_number]['lot_number'] = $res->lot_number; 206 | $TLotNumber[$res->lot_number]['label'] = $res->lot_number." / ".$res->qty." ".(($asset->assetType->measuring_units == 'unit') ? 'unité(s)' : measuring_units_string($res->unit,$asset->assetType->measuring_units)); 207 | } 208 | return $TLotNumber; 209 | } 210 | 211 | 212 | /** 213 | * Mark a shipment asset detail line as prepared 214 | * 215 | * @param TPDOdb $PDOdb Database connection 216 | * @param int $fk_expditiondet_asset ID of expeditiondet_asset line 217 | * @param int $is_prepared 0/1, whether the asset has been prepared or not 218 | * 219 | * @return array Response array with success and message fields, to be JSON-encoded 220 | */ 221 | function _set_line_is_prepared(TPDOdb &$PDOdb, $fk_expeditiondet_asset, $is_prepared) 222 | { 223 | global $langs; 224 | 225 | dol_include_once('/dispatch/class/dispatchdetail.class.php'); 226 | 227 | $langs->load('dispatch@dispatch'); 228 | 229 | $dispatchDetail = new TDispatchDetail; 230 | $dispatchLoaded = $dispatchDetail->load($PDOdb, $fk_expeditiondet_asset); 231 | 232 | if(empty($dispatchLoaded)) 233 | { 234 | return array('success' => false, 'message' => $langs->trans('CouldNotLoadAssetDetail')); 235 | } 236 | 237 | $dispatchDetail->is_prepared = $is_prepared; 238 | 239 | $dispatchID = $dispatchDetail->save($PDOdb); 240 | 241 | if(empty($dispatchID)) 242 | { 243 | return array('success' => false, 'message' => $langs->trans('CouldNotSaveAssetDetail')); 244 | } 245 | 246 | $message = $langs->trans(empty($is_prepared) ? 'AssetMarkedAsNotPrepared' : 'AssetMarkedAsPrepared'); 247 | 248 | return array('success' => true, 'message' => $message); 249 | } 250 | 251 | 252 | /** 253 | * Mark all shipment asset detail lines as prepared or not 254 | * 255 | * @param TPDOdb $PDOdb Database connection 256 | * @param int $fk_expedition ID of expedition 257 | * @param int $is_prepared 0/1, whether the asset has been prepared or not 258 | * 259 | * @return array Response array with success and message fields, to be JSON-encoded 260 | */ 261 | function _set_all_lines_is_prepared(TPDOdb &$PDOdb, $fk_expedition, $is_prepared) 262 | { 263 | global $langs; 264 | 265 | dol_include_once('/dispatch/class/dispatchdetail.class.php'); 266 | 267 | $langs->load('dispatch@dispatch'); 268 | 269 | $sql = 'SELECT eda.rowid 270 | FROM ' . MAIN_DB_PREFIX . 'expeditiondet_asset eda 271 | INNER JOIN ' . MAIN_DB_PREFIX .'expeditiondet ed ON (ed.rowid = eda.fk_expeditiondet) 272 | WHERE ed.fk_expedition = ' . $fk_expedition; 273 | 274 | $TDispatchDetail = $PDOdb->ExecuteAsArray($sql); 275 | 276 | $countFail = 0; 277 | 278 | foreach($TDispatchDetail as $dispatchDetailStatic) 279 | { 280 | $TResult = _set_line_is_prepared($PDOdb, $dispatchDetailStatic->rowid, $is_prepared); 281 | 282 | if(empty($TResult['success'])) 283 | { 284 | $countFail++; 285 | } 286 | } 287 | 288 | $message = $langs->trans(empty($is_prepared) ? 'AssetsMarkedAsNotPrepared' : 'AssetsMarkedAsPrepared'); 289 | 290 | if($countFail > 0) 291 | { 292 | $message = $langs->trans('NAssetsMarkedCouldNotBeMarked', $countFail); 293 | } 294 | 295 | return array('success' => $countFail == 0, 'message' => $message); 296 | } 297 | 298 | function _measuringUnits($measuring_style) 299 | { 300 | global $langs, $db; 301 | 302 | $langs->load("other"); 303 | $TArray = array(); 304 | 305 | 306 | require_once DOL_DOCUMENT_ROOT.'/core/class/cunits.class.php'; 307 | $measuringUnits = new CUnits($db); 308 | 309 | $filter = array(); 310 | $filter['t.active'] = 1; 311 | if ($measuring_style) $filter['t.unit_type'] = $measuring_style; 312 | 313 | $result = $measuringUnits->fetchAll( 314 | '', 315 | '', 316 | 0, 317 | 0, 318 | $filter 319 | ); 320 | 321 | if ($result > 0) { 322 | foreach ($measuringUnits->records as $lines) 323 | { 324 | $obj = new stdClass(); 325 | 326 | $obj->id = $lines->id; 327 | $obj->short_label = $lines->short_label; 328 | $obj->scale = $lines->scale; 329 | 330 | if ($measuring_style == 'time') $obj->label = $langs->transnoentitiesnoconv(ucfirst($lines->label)); 331 | else $obj->label = $langs->transnoentitiesnoconv($lines->label); 332 | 333 | $TArray[] = $obj; 334 | } 335 | } 336 | 337 | return $TArray; 338 | } 339 | 340 | -------------------------------------------------------------------------------- /script/interface.php.orig: -------------------------------------------------------------------------------- 1 | fetch($fk_product); 73 | return $formproduct->selectWarehouses($prod->fk_default_warehouse,'TLine[-1][entrepot]','',1,0,$prod->id,'',0,1); 74 | } 75 | 76 | function _serial_number(&$PDOdb, $sn) { 77 | 78 | $sql = "SELECT DISTINCT(rowid) as id, serial_number 79 | FROM ".MAIN_DB_PREFIX.ATM_ASSET_NAME." 80 | WHERE serial_number LIKE '".$sn."%'"; 81 | $PDOdb->Execute($sql); 82 | $Tab=array(); 83 | 84 | while($obj=$PDOdb->Get_line()) { 85 | /* 86 | $Tab[]=array( 87 | 'value'=>$obj->id 88 | ,'label'=>$obj->serial_number 89 | ); 90 | */ 91 | 92 | $Tab[]=$obj->serial_number; 93 | } 94 | 95 | return $Tab; 96 | } 97 | 98 | function _autocomplete_asset(&$PDOdb, $lot_number, $productid, $expeditionID, $expeditionDetID) { 99 | global $db, $conf, $langs; 100 | $langs->load('other'); 101 | 102 | dol_include_once('/core/lib/product.lib.php'); 103 | dol_include_once('/societe/class/societe.class.php'); 104 | dol_include_once('/expedition/class/expedition.class.php'); 105 | 106 | $sql = "SELECT fk_entrepot FROM ".MAIN_DB_PREFIX."expeditiondet WHERE rowid = ".$expeditionDetID." LIMIT 1"; 107 | 108 | $societe = new Societe($db); 109 | $societe->fetch('', $conf->global->MAIN_INFO_SOCIETE_NOM); 110 | 111 | $TWarehouses = $PDOdb->ExecuteAsArray($sql); 112 | $warehouseID = $TWarehouses[0]->fk_entrepot; 113 | 114 | $sql = "SELECT DISTINCT a.rowid 115 | FROM ".MAIN_DB_PREFIX.ATM_ASSET_NAME." a 116 | LEFT JOIN ".MAIN_DB_PREFIX."expeditiondet_asset eda ON (eda.fk_asset = a.rowid) 117 | LEFT JOIN ".MAIN_DB_PREFIX."expeditiondet ed ON (ed.rowid = eda.fk_expeditiondet) 118 | LEFT JOIN ".MAIN_DB_PREFIX."expedition e ON (e.rowid = ed.fk_expedition) 119 | WHERE a.fk_product = ".$productid; 120 | 121 | // On ne prend pas en compte le numéro de lot dans la requête pour les équipements sans numéro de lot 122 | if ($lot_number == -3) $sql .= " AND (a.lot_number IS NULL OR a.lot_number = '')"; 123 | else $sql .= " AND a.lot_number = '".$lot_number."'"; 124 | 125 | <<<<<<< HEAD 126 | if(empty($conf->global->DISPATCH_ALLOW_DISPATCHING_IGNORING_LOCALISATION)) { 127 | if(! empty($societe->id)) { 128 | // Par défaut, dispatch associe un équipement réceptionné par commande fournisseur à une société qui porte le même nom que $mysoc 129 | $sql .= " 130 | AND (COALESCE(a.fk_societe_localisation, 0) IN (0, ".$societe->id."))"; 131 | } 132 | else { 133 | $sql .= " 134 | AND COALESCE(a.fk_societe_localisation, 0) = 0"; 135 | } 136 | } 137 | ======= 138 | // note dans le cas des asset avec gestion de stock quantitatif la notion de localisation n'a généralement pas de sens 139 | // c'est pourquoi il faut désactiver le filtre de localisation sur les gestions quantitative 140 | if(! empty($societe->id)) 141 | { 142 | // Par défaut, dispatch associe un équipement réceptionné par commande fournisseur à une société qui porte le même nom que $mysoc 143 | $sql.= " 144 | AND ( COALESCE(a.fk_societe_localisation, 0) IN (0, ".$societe->id.") OR a.gestion_stock = 'QUANTITY' )"; 145 | } else { 146 | $sql.= " 147 | AND ( COALESCE(a.fk_societe_localisation, 0) = 0 OR a.gestion_stock = 'QUANTITY' )"; 148 | } 149 | >>>>>>> 670a84056acb3657683865bb043ca1dfabcc80da 150 | 151 | if(! empty($warehouseID)) { 152 | $sql.= " 153 | AND a.fk_entrepot = ".$warehouseID; 154 | } 155 | 156 | $sql.= " 157 | GROUP BY a.rowid 158 | HAVING 1=1"; 159 | if(empty($conf->global->DISPATCH_ALLOW_SENDING_SAME_PRODUCT_IN_SAME_EXP)) $sql .= " AND NOT(GROUP_CONCAT(e.rowid) IS NOT NULL AND GROUP_CONCAT(e.rowid, ',') REGEXP '(^|\,)" . $expeditionID . "(\,|$)')"; 160 | //Si l'équipement est attribué à une autre expédition qui a le statut brouillon ou validé, on ne le propose pas 161 | $exp = new Expedition($db); 162 | if(!empty($expeditionID)) { 163 | $exp->fetch($expeditionID); 164 | if($exp->statut == Expedition::STATUS_DRAFT || $exp->statut == Expedition::STATUS_VALIDATED ) { 165 | $sql.= " AND SUM(a.contenancereel_value) > (SELECT COALESCE(SUM(eda2.weight),0) FROM ".MAIN_DB_PREFIX."expeditiondet_asset as eda2 LEFT JOIN ".MAIN_DB_PREFIX."expeditiondet as ed2 ON (ed2.rowid = eda2.fk_expeditiondet) LEFT JOIN ".MAIN_DB_PREFIX."expedition as e2 ON (e2.rowid = ed2.fk_expedition) WHERE e2.fk_statut < 2 AND eda2.fk_asset = a.rowid)"; 166 | } 167 | } 168 | 169 | 170 | $PDOdb->Execute($sql); 171 | $TAssetIds = $PDOdb->Get_All(); 172 | $totalAssets = count($TAssetIds); 173 | 174 | $Tres = array(); 175 | foreach ($TAssetIds as $res) 176 | { 177 | $asset = new TAsset; 178 | $asset->load($PDOdb, $res->rowid); 179 | $asset->load_asset_type($PDOdb); 180 | 181 | if($asset->contenancereel_value > 0) 182 | { 183 | $Tres[$asset->serial_number]['serial_number'] = $asset->serial_number; 184 | $Tres[$asset->serial_number]['qty'] = $asset->contenancereel_value; 185 | $Tres[$asset->serial_number]['unite_string'] = ($asset->assetType->measuring_units == 'unit') ? 'unité(s)' : measuring_units_string($asset->contenancereel_units, $asset->assetType->measuring_units); 186 | $Tres[$asset->serial_number]['unite'] = ($asset->assetType->measuring_units == 'unit') ? 'unité(s)' : $asset->contenancereel_units; 187 | $Tres[$asset->serial_number]['measuring_units'] = $asset->assetType->measuring_units; 188 | $Tres['DispatchTotalAssetsNumberInOF'] = $totalAssets; 189 | } 190 | } 191 | return $Tres; 192 | } 193 | 194 | function _autocomplete_lot_number(&$PDOdb, $productid) { 195 | global $db, $conf, $langs; 196 | $langs->load('other'); 197 | dol_include_once('/core/lib/product.lib.php'); 198 | 199 | $sql = "SELECT DISTINCT(lot_number),rowid, SUM(contenancereel_value) as qty, contenancereel_units as unit 200 | FROM ".MAIN_DB_PREFIX.ATM_ASSET_NAME." 201 | WHERE fk_product = ".$productid." GROUP BY lot_number,contenancereel_units,rowid HAVING SUM(contenancereel_value) != 0"; 202 | $PDOdb->Execute($sql); 203 | 204 | $TLotNumber = array('no_lot_number' => array('lot_number' => -3, 'label' => $langs->transnoentitiesnoconv('AssetsWithoutLotNumber'))); 205 | $PDOdb->Execute($sql); 206 | $Tres = $PDOdb->Get_All(); 207 | foreach($Tres as $res){ 208 | 209 | $asset = new TAsset; 210 | $asset->load($PDOdb, $res->rowid); 211 | $asset->load_asset_type($PDOdb); 212 | //pre($asset,true);exit; 213 | $TLotNumber[$res->lot_number]['lot_number'] = $res->lot_number; 214 | $TLotNumber[$res->lot_number]['label'] = $res->lot_number." / ".$res->qty." ".(($asset->assetType->measuring_units == 'unit') ? 'unité(s)' : measuring_units_string($res->unit,$asset->assetType->measuring_units)); 215 | } 216 | return $TLotNumber; 217 | } 218 | 219 | 220 | /** 221 | * Mark a shipment asset detail line as prepared 222 | * 223 | * @param TPDOdb $PDOdb Database connection 224 | * @param int $fk_expditiondet_asset ID of expeditiondet_asset line 225 | * @param int $is_prepared 0/1, whether the asset has been prepared or not 226 | * 227 | * @return array Response array with success and message fields, to be JSON-encoded 228 | */ 229 | function _set_line_is_prepared(TPDOdb &$PDOdb, $fk_expeditiondet_asset, $is_prepared) 230 | { 231 | global $langs; 232 | 233 | dol_include_once('/dispatch/class/dispatchdetail.class.php'); 234 | 235 | $langs->load('dispatch@dispatch'); 236 | 237 | $dispatchDetail = new TDispatchDetail; 238 | $dispatchLoaded = $dispatchDetail->load($PDOdb, $fk_expeditiondet_asset); 239 | 240 | if(empty($dispatchLoaded)) 241 | { 242 | return array('success' => false, 'message' => $langs->trans('CouldNotLoadAssetDetail')); 243 | } 244 | 245 | $dispatchDetail->is_prepared = $is_prepared; 246 | 247 | $dispatchID = $dispatchDetail->save($PDOdb); 248 | 249 | if(empty($dispatchID)) 250 | { 251 | return array('success' => false, 'message' => $langs->trans('CouldNotSaveAssetDetail')); 252 | } 253 | 254 | $message = $langs->trans(empty($is_prepared) ? 'AssetMarkedAsNotPrepared' : 'AssetMarkedAsPrepared'); 255 | 256 | return array('success' => true, 'message' => $message); 257 | } 258 | 259 | 260 | /** 261 | * Mark all shipment asset detail lines as prepared or not 262 | * 263 | * @param TPDOdb $PDOdb Database connection 264 | * @param int $fk_expedition ID of expedition 265 | * @param int $is_prepared 0/1, whether the asset has been prepared or not 266 | * 267 | * @return array Response array with success and message fields, to be JSON-encoded 268 | */ 269 | function _set_all_lines_is_prepared(TPDOdb &$PDOdb, $fk_expedition, $is_prepared) 270 | { 271 | global $langs; 272 | 273 | dol_include_once('/dispatch/class/dispatchdetail.class.php'); 274 | 275 | $langs->load('dispatch@dispatch'); 276 | 277 | $sql = 'SELECT eda.rowid 278 | FROM ' . MAIN_DB_PREFIX . 'expeditiondet_asset eda 279 | INNER JOIN ' . MAIN_DB_PREFIX .'expeditiondet ed ON (ed.rowid = eda.fk_expeditiondet) 280 | WHERE ed.fk_expedition = ' . $fk_expedition; 281 | 282 | $TDispatchDetail = $PDOdb->ExecuteAsArray($sql); 283 | 284 | $countFail = 0; 285 | 286 | foreach($TDispatchDetail as $dispatchDetailStatic) 287 | { 288 | $TResult = _set_line_is_prepared($PDOdb, $dispatchDetailStatic->rowid, $is_prepared); 289 | 290 | if(empty($TResult['success'])) 291 | { 292 | $countFail++; 293 | } 294 | } 295 | 296 | $message = $langs->trans(empty($is_prepared) ? 'AssetsMarkedAsNotPrepared' : 'AssetsMarkedAsPrepared'); 297 | 298 | if($countFail > 0) 299 | { 300 | $message = $langs->trans('NAssetsMarkedCouldNotBeMarked', $countFail); 301 | } 302 | 303 | return array('success' => $countFail == 0, 'message' => $message); 304 | } 305 | 306 | function _measuringUnits($measuring_style) 307 | { 308 | global $langs, $db; 309 | 310 | $langs->load("other"); 311 | $TArray = array(); 312 | 313 | 314 | require_once DOL_DOCUMENT_ROOT.'/core/class/cunits.class.php'; 315 | $measuringUnits = new CUnits($db); 316 | 317 | $filter = array(); 318 | $filter['t.active'] = 1; 319 | if ($measuring_style) $filter['t.unit_type'] = $measuring_style; 320 | 321 | $result = $measuringUnits->fetchAll( 322 | '', 323 | '', 324 | 0, 325 | 0, 326 | $filter 327 | ); 328 | 329 | if ($result > 0) { 330 | foreach ($measuringUnits->records as $lines) 331 | { 332 | $obj = new stdClass(); 333 | 334 | $obj->id = $lines->id; 335 | $obj->short_label = $lines->short_label; 336 | $obj->scale = $lines->scale; 337 | 338 | if ($measuring_style == 'time') $obj->label = $langs->transnoentitiesnoconv(ucfirst($lines->label)); 339 | else $obj->label = $langs->transnoentitiesnoconv($lines->label); 340 | 341 | $TArray[] = $obj; 342 | } 343 | } 344 | 345 | return $TArray; 346 | } 347 | 348 | -------------------------------------------------------------------------------- /detail_head.php: -------------------------------------------------------------------------------- 1 | product->enabled) || ! empty($conf->service->enabled)) require_once DOL_DOCUMENT_ROOT.'/product/class/product.class.php'; 17 | if (! empty($conf->propal->enabled)) require_once DOL_DOCUMENT_ROOT.'/comm/propal/class/propal.class.php'; 18 | if (! empty($conf->commande->enabled)) require_once DOL_DOCUMENT_ROOT.'/commande/class/commande.class.php'; 19 | if (! empty($conf->stock->enabled)) require_once DOL_DOCUMENT_ROOT.'/product/stock/class/entrepot.class.php'; 20 | 21 | $langs->load("sendings"); 22 | $langs->load("companies"); 23 | $langs->load("bills"); 24 | $langs->load('deliveries'); 25 | $langs->load('orders'); 26 | $langs->load('stocks'); 27 | $langs->load('other'); 28 | $langs->load('propal'); 29 | 30 | $newToken = function_exists('newToken') ? newToken() : $_SESSION['newtoken']; 31 | 32 | $origin = GETPOST('origin','alpha')?GETPOST('origin','alpha'):'expedition'; // Example: commande, propal 33 | $origin_id = GETPOST('id','int')?GETPOST('id','int'):''; 34 | if (empty($origin_id)) $origin_id = GETPOST('origin_id','int'); // Id of order or propal 35 | if (empty($origin_id)) $origin_id = GETPOST('object_id','int'); // Id of order or propal 36 | $id = $origin_id; 37 | $ref=GETPOST('ref','alpha'); 38 | 39 | // Security check 40 | $socid=''; 41 | if ($user->societe_id) $socid=$user->societe_id; 42 | $result=restrictedArea($user, $origin, $origin_id); 43 | 44 | $action = GETPOST('action','alpha'); 45 | 46 | $object = new Expedition($db); 47 | (GETPOST('id'))? $object->fetch(GETPOST('id')): "" ; 48 | 49 | llxHeader('',$langs->trans('Sending'),'Expedition'); 50 | 51 | $form = new Form($db); 52 | $formfile = new FormFile($db); 53 | $formproduct = new FormProduct($db); 54 | $product_static = new Product($db); 55 | 56 | if ($action == 'setdate_livraison' && $user->rights->expedition->creer) 57 | { 58 | //print "x ".$_POST['liv_month'].", ".$_POST['liv_day'].", ".$_POST['liv_year']; 59 | $datedelivery=dol_mktime(GETPOST('liv_hour','int'), GETPOST('liv_min','int'), 0, GETPOST('liv_month','int'), GETPOST('liv_day','int'), GETPOST('liv_year','int')); 60 | 61 | $object->fetch($id); 62 | 63 | if (!is_callable(array($object, 'setDeliveryDate'))) { 64 | // For Dolibarr < 14 retrocompatibility 65 | $result = $object->set_date_livraison($user, $datedelivery); 66 | } else { 67 | $result = $object->setDeliveryDate($user, $datedelivery); 68 | } 69 | if ($result < 0) 70 | { 71 | $mesg='
'.$object->error.'
'; 72 | } 73 | } 74 | 75 | // Action update description of emailing 76 | else if ($action == 'settrackingnumber' || $action == 'settrackingurl' 77 | || $action == 'settrueWeight' 78 | || $action == 'settrueWidth' 79 | || $action == 'settrueHeight' 80 | || $action == 'settrueDepth' 81 | || $action == 'setshipping_method_id') 82 | { 83 | $error=0; 84 | 85 | $shipping = new Expedition($db); 86 | $result=$shipping->fetch($id); 87 | if ($result < 0) dol_print_error($db,$shipping->error); 88 | 89 | if ($action == 'settrackingnumber') $shipping->tracking_number = trim(GETPOST('trackingnumber','alpha')); 90 | if ($action == 'settrackingurl') $shipping->tracking_url = trim(GETPOST('trackingurl','int')); 91 | if ($action == 'settrueWeight') $shipping->trueWeight = trim(GETPOST('trueWeight','int')); 92 | if ($action == 'settrueWidth') $shipping->trueWidth = trim(GETPOST('trueWidth','int')); 93 | if ($action == 'settrueHeight') $shipping->trueHeight = trim(GETPOST('trueHeight','int')); 94 | if ($action == 'settrueDepth') $shipping->trueDepth = trim(GETPOST('trueDepth','int')); 95 | if ($action == 'setshipping_method_id') $shipping->shipping_method_id = trim(GETPOST('shipping_method_id','int')); 96 | 97 | if (! $error) 98 | { 99 | if ($shipping->update($user) >= 0) 100 | { 101 | ?> 102 | 105 | error,'errors'); 109 | } 110 | 111 | $action=""; 112 | } 113 | 114 | if (! empty($id) || ! empty($ref)) 115 | { 116 | $result = $object->fetch($id,$ref); 117 | if ($result < 0) 118 | { 119 | dol_print_error($db,$object->error); 120 | exit -1; 121 | } 122 | $lines = $object->lines; 123 | $num_prod = count($lines); 124 | 125 | if ($object->id > 0) 126 | { 127 | dol_htmloutput_mesg($mesg); 128 | 129 | if (!empty($object->origin)) 130 | { 131 | $typeobject = $object->origin; 132 | $origin = $object->origin; 133 | $object->fetch_origin(); 134 | } 135 | 136 | $soc = new Societe($db); 137 | $soc->fetch($object->socid); 138 | 139 | $head=shipping_prepare_head($object); 140 | dol_fiche_head($head, 'delivery', $langs->trans("Sending"), 0, 'sending'); 141 | 142 | dol_htmloutput_mesg($mesg); 143 | 144 | // Calculate true totalWeight and totalVolume for all products 145 | // by adding weight and volume of each product line. 146 | $totalWeight = ''; 147 | $totalVolume = ''; 148 | $weightUnit=0; 149 | $volumeUnit=0; 150 | for ($i = 0 ; $i < $num_prod ; $i++) 151 | { 152 | $weightUnit=0; 153 | $volumeUnit=0; 154 | if (! empty($lines[$i]->weight_units)) $weightUnit = $lines[$i]->weight_units; 155 | if (! empty($lines[$i]->volume_units)) $volumeUnit = $lines[$i]->volume_units; 156 | 157 | // TODO Use a function addvalueunits(val1,unit1,val2,unit2)=>(val,unit) 158 | if ($lines[$i]->weight_units < 50) 159 | { 160 | $trueWeightUnit=pow(10,$weightUnit); 161 | $totalWeight += $lines[$i]->weight*$lines[$i]->qty_shipped*$trueWeightUnit; 162 | } 163 | else 164 | { 165 | $trueWeightUnit=$weightUnit; 166 | $totalWeight += $lines[$i]->weight*$lines[$i]->qty_shipped; 167 | } 168 | if ($lines[$i]->volume_units < 50) 169 | { 170 | //print $lines[$i]->volume."x".$lines[$i]->volume_units."x".($lines[$i]->volume_units < 50)."x".$volumeUnit; 171 | $trueVolumeUnit=pow(10,$volumeUnit); 172 | //print $lines[$i]->volume; 173 | $totalVolume += $lines[$i]->volume*$lines[$i]->qty_shipped*$trueVolumeUnit; 174 | } 175 | else 176 | { 177 | $trueVolumeUnit=$volumeUnit; 178 | $totalVolume += $lines[$i]->volume*$lines[$i]->qty_shipped; 179 | } 180 | } 181 | 182 | print '
'.$langs->trans('Product') .''.$langs->trans('DispatchSerialNumber').''.$langs->trans('DispatchBatchNumber').''.$langs->trans('Warehouse').'DLUO'.$langs->trans('Quantity').'' . $langs->trans('Unit') . 'IMEIFirmware 
". 166 | $prod->getNomUrl(1). 167 | $form->hidden('TLine['.$key.'][fk_product]', $prod->id). 168 | $form->hidden('TLine['.$key.'][ref]', $prod->ref)." - ". 169 | $prod->label. 170 | $form->hidden('TLine['.$key.'][fk_asset]', $fk_asset). 171 | "'; 173 | if (is_object($line)) { 174 | $output .= $form->hidden('TLine['.$key.'][subprice]', $line->subprice); 175 | $output .= $form->hidden('TLine['.$key.'][supplier_price]', $line->supplier_price); 176 | $output .= $form->hidden('TLine['.$key.'][supplier_qty]', $line->supplier_qty); 177 | $output .= $form->hidden('TLine['.$key.'][generate_supplier_tarif]', $line->generate_supplier_tarif); 178 | 179 | } 180 | 181 | if (is_array($line)) { 182 | $output .= $form->texte('', 'TLine[' . $key . '][numserie]', $line['obj']->serial_number, 30); 183 | 184 | $output .= $form->hidden('TLine['.$key.'][numlog]', $line['obj']->numlog); 185 | $output .= $form->hidden('TLine['.$key.'][codebarre]', $line['obj']->codebarre); 186 | $output .= $form->hidden('TLine['.$key.'][vpn]', $line['obj']->vpn); 187 | $output .= $form->hidden('TLine['.$key.'][notes]', $line['obj']->notes); 188 | } 189 | $output .= ''; 193 | require_once DOL_DOCUMENT_ROOT.'/product/class/html.formproduct.class.php'; 194 | 195 | $formproduct=new FormProduct($db); 196 | $backupEntity = $conf->entity; 197 | 198 | $conf->entity = $entity; 199 | $formproduct->loadWarehouses(); 200 | 201 | if (count($formproduct->cache_warehouses) > 1) { 202 | 203 | $output .=$formproduct->selectWarehouses($idWarehouse, 'TLine['.$key.'][entrepot]','',1,0,$prod->id,'',1); 204 | } elseif (count($formproduct->cache_warehouses)==1) { 205 | $output .=$formproduct->selectWarehouses($idWarehouse, 'TLine['.$key.'][entrepot]','',0,0,$prod->id,'',0,1); 206 | } else { 207 | $output .= $langs->trans("NoWarehouseDefined"); 208 | } 209 | 210 | $output .='" . $form->hidden('TLine['.$key.'][quantity]', 1) . "1'. $form->hidden('TLine['.$key.'][quantity]', $line->qty_shipped). $line->qty_shipped.'".$form->texte('','TLine['.$key.'][lot_number]', $line->lot_number, 30)."'.$form->calendrier('','TLine['.$k.'][dluo]', date('d/m/Y',strtotime($line['dluo']))).''. ($commande->statut < 5) ? $formproduct->select_measuring_units('TLine['.$k.'][quantity_unit]','weight',$line['quantity_unit']) : measuring_units_string($line['quantity_unit'],'weight').'" . $form->hidden('TLine['.$key.'][quantity]', 1) . "1'. $form->hidden('TLine['.$key.'][quantity]', $line->qty_shipped). $line->qty_shipped.''.$form->texte('','TLine['.$key.'][imei]', $line->imei, 30).''.$form->texte('','TLine['.$key.'][firmware]', $line->firmware, 30).''; 252 | $output .='
'.$langs->trans("Annuler").'
'; 265 | $output .= $langs->trans("DispatchDateReception").' : '.$form->calendrier('', 'date_recep', time()); 266 | 267 | $output .= $langs->trans("Comment").' : '.$form->texte('', 'comment', !empty($comment)?$comment:'', 60,128); 268 | 269 | $output .= $form->btsubmit($langs->trans('AssetVentil'), 'bt_create', '', 'butAction butValidateVentilation'); 270 | $output .= $form->hidden('data-shipment-treated-id', $currentExp->id); 271 | 272 | // On remonte l'entité liée à la société 273 | $soc = new Societe($db); 274 | //var_dump($currentExp->id); 275 | $res = $soc->fetch($currentExp->socid); 276 | if ($res){ 277 | $output .= $form->hidden('data-shipment-entity', $soc->entity); 278 | } 279 | $output .= '
'; 183 | 184 | $linkback = ''.$langs->trans("BackToList").''; 185 | 186 | // Ref 187 | print ''; 188 | print ''; 191 | 192 | // Customer 193 | print ''; 194 | print ''; 195 | print ""; 196 | 197 | // Linked documents 198 | if ($typeobject == 'commande' && $object->$typeobject->id && ! empty($conf->commande->enabled)) 199 | { 200 | print ''; 204 | print '\n"; 207 | print ''; 208 | } 209 | if ($typeobject == 'propal' && $object->$typeobject->id && ! empty($conf->propal->enabled)) 210 | { 211 | print ''; 215 | print '\n"; 218 | print ''; 219 | } 220 | 221 | // Ref customer 222 | print ''; 223 | print '\n"; 224 | print ''; 225 | 226 | // Date creation 227 | print ''; 228 | print '\n"; 229 | print ''; 230 | 231 | // Delivery date planed 232 | print ''; 241 | print ''; 242 | 243 | // Weight 244 | print ''; 248 | 249 | // Width 250 | print ''; 254 | 255 | // Height 256 | print ''; 260 | 261 | // Depth 262 | print ''; 266 | 267 | // Volume 268 | print ''; 271 | print '\n"; 288 | print ''; 289 | 290 | // Status 291 | print ''; 292 | print '\n"; 293 | print ''; 294 | 295 | // Sending method 296 | print ''; 325 | print ''; 326 | 327 | // Tracking Number 328 | print ''; 331 | 332 | // Other attributes 333 | $parameters=array('colspan' => ' colspan="3"'); 334 | $reshook=$hookmanager->executeHooks('formObjectOptions',$parameters,$object,$action); // Note that $action and $object may have been modified by hook 335 | 336 | print "
'.$langs->trans("Ref").''; 189 | print $form->showrefnav($object, 'ref', $linkback, 1, 'ref', 'ref'); 190 | print '
'.$langs->trans("Customer").''.$soc->getNomUrl(1).'
'; 201 | $objectsrc=new Commande($db); 202 | $objectsrc->fetch($object->$typeobject->id); 203 | print $langs->trans("RefOrder").''; 205 | print $objectsrc->getNomUrl(1,'commande'); 206 | print "
'; 212 | $objectsrc=new Propal($db); 213 | $objectsrc->fetch($object->$typeobject->id); 214 | print $langs->trans("RefProposal").''; 216 | print $objectsrc->getNomUrl(1,'expedition'); 217 | print "
'.$langs->trans("RefCustomer").''.$object->ref_customer."
'.$langs->trans("DateCreation").''.dol_print_date($object->date_creation,"day")."
'; 233 | print ''; 236 | 237 | print '
'; 234 | print $langs->trans('DateDeliveryPlanned'); 235 | print '
'; 238 | print '
'; 239 | print $object->date_delivery ? dol_print_date($object->date_delivery,'dayhourtext') : ' '; 240 | print '
'.$form->editfieldkey("Weight",'trueWeight',$object->trueWeight,$object,$user->rights->expedition->creer).''; 245 | print $form->editfieldval("Weight",'trueWeight',$object->trueWeight,$object,$user->rights->expedition->creer); 246 | print ($object->trueWeight && $object->weight_units!='')?' '.measuring_units_string($object->weight_units,"weight"):''; 247 | print '
'.$form->editfieldkey("Width",'trueWidth',$object->trueWidth,$object,$user->rights->expedition->creer).''; 251 | print $form->editfieldval("Width",'trueWidth',$object->trueWidth,$object,$user->rights->expedition->creer); 252 | print ($object->trueWidth && $object->width_units!='')?' '.measuring_units_string($object->width_units,"size"):''; 253 | print '
'.$form->editfieldkey("Height",'trueHeight',$object->trueHeight,$object,$user->rights->expedition->creer).''; 257 | print $form->editfieldval("Height",'trueHeight',$object->trueHeight,$object,$user->rights->expedition->creer); 258 | print ($object->trueHeight && $object->height_units!='')?' '.measuring_units_string($object->height_units,"size"):''; 259 | print '
'.$form->editfieldkey("Depth",'trueDepth',$object->trueDepth,$object,$user->rights->expedition->creer).''; 263 | print $form->editfieldval("Depth",'trueDepth',$object->trueDepth,$object,$user->rights->expedition->creer); 264 | print ($object->trueDepth && $object->depth_units!='')?' '.measuring_units_string($object->depth_units,"size"):''; 265 | print '
'; 269 | print $langs->trans("Volume"); 270 | print ''; 272 | $calculatedVolume=0; 273 | if ($object->trueWidth && $object->trueHeight && $object->trueDepth) $calculatedVolume=($object->trueWidth * $object->trueHeight * $object->trueDepth); 274 | // If sending volume not defined we use sum of products 275 | if ($calculatedVolume > 0) 276 | { 277 | print $calculatedVolume.' '; 278 | if ($volumeUnit < 50) print measuring_units_string(0,"volume"); 279 | else print measuring_units_string($volumeUnit,"volume"); 280 | } 281 | if ($totalVolume > 0) 282 | { 283 | if ($calculatedVolume) print ' ('.$langs->trans("SumOfProductVolumes").': '; 284 | print $totalVolume; 285 | if ($calculatedVolume) print ')'; 286 | } 287 | print "
'.$langs->trans("Status").''.$object->getLibStatut(4)."
'; 297 | print ''; 300 | 301 | if ($action != 'editshipping_method_id') print ''; 302 | print '
'; 298 | print $langs->trans('SendingMethod'); 299 | print 'id.'">'.img_edit($langs->trans('SetSendingMethod'),1).'
'; 303 | print '
'; 304 | if ($action == 'editshipping_method_id') 305 | { 306 | print '
'; 307 | print ''; 308 | print ''; 309 | $object->fetch_delivery_methods(); 310 | print $form->selectarray("shipping_method_id",$object->meths,$object->shipping_method_id,1,0,0,"",1); 311 | if ($user->admin) print info_admin($langs->trans("YouCanChangeValuesForThisListFromDictionnarySetup"),1); 312 | print ''; 313 | print '
'; 314 | } 315 | else 316 | { 317 | if ($object->shipping_method_id > 0) 318 | { 319 | // Get code using getLabelFromKey 320 | $code=$langs->getLabelFromKey($db,$object->shipping_method_id,'c_shipment_mode','rowid','code'); 321 | print $langs->trans("SendingMethod".strtoupper($code)); 322 | } 323 | } 324 | print '
'.$form->editfieldkey("TrackingNumber",'trackingnumber',$object->tracking_number,$object,$user->rights->expedition->creer).''; 329 | print $form->editfieldval("TrackingNumber",'trackingnumber',$object->tracking_url,$object,$user->rights->expedition->creer,'string',$object->tracking_number); 330 | print '
\n"; 337 | 338 | 339 | } 340 | } 341 | 342 | print "\n"; 343 | 344 | print "\n\n"; 345 | -------------------------------------------------------------------------------- /core/triggers/interface_99_modDispatch_DispatchWorkflow.class.php: -------------------------------------------------------------------------------- 1 | 3 | * Copyright (C) 2005-2011 Regis Houssin 4 | * 5 | * This program is free software; you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation; either version 2 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | /** 20 | * \file htdocs/core/triggers/interface_90_all_Demo.class.php 21 | * \ingroup core 22 | * \brief Fichier de demo de personalisation des actions du workflow 23 | * \remarks Son propre fichier d'actions peut etre cree par recopie de celui-ci: 24 | * - Le nom du fichier doit etre: interface_99_modMymodule_Mytrigger.class.php 25 | * ou: interface_99_all_Mytrigger.class.php 26 | * - Le fichier doit rester stocke dans core/triggers 27 | * - Le nom de la classe doit etre InterfaceMytrigger 28 | * - Le nom de la methode constructeur doit etre InterfaceMytrigger 29 | * - Le nom de la propriete name doit etre Mytrigger 30 | */ 31 | 32 | 33 | /** 34 | * Class of triggers for Mantis module 35 | */ 36 | 37 | class InterfaceDispatchWorkflow 38 | { 39 | var $db; 40 | 41 | /** 42 | * Constructor 43 | * 44 | * @param DoliDB $db Database handler 45 | */ 46 | function __construct($db) 47 | { 48 | $this->db = $db; 49 | 50 | global $langs; 51 | 52 | $this->name = preg_replace('/^Interface/i','',get_class($this)); 53 | $this->family = "ATM"; 54 | $this->description = $langs->trans( 'DispatchInterfaceDesc' ); // Trigger of the specific Latoxan shipping module // 55 | $this->version = 'dolibarr'; // 'development', 'experimental', 'dolibarr' or version 56 | $this->picto = 'technic'; 57 | } 58 | 59 | 60 | /** 61 | * Return name of trigger file 62 | * 63 | * @return string Name of trigger file 64 | */ 65 | function getName() 66 | { 67 | return $this->name; 68 | } 69 | 70 | /** 71 | * Return description of trigger file 72 | * 73 | * @return string Description of trigger file 74 | */ 75 | function getDesc() 76 | { 77 | return $this->description; 78 | } 79 | 80 | /** 81 | * Return version of trigger file 82 | * 83 | * @return string Version of trigger file 84 | */ 85 | function getVersion() 86 | { 87 | global $langs; 88 | $langs->load("admin"); 89 | 90 | if ($this->version == 'development') return $langs->trans("Development"); 91 | elseif ($this->version == 'experimental') return $langs->trans("Experimental"); 92 | elseif ($this->version == 'dolibarr') return DOL_VERSION; 93 | elseif ($this->version) return $this->version; 94 | else return $langs->trans("Unknown"); 95 | } 96 | 97 | 98 | /** 99 | * Function called when a Dolibarrr business event is done. 100 | * All functions "run_trigger" are triggered if file is inside directory htdocs/core/triggers 101 | * 102 | * @param string $action Event action code 103 | * @param Object $object Object 104 | * @param User $user Object user 105 | * @param Translate $langs Object langs 106 | * @param conf $conf Object conf 107 | * @return int <0 if KO, 0 if no triggered ran, >0 if OK 108 | */ 109 | function run_trigger($action,$object,$user,$langs,$conf) 110 | { 111 | global $conf,$db, $langs; 112 | 113 | if(!defined('INC_FROM_DOLIBARR')) define('INC_FROM_DOLIBARR',true); 114 | 115 | $update = '_MODIFY'; 116 | if (intval(DOL_VERSION) < 16) $update = '_UPDATE'; 117 | 118 | if ($action == 'SHIPPING_VALIDATE') { 119 | if (!empty($conf->global->STOCK_CALCULATE_ON_SHIPMENT)) { 120 | $this->move_assets_according_to_shipment($object); 121 | } 122 | dol_syslog("Trigger '".$this->name."' for action '$action' launched by ".__FILE__.". id=".$object->id); 123 | return 1; 124 | } 125 | 126 | if($action == 'SHIPPING_DELETE') 127 | { 128 | dol_include_once('/dispatch/config.php'); 129 | dol_include_once('/dispatch/class/dispatchdetail.class.php'); 130 | 131 | $PDOdb = new TPDOdb; 132 | 133 | foreach($object->lines as &$line) { 134 | $dispatchDetail = new TDispatchDetail; 135 | $TDetail = $dispatchDetail->LoadAllBy($PDOdb, array('fk_expeditiondet' => $line->id)); 136 | 137 | foreach($TDetail as &$detail) { 138 | if(!empty($conf->global->DISPATCH_RESET_ASSET_QTY_DELETE_SHIPMENT) 139 | && (($conf->global->STOCK_CALCULATE_ON_SHIPMENT && $object->statut > 0) 140 | || ($conf->global->STOCK_CALCULATE_ON_SHIPMENT_CLOSE && $object->statut == 2))) { 141 | $asset = new TAsset; 142 | $asset->load($PDOdb, $detail->fk_asset); 143 | 144 | $asset->fk_entrepot = $line->entrepot_id; 145 | $asset->fk_societe_localisation = 0; 146 | 147 | // on ne fait pas le mouvement standard qui a été traité par dolibarr à la suppression d'expédition 148 | $asset->save($PDOdb, $user, $langs->trans("ShipmentDeletedInDolibarr", $object->ref), $detail->weight_reel, false, 0, true); 149 | 150 | $stock = new TAssetStock; 151 | $stock->mouvement_stock($PDOdb, $user, $asset->getId(), $detail->weight_reel, $langs->trans("ShipmentDeletedInDolibarr", $object->ref), $detail->fk_expeditiondet); 152 | } 153 | 154 | $detail->delete($PDOdb); 155 | } 156 | } 157 | 158 | 159 | } 160 | 161 | 162 | if($action == 'SHIPPING_CLOSED') 163 | { 164 | if (! empty($conf->global->DISPATCH_BLOCK_SHIPPING_CLOSING_IF_PRODUCTS_NOT_PREPARED)) 165 | { 166 | if(! defined('INC_FROM_DOLIBARR')) define('INC_FROM_DOLIBARR', true); 167 | dol_include_once('/dispatch/config.php'); 168 | dol_include_once('/dispatch/lib/dispatch.lib.php'); 169 | 170 | list($canBeClosed, $msg) = dispatch_shipment_can_be_closed($object); 171 | 172 | if(empty($canBeClosed)) 173 | { 174 | setEventMessage($langs->trans('ShipmentCannotBeClosed', $msg), 'errors'); 175 | return -1; 176 | } 177 | } 178 | 179 | if (!empty($conf->global->STOCK_CALCULATE_ON_SHIPMENT_CLOSE)) { 180 | $this->move_assets_according_to_shipment($object); 181 | } 182 | } 183 | 184 | if ($action == 'BONDERETOUR_VALIDATE') 185 | { 186 | if (!empty($conf->global->STOCK_CALCULATE_ON_BONDERETOUR_VALIDATE)) 187 | { 188 | $this->move_assets_according_to_BDR($object, $action); 189 | } 190 | } 191 | 192 | if ($action == 'BONDERETOUR_UNVALIDATE') 193 | { 194 | if (!empty($conf->global->STOCK_CALCULATE_ON_BONDERETOUR_VALIDATE)) 195 | { 196 | $this->move_assets_according_to_BDR($object, $action, true); 197 | } 198 | } 199 | 200 | if ($action == 'BONDERETOUR_CLOSED') 201 | { 202 | if (!empty($conf->global->STOCK_CALCULATE_ON_BONDERETOUR_CLOSE)) 203 | { 204 | $this->move_assets_according_to_BDR($object, $action); 205 | } 206 | } 207 | 208 | if ($action == 'BONDERETOUR_REOPEN') 209 | { 210 | if (!empty($conf->global->STOCK_CALCULATE_ON_BONDERETOUR_CLOSE)) 211 | { 212 | $this->move_assets_according_to_BDR($object, $action, true); 213 | } 214 | } 215 | 216 | if ($action == 'BONDERETOUR_DELETE') 217 | { 218 | if (($object->statut == 1 && !empty($conf->global->STOCK_CALCULATE_ON_BONDERETOUR_VALIDATE)) 219 | || ($object->statut == 2 && !empty($conf->global->STOCK_CALCULATE_ON_BONDERETOUR_CLOSE)) 220 | ) 221 | { 222 | $this->move_assets_according_to_BDR($object, $action, true); 223 | } 224 | 225 | dol_include_once('/dispatch/config.php'); 226 | dol_include_once('/dispatch/class/dispatchdetail.class.php'); 227 | 228 | $PDOdb = new TPDOdb(); 229 | 230 | if (!empty($object->lines)) 231 | { 232 | foreach ($object->lines as $line) 233 | { 234 | $d = new TRecepBDRDetail(); 235 | $d->loadLines($PDOdb, $line->id); 236 | 237 | if (!empty($d->lines)) 238 | { 239 | foreach ($d->lines as $detail) 240 | { 241 | $detail->delete($PDOdb); 242 | } 243 | } 244 | } 245 | } 246 | 247 | } 248 | 249 | if ($action == 'LINEBONDERETOUR'.$update) 250 | { 251 | if (!empty($object->oldcopy)) 252 | { 253 | if ($object->fk_entrepot != $object->oldcopy->fk_entrepot) 254 | { 255 | dol_include_once('/dispatch/config.php'); 256 | dol_include_once('/dispatch/class/dispatchdetail.class.php'); 257 | 258 | $PDOdb = new TPDOdb(); 259 | 260 | $d = new TRecepBDRDetail(); 261 | $d->loadLines($PDOdb, $object->id); 262 | 263 | if (!empty($d->lines)) 264 | { 265 | foreach ($d->lines as $detail) 266 | { 267 | $detail->fk_warehouse = $object->fk_entrepot; 268 | $detail->save($PDOdb); 269 | } 270 | } 271 | } 272 | } 273 | } 274 | 275 | 276 | return 0; 277 | } 278 | 279 | private function create_flacon_stock_mouvement(&$PDOdb, &$linedetail, $numref,$fk_soc = 0, $exp_id = 0) { 280 | global $user, $langs, $conf, $db; 281 | dol_include_once('/' . ATM_ASSET_NAME . '/class/asset.class.php'); 282 | dol_include_once('/product/class/product.class.php'); 283 | dol_include_once('/expedition/class/expedition.class.php'); 284 | 285 | $asset = new TAsset; 286 | $asset->load($PDOdb,$linedetail->fk_asset); 287 | 288 | if($conf->global->clilatoxan){ 289 | $poids_destocke = $this->calcule_poids_destocke($PDOdb,$linedetail); 290 | $poids_destocke = $poids_destocke * pow(10,$asset->contenancereel_units); 291 | } 292 | else{ 293 | $poids_destocke = $linedetail->weight_reel; 294 | } 295 | /*pre($linedetail,true); 296 | echo $poids_destocke;exit;*/ 297 | 298 | //$asset->contenancereel_value = $asset->contenancereel_value - $poids_destocke; 299 | $asset->fk_societe_localisation = $fk_soc; 300 | if (!empty($conf->global->DISPATCH_RESET_ASSET_WAREHOUSE_ON_SHIPMENT)) $asset->fk_entrepot = 0; 301 | 302 | 303 | // Destockage Dolibarr déjà fait par à la validation de l'expédition, et impossible de ne destocker que l'équipement : on save sans rien déstocker 304 | $asset->save($PDOdb, $user, $langs->trans("ShipmentValidatedInDolibarr",$numref), -$poids_destocke, false, 0, true); 305 | 306 | $fk_dol_moov = 0; 307 | if ($conf->global->DISPATCH_LINK_ASSET_TO_STOCK_MOOV) 308 | { 309 | $sql = "SELECT m.rowid FROM ".MAIN_DB_PREFIX."stock_mouvement as m"; 310 | $sql.= " WHERE m.fk_product = ".$asset->fk_product; 311 | $sql.= " AND m.type_mouvement = 2"; 312 | $sql.= " AND m.value < 0"; 313 | $sql.= " AND m.origintype = 'shipping'"; 314 | $sql.= " AND m.fk_origin = ".$exp_id; 315 | $sql.= " ORDER BY m.tms DESC LIMIT 1"; 316 | $res = $db->query($sql); // on utilise doliDB pour rester dans la même transaction et récupérer le bon ID de mvt dolibarr 317 | if ($res && $db->num_rows($res)) 318 | { 319 | $obj = $db->fetch_object($res); 320 | $fk_dol_moov = $obj->rowid; 321 | } 322 | } 323 | 324 | // Destockage équipement 325 | $stock = new TAssetStock; 326 | $stock->mouvement_stock($PDOdb, $user, $asset->getId(), -$poids_destocke, $langs->trans("ShipmentValidatedInDolibarr",$numref), $linedetail->fk_expeditiondet, $fk_dol_moov); 327 | 328 | return $poids_destocke; 329 | } 330 | 331 | /*private function create_standard_stock_mouvement(&$line, $qty, $numref) { 332 | global $user, $langs; 333 | require_once DOL_DOCUMENT_ROOT.'/product/stock/class/mouvementstock.class.php'; 334 | 335 | $mouvS = new MouvementStock($this->db); 336 | // We decrement stock of product (and sub-products) 337 | // We use warehouse selected for each line 338 | $result=$mouvS->livraison($user, $line->fk_product, $line->entrepot_id, $qty, $line->subprice, $langs->trans("ShipmentValidatedInDolibarr",$numref)); 339 | return $result; 340 | }*/ 341 | 342 | private function calcule_poids_destocke(&$PDOdb,&$linedetail){ 343 | 344 | $sql = "SELECT p.weight, p.weight_units 345 | FROM ".MAIN_DB_PREFIX."product as p 346 | LEFT JOIN ".MAIN_DB_PREFIX.ATM_ASSET_NAME." as a ON (a.fk_product = p.rowid) 347 | LEFT JOIN ".MAIN_DB_PREFIX."expeditiondet_asset as eda ON (eda.fk_asset = a.rowid) 348 | LEFT JOIN ".MAIN_DB_PREFIX."expeditiondet as ed ON (ed.rowid = eda.fk_expeditiondet) 349 | WHERE ed.rowid = ".$linedetail->fk_expeditiondet; 350 | 351 | $PDOdb->Execute($sql); 352 | $PDOdb->Get_line(); 353 | $weight = $PDOdb->Get_field('weight'); 354 | $poids = (!empty($weight)) ? $weight : 1 ; 355 | $weight_units = $PDOdb->Get_field('weight_units'); 356 | $poids_unite = (!empty($weight_units)) ? $weight_units : $linedetail->weight_reel_unit ; 357 | $poids = $poids * pow(10,$poids_unite); 358 | $weight_reel = $linedetail->weight_reel * pow(10,$linedetail->weight_reel_unit ); 359 | 360 | return $weight_reel / $poids; 361 | } 362 | 363 | private function move_assets_according_to_BDR($object, $event = '', $reverse = false) 364 | { 365 | global $conf, $db, $user, $langs; 366 | 367 | $object->old_details = array(); 368 | 369 | dol_include_once('/dispatch/config.php'); 370 | dol_include_once('/dispatch/class/dispatchdetail.class.php'); 371 | 372 | if($conf->{ ATM_ASSET_NAME }->enabled) 373 | { 374 | dol_include_once('/' . ATM_ASSET_NAME . '/class/asset.class.php'); 375 | 376 | $PDOdb = new TPDOdb(); 377 | 378 | if (!empty($object->lines)) 379 | { 380 | foreach ($object->lines as $line) { 381 | $d = new TRecepBDRDetail(); 382 | 383 | $d->loadLines($PDOdb, $line->id); 384 | 385 | if (!empty($d->lines)) 386 | { 387 | foreach ($d->lines as $detail) 388 | { 389 | $asset = new TAsset(); 390 | 391 | $prod = new Product($db); 392 | $prod->fetch($line->fk_product); 393 | 394 | $ret = $asset->loadReference($PDOdb, $detail->serial_number, $detail->fk_product); 395 | if (!$ret) // l'asset n'existe pas 396 | { 397 | $asset->fk_product = $detail->fk_product; 398 | $asset->serial_number = $detail->serial_number; 399 | $asset->weight = $detail->weight; 400 | $asset->weight_reel = $detail->weight_reel; 401 | $asset->fk_asset_type = $asset->get_asset_type($PDOdb, $prod->id); 402 | } 403 | 404 | $asset->fk_societe_localisation = 0; 405 | $object->old_details[$asset->id] = $asset->fk_entrepot; 406 | $asset->fk_entrepot = $detail->fk_warehouse; 407 | $qty = $detail->weight_reel; 408 | 409 | if ($reverse) 410 | { 411 | $qty = -$qty; 412 | $asset->fk_societe_localisation = $object->socid; 413 | $asset->fk_entrepot = 0; 414 | } 415 | 416 | $asset->save($PDOdb, $user, $langs->trans($event."InDolibarr",$object->ref), $qty, false, 0, true); 417 | 418 | //dernier mouvement de stock standard dolibarr créé 419 | $sql = "SELECT MAX(rowid) as rowid FROM " .MAIN_DB_PREFIX. "stock_mouvement"; 420 | $resql = $db->query($sql); 421 | 422 | if($obj = $db->fetch_object($resql)){ 423 | $last_moov = $obj->rowid; 424 | } 425 | 426 | // Destockage équipement 427 | $stock = new TAssetStock; 428 | $stock->mouvement_stock($PDOdb, $user, $asset->getId(), $qty, $langs->trans($event."InDolibarr",$object->ref), $detail->fk_bonderetourdet, $last_moov); 429 | } 430 | } 431 | } 432 | } 433 | } 434 | } 435 | 436 | /** 437 | * @param $object 438 | * 439 | * @return bool 440 | */ 441 | private function move_assets_according_to_shipment($object) { 442 | global $conf, $db, $langs; 443 | if(!defined('INC_FROM_DOLIBARR')) define('INC_FROM_DOLIBARR', true); 444 | dol_include_once('/dispatch/config.php'); 445 | dol_include_once('/dispatch/class/dispatchdetail.class.php'); 446 | 447 | $PDOdb = new TPDOdb(); 448 | 449 | $noDetailAlert = true; 450 | 451 | // Pour chaque ligne de l'expédition 452 | foreach($object->lines as $line) { 453 | // Chargement de l'objet detail dispatch relié à la ligne d'expédition 454 | $dd = new TDispatchDetail(); 455 | 456 | $TIdExpeditionDet = TRequeteCore::get_id_from_what_you_want($PDOdb, MAIN_DB_PREFIX.'expeditiondet', array('fk_expedition' => $object->id, 'fk_origin_line' => $line->fk_origin_line)); 457 | $idExpeditionDet = $TIdExpeditionDet[0]; 458 | $nb_year_garantie = 0; 459 | 460 | //if(!empty($idExpeditionDet) && $dd->loadBy($PDOdb, $idExpeditionDet, 'fk_expeditiondet')) { 461 | if(!empty($idExpeditionDet)) { 462 | 463 | $dd->loadLines($PDOdb, $idExpeditionDet); 464 | 465 | if($conf->{ ATM_ASSET_NAME }->enabled){ 466 | // Création des mouvements de stock de flacon 467 | foreach($dd->lines as $detail) { 468 | // Création du mouvement de stock standard 469 | $poids_destocke = $this->create_flacon_stock_mouvement($PDOdb, $detail, !empty($object->newref) ? $object->newref : $object->ref,(empty($object->fk_soc)?$object->socid:$object->fk_soc), $object->id); 470 | if($poids_destocke > 0) $noDetailAlert = false; 471 | //$this->create_standard_stock_mouvement($line, $poids_destocke, $object->ref); 472 | 473 | if($conf->clinomadic->enabled){ 474 | $asset = new TAsset; 475 | $asset->load($PDOdb, $detail->fk_asset); 476 | 477 | $prod = new Product($db); 478 | $prod->fetch($asset->fk_product); 479 | 480 | //Affectation du type d'équipement pour avoir accès aux extrafields équipement 481 | $asset->fk_asset_type = $asset->get_asset_type($PDOdb, $prod->id); 482 | $asset->load_asset_type($PDOdb); 483 | 484 | //Localisation client 485 | $asset->fk_societe_localisation = $object->socid; 486 | 487 | if(!empty($object->linkedObjects['commande'][0]->array_options['options_duree_pret'])){ 488 | $asset->etat = 2; //Prêté 489 | $asset->set_date('date_deb_pret', $object->date_valid); 490 | $asset->set_date('date_fin_pret', strtotime('+'.$object->commande[0]->array_options['options_duree_pret'].'year',$object->date_valid)); 491 | } 492 | else{ 493 | $asset->etat = 1; //Vendu 494 | } 495 | 496 | foreach($object->linkedObjects['commande'][0]->lines as $line){ 497 | if($line->fk_product == $asset->fk_product){ 498 | $extension_garantie = $line->array_options['options_extension_garantie']; 499 | } 500 | } 501 | 502 | $nb_year_garantie+=$prod->array_options['options_duree_garantie_client']; 503 | 504 | $asset->date_fin_garantie_cli = strtotime('+'.$nb_year_garantie.'year', $object->date_valid); 505 | $asset->date_fin_garantie_cli = strtotime('+'.$extension_garantie.'year', $asset->date_fin_garantie_cli); 506 | 507 | $asset->save($PDOdb); 508 | } 509 | } 510 | } 511 | //exit; 512 | } // if(!empty($idExpeditionDet)) 513 | /* else { // Pas de détail, on déstocke la quantité comme Dolibarr standard 514 | $this->create_standard_stock_mouvement($line, $line->qty, $object->ref); 515 | }*/ 516 | } 517 | 518 | if(! empty($conf->global->DISPATCH_SHIPPING_VALIDATE_ALERT_IF_NO_DETAIL) && $noDetailAlert) { 519 | $langs->load('dispatch@dispatch'); 520 | setEventMessage('DispatchExpeditionNoDetail'); 521 | } 522 | 523 | } 524 | } 525 | -------------------------------------------------------------------------------- /core/modules/moddispatch.class.php: -------------------------------------------------------------------------------- 1 | 3 | * Copyright (C) 2004-2012 Laurent Destailleur 4 | * Copyright (C) 2005-2012 Regis Houssin 5 | * 6 | * This program is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program. If not, see . 18 | */ 19 | 20 | /** 21 | * \defgroup mymodule Module MyModule 22 | * \brief Example of a module descriptor. 23 | * Such a file must be copied into htdocs/mymodule/core/modules directory. 24 | * \file htdocs/mymodule/core/modules/modMyModule.class.php 25 | * \ingroup mymodule 26 | * \brief Description and activation file for module MyModule 27 | */ 28 | include_once DOL_DOCUMENT_ROOT .'/core/modules/DolibarrModules.class.php'; 29 | 30 | 31 | /** 32 | * Description and activation class for module MyModule 33 | */ 34 | class moddispatch extends DolibarrModules 35 | { 36 | /** 37 | * Constructor. Define names, constants, directories, boxes, permissions 38 | * 39 | * @param DoliDB $db Database handler 40 | */ 41 | function __construct($db) 42 | { 43 | global $langs,$conf; 44 | 45 | $this->db = $db; 46 | $this->editor_name = 'ATM Consulting'; 47 | $this->editor_url = 'https://www.atm-consulting.fr'; 48 | // Id for module (must be unique). 49 | // Use here a free id (See in Home -> System information -> Dolibarr for list of used modules id). 50 | $this->numero = 104970; 51 | // Key text used to identify module (for permissions, menus, etc...) 52 | $this->rights_class = 'dispatch'; 53 | 54 | // Family can be 'crm','financial','hr','projects','products','ecm','technic','other' 55 | // It is used to group modules in module setup page 56 | $this->family = "ATM Consulting - GPAO"; 57 | // Module label (no space allowed), used if translation string 'ModuleXXXName' not found (where XXX is value of numeric property 'numero' of module) 58 | $this->name = preg_replace('/^mod/i','',get_class($this)); 59 | // Module description, used if translation string 'ModuleXXXDesc' not found (where XXX is value of numeric property 'numero' of module) 60 | $this->description = "Module104970Desc"; 61 | // Possible values for version are: 'development', 'experimental', 'dolibarr' or version 62 | 63 | 64 | $this->version = '3.7.7'; 65 | 66 | // Key used in llx_const table to save module status enabled/disabled (where MYMODULE is value of property name of module in uppercase) 67 | $this->const_name = 'MAIN_MODULE_'.strtoupper($this->name); 68 | // Where to store the module in setup page (0=common,1=interface,2=others,3=very specific) 69 | $this->special = 0; 70 | // Name of image file used for this module. 71 | // If file is in theme/yourtheme/img directory under name object_pictovalue.png, use this->picto='pictovalue' 72 | // If file is in module/img directory under name object_pictovalue.png, use this->picto='pictovalue@module' 73 | $this->picto='dispatch.svg@dispatch'; 74 | 75 | // Defined all module parts (triggers, login, substitutions, menus, css, etc...) 76 | // for default path (eg: /mymodule/core/xxxxx) (0=disable, 1=enable) 77 | // for specific path of parts (eg: /mymodule/core/modules/barcode) 78 | // for specific css file (eg: /mymodule/css/mymodule.css.php) 79 | //$this->module_parts = array('triggers' => 1); 80 | //$this->module_parts = array( 81 | // 'triggers' => 1 // Set this to 1 if module has its own trigger directory (core/triggers) 82 | // 'login' => 0, // Set this to 1 if module has its own login method directory (core/login) 83 | // 'substitutions' => 0, // Set this to 1 if module has its own substitution function file (core/substitutions) 84 | // 'menus' => 0, // Set this to 1 if module has its own menus handler directory (core/menus) 85 | // 'theme' => 0, // Set this to 1 if module has its own theme directory (core/theme) 86 | // 'tpl' => 0, // Set this to 1 if module overwrite template dir (core/tpl) 87 | // 'barcode' => 0, // Set this to 1 if module has its own barcode directory (core/modules/barcode) 88 | // 'models' => 0, // Set this to 1 if module has its own models directory (core/modules/xxx) 89 | // 'css' => array('/mymodule/css/mymodule.css.php'), // Set this to relative path of css file if module has its own css file 90 | // 'js' => array('/mymodule/js/mymodule.js'), // Set this to relative path of js file if module must load a js on all pages 91 | // 'hooks' => array('hookcontext1','hookcontext2') // Set here all hooks context managed by module 92 | // 'dir' => array('output' => 'othermodulename'), // To force the default directories names 93 | // 'workflow' => array('WORKFLOW_MODULE1_YOURACTIONTYPE_MODULE2'=>array('enabled'=>'! empty($conf->module1->enabled) && ! empty($conf->module2->enabled)', 'picto'=>'yourpicto@mymodule')) // Set here all workflow context managed by module 94 | // ); 95 | //$this->module_parts = array('hooks'=>array('ordersuppliercard','propalcard', 'ordercard', 'invoicecard'),'triggers' => 1); 96 | $this->module_parts = array( 97 | 'triggers' => 1, 98 | 'hooks' => array('expeditioncard', 'ordersuppliercard', 'pdfgeneration', 'bonderetourcard','receptionstockcard') 99 | ); 100 | 101 | // Data directories to create when module is enabled. 102 | // Example: this->dirs = array("/mymodule/temp"); 103 | $this->dirs = array(); 104 | 105 | // Config pages. Put here list of php page, stored into mymodule/admin directory, to use to setup module. 106 | $this->config_page_url = array(); 107 | 108 | // Dependencies 109 | $this->depends = array(); // List of modules id that must be enabled if this module is enabled 110 | $this->requiredby = array(); // List of modules id to disable if this one is disabled 111 | $this->phpmin = array(5,0); // Minimum version of PHP required by module 112 | $this->need_dolibarr_version = array(3,0); // Minimum version of Dolibarr required by module 113 | $this->langfiles = array("dispatch@dispatch"); 114 | 115 | $this->config_page_url = array("admin.php@dispatch"); 116 | // Constants 117 | // List of particular constants to add when module is enabled (key, 'chaine', value, desc, visible, 'current' or 'allentities', deleteonunactive) 118 | // Example: $this->const=array(0=>array('MYMODULE_MYNEWCONST1','chaine','myvalue','This is a constant to add',1), 119 | // 1=>array('MYMODULE_MYNEWCONST2','chaine','myvalue','This is another constant to add',0, 'current', 1) 120 | // ); 121 | $this->const = array(); 122 | 123 | // Array to add new pages in new tabs 124 | // Example: $this->tabs = array('objecttype:+tabname1:Title1:mylangfile@mymodule:$user->rights->mymodule->read:/mymodule/mynewtab1.php?id=__ID__', // To add a new tab identified by code tabname1 125 | // 'objecttype:+tabname2:Title2:mylangfile@mymodule:$user->rights->othermodule->read:/mymodule/mynewtab2.php?id=__ID__', // To add another new tab identified by code tabname2 126 | // 'objecttype:-tabname':NU:conditiontoremove); // To remove an existing tab identified by code tabname 127 | 128 | if(! defined('ATM_ASSET_NAME')) 129 | { 130 | define('INC_FROM_DOLIBARR', true); 131 | dol_include_once('/dispatch/config.php'); 132 | } 133 | 134 | $this->tabs = array( 135 | 'delivery:+dispatch:ShippingDetailsTab:dispatch@dispatch:$conf->' . ATM_ASSET_NAME . '->enabled:/dispatch/detail.php?id=__ID__' 136 | ,'bonderetour:+recepasset:ManualReceptionTab:dispatch@dispatch:$conf->' . ATM_ASSET_NAME . '->enabled:/dispatch/receptionbdr.php?id=__ID__' 137 | ,'contract:+dispatchAsset:EquipmentDetailsTab:dispatch@dispatch:$conf->' . ATM_ASSET_NAME . '->enabled:/dispatch/asset.php?id=__ID__&type_object=contrat' 138 | ,'intervention:+dispatchAsset:EquipmentDetailsTab:dispatch@dispatch:$conf->' . ATM_ASSET_NAME . '->enabled:/dispatch/asset.php?id=__ID__&type_object=intervention' 139 | ,'ticketsup:+dispatchAsset:EquipmentDetailsTab:dispatch@dispatch:$conf->' . ATM_ASSET_NAME . '->enabled:/dispatch/asset.php?id=__ID__&type_object=ticketsup' 140 | ,'supplier_order:+recepasset:ReceptionTab:dispatch@dispatch:$conf->' . ATM_ASSET_NAME . '->enabled:/dispatch/reception.php?id=__ID__' 141 | ,'supplier_order:-dispatch' 142 | ,'order:+dispatchAsset:EquipmentDetailsTab:dispatch@dispatch:$conf->' . ATM_ASSET_NAME . '->enabled:/dispatch/asset.php?id=__ID__&type_object=commande' 143 | ); 144 | 145 | // where objecttype can be 146 | // 'thirdparty' to add a tab in third party view 147 | // 'intervention' to add a tab in intervention view 148 | // 'order_supplier' to add a tab in supplier order view 149 | // 'invoice_supplier' to add a tab in supplier invoice view 150 | // 'invoice' to add a tab in customer invoice view 151 | // 'order' to add a tab in customer order view 152 | // 'product' to add a tab in product view 153 | // 'stock' to add a tab in stock view 154 | // 'propal' to add a tab in propal view 155 | // 'member' to add a tab in fundation member view 156 | // 'contract' to add a tab in contract view 157 | // 'user' to add a tab in user view 158 | // 'group' to add a tab in group view 159 | // 'contact' to add a tab in contact view 160 | // 'categories_x' to add a tab in category view (replace 'x' by type of category (0=product, 1=supplier, 2=customer, 3=member) 161 | 162 | // Dictionnaries 163 | if (! isset($conf->dispatch->enabled)){ 164 | @$conf->dispatch->enabled=0; 165 | } 166 | $this->dictionnaries=array(); 167 | /* Example: 168 | if (! isset($conf->mymodule->enabled)) $conf->mymodule->enabled=0; // This is to avoid warnings 169 | $this->dictionnaries=array( 170 | 'langs'=>'mylangfile@mymodule', 171 | 'tabname'=>array(MAIN_DB_PREFIX."table1",MAIN_DB_PREFIX."table2",MAIN_DB_PREFIX."table3"), // List of tables we want to see into dictonnary editor 172 | 'tablib'=>array("Table1","Table2","Table3"), // Label of tables 173 | 'tabsql'=>array('SELECT f.rowid as rowid, f.code, f.label, f.active FROM '.MAIN_DB_PREFIX.'table1 as f','SELECT f.rowid as rowid, f.code, f.label, f.active FROM '.MAIN_DB_PREFIX.'table2 as f','SELECT f.rowid as rowid, f.code, f.label, f.active FROM '.MAIN_DB_PREFIX.'table3 as f'), // Request to select fields 174 | 'tabsqlsort'=>array("label ASC","label ASC","label ASC"), // Sort order 175 | 'tabfield'=>array("code,label","code,label","code,label"), // List of fields (result of select to show dictionnary) 176 | 'tabfieldvalue'=>array("code,label","code,label","code,label"), // List of fields (list of fields to edit a record) 177 | 'tabfieldinsert'=>array("code,label","code,label","code,label"), // List of fields (list of fields for insert) 178 | 'tabrowid'=>array("rowid","rowid","rowid"), // Name of columns with primary key (try to always name it 'rowid') 179 | 'tabcond'=>array($conf->mymodule->enabled,$conf->mymodule->enabled,$conf->mymodule->enabled) // Condition to show each dictionnary 180 | ); 181 | */ 182 | 183 | // Boxes 184 | // Add here list of php file(s) stored in core/boxes that contains class to show a box. 185 | $this->boxes = array(); // List of boxes 186 | $r=0; 187 | // Example: 188 | /* 189 | $this->boxes[$r][1] = "myboxa.php"; 190 | $r++; 191 | $this->boxes[$r][1] = "myboxb.php"; 192 | $r++; 193 | */ 194 | 195 | // Permissions 196 | $this->rights = array(); // Permission array used by this module 197 | $r=0; 198 | 199 | // Add here list of permission defined by an id, a label, a boolean and two constant strings. 200 | // Example: 201 | // $this->rights[$r][0] = 2000; // Permission id (must not be already used) 202 | // $this->rights[$r][1] = 'Permision label'; // Permission label 203 | // $this->rights[$r][3] = 1; // Permission by default for new user (0/1) 204 | // $this->rights[$r][4] = 'level1'; // In php code, permission will be checked by test if ($user->rights->permkey->level1->level2) 205 | // $this->rights[$r][5] = 'level2'; // In php code, permission will be checked by test if ($user->rights->permkey->level1->level2) 206 | // $r++; 207 | 208 | 209 | // Main menu entries 210 | $this->menus = array(); // List of menus to add 211 | $r=0; 212 | 213 | // Add here entries to declare new menus 214 | // 215 | // Example to declare a new Top Menu entry and its Left menu entry: 216 | // $this->menu[$r]=array( 'fk_menu'=>0, // Put 0 if this is a top menu 217 | // 'type'=>'top', // This is a Top menu entry 218 | // 'titre'=>'MyModule top menu', 219 | // 'mainmenu'=>'mymodule', 220 | // 'leftmenu'=>'mymodule', 221 | // 'url'=>'/mymodule/pagetop.php', 222 | // 'langs'=>'mylangfile@mymodule', // Lang file to use (without .lang) by module. File must be in langs/code_CODE/ directory. 223 | // 'position'=>100, 224 | // 'enabled'=>'$conf->mymodule->enabled', // Define condition to show or hide menu entry. Use '$conf->mymodule->enabled' if entry must be visible if module is enabled. 225 | // 'perms'=>'1', // Use 'perms'=>'$user->rights->mymodule->level1->level2' if you want your menu with a permission rules 226 | // 'target'=>'', 227 | // 'user'=>2); // 0=Menu for internal users, 1=external users, 2=both 228 | // $r++; 229 | // 230 | // Example to declare a Left Menu entry into an existing Top menu entry: 231 | // $this->menu[$r]=array( 'fk_menu'=>'fk_mainmenu=xxx', // Use 'fk_mainmenu=xxx' or 'fk_mainmenu=xxx,fk_leftmenu=yyy' where xxx is mainmenucode and yyy is a leftmenucode 232 | // 'type'=>'left', // This is a Left menu entry 233 | // 'titre'=>'MyModule left menu', 234 | // 'mainmenu'=>'xxx', 235 | // 'leftmenu'=>'mymodule', 236 | // 'url'=>'/mymodule/pagelevel2.php', 237 | // 'langs'=>'mylangfile@mymodule', // Lang file to use (without .lang) by module. File must be in langs/code_CODE/ directory. 238 | // 'position'=>100, 239 | // 'enabled'=>'$conf->mymodule->enabled', // Define condition to show or hide menu entry. Use '$conf->mymodule->enabled' if entry must be visible if module is enabled. Use '$leftmenu==\'system\'' to show if leftmenu system is selected. 240 | // 'perms'=>'1', // Use 'perms'=>'$user->rights->mymodule->level1->level2' if you want your menu with a permission rules 241 | // 'target'=>'', 242 | // 'user'=>2); // 0=Menu for internal users, 1=external users, 2=both 243 | // $r++; 244 | $this->menu[$r]=array( 'fk_menu'=>'fk_mainmenu=products,fk_leftmenu=sendings', // Use 'fk_mainmenu=xxx' or 'fk_mainmenu=xxx,fk_leftmenu=yyy' where xxx is mainmenucode and yyy is a leftmenucode 245 | 'type'=>'left', // This is a Left menu entry 246 | 'titre'=> $langs->transnoentities( 'DispatchMenuTitle' ), 247 | 'mainmenu'=>'products', 248 | 'leftmenu'=>'sendings', 249 | 'url'=>'/dispatch/liste_expedition_todo.php?leftmenu=sendings', 250 | 'langs'=>'dispatch@dispatch', // Lang file to use (without .lang) by module. File must be in langs/code_CODE/ directory. 251 | 'position'=>100, 252 | 'enabled'=>'$conf->expedition->enabled', // Define condition to show or hide menu entry. Use '$conf->mymodule->enabled' if entry must be visible if module is enabled. Use '$leftmenu==\'system\'' to show if leftmenu system is selected. 253 | 'perms'=>'$user->rights->expedition->lire', // Use 'perms'=>'$user->rights->mymodule->level1->level2' if you want your menu with a permission rules 254 | 'target'=>'', 255 | 'user'=>2); // 0=Menu for internal users, 1=external users, 2=both 256 | $r++; 257 | 258 | 259 | // Exports 260 | $r=1; 261 | 262 | // Example: 263 | // $this->export_code[$r]=$this->rights_class.'_'.$r; 264 | // $this->export_label[$r]='CustomersInvoicesAndInvoiceLines'; // Translation key (used only if key ExportDataset_xxx_z not found) 265 | // $this->export_enabled[$r]='1'; // Condition to show export in list (ie: '$user->id==3'). Set to 1 to always show when module is enabled. 266 | // $this->export_permission[$r]=array(array("facture","facture","export")); 267 | // $this->export_fields_array[$r]=array('s.rowid'=>"IdCompany",'s.nom'=>'CompanyName','s.address'=>'Address','s.cp'=>'Zip','s.ville'=>'Town','s.fk_pays'=>'Country','s.tel'=>'Phone','s.siren'=>'ProfId1','s.siret'=>'ProfId2','s.ape'=>'ProfId3','s.idprof4'=>'ProfId4','s.code_compta'=>'CustomerAccountancyCode','s.code_compta_fournisseur'=>'SupplierAccountancyCode','f.rowid'=>"InvoiceId",'f.facnumber'=>"InvoiceRef",'f.datec'=>"InvoiceDateCreation",'f.datef'=>"DateInvoice",'f.total'=>"TotalHT",'f.total_ttc'=>"TotalTTC",'f.tva'=>"TotalVAT",'f.paye'=>"InvoicePaid",'f.fk_statut'=>'InvoiceStatus','f.note'=>"InvoiceNote",'fd.rowid'=>'LineId','fd.description'=>"LineDescription",'fd.price'=>"LineUnitPrice",'fd.tva_tx'=>"LineVATRate",'fd.qty'=>"LineQty",'fd.total_ht'=>"LineTotalHT",'fd.total_tva'=>"LineTotalTVA",'fd.total_ttc'=>"LineTotalTTC",'fd.date_start'=>"DateStart",'fd.date_end'=>"DateEnd",'fd.fk_product'=>'ProductId','p.ref'=>'ProductRef'); 268 | // $this->export_entities_array[$r]=array('s.rowid'=>"company",'s.nom'=>'company','s.address'=>'company','s.cp'=>'company','s.ville'=>'company','s.fk_pays'=>'company','s.tel'=>'company','s.siren'=>'company','s.siret'=>'company','s.ape'=>'company','s.idprof4'=>'company','s.code_compta'=>'company','s.code_compta_fournisseur'=>'company','f.rowid'=>"invoice",'f.facnumber'=>"invoice",'f.datec'=>"invoice",'f.datef'=>"invoice",'f.total'=>"invoice",'f.total_ttc'=>"invoice",'f.tva'=>"invoice",'f.paye'=>"invoice",'f.fk_statut'=>'invoice','f.note'=>"invoice",'fd.rowid'=>'invoice_line','fd.description'=>"invoice_line",'fd.price'=>"invoice_line",'fd.total_ht'=>"invoice_line",'fd.total_tva'=>"invoice_line",'fd.total_ttc'=>"invoice_line",'fd.tva_tx'=>"invoice_line",'fd.qty'=>"invoice_line",'fd.date_start'=>"invoice_line",'fd.date_end'=>"invoice_line",'fd.fk_product'=>'product','p.ref'=>'product'); 269 | // $this->export_sql_start[$r]='SELECT DISTINCT '; 270 | // $this->export_sql_end[$r] =' FROM ('.MAIN_DB_PREFIX.'facture as f, '.MAIN_DB_PREFIX.'facturedet as fd, '.MAIN_DB_PREFIX.'societe as s)'; 271 | // $this->export_sql_end[$r] .=' LEFT JOIN '.MAIN_DB_PREFIX.'product as p on (fd.fk_product = p.rowid)'; 272 | // $this->export_sql_end[$r] .=' WHERE f.fk_soc = s.rowid AND f.rowid = fd.fk_facture'; 273 | // $r++; 274 | } 275 | 276 | /** 277 | * Function called when module is enabled. 278 | * The init function add constants, boxes, permissions and menus (defined in constructor) into Dolibarr database. 279 | * It also creates data directories 280 | * 281 | * @param string $options Options when enabling module ('', 'noboxes') 282 | * @return int 1 if OK, 0 if KO 283 | */ 284 | function init($options='') 285 | { 286 | $sql = array(); 287 | 288 | $result=$this->load_tables(); 289 | 290 | define('INC_FROM_DOLIBARR',true); 291 | dol_include_once('/dispatch/config.php'); 292 | dol_include_once("/dispatch/script/create-maj-base.php"); 293 | 294 | return $this->_init($sql, $options); 295 | } 296 | 297 | /** 298 | * Function called when module is disabled. 299 | * Remove from database constants, boxes and permissions from Dolibarr database. 300 | * Data directories are not deleted 301 | * 302 | * @param string $options Options when enabling module ('', 'noboxes') 303 | * @return int 1 if OK, 0 if KO 304 | */ 305 | function remove($options='') 306 | { 307 | $sql = array(); 308 | 309 | return $this->_remove($sql, $options); 310 | } 311 | 312 | 313 | /** 314 | * Create tables, keys and data required by module 315 | * Files llx_table1.sql, llx_table1.key.sql llx_data.sql with create table, create keys 316 | * and create data commands must be stored in directory /mymodule/sql/ 317 | * This function is called by this->init 318 | * 319 | * @return int <=0 if KO, >0 if OK 320 | */ 321 | function load_tables() 322 | { 323 | return $this->_load_tables('/dispatch/sql/'); 324 | } 325 | } 326 | 327 | ?> 328 | -------------------------------------------------------------------------------- /class/actions_dispatch.class.php: -------------------------------------------------------------------------------- 1 | fetchObjectLinked(); 25 | //var_dump($com); 26 | $sql = "SELECT DISTINCT c.rowid FROM " . MAIN_DB_PREFIX . "commande AS c "; 27 | $sql .= " INNER JOIN " . MAIN_DB_PREFIX . "element_element AS ee ON c.rowid = ee.fk_target"; 28 | $sql .= " INNER JOIN " . MAIN_DB_PREFIX . "commandedet AS cd ON c.rowid = cd.fk_commande "; 29 | $sql .= " AND ee.fk_source = " . $object->id . ""; 30 | $sql .= " AND ee.targettype = 'commande'"; 31 | $sql .= " AND ee.sourcetype = 'commandefourn'"; 32 | $sql .= " ORDER BY cd.rowid "; 33 | 34 | $resultSetSupplierOrder = $db->query($sql); 35 | 36 | if ($resultSetSupplierOrder) { 37 | $resql = $db->fetch_object($resultSetSupplierOrder); 38 | if ($resql) { 39 | $orderFromSupplierOrder = new Commande($db); 40 | $orderFromSupplierOrder->fetch($resql->rowid); 41 | 42 | if($orderFromSupplierOrder) { 43 | 44 | $shipmentsSql = "SELECT ex.customer_treated_shipment, ex.rowid, e.fk_statut , e.entity , e.rowid"; 45 | $shipmentsSql .= " FROM " . MAIN_DB_PREFIX . "commande AS c "; 46 | $shipmentsSql .= " INNER JOIN " . MAIN_DB_PREFIX . "element_element AS ee ON c.rowid = ee.fk_source "; 47 | $shipmentsSql .= " INNER JOIN " . MAIN_DB_PREFIX . "expedition AS e ON e.rowid = ee.fk_target "; 48 | $shipmentsSql .= " INNER JOIN " . MAIN_DB_PREFIX . "expedition_extrafields AS ex ON e.rowid = ex.fk_object"; 49 | $shipmentsSql .= " AND c.rowid = '" . $orderFromSupplierOrder->id . "' "; 50 | $shipmentsSql .= " AND ee.sourcetype = 'commande' "; 51 | $shipmentsSql .= " AND ee.targettype = 'shipping' "; 52 | 53 | $resultSetShipments = $db->query($shipmentsSql); 54 | $TShipments = array(); 55 | 56 | if ($resultSetShipments) { 57 | $num = $db->num_rows($resultSetShipments); 58 | $i = 0; 59 | while ($i < $num) { 60 | $obj = $db->fetch_object($resultSetShipments); 61 | 62 | /** 63 | *on ne remonte que les expedition au statut cloturée 64 | * ou bien les expeditions traitées 65 | */ 66 | if ($obj) { 67 | if($obj->fk_statut == Expedition::STATUS_CLOSED){ 68 | $TShipments[] = $obj; 69 | } 70 | } else { 71 | dol_syslog(__METHOD__.' $obj='.var_export($obj,true), LOG_ERR); 72 | } 73 | $i++; 74 | } 75 | 76 | } else { 77 | setEventMessage($langs->trans('ErrorAtResultSet', 'resultSetShipments'), 'errors'); 78 | dol_syslog(__METHOD__.' $resql='.var_export($resql,true), LOG_ERR); 79 | } 80 | $object->orderFromSupplierOrder = $orderFromSupplierOrder; 81 | $object->shipmentsFromSupplier = $TShipments; 82 | } else { 83 | dol_syslog(__METHOD__.' $orderFromSupplierOrder='.var_export($orderFromSupplierOrder,true), LOG_ERR); 84 | } 85 | } else { 86 | dol_syslog(__METHOD__.' $resql='.var_export($resql,true), LOG_ERR); 87 | } 88 | } else { 89 | setEventMessage($langs->trans('ErrorAtResultSet', 'resultSetSupplierOrder'), 'errors'); 90 | dol_syslog(__METHOD__.' $resultSetSupplierOrder='.var_export($resultSetSupplierOrder,true), LOG_ERR); 91 | } 92 | } 93 | } 94 | 95 | /** 96 | * Overloading the doActions function : replacing the parent's function with the one below 97 | * 98 | * @param array() $parameters Hook metadatas (context, etc...) 99 | * @param CommonObject &$object The object to process (an invoice if you are in invoice module, a propale in propale's module, etc...) 100 | * @param string &$action Current action (if set). Generally create or edit or null 101 | * @param HookManager $hookmanager Hook manager propagated to allow calling another hook 102 | * @return int < 0 on error, 0 on success, 1 to replace standard code 103 | */ 104 | function doActions($parameters, &$object, &$action, $hookmanager) 105 | { 106 | global $conf; 107 | 108 | $TContexts = explode(':', $parameters['context']); 109 | 110 | if (in_array('bonderetourcard', $TContexts)) { 111 | // var_dump($conf->global->STOCK_CALCULATE_ON_BONDERETOUR_VALIDATE, $conf->global->STOCK_CALCULATE_ON_BONDERETOUR_CLOSE); 112 | //if (! empty($conf->global->STOCK_CALCULATE_ON_BONDERETOUR_VALIDATE)) $conf->global->STOCK_CALCULATE_ON_BONDERETOUR_VALIDATE = 0; 113 | //if (! empty($conf->global->STOCK_CALCULATE_ON_BONDERETOUR_CLOSE)) $conf->global->STOCK_CALCULATE_ON_BONDERETOUR_CLOSE = 0; 114 | // var_dump($conf->global->STOCK_CALCULATE_ON_BONDERETOUR_VALIDATE, $conf->global->STOCK_CALCULATE_ON_BONDERETOUR_CLOSE); 115 | // exit('la'); 116 | } 117 | 118 | return 0; 119 | } 120 | 121 | /** Overloading the addMoreActionsButtons function : replacing the parent's function with the one below 122 | * @param parameters meta datas of the hook (context, etc...) 123 | * @param object the object you want to process (an invoice if you are in invoice module, a propale in propale's module, etc...) 124 | * @param action current action (if set). Generally create or edit or null 125 | * @return void 126 | */ 127 | function addMoreActionsButtons($parameters, &$object, &$action, $hookmanager) 128 | { 129 | global $conf; 130 | 131 | $TContexts = explode(':', $parameters['context']); 132 | 133 | // Add more cols on card lines table 134 | $this->addMoreColsOnCardTable($parameters, $object, $action, $hookmanager); 135 | 136 | 137 | if (in_array('ordersuppliercard', $TContexts)) { 138 | $id = GETPOST('id'); 139 | $targetUrl = dol_buildpath('/dispatch/reception.php', 2) . '?id=' . $id; 140 | ?> 141 | 146 | statut == Expedition::STATUS_VALIDATED && !empty($conf->global->DISPATCH_BLOCK_SHIPPING_CLOSING_IF_PRODUCTS_NOT_PREPARED)) { 150 | if (!defined('INC_FROM_DOLIBARR')) 151 | define('INC_FROM_DOLIBARR', true); 152 | dol_include_once('/dispatch/config.php'); 153 | dol_include_once('/dispatch/lib/dispatch.lib.php'); 154 | 155 | list($canBeClosed, $msg) = dispatch_shipment_can_be_closed($object); 156 | 157 | if (empty($canBeClosed)) { 158 | global $langs; 159 | 160 | $langs->load('dispatch@dispatch'); 161 | 162 | $message = dol_escape_js($langs->transnoentities('ShipmentCannotBeClosed', $msg), 1); 163 | ?> 164 | 169 | load(ATM_ASSET_NAME . '@' . ATM_ASSET_NAME); 203 | $outputlangs->load('productbatch'); 204 | $outputlangs->load('dispatch@dispatch'); 205 | 206 | $expedition = $object; 207 | if (get_class($object) == 'Livraison') { 208 | $expedition = new Expedition($object->db); 209 | $expedition->fetch($object->origin_id); 210 | } 211 | foreach($object->lines as &$line) { 212 | $details = new TDispatchDetail; 213 | 214 | $fkExpeditionLine = $line->id; 215 | 216 | if(get_class($object) == 'Livraison') { 217 | $fkExpeditionLine = 0; 218 | 219 | foreach($expedition->lines as $lineExpe) { 220 | if($lineExpe->fk_origin_line == $line->fk_origin_line) { // La ligne d'origine de la livraison est la ligne de commande et non la ligne d'expédition 221 | $fkExpeditionLine = $lineExpe->id; 222 | break; 223 | } 224 | } 225 | } 226 | 227 | if(! empty($parameters['object']) && get_class($object) == 'CommandeFournisseur') { 228 | $PDOdb = new TPDOdb; 229 | 230 | $outputlangs = $parameters['outputlangs']; 231 | $outputlangs->load(ATM_ASSET_NAME.'@'.ATM_ASSET_NAME); 232 | $outputlangs->load('productbatch'); 233 | $outputlangs->load('dispatch@dispatch'); 234 | 235 | foreach($object->lines as &$line) { 236 | $details = new TRecepDetail; 237 | $TRecepDetail = $details->LoadAllBy($PDOdb, array('fk_commandedet' => $line->id)); 238 | 239 | if(count($TRecepDetail) > 0) { 240 | $line->desc .= '
'.$outputlangs->trans('ProductsReceived').' :'; 241 | 242 | foreach($TRecepDetail as $detail) { 243 | $asset = new TAsset; 244 | $asset->loadBy($PDOdb, $detail->serial_number, 'serial_number'); 245 | $asset->load_asset_type($PDOdb); 246 | $this->_addAssetToLineDesc($line, $detail, $asset, $outputlangs); 247 | } 248 | } 249 | } 250 | } 251 | 252 | if(! empty($fkExpeditionLine)) { 253 | $TRecepDetail = $details->LoadAllBy($PDOdb, array('fk_expeditiondet' => $fkExpeditionLine)); 254 | 255 | if(count($TRecepDetail) > 0) { 256 | if(! empty($line->description) && $line->description != $line->desc) $line->desc .= $line->description.'
'; // Sinon Dans certains cas desc écrase description 257 | $line->desc .= '
'.$outputlangs->trans('ProductsSent').' :'; 258 | 259 | $TCompareDetails = array(); 260 | 261 | foreach($TRecepDetail as $detail) { 262 | // Grouping with conf 263 | if(! empty($conf->global->DISPATCH_GROUP_DETAILS_ON_PDF) && intval($detail->fk_asset) > 0) { 264 | $asset = new TAsset; 265 | $asset->load($PDOdb, $detail->fk_asset); 266 | $newComparaison = $this->getArrayForAssetToLineDescCompare($detail, $asset, $outputlangs); 267 | 268 | $isGrouped = false; 269 | //This condition exists for the first case : key = 0 270 | if(! empty($TCompareDetails)) { 271 | foreach($TCompareDetails as $compKey => $compareDetail) { 272 | //Comparing lot numbers between them 273 | $resComp = array_diff_assoc($newComparaison, $compareDetail->TCompare); 274 | if(empty($resComp)) { 275 | $isGrouped = true; 276 | $TCompareDetails[$compKey]->total_weight_reel += doubleval($detail->weight_reel); 277 | break; 278 | } 279 | } 280 | } 281 | 282 | if(! $isGrouped) { 283 | //Creation of the first element 284 | $compareDetail = new stdClass(); 285 | $compareDetail->total_weight_reel = doubleval($line->qty); 286 | $compareDetail->TCompare = $newComparaison; 287 | $TCompareDetails[] = $compareDetail; 288 | } 289 | } 290 | else { 291 | $asset = new TAsset; 292 | $asset->loadBy($PDOdb, $detail->lot_number, 'lot_number'); 293 | $asset->load_asset_type($PDOdb); 294 | $this->_addAssetToLineDesc($line, $detail, $asset, $outputlangs); 295 | } 296 | } 297 | 298 | if(! empty($TCompareDetails)) { 299 | foreach($TCompareDetails as $compareDetail) { 300 | $this->_addAssetGroupToLineDesc($line, $compareDetail, $outputlangs); 301 | } 302 | } 303 | } 304 | } 305 | } 306 | } 307 | } 308 | } 309 | 310 | /** 311 | * @param $detail 312 | * @param $asset 313 | * @param $outputlangs 314 | * @return array containing unite and lot number if there is a lot, and unite, lot number and serial number if not 315 | */ 316 | public function getArrayForAssetToLineDescCompare($detail, $asset, $outputlangs) 317 | { 318 | $unite = (($asset->assetType->measuring_units == 'unit') ? $outputlangs->trans('Assetunit_s') : measuring_units_string($detail->weight_reel_unit, $asset->assetType->measuring_units)); 319 | 320 | if (!empty($asset->lot_number)) 321 | { 322 | $forCompare = array( 323 | 'unite' => $unite, 324 | 'lot_number' => $asset->lot_number 325 | ); 326 | } 327 | else // Case without lot 328 | { 329 | $forCompare = array( 330 | 'unite' => $unite, 331 | 'lot_number' => $asset->lot_number, 332 | 'serial_number' => $asset->serial_number 333 | ); 334 | } 335 | 336 | if (!empty($conf->global->ASSET_SHOW_DLUO) && empty($conf->global->DISPATCH_HIDE_DLUO_PDF) && !empty($asset->date_dluo)) { 337 | $forCompare['DateDluo'] = $asset->get_date('dluo'); 338 | } 339 | 340 | return $forCompare; 341 | } 342 | 343 | /** 344 | * @param $line 345 | * @param $detail 346 | * @param $asset 347 | * @param Translate $outputlangs 348 | */ 349 | function _addAssetToLineDesc(&$line, $detail, $asset, Translate $outputlangs) 350 | { 351 | global $conf; 352 | 353 | $unite = (($asset->assetType->measuring_units == 'unit') ? $outputlangs->trans('Assetunit_s') : measuring_units_string($detail->weight_reel_unit, $asset->assetType->measuring_units)); 354 | 355 | if (empty($asset->lot_number)) { 356 | $desc = '
- ' . $outputlangs->trans('SerialNumberShort') . ' : ' . $asset->serial_number; 357 | } else { 358 | $desc = "
- " . $asset->lot_number . " x " . $detail->weight_reel . " " . $unite; 359 | } 360 | 361 | if (!empty($conf->global->ASSET_SHOW_DLUO) && empty($conf->global->DISPATCH_HIDE_DLUO_PDF) && !empty($asset->date_dluo)) { 362 | $desc .= ' (' . $outputlangs->trans('EatByDate') . ' : ' . $asset->get_date('dluo') . ')'; 363 | } 364 | 365 | $line->desc .= $desc; 366 | } 367 | 368 | /** 369 | * @param $line 370 | * @param $compareDetail 371 | * @param $outputlangs 372 | */ 373 | function _addAssetGroupToLineDesc(&$line, $compareDetail, $outputlangs) 374 | { 375 | global $conf; 376 | $unite = $compareDetail->TCompare['unite']; 377 | $serial_number = $compareDetail->TCompare['serial_number']; 378 | $lot_number = $compareDetail->TCompare['lot_number']; 379 | 380 | if (empty($lot_number)) { 381 | $desc = '
- ' . $outputlangs->trans('SerialNumberShort') . ' : ' . $serial_number; 382 | } else { 383 | $desc = "
- " . $lot_number . " x " . $compareDetail->total_weight_reel . " " . $unite; 384 | } 385 | 386 | if (!empty($conf->global->ASSET_SHOW_DLUO) && empty($conf->global->DISPATCH_HIDE_DLUO_PDF) && !empty($compareDetail->TCompare['DateDluo'])) { 387 | $desc .= ' (' . $outputlangs->trans('EatByDate') . ' : ' . $compareDetail->TCompare['DateDluo'] . ')'; 388 | } 389 | 390 | $line->desc .= $desc; 391 | } 392 | 393 | 394 | /* 395 | * Overloading the addMoreActionsButtons function 396 | * 397 | * @param array() $parameters Hook metadatas (context, etc...) 398 | * @param CommonObject $object The object to process (an invoice if you are in invoice module, a propale in propale's module, etc...) 399 | * @param string $action Current action (if set). Generally create or edit or null 400 | * @param HookManager $hookmanager Hook manager propagated to allow calling another hook 401 | * @return int < 0 on error, 0 on success, 1 to replace standard code 402 | */ 403 | public function addMoreColsOnCardTable(&$parameters, &$object, &$action, $hookmanager) 404 | { 405 | global $conf, $langs, $db; 406 | 407 | if (intval(DOL_VERSION) < 11 && empty($conf->global->DISPATCH_SHOW_BATCH_COL_IN_CARD)) { 408 | return 0; 409 | } 410 | 411 | if (empty($conf->assetatm->enabled)) { 412 | return 0; 413 | } 414 | 415 | 416 | $contextArray = explode(':', $parameters['context']); 417 | 418 | if (in_array('expeditioncard', $contextArray)) { 419 | 420 | define('INC_FROM_DOLIBARR', true); 421 | dol_include_once('/dispatch/config.php'); 422 | dol_include_once('/' . ATM_ASSET_NAME . '/class/asset.class.php'); 423 | dol_include_once('/dispatch/class/dispatchdetail.class.php'); 424 | dol_include_once('/dispatch/class/dispatchasset.class.php'); 425 | 426 | $expedition = $object; 427 | 428 | $jsonObjectData = array(); 429 | foreach ($object->lines as $i => $line) { 430 | $jsonObjectData[$line->id] = new stdClass(); 431 | $jsonObjectData[$line->id]->id = $line->id; 432 | 433 | $product = new Product($db); 434 | if (!empty($line->fk_product)) { 435 | $product->fetch($line->fk_product); 436 | } 437 | 438 | $jsonObjectData[$line->id]->batch = ''; 439 | 440 | // GET DISPATCH INFOS 441 | $PDOdb = new TPDOdb; 442 | $details = new TDispatchDetail(); 443 | 444 | $fkExpeditionLine = $line->id; 445 | 446 | if (get_class($object) == 'Livraison') { 447 | $fkExpeditionLine = 0; 448 | 449 | foreach ($expedition->lines as $lineExpe) { 450 | if ($lineExpe->fk_origin_line == $line->fk_origin_line) { // La ligne d'origine de la livraison est la ligne de commande et non la ligne d'expédition 451 | $fkExpeditionLine = $lineExpe->id; 452 | break; 453 | } 454 | } 455 | } 456 | 457 | if (!empty($fkExpeditionLine)) { 458 | $TRecepDetail = $details->LoadAllBy($PDOdb, array('fk_expeditiondet' => $fkExpeditionLine)); 459 | 460 | if (count($TRecepDetail) > 0) { 461 | if (!empty($line->description) && $line->description != $line->desc) 462 | $line->desc .= $line->description . '
'; // Sinon Dans certains cas desc écrase description 463 | $batch = ''; 464 | 465 | foreach ($TRecepDetail as $detail) { 466 | $asset = new TAsset; 467 | $asset->load($PDOdb, $detail->fk_asset); 468 | $asset->load_asset_type($PDOdb); 469 | 470 | $unite = (($asset->assetType->measuring_units == 'unit') ? 'unité(s)' : measuring_units_string($detail->weight_reel_unit, $asset->assetType->measuring_units)); 471 | 472 | if (empty($asset->lot_number)) { 473 | $batch = $asset->serial_number; 474 | } else { 475 | $batch = $asset->lot_number . " x " . $detail->weight_reel . " " . $unite; 476 | } 477 | 478 | if (!empty($conf->global->ASSET_SHOW_DLUO) && empty($conf->global->DISPATCH_HIDE_DLUO_PDF) && !empty($asset->date_dluo)) 479 | $batch .= ' (DLUO : ' . $asset->get_date('dluo') . ')'; 480 | $jsonObjectData[$line->id]->batch = $batch; 481 | } 482 | } 483 | } 484 | 485 | } 486 | 487 | $totalAddedCols = 1; 488 | ?> 489 | 523 | load('orders'); 16 | $PDOdb=new TPDOdb; 17 | 18 | $id = GETPOST('id'); 19 | $ref = GETPOST('ref'); 20 | 21 | $expedition = new Expedition($db); 22 | $expedition->fetch($id, $ref); 23 | 24 | $action = GETPOST('action'); 25 | $TImport = _loadDetail($PDOdb, $expedition); 26 | 27 | $hookmanager->initHooks(array('shipmentdispatchcard')); 28 | 29 | $parameters = array(); 30 | $reshook = $hookmanager->executeHooks('doActions', $parameters, $TImport, $action); 31 | if ($reshook < 0) setEventMessages($hookmanager->error, $hookmanager->errors, 'errors'); 32 | if(empty($reshook)) 33 | { 34 | switch ($action) 35 | { 36 | case 'importfile': 37 | // TODO à nettoyer, dégueulasse et spécifique (ex. IMEI ?!) - MdLL, 12/03/2019 38 | if (isset($_FILES['file1']) && $_FILES['file1']['name'] != '') { 39 | $f1 = file($_FILES['file1']['tmp_name']); 40 | 41 | $TImport = array(); 42 | 43 | foreach ($f1 as $line) { 44 | list($ref, $numserie, $imei, $firmware) = str_getcsv($line, ';', '"'); 45 | 46 | $TImport = _addExpeditiondetLine($PDOdb, $TImport, $expedition, $numserie); 47 | } 48 | } 49 | 50 | break; 51 | 52 | case 'deleteline': 53 | array_splice($TImport, (int)GETPOST('k'), 1); // Supprime le k-ième élément et décale les suivants dans le tableau 54 | 55 | $rowid = GETPOST('rowid'); 56 | 57 | $dispatchdetail = new TDispatchDetail; 58 | $dispatchdetail->load($PDOdb, $rowid); 59 | $dispatchdetail->delete($PDOdb); 60 | 61 | setEventMessage('Ligne supprimée'); 62 | 63 | break; 64 | 65 | case 'save': 66 | $numserie = GETPOST('numserie'); // Peut être un numéro de série ou bien la valeur -2 du select (Ajouter automatiquement) 67 | $lot_number = GETPOST('lot_number'); 68 | $line = new ExpeditionLigne($db); 69 | $lineId = GETPOST('lineexpeditionid', 'int'); 70 | $line->fetch($lineId); 71 | if ($line->id === null) { 72 | setEventMessage($langs->trans("ErrorUnableToFetchLine", $lineId),"errors"); 73 | break; 74 | } 75 | 76 | if ($numserie == -2){ 77 | $sql = 'SELECT a.rowid, serial_number FROM '.MAIN_DB_PREFIX.'assetatm a'; 78 | $sql.= " WHERE a.lot_number LIKE '".$db->escape($lot_number)."'"; 79 | 80 | //Si l'équipement est attribué à une autre expédition qui a le statut brouillon ou validé, on ne le propose pas 81 | if($expedition->statut == Expedition::STATUS_DRAFT || $expedition->statut == Expedition::STATUS_VALIDATED ) { 82 | $sql.= " AND a.rowid NOT IN (SELECT eda2.fk_asset FROM ".MAIN_DB_PREFIX."expeditiondet_asset eda2 83 | LEFT JOIN ".MAIN_DB_PREFIX."expeditiondet as ed2 ON (ed2.rowid = eda2.fk_expeditiondet) 84 | LEFT JOIN ".MAIN_DB_PREFIX."expedition as e2 ON (e2.rowid = ed2.fk_expedition) WHERE e2.fk_statut < 2) LIMIT " . $line->qty; 85 | } 86 | 87 | $resql = $db->query($sql); 88 | if (! empty($resql->num_rows)) { 89 | while($obj = $db->fetch_object($resql)) { 90 | _addExpeditiondetLine($PDOdb, $TImport, $expedition, $obj->serial_number); 91 | } 92 | 93 | setEventMessage($langs->trans('AllSerialNumbersAdded')); 94 | } 95 | else setEventMessage($langs->trans('NoMoreAssetAvailable'), 'errors'); 96 | } 97 | else { 98 | $asset = new TAsset; 99 | if ($asset->loadBy($PDOdb, $numserie, 'serial_number')) { 100 | 101 | _addExpeditiondetLine($PDOdb, $TImport, $expedition, $numserie); 102 | 103 | setEventMessage('Numéro de série enregistré'); 104 | } else { 105 | setEventMessage('Aucun équipement pour ce numéro de série', 'errors'); 106 | } 107 | } 108 | 109 | 110 | header('location:'.$_SERVER['PHP_SELF'].'?id='.$id); 111 | exit; 112 | 113 | break; 114 | } 115 | } 116 | 117 | 118 | fiche($PDOdb,$expedition, $TImport); 119 | 120 | function _loadDetail(&$PDOdb, &$expedition) 121 | { 122 | $TImport = array(); 123 | 124 | foreach($expedition->lines as $line) 125 | { 126 | $sql = "SELECT ea.rowid as fk_expeditiondet_asset, a.rowid as id,a.serial_number,p.ref,p.rowid, ea.fk_expeditiondet, ea.lot_number, ea.weight_reel, ea.weight_reel_unit, ea.is_prepared 127 | FROM ".MAIN_DB_PREFIX."expeditiondet_asset as ea 128 | LEFT JOIN ".MAIN_DB_PREFIX.ATM_ASSET_NAME." as a ON ( a.rowid = ea.fk_asset) 129 | LEFT JOIN ".MAIN_DB_PREFIX."product as p ON (p.rowid = a.fk_product) 130 | WHERE ea.fk_expeditiondet = ".$line->line_id." 131 | ORDER BY ea.rang ASC"; 132 | 133 | $PDOdb->Execute($sql); 134 | $Tres = $PDOdb->Get_All(); 135 | 136 | foreach ($Tres as $res) 137 | { 138 | $TImport[] = array( 139 | 'fk_expeditiondet_asset'=>$res->fk_expeditiondet_asset 140 | ,'ref'=>$res->ref 141 | ,'numserie'=>$res->serial_number 142 | ,'fk_product'=>$res->rowid 143 | ,'fk_expeditiondet'=>$res->fk_expeditiondet 144 | ,'lot_number'=>$res->lot_number 145 | ,'quantity'=>$res->weight_reel 146 | ,'quantity_unit'=>$res->weight_reel_unit 147 | ,'is_prepared'=>$res->is_prepared 148 | ); 149 | } 150 | } 151 | 152 | return $TImport; 153 | } 154 | 155 | function _addExpeditiondetLine(&$PDOdb,&$TImport,&$expedition,$numserie) 156 | { 157 | global $db; 158 | 159 | //Charge l'asset lié au numéro de série dans le fichier 160 | $asset = new TAsset; 161 | if($asset->loadBy($PDOdb,$numserie,'serial_number')){ 162 | 163 | //Charge le produit associé à l'équipement 164 | $prodAsset = new Product($db); 165 | $prodAsset->fetch($asset->fk_product); 166 | 167 | $fk_line_expe = (int)GETPOST('lineexpeditionid'); 168 | if( empty($fk_line_expe) ) { 169 | //Récupération de l'indentifiant de la ligne d'expédition concerné par le produit 170 | foreach($expedition->lines as $expeline){ 171 | if($expeline->fk_product == $prodAsset->id){ 172 | $fk_line_expe = $expeline->line_id; 173 | } 174 | } 175 | } 176 | 177 | //Sauvegarde (ajout/MAJ) des lignes de détail d'expédition 178 | $dispatchdetail = new TDispatchDetail; 179 | 180 | //Si déjà existant => MAj 181 | $PDOdb->Execute("SELECT rowid FROM ".MAIN_DB_PREFIX."expeditiondet_asset WHERE fk_asset = ".$asset->rowid." AND fk_expeditiondet = ".$fk_line_expe." "); 182 | if($PDOdb->Get_line()){ 183 | $dispatchdetail->load($PDOdb,$PDOdb->Get_field('rowid')); 184 | } 185 | 186 | $keys = array_keys($TImport); 187 | $rang = $keys[count($keys)-1]; 188 | 189 | $dispatchdetail->fk_expeditiondet = $fk_line_expe; 190 | $dispatchdetail->fk_asset = $asset->rowid; 191 | $dispatchdetail->rang = $rang; 192 | $dispatchdetail->lot_number = $asset->lot_number; 193 | $dispatchdetail->weight = (GETPOST('quantity')) ? GETPOST('quantity') : $asset->contenancereel_value; 194 | $dispatchdetail->weight_reel = (GETPOST('quantity')) ? GETPOST('quantity') : $asset->contenancereel_value; 195 | $dispatchdetail->weight_unit = (GETPOST('quantity_unit')) ? GETPOST('quantity_unit') : $asset->contenancereel_units; 196 | $dispatchdetail->weight_reel_unit = (GETPOST('quantity_unit')) ? GETPOST('quantity_unit') : $asset->contenancereel_units; 197 | $dispatchdetail->is_prepared = 0; 198 | 199 | $fk_expeditiondet_asset = $dispatchdetail->save($PDOdb); 200 | 201 | if($fk_expeditiondet_asset > 0) 202 | { 203 | // Remplit le tableau utilisé pour l'affichage des lignes 204 | $TImport[] =array( 205 | 'fk_expeditiondet_asset'=>$fk_expeditiondet_asset 206 | ,'ref'=>$prodAsset->ref 207 | ,'numserie'=>$numserie 208 | ,'fk_product'=>$prodAsset->id 209 | ,'fk_expeditiondet'=>$fk_line_expe 210 | ,'lot_number'=>$asset->lot_number 211 | ,'quantity'=> (GETPOST('quantity')) ? GETPOST('quantity') : $asset->contenancereel_value 212 | ,'quantity_unit'=> (GETPOST('quantity_unit')) ? GETPOST('quantity_unit') : $asset->contenancereel_units 213 | ,'is_prepared' => 0 214 | ); 215 | } 216 | } 217 | //pre($TImport,true); 218 | return $TImport; 219 | 220 | } 221 | 222 | 223 | function fiche(&$PDOdb,&$expedition, &$TImport) 224 | { 225 | global $langs, $db, $conf; 226 | 227 | llxHeader(); 228 | 229 | $head = shipping_prepare_head($expedition); 230 | 231 | $title=$langs->trans("Shipment"); 232 | dol_fiche_head($head, 'dispatch', $title, -1, 'sending'); 233 | 234 | enteteexpedition($expedition); 235 | 236 | if($expedition->statut == 0 && ! empty($conf->global->DISPATCH_USE_IMPORT_FILE)) 237 | { 238 | //Form pour import de fichier 239 | echo '
'; 240 | 241 | $form=new TFormCore('auto','formimport','post', true); 242 | 243 | echo $form->hidden('action', 'importfile'); 244 | echo $form->hidden('id', $expedition->id); 245 | 246 | echo $form->fichier('Fichier à importer','file1','',80); 247 | echo $form->btsubmit('Envoyer', 'btsend'); 248 | 249 | $form->end(); 250 | } 251 | 252 | tabImport($TImport,$expedition); 253 | 254 | dol_fiche_end(); 255 | 256 | llxFooter(); 257 | } 258 | 259 | 260 | function tabImport(&$TImport,&$expedition) 261 | { 262 | global $langs, $db, $conf, $hookmanager; 263 | 264 | $form = new TFormCore('auto', 'formaddasset','post'); 265 | echo $form->hidden('action','save'); 266 | echo $form->hidden('mode','addasset'); 267 | echo $form->hidden('id', $expedition->id); 268 | 269 | $PDOdb=new TPDOdb; 270 | 271 | print load_fiche_titre($langs->trans('DispatchItemCountDispatch', count($TImport)), '', ''); 272 | 273 | $fullColspan = 4; 274 | if(! empty($conf->global->USE_LOT_IN_OF)) $fullColspan++; 275 | if(! empty($conf->global->DISPATCH_SHIPPING_LINES_CAN_BE_CHECKED_PREPARED)) $fullColspan++; 276 | ?> 277 |
278 | 279 | 280 | 281 | global->USE_LOT_IN_OF)) { ?> 282 | 283 | 284 | 285 | 286 | global->DISPATCH_SHIPPING_LINES_CAN_BE_CHECKED_PREPARED)) { ?> 287 | 288 | &$fullColspan); 291 | $reshook = $hookmanager->executeHooks('addColumnsHeader', $parameters, $TImport, $action); 292 | if(empty($reshook)) echo $hookmanager->resPrint; 293 | ?> 294 | 295 | 296 | 297 | Set_typeaff('view'); 301 | 302 | $canEdit = $expedition->statut == 0 || (! empty($conf->global->STOCK_CALCULATE_ON_SHIPMENT_CLOSE) && $expedition->statut == 1); 303 | 304 | if(! empty($TImport)){ 305 | 306 | foreach ($TImport as $k=>$line) { 307 | 308 | if($prod->id==0 || $line['ref']!= $prod->ref) { 309 | if(!empty( $line['fk_product']))$prod->fetch($line['fk_product']); 310 | else $prod->fetch('', $line['ref']); 311 | } 312 | 313 | $asset = new TAsset; 314 | $asset->loadBy($PDOdb,$line['numserie'],'serial_number'); 315 | $asset->load_asset_type($PDOdb); 316 | 317 | $assetLot = new TAssetLot; 318 | $assetLot->loadBy($PDOdb,$line['lot_number'],'lot_number'); 319 | 320 | $Trowid = TRequeteCore::get_id_from_what_you_want($PDOdb, MAIN_DB_PREFIX."expeditiondet_asset",array('fk_asset'=>$asset->rowid,'fk_expeditiondet'=>$line['fk_expeditiondet'])); 321 | ?> 322 | 323 | global->USE_LOT_IN_OF)) { ?> 324 | 325 | 326 | 327 | 328 | global->DISPATCH_SHIPPING_LINES_CAN_BE_CHECKED_PREPARED)) 330 | { 331 | if($expedition->statut < Expedition::STATUS_CLOSED) $form->Set_typeaff('edit'); 332 | ?> 333 | 336 | statut < Expedition::STATUS_CLOSED) $form->Set_typeaff('view'); 338 | } 339 | 340 | $parameters = array('line' => &$line, 'k' => &$k, 'asset' => &$asset, 'form' => &$form); 341 | $reshook = $hookmanager->executeHooks('addColumnsLines', $parameters, $expedition, $action); 342 | if(empty($reshook)) echo $hookmanager->resPrint; 343 | ?> 344 | 349 | 350 | 351 | 357 | 358 | 365 |
trans('Product'); ?>trans('DispatchBatchNumber'); ?>trans('DispatchSerialNumber'); ?>trans('Quantity'); ?>checkbox1('', 'allPrepared', 1, false, '','allPreparedCheckbox'); ?> Préparé 
getNomUrl(1).$form->hidden('TLine['.$k.'][fk_expeditiondet_asset]', $line['fk_expeditiondet_asset']).$form->hidden('TLine['.$k.'][fk_product]', $prod->id).$form->hidden('TLine['.$k.'][ref]', $prod->ref).$form->hidden('TLine['.$k.'][fk_expeditiondet]', $line['fk_expeditiondet']) ?>texte('','TLine['.$k.'][lot_number]', $line['lot_number'], 30); ?>texte('','TLine['.$k.'][numserie]', $line['numserie'], 30); ?>assetType->measuring_units == 'unit') ? 'unité(s)' : measuring_units_string('', '', ($line['quantity_unit']))); ?> 334 | checkbox1('', 'TLine[' . $k . '][is_prepared]', 1, ! empty($line['is_prepared']), '', 'isPreparedCheckbox'); ?> 335 | 345 | id.'&rowid='.$Trowid[0].'&token='.newToken().'">'.img_delete().''; 347 | ?> 348 |
trans('NoShipmentAssetDetail'); ?>
366 | end(); 369 | 370 | if($canEdit || $expedition->statut < Expedition::STATUS_CLOSED) { 371 | printJSTabImportAddLine(); 372 | } 373 | } 374 | 375 | /** 376 | * @param TPDOdb $PDOdb 377 | * @param Expedition $expedition 378 | * @param TFormCore $form 379 | * @param $fullColspan 380 | */ 381 | function tabImportAddLine(&$PDOdb, &$expedition, $form, $fullColspan) 382 | { 383 | global $conf, $db, $hookmanager, $langs; 384 | $DoliFormProduct = new FormProduct($db); 385 | 386 | $form->Set_typeaff('edit'); 387 | ?> 388 | 389 | Nouvel équipement 390 | 391 | global->DISPATCH_SERIALIZED_PRODUCTS_MUST_HAVE_ASSET_TYPE_SET)) 400 | { 401 | $sql.= " 402 | LEFT JOIN " . MAIN_DB_PREFIX . "product_extrafields pe ON pe.fk_object = p.rowid "; 403 | } 404 | 405 | $sql.= " 406 | LEFT JOIN ".MAIN_DB_PREFIX."commandedet as cd ON (cd.fk_product = p.rowid) 407 | LEFT JOIN ".MAIN_DB_PREFIX."expeditiondet as ed ON (ed.fk_origin_line = cd.rowid) 408 | LEFT JOIN ".MAIN_DB_PREFIX."expeditiondet_asset as eda ON (eda.fk_expeditiondet = ed.rowid) 409 | WHERE ed.fk_expedition = ".$expedition->id; 410 | 411 | if (! empty($conf->global->DISPATCH_SERIALIZED_PRODUCTS_MUST_HAVE_ASSET_TYPE_SET)) 412 | { 413 | $sql.= " 414 | AND COALESCE(pe.type_asset, 0) > 0"; 415 | } 416 | 417 | $sql.= " 418 | GROUP BY ed.rowid 419 | HAVING COALESCE(SUM(eda.weight_reel), 0) < ed.qty"; 420 | 421 | $PDOdb->Execute($sql); 422 | 423 | if($PDOdb->Get_Recordcount() > 0) { 424 | 425 | $productOptions = ''; 426 | 427 | while ($obj = $PDOdb->Get_line()) { 428 | $prodStatic = new Product($db); 429 | $prodStatic->fetch($obj->fk_product); 430 | 431 | $productOptions.= ''; 432 | } 433 | ?> 434 | 435 | 436 | 437 | global->USE_LOT_IN_OF)) { ?> 438 | 439 | 440 | combo_sexy('', 'lot_number', $TLotNumber, ''); ?> 441 | 442 | hidden('lot_number', ''); ?> 443 | 444 | 445 | combo_sexy('','numserie',$TSerialNumber,''); ?> 446 | 447 | load_measuring_units('quantity_unit" id="quantity_unit', 'weight'); 450 | } 451 | else{ 452 | if(intval(DOL_VERSION) >= 14) { 453 | echo $DoliFormProduct->selectMeasuringUnits('quantity_unit', 'weight'); 454 | } 455 | else echo $DoliFormProduct->selectMeasuringUnits('quantity_unit" id="quantity_unit', 'weight'); 456 | } 457 | ?> 458 | 459 | global->DISPATCH_SHIPPING_LINES_CAN_BE_CHECKED_PREPARED)) { ?> 460 |   461 | executeHooks('addColumnsNewLine', $parameters,$expedition ,$action); 466 | if(empty($reshook)) echo $hookmanager->resPrint; 467 | ?> 468 | btsubmit('Ajouter', 'btaddasset'); ?> 469 | 470 | Get_Recordcount() > 0) 472 | else { 473 | ?> 474 | 475 | Tous les équipements de l'expédition ont été renseignés 476 | 477 | 487 | 787 | fetch($expedition->socid); 797 | 798 | if (!empty($expedition->origin) && $expedition->origin_id > 0) 799 | { 800 | $typeobject = $expedition->origin; 801 | $origin = $expedition->origin; 802 | $origin_id = $expedition->origin_id; 803 | $expedition->fetch_origin(); // Load property $object->commande, $object->propal, ... 804 | 805 | if ($typeobject == 'commande' && $expedition->$typeobject->id && ! empty($conf->commande->enabled)) 806 | { 807 | $objectsrc=new Commande($db); 808 | $objectsrc->fetch($expedition->$typeobject->id); 809 | } 810 | 811 | if ($typeobject == 'propal' && $expedition->$typeobject->id && ! empty($conf->propal->enabled)) 812 | { 813 | $objectsrc=new Propal($db); 814 | $objectsrc->fetch($expedition->$typeobject->id); 815 | } 816 | } 817 | 818 | if(empty($expedition->thirdparty) && method_exists($expedition, 'fetch_thirdparty')) 819 | { 820 | $expedition->fetch_thirdparty(); 821 | } 822 | 823 | $hasDolBannerTab = function_exists('dol_banner_tab'); 824 | 825 | $linkback = ''.$langs->trans("BackToList").''; 826 | 827 | if($hasDolBannerTab) 828 | { 829 | $morehtmlref='
' . $langs->trans('RefCustomer') . ' : ' . $expedition->ref_customer; 830 | // Thirdparty 831 | $morehtmlref.='
'.$langs->trans('ThirdParty') . ' : ' . $expedition->thirdparty->getNomUrl(1); 832 | // Project 833 | if (! empty($conf->projet->enabled)) { 834 | dol_include_once('/projet/class/project.class.php'); 835 | $langs->load("projects"); 836 | $morehtmlref .= '
' . $langs->trans('Project') . ' '; 837 | 838 | // We don't have project on shipment, so we will use the project or source object instead 839 | $morehtmlref .= ' : '; 840 | if (! empty($objectsrc->fk_project)) { 841 | $proj = new Project($db); 842 | $proj->fetch($objectsrc->fk_project); 843 | $morehtmlref .= ''; 844 | $morehtmlref .= $proj->ref; 845 | $morehtmlref .= ''; 846 | } 847 | } 848 | $morehtmlref.='
'; 849 | 850 | 851 | dol_banner_tab($expedition, 'ref', $linkback, 1, 'ref', 'ref', $morehtmlref); 852 | } 853 | 854 | print ''; 855 | 856 | if(! $hasDolBannerTab) 857 | { 858 | // Ref 859 | print ''; 860 | print ''; 863 | 864 | // Customer 865 | print ''; 866 | print ''; 867 | print ""; 868 | } 869 | 870 | // Linked documents 871 | if ($typeobject == 'commande' && $expedition->$typeobject->id && ! empty($conf->commande->enabled)) 872 | { 873 | print ''; 877 | print '\n"; 880 | print ''; 881 | } 882 | if ($typeobject == 'propal' && $expedition->$typeobject->id && ! empty($conf->propal->enabled)) 883 | { 884 | print ''; 888 | print '\n"; 891 | print ''; 892 | } 893 | 894 | if(! $hasDolBannerTab) 895 | { 896 | // Ref customer 897 | print ''; 898 | print '\n"; 899 | print ''; 900 | } 901 | 902 | // Date creation 903 | print ''; 904 | print '\n"; 905 | print ''; 906 | 907 | // Delivery date planed 908 | print ''; 917 | print ''; 918 | 919 | if(! $hasDolBannerTab) 920 | { 921 | // Status 922 | print ''; 923 | print '\n"; 924 | print ''; 925 | } 926 | 927 | // Sending method 928 | print ''; 942 | print ''; 943 | 944 | print "
' . $langs->trans("Ref") . ''; 861 | print $form->showrefnav($expedition, 'ref', $linkback, 1, 'ref', 'ref'); 862 | print '
' . $langs->trans("Customer") . '' . $soc->getNomUrl(1) . '
'; 874 | $objectsrc=new Commande($db); 875 | $objectsrc->fetch($expedition->$typeobject->id); 876 | print $langs->trans("RefOrder").''; 878 | print $objectsrc->getNomUrl(1,'commande'); 879 | print "
'; 885 | $objectsrc=new Propal($db); 886 | $objectsrc->fetch($expedition->$typeobject->id); 887 | print $langs->trans("RefProposal").''; 889 | print $objectsrc->getNomUrl(1,'expedition'); 890 | print "
' . $langs->trans("RefCustomer") . '' . $expedition->ref_customer . "
'.$langs->trans("DateCreation").''.dol_print_date($expedition->date_creation,"dayhour")."
'; 909 | print ''; 912 | 913 | print '
'; 910 | print $langs->trans('DateDeliveryPlanned'); 911 | print '
'; 914 | print '
'; 915 | print $expedition->date_delivery ? dol_print_date($expedition->date_delivery,'dayhourtext') : ' '; 916 | print '
' . $langs->trans("Status") . '' . $expedition->getLibStatut(4) . "
'; 929 | print ''; 932 | 933 | print '
'; 930 | print $langs->trans('SendingMethod'); 931 | print '
'; 934 | print '
'; 935 | if ($expedition->shipping_method_id > 0) 936 | { 937 | // Get code using getLabelFromKey 938 | $code=$langs->getLabelFromKey($db,$expedition->shipping_method_id,'c_shipment_mode','rowid','code'); 939 | print $langs->trans("SendingMethod".strtoupper($code)); 940 | } 941 | print '
\n"; 945 | } 946 | --------------------------------------------------------------------------------