├── .gitignore ├── config.php ├── img ├── plus.png ├── plus.xcf ├── ATM_logo.jpg ├── bt-save.png ├── minus16.png ├── plus16.png ├── inventory.png ├── object_inventory.png └── Dolibarr_Preferred_Partner_logo.png ├── exempleTemplate ├── templateINVENTORY.odt └── templateINVENTORY_lot.odt ├── script ├── create-maj-base.php ├── migration60.php └── interface.php ├── README ├── config.default.php ├── langs ├── en_US │ └── inventory.lang ├── en_GB │ └── inventory.lang └── fr_FR │ └── inventory.lang ├── ChangeLog.md ├── admin ├── inventory_about.php └── inventory_setup.php ├── class ├── actions_inventory.class.php └── inventory.class.php ├── lib └── inventory.lib.php ├── tpl └── inventory.tpl.php ├── core ├── modules │ └── modinventory.class.php └── triggers │ └── interface_99_modinventory_inventorytrigger.class.php └── inventory.php /.gitignore: -------------------------------------------------------------------------------- 1 | .buildpath 2 | .project 3 | .settings/ 4 | *.log 5 | /nbproject -------------------------------------------------------------------------------- /config.php: -------------------------------------------------------------------------------- 1 | debug=true; 12 | } 13 | else 14 | { 15 | $PDOdb=new TPDOdb; 16 | } 17 | 18 | dol_include_once('/inventory/class/inventory.class.php'); 19 | 20 | $o=new TInventory(); 21 | $o->init_db_by_vars($PDOdb); 22 | 23 | $o=new TInventorydet(); 24 | $o->init_db_by_vars($PDOdb); -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 ATM Consulting 3 | * 4 | * This program and files/directory inner it is free software: you can 5 | * redistribute it and/or modify it under the terms of the 6 | * GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 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 | -------------------------------------------------------------------------------- /config.default.php: -------------------------------------------------------------------------------- 1 | trans('AbricotNotFound'). ' : Abricot'; 27 | exit; 28 | } 29 | 30 | $module_helpurl='http://wiki.atm-consulting.fr/index.php/Inventaire/Documentation_utilisateur'; 31 | 32 | -------------------------------------------------------------------------------- /script/migration60.php: -------------------------------------------------------------------------------- 1 | query('ALTER TABLE '.MAIN_DB_PREFIX.'inventory CHANGE COLUMN date_maj tms timestamp'); 20 | $db->query('ALTER TABLE '.MAIN_DB_PREFIX.'inventory ADD COLUMN tms timestamp'); 21 | $db->query('UPDATE '.MAIN_DB_PREFIX.'inventory SET tms = date_maj WHERE tms IS NULL'); 22 | 23 | //$db->query('ALTER TABLE '.MAIN_DB_PREFIX.'inventorydet CHANGE COLUMN date_maj tms timestamp'); 24 | $db->query('ALTER TABLE '.MAIN_DB_PREFIX.'inventorydet ADD COLUMN tms timestamp'); 25 | $db->query('UPDATE '.MAIN_DB_PREFIX.'inventorydet SET tms = date_maj WHERE tms IS NULL'); 26 | 27 | //$db->query('ALTER TABLE '.MAIN_DB_PREFIX.'inventorydet CHANGE COLUMN date_cre datec datetime DEFAULT NULL'); 28 | $db->query('ALTER TABLE '.MAIN_DB_PREFIX.'inventorydet ADD COLUMN datec datetime DEFAULT NULL'); 29 | $db->query('UPDATE '.MAIN_DB_PREFIX.'inventorydet SET datec = date_cre WHERE datec IS NULL'); -------------------------------------------------------------------------------- /langs/en_US/inventory.lang: -------------------------------------------------------------------------------- 1 | Module104420Name = inventory 2 | Module104420Desc = inventory Descripion 3 | 4 | ATMAbout = This module has been developed by ATM Consulting
You can find the documentation on our wiki

For any question or feedback, contact us on support@atm-consulting.fr

For any commercial question, contact us on contact@atm-consulting.fr or at +33 9 77 19 50 70

Find our other modules on Dolistore 5 | 6 | inventorySetup = inventory module setup 7 | inventoryAbout = About inventory 8 | 9 | INVENTORY_DISABLE_VIRTUAL=Usefull if you don't want to unstock children product from virtual product in inventory 10 | 11 | 12 | INVENTORY_PERF_TWEAKS=Improve performance when many products exist (more than 1000) 13 | INVENTORY_PERF_TWEAKS_HELP=Pages will display much faster when creating or viewing inventories. The tradeoff is that detailed tooltips will be disabled when hovering the mouse cursor over a product ref. 14 | -------------------------------------------------------------------------------- /ChangeLog.md: -------------------------------------------------------------------------------- 1 | # Change Log 2 | All notable changes to this project will be documented in this file. 3 | 4 | ## [Unreleased] 5 | 6 | ## Version 1.11 7 | 8 | - FIX : DA021763 - Prise en compte de la date d'inventaire pour le caulcul des inventaires *2022-04-26* - 1.11.7 9 | - FIX : Bug affichage du select -Choix du filtre de catégorie- dans un nouvel inventaire *2022-01-11* - 1.11.6 10 | - FIX : Fatal error and return value for save method *2021-09-22* - 1.11.5 11 | - FIX : V13 Compatibility no token renewal *2021-05-07* - 1.11.4 12 | - FIX : PHP error for non countable element *2021-03-09* 13 | - FIX : Sort inventory's details on p.ref ASC by default *2021-03-09* - 1.11.2 14 | - FIX : V13 Compatibility action links - 1.11.1 15 | - NEW : Ajout de l'objet inventory pour fonctionnement correct des hooks pour export CSV et ODT - 1.11.0 16 | - NEW : hooks on list && hooks on CSV and ODT exports - 1.10.0 17 | 18 | ## Version 1.9 19 | 20 | ### Added 21 | 22 | - NEW : Sort lines per product 23 | - NEW : Evol product's extrafields column in inventory card 24 | - NEW : Add column "lot" in inventory's ODT 25 | - NEW : Create CSV of an inventory with batch's number 26 | - NEW : Multiple categ 27 | 28 | ### Changed 29 | 30 | - FIX : Remove unused Box - 1.9.1 31 | - FIX : Getposts in modules 32 | - FIX : Tk11498 - new option => huge performance boost by replacing/caching getNomURL() 33 | - FIX : Minus doesn't change total quantity 34 | - FIX : Tk9573 : arrondi pour éviter les valeurs de stock à 1.4210854715202E-14 35 | - FIX : Fatal error on Dolibarr <= 6.0 36 | -------------------------------------------------------------------------------- /admin/inventory_about.php: -------------------------------------------------------------------------------- 1 | 3 | * Copyright (C) 2015 ATM Consulting 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 3 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 admin/about.php 21 | * \ingroup inventory 22 | * \brief This file is an example about page 23 | * Put some comments here 24 | */ 25 | // Dolibarr environment 26 | require_once '../config.php'; 27 | 28 | // Libraries 29 | require_once DOL_DOCUMENT_ROOT . "/core/lib/admin.lib.php"; 30 | require_once '../lib/inventory.lib.php'; 31 | 32 | // Translations 33 | $langs->load("inventory@inventory"); 34 | 35 | // Access control 36 | if (! $user->admin) { 37 | accessforbidden(); 38 | } 39 | 40 | /* 41 | * View 42 | */ 43 | $page_name = "inventoryAbout"; 44 | llxHeader('', $langs->trans($page_name), $module_helpurl); 45 | 46 | // Subheader 47 | $linkback = '' 48 | . $langs->trans("BackToModuleList") . ''; 49 | print_fiche_titre($langs->trans($page_name), $linkback); 50 | 51 | // Configuration header 52 | $head = inventoryAdminPrepareHead(); 53 | dol_fiche_head( 54 | $head, 55 | 'about', 56 | $langs->trans("Module104420Name"), 57 | 0, 58 | 'inventory@inventory' 59 | ); 60 | 61 | // About page goes here 62 | print '
'; 63 | print '
'.$langs->trans('ATMAbout').'
'; 64 | 65 | dol_fiche_end(); 66 | 67 | print '
'; 68 | print ''; 69 | print '
'; 70 | 71 | llxFooter(); 72 | 73 | $db->close(); 74 | -------------------------------------------------------------------------------- /class/actions_inventory.class.php: -------------------------------------------------------------------------------- 1 | 3 | * Copyright (C) 2015 ATM Consulting 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 3 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 class/actions_inventory.class.php 21 | * \ingroup inventory 22 | * \brief This file is an example hook overload class file 23 | * Put some comments here 24 | */ 25 | 26 | /** 27 | * Class Actionsinventory 28 | */ 29 | class Actionsinventory 30 | { 31 | /** 32 | * @var array Hook results. Propagated to $hookmanager->resArray for later reuse 33 | */ 34 | public $results = array(); 35 | 36 | /** 37 | * @var string String displayed by executeHook() immediately after return 38 | */ 39 | public $resprints; 40 | 41 | /** 42 | * @var array Errors 43 | */ 44 | public $errors = array(); 45 | 46 | /** 47 | * Constructor 48 | */ 49 | public function __construct() 50 | { 51 | } 52 | 53 | /** 54 | * Overloading the doActions function : replacing the parent's function with the one below 55 | * 56 | * @param array() $parameters Hook metadatas (context, etc...) 57 | * @param CommonObject &$object The object to process (an invoice if you are in invoice module, a propale in propale's module, etc...) 58 | * @param string &$action Current action (if set). Generally create or edit or null 59 | * @param HookManager $hookmanager Hook manager propagated to allow calling another hook 60 | * @return int < 0 on error, 0 on success, 1 to replace standard code 61 | */ 62 | function doActions($parameters, &$object, &$action, $hookmanager) 63 | { 64 | $error = 0; // Error counter 65 | $myvalue = 'test'; // A result value 66 | 67 | print_r($parameters); 68 | echo "action: " . $action; 69 | print_r($object); 70 | 71 | if (in_array('somecontext', explode(':', $parameters['context']))) 72 | { 73 | // do something only for the context 'somecontext' 74 | } 75 | 76 | if (! $error) 77 | { 78 | $this->results = array('myreturn' => $myvalue); 79 | $this->resprints = 'A text to show'; 80 | return 0; // or return 1 to replace standard code 81 | } 82 | else 83 | { 84 | $this->errors[] = 'Error message'; 85 | return -1; 86 | } 87 | } 88 | } -------------------------------------------------------------------------------- /script/interface.php: -------------------------------------------------------------------------------- 1 | rights->inventory->write) { echo -1; exit; } 18 | 19 | $fk_det_inventory = GETPOST('fk_det_inventory','int'); 20 | 21 | $det = new TInventorydet; 22 | if( $det->load($PDOdb, $fk_det_inventory)) { 23 | $det->qty_view+=GETPOST('qty','int'); 24 | $det->save($PDOdb); 25 | 26 | echo $det->qty_view; 27 | } 28 | else { 29 | echo -2; 30 | } 31 | 32 | break; 33 | 34 | case 'pmp': 35 | if (!$user->rights->inventory->write || !$user->rights->inventory->changePMP) { echo -1; exit; } 36 | 37 | $fk_det_inventory = GETPOST('fk_det_inventory','int'); 38 | 39 | $det = new TInventorydet; 40 | if( $det->load($PDOdb, $fk_det_inventory)) { 41 | $det->new_pmp=price2num(GETPOST('pmp','int')); 42 | $det->save($PDOdb); 43 | 44 | echo $det->new_pmp; 45 | } 46 | else { 47 | echo -2; 48 | } 49 | 50 | break; 51 | 52 | case 'batch': 53 | if (!$user->rights->inventory->write) { echo -1; exit; } 54 | 55 | $index = (int)GETPOST('index','int'); 56 | $lot = GETPOST('batch','alpha'); 57 | $qty = (float)GETPOST('qty','int'); 58 | 59 | // id de l'inventaire 60 | $fk_inventory = (int)GETPOST('fk_inventory','int'); 61 | $inv = new TInventory(); 62 | $inv->load($PDOdb, $fk_inventory); 63 | 64 | // ajouter une ligne copie de la dernière ligne de l'inventaire 65 | 66 | 67 | $k = $inv->addChild($PDOdb, 'TInventorydet'); 68 | $det = &$inv->TInventorydet[$k]; 69 | 70 | // echo '
'; print_r($inv->TInventorydet[$index]->id); exit;
71 |             $det->fk_inventory = $inv->getId();
72 |             $det->fk_product = $inv->TInventorydet[$index]->fk_product;
73 |             $det->fk_warehouse = $inv->TInventorydet[$index]->fk_warehouse;
74 | //             //        var_dump($det);exit;
75 |             $det->load_product();
76 |             $det->lot = $lot;
77 |             $det->qty_view = $qty;
78 |             $inv->save($PDOdb);
79 |                         
80 |             echo 1;
81 |             
82 |             break;
83 |     }
84 |  
85 | 


--------------------------------------------------------------------------------
/langs/en_GB/inventory.lang:
--------------------------------------------------------------------------------
 1 | Module104420Name = Inventory
 2 | Module104420Desc = Allows inventory of different warehouses
 3 | 
 4 | ATMAbout = This module has been developed by ATM Consulting
You can find the documentation on our wiki

For any question or feedback, contact us on support@atm-consulting.fr

For any commercial question, contact us on contact@atm-consulting.fr or at +33 9 77 19 50 70

Find our other modules on Dolistore 5 | 6 | inventorySetup = Inventory module setup 7 | inventoryAbout = About Inventory 8 | 9 | inventoryCreatePermission=Create New Inventory 10 | inventoryReadPermission=Read Inventories 11 | inventoryWritePermission=Modify Inventories 12 | inventoryValidatePermission=Validate Inventories 13 | 14 | inventoryTitle=Stock Inventory 15 | inventoryListTitle=List of Inventories 16 | inventoryListEmpty=There are no inventory in progress 17 | 18 | inventoryCreateDelete=Create / delete a new inventory 19 | inventoryCreate=Create Inventory 20 | inventoryEdit=Editing an inventory 21 | inventoryValidate=Validate 22 | inventoryDraft=In progress 23 | inventorySelectWarehouse=Select warehouse 24 | inventoryConfirmCreate=Create an inventory 25 | inventoryOfWarehouse=Inventory of warehouse : %s 26 | inventoryErrorQtyAdd=Error: at least one of the quantities entered is less than 0 27 | inventoryMvtStock=Inventory N°%s 28 | inventoryMvtStockWithNomInventaire=%s 29 | inventoryWarningProductAlreadyExists=The product already exists in the list 30 | INVENTORY_GEN_PDF=Generate the document inventory in PDF (requires the presence of LibreOffice Writer on the server) 31 | SelectCategory=Select Category 32 | SelectFournisseur=Select Supplier 33 | inventoryOnDate=Inventory on 34 | INVENTORY_DISABLE_VIRTUAL=Usefull if you don't want to unstock children product from virtual product in inventory 35 | INVENTORY_USE_MIN_PA_IF_NO_LAST_PA=Giving the valuation with the current purchase price on last PA zero 36 | INVENTORY_USE_INVENTORY_DATE_FROM_DATEMVT=Date Inventory Movements as of Inventory Date 37 | INVENTORY_NB_PRODUCT_IN_SELECT=Number of product visible in the drop-down list (0 = no limit) if the parameterization of the product module does not use auto-completion 38 | inventoryChangePMPPermission=Change the value of a product's PMP 39 | ColumnNewPMP=New unit PMP 40 | OnlyProdsInStock=Do not include products that do not have stock in the selected warehouse 41 | IncludeProdWithCurrentStockValue=Integrate products with their current stock and PMP 42 | INVENTORY_USE_MIN_PA_OR_LAST_PA_MIN_PMP_IS_NULL=Use the last purchase price or the minimum for PMP in case of no MPP 43 | UsePAifnull=Uses the purchase price if null 44 | 45 | Numero=Ref 46 | Entrepot=Warehouse 47 | DateInventaire=Inventory Date 48 | DateCreation=Created 49 | DateUpdated=Date Updated 50 | Status=Status 51 | ThisIsNotAProduct=This item is not a product 52 | inventoryOnDate= 53 | inventoryDeleteLine=Delete line 54 | MyBoxDescription=Inventory Activities 55 | MyBoxContent=MyBoxContent 56 | MyBox=MyBox -------------------------------------------------------------------------------- /langs/fr_FR/inventory.lang: -------------------------------------------------------------------------------- 1 | Module104420Name = Inventaire 2 | Module104420Desc = Permet de faire l'inventaire des différents entrepôts 3 | 4 | ATMAbout = Ce module a été développé par ATM Consulting
Vous pouvez retrouver la documentation sur notre wiki

Pour toute question technique ou retour, contactez-nous sur support@atm-consulting.fr

Pour toute question commerciale, contactez-nous sur contact@atm-consulting.fr ou au +33 9 77 19 50 70

