* Copyright (C) 2004-2013 Laurent Destailleur * Copyright (C) 2005 Eric Seigne * Copyright (C) 2005-2012 Regis Houssin * Copyright (C) 2006 Andre Cianfarani * Copyright (C) 2011-2014 Juanjo Menent * Copyright (C) 2015 Raphaƫl Doursenaud * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ /** * \file htdocs/product/composition/card.php * \ingroup product * \brief Page de la fiche produit */ require '../../main.inc.php'; require_once DOL_DOCUMENT_ROOT.'/core/lib/product.lib.php'; require_once DOL_DOCUMENT_ROOT.'/product/class/product.class.php'; require_once DOL_DOCUMENT_ROOT.'/categories/class/categorie.class.php'; $langs->load("bills"); $langs->load("products"); $langs->load("stocks"); $id=GETPOST('id','int'); $ref=GETPOST('ref','alpha'); $action=GETPOST('action','alpha'); $confirm=GETPOST('confirm','alpha'); $cancel=GETPOST('cancel','alpha'); $key=GETPOST('key'); $parent=GETPOST('parent'); // Security check if (! empty($user->societe_id)) $socid=$user->societe_id; $fieldvalue = (! empty($id) ? $id : (! empty($ref) ? $ref : '')); $fieldtype = (! empty($ref) ? 'ref' : 'rowid'); $result=restrictedArea($user,'produit|service',$fieldvalue,'product&product','','',$fieldtype); $object = new Product($db); $objectid=0; if ($id > 0 || ! empty($ref)) { $result = $object->fetch($id,$ref); $objectid=$object->id; $id=$object->id; } /* * Actions */ if ($cancel) $action =''; // Action association d'un sousproduit if ($action == 'add_prod' && ($user->rights->produit->creer || $user->rights->service->creer)) { $error=0; for ($i=0; $i<$_POST["max_prod"]; $i++) { if ($_POST["prod_qty_".$i] > 0) { if ($object->add_sousproduit($id, $_POST["prod_id_".$i], $_POST["prod_qty_".$i], $_POST["prod_incdec_".$i]) > 0) { //var_dump($id.' - '.$_POST["prod_id_".$i].' - '.$_POST["prod_qty_".$i]);exit; $action = 'edit'; } else { $error++; $action = 're-edit'; if ($object->error == "isFatherOfThis") { setEventMessage($langs->trans("ErrorAssociationIsFatherOfThis"), 'errors'); } else { setEventMessage($object->error, 'errors'); } } } else { if ($object->del_sousproduit($id, $_POST["prod_id_".$i]) > 0) { $action = 'edit'; } else { $error++; $action = 're-edit'; setEventMessage($object->error, 'errors'); } } } if (! $error) { header("Location: ".$_SERVER["PHP_SELF"].'?id='.$object->id); exit; } } else if($action==='save_composed_product') { $TProduct = GETPOST('TProduct', 'array'); if(!empty($TProduct)) { foreach ($TProduct as $id_product => $row) { if ($row['qty'] > 0) $object->update_sousproduit($id, $id_product, $row['qty'], isset($row['incdec']) ? 1 : 0 ); else $object->del_sousproduit($id, $id_product); } } $action=''; } /* * View */ $product_fourn = new ProductFournisseur($db); $productstatic = new Product($db); $form = new Form($db); // action recherche des produits par mot-cle et/ou par categorie if ($action == 'search') { $current_lang = $langs->getDefaultLang(); $sql = 'SELECT DISTINCT p.rowid, p.ref, p.label, p.barcode, p.price, p.price_ttc, p.price_base_type,'; $sql.= ' p.fk_product_type, p.tms as datem'; if (! empty($conf->global->MAIN_MULTILANGS)) $sql.= ', pl.label as labelm, pl.description as descriptionm'; $sql.= ' FROM '.MAIN_DB_PREFIX.'product as p'; $sql.= ' LEFT JOIN '.MAIN_DB_PREFIX.'categorie_product as cp ON p.rowid = cp.fk_product'; if (! empty($conf->global->MAIN_MULTILANGS)) $sql.= " LEFT JOIN ".MAIN_DB_PREFIX."product_lang as pl ON pl.fk_product = p.rowid AND lang='".($current_lang)."'"; $sql.= ' WHERE p.entity IN ('.getEntity('product', 1).')'; if ($key != "") { // For natural search $params = array('p.ref', 'p.label', 'p.description', 'p.note'); // multilang if (! empty($conf->global->MAIN_MULTILANGS)) { $params[] = 'pl.label'; $params[] = 'pl.description'; $params[] = 'pl.note'; } if (! empty($conf->barcode->enabled)) { $params[] = 'p.barcode'; } $sql .= natural_search($params, $key); } if (! empty($conf->categorie->enabled) && ! empty($parent) && $parent != -1) { $sql.= " AND cp.fk_categorie ='".$db->escape($parent)."'"; } $sql.= " ORDER BY p.ref ASC"; $resql = $db->query($sql); } //print $sql; llxHeader("","",$langs->trans("CardProduct".$object->type)); $head=product_prepare_head($object); $titre=$langs->trans("CardProduct".$object->type); $picto=($object->type==Product::TYPE_SERVICE?'service':'product'); dol_fiche_head($head, 'subproduct', $titre, 0, $picto); if ($id > 0 || ! empty($ref)) { /* * Fiche en mode edition */ if ($user->rights->produit->lire || $user->rights->service->lire) { print ''; print ""; $nblignes=6; if ($object->isproduct() && ! empty($conf->stock->enabled)) $nblignes++; if ($object->isservice()) $nblignes++; // Reference print ''; print ''; // Label print ''; print ''; // Nature if($object->type!=Product::TYPE_SERVICE) { print ''; } if (empty($conf->global->PRODUIT_MULTIPRICES)) { // Price print ''; // Price minimum print ''; } print '
'.$langs->trans("Ref").''; print $form->showrefnav($object,'ref','',1,'ref'); print '
'.$langs->trans("Label").''.$object->label.'
'.$langs->trans("Nature").''; print $object->getLibFinished(); print '
'.$langs->trans("SellingPrice").''; if ($object->price_base_type == 'TTC') { print price($object->price_ttc).' '.$langs->trans($object->price_base_type); } else { print price($object->price).' '.$langs->trans($object->price_base_type?$object->price_base_type:'HT'); } print '
'.$langs->trans("MinPrice").''; if ($object->price_base_type == 'TTC') { print price($object->price_min_ttc).' '.$langs->trans($object->price_base_type); } else { print price($object->price_min).' '.$langs->trans($object->price_base_type?$object->price_base_type:'HT'); } print '
'; dol_fiche_end(); $prodsfather = $object->getFather(); // Parent Products $object->get_sousproduits_arbo(); // Load $object->sousprod $prods_arbo=$object->get_arbo_each_prod(); $nbofsubsubproducts=count($prods_arbo); // This include sub sub product into nb $prodschild = $object->getChildsArbo($id,1); $nbofsubproducts=count($prodschild); // This include only first level of childs // Number of parent virtual products //print $form->textwithpicto($langs->trans("ParentProductsNumber").': '.count($prodsfather), $langs->trans('IfZeroItIsNotUsedByVirtualProduct')); //if (count($prodsfather) > 0) //{ print_fiche_titre($langs->trans("ProductParentList"),'','').'
'; print ''; print ''; print ''; print ''; print ''; print ''; if (count($prodsfather) > 0) { $class='pair'; foreach($prodsfather as $value) { $idprod= $value["id"]; $productstatic->id=$idprod;// $value["id"]; $productstatic->type=$value["fk_product_type"]; $productstatic->ref=$value['ref']; $productstatic->label=$value['label']; $class=($class=='impair')?'pair':'impair'; print ''; print ''; print ''; print ''; print ''; } } else { print ''; print ''; print ''; } print '
'.$langs->trans('ParentProduct').''.$langs->trans('Label').''.$langs->trans('Qty').'
'.$productstatic->getNomUrl(1,'composition').''.$productstatic->label.''.$value['qty'].'
'.$langs->trans("None").'
'; //} print '
'."\n"; // Number of subproducts //print $form->textwithpicto($langs->trans("AssociatedProductsNumber").': '.(empty($conf->global->PRODUCT_SHOW_SUB_SUB_PRODUCTS)?$nbofsubproducts:$nbofsubsubproducts), $langs->trans('IfZeroItIsNotAVirtualProduct')); // List of subproducts //if (count($prods_arbo) > 0) //{ $atleastonenotdefined=0; print_fiche_titre($langs->trans("ProductAssociationList"),'','').'
'; print '
'; print ''; print ''; print ''; print ''; print ''; print ''; print ''; if (! empty($conf->stock->enabled)) print ''; print ''; print ''; print ''."\n"; $class='pair'; if (count($prods_arbo)) { foreach($prods_arbo as $value) { $productstatic->id=$value['id']; $productstatic->type=$value['type']; $productstatic->label=$value['label']; if ($value['level'] <= 1) { $class=($class=='impair')?'pair':'impair'; print ''; $notdefined=0; $productstatic->ref=$value['ref']; $nb_of_subproduct = $value['nb']; print ''; print ''; // Best buying price print ''; $totalline=price2num($value['nb'] * $product_fourn->fourn_unitprice, 'MT'); $total+=$totalline; print ''; // Stock if (! empty($conf->stock->enabled)) print ''; // Real stock // Qty + IncDec if ($user->rights->produit->creer || $user->rights->service->creer) { print ''; print ''; } else{ print ''; print ''; } print ''."\n"; } else // By default, we do not show this. It makes screen very difficult to understand { $hide=''; if (empty($conf->global->PRODUCT_SHOW_SUB_SUB_PRODUCTS)) $hide=' hideobject'; $class=($class=='impair')?'pair':'impair'; print ''; //$productstatic->ref=$value['label']; $productstatic->ref=$value['ref']; print ''; print ''; print ''; print ''; if (! empty($conf->stock->enabled)) print ''; // Real stock print ''; print ''; print ''."\n"; } } print ''; print ''; print ''; // Minimum buying price print ''; print ''; // Stock if (! empty($conf->stock->enabled)) print ''; print ''; print ''."\n"; } else { $colspan=6; if (! empty($conf->stock->enabled)) $colspan++; print ''; print ''; print ''; } print '
'.$langs->trans('ComposedProduct').''.$langs->trans('Label').''.$langs->trans('MinSupplierPrice').''.$langs->trans('Stock').''.$langs->trans('Qty').''.$langs->trans('ComposedProductIncDecStock').'
'.$productstatic->getNomUrl(1,'composition').''.$productstatic->label.''; if ($product_fourn->find_min_price_product_fournisseur($productstatic->id) > 0) { print '   '.$langs->trans("BuyingPriceMinShort").': '; if ($product_fourn->product_fourn_price_id > 0) print $product_fourn->display_price_product_fournisseur(0,0); else { print $langs->trans("NotDefined"); $notdefined++; $atleastonenotdefined++; } } print ''; print ($notdefined?'':($value['nb']> 1 ? $value['nb'].'x' : '').price($product_fourn->fourn_unitprice,'','',0,0,-1,$conf->currency)); print ''.$value['stock'].''.$nb_of_subproduct.''.($value['incdec']==1?'x':'' ).'
'; for ($i=0; $i < $value['level']; $i++) print '     '; // Add indentation print $productstatic->getNomUrl(1,'composition').''.$productstatic->label.'  '.$value['nb'].' 
'; print $langs->trans("TotalBuyingPriceMin"); print ''; if ($atleastonenotdefined) print $langs->trans("Unknown").' ('.$langs->trans("SomeSubProductHaveNoPrices").')'; print ($atleastonenotdefined?'':price($total,'','',0,0,-1,$conf->currency)); print ' '; if ($user->rights->produit->creer || $user->rights->service->creer) { print ''; } print '
'.$langs->trans("None").'
'; /*if($user->rights->produit->creer || $user->rights->service->creer) { print ''; }*/ print '
'; //} // Form with product to add if ((empty($action) || $action == 'view' || $action == 'edit' || $action == 'search' || $action == 're-edit') && ($user->rights->produit->creer || $user->rights->service->creer)) { print '
'; $rowspan=1; if (! empty($conf->categorie->enabled)) $rowspan++; print_fiche_titre($langs->trans("ProductToAddSearch"),'',''); print '
'; print ''; print ''; print ''; if (! empty($conf->categorie->enabled)) { require_once DOL_DOCUMENT_ROOT . '/categories/class/categorie.class.php'; print ''; print ''; } print '
'; print ''; print $langs->trans("KeywordFilter").'   '; print ''; print ''; print ''; print ''; print ''; print '
'.$langs->trans("CategoryFilter").'   '.$form->select_all_categories(Categorie::TYPE_PRODUCT, $parent).'
'; print '
'; } // List of products if ($action == 'search') { print '
'; print '
'; print ''; print ''; print ''; print ''; print ''; print ''; print ''; if ($resql) { $num = $db->num_rows($resql); $i=0; $var=true; if($num == 0) print ''; while ($i < $num) { $objp = $db->fetch_object($resql); if($objp->rowid != $id) { // check if a product is not already a parent product of this one $prod_arbo=new Product($db); $prod_arbo->id=$objp->rowid; if ($prod_arbo->type==Product::TYPE_ASSEMBLYKIT || $prod_arbo->type== Product::TYPE_STOCKKIT) { $is_pere=0; $prod_arbo->get_sousproduits_arbo(); // associations sousproduits $prods_arbo = $prod_arbo->get_arbo_each_prod(); if (count($prods_arbo) > 0) { foreach($prods_arbo as $key => $value) { if ($value[1]==$id) { $is_pere=1; } } } if ($is_pere==1) { $i++; continue; } } $var=!$var; print "\n"; $productstatic->id=$objp->rowid; $productstatic->ref=$objp->ref; $productstatic->label=$objp->label; $productstatic->type=$objp->type; print ''; $labeltoshow=$objp->label; if ($conf->global->MAIN_MULTILANGS && $objp->labelm) $labeltoshow=$objp->labelm; print ''; if($object->is_sousproduit($id, $objp->rowid)) { //$addchecked = ' checked'; $qty=$object->is_sousproduit_qty; $incdec=$object->is_sousproduit_incdec; } else { //$addchecked = ''; $qty=0; $incdec=0; } // Contained into package /*print '';*/ // Qty print ''; // Inc Dec print ''; print ''; } $i++; } } else { dol_print_error($db); } print '
'.$langs->trans("ComposedProduct").''; print ''.$langs->trans("Label").''; //print ''.$langs->trans("IsInPackage").''; print ''.$langs->trans("Qty").''; print ''.$langs->trans('ComposedProductIncDecStock').'
'.$langs->trans("NoMatchFound").'
'.$productstatic->getNomUrl(1,'',24).''.$labeltoshow.''; print ''; if ($qty) print ''; else { // TODO Hide field and show it when setting a qty print ''; //print ''; } print '
'; print ''; if($num > 0) { print '
'; print 'trans("Update").'">'; print '     '; print ''; print '
'; } print '
'; } } } llxFooter(); $db->close();