';
114 | print '';
115 | print '| '.$langs->trans("Parameters").' | '."\n";
116 | print ' | ';
117 | print ''.$langs->trans("Value").' | '."\n";
118 |
119 |
120 | // Add shipment as titles in invoice
121 | $var=!$var;
122 | print '
';
123 | print '| '.$langs->trans("CreateNewSupplierOrderAnyTime");
124 | $htmltooltip = $langs->trans('InfoCreateNewSupplierOrderAnyTime');
125 | print $form->textwithpicto('', $htmltooltip, 1, 0);
126 | print ' | ';
127 | print ' | ';
128 | print '';
129 | print '';
135 | print ' |
';
136 |
137 | $var=!$var;
138 | print '';
139 | print '| '.$form->textwithpicto($langs->trans("SOFO_ENABLE_LINKED_EXTRAFIELDS"), $langs->trans("SOFO_ENABLE_LINKED_EXTRAFIELDS_HELP")).' | ';
140 | print ' | ';
141 | print '';
142 | print '';
148 | 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 '| '.$langs->trans("UseOrderLineDescInSupplierOrder").' | ';
155 | print ' | ';
156 | print '';
157 | print '';
163 | print ' |
';
164 |
165 | // Description of all products on orders
166 | $var=!$var;
167 | print '';
168 | print '| '.$langs->trans("CreateNewSupplierOrderWithProductDesc").' | ';
169 | print ' | ';
170 | print '';
171 | print '';
177 | print ' |
';
178 |
179 | // Create identical supplier order to order
180 | $var=!$var;
181 | print '';
182 | print '| '.$langs->trans("AddFreeLinesInSupplierOrder").' | ';
183 | print ' | ';
184 | print '';
185 | print '';
191 | 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 '| '.$langs->trans("UseCostPriceAsBuyingPrice").' | ';
198 | print ' | ';
199 | print '';
200 | print '';
206 | print ' |
';
207 | }
208 |
209 |
210 | // Create distinct supplier order from order depending of project
211 | $var=!$var;
212 | print '';
213 | print '| '.$langs->trans("CreateDistinctSupplierOrderFromOrderDependingOfProject").' | ';
214 | print ' | ';
215 | print '';
216 | print '';
222 | print ' |
';
223 |
224 | // Import Shipping contact in supplier order
225 | $var=!$var;
226 | print '';
227 | print '| '.$langs->trans("SUPPLIERORDER_FROM_ORDER_CONTACT_DELIVERY").' | ';
228 | print ' | ';
229 | print '';
230 | print '';
236 | print ' |
';
237 |
238 | // Import Notes in supplier order
239 | $var=!$var;
240 | print '';
241 | print '| '.$langs->trans("SUPPLIERORDER_FROM_ORDER_NOTES_PUBLIC").' | ';
242 | print ' | ';
243 | print '';
244 | print '';
250 | print ' |
';
251 |
252 |
253 | // Import Notes in supplier order
254 | $var=!$var;
255 | print '';
256 | print '| '.$langs->trans("SUPPLIERORDER_FROM_ORDER_NOTES_PRIVATE").' | ';
257 | print ' | ';
258 | print '';
259 | print '';
265 | print ' |
';
266 |
267 | // Header to supplier order if only one supplier reported
268 | $var=!$var;
269 | print '';
270 | print '| '.$langs->trans("SUPPLIERORDER_FROM_ORDER_HEADER_SUPPLIER_ORDER").' | ';
271 | print ' | ';
272 | print '';
273 | print '';
279 | print ' |
';
280 |
281 | $var=!$var;
282 | print '';
283 | print '| '.$langs->trans("UseDeliveryTimeToReplenish").' | ';
284 | print ' | ';
285 | print '';
286 | print '';
292 | print ' |
';
293 |
294 | $var=!$var;
295 | print '';
296 | print '| '.$langs->trans("UseVirtualStockOfOrdersSkipDoliConfig").' | ';
297 | print ' | ';
298 | print '';
299 | print '';
305 | print ' |
';
306 |
307 | $var=!$var;
308 | print '';
309 | print '| '.$langs->trans("SOFO_DO_NOT_USE_CUSTOMER_ORDER").' | ';
310 | print ' | ';
311 | print '';
312 | print '';
318 | print ' |
';
319 |
320 | $var=!$var;
321 | print '';
322 | print '| '.$langs->trans("SOFO_DEFAUT_FILTER").' | ';
323 | print ' | ';
324 | print '';
325 | print '';
332 | print ' |
';
333 |
334 | $var=!$var;
335 | print '';
336 | print '| '.$langs->trans("SOFO_GET_INFOS_FROM_FOURN").' | ';
337 | print ' | ';
338 | print '';
339 | print '';
345 | print ' |
';
346 |
347 | $var=!$var;
348 | print '';
349 | print '| '.$langs->trans("SOFO_GET_EXTRAFIELDS_FROM_ORDER").' | ';
350 | print ' | ';
351 | print '';
352 | print '';
358 | print ' |
';
359 |
360 | $var=!$var;
361 | print '';
362 | print '| '.$langs->trans("SOFO_GET_INFOS_FROM_ORDER").' | ';
363 | print ' | ';
364 | print '';
365 | print '';
371 | print ' |
';
372 |
373 | $var=!$var;
374 | print '';
375 | print '| '.$langs->trans("SOFO_USE_MAX_DELIVERY_DATE").' | ';
376 | print ' | ';
377 | print '';
378 | print '';
384 | print ' |
';
385 |
386 | $var=!$var;
387 | print '';
388 | print '| '.$langs->trans("SOFO_DISPLAY_SERVICES").' | ';
389 | print ' | ';
390 | print '';
391 | print '';
397 | print ' |
';
398 |
399 |
400 | $var=!$var;
401 | print '';
402 | print '| '.$langs->trans("INCLUDE_PRODUCT_LINES_WITH_ADEQUATE_STOCK").' | ';
403 | print ' | ';
404 | print '';
405 | print '';
411 | print ' |
';
412 |
413 |
414 | $var=!$var;
415 | print '';
416 | print '| '.$langs->trans('SOFO_PRESELECT_SUPPLIER_PRICE_FROM_LINE_BUY_PRICE').' | ';
417 | print ' | ';
418 | print '';
419 | print '';
425 | print ' |
';
426 |
427 |
428 | $var=!$var;
429 | print '';
430 | 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 ' | ';
434 | print ' | ';
435 | print '';
436 | print '';
442 | print ' |
';
443 |
444 |
445 | $var=!$var;
446 | print '';
447 | print '| '.$langs->trans('SOFO_GROUP_LINES_BY_PRODUCT').' | ';
448 | print ' | ';
449 | print '';
450 | print '';
456 | print ' |
';
457 |
458 | $var=!$var;
459 | print '';
460 | print '| '.$langs->trans('SOFO_GET_REF_SUPPLIER_FROM_ORDER').' | ';
461 | print ' | ';
462 | print '';
463 | print '';
469 | print ' |
';
470 |
471 | if(getDolGlobalString('PRODUIT_SOUSPRODUITS')) {
472 | $var = !$var;
473 | print '';
474 | print '| ' . $langs->trans('SOFO_VIRTUAL_PRODUCTS') . ' | ';
475 | print ' | ';
476 | print '';
477 | print '';
483 | print ' |
';
484 | }
485 |
486 | if (isModEnabled('multicompany') && getDolGlobalString('MULTICOMPANY_STOCK_SHARING_ENABLED')) {
487 | $var = !$var;
488 | print '';
489 | print '| ' . $langs->trans('SOFO_CHECK_STOCK_ON_SHARED_STOCK') . ' | ';
490 | print ' | ';
491 | print '';
492 | print '';
498 | print ' |
';
499 | }
500 |
501 | if(isModEnabled('categorie')) {
502 | $var=!$var;
503 | print '';
504 | print '| '.$langs->trans("SOFO_DEFAULT_PRODUCT_CATEGORY_FILTER").' | ';
505 | print ' | ';
506 | print '';
507 | print '';
514 | ?>
515 |
523 | |
';
525 | }
526 |
527 | print '
';
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 |
--------------------------------------------------------------------------------