Retrouvez nos autres modules sur Dolistore 5 | 6 | inventorySetup = Configuration du module inventaire 7 | inventoryAbout = A propos du module inventaire 8 | 9 | inventoryCreatePermission=Créer un nouvel inventaire 10 | inventoryReadPermission=Consulter les inventaires 11 | inventoryWritePermission=Modifier les inventaires 12 | inventoryValidatePermission=Valider les inventaires 13 | 14 | inventoryTitle=Inventaire 15 | inventoryListTitle=Liste des inventaires 16 | inventoryListEmpty=Il n'y a aucun inventaire en cours 17 | 18 | inventoryCreateDelete=Créer/supprimer un nouvel inventaire 19 | inventoryCreate=Créer un nouvel inventaire 20 | inventoryEdit=Edition d'un inventaire 21 | inventoryValidate=Validé 22 | inventoryDraft=En cours 23 | inventorySelectWarehouse=Choix de l'entrepôt 24 | inventoryConfirmCreate=Créer un inventaire 25 | inventoryOfWarehouse=Inventaire de l'entrepôt : %s 26 | inventoryErrorQtyAdd=Erreur : au moins une des quantités saisie est inférieure à 0 27 | inventoryMvtStock=Inventaire n°%s 28 | inventoryMvtStockWithNomInventaire=%s 29 | inventoryWarningProductAlreadyExists=Le produit existe déjà dans la liste 30 | INVENTORY_GEN_PDF=Générer le document inventaire en PDF (nécessite la présence de libreoffice Writer sur le serveur) 31 | SelectCategory=Choix du filtre de catégorie 32 | SelectFournisseur=Choix du filtre de fournisseur 33 | inventoryOnDate=Inventaire au 34 | INVENTORY_DISABLE_VIRTUAL=Permet de ne pas déstocker les produits enfants des produits virtualisés lors de l'inventaire 35 | INVENTORY_USE_MIN_PA_IF_NO_LAST_PA=Donner la valorisation avec le prix d'achat courrant sur dernier PA nul 36 | INVENTORY_USE_INVENTORY_DATE_FROM_DATEMVT=Dater les mouvements d'inventaire à date de l'inventaire 37 | INVENTORY_NB_PRODUCT_IN_SELECT=Nombre de produit visible dans la liste déroulante (0 = pas de limite) si le paramétrage du module produit n'utilise pas l'auto-complétion 38 | inventoryChangePMPPermission=Changer la valeur du PMP d'un produit 39 | ColumnNewPMP=Nouveau PMP 40 | OnlyProdsInStock=Ne pas intégrer les produits qui n'ont pas de stock dans l'entrepôt sélectionné 41 | IncludeProdWithCurrentStockValue=Intégrer les produits avec leur stock actuel et PMP 42 | INVENTORY_USE_MIN_PA_OR_LAST_PA_MIN_PMP_IS_NULL=Utiliser le dernier prix d'achat ou le minimal pour PMP en cas de PMP nul 43 | UsePAifnull=Utilise le prix d'achat si null 44 | InventoryWithBatchDetail=Faire l'inventaire par numeros de lot 45 | INVENTORY_USE_ONLY_INTEGER=Restrindre la saisie des quantités sur un mode unitaire (virgule non acceptée) 46 | 47 | INVENTORY_PERF_TWEAKS=Optimiser la performance pour de nombreux produits (plus de 1000) 48 | INVENTORY_PERF_TWEAKS_HELP=La création et la consultation des inventaires sera beaucoup plus rapide, mais il n'y aura plus d'infobulle au survol du produit. 49 | InventoryModuleNotAvailable = Module inventaire non disponible 50 | -------------------------------------------------------------------------------- /admin/inventory_setup.php: -------------------------------------------------------------------------------- 1 | 3 | * Copyright (C) 2015 ATM Consulting 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 3 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 admin/inventory.php 21 | * \ingroup inventory 22 | * \brief This file is an example module setup page 23 | * Put some comments here 24 | */ 25 | // Dolibarr environment 26 | require_once '../config.php'; 27 | 28 | // Libraries 29 | require_once DOL_DOCUMENT_ROOT . "/core/lib/admin.lib.php"; 30 | require_once '../lib/inventory.lib.php'; 31 | 32 | // Translations 33 | $langs->load("inventory@inventory"); 34 | 35 | // Access control 36 | if (! $user->admin) { 37 | accessforbidden(); 38 | } 39 | 40 | // Parameters 41 | $action = GETPOST('action', 'alpha'); 42 | 43 | /* 44 | * Actions 45 | */ 46 | if (preg_match('/set_(.*)/',$action,$reg)) 47 | { 48 | $code=$reg[1]; 49 | if (dolibarr_set_const($db, $code, GETPOST($code,'none'), 'chaine', 0, '', $conf->entity) > 0) 50 | { 51 | header("Location: ".$_SERVER["PHP_SELF"]); 52 | exit; 53 | } 54 | else 55 | { 56 | dol_print_error($db); 57 | } 58 | } 59 | 60 | if (preg_match('/del_(.*)/',$action,$reg)) 61 | { 62 | $code=$reg[1]; 63 | if (dolibarr_del_const($db, $code, 0) > 0) 64 | { 65 | Header("Location: ".$_SERVER["PHP_SELF"]); 66 | exit; 67 | } 68 | else 69 | { 70 | dol_print_error($db); 71 | } 72 | } 73 | 74 | /* 75 | * View 76 | */ 77 | $page_name = "inventorySetup"; 78 | llxHeader('', $langs->trans($page_name), $module_helpurl); 79 | 80 | // Subheader 81 | $linkback = '' 82 | . $langs->trans("BackToModuleList") . ''; 83 | print_fiche_titre($langs->trans($page_name), $linkback); 84 | 85 | // Configuration header 86 | $head = inventoryAdminPrepareHead(); 87 | dol_fiche_head( 88 | $head, 89 | 'settings', 90 | $langs->trans("Module104420Name"), 91 | -1, 92 | "inventory@inventory" 93 | ); 94 | 95 | // Setup page goes here 96 | $form=new Form($db); 97 | $var=false; 98 | print ''; 99 | print ''; 100 | print ''."\n"; 101 | print ''; 102 | print ''."\n"; 103 | 104 | 105 | // Example with a yes / no select 106 | $var=!$var; 107 | print ''; 108 | print ''; 109 | print ''; 110 | print ''; 118 | 119 | // Example with a yes / no select 120 | $var=!$var; 121 | print ''; 122 | print ''; 123 | print ''; 124 | print ''; 132 | 133 | // Example with a yes / no select 134 | $var=!$var; 135 | print ''; 136 | print ''; 137 | print ''; 138 | print ''; 146 | 147 | $var=!$var; 148 | print ''; 149 | print ''; 150 | print ''; 151 | print ''; 159 | 160 | 161 | // Example with a yes / no select 162 | $var=!$var; 163 | print ''; 164 | print ''; 165 | print ''; 166 | print ''; 174 | 175 | $var=!$var; 176 | print ''; 177 | print ''; 178 | print ''; 179 | print ''; 187 | 188 | $var=!$var; 189 | print ''; 190 | print ''; 191 | print ''; 192 | print ''; 195 | 196 | $var=!$var; 197 | print ''; 198 | print ''; 202 | print ''; 203 | print ''; 206 | 207 | print '
'.$langs->trans("Parameters").' '.$langs->trans("Value").'
'.$langs->trans("INVENTORY_GEN_PDF").' '; 111 | print '
'; 112 | print ''; 113 | print ''; 114 | print $form->selectyesno("INVENTORY_GEN_PDF",$conf->global->INVENTORY_GEN_PDF,1); 115 | print ''; 116 | print '
'; 117 | print '
'.$langs->trans("INVENTORY_DISABLE_VIRTUAL").' '; 125 | print '
'; 126 | print ''; 127 | print ''; 128 | print $form->selectyesno("INVENTORY_DISABLE_VIRTUAL",$conf->global->INVENTORY_DISABLE_VIRTUAL,1); 129 | print ''; 130 | print '
'; 131 | print '
'.$langs->trans("INVENTORY_USE_MIN_PA_IF_NO_LAST_PA").' '; 139 | print '
'; 140 | print ''; 141 | print ''; 142 | print $form->selectyesno("INVENTORY_USE_MIN_PA_IF_NO_LAST_PA",$conf->global->INVENTORY_USE_MIN_PA_IF_NO_LAST_PA,1); 143 | print ''; 144 | print '
'; 145 | print '
'.$langs->trans("INVENTORY_USE_MIN_PA_OR_LAST_PA_MIN_PMP_IS_NULL").' '; 152 | print '
'; 153 | print ''; 154 | print ''; 155 | print $form->selectyesno("INVENTORY_USE_MIN_PA_OR_LAST_PA_MIN_PMP_IS_NULL",$conf->global->INVENTORY_USE_MIN_PA_OR_LAST_PA_MIN_PMP_IS_NULL,1); 156 | print ''; 157 | print '
'; 158 | print '
'.$langs->trans("INVENTORY_USE_INVENTORY_DATE_FROM_DATEMVT").' '; 167 | print '
'; 168 | print ''; 169 | print ''; 170 | print $form->selectyesno("INVENTORY_USE_INVENTORY_DATE_FROM_DATEMVT",$conf->global->INVENTORY_USE_INVENTORY_DATE_FROM_DATEMVT,1); 171 | print ''; 172 | print '
'; 173 | print '
'.$langs->trans("INVENTORY_NB_PRODUCT_IN_SELECT").' '; 180 | print '
'; 181 | print ''; 182 | print ''; 183 | print ''; 184 | print ''; 185 | print '
'; 186 | print '
'.$langs->trans('INVENTORY_USE_ONLY_INTEGER').' '; 193 | print ajax_constantonoff('INVENTORY_USE_ONLY_INTEGER'); 194 | print '
' 199 | .$langs->trans('INVENTORY_PERF_TWEAKS') 200 | .'
' . $langs->trans('INVENTORY_PERF_TWEAKS_HELP') . '' 201 | .'
 '; 204 | print ajax_constantonoff('INVENTORY_PERF_TWEAKS'); 205 | print '
