├── README ├── config.php ├── .gitignore ├── img ├── logo.png ├── no.png ├── yes.png ├── gplv3.png ├── ATM_logo.jpg ├── supplierorderfromorder.png ├── object_supplierorderfromorder.png └── object_module.svg ├── docs └── SupplierOrderFromOrder.xmind ├── composer.json ├── config.default.php ├── css └── style.css ├── backport └── v19 │ └── core │ └── class │ └── commonhookactions.class.php ├── admin ├── supplierorderfromorder_about.php ├── dispatch_to_supplier_order_setup.php └── supplierorderfromorder_setup.php ├── script └── interface.php ├── core ├── triggers │ └── interface_99_modSupplierorderfromorder_supplierorderfromorder.class.php └── modules │ └── modSupplierorderfromorder.class.php ├── langs ├── en_US │ └── supplierorderfromorder.lang ├── de_DE │ └── supplierorderfromorder.lang └── fr_FR │ └── supplierorderfromorder.lang ├── ChangeLog.md ├── js └── dispatch_to_supplier_order.js.php ├── class ├── techatm.class.php ├── sofo.class.php └── actions_supplierorderfromorder.class.php └── lib ├── cbn.genorder.php └── function.lib.php /README: -------------------------------------------------------------------------------- 1 | STRUCTURE STANDARD POUR CREATION DE MODULE DOLIBARR - ATM 2 | -------------------------------------------------------------------------------- /config.php: -------------------------------------------------------------------------------- 1 | tbody > tr.objectline-row:nth-child(even) {background: #e1e0efaa;} 14 | .noborder > tbody > tr.objectline-row:nth-child(odd) {background: #e1e0ef;} 15 | .noborder > tbody > tr.objectline-row:hover{background: #dad8ef;} 16 | .noborder > tbody > tr.nomenclature-row:nth-child(even) {background: #f1f1f1;} 17 | .noborder > tbody > tr.nomenclature-row:nth-child(odd) {background: #FFF;} 18 | .noborder > tbody > tr.nomenclature-row:hover{background: #f9f6e4;} 19 | 20 | .dispatch-msg, .dispatch-err{ 21 | display: inline-block; 22 | padding: .25em .4em; 23 | font-size: 75%; 24 | font-weight: 700; 25 | line-height: 1; 26 | text-align: center; 27 | white-space: nowrap; 28 | vertical-align: baseline; 29 | border-radius: .25rem; 30 | transition: color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out; 31 | } 32 | 33 | .dispatch-err{ 34 | color: #fff; 35 | background-color: #dc3545; 36 | } 37 | 38 | .dispatch-msg{ 39 | color: #fff; 40 | background-color: #17a2b8; 41 | } 42 | -------------------------------------------------------------------------------- /backport/v19/core/class/commonhookactions.class.php: -------------------------------------------------------------------------------- 1 | 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation; either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | /** 19 | * \file htdocs/core/class/commonhookactions.class.php 20 | * \ingroup core 21 | * \brief File of parent class of all other hook actions classes 22 | */ 23 | 24 | namespace supplierorderfromorder; 25 | 26 | if (file_exists(DOL_DOCUMENT_ROOT. '/core/class/commonhookactions.class.php')){ 27 | 28 | /** 29 | * Parent class of all other hook actions classes 30 | */ 31 | require_once DOL_DOCUMENT_ROOT.'/core/class/commonhookactions.class.php'; 32 | abstract class RetroCompatCommonHookActions extends \CommonHookActions{ 33 | 34 | } 35 | 36 | 37 | 38 | }else{ 39 | /** 40 | * Parent class of all other hook actions classes 41 | */ 42 | abstract class RetroCompatCommonHookActions 43 | { 44 | /** 45 | * @var string String of results. 46 | */ 47 | public $resprints; 48 | 49 | /** 50 | * @var array Array of results. 51 | */ 52 | public $results = array(); 53 | } 54 | } 55 | 56 | 57 | -------------------------------------------------------------------------------- /admin/supplierorderfromorder_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/supplierorderfromorder_about.php 21 | * \ingroup supplierorderfromorder 22 | * \brief This file is an example about page 23 | * Put some comments here 24 | */ 25 | // Dolibarr environment 26 | $res = @include("../../main.inc.php"); // From htdocs directory 27 | if (! $res) { 28 | $res = @include("../../../main.inc.php"); // From "custom" directory 29 | } 30 | 31 | // Libraries 32 | require_once DOL_DOCUMENT_ROOT . "/core/lib/admin.lib.php"; 33 | require_once '../lib/function.lib.php'; 34 | 35 | // Translations 36 | $langs->load("supplierorderfromorder@supplierorderfromorder"); 37 | 38 | // Access control 39 | if (! $user->admin) { 40 | accessforbidden(); 41 | } 42 | 43 | /* 44 | * View 45 | */ 46 | $page_name = "supplierorderfromorderAbout"; 47 | llxHeader('', $langs->trans($page_name)); 48 | 49 | // Subheader 50 | $linkback = '' 51 | . $langs->trans("BackToModuleList") . ''; 52 | print load_fiche_titre($langs->trans($page_name), $linkback,'supplierorderfromorder@supplierorderfromorder'); 53 | 54 | // Configuration header 55 | $head = supplierorderfromorderAdminPrepareHead(); 56 | print dol_get_fiche_head( 57 | $head, 58 | 'about', 59 | $langs->trans("Module104130Name"), 60 | 0, 61 | 'supplierorderfromorder@supplierorderfromorder' 62 | ); 63 | 64 | // About page goes here 65 | require_once __DIR__ . '/../class/techatm.class.php'; 66 | $techATM = new \supplierorderfromorder\TechATM($db); 67 | 68 | require_once __DIR__ . '/../core/modules/modSupplierorderfromorder.class.php'; 69 | $moduleDescriptor = new modSupplierorderfromorder($db); 70 | 71 | print $techATM->getAboutPage($moduleDescriptor); 72 | 73 | // Page end 74 | print dol_get_fiche_end(); 75 | 76 | llxFooter(); 77 | 78 | $db->close(); 79 | -------------------------------------------------------------------------------- /script/interface.php: -------------------------------------------------------------------------------- 1 | fetch($fk_product)>0) 48 | { 49 | if($productFournisseur->fetch_product_fournisseur_price($fk_price, 1)>0) //Ignore the math expression when getting the price 50 | { 51 | $fk_fourn = $productFournisseur->fourn_id; 52 | } 53 | } 54 | 55 | $nb_day = (int)TSOFO::getMinAvailability($fk_product, $qty,1,$fk_fourn); 56 | print ($nb_day == 0 ? $langs->trans('Unknown') : $nb_day.' '.$langs->trans('Days')); 57 | } 58 | exit(); 59 | } 60 | 61 | function _stockDetails() 62 | { 63 | global $db,$langs,$conf; 64 | $prod = new Product($db); 65 | $prod->fetch(GETPOST('idprod', 'int')); 66 | 67 | 68 | if($prod->id<=0)exit; 69 | 70 | $prod->load_stock(); 71 | 72 | $r =''; 73 | foreach($prod->stock_warehouse as $fk_warehouse=>$obj) { 74 | 75 | $e=new Entrepot($db); 76 | $e->fetch($fk_warehouse); 77 | $r .='
'.$e->getNomUrl(1).' x '.$obj->real; 78 | 79 | } 80 | if(!empty($r)) { 81 | print '

'; 82 | print 'Stock physique'; 83 | print $r; 84 | print '

'; 85 | 86 | 87 | } 88 | 89 | $filterShipmentStatus = Expedition::STATUS_VALIDATED; 90 | if(getDolGlobalString('STOCK_CALCULATE_ON_SHIPMENT')) { 91 | $filterShipmentStatus = Expedition::STATUS_VALIDATED.','.Expedition::STATUS_CLOSED; 92 | } 93 | else if(getDolGlobalString('STOCK_CALCULATE_ON_SHIPMENT_CLOSE')) { 94 | $filterShipmentStatus = Expedition::STATUS_CLOSED; 95 | } 96 | 97 | $sql = "SELECT DISTINCT e.rowid, ed.qty"; 98 | $sql.= " FROM ".$db->prefix()."expeditiondet as ed"; 99 | $sql.= " LEFT JOIN ".$db->prefix()."expedition as e ON (e.rowid=ed.fk_expedition)"; 100 | if ((float) DOL_VERSION < 20) $sql.= " LEFT JOIN ".$db->prefix()."commandedet as cd ON (ed.fk_origin_line=cd.rowid)"; 101 | else $sql.= " LEFT JOIN ".$db->prefix()."commandedet as cd ON (ed.fk_elementdet=cd.rowid)"; 102 | $sql.= " LEFT JOIN ".$db->prefix()."commande as c ON (cd.fk_commande=c.rowid)"; 103 | $sql.= " WHERE 1"; 104 | $sql.= " AND e.entity = ".$conf->entity; 105 | $sql.= " AND cd.fk_product = ".$prod->id; 106 | $sql.= " AND c.fk_statut in (".Commande::STATUS_VALIDATED.','.Commande::STATUS_ACCEPTED.")"; //récup du load_stats d'un produit 107 | $sql.= " AND e.fk_statut in ($filterShipmentStatus)"; 108 | 109 | $r =''; 110 | $result =$db->query($sql); 111 | //var_dump($db); 112 | while($obj = $db->fetch_object($result)) { 113 | 114 | $e=new Expedition($db); 115 | $e->fetch($obj->rowid); 116 | 117 | $r.='
'.$e->getNomUrl(1).' x '.$obj->qty.''; 118 | 119 | } 120 | 121 | 122 | if(!empty($r)) { 123 | print '

'; 124 | print 'Expéditions'; 125 | print $r; 126 | print '

'; 127 | 128 | 129 | } 130 | 131 | } 132 | -------------------------------------------------------------------------------- /admin/dispatch_to_supplier_order_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/supplierorderfromorder.php 21 | * \ingroup supplierorderfromorder 22 | * \brief This file is an example module setup page 23 | * Put some comments here 24 | */ 25 | // Dolibarr environment 26 | $res = @include("../../main.inc.php"); // From htdocs directory 27 | if (! $res) { 28 | $res = @include("../../../main.inc.php"); // From "custom" directory 29 | } 30 | 31 | // Libraries 32 | require_once DOL_DOCUMENT_ROOT . "/core/lib/admin.lib.php"; 33 | require_once '../lib/function.lib.php'; 34 | dol_include_once('abricot/includes/lib/admin.lib.php'); 35 | 36 | // Translations 37 | $langs->load("admin"); 38 | $langs->load('supplierorderfromorder@supplierorderfromorder'); 39 | 40 | // Access control 41 | if (! $user->admin) { 42 | accessforbidden(); 43 | } 44 | 45 | // Parameters 46 | $action = GETPOST('action', 'alpha'); 47 | 48 | /* 49 | * Actions 50 | */ 51 | if (preg_match('/set_(.*)/',$action,$reg)) 52 | { 53 | $code=$reg[1]; 54 | if (dolibarr_set_const($db, $code, GETPOST($code, 'none'), 'chaine', 0, '', $conf->entity) > 0) 55 | { 56 | header("Location: ".$_SERVER["PHP_SELF"]); 57 | exit; 58 | } 59 | else 60 | { 61 | dol_print_error($db); 62 | } 63 | } 64 | 65 | if (preg_match('/del_(.*)/',$action,$reg)) 66 | { 67 | $code=$reg[1]; 68 | if (dolibarr_del_const($db, $code, 0) > 0) 69 | { 70 | Header("Location: ".$_SERVER["PHP_SELF"]); 71 | exit; 72 | } 73 | else 74 | { 75 | dol_print_error($db); 76 | } 77 | } 78 | 79 | /* 80 | * View 81 | */ 82 | $page_name = "supplierorderfromorderSetup"; 83 | llxHeader('', $langs->trans($page_name)); 84 | 85 | $linkback=''.$langs->trans("BackToModuleList").''; 86 | print load_fiche_titre($langs->trans("SupplierOrderFromOrder"),$linkback,'supplierorderfromorder@supplierorderfromorder'); 87 | 88 | // Configuration header 89 | $head = supplierorderfromorderAdminPrepareHead(); 90 | print dol_get_fiche_head( 91 | $head, 92 | 'nomenclature', 93 | $langs->trans("Module104130Name"), 94 | 0, 95 | "supplierorderfromorder@supplierorderfromorder" 96 | ); 97 | 98 | 99 | 100 | 101 | 102 | print dol_get_fiche_end(); 103 | 104 | 105 | // Setup page goes here 106 | $form=new Form($db); 107 | $var=false; 108 | print ''; 109 | 110 | 111 | if(!function_exists('setup_print_title')){ 112 | print '
'.$langs->trans('AbricotNeedUpdate').' : Wiki
'; 113 | exit; 114 | } 115 | 116 | setup_print_title("Parameters"); 117 | 118 | // USE Nomenclature tab 119 | setup_print_on_off('SOFO_USE_NOMENCLATURE',false, '', 'SOFO_USE_NOMENCLATURE_HELP'); 120 | 121 | 122 | setup_print_title("ParametersNeedSOFO_USE_NOMENCLATURE"); 123 | 124 | // Fill qty for nomenclature 125 | setup_print_on_off('SOFO_FILL_QTY_NOMENCLATURE',false); 126 | 127 | // Disable product order if nomenclature 128 | setup_print_on_off('SOFO_DISABLE_ORDER_POSIBILITY_TO_PRODUCT_WITH_NOMENCLATURE'); 129 | 130 | 131 | // USE DELIVERY CONTACT 132 | setup_print_on_off('SOFO_USE_DELIVERY_CONTACT',false, '', 'DeliveryHelp'); 133 | 134 | 135 | // USE RESTRICTION CONTACT 136 | setup_print_on_off('SOFO_USE_RESTRICTION_TO_CUSTOMER_ORDER'); 137 | 138 | setup_print_on_off('SOFO_ADD_QUANTITY_RATHER_THAN_CREATE_LINES'); 139 | 140 | setup_print_on_off('SOFO_VIEW_SUBNOMENCLATURE8LINES'); 141 | 142 | 143 | // Example with imput 144 | //setup_print_input_form_part('CONSTNAME', 'ParamLabel'); 145 | 146 | // Example with color 147 | // setup_print_input_form_part('CONSTNAME', 'ParamLabel', 'ParamDesc', array('type'=>'color'),'input','ParamHelp'); 148 | 149 | // Example with placeholder 150 | //setup_print_input_form_part('CONSTNAME','ParamLabel','ParamDesc',array('placeholder'=>'http://'),'input','ParamHelp'); 151 | 152 | // Example with textarea 153 | //setup_print_input_form_part('CONSTNAME','ParamLabel','ParamDesc',array(),'textarea'); 154 | 155 | 156 | print '
'; 157 | 158 | llxFooter(); 159 | 160 | $db->close(); 161 | -------------------------------------------------------------------------------- /core/triggers/interface_99_modSupplierorderfromorder_supplierorderfromorder.class.php: -------------------------------------------------------------------------------- 1 | 3 | * Copyright (C) 2013 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_Mytrigger.class.php 21 | * \ingroup mymodule 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 InterfaceSupplierorderfromorder extends DolibarrTriggers 37 | { 38 | 39 | /** 40 | * Database handler 41 | * @var DoliDB 42 | */ 43 | protected $db; 44 | 45 | /** 46 | * Constructor 47 | * 48 | * @param DoliDB $db Database handler 49 | */ 50 | public function __construct($db) 51 | { 52 | $this->db = $db; 53 | 54 | $this->name = preg_replace('/^Interface/i', '', get_class($this)); 55 | $this->family = "ATM"; 56 | $this->description = "Triggers pour ajouter le code de lavage à la description d'un produit lors de l'ajout d'une ligne de commande, de facture ou de propale."; 57 | // 'development', 'experimental', 'dolibarr' or version 58 | $this->version = 'dolibarr'; 59 | $this->picto = 'clipastel@clipastel'; 60 | } 61 | 62 | /** 63 | * Trigger name 64 | * 65 | * @return string Name of trigger file 66 | */ 67 | public function getName() 68 | { 69 | return $this->name; 70 | } 71 | 72 | /** 73 | * Trigger description 74 | * 75 | * @return string Description of trigger file 76 | */ 77 | public function getDesc() 78 | { 79 | return $this->description; 80 | } 81 | 82 | /** 83 | * Trigger version 84 | * 85 | * @return string Version of trigger file 86 | */ 87 | public function getVersion() 88 | { 89 | global $langs; 90 | $langs->load("admin"); 91 | 92 | if ($this->version == 'development') { 93 | return $langs->trans("Development"); 94 | } elseif ($this->version == 'experimental') 95 | 96 | return $langs->trans("Experimental"); 97 | elseif ($this->version == 'dolibarr') return DOL_VERSION; 98 | elseif ($this->version) return $this->version; 99 | else { 100 | return $langs->trans("Unknown"); 101 | } 102 | } 103 | 104 | /** 105 | * @param string $action 106 | * @param Object $object 107 | * @param User $user 108 | * @param Translate $langs 109 | * @param Conf $conf 110 | * @return int 111 | */ 112 | public function runTrigger($action, $object, User $user, Translate $langs, Conf $conf) { 113 | return $this->run_trigger($action, $object, $user, $langs, $conf); 114 | } 115 | 116 | /** 117 | * Function called when a Dolibarrr business event is done. 118 | * All functions "run_trigger" are triggered if file 119 | * is inside directory core/triggers 120 | * 121 | * @param string $action Event action code 122 | * @param Object $object Object 123 | * @param User $user Object user 124 | * @param Translate $langs Object langs 125 | * @param conf $conf Object conf 126 | * @return int <0 if KO, 0 if no triggered ran, >0 if OK 127 | */ 128 | public function run_trigger($action, $object, $user, $langs, $conf) 129 | { 130 | // Put here code you want to execute when a Dolibarr business events occurs. 131 | // Data and type of action are stored into $object and $action 132 | // Users 133 | global $db; 134 | //dol_include_once('/product/class/product.class.php'); 135 | if ($action == 'ORDER_SUPPLIER_DELETE') { 136 | 137 | dol_syslog("Trigger '" . $this->name . "' for action '$action' launched by " . __FILE__ . ". id=" . $object->id ); 138 | 139 | if(!empty($object->lines)) 140 | { 141 | foreach ($object->lines as $line) 142 | { 143 | // Delete linked object 144 | $res = $line->deleteObjectLinked(); 145 | } 146 | } 147 | 148 | $object->deleteObjectLinked('', 'commande', $object->id, 'order_supplier'); 149 | 150 | 151 | } 152 | 153 | if($action == 'LINEORDER_DELETE' || $action == 'LINEORDER_SUPPLIER_DELETE') { 154 | 155 | dol_syslog( "Trigger '" . $this->name . "' for action '$action' launched by " . __FILE__ . ". id=" . $object->id ); 156 | 157 | // Delete linked object 158 | if($object->element == 'commandedet'){ 159 | return $object->deleteObjectLinked(); 160 | } 161 | elseif($object->element == 'commande_fournisseurdet'){ 162 | return $object->deleteObjectLinked(); 163 | } 164 | 165 | } 166 | 167 | return 0; 168 | } 169 | } -------------------------------------------------------------------------------- /langs/en_US/supplierorderfromorder.lang: -------------------------------------------------------------------------------- 1 | Module104130Name = Supplier orders from customer order 2 | Module104130Desc = Create supplier orders from a customer order 3 | 4 | SelectProduct = Select at least one product and one supplier 5 | ProductsToOrder = Product to order 6 | OrderToSuppliers = Create supplier order 7 | GenerateSupplierOrder = Generate supplier orders 8 | SupplierOrderFromOrder = Supplier order from customer order 9 | CreateNewSupplierOrderAnyTime = Create a new supplier order draft for each customer order 10 | InfoCreateNewSupplierOrderAnyTime = If not, add up the quantities of the products in the corresponding lines on the latest existing supplier order. 11 | UseOrderLineDescInSupplierOrder = Create a line in the supplier order for each different description in the customer order 12 | NbWeekToReplenish = Take in consideration the number of weeks of the product leadtime 13 | ReCalculate = Recalculate 14 | AddFreeLinesInSupplierOrder = Add free lines as the free lines in the customer order 15 | GetOrderPaimentInfo = Reuse the payment and supply terms from the customer order 16 | SUPPLIERORDER_FROM_ORDER_CONTACT_DELIVERY = Import the shipment contact from the customer order to the supplier order 17 | SUPPLIERORDER_FROM_ORDER_HEADER_SUPPLIER_ORDER = Redirect to the supplier order when there is only one supplier to order (from v.3.8) 18 | UseDeliveryTimeToReplenish = Use a time period (in weeks) for the supply need 19 | UseVirtualStockOfOrdersSkipDoliConfig = Use the virtual stock for the orders, independently from the global configuration 20 | 21 | SOFO_DO_NOT_USE_CUSTOMER_ORDER = Do not take the existing supplier orders in consideration 22 | SOFO_DEFAUT_FILTER = Filter by default on the nature of the product 23 | ShowLineEvenIfStockIsSuffisant = Include lines with sufficient stock 24 | supplierorderfromorder_nb_orders_created = Number of supplier order(s) created: %s 25 | CreateDistinctSupplierOrderFromOrderDependingOfProject = Create separate supplier orders if the projects in the customer orders are different 26 | UseCostPriceAsBuyingPrice = Use cost price as buying price for free lines 27 | SOFO_DEFAULT_PRODUCT_CATEGORY_FILTER = Default product category filter 28 | DeleteFilter = Delete filter 29 | NoFilter = No filter 30 | 31 | SOFO_PRESELECT_SUPPLIER_PRICE_FROM_LINE_BUY_PRICE=By default, preselect the supplier prices equal to the buying price set in the initial customer order (needs module Margins) 32 | 33 | PurgeSessionForCachedProduct=Display based on a product cache, purge the cache? 34 | SOFO_GET_INFOS_FROM_FOURN=When generating a supplier order, update the payment conditions, payment methods from customer 35 | SOFO_GET_INFOS_FROM_ORDER=When generating a supplier order, update the payment conditions, payment methods from customer order 36 | SOFO_GET_EXTRAFIELDS_FROM_ORDER=When generating a supplier order, update extrafields (with the same definition) from customer order 37 | SOFO_USE_MAX_DELIVERY_DATE=Use the largest delivery date (creation date + largest available among those available) 38 | GenerateSupplierPropal=Create price requests 39 | ProductAddToSupplierQuotation=Product% s added to supplier quotation '%s' 40 | ProductAddToSupplierOrder=Product %s added to supplier's order '%s' 41 | SelectSameSupplier=Use this supplier for all products 42 | NoCommonSupplier=No common supplier 43 | SOFO_DISPLAY_SERVICES=Allow services ordering 44 | FournDispatch=proceed supplier(s) order's) 45 | PrepareFournDispatch=Preparation of supplier orders from customer N° 46 | Stock_reel=Real stock 47 | Stock_theorique=Theoretical stock 48 | QtyToOrder=Qty to order 49 | QtyToOrderHelp=By default, the quantities displayed are calculated from the theoretical stock 50 | DeliveryHelp=If the supplier order is to be delivered directly to the customer, it's possible to select the delivery contact from the contacts in the customer order. 51 | servicesAreNotDispatch=Services cannot be used in a supplier order 52 | PleaseCheckAtLeastOneCheckbox=You must select at least one line. 53 | AllreadyImported=This line is already in a supplier order 54 | AllreadyDispatched=This line is already in a supplier order 55 | AllreadyDispatcheds=This line is already in a supplier order(s) 56 | FournDispatchResult=Dispatch result fot customer order N ° 57 | ErrorFournDoesNotExist=Supplier not found 58 | clicToReplaceQty=Click to replace the quantity to order 59 | ProductToOrderManuellement=Product to be ordered manually 60 | ForceDispatch=Forcing ventilation 61 | DisplayNomenclature=Show / Hide the details of the nomenclature 62 | YouNeedToSelectAtLeastOneSupplierPrice=You must select a supplier price 63 | YouNeedToGiveASupplierPrice=You must enter a unit price 64 | YouNeedToGiveAQty=You must enter a quantity 65 | MoreOptions=More options 66 | ForceFourn=Forcing supplier 67 | ForceFournHelp=By forcing the supplier, all the products of the BOM will be ordered from this supplier 68 | ProductsAssetsToOrder=Components to order 69 | SOFO_USE_NOMENCLATURE=Add the tab "Components to order" 70 | SOFO_USE_NOMENCLATURE_HELP=En activant cette option, un nouvel onglet "Composants à commander" apparaît sur la page de réapprovisionnement 71 | SOFO_USE_DELIVERY_CONTACT=Allow choice of delivery contact 72 | SOFO_FILL_QTY_NOMENCLATURE=Pre-fill the quantities of the components 73 | SOFO_USE_RESTRICTION_TO_CUSTOMER_ORDER=Restrict supplier orders to a single customer order 74 | SOFO_DISABLE_ORDER_POSIBILITY_TO_PRODUCT_WITH_NOMENCLATURE=Disable the possibility of directly ordering the product with a BOM 75 | ParametersNeedSOFO_USE_NOMENCLATURE=Parameters: the "Components to order" tab is necessary to use these parameters 76 | SOFO_ADD_QUANTITY_RATHER_THAN_CREATE_LINES=Favor adding quantity to a supplier order line instead of adding a line for each customer order line 77 | Fabriquer = Create 78 | SOFO_GET_REF_SUPPLIER_FROM_ORDER=Transfer the customer reference to the supplier order. 79 | SOFO_GROUP_LINES_BY_PRODUCT=Group lines by product 80 | DontGroupByProduct=Don't group lines by product 81 | GroupByProductHelp=Default value can be set in configuration page 82 | AlreadyShipped = Already shipped 83 | SOFO_ENABLE_LINKED_EXTRAFIELDS=Show the "Order" and "Third party" extra fields on supplier orders lines and supplier receptions lines 84 | SOFO_ENABLE_LINKED_EXTRAFIELDS_HELP=If enabled, adds the "Order" and "Third party" extra fields to supplier order lines and supplier reception lines (object link type) 85 | -------------------------------------------------------------------------------- /ChangeLog.md: -------------------------------------------------------------------------------- 1 | # ChangeLog 2 | 3 | ## [Unreleased] 4 | - NEW : ADD extrafields Order + Thirdparty on SupplierOrderFromOrder Card and reception card - *23/12/2025* - 2.11.0 5 | 6 | ## RELEASES 2.10 7 | - FIX : Currently, decimals are not taken into account in quantities when creating supplier orders. - *19/12/2025* - 2.10.1 8 | - NEW : Add conf SOFO_GET_REF_SUPPLIER_FROM_ORDER - *09/12/2025* - 2.10.0 9 | + FIX : group lines by product, alls group product when conf SOFO_GROUP_LINES_BY_PRODUCT was set to no 10 | 11 | ## RELEASES 2.9 12 | - FIX : Warning activation module- **07/07/2025* - 2.9.5 13 | - FIX : COMPAT V22 - **07/07/2025* - 2.9.4 14 | - FIX : COMPAT V21 - **11/12/2024** - 2.9.2 15 | - FIX : Depuis la V20, le champ "fk_origin_line" dans la table llx_expeditiondet a été renommé "fk_elementdet" ce qui causait des erreurs - *22/10/2024* - 2.9.1 16 | - NEW : new coloumn on supplier order creation form : quantities already shipped - *03/09/2024* - 2.9.0 17 | 18 | ## RELEASES 2.8 19 | 20 | - FIX : DA025395 - Retour de ticket - *30/08/2024* - 2.8.3 21 | - FIX : DA025395 - Gestion de creation commande fournisseur "Créer une commande fournisseur brouillon pour chaque commande client" - *27/08/2024* - 2.8.2 22 | - FIX : DA025395 - Ajout de la conf "Créer une commande fournisseur brouillon pour chaque commande client" sur la page dispatch_to_supplier_order.php - *27/08/2024* - 2.8.1 23 | - NEW : DA025170 - Ajout de la description des produits lors de la création d'une facture fournisseur (soumis a conf) - *15/07/2024* - 2.8.0 24 | - NEW : Compat V20 - *02/07/2024* - 2.8.0 25 | - NEW : Options to import notes on orders - *15/01/2024* - 2.8.0 26 | 27 | ## RELEASES 2.7 28 | - FIX : DA025148 - Correction chemin vers main.inc et verif que les commandes fournisseurs soient activées - *29/05/2024* - 2.7.3 29 | - FIX : DA024990 - Suppression de isfile inutiles - *29/05/2024* - 2.7.2 30 | - FIX : warnings - *29/02/2024* - 2.7.1 31 | - NEW : compatv19 - *04/12/2023* - 2.7.0 32 | 33 | ## RELEASES 2.6 34 | - FIX : remove warning error display - *30/11/2023* - 2.6.7 35 | - FIX : remove overwritting initial orderline product in cmdfourn create - *05/10/2023* - 2.6.6 36 | - FIX : FIX: missing CSRF token in form - *28/09/2023* - 2.6.5 37 | - FIX : Warnings DA02684 - *11/09/2023* - 2.6.4 38 | - FIX : Warnings (accessing global confs without checking for existence) - *03/08/2023* - 2.6.3 39 | - FIX : DA023344 - wrong virtual stock - *26/05/2023* - 2.6.2 40 | - FIX : debugbar - *30/03/2023* - 2.6.1 41 | - NEW : It's now possible to group by product or dissociate on ordercustomer.php page - *20/03/2023* - 2.6.0 42 | 43 | ## RELEASES 2.5 44 | - FIX : filter of column "finished" doesn't work - *22/03/2023* - 2.5.9 45 | - FIX : bad return for printCommonFooter hook - *03/03/2023* - 2.5.8 46 | - FIX : remove ordersupplierButton on presen action - *15/02/2023* - 2.5.7 47 | - FIX : DA022726 keep unit from component *07/02/2023* 2.5.6 48 | - FIX : when SOFO_QTY_LINES_COMES_FROM_ORIGIN_ORDER_ONLY is activated column to order was sometimes different from column ordered *31/01/2023* 2.5.5 49 | - FIX : add step any on dispatch page *11/01/2023* 2.5.4 50 | - FIX : Handle multihook with group by *02/11/2022* 2.5.3 51 | - FIX : Missing icon *19/10/2022* 2.5.1 52 | - NEW : Ajout de la class TechATM pour l'affichage de la page "A propos" *11/05/2022* 2.5.0 53 | 54 | ## RELEASES 2.4 - 26/01/2022 55 | - FIX: Warnings (variables referenced prior to assignment) - *25/07/2023* - 2.4.10 56 | - FIX : Création des commandes fournisseurs dans la devise du fournisseur - *06/01/2023* - 2.4.9 57 | - FIX : PHP 8 - *03/08/2022* - 2.4.8 58 | - FIX : Compatibility V16 - *06/06/2022* - 2.4.7 59 | - FIX DA022202 : Error: Trigger InterfaceSupplierorderfromorder does not extends DolibarrTriggers - 2.4.6 - *20/07/2022* 60 | - FIX DA021939 : SOFO_GROUP_LINES_BY_PRODUCT prend parfois que la 1re ligne s'il y a plusieurs lignes dans la meme commande 2.4.5 - *18/05/2022* 61 | - FIX ticket DA021862 : SOFO_GROUP_LINES_BY_PRODUCT ne doit pas s'appliquer pour les sous-produits + la "Qté dans CF" doit afficher 0 pour les sous-produits (un chiffre sans aucun sens était affiché) - 2.4.4 - *04/05/2022* 62 | - FIX : add exit to header location function on SUPPLIERORDER_FROM_ORDER_HEADER_SUPPLIER_ORDER 2.4.3 - *01/02/2022* 63 | - FIX : Pgsql query - 2.4.2 *09/02/2022* 64 | - FIX : Don't redirect on order list when it's proposal validation - 2.4.1 - *25/01/2022* 65 | - NEW : conf SOFO_QTY_LINES_COMES_FROM_ORIGIN_ORDER_ONLY, when it's on : columns "ordered" and "to order" are only filled with origin cmd lines quantities - 2.4.0 - *10/11/2021* 66 | - NEW : conf SOFO_GROUP_LINES_BY_PRODUCT, when it's on : each product reference is grouped on one and only line - 2.4.0 - *10/11/2021* 67 | 68 | ## RELEASES 2.3 69 | FIX : changement du calcul de ligne pour prendre en compte le prix unitaire de la nomenclature - *17/03/2022)* - 2.3.3 70 | - FIX : change params passed to find_min_price_product_fournisseur ($productid instaed of $line->fk_product) - 2.3.0 - *30/09/2021* 71 | - FIX : change params passed to find_min_price_product_fournisseur ($productid instaed of $line->fk_product) - 2.3.2 - 06/01/2022 72 | - FIX : change SQL query aliases for list: `p` is now `prod` - 2.3.1 - 01/10/2021 73 | - New - add doAction hook 2.3.0 - *30/09/2021* 74 | - New - add redirection button to command fourn 2.2.0- *28/09/2021* 75 | - New - restrict input number on product 76 | - New - add Qty product column and link to cmd fourn if exit. 77 | 78 | 79 | ## RELEASES 2.1 80 | 81 | - FIX : default val for $maxDeep - 2.1.2 - *20/12/2021* 82 | - Fix : bad if conditions - 2.1.0 - *16/08/2021* 83 | - Fix : refacto de batard - 2.1.0 - *16/08/2021* 84 | - Fix : treatment after error validation - 2.1.0 - *16/08/2021* 85 | - New : Add sub-nomenclature view (+ conf) - 2.1.0 - *16/08/2021* 86 | - Fix : link nomenclature lines to supplier order line - 2.1.0 - *16/08/2021* 87 | 88 | ## RELEASES 2.0 89 | 90 | - FIX: Gestion de la remise relative du fournisseur - 2.0.7 - *03/08/2021* 91 | - FIX: v14 compatibility - setDateLivraison -> setDeliveryDate - 2.0.6 - *27/07/2021* 92 | - FIX: Dispatch to supplier soc detection - 2.0.5 - *12/07/2021* 93 | - FIX: DA020591 : Erreur de calcul sur la qté à commander sur écran de réappro lorsque plusieurs fois le même produit dans la même commande + FIX informations infobulle - 2.0.4 - *02/07/2021* 94 | - FIX: v14 compatibility - NOCSRFCHECK + setDateLivraison - 2.0.3 - *29/06/2021* 95 | - FIX: Add conf to take card of aproved supplier orders for virtual stocks - 2.0.2 - *28/04/2021* 96 | - FIX: Compatibility V13 - add token renowal - 2.0.2 - *17.05.2021* 97 | - FIX: warning when clicking “Create Supplier Order” - 2.0.1 - *23/04/2021* 98 | - No changelog up to this point 99 | 100 | ## RELEASES 1.6 101 | - No changelog up to this point 102 | 103 | ## RELEASES 1.0 104 | - No changelog up to this point 105 | 106 | -------------------------------------------------------------------------------- /langs/de_DE/supplierorderfromorder.lang: -------------------------------------------------------------------------------- 1 | Module104130Name = Lieferantenbestellungen aus Kundenauftrag 2 | Module104130Desc = Erstellen von Lieferantenaufträgen aus einem Kundenauftrag 3 | 4 | SelectProduct = Wählen Sie minestens ein Produkt und einen Lieferanten 5 | ProductsToOrder = Zu bestellendes Produkt 6 | OrderToSuppliers = Lieferantenbestellung erstellen 7 | GenerateSupplierOrder = Lieferantenbestellungen generieren 8 | SupplierOrderFromOrder = Lieferantenbestellung aus Kundenauftrag 9 | CreateNewSupplierOrderAnyTime = Erstellen Sie für jeden Kundenauftrag einen Entwurf der Lieferantenbestellung 10 | InfoCreateNewSupplierOrderAnyTime = Falls nicht, addieren Sie die Mengen der Produkte in den entsprechenden Zeilen auf der letzten vorhandenen Bestellung beim Lieferanten. 11 | UseOrderLineDescInSupplierOrder = In der Lieferantenbestellung eine Zeile für jede vom Kundenauftrag abweichende Beschreibung erstellen 12 | NbWeekToReplenish = Anzahl der Wochen der Prouktvorlaufzeit berücksichtigen 13 | ReCalculate = Neu berechnen 14 | AddFreeLinesInSupplierOrder = Freie Zeilen, die in dem Kundenauftrag vorhanden sind, in die Lieferantenbestellung einfügen 15 | GetOrderPaimentInfo = Abrufen der Zahlungs- und Lieferbedingungen aus dem Kundenauftrag 16 | SUPPLIERORDER_FROM_ORDER_CONTACT_DELIVERY = Den Lieferkontakt von dem Kundenauftrag in die Lieferantenbestellung importieren 17 | SUPPLIERORDER_FROM_ORDER_HEADER_SUPPLIER_ORDER = Weiterleiten an die Lieferantenbestellung, wenn nur ein Lieferant betroffen ist 18 | UseDeliveryTimeToReplenish = Geben Sie einen Zeitraum (in Wochen) für den Lieferbedarf an 19 | UseVirtualStockOfOrdersSkipDoliConfig = Verwenden Sie den virtuellen Bestand für die Aufträge, unabhängig von der globalen Konfiguration 20 | 21 | SOFO_DO_NOT_USE_CUSTOMER_ORDER = Lieferantenbestellungen nicht berücksichtigen 22 | SOFO_DEFAUT_FILTER = Standardmäßig nach Art des Produkts filtern 23 | ShowLineEvenIfStockIsSuffisant = Zeilen mit ausreichendem Bestand einbeziehen 24 | supplierorderfromorder_nb_orders_created = Anzahl der erstellten Lieferantenbestellungen: %s 25 | CreateDistinctSupplierOrderFromOrderDependingOfProject = Erstellen Sie separate Lieferantenbestellungen, wenn die Entwürfe der Kundenaufträge unterschiedlich sind. 26 | UseCostPriceAsBuyingPrice = Den Selbstkostenpreis als Kaufpreis verwenden 27 | PurgeSessionForCachedProduct = Auf der Grundlage eines Produkt-Caches anzeigen, den Cache leeren? 28 | GenerateSupplierPropal = Preisanfrage erstellen 29 | ProductAddToSupplierQuotation = Produkt %s zur Preisanfrage des Lieferanten '%s' hinzugefügt 30 | ProductAddToSupplierOrder = Produkt %s zur Bestellung des Lieferanten '%s' hinzugefügt 31 | SelectSameSupplier = Den Lieferanten für alle Produkte verwenden 32 | NoCommonSupplier = Keine gemeinsamen Lieferanten 33 | SOFO_DISPLAY_SERVICES = Bestellung von Dienstleistungen erlauben 34 | SOFO_DEFAULT_PRODUCT_CATEGORY_FILTER = Standardfilter für Produktkategorien 35 | DeleteFilter = Filter löschen 36 | NoFilter = kein Filter 37 | 38 | # dispatch_dispatch_to_supplier_order 39 | FournDispatch=Bestellung(en) bei Lieferanten aufgeben 40 | PrepareFournDispatch=Vorbereitung von Lieferantenbestellungen aus der Kundennummer 41 | Stock_reel=reeler Lagerbestand 42 | Stock_theorique=theoretischer Lagerbestand 43 | QtyToOrder=Zu bestellende Menge 44 | QtyToOrderHelp=Standardmäßig werden die angezeigten Mengen aus dem Sollbestand berechnet 45 | DeliveryHelp=Wenn die Lieferantenbestellung direkt an den Kunden geliefert werden soll, kann der Lieferkontakt aus den Kontakten des Kundenauftrages ausgewählt werden. 46 | servicesAreNotDispatch=Dienstleistungen können nicht Teil einer Lieferantenbestellung sein 47 | PleaseCheckAtLeastOneCheckbox=Sie müssen mindestens eine Zeile auswählen. 48 | AllreadyImported=Diese Zeile ist bereits Teil einer Lieferantenbestellung 49 | AllreadyDispatched=Diese Zeile ist bereits Teil einer Lieferantenbestellung 50 | AllreadyDispatcheds=Diese Zeile ist bereits Teil von Lieferantenbestellung(en) 51 | FournDispatchResult=Ergebnis der Aufschlüsselung des Kundenauftrags Nr. 52 | ErrorFournDoesNotExist=Lieferant nicht gefunden 53 | clicToReplaceQty=Klicken Sie, um die Bestellmenge zu ersetzen 54 | ProductToOrderManuellement=Produkt, das manuell bestellt werden muss 55 | ForceDispatch=Zwangsbelüftung 56 | DisplayNomenclature=Stücklistendetails anzeigen/ausblenden 57 | YouNeedToSelectAtLeastOneSupplierPrice=Sie müssen einen Lieferantenpreis auswählen 58 | YouNeedToGiveASupplierPrice=Sie müssen einen Lieferantenpreis eingeben 59 | YouNeedToGiveAQty=Sie müssen eine Menge eingeben 60 | MoreOptions=Weitere Optionen 61 | ForceFourn=Lieferant erzwingen 62 | ForceFournHelp=Durch Erzwingen des Lieferanten werden alle Produkte in der Nomenklatur bei diesem Lieferanten bestellt. 63 | ProductsAssetsToOrder=Zu bestellende Komponenten 64 | 65 | # admin 66 | SOFO_USE_NOMENCLATURE=Reiter "Zu bestellende Komponenten" hinzufügen 67 | SOFO_USE_NOMENCLATURE_HELP=Wenn Sie diese Option aktivieren, erscheint ein neuer Reiter "Zu bestellende Komponenten". 68 | SOFO_USE_DELIVERY_CONTACT=Auswahl des Lieferkontakts ermöglichen 69 | SOFO_FILL_QTY_NOMENCLATURE=Mengen der Komponenten vorausfüllen 70 | SOFO_USE_RESTRICTION_TO_CUSTOMER_ORDER=Lieferantenbestellungen auf einen Kundenauftrag beschränken 71 | SOFO_DISABLE_ORDER_POSIBILITY_TO_PRODUCT_WITH_NOMENCLATURE=Deaktivieren der Möglichkeit, das Produkt direkt mit einer Stückliste zu bestellen 72 | ParametersNeedSOFO_USE_NOMENCLATURE=Einstellungen: Die Registerkarte "Zu bestellende Komponenten" ist erforderlich, um diese Einstellungen zu verwenden. 73 | SOFO_ADD_QUANTITY_RATHER_THAN_CREATE_LINES=Bevorzugen Sie das Hinzufügen von Mengen zu einer Lieferantenbestellzeile, anstatt eine Zeile für jede Kundenbestellzeile hinzuzufügen. 74 | SOFO_PRESELECT_SUPPLIER_PRICE_FROM_LINE_BUY_PRICE=Voreingestellte Voreinstellung für Lieferantenpreise, die dem Einkaufspreis in der ursprünglichen Kundenbestellzeile entsprechen (erfordert das Modul Margen). 75 | SOFO_CHECK_STOCK_ON_SHARED_STOCK=Mit dem Multicompany-Modul haben Sie die Sichtbarkeit von Lagern/Beständen geteilt. Wollen Sie, dass Lieferantenbestellungen von Kundenaufträgen die geteilten Lagerbestände berücksichtigen oder nicht? 76 | SOFO_VIRTUAL_PRODUCTS=Verwaltung virtueller Produkte durch das Modul 77 | SOFO_VIEW_SUBNOMENCLATURE8LINES=Unterstücklisten in den zu bestellenden Komponenten anzeigen 78 | SOFO_GET_INFOS_FROM_ORDER=Bei der Generierung einer Lieferantenbestellung die Zahlungsbedingungen und Zahlungsarten aus der Bestellung übernehmen 79 | SOFO_GET_EXTRAFIELDS_FROM_ORDER=Bei der Generierung einer Lieferantenbestellung die ergänzenden Attribute (wenn sie die gleiche Definition haben) aus dem Kundenauftrag übernehmen 80 | SOFO_GET_INFOS_FROM_FOURN=Bei der Generierung einer Lieferantenbestellung die Zahlungsbedingungen, Zahlungsarten vom Kunden übernehmen 81 | SOFO_USE_MAX_DELIVERY_DATE=Längstes Lieferdatum verwenden (Erstellungsdatum + größtes Dispo unter den verfügbaren) 82 | 83 | DispatchAndOrders = Bestellungen aufgeben 84 | INCLUDE_PRODUCT_LINES_WITH_ADEQUATE_STOCK=Alle Produktlinien mit ausreichendem Bestand standardmäßig einbeziehen 85 | Diff=Menge in Lieferantenbestellung 86 | ViewSupplierOrderGenerated=Siehe verknüpfte Lieferantenbestellung 87 | InitialCommande=Ursprüngliche Bestellung: 88 | listOrderSupplierForCustomerCommand=Liste der mit der Bestellung verbundenen Lieferantenbestellungen 89 | SOFO_QTY_LINES_COMES_FROM_ORIGIN_ORDER_ONLY=Die Mengen in den Spalten "Bestellt" und "Zu bestellen" stammen nur aus der ursprünglichen Bestellung. 90 | SOFO_GROUP_LINES_BY_PRODUCT=Zeilen nach Produkt gruppieren 91 | SupplierProposalSuccessfullyCreated=Erstellte Lieferantenpreisanfragen 92 | supplierorderfromorderAbout = Über das Modul Lieferantenbestellung aus Kundenauftrag 93 | Fabriquer = Erstellen 94 | AlreadyShipped = Bereits versendet 95 | -------------------------------------------------------------------------------- /img/object_module.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 22 | 24 | 46 | 49 | 54 | 59 | 60 | 62 | 63 | 65 | image/svg+xml 66 | 68 | 69 | 70 | 71 | 72 | 77 | 82 | 86 | 90 | 91 | 96 | 101 | 106 | 111 | 116 | 121 | 126 | 131 | 135 | 139 | 140 | 141 | 142 | -------------------------------------------------------------------------------- /js/dispatch_to_supplier_order.js.php: -------------------------------------------------------------------------------- 1 | . 16 | * 17 | * Library javascript to enable Browser notifications 18 | */ 19 | 20 | if (!defined('NOREQUIREUSER')) define('NOREQUIREUSER', '1'); 21 | if (!defined('NOREQUIREDB')) define('NOREQUIREDB','1'); 22 | if (!defined('NOREQUIRESOC')) define('NOREQUIRESOC', '1'); 23 | //if (!defined('NOREQUIRETRAN')) define('NOREQUIRETRAN','1'); 24 | if (!defined('NOCSRFCHECK')) define('NOCSRFCHECK', 1); 25 | if (!defined('NOTOKENRENEWAL')) define('NOTOKENRENEWAL', 1); 26 | if (!defined('NOLOGIN')) define('NOLOGIN', 1); 27 | if (!defined('NOREQUIREMENU')) define('NOREQUIREMENU', 1); 28 | if (!defined('NOREQUIREHTML')) define('NOREQUIREHTML', 1); 29 | if (!defined('NOREQUIREAJAX')) define('NOREQUIREAJAX','1'); 30 | 31 | 32 | /** 33 | * \file js/dispatch_to_supplier_order.js.php 34 | * \ingroup supplierorderfromorder 35 | * \brief JavaScript file for module supplierorderfromorder. 36 | */ 37 | 38 | 39 | include_once __DIR__ . '/../config.php'; 40 | 41 | // Define js type 42 | header('Content-Type: application/javascript'); 43 | // Important: Following code is to cache this file to avoid page request by browser at each Dolibarr page access. 44 | // You can use CTRL+F5 to refresh your browser cache. 45 | if (empty($dolibarr_nocache)) header('Cache-Control: max-age=3600, public, must-revalidate'); 46 | else header('Cache-Control: no-cache'); 47 | 48 | 49 | // Load traductions files requiredby by page 50 | $langs->loadLangs(array("supplierorderfromorder@supplierorderfromorder","other")); 51 | ?> 52 | // 50 | 51 | $line,'var'=>$var,'num'=>$num,'i'=>$i,'dateSelector'=>$dateSelector,'seller'=>$seller,'buyer'=>$buyer,'selected'=>$selected, 'extrafieldsline'=>$extrafieldsline); 70 | 71 | extract($parameters, EXTR_SKIP); 72 | if ($action != 'editline' || $selected != $line->id) 73 | { 74 | 75 | $result = 0; 76 | 77 | // DISPLAY SUPPLIER REFERENCE 78 | if(!empty($line->ref_supplier)){ 79 | $line->description = '(ref fourn : '.$line->ref_supplier.') '.$line->description; 80 | $result = 1; 81 | } 82 | 83 | // DISPLAY EXTRA INFORMATIONS ON DESCRIPTION FROM ORDERS LINES 84 | $searchOrderLine = getLinkedOrderLineFromSupplierOrderLine($line->id); 85 | 86 | if(!empty($searchOrderLine)) 87 | { 88 | dol_include_once('commande/class/commande.class.php'); 89 | $commandeLigne = new OrderLine($db); 90 | if($commandeLigne->fetch($searchOrderLine)>0) 91 | { 92 | 93 | 94 | $line->description .= '
'; 95 | $commande = new Commande($db); 96 | $commande->fetch($commandeLigne->fk_commande); 97 | 98 | $line->description .= $action.'Commande client '; 99 | 100 | $line->description .= ' x '.$commandeLigne->qty; 101 | 102 | if(!empty($line->fk_unit)){ 103 | $productDefault = new Product($db); 104 | $productDefault->fk_unit = $line->fk_unit; 105 | $line->description .= ' '.$productDefault->getLabelOfUnit('short').''; 106 | } 107 | 108 | $line->description .= ' : '; 109 | 110 | $commande->fetch_thirdparty(); 111 | $line->description .= ' '.$commande->thirdparty->name ; //$commandeFournisseur->thirdparty->getNomUrl(1,'supplier'); 112 | 113 | $line->description .= ' '.$commande->getNomUrl(1); 114 | 115 | $line->description .= '
'; 116 | 117 | $result = 1; 118 | } 119 | } 120 | 121 | // OVERRIDE PRINT LINE 122 | if($result) 123 | { 124 | $object->printObjectLine($action,$line,$var,$num,$i,$dateSelector,$seller,$buyer,$selected,$extrafieldsline); 125 | return 1; 126 | } 127 | } 128 | 129 | } 130 | } 131 | 132 | if (in_array('ordercard',explode(':',$parameters['context']))) 133 | { 134 | if( getDolGlobalString('SOFO_DISPLAY_LINKED_ELEMENT_ON_LINES')) 135 | { 136 | extract($parameters, EXTR_SKIP); 137 | dol_include_once('supplierorderfromorder/lib/function.lib.php'); 138 | 139 | // DISPLAY EXTRA INFORMATIONS ON DESCRIPTION FROM SUPPLIER ORDERS LINES 140 | if ($action != 'editline' || $selected != $line->id) 141 | { 142 | 143 | $overridePrintLine = false; 144 | 145 | 146 | // GET SUPPLIER ORDER INFOS 147 | dol_include_once('fourn/class/fournisseur.commande.class.php'); 148 | 149 | $searchSupplierOrderLine = getLinkedSupplierOrderLineFromElementLine($line->id); 150 | 151 | if(!empty($searchSupplierOrderLine)) 152 | { 153 | 154 | if(!empty($line->description)) 155 | { 156 | //$line->description .= '
'; 157 | } 158 | 159 | $commandeFournisseurLigne = new CommandeFournisseurLigne($db); 160 | if($commandeFournisseurLigne->fetch($searchSupplierOrderLine)>0) 161 | { 162 | 163 | 164 | $line->description .= '
'; 165 | $commandeFournisseur = new CommandeFournisseur($db); 166 | $commandeFournisseur->fetch($commandeFournisseurLigne->fk_commande); 167 | 168 | $line->description .= $action.'Commande fournisseur '; 169 | 170 | $line->description .= $commandeFournisseurLigne->ref_supplier.' x '.$commandeFournisseurLigne->qty; 171 | 172 | if(!empty($line->fk_unit)){ 173 | $productDefault = new Product($db); 174 | $productDefault->fk_unit = $line->fk_unit; 175 | $line->description .= ' '.$productDefault->getLabelOfUnit('short').''; 176 | } 177 | 178 | $line->description .= ' : '; 179 | 180 | $commandeFournisseur->fetch_thirdparty(); 181 | $line->description .= ' '.$commandeFournisseur->thirdparty->name ; //$commandeFournisseur->thirdparty->getNomUrl(1,'supplier'); 182 | 183 | $line->description .= ' '.$commandeFournisseur->getNomUrl(1); 184 | 185 | $line->description .= '
'; 186 | } 187 | 188 | $overridePrintLine = true; 189 | } 190 | 191 | 192 | // OVERRIDE PRINT LINE 193 | if($overridePrintLine) 194 | { 195 | $object->printObjectLine($action,$line,$var,$num,$i,$dateSelector,$seller,$buyer,$selected,$extrafieldsline); 196 | 197 | return 1; 198 | } 199 | } 200 | } 201 | } 202 | 203 | 204 | } 205 | 206 | 207 | /** 208 | * On tri les commandes fournisseurs par commande client 209 | * 210 | * @param $parameters 211 | * @param $object 212 | * @param $action 213 | * @param $hookmanager 214 | */ 215 | function printFieldListWhere($parameters, &$object, &$action, $hookmanager) { 216 | 217 | dol_include_once('/supplierorderfromorder/class/sofo.class.php'); 218 | $TContext = explode(':', $parameters['context']); 219 | if(in_array('supplierorderlist', $TContext)) { 220 | $origin_page = GETPOST('origin_page'); 221 | if($origin_page === 'ordercustomer') { 222 | if(!empty($this->resprints) && strpos(strtolower($this->resprints), 'group by')) { 223 | $this->resprints = ' AND e.fk_source = '.GETPOST('id', 'int'). ' ' . $this->resprints; 224 | } 225 | else $this->resprints = ' AND e.fk_source = '.GETPOST('id', 'int'); 226 | } 227 | } 228 | 229 | } 230 | 231 | /** 232 | * Ajoute une jointure avec element_element qui permet de trier les factures fournisseur par id de commande client 233 | * 234 | * @param $parameters 235 | * @param $object 236 | * @param $action 237 | * @param $hookmanage 238 | */ 239 | function printFieldListFrom($parameters, &$object, &$action, $hookmanager) 240 | { 241 | 242 | global $db; 243 | dol_include_once('/supplierorderfromorder/class/sofo.class.php'); 244 | 245 | $TContext = explode(':', $parameters['context']); 246 | if(in_array('supplierorderlist', $TContext)) { 247 | $origin_page = GETPOST('origin_page'); 248 | if($origin_page === 'ordercustomer') { 249 | $this->resprints = " LEFT JOIN ".$db->prefix()."element_element as e ON (cf.rowid = e.fk_target AND targettype = 'order_supplier' AND sourcetype = 'commande')"; 250 | } 251 | } 252 | } 253 | 254 | /** 255 | * @param $parameters 256 | * @param $object 257 | * @param $action 258 | * @param $hookmanager 259 | * @return int 260 | */ 261 | function printCommonFooter($parameters, &$object, &$action, $hookmanager){ 262 | global $langs , $db; 263 | 264 | $TContext = explode(':', $parameters['context']); 265 | 266 | if(in_array('supplierorderlist', $TContext)) { 267 | // la page 268 | $origin_page = GETPOST('origin_page','alpha'); 269 | $id = GETPOST('id','int'); 270 | $ref = ''; 271 | 272 | if($origin_page === 'ordercustomer'){ 273 | $pos = strpos($_SERVER['SCRIPT_NAME'],DOL_URL_ROOT); 274 | if (is_int($pos)){ 275 | $file = substr($_SERVER['SCRIPT_NAME'],$pos + strlen(DOL_URL_ROOT)); 276 | if ($file == "/fourn/commande/list.php"){ 277 | dol_include_once('/commande/class/commande.class.php'); 278 | $cmd = NEW Commande($db); 279 | $res = $cmd->fetch($id); 280 | 281 | if ($res > 0 ){ 282 | $ref = $langs->transnoentities('listOrderSupplierForCustomerCommand'); 283 | $ref .= " ". $cmd->ref; 284 | } 285 | 286 | print ''; 291 | } 292 | } 293 | } 294 | return 1; 295 | } 296 | 297 | return 0; 298 | } 299 | } 300 | -------------------------------------------------------------------------------- /core/modules/modSupplierorderfromorder.class.php: -------------------------------------------------------------------------------- 1 | 3 | * Copyright (C) 2013 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 | * \defgroup mymodule MyModule module 21 | * \brief MyModule module descriptor. 22 | * \file core/modules/modMyModule.class.php 23 | * \ingroup mymodule 24 | * \brief Description and activation file for module MyModule 25 | */ 26 | include_once DOL_DOCUMENT_ROOT . "/core/modules/DolibarrModules.class.php"; 27 | require_once DOL_DOCUMENT_ROOT.'/core/class/extrafields.class.php'; 28 | 29 | /** 30 | * Description and activation class for module MyModule 31 | */ 32 | class modSupplierorderfromorder extends DolibarrModules 33 | { 34 | 35 | /** 36 | * Constructor. Define names, constants, directories, boxes, permissions 37 | * 38 | * @param DoliDB $db Database handler 39 | */ 40 | public function __construct($db) 41 | { 42 | global $langs, $conf; 43 | 44 | $this->db = $db; 45 | 46 | $this->editor_name = 'ATM Consulting'; 47 | $this->editor_url = 'https://www.atm-consulting.fr'; 48 | // Id for module (must be unique). 49 | // Use a free id here 50 | // (See in Home -> System information -> Dolibarr for list of used modules id). 51 | $this->numero = 104130; // 104000 to 104999 for ATM CONSULTING 52 | // Key text used to identify module (for permissions, menus, etc...) 53 | $this->rights_class = 'supplierorderfromorder'; 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 = "ATM Consulting - CRM"; 58 | // Module label (no space allowed) 59 | // used if translation string 'ModuleXXXName' not found 60 | // (where XXX is value of numeric property 'numero' of module) 61 | $this->name = preg_replace('/^mod/i', '', get_class($this)); 62 | // Module description 63 | // used if translation string 'ModuleXXXDesc' not found 64 | // (where XXX is value of numeric property 'numero' of module) 65 | $this->description = "Module commande fournisseur à partir d'une commande client"; 66 | // Possible values for version are: 'development', 'experimental' or version 67 | 68 | $this->version = '2.11.0'; 69 | // Url to the file with your last numberversion of this module 70 | require_once __DIR__ . '/../../class/techatm.class.php'; 71 | $this->url_last_version = \supplierorderfromorder\TechATM::getLastModuleVersionUrl($this); 72 | 73 | // Key used in llx_const table to save module status enabled/disabled 74 | // (where MYMODULE is value of property name of module in uppercase) 75 | $this->const_name = 'MAIN_MODULE_' . strtoupper($this->name); 76 | // Where to store the module in setup page 77 | // (0=common,1=interface,2=others,3=very specific) 78 | $this->special = 0; 79 | // Name of image file used for this module. 80 | // If file is in theme/yourtheme/img directory under name object_pictovalue.png 81 | // use this->picto='pictovalue' 82 | // If file is in module/img directory under name object_pictovalue.png 83 | // use this->picto='pictovalue@module' 84 | $this->picto = 'module.svg@supplierorderfromorder'; // mypicto@mymodule 85 | // Defined all module parts (triggers, login, substitutions, menus, css, etc...) 86 | // for default path (eg: /mymodule/core/xxxxx) (0=disable, 1=enable) 87 | // for specific path of parts (eg: /mymodule/core/modules/barcode) 88 | // for specific css file (eg: /mymodule/css/mymodule.css.php) 89 | $this->module_parts = array( 90 | // Set this to 1 if module has its own trigger directory 91 | 'triggers' => 1, 92 | // Set this to 1 if module has its own login method directory 93 | //'login' => 0, 94 | // Set this to 1 if module has its own substitution function file 95 | //'substitutions' => 0, 96 | // Set this to 1 if module has its own menus handler directory 97 | //'menus' => 0, 98 | // Set this to 1 if module has its own barcode directory 99 | //'barcode' => 0, 100 | // Set this to 1 if module has its own models directory 101 | //'models' => 0, 102 | // Set this to relative path of css if module has its own css file 103 | //'css' => '/mymodule/css/mycss.css.php', 104 | // Set here all hooks context managed by module 105 | 'hooks' => array( 106 | 'ordercard' 107 | ,'ordersuppliercard' 108 | ,'supplierorderlist' 109 | ) 110 | // Set here all workflow context managed by module 111 | //'workflow' => array('order' => array('WORKFLOW_ORDER_AUTOCREATE_INVOICE')) 112 | ); 113 | 114 | // Data directories to create when module is enabled. 115 | // Example: this->dirs = array("/mymodule/temp"); 116 | $this->dirs = array(); 117 | 118 | // Config pages. Put here list of php pages 119 | // stored into mymodule/admin directory, used to setup module. 120 | $this->config_page_url = array("supplierorderfromorder_setup.php@supplierorderfromorder"); 121 | 122 | // Dependencies 123 | // List of modules id that must be enabled if this module is enabled 124 | $this->depends = array(); 125 | // List of modules id to disable if this one is disabled 126 | $this->requiredby = array(); 127 | // Minimum version of PHP required by module 128 | $this->phpmin = array(7, 0); 129 | // Minimum version of Dolibarr required by module 130 | $this->need_dolibarr_version = array(16, 0); 131 | $this->langfiles = array("supplierorderfromorder@supplierorderfromorder"); // langfiles@mymodule 132 | // Constants 133 | // List of particular constants to add when module is enabled 134 | // (key, 'chaine', value, desc, visible, 'current' or 'allentities', deleteonunactive) 135 | // Example: 136 | $this->const = array(); 137 | 138 | // Array to add new pages in new tabs 139 | // Example: 140 | $this->tabs = array(); 141 | 142 | // Dictionnaries 143 | if (!isset($conf->ordersupplierfromorder->enabled)) { 144 | $conf->ordersupplierfromorder=new stdClass(); 145 | $conf->ordersupplierfromorder->enabled = 0; 146 | } 147 | $this->dictionnaries = array(); 148 | 149 | 150 | // Boxes 151 | // Add here list of php file(s) stored in core/boxes that contains class to show a box. 152 | $this->boxes = array(); // Boxes list 153 | $r = 0; 154 | // Example: 155 | 156 | /* 157 | $this->boxes[$r][1] = "myboxb.php"; 158 | $r++; 159 | */ 160 | 161 | // Permissions 162 | $this->rights = array(); // Permission array used by this module 163 | $r = 0; 164 | 165 | $this->rights[$r][0] = $this->numero + $r; // Permission id (must not be already used) 166 | $this->rights[$r][1] = 'Convertir les commandes clients en commandes fournisseurs'; // Permission label 167 | $this->rights[$r][3] = 0; // Permission by default for new user (0/1) 168 | $this->rights[$r][4] = 'read'; // In php code, permission will be checked by test if ($user->rights->permkey->level1->level2) 169 | $this->rights[$r][5] = ''; // In php code, permission will be checked by test if ($user->rights->permkey->level1->level2) 170 | $r++; 171 | 172 | // Main menu entries 173 | $this->menus = array(); // List of menus to add 174 | $r = 0; 175 | 176 | $this->menu[]=array( 177 | 'fk_menu'=>'fk_mainmenu=of', // Use r=value where r is index key used for the parent menu entry (higher parent must be a top menu entry) 178 | 'type'=>'left', // This is a Left menu entry 179 | 'titre'=>'ProductsToOrder', 180 | 'mainmenu'=>'replenishGPAO', 181 | 'leftmenu'=>'replenishGPAO', 182 | 'url'=>'/supplierorderfromorder/ordercustomer.php', 183 | 'langs'=>'supplierorderfromorder@supplierorderfromorder', 184 | 'perms' => '', 185 | 'position'=>300, 186 | 'target'=>'', 187 | 'user'=>2 188 | ); 189 | 190 | 191 | // Exports 192 | $r = 1; 193 | 194 | 195 | } 196 | 197 | /** 198 | * Function called when module is enabled. 199 | * The init function add constants, boxes, permissions and menus 200 | * (defined in constructor) into Dolibarr database. 201 | * It also creates data directories 202 | * 203 | * @param string $options Options when enabling module ('', 'noboxes') 204 | * @return int 1 if OK, 0 if KO 205 | */ 206 | public function init($options = '') 207 | { 208 | $sql = array(); 209 | 210 | $result = $this->loadTables(); 211 | 212 | // Create extrafields (idempotent) on supplier order lines and receptions 213 | global $langs, $conf; 214 | $langs->loadLangs(array('main', 'order', 'companies', 'supplierorderfromorder@supplierorderfromorder')); 215 | $extrafields = new ExtraFields($this->db); 216 | $elements = array('commande_fournisseurdet', 'receptiondet_batch'); 217 | $linkOrderParams = array('options' => array('Commande:commande/class/commande.class.php' => null)); 218 | $linkThirdpartyParams = array('options' => array('Societe:societe/class/societe.class.php' => null)); 219 | $enabledCondition = 'isModEnabled("supplierorderfromorder") && getDolGlobalInt("SOFO_ENABLE_LINKED_EXTRAFIELDS")'; 220 | foreach ($elements as $elementtype) { 221 | // Visibility/list = 2 (view only, hidden on create/edit forms) 222 | $extrafields->addExtraField('SOFO_linked_order', $langs->transnoentities('Order'), 'link', 101, '', $elementtype, 0, 0, '', $linkOrderParams, 0, '', 2, '', '', $conf->entity, 'supplierorderfromorder@supplierorderfromorder', $enabledCondition, 0, 0); 223 | $extrafields->addExtraField('SOFO_linked_thirdparty', $langs->transnoentities('ThirdParty'), 'link', 102, '', $elementtype, 0, 0, '', $linkThirdpartyParams, 0, '', 2, '', '', $conf->entity, 'supplierorderfromorder@supplierorderfromorder', $enabledCondition, 0, 0); 224 | } 225 | 226 | return $this->_init($sql, $options); 227 | } 228 | 229 | /** 230 | * Function called when module is disabled. 231 | * Remove from database constants, boxes and permissions from Dolibarr database. 232 | * Data directories are not deleted 233 | * 234 | * @param string $options Options when enabling module ('', 'noboxes') 235 | * @return int 1 if OK, 0 if KO 236 | */ 237 | public function remove($options = '') 238 | { 239 | $sql = array(); 240 | 241 | return $this->_remove($sql, $options); 242 | } 243 | 244 | /** 245 | * Create tables, keys and data required by module 246 | * Files llx_table1.sql, llx_table1.key.sql llx_data.sql with create table, create keys 247 | * and create data commands must be stored in directory /mymodule/sql/ 248 | * This function is called by this->init 249 | * 250 | * @return int <=0 if KO, >0 if OK 251 | */ 252 | private function loadTables() 253 | { 254 | return $this->_load_tables('/supplierorderfromorder/sql/'); 255 | } 256 | } 257 | -------------------------------------------------------------------------------- /lib/cbn.genorder.php: -------------------------------------------------------------------------------- 1 | 0) { 11 | 12 | $suppliers = array(); 13 | //var_dump($linecount);exit; 14 | for ($i = 0; $i < $linecount; $i++) { 15 | 16 | if(GETPOST('check'.$i, 'alpha') === 'on' && (GETPOST('fourn' . $i, 'int') > 0 || GETPOST('fourn_free' . $i, 'int') > 0)) { //one line 17 | 18 | //echo GETPOST('tobuy_free'.$i, 'none').'
'; 19 | //Lignes de produit 20 | if(!GETPOST('tobuy_free'.$i, 'none')){ 21 | $box = $i; 22 | $supplierpriceid = GETPOST('fourn'.$i, 'int'); 23 | //get all the parameters needed to create a line 24 | $qty = GETPOST('tobuy'.$i, 'int'); 25 | $desc = GETPOST('desc'.$i, 'alpha'); 26 | 27 | $sql = 'SELECT fk_product, fk_soc, ref_fourn'; 28 | $sql .= ', tva_tx, unitprice, remise_percent FROM '; 29 | $sql .= $db->prefix() . 'product_fournisseur_price'; 30 | $sql .= ' WHERE rowid = ' . $supplierpriceid; 31 | 32 | $resql = $db->query($sql); 33 | 34 | if ($resql && $db->num_rows($resql) > 0) { 35 | //might need some value checks 36 | $obj = $db->fetch_object($resql); 37 | $line = new CommandeFournisseurLigne($db); 38 | $line->qty = $qty; 39 | $line->desc = $desc; 40 | $line->fk_product = $obj->fk_product; 41 | $line->tva_tx = $obj->tva_tx; 42 | $line->subprice = $obj->unitprice; 43 | $line->total_ht = $obj->unitprice * $qty; 44 | $tva = $line->tva_tx / 100; 45 | $line->total_tva = $line->total_ht * $tva; 46 | $line->total_ttc = $line->total_ht + $line->total_tva; 47 | $line->ref_fourn = $obj->ref_fourn; 48 | $line->remise_percent = $obj->remise_percent; 49 | // FIXME: Ugly hack to get the right purchase price since supplier references can collide 50 | // (eg. same supplier ref for multiple suppliers with different prices). 51 | $line->fk_prod_fourn_price = $supplierpriceid; 52 | 53 | if(!empty($_REQUEST['tobuy'.$i])) { 54 | $suppliers[$obj->fk_soc]['lines'][] = $line; 55 | } 56 | 57 | 58 | } else { 59 | $error=$db->lasterror(); 60 | dol_print_error($db); 61 | dol_syslog('replenish.php: '.$error, LOG_ERR); 62 | } 63 | $db->free($resql); 64 | unset($_POST['fourn' . $i]); 65 | } 66 | //Lignes libres 67 | else{ 68 | //var_dump($_REQUEST); 69 | //echo 'ok
'; 70 | $box = $i; 71 | $qty = GETPOST('tobuy_free'.$i, 'int'); 72 | $desc = GETPOST('desc'.$i, 'alpha'); 73 | $product_type = GETPOST('product_type'.$i, 'int'); 74 | $price = price2num(GETPOST('price_free'.$i, 'none')); 75 | $lineid = GETPOST('lineid_free'.$i, 'int'); 76 | $fournid = GETPOST('fourn_free'.$i, 'int'); 77 | $commandeline = new OrderLine($db); 78 | $commandeline->fetch($lineid); 79 | 80 | $line = new CommandeFournisseurLigne($db); 81 | $line->qty = $qty; 82 | $line->desc = $desc; 83 | $line->product_type = $product_type; 84 | $line->tva_tx = $commandeline->tva_tx; 85 | $line->subprice = $price; 86 | $line->total_ht = $price * $qty; 87 | $tva = $line->tva_tx / 100; 88 | $line->total_tva = $line->total_ht * $tva; 89 | $line->total_ttc = $line->total_ht + $line->total_tva; 90 | //$line->ref_fourn = $obj->ref_fourn; 91 | $line->remise_percent = $commandeline->remise_percent; 92 | 93 | if(!empty($_REQUEST['tobuy_free'.$i])) { 94 | $suppliers[$fournid]['lines'][] = $line; 95 | } 96 | unset($_POST['fourn_free' . $i]); 97 | } 98 | } 99 | unset($_POST[$i]); 100 | } 101 | 102 | //we now know how many orders we need and what lines they have 103 | $i = 0; 104 | $nb_orders_created = 0; 105 | $orders = array(); 106 | $suppliersid = array_keys($suppliers); 107 | $projectid = GETPOST('projectid', 'int'); 108 | foreach ($suppliers as $idsupplier => $supplier) { 109 | 110 | $sql2 = 'SELECT rowid, ref'; 111 | $sql2 .= ' FROM ' . $db->prefix(). 'commande_fournisseur'; 112 | $sql2 .= ' WHERE fk_soc = '.$idsupplier; 113 | $sql2 .= ' AND fk_statut = 0'; // 0 = DRAFT (Brouillon) 114 | if(getDolGlobalString('SOFO_DISTINCT_ORDER_BY_PROJECT') && !empty($projectid)){ 115 | $sql2 .= ' AND fk_projet = '.$projectid; 116 | } 117 | 118 | $sql2 .= ' AND entity IN('.getEntity('commande_fournisseur').')'; 119 | $sql2 .= ' ORDER BY rowid DESC'; 120 | $sql2 .= ' LIMIT 1'; 121 | 122 | $res = $db->query($sql2); 123 | $obj = $db->fetch_object($res); 124 | 125 | $commandeClient = new Commande($db); 126 | $commandeClient->fetch($_REQUEST['id']); 127 | 128 | // Test recupération contact livraison 129 | if( getDolGlobalString('SUPPLIERORDER_FROM_ORDER_CONTACT_DELIVERY')) 130 | { 131 | $contact_ship = $commandeClient->getIdContact('external', 'SHIPPING'); 132 | $contact_ship=$contact_ship[0]; 133 | }else{$contact_ship=null;} 134 | //Si une commande au statut brouillon existe déjà et que l'option SOFO_CREATE_NEW_SUPPLIER_ODER_ANY_TIME 135 | if($obj && empty(getDolGlobalString('SOFO_CREATE_NEW_SUPPLIER_ODER_ANY_TIME')) ) { 136 | 137 | $order = new CommandeFournisseur($db); 138 | $order->fetch($obj->rowid); 139 | $order->socid = $idsupplier; 140 | // var_dump($obj,$order);exit; 141 | if(!empty($projectid)){ 142 | $order->fk_project = GETPOST('projectid', 'int'); 143 | } 144 | // On vérifie qu'il n'existe pas déjà un lien entre la commande client et la commande fournisseur dans la table element_element. 145 | // S'il n'y en a pas, on l'ajoute, sinon, on ne l'ajoute pas 146 | $order->fetchObjectLinked('', 'commande', $order->id, 'order_supplier'); 147 | 148 | //if(count($order->linkedObjects) == 0) { 149 | 150 | $order->add_object_linked('commande', $_REQUEST['id']); 151 | 152 | //} 153 | if( getDolGlobalString('SOFO_GET_INFOS_FROM_ORDER')){ 154 | $order->mode_reglement_code = $commandeClient->mode_reglement_code; 155 | $order->mode_reglement_id = $commandeClient->mode_reglement_id; 156 | $order->cond_reglement_id = $commandeClient->cond_reglement_id; 157 | $order->cond_reglement_code = $commandeClient->cond_reglement_code; 158 | $order->delivery_date = $commandeClient->delivery_date; 159 | } 160 | $id++; //$id doit être renseigné dans tous les cas pour que s'affiche le message 'Vos commandes ont été générées' 161 | $newCommande = false; 162 | } else { 163 | /*echo '
';
164 | 				print_r($commandeClient);exit;*/
165 | 
166 | 				$order = new CommandeFournisseur($db);
167 | 				$order->socid = $idsupplier;
168 | 				if(!empty($projectid)){
169 | 					$order->fk_project = $projectid;
170 | 				}
171 | 				if( getDolGlobalString('SOFO_GET_INFOS_FROM_ORDER')){
172 | 					$order->mode_reglement_code = $commandeClient->mode_reglement_code;
173 | 					$order->mode_reglement_id = $commandeClient->mode_reglement_id;
174 | 					$order->cond_reglement_id = $commandeClient->cond_reglement_id;
175 | 					$order->cond_reglement_code = $commandeClient->cond_reglement_code;
176 | 					$order->delivery_date = $commandeClient->delivery_date;
177 | 				}
178 | 
179 | 				$id = $order->create($user);
180 | 				if($contact_ship && getDolGlobalString('SUPPLIERORDER_FROM_ORDER_CONTACT_DELIVERY')) $order->add_contact($contact_ship, 'SHIPPING');
181 | 				$order->add_object_linked('commande', $_REQUEST['id']);
182 | 				$newCommande = true;
183 | 
184 | 				$nb_orders_created++;
185 | 			}
186 | 			$order_id = $order->id;
187 |             //trick to know which orders have been generated this way
188 |             $order->source = 42;
189 | 
190 |             foreach ($supplier['lines'] as $line) {
191 | 
192 | 	            $done = false;
193 | 
194 | 				$prodfourn = new ProductFournisseur($db);
195 | 				$prodfourn->fetch_product_fournisseur_price($_REQUEST['fourn'.$i]);
196 | 
197 |             	foreach($order->lines as $lineOrderFetched) {
198 | 
199 |             		if($line->fk_product == $lineOrderFetched->fk_product) {
200 | 
201 |                         $remise_percent = $lineOrderFetched->remise_percent;
202 |                         if($line->remise_percent > $remise_percent)$remise_percent = $line->remise_percent;
203 | //var_dump($line);
204 |             			$order->updateline(
205 |                             $lineOrderFetched->id,
206 |                             $lineOrderFetched->desc,
207 |                             // FIXME: The current existing line may very well not be at the same purchase price
208 |                             $lineOrderFetched->pu_ht,
209 |                             $lineOrderFetched->qty + $line->qty,
210 |                             $remise_percent,
211 |                             $lineOrderFetched->tva_tx
212 |                         );
213 |                           // add link to element_element between order line and supplier order line if not exist
214 | 
215 |                           $linkendline = getlinkedobject($lineOrderFetched->id,$linkendline->element,'commande_commandedet');
216 |                           if($linkendline == 0){
217 |                                  $lineOrderFetched->add_object_linked($line->id,'commande_commandedet');
218 |                           }
219 | 
220 | 						$done = true;
221 | 						break;
222 | 
223 |             		}
224 | 
225 |             	}
226 | 
227 | 				// On ajoute une ligne seulement si un "updateline()" n'a pas été fait et si la quantité souhaitée est supérieure à zéro
228 | 
229 | 				if(!$done) {
230 | 
231 | 					$newlineid = $order->addline(
232 |                         $line->desc,
233 |                         $line->subprice,
234 |                         $line->qty,
235 |                         $line->tva_tx,
236 |                         null,
237 |                         null,
238 |                         $line->fk_product,
239 |                         // We need to pass fk_prod_fourn_price to get the right price.
240 |                         $line->fk_prod_fourn_price,
241 |                         $line->ref_fourn,
242 |                         $line->remise_percent
243 |                         ,'HT'
244 |                         ,0
245 |                         ,$line->product_type
246 |                         ,$line->info_bits
247 |                     );
248 | 
249 |                      // add link to element_element between order line and supplier order line
250 |                      $newline = new CommandeFournisseurLigne($db);
251 |                      $result = $newline->fetch($newlineid);
252 |                      if($result == 1){
253 |                            $newline->add_object_linked($line->id,'commandedet');
254 |                      }
255 | 
256 | 				}
257 | 
258 |             }
259 | 
260 |             $order->cond_reglement_id = 0;
261 |             $order->mode_reglement_id = 0;
262 | 
263 |             if ($id < 0) {
264 |                 $fail++; // FIXME: declare somewhere and use, or get rid of it!
265 |                 $msg = $langs->trans('OrderFail') . " : ";
266 |                 $msg .= $order->error;
267 |                 setEventMessage($msg, 'errors');
268 |             }else{
269 |             	// CODE de redirection s'il y a un seul fournisseur (évite de le laisser sur la page sans comprendre)
270 |             	if(getDolGlobalString('SUPPLIERORDER_FROM_ORDER_HEADER_SUPPLIER_ORDER'))
271 | 				{
272 | 	            	if(count($suppliersid) == 1)
273 | 					{
274 | 						$link = dol_buildpath('/fourn/commande/card.php?id='.$order_id, 1);
275 | 						header('Location:'.$link);
276 | 					}
277 | 				}
278 |             }
279 |             $i++;
280 |         }
281 | 
282 | 		/*if($newCommande) {
283 | 
284 | 			setEventMessage("Commande fournisseur créée avec succès !", 'errors');
285 | 
286 | 		} else {
287 | 
288 | 			setEventMessage("Produits ajoutés à la commande en cours !", 'errors');
289 | 
290 | 		}*/
291 | 
292 |         /*if (!$fail && $id) {
293 |             setEventMessage($langs->trans('OrderCreated'), 'mesgs');
294 |             //header('Location: '.DOL_URL_ROOT.'/commande/fiche.php?id='.$_REQUEST['id'].'');
295 |         } else {
296 |         	setEventMessage('coucou', 'mesgs');
297 |         }*/
298 |     }
299 | 
300 | 	if ($nb_orders_created > 0)
301 | 	{
302 | 		setEventMessages($langs->trans('supplierorderfromorder_nb_orders_created', $nb_orders_created), array());
303 | 	}
304 | 
305 |     if ($box === false) {
306 |         setEventMessage($langs->trans('SelectProduct'), 'warnings');
307 |     } else {
308 | 
309 |     	foreach($suppliers as $idSupplier => $lines) {
310 |     		$j = 0;
311 |     		foreach($lines as $line) {
312 | 		    	$sql = "SELECT quantity";
313 | 				$sql.= " FROM ".$db->prefix()."product_fournisseur_price";
314 | 				$sql.= " WHERE fk_soc = ".$idSupplier;
315 | 				$sql.= " AND fk_product = ".$line[$j]->fk_product;
316 | 				$sql.= " ORDER BY quantity ASC";
317 | 				$sql.= " LIMIT 1";
318 | 				$resql = $db->query($sql);
319 | 				if($resql){
320 | 					$resql = $db->fetch_object($resql);
321 | 
322 | 					//echo $j;
323 | 
324 | 					if($line[$j]->qty < $resql->quantity) {
325 | 						$p = new Product($db);
326 | 						$p->fetch($line[$j]->fk_product);
327 | 						$f = new Fournisseur($db);
328 | 						$f->fetch($idSupplier);
329 | 						$rates[$f->name] = $p->label;
330 | 					} else {
331 | 						$p = new Product($db);
332 | 						$p->fetch($line[$j]->fk_product);
333 | 						$f = new Fournisseur($db);
334 | 						$f->fetch($idSupplier);
335 | 						$ajoutes[$f->name] = $p->label;
336 | 					}
337 | 				}
338 | 
339 | 				/*echo "
";
340 | 				print_r($rates);
341 | 				echo "
"; 342 | echo "
";
343 | 				print_r($ajoutes);
344 | 				echo "
";*/ 345 | $j++; 346 | } 347 | } 348 | $mess = ""; 349 | // FIXME: declare $ajoutes somewhere. It's unclear if it should be reinitialized or not in the interlocking loops. 350 | if($ajoutes) { 351 | foreach($ajoutes as $nomFournisseur => $nomProd) { 352 | $mess.= "Produit ' ".$nomProd." ' ajouté à la commande du fournisseur ' ".$nomFournisseur." '
"; 353 | } 354 | } 355 | // FIXME: same as $ajoutes. 356 | if($rates) { 357 | foreach($rates as $nomFournisseur => $nomProd) { 358 | $mess.= "Quantité insuffisante de ' ".$nomProd." ' pour le fournisseur ' ".$nomFournisseur." '
"; 359 | } 360 | } 361 | if($rates) { 362 | setEventMessage($mess, 'warnings'); 363 | } else { 364 | setEventMessage($mess, 'mesgs'); 365 | } 366 | } 367 | } 368 | -------------------------------------------------------------------------------- /admin/supplierorderfromorder_setup.php: -------------------------------------------------------------------------------- 1 | load("admin"); 12 | $langs->load('supplierorderfromorder@supplierorderfromorder'); 13 | 14 | $newToken = function_exists('newToken') ? newToken() : $_SESSION['newtoken']; 15 | 16 | global $db; 17 | 18 | // Security check 19 | if (! $user->admin) accessforbidden(); 20 | 21 | $action=GETPOST('action', 'alpha'); 22 | $id=GETPOST('id', 'int'); 23 | 24 | /* 25 | * Action 26 | */ 27 | if (preg_match('/set_(.*)/',$action,$reg)) 28 | { 29 | $code=$reg[1]; 30 | 31 | $value = GETPOST($code, 'none'); 32 | 33 | if($code == 'SOFO_DEFAULT_PRODUCT_CATEGORY_FILTER') { 34 | 35 | if(is_array($value)) 36 | { 37 | if(in_array(-1, $value) && count($value) > 1) { 38 | unset($value[array_search(-1, $value)]); 39 | } 40 | $TCategories = array_map('intval', $value); 41 | } 42 | elseif($value > 0) 43 | { 44 | $TCategories = array(intval($value)); 45 | } 46 | else { 47 | $TCategories = array(-1); 48 | } 49 | 50 | $value = serialize($TCategories); 51 | } 52 | 53 | if (dolibarr_set_const($db, $code, $value, 'chaine', 0, '', $conf->entity) > 0) 54 | { 55 | 56 | if($code=='SOFO_USE_DELIVERY_TIME' && GETPOST($code, 'none') == 1) { 57 | 58 | dolibarr_set_const($db,'FOURN_PRODUCT_AVAILABILITY',1); 59 | } 60 | 61 | header("Location: ".$_SERVER["PHP_SELF"]); 62 | exit; 63 | } 64 | else 65 | { 66 | dol_print_error($db); 67 | } 68 | } 69 | 70 | if (preg_match('/del_(.*)/',$action,$reg)) 71 | { 72 | $code=$reg[1]; 73 | if (dolibarr_del_const($db, $code, 0) > 0) 74 | { 75 | Header("Location: ".$_SERVER["PHP_SELF"]); 76 | exit; 77 | } 78 | else 79 | { 80 | dol_print_error($db); 81 | } 82 | } 83 | 84 | /* 85 | * View 86 | */ 87 | 88 | llxHeader('',$langs->trans("SupplierOrderFromOrder")); 89 | 90 | 91 | $linkback=''.$langs->trans("BackToModuleList").''; 92 | print load_fiche_titre($langs->trans("SupplierOrderFromOrder"),$linkback,'supplierorderfromorder@supplierorderfromorder'); 93 | 94 | 95 | // Configuration header 96 | $head = supplierorderfromorderAdminPrepareHead(); 97 | print dol_get_fiche_head( 98 | $head, 99 | 'settings', 100 | $langs->trans("Module104130Name"), 101 | 0, 102 | "supplierorderfromorder@supplierorderfromorder" 103 | ); 104 | 105 | 106 | 107 | print dol_get_fiche_end(); 108 | 109 | print '
'; 110 | 111 | $form=new Form($db); 112 | $var=true; 113 | print ''; 114 | print ''; 115 | print ''."\n"; 116 | print ''; 117 | print ''."\n"; 118 | 119 | 120 | // Add shipment as titles in invoice 121 | $var=!$var; 122 | print ''; 123 | print ''; 127 | print ''; 128 | print ''; 136 | 137 | $var=!$var; 138 | print ''; 139 | print ''; 140 | print ''; 141 | print ''; 149 | 150 | 151 | // Create a new line in supplier order for each line having a different description in the customer order 152 | $var=!$var; 153 | print ''; 154 | print ''; 155 | print ''; 156 | print ''; 164 | 165 | // Description of all products on orders 166 | $var=!$var; 167 | print ''; 168 | print ''; 169 | print ''; 170 | print ''; 178 | 179 | // Create identical supplier order to order 180 | $var=!$var; 181 | print ''; 182 | print ''; 183 | print ''; 184 | print ''; 192 | 193 | if (getDolGlobalString('SOFO_ADD_FREE_LINES')) { 194 | //Use cost price as buying price for free lines 195 | $var=!$var; 196 | print ''; 197 | print ''; 198 | print ''; 199 | print ''; 207 | } 208 | 209 | 210 | // Create distinct supplier order from order depending of project 211 | $var=!$var; 212 | print ''; 213 | print ''; 214 | print ''; 215 | print ''; 223 | 224 | // Import Shipping contact in supplier order 225 | $var=!$var; 226 | print ''; 227 | print ''; 228 | print ''; 229 | print ''; 237 | 238 | // Import Notes in supplier order 239 | $var=!$var; 240 | print ''; 241 | print ''; 242 | print ''; 243 | print ''; 251 | 252 | 253 | // Import Notes in supplier order 254 | $var=!$var; 255 | print ''; 256 | print ''; 257 | print ''; 258 | print ''; 266 | 267 | // Header to supplier order if only one supplier reported 268 | $var=!$var; 269 | print ''; 270 | print ''; 271 | print ''; 272 | print ''; 280 | 281 | $var=!$var; 282 | print ''; 283 | print ''; 284 | print ''; 285 | print ''; 293 | 294 | $var=!$var; 295 | print ''; 296 | print ''; 297 | print ''; 298 | print ''; 306 | 307 | $var=!$var; 308 | print ''; 309 | print ''; 310 | print ''; 311 | print ''; 319 | 320 | $var=!$var; 321 | print ''; 322 | print ''; 323 | print ''; 324 | print ''; 333 | 334 | $var=!$var; 335 | print ''; 336 | print ''; 337 | print ''; 338 | print ''; 346 | 347 | $var=!$var; 348 | print ''; 349 | print ''; 350 | print ''; 351 | print ''; 359 | 360 | $var=!$var; 361 | print ''; 362 | print ''; 363 | print ''; 364 | print ''; 372 | 373 | $var=!$var; 374 | print ''; 375 | print ''; 376 | print ''; 377 | print ''; 385 | 386 | $var=!$var; 387 | print ''; 388 | print ''; 389 | print ''; 390 | print ''; 398 | 399 | 400 | $var=!$var; 401 | print ''; 402 | print ''; 403 | print ''; 404 | print ''; 412 | 413 | 414 | $var=!$var; 415 | print ''; 416 | print ''; 417 | print ''; 418 | print ''; 426 | 427 | 428 | $var=!$var; 429 | print ''; 430 | print ''; 434 | print ''; 435 | print ''; 443 | 444 | 445 | $var=!$var; 446 | print ''; 447 | print ''; 448 | print ''; 449 | print ''; 457 | 458 | $var=!$var; 459 | print ''; 460 | print ''; 461 | print ''; 462 | print ''; 470 | 471 | if(getDolGlobalString('PRODUIT_SOUSPRODUITS')) { 472 | $var = !$var; 473 | print ''; 474 | print ''; 475 | print ''; 476 | print ''; 484 | } 485 | 486 | if (isModEnabled('multicompany') && getDolGlobalString('MULTICOMPANY_STOCK_SHARING_ENABLED')) { 487 | $var = !$var; 488 | print ''; 489 | print ''; 490 | print ''; 491 | print ''; 499 | } 500 | 501 | if(isModEnabled('categorie')) { 502 | $var=!$var; 503 | print ''; 504 | print ''; 505 | print ''; 506 | print ''; 525 | } 526 | 527 | print '
'.$langs->trans("Parameters").' '.$langs->trans("Value").'
'.$langs->trans("CreateNewSupplierOrderAnyTime"); 124 | $htmltooltip = $langs->trans('InfoCreateNewSupplierOrderAnyTime'); 125 | print $form->textwithpicto('', $htmltooltip, 1, 0); 126 | print ' '; 129 | print '
'; 130 | print ''; 131 | print ''; 132 | print $form->selectyesno("SOFO_CREATE_NEW_SUPPLIER_ODER_ANY_TIME",getDolGlobalString('SOFO_CREATE_NEW_SUPPLIER_ODER_ANY_TIME'),1); 133 | print ''; 134 | print '
'; 135 | print '
'.$form->textwithpicto($langs->trans("SOFO_ENABLE_LINKED_EXTRAFIELDS"), $langs->trans("SOFO_ENABLE_LINKED_EXTRAFIELDS_HELP")).' '; 142 | print '
'; 143 | print ''; 144 | print ''; 145 | print $form->selectyesno("SOFO_ENABLE_LINKED_EXTRAFIELDS", getDolGlobalInt('SOFO_ENABLE_LINKED_EXTRAFIELDS'), 1); 146 | print ''; 147 | print '
'; 148 | print '
'.$langs->trans("UseOrderLineDescInSupplierOrder").' '; 157 | print '
'; 158 | print ''; 159 | print ''; 160 | print $form->selectyesno("SUPPORDERFROMORDER_USE_ORDER_DESC",getDolGlobalString('SUPPORDERFROMORDER_USE_ORDER_DESC'),1); 161 | print ''; 162 | print '
'; 163 | print '
'.$langs->trans("CreateNewSupplierOrderWithProductDesc").' '; 171 | print '
'; 172 | print ''; 173 | print ''; 174 | print $form->selectyesno("SOFO_CREATE_NEW_SUPPLIER_ODER_WITH_PRODUCT_DESC",getDolGlobalString('SOFO_CREATE_NEW_SUPPLIER_ODER_WITH_PRODUCT_DESC'),1); 175 | print ''; 176 | print '
'; 177 | print '
'.$langs->trans("AddFreeLinesInSupplierOrder").' '; 185 | print '
'; 186 | print ''; 187 | print ''; 188 | print $form->selectyesno("SOFO_ADD_FREE_LINES",getDolGlobalString('SOFO_ADD_FREE_LINES'),1); 189 | print ''; 190 | print '
'; 191 | print '
'.$langs->trans("UseCostPriceAsBuyingPrice").' '; 200 | print '
'; 201 | print ''; 202 | print ''; 203 | print $form->selectyesno("SOFO_COST_PRICE_AS_BUYING",getDolGlobalString('SOFO_COST_PRICE_AS_BUYING'),1); 204 | print ''; 205 | print '
'; 206 | print '
'.$langs->trans("CreateDistinctSupplierOrderFromOrderDependingOfProject").' '; 216 | print '
'; 217 | print ''; 218 | print ''; 219 | print $form->selectyesno("SOFO_DISTINCT_ORDER_BY_PROJECT",getDolGlobalString('SOFO_DISTINCT_ORDER_BY_PROJECT'),1); 220 | print ''; 221 | print '
'; 222 | print '
'.$langs->trans("SUPPLIERORDER_FROM_ORDER_CONTACT_DELIVERY").' '; 230 | print '
'; 231 | print ''; 232 | print ''; 233 | print $form->selectyesno("SUPPLIERORDER_FROM_ORDER_CONTACT_DELIVERY",getDolGlobalString('SUPPLIERORDER_FROM_ORDER_CONTACT_DELIVERY'),1); 234 | print ''; 235 | print '
'; 236 | print '
'.$langs->trans("SUPPLIERORDER_FROM_ORDER_NOTES_PUBLIC").' '; 244 | print '
'; 245 | print ''; 246 | print ''; 247 | print $form->selectyesno("SUPPLIERORDER_FROM_ORDER_NOTES_PUBLIC", getDolGlobalInt('SUPPLIERORDER_FROM_ORDER_NOTES_PUBLIC'),1); 248 | print ''; 249 | print '
'; 250 | print '
'.$langs->trans("SUPPLIERORDER_FROM_ORDER_NOTES_PRIVATE").' '; 259 | print '
'; 260 | print ''; 261 | print ''; 262 | print $form->selectyesno("SUPPLIERORDER_FROM_ORDER_NOTES_PRIVATE", getDolGlobalInt('SUPPLIERORDER_FROM_ORDER_NOTES_PRIVATE'),1); 263 | print ''; 264 | print '
'; 265 | print '
'.$langs->trans("SUPPLIERORDER_FROM_ORDER_HEADER_SUPPLIER_ORDER").' '; 273 | print '
'; 274 | print ''; 275 | print ''; 276 | print $form->selectyesno("SUPPLIERORDER_FROM_ORDER_HEADER_SUPPLIER_ORDER",getDolGlobalString('SUPPLIERORDER_FROM_ORDER_HEADER_SUPPLIER_ORDER'),1); 277 | print ''; 278 | print '
'; 279 | print '
'.$langs->trans("UseDeliveryTimeToReplenish").' '; 286 | print '
'; 287 | print ''; 288 | print ''; 289 | print $form->selectyesno("SOFO_USE_DELIVERY_TIME",getDolGlobalString('SOFO_USE_DELIVERY_TIME'),1); 290 | print ''; 291 | print '
'; 292 | print '
'.$langs->trans("UseVirtualStockOfOrdersSkipDoliConfig").' '; 299 | print '
'; 300 | print ''; 301 | print ''; 302 | print $form->selectyesno("SOFO_USE_VIRTUAL_ORDER_STOCK",getDolGlobalString('SOFO_USE_VIRTUAL_ORDER_STOCK'),1); 303 | print ''; 304 | print '
'; 305 | print '
'.$langs->trans("SOFO_DO_NOT_USE_CUSTOMER_ORDER").' '; 312 | print '
'; 313 | print ''; 314 | print ''; 315 | print $form->selectyesno("SOFO_DO_NOT_USE_CUSTOMER_ORDER",getDolGlobalString('SOFO_DO_NOT_USE_CUSTOMER_ORDER'),1); 316 | print ''; 317 | print '
'; 318 | print '
'.$langs->trans("SOFO_DEFAUT_FILTER").' '; 325 | print '
'; 326 | print ''; 327 | print ''; 328 | $statutarray=array('1' => $langs->trans("Finished"), '0' => $langs->trans("RowMaterial")); 329 | print $form->selectarray('SOFO_DEFAUT_FILTER',$statutarray,getDolGlobalString('SOFO_DEFAUT_FILTER','-1'),1); 330 | print ''; 331 | print '
'; 332 | print '
'.$langs->trans("SOFO_GET_INFOS_FROM_FOURN").' '; 339 | print '
'; 340 | print ''; 341 | print ''; 342 | print $form->selectyesno("SOFO_GET_INFOS_FROM_FOURN",getDolGlobalString('SOFO_GET_INFOS_FROM_FOURN'),1); 343 | print ''; 344 | print '
'; 345 | print '
'.$langs->trans("SOFO_GET_EXTRAFIELDS_FROM_ORDER").' '; 352 | print '
'; 353 | print ''; 354 | print ''; 355 | print $form->selectyesno("SOFO_GET_EXTRAFIELDS_FROM_ORDER",getDolGlobalInt('SOFO_GET_EXTRAFIELDS_FROM_ORDER'),1); 356 | print ''; 357 | print '
'; 358 | print '
'.$langs->trans("SOFO_GET_INFOS_FROM_ORDER").' '; 365 | print '
'; 366 | print ''; 367 | print ''; 368 | print $form->selectyesno("SOFO_GET_INFOS_FROM_ORDER",getDolGlobalInt('SOFO_GET_INFOS_FROM_ORDER'),1); 369 | print ''; 370 | print '
'; 371 | print '
'.$langs->trans("SOFO_USE_MAX_DELIVERY_DATE").' '; 378 | print '
'; 379 | print ''; 380 | print ''; 381 | print $form->selectyesno("SOFO_USE_MAX_DELIVERY_DATE",getDolGlobalString('SOFO_USE_MAX_DELIVERY_DATE'),1); 382 | print ''; 383 | print '
'; 384 | print '
'.$langs->trans("SOFO_DISPLAY_SERVICES").' '; 391 | print '
'; 392 | print ''; 393 | print ''; 394 | print $form->selectyesno("SOFO_DISPLAY_SERVICES",getDolGlobalString('SOFO_DISPLAY_SERVICES'),1); 395 | print ''; 396 | print '
'; 397 | print '
'.$langs->trans("INCLUDE_PRODUCT_LINES_WITH_ADEQUATE_STOCK").' '; 405 | print '
'; 406 | print ''; 407 | print ''; 408 | print $form->selectyesno("INCLUDE_PRODUCT_LINES_WITH_ADEQUATE_STOCK",getDolGlobalString('INCLUDE_PRODUCT_LINES_WITH_ADEQUATE_STOCK'),1); 409 | print ''; 410 | print '
'; 411 | print '
'.$langs->trans('SOFO_PRESELECT_SUPPLIER_PRICE_FROM_LINE_BUY_PRICE').' '; 419 | print '
'; 420 | print ''; 421 | print ''; 422 | print $form->selectyesno('SOFO_PRESELECT_SUPPLIER_PRICE_FROM_LINE_BUY_PRICE', getDolGlobalString('SOFO_PRESELECT_SUPPLIER_PRICE_FROM_LINE_BUY_PRICE'),1); 423 | print ''; 424 | print '
'; 425 | print '
'.$langs->trans('SOFO_QTY_LINES_COMES_FROM_ORIGIN_ORDER_ONLY'); 431 | $htmltooltip = $langs->trans('InfoSOFO_QTY_LINES_COMES_FROM_ORIGIN_ORDER_ONLY'); 432 | print $form->textwithpicto('', $htmltooltip, 1, 0); 433 | print ' '; 436 | print '
'; 437 | print ''; 438 | print ''; 439 | print $form->selectyesno('SOFO_QTY_LINES_COMES_FROM_ORIGIN_ORDER_ONLY', getDolGlobalString('SOFO_QTY_LINES_COMES_FROM_ORIGIN_ORDER_ONLY'),1); 440 | print ''; 441 | print '
'; 442 | print '
'.$langs->trans('SOFO_GROUP_LINES_BY_PRODUCT').' '; 450 | print '
'; 451 | print ''; 452 | print ''; 453 | print $form->selectyesno('SOFO_GROUP_LINES_BY_PRODUCT', getDolGlobalString('SOFO_GROUP_LINES_BY_PRODUCT'),1); 454 | print ''; 455 | print '
'; 456 | print '
'.$langs->trans('SOFO_GET_REF_SUPPLIER_FROM_ORDER').' '; 463 | print '
'; 464 | print ''; 465 | print ''; 466 | print $form->selectyesno('SOFO_GET_REF_SUPPLIER_FROM_ORDER', getDolGlobalString('SOFO_GET_REF_SUPPLIER_FROM_ORDER'),1); 467 | print ''; 468 | print '
'; 469 | print '
' . $langs->trans('SOFO_VIRTUAL_PRODUCTS') . ' '; 477 | print '
'; 478 | print ''; 479 | print ''; 480 | print $form->selectyesno("SOFO_VIRTUAL_PRODUCTS", getDolGlobalString('SOFO_VIRTUAL_PRODUCTS'), 1); 481 | print ''; 482 | print '
'; 483 | print '
' . $langs->trans('SOFO_CHECK_STOCK_ON_SHARED_STOCK') . ' '; 492 | print '
'; 493 | print ''; 494 | print ''; 495 | print $form->selectyesno('SOFO_CHECK_STOCK_ON_SHARED_STOCK', getDolGlobalString('SOFO_CHECK_STOCK_ON_SHARED_STOCK'), 1); 496 | print ''; 497 | print '
'; 498 | print '
'.$langs->trans("SOFO_DEFAULT_PRODUCT_CATEGORY_FILTER").' '; 507 | print '
'; 508 | print ''; 509 | print ''; 510 | print getCatMultiselect("SOFO_DEFAULT_PRODUCT_CATEGORY_FILTER", getDolGlobalString('SOFO_DEFAULT_PRODUCT_CATEGORY_FILTER') ? unserialize(getDolGlobalString('SOFO_DEFAULT_PRODUCT_CATEGORY_FILTER')) : array(-1)); 511 | print 'Supprimer le filtre'; 512 | print ''; 513 | print '
'; 514 | ?> 515 | 523 |
'; 528 | 529 | // Footer 530 | llxFooter(); 531 | // Close database handler 532 | $db->close(); 533 | -------------------------------------------------------------------------------- /lib/function.lib.php: -------------------------------------------------------------------------------- 1 | prefix()."commande_fournisseurdet as cd"; 22 | $sql.= ", ".$db->prefix()."commande_fournisseur as c"; 23 | $sql.= ", ".$db->prefix()."societe as s"; 24 | $sql.= " WHERE c.rowid = cd.fk_commande"; 25 | $sql.= " AND c.fk_soc = s.rowid"; 26 | $sql.= " AND c.entity = ".$conf->entity; 27 | $sql.= " AND cd.fk_product = ".$fk_product; 28 | $sql.= " AND (c.delivery_date IS NULL OR c.delivery_date <= '".$date."') "; 29 | if ($filtrestatut != '') $sql.= " AND c.fk_statut in (".$filtrestatut.")"; 30 | 31 | $result =$db->query($sql); 32 | if ( $result ) 33 | { 34 | $obj = $db->fetch_object($result); 35 | return (float)$obj->qty; 36 | } 37 | else 38 | { 39 | 40 | return 0; 41 | } 42 | } 43 | 44 | function _load_stats_commande_date($fk_product, $date,$filtrestatut='1,2') { 45 | global $conf,$user,$db; 46 | 47 | $sql = "SELECT SUM(cd.qty) as qty"; 48 | $sql.= " FROM ".$db->prefix()."commandedet as cd"; 49 | $sql.= ", ".$db->prefix()."commande as c"; 50 | $sql.= ", ".$db->prefix()."societe as s"; 51 | $sql.= " WHERE c.rowid = cd.fk_commande"; 52 | $sql.= " AND c.fk_soc = s.rowid"; 53 | $sql.= " AND c.entity = ".$conf->entity; 54 | $sql.= " AND cd.fk_product = ".$fk_product; 55 | $sql.= " AND (c.delivery_date IS NULL OR c.delivery_date <='".$date."') "; 56 | if ($filtrestatut <> '') $sql.= " AND c.fk_statut in (".$filtrestatut.")"; 57 | 58 | $result =$db->query($sql); 59 | if ( $result ) 60 | { 61 | $obj = $db->fetch_object($result); 62 | return (float)$obj->qty; 63 | } 64 | else 65 | { 66 | 67 | return 0; 68 | } 69 | } 70 | 71 | function getExpedie($fk_product) { 72 | global $conf, $db; 73 | 74 | $sql = "SELECT SUM(ed.qty) as qty"; 75 | $sql.= " FROM ".$db->prefix()."expeditiondet as ed"; 76 | $sql.= " LEFT JOIN ".$db->prefix()."expedition as e ON (e.rowid=ed.fk_expedition)"; 77 | if ((float) DOL_VERSION < 20) $sql.= " LEFT JOIN ".$db->prefix()."commandedet as cd ON (ed.fk_origin_line=cd.rowid)"; 78 | else $sql.= " LEFT JOIN ".$db->prefix()."commandedet as cd ON (ed.fk_elementdet=cd.rowid)"; 79 | $sql.= " WHERE 1"; 80 | $sql.= " AND e.entity = ".$conf->entity; 81 | $sql.= " AND cd.fk_product = ".$fk_product; 82 | $sql.= " AND e.fk_statut in (1)"; 83 | 84 | $result =$db->query($sql); 85 | if ( $result ) 86 | { 87 | $obj = $db->fetch_object($result); 88 | return (float)$obj->qty; 89 | } 90 | else 91 | { 92 | 93 | return 0; 94 | } 95 | 96 | } 97 | 98 | function getPaiementCode($id) { 99 | 100 | global $db; 101 | 102 | if(empty($id)) return ''; 103 | 104 | $sql = 'SELECT code FROM '.$db->prefix().'c_paiement WHERE id = '.$id; 105 | $resql = $db->query($sql); 106 | $res = $db->fetch_object($resql); 107 | 108 | return $res->code; 109 | } 110 | 111 | 112 | function getPaymentTermCode($id) { 113 | 114 | global $db; 115 | 116 | if(empty($id)) return ''; 117 | 118 | $sql = 'SELECT code FROM '.$db->prefix().'c_payment_term WHERE rowid = '.$id; 119 | $resql = $db->query($sql); 120 | $res = $db->fetch_object($resql); 121 | 122 | return $res->code; 123 | } 124 | 125 | 126 | function getCatMultiselect($htmlname, $TCategories) 127 | { 128 | global $form, $langs; 129 | 130 | $maxlength=64; 131 | $excludeafterid=0; 132 | $outputmode=1; 133 | $array=$form->select_all_categories('product', $TCategories, $htmlname, $maxlength, $excludeafterid, $outputmode); 134 | $array[-1] = '('.$langs->trans('NoFilter').')'; 135 | 136 | $key_in_label=0; 137 | $value_as_key=0; 138 | $morecss=''; 139 | $translate=0; 140 | $width='80%'; 141 | $moreattrib=''; 142 | $elemtype=''; 143 | 144 | return $form->multiselectarray($htmlname, $array, $TCategories, $key_in_label, $value_as_key, $morecss, $translate, $width, $moreattrib,$elemtype); 145 | } 146 | 147 | 148 | 149 | function getSupplierOrderAvailable($supplierSocId,$shippingContactId=0,$array_options=array(),$restrictToCustomerOrder = 0) 150 | { 151 | global $db, $conf; 152 | $shippingContactId = intval($shippingContactId); 153 | $status = intval($status); 154 | 155 | $Torder = array(); 156 | 157 | $sql = 'SELECT cf.rowid '; 158 | $sql .= ' FROM ' . $db->prefix() . 'commande_fournisseur cf '; 159 | $sql .= ' LEFT JOIN ' . $db->prefix() . 'commande_fournisseur_extrafields cfext ON (cfext.fk_object = cf.rowid) '; 160 | 161 | if(!empty($shippingContactId)) 162 | { 163 | $sql .= ' JOIN ' . $db->prefix() . 'element_contact ec ON (ec.element_id = fk_target AND ec.fk_socpeople = '.$shippingContactId.') '; 164 | } 165 | 166 | $sql .= ' WHERE cf.fk_soc = '.intval($supplierSocId).' '; 167 | 168 | $sql .= ' AND cf.fk_statut = 0 '; 169 | $sql .= ' AND cf.ref LIKE "(PROV%" '; 170 | 171 | 172 | if(!empty($array_options)) 173 | { 174 | foreach ($array_options as $col => $value) 175 | { 176 | $sql .= ' AND cfext.`'.$col.'` = \''.$value.'\' '; 177 | } 178 | } 179 | //print $sql; 180 | $resql=$db->query($sql); 181 | if ($resql) 182 | { 183 | while ($obj = $db->fetch_object($resql)) 184 | { 185 | $restriction = false; 186 | 187 | if($restrictToCustomerOrder>0){ 188 | // recherche des commandes client liées 189 | $TLinkedObject = getLinkedObject($obj->rowid,'order_supplier','commande'); 190 | if(!empty($TLinkedObject) && is_array($TLinkedObject)){ 191 | foreach($TLinkedObject as $commandeId){ 192 | // comparaison avec la commande recherchée 193 | if((int)$commandeId != (int)$restrictToCustomerOrder){ 194 | $restriction = true; 195 | break; 196 | } 197 | } 198 | } 199 | else{ 200 | $restriction = true; 201 | } 202 | } 203 | 204 | if(!$restriction){ 205 | $Torder[] = $obj->rowid; 206 | } 207 | } 208 | 209 | 210 | 211 | return $Torder; 212 | } 213 | 214 | return -1; 215 | 216 | } 217 | 218 | /** 219 | * Création ou mise à jour de la commande fournisseur selon la conf 220 | * getDolGlobalString('SOFO_CREATE_NEW_SUPPLIER_ODER_ANY_TIME') 221 | * 222 | * @param OrderLine $line 223 | * @param int $supplierSocId 224 | * @param int $shippingContactId 225 | * @param int $supplierOrderStatus 226 | * @param bool $createCommande 227 | * @param bool $fetchCommande 228 | * @return CommandeFournisseur 229 | */ 230 | function getSupplierOrderToUpdate(OrderLine $line, int $supplierSocId, int $shippingContactId, int $supplierOrderStatus, bool $createCommande = false, bool $fetchCommande = false) :CommandeFournisseur 231 | { 232 | dol_include_once('fourn/class/fournisseur.commande.class.php'); 233 | 234 | global $db, $user, $langs; 235 | 236 | $array_options = array(); 237 | $CommandeFournisseur = new CommandeFournisseur($db); 238 | 239 | $societe = new Societe($db); 240 | $res = $societe->fetch($supplierSocId); 241 | 242 | if ($res < 0){ 243 | setEventMessage('NoCreateSupplierOrderMissingSociete', 'errors'); 244 | return $CommandeFournisseur; // pas de société retourne la commande null 245 | } 246 | 247 | // search and get draft supplier order linked 248 | $TSearchSupplierOrder = getLinkedSupplierOrderFromOrder($line->fk_commande, $supplierSocId, $shippingContactId, $supplierOrderStatus); 249 | if(empty($TSearchSupplierOrder)) { 250 | $restrictToCustomerOrder = 0; // search draft supplier order with same critera 251 | if(getDolGlobalString('SOFO_USE_RESTRICTION_TO_CUSTOMER_ORDER')){ 252 | $restrictToCustomerOrder = $line->fk_commande; 253 | } 254 | $TSearchSupplierOrder = getSupplierOrderAvailable($supplierSocId, $shippingContactId, $array_options, $restrictToCustomerOrder); 255 | } 256 | if (!is_array($TSearchSupplierOrder)) { 257 | setEventMessage('NoCreateSupplierOrderErrorSearch', 'errors'); 258 | return $CommandeFournisseur; // pas de $TSearchSupplierOrder retourne la commande null 259 | } 260 | //====================================================================================================== 261 | // Section concernant la Conf "Créer une commande fournisseur brouillon pour chaque commande client" 262 | 263 | /** 264 | * Création de commande fournisseur si : 265 | * SI Aucune commande contenue dans $TSearchSupplierOrder 266 | * OU mon parametre de fonction $createCommande est à true et $fetchCommande à false 267 | * OU si ma conf de module SOFO_CREATE_NEW_SUPPLIER_ODER_ANY_TIME "Créer une commande fournisseur brouillon pour chaque commande client" est a TRUE ET que $fetchCommande est à false 268 | */ 269 | if ((($createCommande && !$fetchCommande ) || empty($TSearchSupplierOrder)) 270 | || (!$fetchCommande && getDolGlobalString('SOFO_CREATE_NEW_SUPPLIER_ODER_ANY_TIME'))) { 271 | $CommandeFournisseur->socid = $supplierSocId; 272 | $CommandeFournisseur->mode_reglement_id = $societe->mode_reglement_supplier_id; 273 | $CommandeFournisseur->cond_reglement_id = $societe->cond_reglement_supplier_id; 274 | $res = $CommandeFournisseur->create($user); 275 | if ($res){ 276 | setEventMessage($langs->trans('supplierOrderCreated', $CommandeFournisseur->ref)); 277 | } 278 | } 279 | /** 280 | * On fetch la dernière commande fournisseur de mon tableau $TSearchSupplierOrder si : 281 | * Si ma conf de module SOFO_CREATE_NEW_SUPPLIER_ODER_ANY_TIME "Créer une commande fournisseur brouillon pour chaque commande client" est à FALSE 282 | * OU mon parametre de fonction $fetchCommande est à true ET SOFO_CREATE_NEW_SUPPLIER_ODER_ANY_TIME est true 283 | */ 284 | if (!getDolGlobalString('SOFO_CREATE_NEW_SUPPLIER_ODER_ANY_TIME') || ($fetchCommande && getDolGlobalString('SOFO_CREATE_NEW_SUPPLIER_ODER_ANY_TIME'))){ 285 | $lastValue = end($TSearchSupplierOrder); 286 | $res = $CommandeFournisseur->fetch($lastValue); 287 | } 288 | if ($res) { 289 | $CommandeFournisseur->add_object_linked('commande', $line->fk_commande); 290 | }else{ 291 | setEventMessage($langs->trans('supplierOrderNotCreated', $line->product_ref )); 292 | dol_syslog(get_class($line)."::getSupplierOrderToUpdate ".$line->error, LOG_ERR); 293 | } 294 | //====================================================================================================== 295 | return $CommandeFournisseur; 296 | 297 | } 298 | 299 | /** 300 | * @param $CommandeFournisseur 301 | * @param $line 302 | * @param $productid 303 | * @param $price 304 | * @param $qty 305 | * @param $supplierSocId 306 | * @return array 307 | */ 308 | function updateOrAddlineToSupplierOrder($CommandeFournisseur, $line, $productid, $price, $qty, $supplierSocId) 309 | { 310 | global $db, $conf; 311 | 312 | $ret = array( 313 | 'return' => 0, 314 | 'mode' => 'add' 315 | ); 316 | 317 | if (empty($productid)) $productid = $line->fk_product; 318 | 319 | // Get subprice from product 320 | if(!empty($productid)){ 321 | $ProductFournisseur = new ProductFournisseur($db); 322 | if($ProductFournisseur->find_min_price_product_fournisseur($productid, $qty, $supplierSocId) > 0){ 323 | $price = floatval($ProductFournisseur->fourn_unitprice); // floatval is used to remove non used zero 324 | $tva_tx = $ProductFournisseur->tva_tx; 325 | $fk_prod_fourn_price = $ProductFournisseur->product_fourn_price_id; 326 | $remise_percent = $ProductFournisseur->fourn_remise_percent; 327 | $ref_supplier= $ProductFournisseur->ref_supplier; 328 | } 329 | } 330 | 331 | //récupération du prix d'achat de la line si pas de prix fournisseur 332 | if(empty($price) && !empty($line->pa_ht) ){ 333 | $price = $line->pa_ht; 334 | } 335 | 336 | // SEARCH in supplier order if same product exist 337 | $supplierLineRowidExist = 0 ; 338 | if(!empty($CommandeFournisseur->lines) && getDolGlobalInt('SOFO_ADD_QUANTITY_RATHER_THAN_CREATE_LINES') ) 339 | { 340 | foreach ($CommandeFournisseur->lines as $li => $fournLine) 341 | { 342 | if( 343 | $fournLine->ref_supplier == $ref_supplier 344 | && $fournLine->fk_product == $productid 345 | ) 346 | { 347 | $supplierLineRowidExist = $fournLine->id; 348 | $fournLine->fetch_product(); 349 | break; 350 | } 351 | } 352 | } 353 | 354 | // UPDATE SUPPLIER LINE 355 | if($supplierLineRowidExist>0) 356 | { 357 | $ret['mode'] = 'update'; 358 | $ret['return'] = $CommandeFournisseur->updateline( 359 | $fournLine->id, 360 | $fournLine->desc, 361 | $fournLine->subprice, 362 | $fournLine->qty + $qty, 363 | $fournLine->remise_percent, 364 | $fournLine->tva_tx, 365 | $fournLine->localtax1_tx, 366 | $fournLine->localtax2_tx, 367 | 'HT', 368 | 0, 369 | $fournLine->product->type, 370 | 0, // $notrigger 371 | '', 372 | '', 373 | $fournLine->array_options, 374 | $fournLine->product->fk_unit, 375 | 0, // $pu_ht_devise 376 | $fournLine->ref_supplier 377 | ); 378 | 379 | if ($ret['return'] >= 0) $ret['return'] = $fournLine->id;// yes $CommandeFournisseur->updateline can return 0 on success 380 | 381 | } 382 | else 383 | { 384 | // les object sont passés par référence par défaut 385 | // l'object line est la ligne de commande initiale 386 | // nous sommes en train de modifier cette ligne si nous ne clonons pas celle-ci 387 | $lineClone = clone $line; 388 | if($lineClone->fk_product != $productid) $lineClone->fk_product = $productid; 389 | $res = $lineClone->fetch_product(); 390 | if($res > 0) { 391 | $fk_unit = $lineClone->product->fk_unit; 392 | $product_type = $lineClone->product->type; 393 | } else { 394 | $fk_unit = $lineClone->fk_unit; 395 | $product_type = $lineClone->product_type; 396 | } 397 | // ADD LINE 398 | $ret['return'] = $CommandeFournisseur->addline( 399 | $lineClone->desc, 400 | $price, 401 | $qty, 402 | $lineClone->tva_tx, 403 | $txlocaltax1=0.0, 404 | $txlocaltax2=0.0, 405 | $productid, 406 | $fk_prod_fourn_price, 407 | $ref_supplier, 408 | $remise_percent, 409 | 'HT', 410 | 0, //$pu_ttc=0.0, 411 | $product_type, 412 | $lineClone->info_bits, 413 | false, //$notrigger=false, 414 | null, //$date_start=null, 415 | null, //$date_end=null, 416 | $lineClone->array_options, //$array_options=0, 417 | $fk_unit, 418 | 0,//$pu_ht_devise=0, 419 | 'commandedet', //$origin= // peut être un jour ça sera géré... 420 | $lineClone->id //$origin_id=0 // peut être un jour ça sera géré... 421 | ); 422 | } 423 | 424 | return $ret; 425 | } 426 | 427 | /** 428 | * @param $sourceCommandeId 429 | * @param $supplierSocId 430 | * @param int $shippingContactId 431 | * @param int $status 432 | * @param array $array_options 433 | * @return array|int 434 | */ 435 | function getLinkedSupplierOrderFromOrder($sourceCommandeId,$supplierSocId,$shippingContactId=0,$status=-1,$array_options=array()) 436 | { 437 | global $db, $conf; 438 | $shippingContactId = intval($shippingContactId); 439 | $status = intval($status); 440 | 441 | $Torder = array(); 442 | 443 | $sql = 'SELECT ee.fk_target '; 444 | $sql .= ' FROM ' . $db->prefix() . 'element_element ee'; 445 | $sql .= ' JOIN ' . $db->prefix() . 'commande_fournisseur cf ON (ee.fk_target = cf.rowid) '; 446 | $sql .= ' LEFT JOIN ' . $db->prefix() . 'commande_fournisseur_extrafields cfext ON (cfext.fk_object = cf.rowid) '; 447 | 448 | if(!empty($shippingContactId)) 449 | { 450 | $sql .= ' JOIN ' . $db->prefix() . 'element_contact ec ON (ec.element_id = fk_target AND ec.fk_socpeople = '.$shippingContactId.') '; 451 | } 452 | 453 | $sql .= ' WHERE ee.fk_source = '.intval($sourceCommandeId).' '; 454 | $sql .= ' AND ee.sourcetype = \'commande\' '; 455 | $sql .= ' AND cf.fk_soc = '.intval($supplierSocId).' '; 456 | $sql .= ' AND ee.targettype = \'order_supplier\' '; 457 | 458 | if($status>=0) 459 | { 460 | $sql .= ' AND cf.fk_statut = '.$status.' '; 461 | } 462 | 463 | if(!empty($array_options)) 464 | { 465 | foreach ($array_options as $col => $value) 466 | { 467 | $sql .= ' AND cfext.`'.$col.'` = \''.$value.'\' '; 468 | } 469 | } 470 | 471 | $resql=$db->query($sql); 472 | if ($resql) 473 | { 474 | while ($obj = $db->fetch_object($resql)) 475 | { 476 | $Torder[] = $obj->fk_target; 477 | } 478 | 479 | return $Torder; 480 | } 481 | 482 | return -1; 483 | 484 | } 485 | 486 | /** 487 | * @param null $sourceid 488 | * @param string $sourcetype 489 | * @param string $targettype 490 | * @return array|int 491 | */ 492 | function getLinkedObject($sourceid=null,$sourcetype='',$targettype='') 493 | { 494 | global $db; 495 | $TElement=array(); 496 | 497 | $sql = 'SELECT fk_target '; 498 | $sql .= ' FROM ' . $db->prefix() . 'element_element ee'; 499 | $sql .= ' WHERE ee.fk_source = '.intval($sourceid).' '; 500 | $sql .= ' AND ee.sourcetype = \''.$db->escape($sourcetype).'\' '; 501 | if(!empty($targettype)){ 502 | $sql .= ' AND ee.targettype = \''.$db->escape($targettype).'\' '; 503 | } 504 | 505 | $resql=$db->query($sql); 506 | if ($resql) 507 | { 508 | while($obj = $db->fetch_object($resql)) 509 | { 510 | $TElement[] = $obj->fk_target; 511 | } 512 | } 513 | 514 | // search for opposite 515 | 516 | $sql = 'SELECT fk_target '; 517 | $sql .= ' FROM ' . $db->prefix() . 'element_element ee'; 518 | $sql .= ' WHERE ee.fk_target = '.intval($sourceid).' '; 519 | $sql .= ' AND ee.targettype = \''.$db->escape($sourcetype).'\' '; 520 | if(!empty($targettype)){ 521 | $sql .= ' AND ee.sourcetype = \''.$db->escape($targettype).'\' '; 522 | } 523 | 524 | $resql=$db->query($sql); 525 | if ($resql) 526 | { 527 | while($obj = $db->fetch_object($resql)) 528 | { 529 | $TElement[] = $obj->fk_source; 530 | } 531 | } 532 | 533 | 534 | return !empty($TElement)?$TElement:0; 535 | 536 | } 537 | 538 | /** 539 | * @param $sourceCommandeLineId 540 | * @param string $sourcetype 541 | * @return int 542 | */ 543 | function getLinkedSupplierOrderLineFromElementLine($sourceCommandeLineId, $sourcetype = 'commandedet') 544 | { 545 | $TElement = getLinkedSupplierOrdersLinesFromElementLine($sourceCommandeLineId, $sourcetype); 546 | if (!empty($TElement)) 547 | { 548 | return (int)$TElement[0]; 549 | } 550 | return 0; 551 | } 552 | 553 | /** 554 | * @param $sourceCommandeLineId 555 | * @param string $sourcetype 556 | * @return array|int 557 | */ 558 | function getLinkedSupplierOrdersLinesFromElementLine($sourceCommandeLineId, $sourcetype = 'commandedet') 559 | { 560 | global $db; 561 | 562 | $sql = 'SELECT fk_target '; 563 | $sql .= ' FROM ' . $db->prefix() . 'element_element ee'; 564 | $sql .= ' WHERE ee.fk_source = '.intval($sourceCommandeLineId).' '; 565 | $sql .= ' AND ee.sourcetype = \''.$db->escape($sourcetype).'\' '; 566 | $sql .= ' AND ee.targettype = \'commande_fournisseurdet\' '; 567 | 568 | $TElement=array(); 569 | 570 | $resql=$db->query($sql); 571 | if ($resql) 572 | { 573 | while($obj = $db->fetch_object($resql)) 574 | { 575 | $TElement[] = $obj->fk_target; 576 | } 577 | 578 | return $TElement; 579 | } 580 | 581 | return 0; 582 | 583 | } 584 | 585 | /** 586 | * @param $sourceCommandeLineId 587 | * @return int 588 | */ 589 | function getLinkedOrderLineFromSupplierOrderLine($sourceCommandeLineId) 590 | { 591 | global $db; 592 | 593 | $sql = 'SELECT fk_source '; 594 | $sql .= ' FROM ' . $db->prefix() . 'element_element ee'; 595 | $sql .= ' WHERE ee.fk_target = '.intval($sourceCommandeLineId).' '; 596 | $sql .= ' AND ee.sourcetype = \'commandedet\' '; 597 | $sql .= ' AND ee.targettype = \'commande_fournisseurdet\' '; 598 | 599 | $resql=$db->query($sql); 600 | if ($resql && $obj = $db->fetch_object($resql)) 601 | { 602 | return $obj->fk_source; 603 | } 604 | return 0; 605 | 606 | } 607 | 608 | /** 609 | * @param $fk_unit 610 | * @param string $return 611 | * @return int|string 612 | */ 613 | function getUnitLabel($fk_unit, $return = 'code') 614 | { 615 | global $db, $langs; 616 | 617 | $sql = 'SELECT label, code from '.$db->prefix().'c_units'; 618 | $sql.= ' WHERE rowid = '.intval($fk_unit); 619 | 620 | $resql=$db->query($sql); 621 | if ($resql && $obj = $db->fetch_object($resql)) 622 | { 623 | if($return == 'label'){ 624 | return $langs->trans('unit'.$obj->code); 625 | }else{ 626 | return $obj->code; 627 | } 628 | 629 | } 630 | return ''; 631 | } 632 | 633 | /** 634 | * @param $fk_element 635 | * @param $element 636 | * @param $fk_product 637 | * @param int $qty 638 | * @param int $deep 639 | * @param int $maxDeep 640 | * @return array|false 641 | */ 642 | function sofo_nomenclatureProductDeepCrawl($fk_element, $element, $fk_product,$qty = 1, $deep = 0, $maxDeep = 0){ 643 | global $db,$conf; 644 | 645 | $maxDeepConf = floatval( getDolGlobalString('NOMENCLATURE_MAX_NESTED_LEVEL','50')); 646 | $maxDeep = !empty($maxDeep)?$maxDeep:$maxDeepConf ; 647 | 648 | if($deep>$maxDeep){ return array(); } 649 | 650 | dol_include_once('/nomenclature/class/nomenclature.class.php'); 651 | 652 | if(!class_exists('TNomenclature')){ 653 | return false; 654 | } 655 | 656 | $nomenclature = new TNomenclature($db); 657 | $PDOdb = new TPDOdb($db); 658 | 659 | $nomenclature->loadByObjectId($PDOdb,$fk_element, $element, false, $fk_product, $qty); //get lines of nomenclature 660 | 661 | $Tlines= array(); 662 | 663 | $i=0; 664 | if(!empty($nomenclature->TNomenclatureDet)){ 665 | $detailsNomenclature=$nomenclature->getDetails($qty); 666 | // PARCOURS DE LA NOMENCLATURE 667 | foreach ($nomenclature->TNomenclatureDet as &$det) 668 | { 669 | $i++; 670 | 671 | $Tlines[$i] = array( 672 | 'element' => 'nomenclaturedet', 673 | 'id' => !empty($det->id)?$det->id:$det->rowid, 674 | 'fk_product'=>$det->fk_product, 675 | 'infos' => array( 676 | 'label' => '', 677 | 'desc' => '', 678 | 'qty' => $qty * $det->qty, 679 | //'object' => $det, 680 | ), 681 | ); 682 | 683 | $childs = sofo_nomenclatureProductDeepCrawl($det->fk_product, 'product', $det->fk_product,$qty * $det->qty, $deep+1, $maxDeep); 684 | 685 | if(!empty($childs)) 686 | { 687 | $Tlines[$i]['children'] = $childs; 688 | } 689 | 690 | } 691 | 692 | } 693 | 694 | return $Tlines; 695 | } 696 | 697 | /** 698 | * @param $fk_product 699 | * @return int 700 | */ 701 | function sofo_getFournMinPrice($fk_product) 702 | { 703 | global $db; 704 | 705 | $ProductFournisseur = new ProductFournisseur($db); 706 | $TfournPrices = $ProductFournisseur->list_product_fournisseur_price($fk_product, '', '', 1); 707 | 708 | 709 | $minFournPrice = 0; 710 | $minFournPriceId = 0; 711 | if(!empty($TfournPrices)) 712 | { 713 | foreach ($TfournPrices as $fournPrices){ 714 | 715 | if(empty($minFournPrice)){ 716 | $minFournPrice = $fournPrices->fourn_unitprice; 717 | $minFournPriceId = $fournPrices->fourn_id; 718 | } 719 | 720 | if(!empty($fournPrices->fourn_unitprice) && $fournPrices->fourn_unitprice < $minFournPrice && !empty($minFournPriceId) ) 721 | { 722 | $minFournPrice = $fournPrices->fourn_unitprice; 723 | $minFournPriceId = $fournPrices->fourn_id; 724 | } 725 | } 726 | } 727 | 728 | return $minFournPriceId; 729 | } 730 | 731 | /** 732 | * @return array 733 | */ 734 | function supplierorderfromorderAdminPrepareHead() 735 | { 736 | global $langs, $conf; 737 | 738 | $langs->load("supplierorderfromorder@supplierorderfromorder"); 739 | 740 | $h = 0; 741 | $head = array(); 742 | 743 | $head[$h][0] = dol_buildpath("/supplierorderfromorder/admin/supplierorderfromorder_setup.php", 1); 744 | $head[$h][1] = $langs->trans("Parameters"); 745 | $head[$h][2] = 'settings'; 746 | $h++; 747 | 748 | if (isModEnabled('nomenclature')){ 749 | $head[$h][0] = dol_buildpath("/supplierorderfromorder/admin/dispatch_to_supplier_order_setup.php", 1); 750 | $head[$h][1] = $langs->trans("Nomenclature"); 751 | $head[$h][2] = 'nomenclature'; 752 | $h++; 753 | } 754 | 755 | $head[$h][0] = dol_buildpath("/supplierorderfromorder/admin/supplierorderfromorder_about.php", 1); 756 | $head[$h][1] = $langs->trans("About"); 757 | $head[$h][2] = 'about'; 758 | $h++; 759 | 760 | complete_head_from_modules($conf, $langs, new stdClass(), $head, $h, 'supplierorderfromorderadmin'); 761 | 762 | return $head; 763 | } 764 | 765 | /** 766 | * Build SQL query for ordercustomer view (grouped by product or not). 767 | * 768 | * @param DoliDB $db Database handler. 769 | * @param int|string $entityToTest List of entities to filter stock on (numeric list or comma string). 770 | * @param array $TCategoriesQuery Category ids to restrict products. 771 | * @param int $fk_commande Customer order id to filter on. 772 | * @param string $search_all Global search term applied to ref/label/description/note. 773 | * @param int|string $type Product type filter (1 service, 0/other product). 774 | * @param string $sref Product ref search (space separated tokens). 775 | * @param string $snom Product label search (space separated tokens). 776 | * @param string $canvas Product canvas filter. 777 | * @param string $salert Whether to filter by stock alert threshold ('on'). 778 | * @param bool $groupByProduct Group lines by product (true) or keep one line per order line. 779 | * @return string 780 | */ 781 | function sofoBuildOrderCustomerQuery($db, $entityToTest, $TCategoriesQuery, $fk_commande, $search_all, $type, $sref, $snom, $canvas, $salert, $groupByProduct = true) : string 782 | { 783 | $sql = 'SELECT prod.rowid, prod.ref, prod.label, cd.description, prod.price, cd.qty as qty, COALESCE(SUM(ed.qty), 0) as qty_shipped, cd.buy_price_ht'; 784 | $sql .= ', prod.price_ttc, prod.price_base_type,prod.fk_product_type'; 785 | $sql .= ', prod.tms as datem, prod.duration, prod.tobuy, prod.seuil_stock_alerte, cd.rang,'; 786 | 787 | if ($groupByProduct) { 788 | if (in_array($db->type, array('pgsql'))) { 789 | $sql .= ' string_agg(DISTINCT cd.rowid::character varying, \'@\') as lineid,'; 790 | } else { 791 | $sql .= ' GROUP_CONCAT(cd.rowid SEPARATOR "@") as lineid,'; 792 | } 793 | } else { 794 | $sql .= ' cd.rowid as lineid,'; 795 | } 796 | 797 | $sql .= ' ( SELECT SUM(s.reel) FROM ' . $db->prefix() . 'product_stock s'; 798 | $sql .= ' INNER JOIN ' . $db->prefix() . 'entrepot as entre ON entre.rowid=s.fk_entrepot'; 799 | $sql .= ' WHERE s.fk_product=prod.rowid AND entre.entity IN (' . $entityToTest . ')) as stock_physique'; 800 | 801 | $sql .= ', prod.desiredstock'; 802 | if ($groupByProduct) { 803 | $sql .= ' FROM ' . $db->prefix() . 'product as prod'; 804 | 805 | $sql .= ' LEFT OUTER JOIN ('; 806 | $sql .= ' SELECT fk_product, fk_commande, SUM(qty) as qty, description, MAX(buy_price_ht) as buy_price_ht, MAX(rang) as rang, GROUP_CONCAT(rowid SEPARATOR "@") as rowid'; 807 | $sql .= ' FROM ' . $db->prefix() . 'commandedet'; 808 | $sql .= ' GROUP BY fk_product, fk_commande'; 809 | $sql .= ') as cd ON prod.rowid = cd.fk_product'; 810 | } else { 811 | $sql .= ' FROM ' . $db->prefix() . 'commandedet as cd'; 812 | $sql .= ' INNER JOIN ' . $db->prefix() . 'product as prod ON prod.rowid = cd.fk_product'; 813 | } 814 | 815 | if ((float)DOL_VERSION >= 20.0) { 816 | $sql .= ' LEFT JOIN ' . $db->prefix() . 'expeditiondet as ed ON (cd.rowid = ed.fk_elementdet)'; 817 | } else { 818 | $sql .= ' LEFT JOIN ' . $db->prefix() . 'expeditiondet as ed ON (cd.rowid = ed.fk_origin_line)'; 819 | } 820 | 821 | if (!empty($TCategoriesQuery)) { 822 | $sql .= ' LEFT OUTER JOIN ' . $db->prefix() . 'categorie_product as cp ON (prod.rowid = cp.fk_product)'; 823 | } 824 | 825 | $sql .= ' WHERE prod.fk_product_type IN (0,1) AND prod.entity IN (' . getEntity("product", 1) . ')'; 826 | 827 | if (intval($fk_commande) > 0) { 828 | $sql .= ' AND cd.fk_commande = ' . intval($fk_commande); 829 | } 830 | 831 | if (!empty($TCategoriesQuery)) { 832 | $sql .= ' AND cp.fk_categorie IN ( ' . implode(',', $TCategoriesQuery) . ' ) '; 833 | } 834 | 835 | if ($search_all) { 836 | $sql .= ' AND (prod.ref LIKE "%' . $db->escape($search_all) . '%" '; 837 | $sql .= 'OR prod.label LIKE "%' . $db->escape($search_all) . '%" '; 838 | $sql .= 'OR prod.description LIKE "%' . $db->escape($search_all) . '%" '; 839 | $sql .= 'OR prod.note LIKE "%' . $db->escape($search_all) . '%")'; 840 | } 841 | 842 | if (dol_strlen($type)) { 843 | if ($type == 1) { 844 | $sql .= ' AND prod.fk_product_type = 1'; 845 | } else { 846 | $sql .= ' AND prod.fk_product_type != 1'; 847 | } 848 | } 849 | 850 | if ($sref) { 851 | $scrit = explode(' ', $sref); 852 | foreach ($scrit as $crit) { 853 | $sql .= ' AND prod.ref LIKE "%' . $db->escape($crit) . '%"'; 854 | } 855 | } 856 | 857 | if ($snom) { 858 | $scrit = explode(' ', $snom); 859 | foreach ($scrit as $crit) { 860 | $sql .= ' AND prod.label LIKE "%' . $db->escape($crit) . '%"'; 861 | } 862 | } 863 | 864 | $sql .= ' AND prod.tobuy = 1'; 865 | 866 | if (!empty($canvas)) { 867 | $sql .= ' AND prod.canvas = "' . $db->escape($canvas) . '"'; 868 | } 869 | 870 | if ($salert == 'on') { 871 | $sql .= " AND prod.seuil_stock_alerte is not NULL "; 872 | } 873 | 874 | $sql .= ' GROUP BY prod.rowid, prod.ref, prod.label, prod.price'; 875 | $sql .= ', prod.price_ttc, prod.price_base_type,prod.fk_product_type, prod.tms'; 876 | $sql .= ', prod.duration, prod.tobuy, prod.seuil_stock_alerte'; 877 | 878 | if (!$groupByProduct) { 879 | $sql .= ', cd.description, cd.qty, cd.buy_price_ht'; 880 | $sql .= ', cd.rang, cd.rowid'; 881 | } 882 | 883 | if ($salert == 'on') { 884 | $sql .= ' HAVING stock_physique < prod.seuil_stock_alerte '; 885 | } 886 | 887 | return $sql; 888 | } 889 | --------------------------------------------------------------------------------