'; 208 | 209 | dol_fiche_end(-1); 210 | 211 | llxFooter(); 212 | 213 | $db->close(); 214 | -------------------------------------------------------------------------------- /lib/inventory.lib.php: -------------------------------------------------------------------------------- 1 | 3 | * Copyright (C) 2015 ATM Consulting 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 3 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 lib/inventory.lib.php 21 | * \ingroup inventory 22 | * \brief This file is an example module library 23 | * Put some comments here 24 | */ 25 | 26 | function inventoryAdminPrepareHead() 27 | { 28 | global $langs, $conf; 29 | 30 | $langs->load("inventory@inventory"); 31 | 32 | $h = 0; 33 | $head = array(); 34 | 35 | $head[$h][0] = dol_buildpath("/inventory/admin/inventory_setup.php", 1); 36 | $head[$h][1] = $langs->trans("Parameters"); 37 | $head[$h][2] = 'settings'; 38 | $h++; 39 | $head[$h][0] = dol_buildpath("/inventory/admin/inventory_about.php", 1); 40 | $head[$h][1] = $langs->trans("About"); 41 | $head[$h][2] = 'about'; 42 | $h++; 43 | 44 | // Show more tabs from modules 45 | // Entries must be declared in modules descriptor with line 46 | //$this->tabs = array( 47 | // 'entity:+tabname:Title:@inventory:/inventory/mypage.php?id=__ID__' 48 | //); // to add new tab 49 | //$this->tabs = array( 50 | // 'entity:-tabname:Title:@inventory:/inventory/mypage.php?id=__ID__' 51 | //); // to remove a tab 52 | complete_head_from_modules($conf, $langs, $object, $head, $h, 'inventory'); 53 | 54 | return $head; 55 | } 56 | 57 | function inventoryPrepareHead(&$inventory, $title='Inventaire', $get='') 58 | { 59 | return array( 60 | array(dol_buildpath('/inventory/inventory.php?id='.$inventory->getId().$get, 1), $title,'inventaire') 61 | ); 62 | } 63 | 64 | 65 | 66 | function inventorySelectProducts(&$PDOdb, &$inventory) 67 | { 68 | global $conf,$db; 69 | 70 | $except_product_id = array(); 71 | 72 | foreach ($inventory->TInventorydet as $TInventorydet) 73 | { 74 | $except_product_id[] = $TInventorydet->fk_product; 75 | } 76 | 77 | ob_start(); 78 | $form = new Form($db); 79 | $form->select_produits(-1, 'fk_product', 0, (int) $conf->global->INVENTORY_NB_PRODUCT_IN_SELECT,0,-1); 80 | 81 | // Il nous faut impérativement une liste custom car il ne faut que les entrepôts de la famille de celui qu'on inventorie 82 | $TChildWarehouses = array($inventory->fk_warehouse); 83 | $e = new Entrepot($db); 84 | $e->fetch($inventory->fk_warehouse); 85 | if(method_exists($e, 'get_children_warehouses')) $e->get_children_warehouses($e->id, $TChildWarehouses); 86 | 87 | $Tab = array(); 88 | $sql = 'SELECT rowid, '.((float)DOL_VERSION >= 7 ? 'ref' : 'label').' 89 | FROM '.MAIN_DB_PREFIX.'entrepot WHERE rowid IN('.implode(', ', $TChildWarehouses).')'; 90 | if(method_exists($e, 'get_children_warehouses')) $sql.= ' ORDER BY fk_parent'; 91 | $resql = $db->query($sql); 92 | while($res = $db->fetch_object($resql)) { 93 | $Tab[$res->rowid] = (float)DOL_VERSION >= 7 ? $res->ref : $res->label; 94 | } 95 | print '   '; 96 | print 'Entrepôt : '.$form::selectarray('fk_warehouse', $Tab); 97 | 98 | $select_html = ob_get_clean(); 99 | 100 | /* 101 | 102 | $sql = 'SELECT rowid, ref, label FROM '.MAIN_DB_PREFIX.'product WHERE fk_product_type = 0 AND rowid NOT IN ('.implode(',', $except_product_id).') ORDER BY ref, label'; 103 | $PDOdb->Execute($sql); 104 | 105 | if (! empty($conf->use_javascript_ajax) && ! empty($conf->global->PRODUIT_USE_SEARCH_TO_SELECT)) 106 | { 107 | $urloption='htmlname=fk_product&outjson=1&price_level=0&type=0&mode=1&status=1&finished=2'; 108 | 109 | print ajaxAutocompleter('', 'fk_product', DOL_URL_ROOT.'/product/ajax/products.php', $urloption, $conf->global->PRODUIT_USE_SEARCH_TO_SELECT, 0, array()); 110 | 111 | $select_html = ''; 112 | } 113 | else 114 | { 115 | $select_html = ''; 121 | } 122 | */ 123 | return $select_html; 124 | } 125 | 126 | function ajaxAutocompleter($selected, $htmlname, $url, $urloption='', $minLength=2, $autoselect=0, $ajaxoptions=array()) 127 | { 128 | if (empty($minLength)) $minLength=1; 129 | 130 | $script = ''; 131 | 132 | $script.= ''; 266 | 267 | return $script; 268 | } 269 | -------------------------------------------------------------------------------- /tpl/inventory.tpl.php: -------------------------------------------------------------------------------- 1 | 244 | 245 | 246 | Ajouter un produit dans l'inventaire : 247 |
248 | 249 | 250 | 251 | 252 | 253 | 254 |
255 | 256 | 257 |
258 | 259 | 260 |
Cet inventaire est validé
261 | 262 | 263 | 264 | 265 | 266 | 267 | 268 | 269 | 270 | $row) { 277 | 278 | $total_pmp+=round($row['pmp_stock'],2); 279 | $total_pa+=round($row['pa_stock'],2); 280 | $total_pmp_actual+=round($row['pmp_actual'],2); 281 | $total_pa_actual+=round($row['pa_actual'],2); 282 | 283 | if($i%20 === 0) 284 | { 285 | _headerList($view); 286 | } // Fin IF principal 287 | ?> 288 | 289 | 290 | 291 | barcode->enabled)) { ?> 292 | 293 | 294 | 295 | 296 | 297 | 298 | 299 | 300 | 301 | global->INVENTORY_USE_MIN_PA_IF_NO_LAST_PA)){ 303 | echo ''; 304 | $total_current_pa+=$row['current_pa_stock']; 305 | } 306 | 307 | ?> 308 | 309 | 312 | 313 | 314 | rights->inventory->changePMP)) { 316 | echo ''; 317 | } 318 | ?> 319 | 320 | global->INVENTORY_USE_MIN_PA_IF_NO_LAST_PA)){ 322 | echo ''; 323 | $total_current_pa_actual+=$row['current_pa_actual']; 324 | } 325 | 326 | ?> 327 | 328 | 329 | $arrayfields, 'k' => $k, 'line' => $row); 334 | $reshook=$hookmanager->executeHooks('printFieldListValue',$parameters, $inventory); // Note that $action and $object may have been modified by hook 335 | print $hookmanager->resPrint; 336 | 337 | //définition de l'objet à afficher pour le tpl extrafields_list_print_fields 338 | $object = new Product($db); //produit 339 | $object->fetch($row['fk_product']); 340 | $obj = (object) $object->array_options; //extrafields du produit 341 | 342 | if(intval(DOL_VERSION) > 6 ) { 343 | include DOL_DOCUMENT_ROOT . '/core/tpl/extrafields_list_print_fields.tpl.php'; 344 | } 345 | ?> 346 | 347 | 348 | 351 | 352 | 353 | 354 | 360 | 361 | 362 | 363 |
  '.price($row['current_pa_stock']).'   310 | 311 | '.$row['pmp_new'].''.price($row['current_pa_actual']).'
364 | 365 | 366 |
367 | 368 | Imprimer 369 | Export CSV 370 | Modifier 371 | rights->inventory->changePMP)) { 373 | echo 'Appliquer le PMP'; 376 | } 377 | 378 | if ($view['can_validate'] == 1) { ?> 379 | Réguler le stock 380 | 381 | 382 | 383 | 384 | 385 | 389 | Vider 390 |     391 | Supprimer 392 | 393 |
394 | 395 | 396 |
397 | 398 | Imprimer 399 | Export CSV 400 | 401 | Supprimer 402 | 403 |
404 | 405 |
406 |

Date de création :
Dernière mise à jour :

407 | 408 | 418 | 419 | -------------------------------------------------------------------------------- /class/inventory.class.php: -------------------------------------------------------------------------------- 1 | set_table( MAIN_DB_PREFIX.'inventory' ); 12 | 13 | $this->add_champs('fk_warehouse,entity,status,per_batch',array('type'=>'integer','index'=>true)); 14 | $this->add_champs('date_inventory',array('type'=>'date')); 15 | $this->add_champs('title'); 16 | 17 | $this->_init_vars(); 18 | 19 | $this->start(); 20 | 21 | $this->setChild('TInventorydet','fk_inventory'); 22 | 23 | $this->status = 0; 24 | $this->entity = $conf->entity; 25 | $this->errors = array(); 26 | $this->amount = 0; 27 | 28 | } 29 | 30 | function sort_det() 31 | { 32 | // usort($this->TInventorydet, array('TInventory', 'customSort')); 33 | usort($this->TInventorydet, array('TInventory', 'orderSort')); 34 | // FIX TK11812 : PR https://github.com/ATM-Consulting/dolibarr_module_inventory/pull/37 35 | if ($this->per_batch && !empty($this->TInventorydet)) 36 | { 37 | $tmpTab = array(); 38 | foreach ($this->TInventorydet as $invDet) 39 | { 40 | if (!array_key_exists($invDet->fk_product, $tmpTab)) 41 | { 42 | $tmpTab[$invDet->fk_product] = array(); 43 | } 44 | 45 | if (empty($invDet->lot)) $tmpTab[$invDet->fk_product][0] = $invDet; 46 | else if (empty($tmpTab[$invDet->fk_product])) $tmpTab[$invDet->fk_product][1] = $invDet; 47 | else $tmpTab[$invDet->fk_product][] = $invDet; 48 | } 49 | 50 | $this->TInventorydet = array(); 51 | foreach ($tmpTab as $produitId => $lines) 52 | { 53 | ksort($lines); 54 | $count = count($lines); 55 | for( $i = 0; $i < $count; $i++) $this->TInventorydet[] = $lines[$i]; 56 | } 57 | } 58 | 59 | } 60 | 61 | function load(&$PDOdb, $id,$annexe = true) 62 | { 63 | 64 | if(!$annexe) $this->withChild = false; 65 | 66 | $res = parent::load($PDOdb, $id); 67 | $this->sort_det(); 68 | 69 | $this->amount = 0; 70 | foreach($this->TInventorydet as &$det){ 71 | $this->amount+=$det->qty_view * $det->pmp; 72 | } 73 | 74 | return $res; 75 | } 76 | 77 | 78 | function customSort(&$objA, &$objB) 79 | { 80 | global $db; 81 | 82 | $r = strcmp(strtoupper(trim($objA->product->ref)), strtoupper(trim($objB->product->ref))); 83 | 84 | if ($r < 0) $r = -1; 85 | elseif ($r > 0) $r = 1; 86 | else $r = 0; 87 | 88 | return $r; 89 | } 90 | 91 | function orderSort(&$objA, &$objB){ 92 | 93 | //champs à trier 94 | $sortfield = GETPOST('sortfield','alpha'); 95 | 96 | $TFieldparts = explode('.', $sortfield, 2); 97 | $fieldtype = $TFieldparts[0]; 98 | $fieldname = $TFieldparts[1]; 99 | 100 | if(GETPOST('sortorder','alpha') == 'desc') { //tri decroissant 101 | 102 | if($fieldtype == 'ef') //extrafield 103 | { 104 | $r = strcmp(strtoupper(trim($objA->product->array_options['options_'.$fieldname])), strtoupper(trim($objB->product->array_options['options_'.$fieldname]))); 105 | 106 | if ($r > 0) $r = -1; 107 | elseif ($r < 0) $r = 1; 108 | else $r = 0; 109 | 110 | return $r; 111 | 112 | } 113 | else if ($fieldtype == 'd') 114 | { 115 | $r = strcmp(strtoupper(trim($objA->$fieldname)), strtoupper(trim($objB->$fieldname))); 116 | 117 | if ($r > 0) $r = -1; 118 | elseif ($r < 0) $r = 1; 119 | else $r = 0; 120 | 121 | return $r; 122 | } 123 | else 124 | { 125 | 126 | $r = strcmp(strtoupper(trim($objA->product->$fieldname)), strtoupper(trim($objB->product->$fieldname))); 127 | 128 | if ($r > 0) $r = -1; 129 | elseif ($r < 0) $r = 1; 130 | else $r = 0; 131 | 132 | return $r; 133 | } 134 | 135 | } elseif (GETPOST('sortorder','alpha') == 'asc') { //tri croissant 136 | 137 | if($fieldtype == 'ef') //extrafield 138 | { 139 | $r = strcmp(strtoupper(trim($objA->product->array_options['options_'.$fieldname])), strtoupper(trim($objB->product->array_options['options_'.$fieldname]))); 140 | 141 | if ($r < 0) $r = -1; 142 | elseif ($r > 0) $r = 1; 143 | else $r = 0; 144 | 145 | return $r; 146 | 147 | } 148 | else if ($fieldtype == 'd') 149 | { 150 | $r = strcmp(strtoupper(trim($objA->$fieldname)), strtoupper(trim($objB->$fieldname))); 151 | 152 | if ($r < 0) $r = -1; 153 | elseif ($r > 0) $r = 1; 154 | else $r = 0; 155 | 156 | return $r; 157 | } 158 | else 159 | { 160 | $r = strcmp(strtoupper(trim($objA->product->$fieldname)), strtoupper(trim($objB->product->$fieldname))); 161 | 162 | if ($r < 0) $r = -1; 163 | elseif ($r > 0) $r = 1; 164 | else $r = 0; 165 | 166 | return $r; 167 | } 168 | } 169 | 170 | } 171 | 172 | function changePMP(&$PDOdb) { 173 | 174 | foreach ($this->TInventorydet as $k => &$TInventorydet) 175 | { 176 | 177 | if($TInventorydet->new_pmp>0) { 178 | $TInventorydet->pmp = $TInventorydet->new_pmp; 179 | $TInventorydet->new_pmp = 0; 180 | 181 | $PDOdb->Execute("UPDATE ".MAIN_DB_PREFIX."product as p SET pmp = ".$TInventorydet->pmp." 182 | WHERE rowid = ".$TInventorydet->fk_product ); 183 | 184 | if((float)DOL_VERSION<4.0) { 185 | 186 | $PDOdb->Execute("UPDATE ".MAIN_DB_PREFIX."product_stock SET pmp=".$TInventorydet->pmp." 187 | WHERE fk_entrepot = ".$this->fk_warehouse." AND fk_product = ".$TInventorydet->fk_product) ; 188 | 189 | } 190 | 191 | } 192 | } 193 | 194 | parent::save($PDOdb); 195 | 196 | } 197 | 198 | function save(&$PDOdb) 199 | { 200 | //si on valide l'inventaire on sauvegarde le stock à cette instant 201 | if ($this->status) 202 | { 203 | $this->regulate($PDOdb); 204 | } 205 | 206 | return parent::save($PDOdb); 207 | } 208 | 209 | function set_values($Tab) 210 | { 211 | global $db,$langs; 212 | 213 | if (isset($Tab['qty_to_add'])) 214 | { 215 | foreach ($Tab['qty_to_add'] as $k => $qty) 216 | { 217 | $qty = (float) price2num($qty); 218 | 219 | if ($qty < 0) 220 | { 221 | $this->errors[] = $langs->trans('inventoryErrorQtyAdd'); 222 | return 0; 223 | } 224 | 225 | $product = new Product($db); 226 | $product->fetch($this->TInventorydet[$k]->fk_product); 227 | 228 | $this->TInventorydet[$k]->pmp = $product->pmp; 229 | $this->TInventorydet[$k]->qty_view += $qty; 230 | } 231 | } 232 | 233 | return parent::set_values($Tab); 234 | } 235 | 236 | function deleteAllLine(&$PDOdb) { 237 | 238 | foreach($this->TInventorydet as &$det) { 239 | $det->to_delete = true; 240 | } 241 | 242 | $this->save($PDOdb); 243 | 244 | $this->TInventorydet=array(); 245 | 246 | } 247 | 248 | function add_product(&$PDOdb, $fk_product, $fk_entrepot='', $addWithCurrentDetails = false) { 249 | global $langs; 250 | if(empty($fk_product)) { 251 | setEventMessages($langs->trans('ErrorNoSelectedProductToAdd'), 'errors'); 252 | return false; 253 | } 254 | 255 | $k = $this->addChild($PDOdb, 'TInventorydet'); 256 | $det = &$this->TInventorydet[$k]; 257 | 258 | $det->fk_inventory = $this->getId(); 259 | $det->fk_product = $fk_product; 260 | $det->fk_warehouse = empty($fk_entrepot) ? $this->fk_warehouse : $fk_entrepot; 261 | // var_dump($det);exit; 262 | $det->load_product(); 263 | 264 | if($addWithCurrentDetails) { 265 | $det->product->load_stock(); 266 | $det->qty_view = $det->product->stock_warehouse[$fk_entrepot]->real; 267 | $det->new_pmp= $det->product->pmp; 268 | } 269 | 270 | $date = $this->get_date('date_inventory', 'Y-m-d'); 271 | if(empty($date))$date = $this->get_date('date_cre', 'Y-m-d'); 272 | $det->setStockDate($PDOdb, $date , $fk_entrepot); 273 | 274 | } 275 | 276 | function add_batch(&$PDOdb, $fk_product, $fk_entrepot='', $date, $addWithCurrentDetails = false) { 277 | global $langs, $db; 278 | if(empty($fk_product)) { 279 | setEventMessages($langs->trans('ErrorNoSelectedProductToAdd'), 'errors'); 280 | return false; 281 | } 282 | $prod = new Product($db); 283 | $prod->fetch($fk_product); 284 | $prod->load_stock(); 285 | 286 | $detailLot = $prod->stock_warehouse[$fk_entrepot]->detail_batch; 287 | // var_dump($detailLot); exit; 288 | //On récupère tous les mouvements de stocks du produit entre aujourd'hui et la date de l'inventaire 289 | $sql = "SELECT value, price, batch 290 | FROM ".MAIN_DB_PREFIX."stock_mouvement 291 | WHERE fk_product = ".$fk_product." 292 | AND fk_entrepot = ".$fk_entrepot." 293 | AND datem > '".date('Y-m-d 23:59:59',strtotime($date))."' 294 | ORDER BY datem DESC"; 295 | 296 | // echo $sql.'
'; exit; 297 | $PDOdb->Execute($sql); 298 | $TMouvementStock = $PDOdb->Get_All(); 299 | 300 | $laststock = $stock; 301 | $lastpmp = $pmp; 302 | //Pour chacun des mouvements on recalcule le PMP et le stock physique 303 | foreach($TMouvementStock as $mouvement){ 304 | 305 | $price = ($mouvement->price>0 && $mouvement->value>0) ? $mouvement->price : $lastpmp; // prix du mouvement si positif 306 | 307 | $stock_value = $laststock * $lastpmp; // valeur du stock 308 | 309 | $laststock -= $mouvement->value; // recalcul du stock en fonction du mouvement 310 | $detailLot[$mouvement->batch]->qty -= $mouvement->value; 311 | $last_stock_value = $stock_value - ($mouvement->value * $price); // valorisation du stock en fonction du mouvement 312 | if($last_stock_value < 0) $last_stock_value = 0; 313 | 314 | //if($last_stock_value<0 || $laststock<0) null; 315 | $lastpmp = ($laststock != 0) ? $last_stock_value / $laststock : $lastpmp; // S'il y a un stock, alors son PMP est sa valeur totale / nombre de pièce 316 | 317 | } 318 | 319 | $total_qty = 0; 320 | if (!empty($detailLot)){ 321 | foreach ($detailLot as $lot => $detail) 322 | { 323 | // var_dump($lot, $detail);exit; 324 | $k = $this->addChild($PDOdb, 'TInventorydet'); 325 | $det = &$this->TInventorydet[$k]; 326 | 327 | $det->fk_inventory = $this->getId(); 328 | $det->fk_product = $fk_product; 329 | $det->fk_warehouse = empty($fk_entrepot) ? $this->fk_warehouse : $fk_entrepot; 330 | // var_dump($det);exit; 331 | $det->load_product(); 332 | $det->lot = $lot; 333 | $det->qty_stock = $detail->qty; 334 | $total_qty += $detail->qty; 335 | 336 | if($addWithCurrentDetails) { 337 | $det->product->load_stock(); 338 | $det->qty_view = $detail->qty; 339 | $det->new_pmp= $det->product->pmp; 340 | } 341 | 342 | $date = $this->get_date('date_inventory', 'Y-m-d'); 343 | if(empty($date))$date = $this->get_date('date_cre', 'Y-m-d'); 344 | // $det->setStockDate($PDOdb, $date , $fk_entrepot); 345 | } 346 | } 347 | // var_dump((float) $total_qty, (float) $prod->stock_warehouse[$fk_entrepot]->real); exit; 348 | if ((float) $total_qty !== (float) $prod->stock_warehouse[$fk_entrepot]->real) 349 | { 350 | $k = $this->addChild($PDOdb, 'TInventorydet'); 351 | $det = &$this->TInventorydet[$k]; 352 | 353 | $det->fk_inventory = $this->getId(); 354 | $det->fk_product = $fk_product; 355 | $det->fk_warehouse = empty($fk_entrepot) ? $this->fk_warehouse : $fk_entrepot; 356 | // var_dump($det);exit; 357 | $det->load_product(); 358 | $det->lot = "NA"; 359 | $det->qty_stock = (float) $prod->stock_warehouse[$fk_entrepot]->real - $total_qty; 360 | 361 | if($addWithCurrentDetails) { 362 | $det->product->load_stock(); 363 | $det->qty_view = $det->product->stock_warehouse[$fk_entrepot]->real; 364 | $det->new_pmp= $det->product->pmp; 365 | } 366 | } 367 | 368 | } 369 | 370 | function correct_stock($fk_product, $id_entrepot, $nbpiece, $movement, $label='', $price=0, $inventorycode='', $batch='') 371 | { 372 | global $conf, $db, $langs, $user; 373 | 374 | /* duplication method product to add datem */ 375 | if ($id_entrepot) 376 | { 377 | $db->begin(); 378 | 379 | require_once DOL_DOCUMENT_ROOT .'/product/stock/class/mouvementstock.class.php'; 380 | 381 | $op[0] = "+".trim($nbpiece); 382 | $op[1] = "-".trim($nbpiece); 383 | 384 | $datem = empty($conf->global->INVENTORY_USE_INVENTORY_DATE_FROM_DATEMVT) ? dol_now() : $this->date_inventory; 385 | 386 | $movementstock=new MouvementStock($db); 387 | if ($batch == '') 388 | $result=$movementstock->_create($user,$fk_product,$id_entrepot,$op[$movement],$movement,$price,$label,$inventorycode, $datem); 389 | else 390 | $result=$movementstock->_create($user,$fk_product,$id_entrepot,$op[$movement],$movement,$price,$label,$inventorycode, $datem, '', '', $batch); 391 | 392 | if ($result >= 0) 393 | { 394 | $db->commit(); 395 | return 1; 396 | } 397 | else 398 | { 399 | $this->error=$movementstock->error; 400 | $this->errors=$movementstock->errors; 401 | 402 | $db->rollback(); 403 | return -1; 404 | } 405 | } 406 | } 407 | 408 | function regulate(&$PDOdb) 409 | { 410 | global $db,$user,$langs,$conf; 411 | 412 | if($conf->global->INVENTORY_DISABLE_VIRTUAL){ 413 | $pdt_virtuel = false; 414 | // Test si pdt virtuel est activé 415 | if($conf->global->PRODUIT_SOUSPRODUITS) 416 | { 417 | $pdt_virtuel = true; 418 | $conf->global->PRODUIT_SOUSPRODUITS = 0; 419 | } 420 | } 421 | 422 | foreach ($this->TInventorydet as $k => $TInventorydet) 423 | { 424 | $product = new Product($db); 425 | $product->fetch($TInventorydet->fk_product); 426 | 427 | /* 428 | * Ancien code qui était pourri et qui modifié la valeur du stock théorique si le parent était déstocké le même jour que l'enfant 429 | * 430 | * $product->load_stock(); 431 | $TInventorydet->qty_stock = $product->stock_warehouse[$this->fk_warehouse]->real; 432 | 433 | if(date('Y-m-d', $this->date_inventory) < date('Y-m-d')) { 434 | $TRes = $TInventorydet->getPmpStockFromDate($PDOdb, date('Y-m-d', $this->date_inventory), $this->fk_warehouse); 435 | $TInventorydet->qty_stock = $TRes[1]; 436 | } 437 | */ 438 | if ($TInventorydet->qty_view != $TInventorydet->qty_stock) 439 | { 440 | $TInventorydet->qty_regulated = $TInventorydet->qty_view - $TInventorydet->qty_stock; 441 | $nbpiece = abs($TInventorydet->qty_regulated); 442 | $movement = (int) ($TInventorydet->qty_view < $TInventorydet->qty_stock); // 0 = add ; 1 = remove 443 | 444 | $href = dol_buildpath('/inventory/inventory.php?id='.$this->getId().'&action=view', 1); 445 | 446 | if (! $this->per_batch || !$product->hasbatch()) { 447 | if(empty($this->title)) 448 | $this->correct_stock($product->id, $TInventorydet->fk_warehouse, $nbpiece, $movement, $langs->trans('inventoryMvtStock', $href, $this->getId())); 449 | else 450 | $this->correct_stock($product->id, $TInventorydet->fk_warehouse, $nbpiece, $movement, $langs->trans('inventoryMvtStockWithNomInventaire', $href, $this->title)); 451 | } 452 | else { 453 | if($TInventorydet->lot !== '') 454 | { 455 | if(empty($this->title)) 456 | $this->correct_stock($product->id, $TInventorydet->fk_warehouse, $nbpiece, $movement, $langs->trans('inventoryMvtStock', $href, $this->getId()), 0 , '', $TInventorydet->lot); 457 | else 458 | $this->correct_stock($product->id, $TInventorydet->fk_warehouse, $nbpiece, $movement, $langs->trans('inventoryMvtStockWithNomInventaire', $href, $this->title), 0 , '', $TInventorydet->lot); 459 | } 460 | } 461 | } 462 | } 463 | 464 | if($conf->global->INVENTORY_DISABLE_VIRTUAL){ 465 | // Test si pdt virtuel était activé avant la régule 466 | if($pdt_virtuel) $conf->global->PRODUIT_SOUSPRODUITS = 1; 467 | } 468 | 469 | return 1; 470 | } 471 | 472 | static function getLink($id) { 473 | global $langs; 474 | 475 | $PDOdb=new TPDOdb; 476 | 477 | $i = new TInventory; 478 | $i->load($PDOdb, $id, false); 479 | 480 | $title = !empty($i->title) ? $i->title : $langs->trans('inventoryTitle').' '.$i->getId(); 481 | 482 | return ''.img_picto('','object_list.png','',0).' '.$title.''; 483 | 484 | } 485 | } 486 | 487 | class TInventorydet extends TObjetStd 488 | { 489 | function __construct() 490 | { 491 | global $conf; 492 | 493 | $this->set_table(MAIN_DB_PREFIX.'inventorydet'); 494 | $this->TChamps = array(); 495 | $this->add_champs('fk_inventory,fk_warehouse,fk_product,entity', 'type=entier;'); 496 | $this->add_champs('qty_view,qty_stock,qty_regulated,pmp,pa,new_pmp', 'type=float;'); 497 | $this->add_champs('lot', 'type=text;'); 498 | 499 | $this->_init_vars(); 500 | $this->start(); 501 | 502 | $this->entity = $conf->entity; 503 | $this->errors = array(); 504 | 505 | $this->product = null; 506 | 507 | $this->current_pa = 0; 508 | 509 | } 510 | 511 | function save(&$PDOdb) 512 | { 513 | global $conf; 514 | 515 | if (!empty($conf->global->INVENTORY_USE_ONLY_INTEGER)) $this->qty_view = (int) $this->qty_view; 516 | 517 | return parent::save($PDOdb); // TODO: Change the autogenerated stub 518 | } 519 | 520 | 521 | function load(&$PDOdb, $id, $loadChild = true) 522 | { 523 | global $conf; 524 | 525 | $res = parent::load($PDOdb, $id, $loadChild); 526 | $this->load_product(); 527 | $this->fetch_current_pa(); 528 | 529 | return $res; 530 | } 531 | 532 | function fetch_current_pa() { 533 | global $db,$conf; 534 | 535 | if(empty($conf->global->INVENTORY_USE_MIN_PA_IF_NO_LAST_PA)) return false; 536 | 537 | if($this->pa>0){ 538 | $this->current_pa = $this->pa; 539 | } 540 | else { 541 | 542 | dol_include_once('/fourn/class/fournisseur.product.class.php'); 543 | $p= new ProductFournisseur($db); 544 | $p->find_min_price_product_fournisseur($this->fk_product); 545 | 546 | if($p->fourn_qty>0) $this->current_pa = $p->fourn_price / $p->fourn_qty; 547 | } 548 | return true; 549 | } 550 | 551 | function setStockDate(&$PDOdb, $date, $fk_warehouse) { 552 | 553 | list($pmp,$stock) = $this->getPmpStockFromDate($PDOdb, $date, $fk_warehouse); 554 | 555 | $this->qty_stock = $stock; 556 | $this->pmp = $pmp; 557 | $last_pa = 0; 558 | $sql = "SELECT price FROM ".MAIN_DB_PREFIX."stock_mouvement 559 | WHERE fk_entrepot=".$fk_warehouse." 560 | AND fk_product=".$this->fk_product." 561 | AND (origintype='order_supplier' || origintype='invoice_supplier') 562 | AND price>0 563 | AND datem<='".$date." 23:59:59' 564 | ORDER BY datem DESC LIMIT 1"; 565 | 566 | $PDOdb->Execute($sql); 567 | 568 | if($obj = $PDOdb->Get_line()) { 569 | $last_pa = $obj->price; 570 | } 571 | 572 | $this->pa = $last_pa; 573 | /* var_dump($fk_warehouse,$this->product->stock_warehouse,$this->pmp, $this->pa, $this->qty_stock); 574 | exit;*/ 575 | } 576 | 577 | function getPmpStockFromDate(&$PDOdb, $date, $fk_warehouse){ 578 | 579 | $res = $this->product->load_stock(); 580 | // var_dump($res, $this->product); 581 | if($res>0) { 582 | $stock = isset($this->product->stock_warehouse[$fk_warehouse]->real) ? $this->product->stock_warehouse[$fk_warehouse]->real : 0; 583 | 584 | if(isset($this->product->stock_warehouse[$fk_warehouse]->pmp))$this->product->stock_warehouse[$fk_warehouse]->pmp = (float)$this->product->stock_warehouse[$fk_warehouse]->pmp; 585 | 586 | if(empty($this->product->stock_warehouse[$fk_warehouse]->pmp)) $pmp = (float)$this->product->pmp; 587 | else { 588 | $pmp = $this->product->stock_warehouse[$fk_warehouse]->pmp; 589 | } 590 | 591 | } 592 | 593 | //On récupère tous les mouvements de stocks du produit entre aujourd'hui et la date de l'inventaire 594 | $sql = "SELECT value, price 595 | FROM ".MAIN_DB_PREFIX."stock_mouvement 596 | WHERE fk_product = ".$this->product->id." 597 | AND fk_entrepot = ".$fk_warehouse." 598 | AND datem > '".date('Y-m-d 23:59:59',strtotime($date))."' 599 | ORDER BY datem DESC"; 600 | 601 | //echo $sql.'
'; 602 | $PDOdb->Execute($sql); 603 | $TMouvementStock = $PDOdb->Get_All(); 604 | $laststock = $stock; 605 | $lastpmp = $pmp; 606 | //Pour chacun des mouvements on recalcule le PMP et le stock physique 607 | foreach($TMouvementStock as $mouvement){ 608 | 609 | $price = ($mouvement->price>0 && $mouvement->value>0) ? $mouvement->price : $lastpmp; // prix du mouvement si positif 610 | 611 | $stock_value = $laststock * $lastpmp; // valeur du stock 612 | 613 | $laststock -= $mouvement->value; // recalcul du stock en fonction du mouvement 614 | 615 | $last_stock_value = $stock_value - ($mouvement->value * $price); // valorisation du stock en fonction du mouvement 616 | if($last_stock_value < 0) $last_stock_value = 0; 617 | 618 | //if($last_stock_value<0 || $laststock<0) null; 619 | $lastpmp = (round($laststock, 4) != 0) ? $last_stock_value / $laststock : $lastpmp; // S'il y a un stock, alors son PMP est sa valeur totale / nombre de pièce 620 | 621 | } 622 | 623 | return array($lastpmp,$laststock); 624 | } 625 | 626 | function load_product() 627 | { 628 | global $db; 629 | 630 | if($this->fk_product>0) { 631 | $this->product = new Product($db); 632 | $this->product->fetch($this->fk_product); 633 | } 634 | 635 | } 636 | 637 | } 638 | -------------------------------------------------------------------------------- /core/modules/modinventory.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 inventory Module inventory 22 | * \brief Example of a module descriptor. 23 | * Such a file must be copied into htdocs/inventory/core/modules directory. 24 | * \file htdocs/inventory/core/modules/modinventory.class.php 25 | * \ingroup inventory 26 | * \brief Description and activation file for module inventory 27 | */ 28 | include_once DOL_DOCUMENT_ROOT .'/core/modules/DolibarrModules.class.php'; 29 | 30 | 31 | /** 32 | * Description and activation class for module inventory 33 | */ 34 | class modinventory 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 | 47 | // Id for module (must be unique). 48 | // Use here a free id (See in Home -> System information -> Dolibarr for list of used modules id). 49 | $this->numero = 104420; // 104000 to 104999 for ATM CONSULTING 50 | $this->editor_name = 'ATM Consulting'; 51 | $this->editor_url = 'https://www.atm-consulting.fr'; 52 | // Key text used to identify module (for permissions, menus, etc...) 53 | $this->rights_class = 'inventory'; 54 | 55 | // Family can be 'crm','financial','hr','projects','products','ecm','technic','other' 56 | // It is used to group modules in module setup page 57 | $this->family = "products"; 58 | // Module label (no space allowed), used if translation string 'ModuleXXXName' not found (where XXX is value of numeric property 'numero' of module) 59 | $this->name = preg_replace('/^mod/i','',get_class($this)); 60 | // Module description, used if translation string 'ModuleXXXDesc' not found (where XXX is value of numeric property 'numero' of module) 61 | $this->description = "Description of module inventory"; 62 | // Possible values for version are: 'development', 'experimental', 'dolibarr' or version 63 | $this->version = '1.11.7'; 64 | // Key used in llx_const table to save module status enabled/disabled (where MYMODULE is value of property name of module in uppercase) 65 | $this->const_name = 'MAIN_MODULE_'.strtoupper($this->name); 66 | // Where to store the module in setup page (0=common,1=interface,2=others,3=very specific) 67 | $this->special = 0; 68 | // Name of image file used for this module. 69 | // If file is in theme/yourtheme/img directory under name object_pictovalue.png, use this->picto='pictovalue' 70 | // If file is in module/img directory under name object_pictovalue.png, use this->picto='pictovalue@module' 71 | $this->picto='inventory@inventory'; 72 | 73 | // Defined all module parts (triggers, login, substitutions, menus, css, etc...) 74 | // for default path (eg: /inventory/core/xxxxx) (0=disable, 1=enable) 75 | // for specific path of parts (eg: /inventory/core/modules/barcode) 76 | // for specific css file (eg: /inventory/css/inventory.css.php) 77 | //$this->module_parts = array( 78 | // 'triggers' => 0, // Set this to 1 if module has its own trigger directory (core/triggers) 79 | // 'login' => 0, // Set this to 1 if module has its own login method directory (core/login) 80 | // 'substitutions' => 0, // Set this to 1 if module has its own substitution function file (core/substitutions) 81 | // 'menus' => 0, // Set this to 1 if module has its own menus handler directory (core/menus) 82 | // 'theme' => 0, // Set this to 1 if module has its own theme directory (theme) 83 | // 'tpl' => 0, // Set this to 1 if module overwrite template dir (core/tpl) 84 | // 'barcode' => 0, // Set this to 1 if module has its own barcode directory (core/modules/barcode) 85 | // 'models' => 0, // Set this to 1 if module has its own models directory (core/modules/xxx) 86 | // 'css' => array('/inventory/css/inventory.css.php'), // Set this to relative path of css file if module has its own css file 87 | // 'js' => array('/inventory/js/inventory.js'), // Set this to relative path of js file if module must load a js on all pages 88 | // 'hooks' => array('hookcontext1','hookcontext2') // Set here all hooks context managed by module 89 | // 'dir' => array('output' => 'othermodulename'), // To force the default directories names 90 | // 'workflow' => array('WORKFLOW_MODULE1_YOURACTIONTYPE_MODULE2'=>array('enabled'=>'! empty($conf->module1->enabled) && ! empty($conf->module2->enabled)', 'picto'=>'yourpicto@inventory')) // Set here all workflow context managed by module 91 | // ); 92 | $this->module_parts = array(); 93 | 94 | // Data directories to create when module is enabled. 95 | // Example: this->dirs = array("/inventory/temp"); 96 | $this->dirs = array('/inventory'); 97 | 98 | // Config pages. Put here list of php page, stored into inventory/admin directory, to use to setup module. 99 | $this->config_page_url = array("inventory_setup.php@inventory"); 100 | 101 | // Dependencies 102 | $this->hidden = false; // A condition to hide module 103 | $this->depends = array('modStock'); // List of modules id that must be enabled if this module is enabled 104 | $this->requiredby = array(); // List of modules id to disable if this one is disabled 105 | $this->conflictwith = array(); // List of modules id this module is in conflict with 106 | $this->phpmin = array(5,0); // Minimum version of PHP required by module 107 | $this->need_dolibarr_version = array(3,0); // Minimum version of Dolibarr required by module 108 | $this->langfiles = array("inventory@inventory"); 109 | 110 | // Constants 111 | // List of particular constants to add when module is enabled (key, 'chaine', value, desc, visible, 'current' or 'allentities', deleteonunactive) 112 | // Example: $this->const=array(0=>array('MYMODULE_MYNEWCONST1','chaine','myvalue','This is a constant to add',1), 113 | // 1=>array('MYMODULE_MYNEWCONST2','chaine','myvalue','This is another constant to add',0, 'current', 1) 114 | // ); 115 | $this->const = array(); 116 | 117 | // Array to add new pages in new tabs 118 | // Example: $this->tabs = array('objecttype:+tabname1:Title1:mylangfile@inventory:$user->rights->inventory->read:/inventory/mynewtab1.php?id=__ID__', // To add a new tab identified by code tabname1 119 | // 'objecttype:+tabname2:Title2:mylangfile@inventory:$user->rights->othermodule->read:/inventory/mynewtab2.php?id=__ID__', // To add another new tab identified by code tabname2 120 | // 'objecttype:-tabname:NU:conditiontoremove'); // To remove an existing tab identified by code tabname 121 | // where objecttype can be 122 | // 'categories_x' to add a tab in category view (replace 'x' by type of category (0=product, 1=supplier, 2=customer, 3=member) 123 | // 'contact' to add a tab in contact view 124 | // 'contract' to add a tab in contract view 125 | // 'group' to add a tab in group view 126 | // 'intervention' to add a tab in intervention view 127 | // 'invoice' to add a tab in customer invoice view 128 | // 'invoice_supplier' to add a tab in supplier invoice view 129 | // 'member' to add a tab in fundation member view 130 | // 'opensurveypoll' to add a tab in opensurvey poll view 131 | // 'order' to add a tab in customer order view 132 | // 'order_supplier' to add a tab in supplier order view 133 | // 'payment' to add a tab in payment view 134 | // 'payment_supplier' to add a tab in supplier payment view 135 | // 'product' to add a tab in product view 136 | // 'propal' to add a tab in propal view 137 | // 'project' to add a tab in project view 138 | // 'stock' to add a tab in stock view 139 | // 'thirdparty' to add a tab in third party view 140 | // 'user' to add a tab in user view 141 | $this->tabs = array(); 142 | 143 | // Dictionaries 144 | if (! isset($conf->inventory->enabled)) 145 | { 146 | $conf->inventory=new stdClass(); 147 | $conf->inventory->enabled=0; 148 | } 149 | $this->dictionaries=array(); 150 | /* Example: 151 | if (! isset($conf->inventory->enabled)) $conf->inventory->enabled=0; // This is to avoid warnings 152 | $this->dictionaries=array( 153 | 'langs'=>'mylangfile@inventory', 154 | 'tabname'=>array(MAIN_DB_PREFIX."table1",MAIN_DB_PREFIX."table2",MAIN_DB_PREFIX."table3"), // List of tables we want to see into dictonnary editor 155 | 'tablib'=>array("Table1","Table2","Table3"), // Label of tables 156 | '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 157 | 'tabsqlsort'=>array("label ASC","label ASC","label ASC"), // Sort order 158 | 'tabfield'=>array("code,label","code,label","code,label"), // List of fields (result of select to show dictionary) 159 | 'tabfieldvalue'=>array("code,label","code,label","code,label"), // List of fields (list of fields to edit a record) 160 | 'tabfieldinsert'=>array("code,label","code,label","code,label"), // List of fields (list of fields for insert) 161 | 'tabrowid'=>array("rowid","rowid","rowid"), // Name of columns with primary key (try to always name it 'rowid') 162 | 'tabcond'=>array($conf->inventory->enabled,$conf->inventory->enabled,$conf->inventory->enabled) // Condition to show each dictionary 163 | ); 164 | */ 165 | 166 | // Boxes 167 | // Add here list of php file(s) stored in core/boxes that contains class to show a box. 168 | $this->boxes = array(); // List of boxes 169 | // Example: 170 | //$this->boxes=array(array(0=>array('file'=>'myboxa.php','note'=>'','enabledbydefaulton'=>'Home'),1=>array('file'=>'myboxb.php','note'=>''),2=>array('file'=>'myboxc.php','note'=>''));); 171 | 172 | $langs->load('inventory@inventory'); 173 | 174 | // Permissions 175 | $this->rights = array(); // Permission array used by this module 176 | $r=0; 177 | 178 | // Add here list of permission defined by an id, a label, a boolean and two constant strings. 179 | // Example: 180 | // $this->rights[$r][0] = $this->numero + $r; // Permission id (must not be already used) 181 | // $this->rights[$r][1] = 'Permision label'; // Permission label 182 | // $this->rights[$r][3] = 1; // Permission by default for new user (0/1) 183 | // $this->rights[$r][4] = 'level1'; // In php code, permission will be checked by test if ($user->rights->permkey->level1->level2) 184 | // $this->rights[$r][5] = 'level2'; // In php code, permission will be checked by test if ($user->rights->permkey->level1->level2) 185 | // $r++; 186 | 187 | $this->rights[$r][0] = $this->numero + $r; // Permission id (must not be already used) 188 | $this->rights[$r][1] = 'inventoryReadPermission'; // Permission label 189 | $this->rights[$r][3] = 0; // Permission by default for new user (0/1) 190 | $this->rights[$r][4] = 'read'; // In php code, permission will be checked by test if ($user->rights->permkey->level1->level2) 191 | $r++; 192 | 193 | $this->rights[$r][0] = $this->numero + $r; // Permission id (must not be already used) 194 | $this->rights[$r][1] = 'inventoryCreatePermission'; // Permission label 195 | $this->rights[$r][3] = 0; // Permission by default for new user (0/1) 196 | $this->rights[$r][4] = 'create'; // In php code, permission will be checked by test if ($user->rights->permkey->level1->level2) 197 | $r++; 198 | 199 | $this->rights[$r][0] = $this->numero + $r; // Permission id (must not be already used) 200 | $this->rights[$r][1] = 'inventoryWritePermission'; // Permission label 201 | $this->rights[$r][3] = 0; // Permission by default for new user (0/1) 202 | $this->rights[$r][4] = 'write'; // In php code, permission will be checked by test if ($user->rights->permkey->level1->level2) 203 | $r++; 204 | 205 | $this->rights[$r][0] = $this->numero + $r; // Permission id (must not be already used) 206 | $this->rights[$r][1] = 'inventoryValidatePermission'; // Permission label 207 | $this->rights[$r][3] = 0; // Permission by default for new user (0/1) 208 | $this->rights[$r][4] = 'validate'; // In php code, permission will be checked by test if ($user->rights->permkey->level1->level2) 209 | $r++; 210 | 211 | $this->rights[$r][0] = $this->numero + $r; // Permission id (must not be already used) 212 | $this->rights[$r][1] = 'inventoryChangePMPPermission'; // Permission label 213 | $this->rights[$r][3] = 0; // Permission by default for new user (0/1) 214 | $this->rights[$r][4] = 'changePMP'; // In php code, permission will be checked by test if ($user->rights->permkey->level1->level2) 215 | $r++; 216 | 217 | // Main menu entries 218 | $this->menu = array(); // List of menus to add 219 | $r=0; 220 | 221 | // Add here entries to declare new menus 222 | // 223 | // Example to declare a new Top Menu entry and its Left menu entry: 224 | // $this->menu[$r]=array( 'fk_menu'=>0, // Put 0 if this is a top menu 225 | // 'type'=>'top', // This is a Top menu entry 226 | // 'titre'=>'inventory top menu', 227 | // 'mainmenu'=>'inventory', 228 | // 'leftmenu'=>'inventory', 229 | // 'url'=>'/inventory/pagetop.php', 230 | // 'langs'=>'mylangfile@inventory', // Lang file to use (without .lang) by module. File must be in langs/code_CODE/ directory. 231 | // 'position'=>100, 232 | // 'enabled'=>'$conf->inventory->enabled', // Define condition to show or hide menu entry. Use '$conf->inventory->enabled' if entry must be visible if module is enabled. 233 | // 'perms'=>'1', // Use 'perms'=>'$user->rights->inventory->level1->level2' if you want your menu with a permission rules 234 | // 'target'=>'', 235 | // 'user'=>2); // 0=Menu for internal users, 1=external users, 2=both 236 | // $r++; 237 | // 238 | // Example to declare a Left Menu entry into an existing Top menu entry: 239 | // $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 240 | // 'type'=>'left', // This is a Left menu entry 241 | // 'titre'=>'inventory left menu', 242 | // 'mainmenu'=>'xxx', 243 | // 'leftmenu'=>'inventory', 244 | // 'url'=>'/inventory/pagelevel2.php', 245 | // 'langs'=>'mylangfile@inventory', // Lang file to use (without .lang) by module. File must be in langs/code_CODE/ directory. 246 | // 'position'=>100, 247 | // 'enabled'=>'$conf->inventory->enabled', // Define condition to show or hide menu entry. Use '$conf->inventory->enabled' if entry must be visible if module is enabled. Use '$leftmenu==\'system\'' to show if leftmenu system is selected. 248 | // 'perms'=>'1', // Use 'perms'=>'$user->rights->inventory->level1->level2' if you want your menu with a permission rules 249 | // 'target'=>'', 250 | // 'user'=>2); // 0=Menu for internal users, 1=external users, 2=both 251 | // $r++; 252 | $this->menu[$r]=array( 'fk_menu'=>'fk_mainmenu=products,fk_leftmenu=stock', // Put 0 if this is a top menu 253 | 'type'=>'left', // This is a Top menu entry 254 | 'titre'=>'inventoryListTitle', 255 | 'mainmenu'=>'inventory', 256 | 257 | 'titre'=>'Liste des inventaires', 258 | 'mainmenu'=>'products', 259 | 'leftmenu'=>'inventory', 260 | 'url'=>'/inventory/inventory.php?action=list', 261 | 'langs'=>'inventory@inventory', // Lang file to use (without .lang) by module. File must be in langs/code_CODE/ directory. 262 | 'position'=>100, 263 | 'enabled'=>'$conf->inventory->enabled', // Define condition to show or hide menu entry. Use '$conf->inventory->enabled' if entry must be visible if module is enabled. 264 | 'perms'=>'$user->rights->inventory->read', // Use 'perms'=>'$user->rights->inventory->level1->level2' if you want your menu with a permission rules 265 | 'target'=>'', 266 | 'user'=>2); // 0=Menu for internal users, 1=external users, 2=both 267 | $r++; 268 | 269 | $this->menu[$r]=array( 'fk_menu'=>'fk_mainmenu=products,fk_leftmenu=stock', // Put 0 if this is a top menu 270 | 'type'=>'left', // This is a Top menu entry 271 | 272 | 'titre'=>'inventoryCreate', 273 | 'mainmenu'=>'inventory', 274 | 'titre'=>'Nouvel inventaire', 275 | 'mainmenu'=>'products', 276 | 'leftmenu'=>'inventory', 277 | 'url'=>'/inventory/inventory.php?action=create', 278 | 'langs'=>'inventory@inventory', // Lang file to use (without .lang) by module. File must be in langs/code_CODE/ directory. 279 | 'position'=>100, 280 | 'enabled'=>'$conf->inventory->enabled', // Define condition to show or hide menu entry. Use '$conf->inventory->enabled' if entry must be visible if module is enabled. 281 | 'perms'=>'$user->rights->inventory->create', // Use 'perms'=>'$user->rights->inventory->level1->level2' if you want your menu with a permission rules 282 | 'target'=>'', 283 | 'user'=>2); // 0=Menu for internal users, 1=external users, 2=both 284 | $r++; 285 | 286 | // Exports 287 | $r=1; 288 | 289 | // Example: 290 | // $this->export_code[$r]=$this->rights_class.'_'.$r; 291 | // $this->export_label[$r]='CustomersInvoicesAndInvoiceLines'; // Translation key (used only if key ExportDataset_xxx_z not found) 292 | // $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. 293 | // $this->export_permission[$r]=array(array("facture","facture","export")); 294 | // $this->export_fields_array[$r]=array('s.rowid'=>"IdCompany",'s.nom'=>'CompanyName','s.address'=>'Address','s.zip'=>'Zip','s.town'=>'Town','s.fk_pays'=>'Country','s.phone'=>'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'); 295 | // $this->export_entities_array[$r]=array('s.rowid'=>"company",'s.nom'=>'company','s.address'=>'company','s.zip'=>'company','s.town'=>'company','s.fk_pays'=>'company','s.phone'=>'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'); 296 | // $this->export_sql_start[$r]='SELECT DISTINCT '; 297 | // $this->export_sql_end[$r] =' FROM ('.MAIN_DB_PREFIX.'facture as f, '.MAIN_DB_PREFIX.'facturedet as fd, '.MAIN_DB_PREFIX.'societe as s)'; 298 | // $this->export_sql_end[$r] .=' LEFT JOIN '.MAIN_DB_PREFIX.'product as p on (fd.fk_product = p.rowid)'; 299 | // $this->export_sql_end[$r] .=' WHERE f.fk_soc = s.rowid AND f.rowid = fd.fk_facture'; 300 | // $this->export_sql_order[$r] .=' ORDER BY s.nom'; 301 | // $r++; 302 | } 303 | 304 | /** 305 | * Function called when module is enabled. 306 | * The init function add constants, boxes, permissions and menus (defined in constructor) into Dolibarr database. 307 | * It also creates data directories 308 | * 309 | * @param string $options Options when enabling module ('', 'noboxes') 310 | * @return int 1 if OK, 0 if KO 311 | */ 312 | function init($options='') 313 | { 314 | $sql = array(); 315 | define('INC_FROM_DOLIBARR', true); 316 | dol_include_once('/inventory/config.php'); 317 | dol_include_once("/inventory/script/create-maj-base.php"); 318 | 319 | return $this->_init($sql, $options); 320 | } 321 | 322 | /** 323 | * Function called when module is disabled. 324 | * Remove from database constants, boxes and permissions from Dolibarr database. 325 | * Data directories are not deleted 326 | * 327 | * @param string $options Options when enabling module ('', 'noboxes') 328 | * @return int 1 if OK, 0 if KO 329 | */ 330 | function remove($options='') 331 | { 332 | $sql = array(); 333 | 334 | return $this->_remove($sql, $options); 335 | } 336 | 337 | } 338 | -------------------------------------------------------------------------------- /core/triggers/interface_99_modinventory_inventorytrigger.class.php: -------------------------------------------------------------------------------- 1 | 3 | * Copyright (C) 2015 ATM Consulting 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 3 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 core/triggers/interface_99_modMyodule_inventorytrigger.class.php 21 | * \ingroup inventory 22 | * \brief Sample trigger 23 | * \remarks You can create other triggers by copying this one 24 | * - File name should be either: 25 | * interface_99_modMymodule_Mytrigger.class.php 26 | * interface_99_all_Mytrigger.class.php 27 | * - The file must stay in core/triggers 28 | * - The class name must be InterfaceMytrigger 29 | * - The constructor method must be named InterfaceMytrigger 30 | * - The name property name must be Mytrigger 31 | */ 32 | 33 | /** 34 | * Trigger class 35 | */ 36 | class Interfaceinventorytrigger 37 | { 38 | 39 | private $db; 40 | 41 | /** 42 | * Constructor 43 | * 44 | * @param DoliDB $db Database handler 45 | */ 46 | public function __construct($db) 47 | { 48 | $this->db = $db; 49 | 50 | $this->name = preg_replace('/^Interface/i', '', get_class($this)); 51 | $this->family = "demo"; 52 | $this->description = "Triggers of this module are empty functions." 53 | . "They have no effect." 54 | . "They are provided for tutorial purpose only."; 55 | // 'development', 'experimental', 'dolibarr' or version 56 | $this->version = 'development'; 57 | $this->picto = 'inventory@inventory'; 58 | } 59 | 60 | /** 61 | * Trigger name 62 | * 63 | * @return string Name of trigger file 64 | */ 65 | public function getName() 66 | { 67 | return $this->name; 68 | } 69 | 70 | /** 71 | * Trigger description 72 | * 73 | * @return string Description of trigger file 74 | */ 75 | public function getDesc() 76 | { 77 | return $this->description; 78 | } 79 | 80 | /** 81 | * Trigger version 82 | * 83 | * @return string Version of trigger file 84 | */ 85 | public function getVersion() 86 | { 87 | global $langs; 88 | $langs->load("admin"); 89 | 90 | if ($this->version == 'development') { 91 | return $langs->trans("Development"); 92 | } elseif ($this->version == 'experimental') 93 | 94 | return $langs->trans("Experimental"); 95 | elseif ($this->version == 'dolibarr') return DOL_VERSION; 96 | elseif ($this->version) return $this->version; 97 | else { 98 | return $langs->trans("Unknown"); 99 | } 100 | } 101 | 102 | /** 103 | * Function called when a Dolibarrr business event is done. 104 | * All functions "run_trigger" are triggered if file 105 | * is inside directory core/triggers 106 | * 107 | * @param string $action Event action code 108 | * @param Object $object Object 109 | * @param User $user Object user 110 | * @param Translate $langs Object langs 111 | * @param conf $conf Object conf 112 | * @return int <0 if KO, 0 if no triggered ran, >0 if OK 113 | */ 114 | public function run_trigger($action, $object, $user, $langs, $conf) 115 | { 116 | // Put here code you want to execute when a Dolibarr business events occurs. 117 | // Data and type of action are stored into $object and $action 118 | // Users 119 | if ($action == 'USER_LOGIN') { 120 | dol_syslog( 121 | "Trigger '" . $this->name . "' for action '$action' launched by " . __FILE__ . ". id=" . $object->id 122 | ); 123 | } elseif ($action == 'USER_UPDATE_SESSION') { 124 | // Warning: To increase performances, this action is triggered only if 125 | // constant MAIN_ACTIVATE_UPDATESESSIONTRIGGER is set to 1. 126 | dol_syslog( 127 | "Trigger '" . $this->name . "' for action '$action' launched by " . __FILE__ . ". id=" . $object->id 128 | ); 129 | } elseif ($action == 'USER_CREATE') { 130 | dol_syslog( 131 | "Trigger '" . $this->name . "' for action '$action' launched by " . __FILE__ . ". id=" . $object->id 132 | ); 133 | } elseif ($action == 'USER_CREATE_FROM_CONTACT') { 134 | dol_syslog( 135 | "Trigger '" . $this->name . "' for action '$action' launched by " . __FILE__ . ". id=" . $object->id 136 | ); 137 | } elseif ($action == 'USER_MODIFY') { 138 | dol_syslog( 139 | "Trigger '" . $this->name . "' for action '$action' launched by " . __FILE__ . ". id=" . $object->id 140 | ); 141 | } elseif ($action == 'USER_NEW_PASSWORD') { 142 | dol_syslog( 143 | "Trigger '" . $this->name . "' for action '$action' launched by " . __FILE__ . ". id=" . $object->id 144 | ); 145 | } elseif ($action == 'USER_ENABLEDISABLE') { 146 | dol_syslog( 147 | "Trigger '" . $this->name . "' for action '$action' launched by " . __FILE__ . ". id=" . $object->id 148 | ); 149 | } elseif ($action == 'USER_DELETE') { 150 | dol_syslog( 151 | "Trigger '" . $this->name . "' for action '$action' launched by " . __FILE__ . ". id=" . $object->id 152 | ); 153 | } elseif ($action == 'USER_LOGOUT') { 154 | dol_syslog( 155 | "Trigger '" . $this->name . "' for action '$action' launched by " . __FILE__ . ". id=" . $object->id 156 | ); 157 | } elseif ($action == 'USER_SETINGROUP') { 158 | dol_syslog( 159 | "Trigger '" . $this->name . "' for action '$action' launched by " . __FILE__ . ". id=" . $object->id 160 | ); 161 | } elseif ($action == 'USER_REMOVEFROMGROUP') { 162 | dol_syslog( 163 | "Trigger '" . $this->name . "' for action '$action' launched by " . __FILE__ . ". id=" . $object->id 164 | ); 165 | } 166 | 167 | // Groups 168 | elseif ($action == 'GROUP_CREATE') { 169 | dol_syslog( 170 | "Trigger '" . $this->name . "' for action '$action' launched by " . __FILE__ . ". id=" . $object->id 171 | ); 172 | } elseif ($action == 'GROUP_MODIFY') { 173 | dol_syslog( 174 | "Trigger '" . $this->name . "' for action '$action' launched by " . __FILE__ . ". id=" . $object->id 175 | ); 176 | } elseif ($action == 'GROUP_DELETE') { 177 | dol_syslog( 178 | "Trigger '" . $this->name . "' for action '$action' launched by " . __FILE__ . ". id=" . $object->id 179 | ); 180 | } 181 | 182 | // Companies 183 | elseif ($action == 'COMPANY_CREATE') { 184 | dol_syslog( 185 | "Trigger '" . $this->name . "' for action '$action' launched by " . __FILE__ . ". id=" . $object->id 186 | ); 187 | } elseif ($action == 'COMPANY_MODIFY') { 188 | dol_syslog( 189 | "Trigger '" . $this->name . "' for action '$action' launched by " . __FILE__ . ". id=" . $object->id 190 | ); 191 | } elseif ($action == 'COMPANY_DELETE') { 192 | dol_syslog( 193 | "Trigger '" . $this->name . "' for action '$action' launched by " . __FILE__ . ". id=" . $object->id 194 | ); 195 | } 196 | 197 | // Contacts 198 | elseif ($action == 'CONTACT_CREATE') { 199 | dol_syslog( 200 | "Trigger '" . $this->name . "' for action '$action' launched by " . __FILE__ . ". id=" . $object->id 201 | ); 202 | } elseif ($action == 'CONTACT_MODIFY') { 203 | dol_syslog( 204 | "Trigger '" . $this->name . "' for action '$action' launched by " . __FILE__ . ". id=" . $object->id 205 | ); 206 | } elseif ($action == 'CONTACT_DELETE') { 207 | dol_syslog( 208 | "Trigger '" . $this->name . "' for action '$action' launched by " . __FILE__ . ". id=" . $object->id 209 | ); 210 | } 211 | 212 | // Products 213 | elseif ($action == 'PRODUCT_CREATE') { 214 | dol_syslog( 215 | "Trigger '" . $this->name . "' for action '$action' launched by " . __FILE__ . ". id=" . $object->id 216 | ); 217 | } elseif ($action == 'PRODUCT_MODIFY') { 218 | dol_syslog( 219 | "Trigger '" . $this->name . "' for action '$action' launched by " . __FILE__ . ". id=" . $object->id 220 | ); 221 | } elseif ($action == 'PRODUCT_DELETE') { 222 | dol_syslog( 223 | "Trigger '" . $this->name . "' for action '$action' launched by " . __FILE__ . ". id=" . $object->id 224 | ); 225 | } 226 | 227 | // Customer orders 228 | elseif ($action == 'ORDER_CREATE') { 229 | dol_syslog( 230 | "Trigger '" . $this->name . "' for action '$action' launched by " . __FILE__ . ". id=" . $object->id 231 | ); 232 | } elseif ($action == 'ORDER_CLONE') { 233 | dol_syslog( 234 | "Trigger '" . $this->name . "' for action '$action' launched by " . __FILE__ . ". id=" . $object->id 235 | ); 236 | } elseif ($action == 'ORDER_VALIDATE') { 237 | dol_syslog( 238 | "Trigger '" . $this->name . "' for action '$action' launched by " . __FILE__ . ". id=" . $object->id 239 | ); 240 | } elseif ($action == 'ORDER_DELETE') { 241 | dol_syslog( 242 | "Trigger '" . $this->name . "' for action '$action' launched by " . __FILE__ . ". id=" . $object->id 243 | ); 244 | } elseif ($action == 'ORDER_BUILDDOC') { 245 | dol_syslog( 246 | "Trigger '" . $this->name . "' for action '$action' launched by " . __FILE__ . ". id=" . $object->id 247 | ); 248 | } elseif ($action == 'ORDER_SENTBYMAIL') { 249 | dol_syslog( 250 | "Trigger '" . $this->name . "' for action '$action' launched by " . __FILE__ . ". id=" . $object->id 251 | ); 252 | } elseif ($action == 'LINEORDER_INSERT') { 253 | dol_syslog( 254 | "Trigger '" . $this->name . "' for action '$action' launched by " . __FILE__ . ". id=" . $object->id 255 | ); 256 | } elseif ($action == 'LINEORDER_DELETE') { 257 | dol_syslog( 258 | "Trigger '" . $this->name . "' for action '$action' launched by " . __FILE__ . ". id=" . $object->id 259 | ); 260 | } 261 | 262 | // Supplier orders 263 | elseif ($action == 'ORDER_SUPPLIER_CREATE') { 264 | dol_syslog( 265 | "Trigger '" . $this->name . "' for action '$action' launched by " . __FILE__ . ". id=" . $object->id 266 | ); 267 | } elseif ($action == 'ORDER_SUPPLIER_VALIDATE') { 268 | dol_syslog( 269 | "Trigger '" . $this->name . "' for action '$action' launched by " . __FILE__ . ". id=" . $object->id 270 | ); 271 | } elseif ($action == 'ORDER_SUPPLIER_SENTBYMAIL') { 272 | dol_syslog( 273 | "Trigger '" . $this->name . "' for action '$action' launched by " . __FILE__ . ". id=" . $object->id 274 | ); 275 | } elseif ($action == 'SUPPLIER_ORDER_BUILDDOC') { 276 | dol_syslog( 277 | "Trigger '" . $this->name . "' for action '$action' launched by " . __FILE__ . ". id=" . $object->id 278 | ); 279 | } 280 | 281 | // Proposals 282 | elseif ($action == 'PROPAL_CREATE') { 283 | dol_syslog( 284 | "Trigger '" . $this->name . "' for action '$action' launched by " . __FILE__ . ". id=" . $object->id 285 | ); 286 | } elseif ($action == 'PROPAL_CLONE') { 287 | dol_syslog( 288 | "Trigger '" . $this->name . "' for action '$action' launched by " . __FILE__ . ". id=" . $object->id 289 | ); 290 | } elseif ($action == 'PROPAL_MODIFY') { 291 | dol_syslog( 292 | "Trigger '" . $this->name . "' for action '$action' launched by " . __FILE__ . ". id=" . $object->id 293 | ); 294 | } elseif ($action == 'PROPAL_VALIDATE') { 295 | dol_syslog( 296 | "Trigger '" . $this->name . "' for action '$action' launched by " . __FILE__ . ". id=" . $object->id 297 | ); 298 | } elseif ($action == 'PROPAL_BUILDDOC') { 299 | dol_syslog( 300 | "Trigger '" . $this->name . "' for action '$action' launched by " . __FILE__ . ". id=" . $object->id 301 | ); 302 | } elseif ($action == 'PROPAL_SENTBYMAIL') { 303 | dol_syslog( 304 | "Trigger '" . $this->name . "' for action '$action' launched by " . __FILE__ . ". id=" . $object->id 305 | ); 306 | } elseif ($action == 'PROPAL_CLOSE_SIGNED') { 307 | dol_syslog( 308 | "Trigger '" . $this->name . "' for action '$action' launched by " . __FILE__ . ". id=" . $object->id 309 | ); 310 | } elseif ($action == 'PROPAL_CLOSE_REFUSED') { 311 | dol_syslog( 312 | "Trigger '" . $this->name . "' for action '$action' launched by " . __FILE__ . ". id=" . $object->id 313 | ); 314 | } elseif ($action == 'PROPAL_DELETE') { 315 | dol_syslog( 316 | "Trigger '" . $this->name . "' for action '$action' launched by " . __FILE__ . ". id=" . $object->id 317 | ); 318 | } elseif ($action == 'LINEPROPAL_INSERT') { 319 | dol_syslog( 320 | "Trigger '" . $this->name . "' for action '$action' launched by " . __FILE__ . ". id=" . $object->id 321 | ); 322 | } elseif ($action == 'LINEPROPAL_MODIFY') { 323 | dol_syslog( 324 | "Trigger '" . $this->name . "' for action '$action' launched by " . __FILE__ . ". id=" . $object->id 325 | ); 326 | } elseif ($action == 'LINEPROPAL_DELETE') { 327 | dol_syslog( 328 | "Trigger '" . $this->name . "' for action '$action' launched by " . __FILE__ . ". id=" . $object->id 329 | ); 330 | } 331 | 332 | // Contracts 333 | elseif ($action == 'CONTRACT_CREATE') { 334 | dol_syslog( 335 | "Trigger '" . $this->name . "' for action '$action' launched by " . __FILE__ . ". id=" . $object->id 336 | ); 337 | } elseif ($action == 'CONTRACT_MODIFY') { 338 | dol_syslog( 339 | "Trigger '" . $this->name . "' for action '$action' launched by " . __FILE__ . ". id=" . $object->id 340 | ); 341 | } elseif ($action == 'CONTRACT_ACTIVATE') { 342 | dol_syslog( 343 | "Trigger '" . $this->name . "' for action '$action' launched by " . __FILE__ . ". id=" . $object->id 344 | ); 345 | } elseif ($action == 'CONTRACT_CANCEL') { 346 | dol_syslog( 347 | "Trigger '" . $this->name . "' for action '$action' launched by " . __FILE__ . ". id=" . $object->id 348 | ); 349 | } elseif ($action == 'CONTRACT_CLOSE') { 350 | dol_syslog( 351 | "Trigger '" . $this->name . "' for action '$action' launched by " . __FILE__ . ". id=" . $object->id 352 | ); 353 | } elseif ($action == 'CONTRACT_DELETE') { 354 | dol_syslog( 355 | "Trigger '" . $this->name . "' for action '$action' launched by " . __FILE__ . ". id=" . $object->id 356 | ); 357 | } 358 | 359 | // Bills 360 | elseif ($action == 'BILL_CREATE') { 361 | dol_syslog( 362 | "Trigger '" . $this->name . "' for action '$action' launched by " . __FILE__ . ". id=" . $object->id 363 | ); 364 | } elseif ($action == 'BILL_CLONE') { 365 | dol_syslog( 366 | "Trigger '" . $this->name . "' for action '$action' launched by " . __FILE__ . ". id=" . $object->id 367 | ); 368 | } elseif ($action == 'BILL_MODIFY') { 369 | dol_syslog( 370 | "Trigger '" . $this->name . "' for action '$action' launched by " . __FILE__ . ". id=" . $object->id 371 | ); 372 | } elseif ($action == 'BILL_VALIDATE') { 373 | dol_syslog( 374 | "Trigger '" . $this->name . "' for action '$action' launched by " . __FILE__ . ". id=" . $object->id 375 | ); 376 | } elseif ($action == 'BILL_BUILDDOC') { 377 | dol_syslog( 378 | "Trigger '" . $this->name . "' for action '$action' launched by " . __FILE__ . ". id=" . $object->id 379 | ); 380 | } elseif ($action == 'BILL_SENTBYMAIL') { 381 | dol_syslog( 382 | "Trigger '" . $this->name . "' for action '$action' launched by " . __FILE__ . ". id=" . $object->id 383 | ); 384 | } elseif ($action == 'BILL_CANCEL') { 385 | dol_syslog( 386 | "Trigger '" . $this->name . "' for action '$action' launched by " . __FILE__ . ". id=" . $object->id 387 | ); 388 | } elseif ($action == 'BILL_DELETE') { 389 | dol_syslog( 390 | "Trigger '" . $this->name . "' for action '$action' launched by " . __FILE__ . ". id=" . $object->id 391 | ); 392 | } elseif ($action == 'LINEBILL_INSERT') { 393 | dol_syslog( 394 | "Trigger '" . $this->name . "' for action '$action' launched by " . __FILE__ . ". id=" . $object->id 395 | ); 396 | } elseif ($action == 'LINEBILL_DELETE') { 397 | dol_syslog( 398 | "Trigger '" . $this->name . "' for action '$action' launched by " . __FILE__ . ". id=" . $object->id 399 | ); 400 | } 401 | 402 | // Payments 403 | elseif ($action == 'PAYMENT_CUSTOMER_CREATE') { 404 | dol_syslog( 405 | "Trigger '" . $this->name . "' for action '$action' launched by " . __FILE__ . ". id=" . $object->id 406 | ); 407 | } elseif ($action == 'PAYMENT_SUPPLIER_CREATE') { 408 | dol_syslog( 409 | "Trigger '" . $this->name . "' for action '$action' launched by " . __FILE__ . ". id=" . $object->id 410 | ); 411 | } elseif ($action == 'PAYMENT_ADD_TO_BANK') { 412 | dol_syslog( 413 | "Trigger '" . $this->name . "' for action '$action' launched by " . __FILE__ . ". id=" . $object->id 414 | ); 415 | } elseif ($action == 'PAYMENT_DELETE') { 416 | dol_syslog( 417 | "Trigger '" . $this->name . "' for action '$action' launched by " . __FILE__ . ". id=" . $object->id 418 | ); 419 | } 420 | 421 | // Interventions 422 | elseif ($action == 'FICHEINTER_CREATE') { 423 | dol_syslog( 424 | "Trigger '" . $this->name . "' for action '$action' launched by " . __FILE__ . ". id=" . $object->id 425 | ); 426 | } elseif ($action == 'FICHEINTER_MODIFY') { 427 | dol_syslog( 428 | "Trigger '" . $this->name . "' for action '$action' launched by " . __FILE__ . ". id=" . $object->id 429 | ); 430 | } elseif ($action == 'FICHEINTER_VALIDATE') { 431 | dol_syslog( 432 | "Trigger '" . $this->name . "' for action '$action' launched by " . __FILE__ . ". id=" . $object->id 433 | ); 434 | } elseif ($action == 'FICHEINTER_DELETE') { 435 | dol_syslog( 436 | "Trigger '" . $this->name . "' for action '$action' launched by " . __FILE__ . ". id=" . $object->id 437 | ); 438 | } 439 | 440 | // Members 441 | elseif ($action == 'MEMBER_CREATE') { 442 | dol_syslog( 443 | "Trigger '" . $this->name . "' for action '$action' launched by " . __FILE__ . ". id=" . $object->id 444 | ); 445 | } elseif ($action == 'MEMBER_VALIDATE') { 446 | dol_syslog( 447 | "Trigger '" . $this->name . "' for action '$action' launched by " . __FILE__ . ". id=" . $object->id 448 | ); 449 | } elseif ($action == 'MEMBER_SUBSCRIPTION') { 450 | dol_syslog( 451 | "Trigger '" . $this->name . "' for action '$action' launched by " . __FILE__ . ". id=" . $object->id 452 | ); 453 | } elseif ($action == 'MEMBER_MODIFY') { 454 | dol_syslog( 455 | "Trigger '" . $this->name . "' for action '$action' launched by " . __FILE__ . ". id=" . $object->id 456 | ); 457 | } elseif ($action == 'MEMBER_NEW_PASSWORD') { 458 | dol_syslog( 459 | "Trigger '" . $this->name . "' for action '$action' launched by " . __FILE__ . ". id=" . $object->id 460 | ); 461 | } elseif ($action == 'MEMBER_RESILIATE') { 462 | dol_syslog( 463 | "Trigger '" . $this->name . "' for action '$action' launched by " . __FILE__ . ". id=" . $object->id 464 | ); 465 | } elseif ($action == 'MEMBER_DELETE') { 466 | dol_syslog( 467 | "Trigger '" . $this->name . "' for action '$action' launched by " . __FILE__ . ". id=" . $object->id 468 | ); 469 | } 470 | 471 | // Categories 472 | elseif ($action == 'CATEGORY_CREATE') { 473 | dol_syslog( 474 | "Trigger '" . $this->name . "' for action '$action' launched by " . __FILE__ . ". id=" . $object->id 475 | ); 476 | } elseif ($action == 'CATEGORY_MODIFY') { 477 | dol_syslog( 478 | "Trigger '" . $this->name . "' for action '$action' launched by " . __FILE__ . ". id=" . $object->id 479 | ); 480 | } elseif ($action == 'CATEGORY_DELETE') { 481 | dol_syslog( 482 | "Trigger '" . $this->name . "' for action '$action' launched by " . __FILE__ . ". id=" . $object->id 483 | ); 484 | } 485 | 486 | // Projects 487 | elseif ($action == 'PROJECT_CREATE') { 488 | dol_syslog( 489 | "Trigger '" . $this->name . "' for action '$action' launched by " . __FILE__ . ". id=" . $object->id 490 | ); 491 | } elseif ($action == 'PROJECT_MODIFY') { 492 | dol_syslog( 493 | "Trigger '" . $this->name . "' for action '$action' launched by " . __FILE__ . ". id=" . $object->id 494 | ); 495 | } elseif ($action == 'PROJECT_DELETE') { 496 | dol_syslog( 497 | "Trigger '" . $this->name . "' for action '$action' launched by " . __FILE__ . ". id=" . $object->id 498 | ); 499 | } 500 | 501 | // Project tasks 502 | elseif ($action == 'TASK_CREATE') { 503 | dol_syslog( 504 | "Trigger '" . $this->name . "' for action '$action' launched by " . __FILE__ . ". id=" . $object->id 505 | ); 506 | } elseif ($action == 'TASK_MODIFY') { 507 | dol_syslog( 508 | "Trigger '" . $this->name . "' for action '$action' launched by " . __FILE__ . ". id=" . $object->id 509 | ); 510 | } elseif ($action == 'TASK_DELETE') { 511 | dol_syslog( 512 | "Trigger '" . $this->name . "' for action '$action' launched by " . __FILE__ . ". id=" . $object->id 513 | ); 514 | } 515 | 516 | // Task time spent 517 | elseif ($action == 'TASK_TIMESPENT_CREATE') { 518 | dol_syslog( 519 | "Trigger '" . $this->name . "' for action '$action' launched by " . __FILE__ . ". id=" . $object->id 520 | ); 521 | } elseif ($action == 'TASK_TIMESPENT_MODIFY') { 522 | dol_syslog( 523 | "Trigger '" . $this->name . "' for action '$action' launched by " . __FILE__ . ". id=" . $object->id 524 | ); 525 | } elseif ($action == 'TASK_TIMESPENT_DELETE') { 526 | dol_syslog( 527 | "Trigger '" . $this->name . "' for action '$action' launched by " . __FILE__ . ". id=" . $object->id 528 | ); 529 | } 530 | 531 | // Shipping 532 | elseif ($action == 'SHIPPING_CREATE') { 533 | dol_syslog( 534 | "Trigger '" . $this->name . "' for action '$action' launched by " . __FILE__ . ". id=" . $object->id 535 | ); 536 | } elseif ($action == 'SHIPPING_MODIFY') { 537 | dol_syslog( 538 | "Trigger '" . $this->name . "' for action '$action' launched by " . __FILE__ . ". id=" . $object->id 539 | ); 540 | } elseif ($action == 'SHIPPING_VALIDATE') { 541 | dol_syslog( 542 | "Trigger '" . $this->name . "' for action '$action' launched by " . __FILE__ . ". id=" . $object->id 543 | ); 544 | } elseif ($action == 'SHIPPING_SENTBYMAIL') { 545 | dol_syslog( 546 | "Trigger '" . $this->name . "' for action '$action' launched by " . __FILE__ . ". id=" . $object->id 547 | ); 548 | } elseif ($action == 'SHIPPING_DELETE') { 549 | dol_syslog( 550 | "Trigger '" . $this->name . "' for action '$action' launched by " . __FILE__ . ". id=" . $object->id 551 | ); 552 | } elseif ($action == 'SHIPPING_BUILDDOC') { 553 | dol_syslog( 554 | "Trigger '" . $this->name . "' for action '$action' launched by " . __FILE__ . ". id=" . $object->id 555 | ); 556 | } 557 | 558 | // File 559 | elseif ($action == 'FILE_UPLOAD') { 560 | dol_syslog( 561 | "Trigger '" . $this->name . "' for action '$action' launched by " . __FILE__ . ". id=" . $object->id 562 | ); 563 | } elseif ($action == 'FILE_DELETE') { 564 | dol_syslog( 565 | "Trigger '" . $this->name . "' for action '$action' launched by " . __FILE__ . ". id=" . $object->id 566 | ); 567 | } 568 | 569 | return 0; 570 | } 571 | } -------------------------------------------------------------------------------- /inventory.php: -------------------------------------------------------------------------------- 1 | 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 3 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 | require('config.php'); 20 | 21 | ini_set('memory_limit', '512M'); 22 | 23 | require('./class/inventory.class.php'); 24 | require('./lib/inventory.lib.php'); 25 | require_once DOL_DOCUMENT_ROOT.'/core/lib/ajax.lib.php'; 26 | require_once DOL_DOCUMENT_ROOT.'/core/lib/product.lib.php'; 27 | include_once DOL_DOCUMENT_ROOT.'/core/lib/admin.lib.php'; 28 | include_once DOL_DOCUMENT_ROOT.'/product/class/product.class.php'; 29 | include_once DOL_DOCUMENT_ROOT.'/product/stock/class/entrepot.class.php'; 30 | include_once DOL_DOCUMENT_ROOT.'/product/class/html.formproduct.class.php'; 31 | 32 | set_time_limit(0); 33 | $dol_version = (float) DOL_VERSION; 34 | 35 | if(!$user->rights->inventory->read) accessforbidden(); 36 | 37 | $langs->load("inventory@inventory"); 38 | 39 | $contextpage = 'inventoryatmcard'; 40 | 41 | include DOL_DOCUMENT_ROOT.'/core/actions_changeselectedfields.inc.php'; 42 | 43 | $hookmanager->initHooks(array('inventoryatmcard')); 44 | 45 | _action(); 46 | 47 | function _action() 48 | { 49 | global $user, $db, $conf, $langs, $hookmanager; 50 | $PDOdb=new TPDOdb; 51 | //$PDOdb->debug=true; 52 | 53 | /******************************************************************* 54 | * ACTIONS 55 | * 56 | * Put here all code to do according to value of "action" parameter 57 | ********************************************************************/ 58 | 59 | $action=__get('action','list'); 60 | 61 | switch($action) { 62 | case 'list': 63 | _liste($user, $db, $conf, $langs); 64 | 65 | break; 66 | 67 | case 'create': 68 | if (!$user->rights->inventory->create) accessforbidden(); 69 | 70 | $PDOdb = new TPDOdb; 71 | $inventory = new TInventory; 72 | 73 | _fiche_warehouse($PDOdb, $user, $db, $conf, $langs, $inventory); 74 | 75 | break; 76 | 77 | case 'confirmCreate': 78 | if (!$user->rights->inventory->create) accessforbidden(); 79 | 80 | $PDOdb = new TPDOdb; 81 | $inventory = new TInventory; 82 | $inventory->set_values($_REQUEST); 83 | 84 | $fk_inventory = $inventory->save($PDOdb); 85 | $fk_category = GETPOST('fk_category', 'array'); 86 | $fk_supplier = (int)GETPOST('fk_supplier','int'); 87 | $fk_warehouse = (int)GETPOST('fk_warehouse','int'); 88 | $only_prods_in_stock = (int)GETPOST('OnlyProdsInStock','int'); 89 | $inventoryWithBatchDetail = (int)GETPOST('inventoryWithBatchDetail','int'); 90 | $inventory->per_batch = $inventoryWithBatchDetail; 91 | 92 | 93 | $e = new Entrepot($db); 94 | $e->fetch($fk_warehouse); 95 | $TChildWarehouses = array($fk_warehouse); 96 | if(method_exists($e, 'get_children_warehouses')) $e->get_children_warehouses($fk_warehouse, $TChildWarehouses); 97 | 98 | $sql = 'SELECT p.rowid AS fk_product, sm.fk_entrepot, SUM(sm.value) AS qty'; 99 | 100 | // Add fields from hooks 101 | $parameters=array(); 102 | $reshook=$hookmanager->executeHooks('printFieldListSelect',$parameters); // Note that $action and $object may have been modified by hook 103 | $sql.=$hookmanager->resPrint; 104 | 105 | $sql.= ' FROM '.MAIN_DB_PREFIX.'product p'; 106 | $sql.= ' LEFT JOIN '.MAIN_DB_PREFIX.'product_stock ps ON (p.rowid = ps.fk_product)'; 107 | $sql.= ' INNER JOIN '.MAIN_DB_PREFIX.'stock_mouvement sm ON (p.rowid = sm.fk_product)'; 108 | $sql.= ' LEFT JOIN '.MAIN_DB_PREFIX.'categorie_product cp ON (cp.fk_product = p.rowid)'; 109 | $sql.= ' LEFT JOIN '.MAIN_DB_PREFIX.'product_fournisseur_price pfp ON (pfp.fk_product = p.rowid)'; 110 | $sql.= ' WHERE sm.fk_entrepot IN ('.implode(', ', $TChildWarehouses).')'; 111 | if (!empty($inventory->date_inventory)) $sql.= ' AND sm.datem < "'.date('Y-m-d 23:59:59', $inventory->date_inventory).'"'; 112 | if (is_array($fk_category) && !empty($fk_category)) $sql.= ' AND cp.fk_categorie IN ('.implode(',',$fk_category).')'; 113 | if ($fk_supplier > 0) $sql.= ' AND pfp.fk_soc = '.$fk_supplier; 114 | 115 | $parameters=array('fk_category'=>$fk_category, 'fk_supplier' => $fk_supplier, 'only_prods_in_stock' => $only_prods_in_stock); 116 | $reshook=$hookmanager->executeHooks('printFieldListWhere',$parameters,$inventory,$action); // Note that $action and $object may have been modified by some hooks 117 | if ($reshook < 0) setEventMessages($hookmanager->error, $hookmanager->errors, 'errors'); 118 | else $sql.=$hookmanager->resPrint; 119 | 120 | $sql.= ' GROUP BY p.rowid, sm.fk_entrepot'; 121 | 122 | if ($only_prods_in_stock > 0) $sql.= ' HAVING qty > 0'; 123 | 124 | $sql.= ' ORDER BY p.ref ASC, p.label ASC'; 125 | 126 | $Tab = $PDOdb->ExecuteAsArray($sql); 127 | 128 | foreach($Tab as &$row) { 129 | 130 | $inventory->add_product($PDOdb, $row->fk_product, $row->fk_entrepot, GETPOST('includeWithStockPMP','alpha')!='' ); 131 | $product = new Product($db); 132 | $product->fetch($row->fk_product); 133 | if($inventoryWithBatchDetail && $product->hasbatch()) $inventory->add_batch($PDOdb, $row->fk_product, $row->fk_entrepot, $inventory->get_date('date_inventory', 'Y-m-d'), GETPOST('includeWithStockPMP','alpha')!='' ); 134 | } 135 | 136 | $inventory->save($PDOdb); 137 | 138 | header('Location: '.dol_buildpath('inventory/inventory.php?id='.$inventory->getId().'&action=edit', 1)); 139 | 140 | case 'view': 141 | case 'edit': 142 | if (!$user->rights->inventory->write) accessforbidden(); 143 | 144 | $PDOdb = new TPDOdb; 145 | $id = __get('id', 0, 'int'); 146 | 147 | $inventory = new TInventory; 148 | $inventory->load($PDOdb, $id); 149 | 150 | _fiche($PDOdb, $user, $db, $conf, $langs, $inventory, __get('action', 'edit', 'string')); 151 | 152 | break; 153 | 154 | case 'save': 155 | if (!$user->rights->inventory->write) accessforbidden(); 156 | 157 | $PDOdb = new TPDOdb; 158 | $id = __get('id', 0, 'int'); 159 | 160 | $inventory = new TInventory; 161 | $inventory->load($PDOdb, $id); 162 | 163 | $inventory->set_values($_REQUEST); 164 | 165 | if ($inventory->errors) 166 | { 167 | setEventMessage($inventory->errors, 'errors'); 168 | _fiche($PDOdb, $user, $db, $conf, $langs, $inventory, 'edit'); 169 | } 170 | else 171 | { 172 | $inventory->save($PDOdb); 173 | header('Location: '.dol_buildpath('inventory/inventory.php?id='.$inventory->getId().'&action=view', 1)); 174 | } 175 | 176 | break; 177 | 178 | case 'regulate': 179 | $PDOdb = new TPDOdb; 180 | $id = __get('id', 0, 'int'); 181 | 182 | $inventory = new TInventory; 183 | $inventory->load($PDOdb, $id); 184 | 185 | if($inventory->status == 0) { 186 | $inventory->status = 1; 187 | $inventory->save($PDOdb); 188 | 189 | _fiche($PDOdb, $user, $db, $conf, $langs, $inventory, 'view'); 190 | 191 | 192 | } 193 | else { 194 | _fiche($PDOdb, $user, $db, $conf, $langs, $inventory, 'view'); 195 | } 196 | 197 | break; 198 | 199 | case 'changePMP': 200 | $PDOdb = new TPDOdb; 201 | $id = __get('id', 0, 'int'); 202 | 203 | $inventory = new TInventory; 204 | $inventory->load($PDOdb, $id); 205 | 206 | $inventory->changePMP($PDOdb); 207 | 208 | _fiche($PDOdb, $user, $db, $conf, $langs, $inventory, 'view'); 209 | 210 | break; 211 | 212 | case 'add_line': 213 | if (!$user->rights->inventory->write) accessforbidden(); 214 | 215 | $PDOdb = new TPDOdb; 216 | $id = __get('id', 0, 'int'); 217 | $fk_warehouse = __get('fk_warehouse', 0, 'int'); 218 | 219 | $inventory = new TInventory; 220 | $inventory->load($PDOdb, $id); 221 | 222 | $type = (!empty($conf->use_javascript_ajax) && !empty($conf->global->PRODUIT_USE_SEARCH_TO_SELECT) ? 'string' : 'int'); //AA heu ? 223 | 224 | $fk_product = __get('fk_product', 0, $type); 225 | 226 | if ($fk_product) 227 | { 228 | $product = new Product($db); 229 | $product->fetch($fk_product); // ! ref TODO vérifier quand même 230 | if($product->type != 0) { 231 | setEventMessage($langs->trans('ThisIsNotAProduct'),'errors'); 232 | } 233 | else{ 234 | 235 | //Check product not already exists 236 | $alreadyExists = false; 237 | foreach ($inventory->TInventorydet as $invdet) 238 | { 239 | if ($invdet->fk_product == $product->id 240 | && $invdet->fk_warehouse == $fk_warehouse) 241 | { 242 | $alreadyExists = true; 243 | break; 244 | } 245 | } 246 | 247 | if (!$alreadyExists) 248 | { 249 | $inventory->add_product($PDOdb, $product->id, $fk_warehouse); 250 | 251 | } 252 | else 253 | { 254 | setEventMessage($langs->trans('inventoryWarningProductAlreadyExists'), 'warnings'); 255 | } 256 | 257 | } 258 | 259 | $inventory->save($PDOdb); 260 | $inventory->sort_det(); 261 | } 262 | 263 | _fiche($PDOdb, $user, $db, $conf, $langs, $inventory, 'edit'); 264 | 265 | break; 266 | 267 | case 'delete_line': 268 | if (!$user->rights->inventory->write) accessforbidden(); 269 | $PDOdb = new TPDOdb; 270 | 271 | //Cette action devrais se faire uniquement si le status de l'inventaire est à 0 mais aucune vérif 272 | $rowid = __get('rowid', 0, 'int'); 273 | $TInventorydet = new TInventorydet; 274 | $TInventorydet->load($PDOdb, $rowid); 275 | $TInventorydet->delete($PDOdb); 276 | 277 | $id = __get('id', 0, 'int'); 278 | $inventory = new TInventory; 279 | $inventory->load($PDOdb, $id); 280 | 281 | _fiche($PDOdb, $user, $db, $conf, $langs, $inventory, 'edit'); 282 | 283 | break; 284 | case 'flush': 285 | if (!$user->rights->inventory->create) accessforbidden(); 286 | 287 | $PDOdb = new TPDOdb; 288 | $id = __get('id', 0, 'int'); 289 | 290 | $inventory = new TInventory; 291 | $inventory->load($PDOdb, $id); 292 | 293 | $inventory->deleteAllLine($PDOdb); 294 | 295 | setEventMessage('Inventaire vidé'); 296 | 297 | _fiche($PDOdb, $user, $db, $conf, $langs, $inventory, 'edit'); 298 | 299 | 300 | break; 301 | case 'delete': 302 | if (!$user->rights->inventory->create) accessforbidden(); 303 | 304 | $PDOdb = new TPDOdb; 305 | $id = __get('id', 0, 'int'); 306 | 307 | $inventory = new TInventory; 308 | $inventory->load($PDOdb, $id); 309 | 310 | $inventory->delete($PDOdb); 311 | 312 | header('Location: '.dol_buildpath('/inventory/inventory.php', 1)); 313 | exit; 314 | //_liste($user, $db, $conf, $langs); 315 | 316 | case 'printDoc': 317 | $PDOdb = new TPDOdb; 318 | $id = __get('id', 0, 'int'); 319 | 320 | $inventory = new TInventory; 321 | $inventory->load($PDOdb, $id); 322 | 323 | generateODT($PDOdb, $db, $conf, $langs, $inventory); 324 | break; 325 | 326 | case 'exportCSV': 327 | $PDOdb = new TPDOdb; 328 | $id = __get('id', 0, 'int'); 329 | 330 | $inventory = new TInventory; 331 | $inventory->load($PDOdb, $id); 332 | 333 | exportCSV($inventory); 334 | exit; 335 | 336 | break; 337 | 338 | default: 339 | //Rien 340 | break; 341 | } 342 | 343 | } 344 | 345 | function _liste(&$user, &$db, &$conf, &$langs) 346 | { 347 | global $dol_version, $module_helpurl; 348 | llxHeader('',$langs->trans('inventoryListTitle'),$module_helpurl,''); 349 | 350 | $form=new TFormCore; 351 | 352 | $inventory = new TInventory; 353 | $r = new TSSRenderControler($inventory); 354 | 355 | $sql="SELECT i.rowid, ".($dol_version >= 7 ? 'e.ref' : 'e.label').", i.date_inventory, i.fk_warehouse, i.date_cre, i.date_maj, i.status 356 | FROM ".MAIN_DB_PREFIX."inventory i 357 | LEFT JOIN ".MAIN_DB_PREFIX."entrepot e ON (e.rowid = i.fk_warehouse) 358 | WHERE i.entity=".(int) $conf->entity; 359 | 360 | if (!__get('TListTBS', 0, 'int')) $sql .= " ORDER BY i.rowid DESC"; 361 | $hide = $dol_version >= 7 ? 'ref' : 'label'; 362 | $THide = array($hide); 363 | 364 | $form=new TFormCore($_SERVER['PHP_SELF'], 'form', 'POST'); 365 | 366 | $ATMdb=new TPDOdb; 367 | $lien = '/product/stock/card.php'; 368 | if($dol_version < 3.8) $lien = '/product/stock/fiche.php'; 369 | 370 | $r->liste($ATMdb, $sql, array( 371 | 'limit'=>array( 372 | 'nbLine'=>'30' 373 | ) 374 | ,'subQuery'=>array() 375 | ,'link'=>array( 376 | 'fk_warehouse'=>''.img_picto('','object_stock.png','',0).' @'.($dol_version >= 7 ? 'ref' : 'label').'@' 377 | ) 378 | ,'translate'=>array() 379 | ,'hide'=>$THide 380 | ,'type'=>array( 381 | 'date_cre'=>'date' 382 | ,'date_maj'=>'datetime' 383 | ,'date_inventory'=>'date' 384 | ) 385 | ,'liste'=>array( 386 | 'titre'=>$langs->trans('inventoryListTitle') 387 | ,'image'=>img_picto('','title.png', '', 0) 388 | ,'picto_precedent'=>img_picto('','back.png', '', 0) 389 | ,'picto_suivant'=>img_picto('','next.png', '', 0) 390 | ,'noheader'=> (int)isset($_REQUEST['fk_soc']) | (int)isset($_REQUEST['fk_product']) 391 | ,'messageNothing'=>$langs->trans('inventoryListEmpty') 392 | ,'picto_search'=>img_picto('','search.png', '', 0) 393 | ) 394 | ,'title'=>array( 395 | 'rowid'=>'Numéro' 396 | ,'fk_warehouse'=>'Entrepôt' 397 | ,'date_inventory'=>'Date inventaire' 398 | ,'date_cre'=>'Date création' 399 | ,'date_maj'=>'Date mise à jour' 400 | ,'status'=>'Status' 401 | ) 402 | ,'eval'=>array( 403 | 'status' => '(@val@ ? img_picto("'.$langs->trans("inventoryValidate").'", "statut4") : img_picto("'.$langs->trans("inventoryDraft").'", "statut3"))' 404 | ,'rowid'=>'TInventory::getLink(@val@)' 405 | 406 | ) 407 | )); 408 | 409 | $form->end(); 410 | 411 | if ($user->rights->inventory->create) 412 | { 413 | print '
'; 414 | print ''.$langs->trans('inventoryCreate').''; 415 | print '
'; 416 | } 417 | 418 | $ATMdb->close(); 419 | 420 | llxFooter(''); 421 | } 422 | 423 | function _fiche_warehouse(&$PDOdb, &$user, &$db, &$conf, $langs, $inventory) 424 | { 425 | global $module_helpurl; 426 | dol_include_once('/categories/class/categorie.class.php'); 427 | 428 | llxHeader('',$langs->trans('inventorySelectWarehouse'),$module_helpurl,''); 429 | print dol_get_fiche_head(inventoryPrepareHead($inventory)); 430 | 431 | $form=new TFormCore('inventory.php', 'confirmCreate'); 432 | print $form->hidden('action', 'confirmCreate'); 433 | $form->Set_typeaff('edit'); 434 | 435 | $formproduct = new FormProduct($db); 436 | $formDoli = new Form($db); 437 | 438 | ?> 439 | 440 | 441 | 442 | 443 | 444 | 445 | 446 | 447 | 448 | 449 | 450 | 451 | 452 | 453 | 454 | 455 | 456 | 457 | 458 | 459 | 460 | 461 | 462 | 463 | 464 | 465 | 466 | 467 | 468 | 469 | 470 | 471 | productbatch->enabled) { ?> 472 | 473 | 474 | 475 | 476 | 477 |
trans('Title') ?>texte('', 'title', '',50,255) ?>
trans('Date') ?>calendrier('', 'date_inventory',time()) ?>
trans('inventorySelectWarehouse') ?>selectWarehouses('', 'fk_warehouse') ?>
trans('SelectCategory') ?>select_all_categories(0,'', 'fk_category[]') ?>
trans('SelectFournisseur') ?>select_company('','fk_supplier','s.fournisseur = 1', 1) ?>
trans('OnlyProdsInStock') ?>
trans('IncludeProdWithCurrentStockValue') ?>
trans('InventoryWithBatchDetail') ?>
478 | '; 481 | print ''; 482 | print ''; 483 | 484 | print $form->end_form(); 485 | llxFooter(''); 486 | ?> 487 | 492 | trans('inventoryEdit'),$module_helpurl,''); 500 | 501 | $action = GETPOST('action','alphanohtml'); 502 | $reshook=$hookmanager->executeHooks('doActions', $parameters,$inventory,$action); 503 | 504 | $warehouse = new Entrepot($db); 505 | $warehouse->fetch($inventory->fk_warehouse); 506 | 507 | print dol_get_fiche_head(inventoryPrepareHead($inventory, $langs->trans('inventoryOfWarehouse', $warehouse->libelle), '&action='.$mode)); 508 | 509 | //Récupération du tableau des champs extrafields que l'on peut ajouter en tant que colonne 510 | $arrayfields = array(); 511 | $extrafields = new ExtraFields($db); 512 | 513 | $product = new Product($db); 514 | 515 | $extrafields->fetch_name_optionals_label('product'); 516 | $extrafields->getOptionalsFromPost($product->table_element,'','ef_'); 517 | 518 | if (is_array($extrafields->attributes[$product->table_element]['label']) && count($extrafields->attributes[$product->table_element]['label'])) 519 | { 520 | foreach($extrafields->attributes[$product->table_element]['label'] as $key => $val) 521 | { 522 | if (! empty($extrafields->attributes[$product->table_element]['list'][$key])) 523 | $arrayfields["ef.".$key]=array('label'=>$extrafields->attributes[$product->table_element]['label'][$key], 'checked'=>0, 'position'=>$extrafields->attributes[$product->table_element]['pos'][$key], 'enabled'=>(abs($extrafields->attributes[$product->table_element]['list'][$key])!=3 && $extrafields->attributes[$product->table_element]['perms'][$key])); 524 | } 525 | } 526 | 527 | $extrafieldsobjectkey = 'product'; 528 | 529 | $arrayfields = dol_sort_array($arrayfields, 'position'); 530 | 531 | $form=new TFormCore(); 532 | $form->Set_typeaff($mode); 533 | 534 | $TInventory = array(); 535 | $Tinventory = _fiche_ligne($db, $user, $langs, $inventory, $TInventory, $form, $mode); 536 | 537 | $TBS=new TTemplateTBS(); 538 | $TBS->TBS->protect=false; 539 | $TBS->TBS->noerr=true; 540 | 541 | //set_time_limit(10); 542 | //var_dump($inventory);exit; 543 | 544 | print ''.$langs->trans('inventoryOnDate')." ".$inventory->get_date('date_inventory', 'd/m/Y').'

'; 545 | 546 | $inventoryTPL = array( 547 | 'id'=> $inventory->getId() 548 | ,'date_cre' => $inventory->get_date('date_cre', 'd/m/Y') 549 | ,'date_maj' => $inventory->get_date('date_maj', 'd/m/Y H:i') 550 | ,'fk_warehouse' => $inventory->fk_warehouse 551 | ,'status' => $inventory->status 552 | ,'entity' => $inventory->entity 553 | ,'amount' => price( round($inventory->amount,2) ) 554 | ,'amount_actual'=>price (round($inventory->amount_actual,2)) 555 | 556 | ); 557 | 558 | $view = array( 559 | 'mode' => $mode 560 | ,'url' => dol_buildpath('/inventory/inventory.php', 1) 561 | ,'can_validate' => (int) $user->rights->inventory->validate 562 | ,'is_already_validate' => (int) $inventory->status 563 | ,'per_batch' => $inventory->per_batch 564 | ,'token'=>$_SESSION['newtoken'] 565 | ); 566 | 567 | $product = array( 568 | 'list'=>inventorySelectProducts($PDOdb, $inventory) 569 | ); 570 | 571 | include './tpl/inventory.tpl.php'; 572 | $reshook = $hookmanager->executeHooks('addMoreActionsButtons', $parameters, $inventory, $action); 573 | llxFooter(''); 574 | } 575 | 576 | 577 | function _fiche_ligne(&$db, &$user, &$langs, &$inventory, &$TInventory, &$form, $mode) 578 | { 579 | global $db,$conf, $extrafieldsobjectkey; 580 | 581 | $inventory->amount_actual = 0; 582 | 583 | $TCacheEntrepot = array(); 584 | 585 | foreach ($inventory->TInventorydet as $k => $TInventorydet) 586 | { 587 | 588 | $product = & $TInventorydet->product; 589 | $stock = $TInventorydet->qty_stock; 590 | 591 | if ($inventory->per_batch && $product->hasbatch()) 592 | { 593 | $product->load_stock(); 594 | $lotstotal = 0; 595 | if (!empty($product->stock_warehouse[$inventory->fk_warehouse]->detail_batch) && is_array($product->stock_warehouse[$inventory->fk_warehouse]->detail_batch)) 596 | { 597 | foreach ($product->stock_warehouse[$inventory->fk_warehouse]->detail_batch as $lot => $details) 598 | { 599 | $lotstotal += $details->qty; 600 | } 601 | } 602 | 603 | $lotparent = ''; 604 | if ((float) $lotstotal !== (float) $stock) 605 | { 606 | $lotparent = img_picto('Stock à corriger', 'error'); 607 | } 608 | // var_dump($lotstotal, $stock); exit; 609 | } 610 | 611 | $pmp = $TInventorydet->pmp; 612 | $pmp_actual = $pmp * $stock; 613 | $inventory->amount_actual+=$pmp_actual; 614 | 615 | $last_pa = $TInventorydet->pa; 616 | $current_pa = $TInventorydet->current_pa; 617 | 618 | if(!empty($conf->global->INVENTORY_USE_MIN_PA_OR_LAST_PA_MIN_PMP_IS_NULL) && empty($pmp_actual)) { 619 | if(!empty($last_pa)){ $pmp_actual = $last_pa* $stock;$pmp=$last_pa;} 620 | else if(!empty($current_pa)) {$pmp_actual = $current_pa* $stock; $pmp=$current_pa;} 621 | } 622 | 623 | $e = new Entrepot($db); 624 | if(!empty($TCacheEntrepot[$TInventorydet->fk_warehouse])) $e = $TCacheEntrepot[$TInventorydet->fk_warehouse]; 625 | elseif($e->fetch($TInventorydet->fk_warehouse) > 0) $TCacheEntrepot[$e->id] = $e; 626 | if($inventory->per_batch) { 627 | 628 | if ($TInventorydet->lot == '') $lastprodline = $k; 629 | 630 | $inventoryItem = array( 631 | // 'produit' => $product->getNomUrl(1).' - '.$product->label 632 | // ,'entrepot'=>$e->getNomUrl(1) 633 | // ,'barcode' => $product->barcode 634 | // ,'qty' => ($TInventorydet->lot == '') ? '' : $form->texte('', 'qty_to_add['.$k.']', (isset($_REQUEST['qty_to_add'][$k]) ? $_REQUEST['qty_to_add'][$k] : 0), 8, 0, "style='text-align:center;'") 635 | // .($form->type_aff!='view' ? ''.img_picto('Ajouter', 'plus16@inventory').'' : '') 636 | // ,'qty_view' => $TInventorydet->qty_view ? $TInventorydet->qty_view : 0 637 | // ,'qty_stock' => $stock 638 | // ,'qty_regulated' => $TInventorydet->qty_regulated ? $TInventorydet->qty_regulated : 0 639 | // ,'action' => $user->rights->inventory->write ? ''.img_picto($langs->trans('inventoryDeleteLine'), 'delete').'' : '' 640 | // ,'pmp_stock'=>round($pmp_actual,2) 641 | // ,'pmp_actual'=> round($pmp * $TInventorydet->qty_view,2) 642 | // ,'pmp_new'=> '' 643 | // ,'pa_stock'=>round($last_pa * $stock,2) 644 | // ,'pa_actual'=>round($last_pa * $TInventorydet->qty_view,2) 645 | // ,'current_pa_stock'=>round($current_pa * $stock,2) 646 | // ,'current_pa_actual'=>round($current_pa * $TInventorydet->qty_view,2) 647 | // ,'lot' => $TInventorydet->lot 648 | // ,'k'=>$k 649 | // ,'id'=>$TInventorydet->getId() 650 | 651 | 'produit' => ($TInventorydet->lot == '') ? $product->getNomUrl(1).' - '.$product->label : $product->getNomUrl(1) 652 | ,'entrepot'=>$e->getNomUrl(1) 653 | ,'barcode' => $product->barcode 654 | ,'lot' => $TInventorydet->lot.(($TInventorydet->lot !== '') ? '': (($mode == "edit" && $product->hasbatch()) ? '' . img_picto('Ajouter un lot', 'plus16@inventory') . ' ' : '') . $lotparent) 655 | ,'qty' => ($TInventorydet->lot == '' && $product->hasbatch()) ? '' : ($form->type_aff!='view' ? ''.img_picto('Enlever', 'minus16@inventory').'' : '' ). 656 | ($form->texte('', 'qty_to_add['.$k.']', (isset($_REQUEST['qty_to_add'][$k]) ? $_REQUEST['qty_to_add'][$k] : 0), 8, 0, "style='text-align:center;'")) 657 | .($form->type_aff!='view' ? ''.img_picto('Ajouter', 'plus16@inventory').'' : '') 658 | ,'qty_view' => $TInventorydet->qty_view ? $TInventorydet->qty_view : 0 659 | ,'qty_stock' => $stock 660 | ,'qty_regulated' => $TInventorydet->qty_regulated ? $TInventorydet->qty_regulated : 0 661 | ,'action' => $user->rights->inventory->write ? ''.img_picto($langs->trans('inventoryDeleteLine'), 'delete').'' : '' 662 | ,'pmp_stock'=>round($pmp_actual,2) 663 | ,'pmp_actual'=> round($pmp * $TInventorydet->qty_view,2) 664 | ,'pmp_new'=>($TInventorydet->lot == '') ? (!empty($user->rights->inventory->changePMP) ? $form->texte('', 'new_pmp['.$k.']',$TInventorydet->new_pmp, 8, 0, "style='text-align:right;'") 665 | .($form->type_aff!='view' ? ''.img_picto($langs->trans('Save'), 'bt-save.png@inventory').'' : '') : '' ) : "" 666 | ,'pa_stock'=>round($last_pa * $stock,2) 667 | ,'pa_actual'=>round($last_pa * $TInventorydet->qty_view,2) 668 | ,'current_pa_stock'=>round($current_pa * $stock,2) 669 | ,'current_pa_actual'=>round($current_pa * $TInventorydet->qty_view,2) 670 | ,'k'=>$k 671 | ,'id'=>$TInventorydet->getId() 672 | ,'fk_product'=>$product->id 673 | ); 674 | 675 | 676 | //var_dump($product->stock_warehouse[$e->id]->detail_batch); exit; 677 | 678 | } else { 679 | $inventoryItem = array( 680 | 'produit' => _productGetNomUrl($product).' - '.$product->label 681 | ,'entrepot'=>_entrepotGetNomUrl($e) 682 | ,'barcode' => $product->barcode 683 | ,'qty' => ($form->type_aff!='view' ? ''.img_picto('Enlever', 'minus16@inventory').'' : '' ). 684 | ($form->texte('', 'qty_to_add['.$k.']', (isset($_REQUEST['qty_to_add'][$k]) ? $_REQUEST['qty_to_add'][$k] : 0), 8, 0, "style='text-align:center;'")) 685 | .($form->type_aff!='view' ? ''.img_picto('Ajouter', 'plus16@inventory').'' : '') 686 | ,'qty_view' => $TInventorydet->qty_view ? $TInventorydet->qty_view : 0 687 | ,'qty_stock' => $stock 688 | ,'qty_regulated' => $TInventorydet->qty_regulated ? $TInventorydet->qty_regulated : 0 689 | ,'action' => $user->rights->inventory->write ? ''.img_picto($langs->trans('inventoryDeleteLine'), 'delete').'' : '' 690 | ,'pmp_stock'=>round($pmp_actual,2) 691 | ,'pmp_actual'=> round($pmp * $TInventorydet->qty_view,2) 692 | ,'pmp_new'=>(!empty($user->rights->inventory->changePMP) ? $form->texte('', 'new_pmp['.$k.']',$TInventorydet->new_pmp, 8, 0, "style='text-align:right;'") 693 | .($form->type_aff!='view' ? ''.img_picto($langs->trans('Save'), 'bt-save.png@inventory').'' : '') : '' ) 694 | ,'pa_stock'=>round($last_pa * $stock,2) 695 | ,'pa_actual'=>round($last_pa * $TInventorydet->qty_view,2) 696 | ,'current_pa_stock'=>round($current_pa * $stock,2) 697 | ,'current_pa_actual'=>round($current_pa * $TInventorydet->qty_view,2) 698 | 699 | ,'k'=>$k 700 | ,'id'=>$TInventorydet->getId() 701 | ,'fk_product'=>$product->id 702 | ); 703 | } 704 | 705 | 706 | $inventoryItem['fk_warehouse'] = $e->id; 707 | 708 | $TInventory[] = $inventoryItem; 709 | } 710 | 711 | } 712 | 713 | function exportCSV(&$inventory) { 714 | global $conf, $db, $hookmanager; 715 | 716 | header('Content-Type: application/octet-stream'); 717 | header('Content-disposition: attachment; filename=inventory-'. $inventory->getId().'-'.date('Ymd-His').'.csv'); 718 | header('Pragma: no-cache'); 719 | header('Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0'); 720 | header('Expires: 0'); 721 | 722 | echo 'Ref;Label;'; 723 | if($inventory->per_batch) echo 'Lot;'; 724 | echo 'barcode;qty theorique;PMP;dernier PA;'; 725 | if(!empty($conf->global->INVENTORY_USE_MIN_PA_IF_NO_LAST_PA)) echo 'PA courant;'; 726 | echo 'qty réelle;PMP;dernier PA;'; 727 | if(!empty($conf->global->INVENTORY_USE_MIN_PA_IF_NO_LAST_PA)) echo 'PA courant;'; 728 | echo 'qty regulée;'; 729 | 730 | // Add fields from hooks 731 | $parameters=array(); 732 | $reshook=$hookmanager->executeHooks('printExportColumnTitle',$parameters, $inventory); // Note that $action and $object may have been modified by hook 733 | if ($reshook < 0) dol_print_error($db, $hookmanager->error, $hookmanager->errors); 734 | else print $hookmanager->resPrint; 735 | 736 | echo "\r\n"; 737 | 738 | foreach ($inventory->TInventorydet as $k => $TInventorydet) 739 | { 740 | $product = & $TInventorydet->product; 741 | $stock = $TInventorydet->qty_stock; 742 | $lot = $TInventorydet->lot; 743 | 744 | $pmp = $TInventorydet->pmp; 745 | $pmp_actual = $pmp * $stock; 746 | $inventory->amount_actual+=$pmp_actual; 747 | 748 | $last_pa = $TInventorydet->pa; 749 | $current_pa = $TInventorydet->current_pa; 750 | 751 | if(!empty($conf->global->INVENTORY_USE_MIN_PA_OR_LAST_PA_MIN_PMP_IS_NULL) && empty($pmp_actual)) { 752 | if(!empty($last_pa)){ $pmp_actual = $last_pa* $stock;$pmp=$last_pa;} 753 | else if(!empty($current_pa)) {$pmp_actual = $current_pa* $stock; $pmp=$current_pa;} 754 | } 755 | 756 | if(!empty($conf->global->INVENTORY_USE_MIN_PA_IF_NO_LAST_PA)) { 757 | if($inventory->per_batch) { 758 | $row = array( 759 | 'produit' => $product->ref 760 | , 'label' => $product->label 761 | , 'lot' => $lot 762 | , 'barcode' => $product->barcode 763 | , 'qty_stock' => $stock 764 | , 'pmp_stock' => round($pmp_actual, 2) 765 | , 'pa_stock' => round($last_pa * $stock, 2) 766 | , 'current_pa_stock' => round($current_pa * $stock, 2) 767 | , 'qty_view' => $TInventorydet->qty_view ? $TInventorydet->qty_view : 0 768 | , 'pmp_actual' => round($pmp * $TInventorydet->qty_view, 2) 769 | , 'pa_actual' => round($last_pa * $TInventorydet->qty_view, 2) 770 | , 'current_pa_actual' => round($current_pa * $TInventorydet->qty_view, 2) 771 | , 'qty_regulated' => $TInventorydet->qty_regulated ? $TInventorydet->qty_regulated : 0 772 | ); 773 | } else { 774 | $row = array( 775 | 'produit' => $product->ref 776 | , 'label' => $product->label 777 | , 'barcode' => $product->barcode 778 | , 'qty_stock' => $stock 779 | , 'pmp_stock' => round($pmp_actual, 2) 780 | , 'pa_stock' => round($last_pa * $stock, 2) 781 | , 'current_pa_stock' => round($current_pa * $stock, 2) 782 | , 'qty_view' => $TInventorydet->qty_view ? $TInventorydet->qty_view : 0 783 | , 'pmp_actual' => round($pmp * $TInventorydet->qty_view, 2) 784 | , 'pa_actual' => round($last_pa * $TInventorydet->qty_view, 2) 785 | , 'current_pa_actual' => round($current_pa * $TInventorydet->qty_view, 2) 786 | , 'qty_regulated' => $TInventorydet->qty_regulated ? $TInventorydet->qty_regulated : 0 787 | ); 788 | } 789 | } 790 | else{ 791 | if($inventory->per_batch) { 792 | $row = array( 793 | 'produit' => $product->ref 794 | , 'label' => $product->label 795 | , 'lot' => $lot 796 | , 'barcode' => $product->barcode 797 | , 'qty_stock' => $stock 798 | , 'pmp_stock' => round($pmp_actual, 2) 799 | , 'pa_stock' => round($last_pa * $stock, 2) 800 | , 'qty_view' => $TInventorydet->qty_view ? $TInventorydet->qty_view : 0 801 | , 'pmp_actual' => round($pmp * $TInventorydet->qty_view, 2) 802 | , 'pa_actual' => round($last_pa * $TInventorydet->qty_view, 2) 803 | , 'qty_regulated' => $TInventorydet->qty_regulated ? $TInventorydet->qty_regulated : 0 804 | ); 805 | } else { 806 | $row = array( 807 | 'produit' => $product->ref 808 | , 'label' => $product->label 809 | , 'barcode' => $product->barcode 810 | , 'qty_stock' => $stock 811 | , 'pmp_stock' => round($pmp_actual, 2) 812 | , 'pa_stock' => round($last_pa * $stock, 2) 813 | , 'qty_view' => $TInventorydet->qty_view ? $TInventorydet->qty_view : 0 814 | , 'pmp_actual' => round($pmp * $TInventorydet->qty_view, 2) 815 | , 'pa_actual' => round($last_pa * $TInventorydet->qty_view, 2) 816 | , 'qty_regulated' => $TInventorydet->qty_regulated ? $TInventorydet->qty_regulated : 0 817 | ); 818 | } 819 | 820 | } 821 | 822 | // Add fields from hooks 823 | $parameters=array('row'=>&$row, 'TInventorydet'=>$TInventorydet); 824 | $reshook=$hookmanager->executeHooks('printExportColumnContent',$parameters, $inventory); // Note that $action and $object may have been modified by hook 825 | if ($reshook < 0) dol_print_error($db, $hookmanager->error, $hookmanager->errors); 826 | 827 | echo '"'.implode('";"', $row).'"'."\r\n"; 828 | 829 | } 830 | 831 | exit; 832 | } 833 | 834 | function generateODT(&$PDOdb, &$db, &$conf, &$langs, &$inventory) 835 | { 836 | global $hookmanager; 837 | $TBS=new TTemplateTBS(); 838 | 839 | $TInventoryPrint = array(); // Tableau envoyé à la fonction render contenant les informations concernant l'inventaire 840 | 841 | foreach($inventory->TInventorydet as $k => $v) 842 | { 843 | $prod = new Product($db); 844 | $prod->fetch($v->fk_product); 845 | //$prod->fetch_optionals($prod->id); 846 | 847 | $TInventoryPrint[] = array( 848 | 'product' => $prod->ref.' - '.$prod->label 849 | , 'lot' => isset($v->lot) ? $v->lot : '' 850 | , 'qty_view' => $v->qty_view 851 | ); 852 | 853 | // Add fields from hooks 854 | $parameters=array('TInventoryPrint'=>&$TInventoryPrint, 'TInventorydet'=> $v); 855 | $reshook=$hookmanager->executeHooks('printODTColumn',$parameters, $inventory); // Note that $action and $object may have been modified by hook 856 | if ($reshook < 0) dol_print_error($db, $hookmanager->error, $hookmanager->errors); 857 | } 858 | 859 | $warehouse = new Entrepot($db); 860 | $warehouse->fetch($inventory->fk_warehouse); 861 | 862 | $dirName = 'INVENTORY'.$inventory->getId().'('.date("d_m_Y").')'; 863 | $dir = $conf->inventory->multidir_output[$conf->entity].'/'.$dirName.'/'; 864 | 865 | @mkdir($dir, 0777, true); 866 | 867 | $inventory->per_batch ? $template = "templateINVENTORY_lot.odt" : $template = "templateINVENTORY.odt"; 868 | //$template = "templateOF.doc"; 869 | 870 | $file_gen = $TBS->render(dol_buildpath('inventory/exempleTemplate/'. $template) 871 | ,array( 872 | 'TInventoryPrint'=>$TInventoryPrint 873 | ) 874 | ,array( 875 | 'date_cre'=>$inventory->get_date('date_cre', 'd/m/Y') 876 | ,'date_maj'=>$inventory->get_date('date_maj', 'd/m/Y H:i') 877 | ,'date_inv'=>$inventory->get_date('date_inventory', 'd/m/Y') 878 | ,'numero'=>empty($inventory->title) ? 'Inventaire n°'.$inventory->getId() : $inventory->title 879 | ,'warehouse'=>$warehouse->libelle 880 | ,'status'=>($inventory->status ? $langs->transnoentitiesnoconv('inventoryValidate') : $langs->transnoentitiesnoconv('inventoryDraft')) 881 | ,'logo'=>DOL_DATA_ROOT."/mycompany/logos/".MAIN_INFO_SOCIETE_LOGO 882 | ) 883 | ,array() 884 | ,array( 885 | 'outFile'=>$dir.$inventory->getId().".odt" 886 | ,"convertToPDF"=>(!empty($conf->global->INVENTORY_GEN_PDF) ? true : false) 887 | ,'charset'=>OPENTBS_ALREADY_UTF8 888 | 889 | ) 890 | 891 | ); 892 | 893 | header("Location: ".DOL_URL_ROOT."/document.php?modulepart=inventory&entity=".$conf->entity."&file=".$dirName."/".$inventory->getId(). (!empty($conf->global->INVENTORY_GEN_PDF) ? '.pdf' : '.odt') ); 894 | 895 | /* 896 | $size = filesize("./" . basename($file_gen)); 897 | header("Content-Type: application/force-download; name=\"" . basename($file_gen) . "\""); 898 | header("Content-Transfer-Encoding: binary"); 899 | header("Content-Length: $size"); 900 | header("Content-Disposition: attachment; filename=\"" . basename($file_gen) . "\""); 901 | header("Expires: 0"); 902 | header("Cache-Control: no-cache, must-revalidate"); 903 | header("Pragma: no-cache"); 904 | 905 | readfile($file_gen); 906 | */ 907 | 908 | //header("Location: ".DOL_URL_ROOT."/document.php?modulepart=asset&entity=1&file=".$dirName."/".$assetOf->numero.".doc"); 909 | 910 | } 911 | function _footerList($view,$total_pmp,$total_pmp_actual,$total_pa,$total_pa_actual, $total_current_pa,$total_current_pa_actual) { 912 | global $conf,$user,$langs; 913 | 914 | 915 | if ($view['can_validate'] == 1) { ?> 916 | 917 |   918 | barcode->enabled)) { ?> 919 |   920 | 921 | 922 |   923 | 924 | 925 | 926 | global->INVENTORY_USE_MIN_PA_IF_NO_LAST_PA)){ 928 | echo ''.price($total_current_pa).''; 929 | } 930 | ?> 931 |   932 | 933 | rights->inventory->changePMP)) { 935 | echo ' '; 936 | } 937 | ?> 938 | 939 | global->INVENTORY_USE_MIN_PA_IF_NO_LAST_PA)){ 941 | echo ''.price($total_current_pa_actual).''; 942 | } 943 | ?> 944 | 945 |   946 | 947 |   948 | 949 | 950 | multiSelectArrayWithCheckbox('selectedfields', $arrayfields, "inventoryatmcard"); 969 | 970 | ?> 971 | 972 | 973 | 974 | 975 | barcode->enabled)) { ?> 976 | Code-barre 977 | 978 | 979 | 980 | N° de lots 981 | 982 | Quantité théorique 983 | global->INVENTORY_USE_MIN_PA_IF_NO_LAST_PA)){ 985 | echo 'Valeur théorique'; 986 | } 987 | else { 988 | echo 'Valeur théorique'; 989 | } 990 | 991 | ?> 992 | 993 | 994 | Quantité réelle 995 | 996 | 997 | global->INVENTORY_USE_MIN_PA_IF_NO_LAST_PA)) $colspan++; 1001 | if(!empty($conf->global->INVENTORY_USE_MIN_PA_IF_NO_LAST_PA)) $colspan++; 1002 | if(empty($user->rights->inventory->changePMP)) $colspan --; 1003 | 1004 | echo 'Valeur réelle'; 1005 | 1006 | ?> 1007 | 1008 | Quantité régulée 1009 | $arrayfields, 1014 | 'selectedfields' => $selectedfields, 1015 | 'sortfield' => $sortfield, 1016 | 'sortorder' => $sortorder, 1017 | 'baseUrl' => $_SERVER["PHP_SELF"] . '?id=1&action=view' 1018 | ); 1019 | $reshook=$hookmanager->executeHooks('printFieldListTitle',$parameters, $inventory); // Note that $action and $object may have been modified by hook 1020 | print $hookmanager->resPrint; 1021 | 1022 | if ($view['is_already_validate'] != 1) { ?> 1023 | # 1024 | 6 ){ 1027 | include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_title.tpl.php'; 1028 | echo ' '; 1029 | echo ''; 1030 | 1031 | //menu hamburger 1032 | print_liste_field_titre($selectedfields, $_SERVER["PHP_SELF"] . '?id=1&action=view', "", '', '', '', $sortfield, $sortorder, 'center maxwidthsearch '); 1033 | } 1034 | ?> 1035 | 1036 | 1037 | 1038 | barcode->enabled) ? 3 : 4; ?> 1039 | productbatch->enabled)) $colspan++; ?> 1040 |   1041 | PMPglobal->INVENTORY_USE_MIN_PA_OR_LAST_PA_MIN_PMP_IS_NULL)) echo img_info($langs->trans('UsePAifnull')); ?> 1042 | Dernier PA 1043 | global->INVENTORY_USE_MIN_PA_IF_NO_LAST_PA)){ 1045 | echo 'PA courant'; 1046 | } 1047 | 1048 | ?> 1049 |   1050 | PMPglobal->INVENTORY_USE_MIN_PA_OR_LAST_PA_MIN_PMP_IS_NULL)) echo img_info($langs->trans('UsePAifnull')); ?> 1051 | rights->inventory->changePMP)) { 1053 | echo ''.$langs->trans('ColumnNewPMP').''; 1054 | } 1055 | ?> 1056 | Dernier PA 1057 | global->INVENTORY_USE_MIN_PA_IF_NO_LAST_PA)){ 1059 | echo 'PA courant'; 1060 | } 1061 | 1062 | ?> 1063 |   1064 | $arrayfields, 1069 | 'selectedfields' => $selectedfields, 1070 | 'sortfield' => $sortfield, 1071 | 'sortorder' => $sortorder, 1072 | 'baseUrl' => $_SERVER["PHP_SELF"] . '?id=1&action=view' 1073 | ); 1074 | $reshook=$hookmanager->executeHooks('printFieldListOption',$parameters, $inventory); // Note that $action and $object may have been modified by hook 1075 | print $hookmanager->resPrint; 1076 | 1077 | if ($view['is_already_validate'] != 1) { print ' '; } 1078 | 1079 | if(intval(DOL_VERSION) > 6 ) { 1080 | foreach ($arrayfields as $field) { 1081 | if ($field['checked'] == 1) echo ' '; //espaces deuxième ligne de titre pour s'adapter à la première en fonction des extrafields 1082 | } 1083 | echo ' '; 1084 | echo ' '; 1085 | } 1086 | ?> 1087 | 1088 | global->INVENTORY_PERF_TWEAKS) { 1102 | return '' . $product->ref . ''; 1103 | } else if(is_callable(array($product,'getNomUrl'))){ 1104 | return $product->getNomUrl(1); 1105 | }else{ 1106 | return 'error'; 1107 | } 1108 | } 1109 | 1110 | /** 1111 | * Performance-enhancing function: when getNomUrl() is called 6000 times, it weighs on performance; since it is 1112 | * mostly called on the same entrepot, caching may be effective, though tests don't show anything significant 1113 | * @param Entrepot $entrepot 1114 | * @return string 1115 | */ 1116 | function _entrepotGetNomUrl($entrepot) { 1117 | // static variables keep their value across calls; this assignment will never be run (it is resolved at compile time) 1118 | static $CACHE_Entrepot_GetNomUrl = array(); 1119 | 1120 | if (!array_key_exists($entrepot->id, $CACHE_Entrepot_GetNomUrl)) { 1121 | $CACHE_Entrepot_GetNomUrl[$entrepot->id] = $entrepot->getNomUrl(1); 1122 | } 1123 | return $CACHE_Entrepot_GetNomUrl[$entrepot->id]; 1124 | } 1125 | --------------------------------------------------------------------------------