/** * Get properties of a product object * * Return an array with product informations * * @param int $id ID of product * @param string $ref Product ref * @param string $ref_ext Product ref ext * @return array|mixed data without useless information * * @url GET product/{id} * @throws RestException */ function get($id = '', $ref = '', $ref_ext = '') { if (!DolibarrApiAccess::$user->rights->produit->lire) { throw new RestException(401); } $result = $this->product->fetch($id, $ref, $ref_ext); if (!$result) { throw new RestException(404, 'Product not found'); } if (!DolibarrApi::_checkAccessToResource('product', $this->product->id)) { throw new RestException(401, 'Access not allowed for login ' . DolibarrApiAccess::$user->login); } $this->product->load_stock(); return $this->_cleanObjectDatas($this->product); }
function isLineShippable(&$line, &$TSomme) { global $conf, $user; $db =& $this->db; $TSomme[$line->fk_product] += $line->qty_toship; if (!isset($line->stock) && $line->fk_product > 0) { if (empty($this->TProduct[$line->fk_product])) { $produit = new Product($db); $produit->fetch($line->fk_product); $produit->load_stock(false); $this->TProduct[$line->fk_product] = $produit; } else { $produit =& $this->TProduct[$line->fk_product]; } $line->stock = $produit->stock_reel; // Filtre par entrepot de l'utilisateur if (!empty($conf->global->SHIPPABLEORDER_ENTREPOT_BY_USER) && !empty($user->array_options['options_entrepot_preferentiel'])) { $line->stock = $produit->stock_warehouse[$user->array_options['options_entrepot_preferentiel']]->real; } elseif (!empty($conf->global->SHIPPABLEORDER_SPECIFIC_WAREHOUSE)) { $line->stock = 0; //Récupération des entrepôts valide $TIdWarehouse = explode(',', $conf->global->SHIPPABLEORDER_SPECIFIC_WAREHOUSE); foreach ($produit->stock_warehouse as $identrepot => $objecttemp) { if (in_array($identrepot, $TIdWarehouse)) { $line->stock += $objecttemp->real; } } } } if ($conf->global->SHIPPABLE_ORDER_ALLOW_SHIPPING_IF_NOT_ENOUGH_STOCK) { $isShippable = 1; $qtyShippable = $line->qty; $line->stock = $line->qty; } else { if ($line->stock <= 0 || $line->qty_toship <= 0) { $isShippable = 0; $qtyShippable = 0; } else { if ($TSomme[$line->fk_product] <= $line->stock) { $isShippable = 1; $qtyShippable = $line->qty_toship; } else { $isShippable = 2; $qtyShippable = $line->qty_toship - $TSomme[$line->fk_product] + $line->stock; } } } $this->TlinesShippable[$line->id] = array('stock' => $line->stock, 'shippable' => $isShippable, 'to_ship' => $line->qty_toship, 'qty_shippable' => $qtyShippable); return $isShippable; }
} } else { setEventMessages($pdluo->error, null, 'errors'); } header("Location: product.php?id=" . $id); exit; } /* * View */ $form = new Form($db); $formproduct = new FormProduct($db); if ($id > 0 || $ref) { $object = new Product($db); $result = $object->fetch($id, $ref); $object->load_stock(); $help_url = 'EN:Module_Stocks_En|FR:Module_Stock|ES:Módulo_Stocks'; llxHeader("", $langs->trans("CardProduct" . $object->type), $help_url); if ($result > 0) { $head = product_prepare_head($object); $titre = $langs->trans("CardProduct" . $object->type); $picto = $object->type == Product::TYPE_SERVICE ? 'service' : 'product'; dol_fiche_head($head, 'stock', $titre, 0, $picto); dol_htmloutput_events(); dol_banner_tab($object, 'ref', '', $user->societe_id ? 0 : 1, 'ref'); print '<div class="fichecenter">'; print '<div class="underbanner clearboth"></div>'; print '<table class="border tableforfield" width="100%">'; if ($conf->productbatch->enabled) { print '<tr><td class="titlefield">' . $langs->trans("ManageLotSerial") . '</td><td>'; print $object->getLibStatut(0, 2);
print '<table class="nobordernopadding"><tr class="nocellnopadd">'; print '<td class="nobordernopadding nowrap">'; print $generic_commande->getNomUrl(1, $viewstatut != 2 ? 0 : $objp->fk_statut); print '</td>'; // Shippable Icon if ($objp->fk_statut > 0 && $objp->fk_statut < 3 && !empty($conf->global->SHIPPABLE_ORDER_ICON_IN_LIST)) { $notshippable = 0; $text_info = ''; $nbprod = 0; for ($lig = 0; $lig < count($generic_commande->lines); $lig++) { if ($generic_commande->lines[$lig]->product_type == 0) { $nbprod++; // order contains real products $generic_product->id = $generic_commande->lines[$lig]->fk_product; if (empty($productstat_cache[$generic_commande->lines[$lig]->fk_product])) { $generic_product->load_stock(true); $productstat_cache[$generic_commande->lines[$lig]->fk_product]['stock_reel'] = $generic_product->stock_reel; } else { $generic_product->stock_reel = $productstat_cache[$generic_commande->lines[$lig]->fk_product]['stock_reel']; } // stock order and stock order_supplier $stock_order = 0; $stock_order_supplier = 0; if (!empty($conf->global->STOCK_CALCULATE_ON_SHIPMENT)) { if (!empty($conf->commande->enabled)) { if (empty($productstat_cache[$generic_commande->lines[$lig]->fk_product]['stats_order_customer'])) { $generic_product->load_stats_commande(0, '1,2'); $productstat_cache[$generic_commande->lines[$lig]->fk_product]['stats_order_customer'] = $generic_product->stats_commande['qty']; } else { $generic_product->stats_commande['qty'] = $productstat_cache[$generic_commande->lines[$lig]->fk_product]['stats_order_customer']; }
dol_fiche_end(); // List of subproducts $prods_arbo = $product->get_arbo_each_prod(); if (count($prods_arbo) > 0) { print '<tr><td colspan="2">'; print '<b>'.$langs->trans("ProductAssociationList").'</b><br>'; print '<table class="nobordernopadding">'; foreach($prods_arbo as $value) { $productstatic->id=$value['id']; $productstatic->type=$value['type']; $productstatic->ref=$value['fullpath']; if ($conf->stock->enabled) $productstatic->load_stock(); //var_dump($value); //print '<pre>'.$productstatic->ref.'</pre>'; //print $productstatic->getNomUrl(1).'<br>'; //print $value[0]; // This contains a tr line. print '<tr>'; print '<td>'.$productstatic->getNomUrl(1,'composition').' ('.$value['nb'].')    </td>'; if ($conf->stock->enabled) print '<td>'.$langs->trans("Stock").' : <b>'.$productstatic->stock_reel.'</b></td>'; print '</tr>'; } print '</table>'; print '</td></tr>'; } // Number of parent products print '<tr><td>'.$langs->trans("ParentProductsNumber").'</td><td>'.count($prodsfather).'</td>';
print_liste_field_titre($langs->trans('Supplier'), $_SERVER["PHP_SELF"], '', $param, '', 'align="right"', $sortfield, $sortorder); print "</tr>\n"; // Lignes des champs de filtre print '<tr class="liste_titre">' . '<td class="liste_titre"> </td>' . '<td class="liste_titre"><input class="flat" type="text" name="sref" size="8" value="' . dol_escape_htmltag($sref) . '"></td>' . '<td class="liste_titre"><input class="flat" type="text" name="snom" size="8" value="' . dol_escape_htmltag($snom) . '"></td>'; if (!empty($conf->service->enabled) && $type == 1) { print '<td class="liste_titre"> </td>'; } print '<td class="liste_titre"> </td>' . '<td class="liste_titre" align="right"> </td>' . '<td class="liste_titre" align="right">' . $langs->trans('AlertOnly') . ' <input type="checkbox" id="salert" name="salert" ' . (!empty($alertchecked) ? $alertchecked : '') . '></td>' . '<td class="liste_titre" align="right"> </td>' . '<td class="liste_titre"> </td>' . '<td class="liste_titre" align="right">' . '<input class="liste_titre" name="button_search" type="image" src="' . img_picto($langs->trans("Search"), 'search.png', '', '', 1) . '" value="' . dol_escape_htmltag($langs->trans("Search")) . '" title="' . dol_escape_htmltag($langs->trans("Search")) . '">' . '<input type="image" class="liste_titre" src="' . img_picto($langs->trans("Search"), 'searchclear.png', '', '', 1) . '" name="button_removefilter" value="' . dol_escape_htmltag($langs->trans("RemoveFilter")) . '" title="' . dol_escape_htmltag($langs->trans("RemoveFilter")) . '">' . '</td>'; print '</tr>'; $prod = new Product($db); $var = True; while ($i < ($limit ? min($num, $limit) : $num)) { $objp = $db->fetch_object($resql); if (!empty($conf->global->STOCK_SUPPORTS_SERVICES) || $objp->fk_product_type == 0) { $prod->fetch($objp->rowid); $prod->load_stock(); // Multilangs if (!empty($conf->global->MAIN_MULTILANGS)) { $sql = 'SELECT label'; $sql .= ' FROM ' . MAIN_DB_PREFIX . 'product_lang'; $sql .= ' WHERE fk_product = ' . $objp->rowid; $sql .= ' AND lang = "' . $langs->getDefaultLang() . '"'; $sql .= ' LIMIT 1'; $resqlm = $db->query($sql); if ($resqlm) { $objtp = $db->fetch_object($resqlm); if (!empty($objtp->label)) { $objp->label = $objtp->label; } } }
/** * Function called when a Dolibarrr business event is done. * All functions "run_trigger" are triggered if file * is inside directory core/triggers * * @param string $action Event action code * @param Object $object Object * @param User $user Object user * @param Translate $langs Object langs * @param conf $conf Object conf * @return int <0 if KO, 0 if no triggered ran, >0 if OK */ public function run_trigger($action, $object, $user, $langs, $conf) { if ($action === 'ORDER_VALIDATE') { global $conf, $db; if ($conf->global->CREATE_OF_ON_ORDER_VALIDATE) { define('INC_FROM_DOLIBARR', true); dol_include_once('/product/class/product.class.php'); dol_include_once('/of/config.php'); dol_include_once('/of/class/ordre_fabrication_asset.class.php'); $PDOdb = new TPDOdb(); foreach ($object->lines as $line) { // Uniquement si c'est un produit if (!empty($line->fk_product) && $line->fk_product_type == 0) { // On charge le produit pour vérifier son stock $prod = new Product($db); $prod->fetch($line->fk_product); $prod->load_stock(); if ($prod->stock_reel < $line->qty) { $assetOF = new TAssetOF(); $assetOF->fk_commande = $_REQUEST['id']; $assetOF->fk_soc = $object->socid; $assetOF->addLine($PDOdb, $line->fk_product, 'TO_MAKE', $line->qty); $assetOF->save($PDOdb); } } } } } elseif ($action === 'ORDER_CANCEL') { if ($conf->global->DELETE_OF_ON_ORDER_CANCEL) { define('INC_FROM_DOLIBARR', true); dol_include_once('/of/config.php'); dol_include_once('/of/class/ordre_fabrication_asset.class.php'); $PDOdb = new TPDOdb(); // On récupère les identifiants des of créés à partir de cette commande $TID_OF_command = TAssetOF::getTID_OF_command($_REQUEST['id']); foreach ($TID_OF_command as $id_of) { $asset = new TAssetOF(); $asset->load($PDOdb, $id_of); if ($asset->status == "DRAFT" || $asset->status == "VALID") { $asset->delete($PDOdb); } } } } elseif ($action === 'TASK_TIMESPENT_CREATE') { if ($conf->workstation->enabled) { define('INC_FROM_DOLIBARR', true); dol_include_once('/of/config.php'); dol_include_once('/of/class/ordre_fabrication_asset.class.php'); $PDOdb = new TPDOdb(); $PDOdb->Execute("SELECT rowid \n\t\t\t\t\t\tFROM " . MAIN_DB_PREFIX . "asset_workstation_of \n\t\t\t\t\t\tWHERE fk_project_task=" . $object->id); if ($obj = $PDOdb->Get_line()) { $wsof = new TAssetWorkstationOF(); $wsof->load($PDOdb, $obj->rowid); $wsof->nb_hour_real = ($object->duration_effective + $object->timespent_duration) / 3600; // Parce que Dolibarr mets le THM à jour après la création de la tâche :/ $sql = "UPDATE " . MAIN_DB_PREFIX . "projet_task_time"; $sql .= " SET thm = (SELECT thm FROM " . MAIN_DB_PREFIX . "user WHERE rowid = " . $object->timespent_fk_user . ")"; // set average hour rate of user $sql .= " WHERE rowid = " . $object->timespent_id; $object->db->query($sql); $wsof->db =& $object->db; $wsof->save($PDOdb); } } } elseif ($action === 'ORDERSUPPLIER_ADD_LIVRAISON') { global $db; if ($conf->of->enabled) { define('INC_FROM_DOLIBARR', true); dol_include_once('/of/config.php'); dol_include_once('/of/class/ordre_fabrication_asset.class.php'); $resql = $db->query('SELECT fk_statut FROM llx_commande_fournisseur WHERE rowid = ' . $_REQUEST['id']); $res = $db->fetch_object($resql); if ($res->fk_statut == 5) { // La livraison est totale //On cherche l'OF lié $resql = $db->query("SELECT fk_source \n\t\t\t\t\t\t\t\t\t\t\tFROM " . MAIN_DB_PREFIX . "element_element \n\t\t\t\t\t\t\t\t\t\t\tWHERE fk_target = " . $_REQUEST['id'] . " \n\t\t\t\t\t\t\t\t\t\t\t\tAND sourcetype = 'ordre_fabrication' \n\t\t\t\t\t\t\t\t\t\t\t\tAND targettype = 'order_supplier'"); $res = $db->fetch_object($resql); $id_of = $res->fk_source; if ($id_of > 0) { $of = new TAssetOF(); $of->load($PDOdb, $id_of); if ($of->status != 'CLOSE') { $of->closeOF($PDOdb); setEventMessage($langs->trans('OFAttachedClosedAutomatically', '<a href="' . dol_buildpath('/of/fiche_of.php?id=' . $id_of, 2) . '">' . $of->numero . '</a>')); } } } } } return 0; }
if ($product_fourn->product_fourn_price_id > 0) { if (!empty($conf->fournisseur->enabled) && $user->rights->fournisseur->lire) { $htmltext = $product_fourn->display_price_product_fournisseur(1, 1, 0, 1); print $form->textwithpicto(price($product_fourn->fourn_unitprice) . ' ' . $langs->trans("HT"), $htmltext); } else { print price($product_fourn->fourn_unitprice) . ' ' . $langs->trans("HT"); } } } } print '</td>'; } if (!empty($conf->stock->enabled) && $user->rights->stock->lire && $type != 1) { if ($objp->fk_product_type != 1) { $product_static->id = $objp->rowid; $product_static->load_stock(); } } // Desired stock if (!empty($arrayfields['p.desiredstock']['checked'])) { print '<td align="right">'; if ($objp->fk_product_type != 1) { print $objp->desiredstock; } print '</td>'; } // Desired stock if (!empty($arrayfields['p.tobatch']['checked'])) { print '<td align="center">'; print yn($objp->tobatch); print '</td>';
/** * Add a expedition line. * If STOCK_WAREHOUSE_NOT_REQUIRED_FOR_SHIPMENTS is set, you can add a shipment line, with no stock source defined * If STOCK_MUST_BE_ENOUGH_FOR_SHIPMENT is not set, you can add a shipment line, even if not enough into stock * * @param int $entrepot_id Id of warehouse * @param int $id Id of source line (order line) * @param int $qty Quantity * @param array $array_options extrafields array * @return int <0 if KO, >0 if OK */ function addline($entrepot_id, $id, $qty, $array_options = 0) { global $conf, $langs; $num = count($this->lines); $line = new ExpeditionLigne($this->db); $line->entrepot_id = $entrepot_id; $line->origin_line_id = $id; $line->qty = $qty; $orderline = new OrderLine($this->db); $orderline->fetch($id); if (!empty($conf->stock->enabled) && !empty($orderline->fk_product)) { $fk_product = $orderline->fk_product; if (!($entrepot_id > 0) && empty($conf->global->STOCK_WAREHOUSE_NOT_REQUIRED_FOR_SHIPMENTS)) { $langs->load("errors"); $this->error = $langs->trans("ErrorWarehouseRequiredIntoShipmentLine"); return -1; } if ($conf->global->STOCK_MUST_BE_ENOUGH_FOR_SHIPMENT) { // Check must be done for stock of product into warehouse if $entrepot_id defined $product = new Product($this->db); $result = $product->fetch($fk_product); $product_type = $product->type; if ($entrepot_id > 0) { $product->load_stock(); $product_stock = $product->stock_warehouse[$entrepot_id]->real; } else { $product_stock = $product->stock_reel; } if ($product_type == 0 && $product_stock < $qty) { $this->error = $langs->trans('ErrorStockIsNotEnough'); $this->db->rollback(); return -3; } } } // extrafields if (empty($conf->global->MAIN_EXTRAFIELDS_DISABLED) && is_array($array_options) && count($array_options) > 0) { // For avoid conflicts if trigger used $line->array_options = $array_options; } $this->lines[$num] = $line; }
/** * Add a movement of stock (in one direction only) * * @param User $user User object * @param int $fk_product Id of product * @param int $entrepot_id Id of warehouse * @param int $qty Qty of movement (can be <0 or >0) * @param int $type Direction of movement: * 0=input (stock increase after stock transfert), 1=output (stock decrease after stock transfer), * 2=output (stock decrease), 3=input (stock increase) * @param int $price Unit price HT of product, used to calculate average weighted price (PMP in french). If 0, average weighted price is not changed. * @param string $label Label of stock movement * @param string $datem Force date of movement * @param date $eatby eat-by date * @param date $sellby sell-by date * @param string $batch batch number * @param boolean $skip_sellby If set to true, stock mouvement is done without impacting batch record * @return int <0 if KO, 0 if fk_product is null, >0 if OK */ function _create($user, $fk_product, $entrepot_id, $qty, $type, $price = 0, $label = '', $datem = '', $eatby = '', $sellby = '', $batch = '', $skip_sellby = false) { global $conf, $langs; require_once DOL_DOCUMENT_ROOT . '/product/class/product.class.php'; $error = 0; dol_syslog(get_class($this) . "::_create start userid={$user->id}, fk_product={$fk_product}, warehouse={$entrepot_id}, qty={$qty}, type={$type}, price={$price} label={$label}"); // Clean parameters if (empty($price)) { $price = 0; } if (empty($fk_product)) { return 0; } $now = !empty($datem) ? $datem : dol_now(); $this->db->begin(); $product = new Product($this->db); $result = $product->fetch_opt($fk_product); if ($result < 0) { dol_print_error('', "Failed to fetch product"); return -1; } $product->load_stock(); // Define if we must make the stock change (If product type is a service or if stock is used also for services) $movestock = 0; if ($product->type != 1 || !empty($conf->global->STOCK_SUPPORTS_SERVICES)) { $movestock = 1; } if ($movestock && $entrepot_id > 0) { if (!empty($this->origin)) { $origintype = $this->origin->element; $fk_origin = $this->origin->id; } else { $origintype = ''; $fk_origin = 0; } $sql = "INSERT INTO " . MAIN_DB_PREFIX . "stock_mouvement"; $sql .= " (datem, fk_product, fk_entrepot, value, type_mouvement, fk_user_author, label, price, fk_origin, origintype)"; $sql .= " VALUES ('" . $this->db->idate($now) . "', " . $fk_product . ", " . $entrepot_id . ", " . $qty . ", " . $type . ","; $sql .= " " . $user->id . ","; $sql .= " '" . $this->db->escape($label) . "',"; $sql .= " '" . price2num($price) . "',"; $sql .= " '" . $fk_origin . "',"; $sql .= " '" . $origintype . "'"; $sql .= ")"; dol_syslog(get_class($this) . "::_create sql=" . $sql, LOG_DEBUG); $resql = $this->db->query($sql); if ($resql) { $mvid = $this->db->last_insert_id(MAIN_DB_PREFIX . "stock_mouvement"); } else { $this->error = $this->db->lasterror(); dol_syslog(get_class($this) . "::_create " . $this->error, LOG_ERR); $error = -1; } // Define current values for qty and pmp $oldqty = $product->stock_reel; $oldqtywarehouse = 0; $oldpmp = $product->pmp; $oldpmpwarehouse = 0; // Test if there is already a record for couple (warehouse / product) $num = 0; if (!$error) { $sql = "SELECT rowid, reel, pmp FROM " . MAIN_DB_PREFIX . "product_stock"; $sql .= " WHERE fk_entrepot = " . $entrepot_id . " AND fk_product = " . $fk_product; dol_syslog(get_class($this) . "::_create sql=" . $sql); $resql = $this->db->query($sql); if ($resql) { $obj = $this->db->fetch_object($resql); if ($obj) { $num = 1; $oldqtywarehouse = $obj->reel; $oldpmpwarehouse = $obj->pmp; $fk_product_stock = $obj->rowid; } $this->db->free($resql); } else { $this->error = $this->db->lasterror(); dol_syslog(get_class($this) . "::_create echec update " . $this->error, LOG_ERR); $error = -2; } } // Calculate new PMP. if (!$error) { $newpmp = 0; $newpmpwarehouse = 0; // Note: PMP is calculated on stock input only (type = 0 or 3). If type == 0 or 3, qty should be > 0. // Note: Price should always be >0 or 0. PMP should be always >0 (calculated on input) if (($type == 0 || $type == 3) && $price > 0) { $oldqtytouse = $oldqty >= 0 ? $oldqty : 0; // We make a test on oldpmp>0 to avoid to use normal rule on old data with no pmp field defined if ($oldpmp > 0) { $newpmp = price2num(($oldqtytouse * $oldpmp + $qty * $price) / ($oldqtytouse + $qty), 'MU'); } else { $newpmp = $price; } $oldqtywarehousetouse = $oldqtywarehouse >= 0 ? $oldqtywarehouse : 0; if ($oldpmpwarehouse > 0) { $newpmpwarehouse = price2num(($oldqtywarehousetouse * $oldpmpwarehouse + $qty * $price) / ($oldqtywarehousetouse + $qty), 'MU'); } else { $newpmpwarehouse = $price; } //print "oldqtytouse=".$oldqtytouse." oldpmp=".$oldpmp." oldqtywarehousetouse=".$oldqtywarehousetouse." oldpmpwarehouse=".$oldpmpwarehouse." "; //print "qty=".$qty." newpmp=".$newpmp." newpmpwarehouse=".$newpmpwarehouse; //exit; } else { $newpmp = $oldpmp; $newpmpwarehouse = $oldpmpwarehouse; } } // Update denormalized value of stock in product_stock and product if (!$error) { if ($num > 0) { $sql = "UPDATE " . MAIN_DB_PREFIX . "product_stock SET pmp = " . $newpmpwarehouse . ", reel = reel + " . $qty; $sql .= " WHERE fk_entrepot = " . $entrepot_id . " AND fk_product = " . $fk_product; } else { $sql = "INSERT INTO " . MAIN_DB_PREFIX . "product_stock"; $sql .= " (pmp, reel, fk_entrepot, fk_product) VALUES "; $sql .= " (" . $newpmpwarehouse . ", " . $qty . ", " . $entrepot_id . ", " . $fk_product . ")"; } dol_syslog(get_class($this) . "::_create sql=" . $sql); $resql = $this->db->query($sql); if (!$resql) { $this->error = $this->db->lasterror(); dol_syslog(get_class($this) . "::_create " . $this->error, LOG_ERR); $error = -3; } else { if (empty($fk_product_stock)) { $fk_product_stock = $this->db->last_insert_id(MAIN_DB_PREFIX . "product_stock"); } } } // Update detail stock for sell-by date if ($product->hasbatch() && !$error && !$skip_sellby) { $param_batch = array('fk_product_stock' => $fk_product_stock, 'eatby' => $eatby, 'sellby' => $sellby, 'batchnumber' => $batch); $result = $this->_create_batch($param_batch, $qty); if ($result < 0) { $error++; } } if (!$error) { $sql = "UPDATE " . MAIN_DB_PREFIX . "product SET pmp = " . $newpmp . ", stock = " . $this->db->ifsql("stock IS NULL", 0, "stock") . " + " . $qty; $sql .= " WHERE rowid = " . $fk_product; // May be this request is better: // UPDATE llx_product p SET p.stock= (SELECT SUM(ps.reel) FROM llx_product_stock ps WHERE ps.fk_product = p.rowid); dol_syslog(get_class($this) . "::_create sql=" . $sql); $resql = $this->db->query($sql); if (!$resql) { $this->error = $this->db->lasterror(); dol_syslog(get_class($this) . "::_create " . $this->error, LOG_ERR); $error = -4; } } } // Add movement for sub products (recursive call) if (!$error && !empty($conf->global->PRODUIT_SOUSPRODUITS)) { $error = $this->_createSubProduct($user, $fk_product, $entrepot_id, $qty, $type, 0, $label); // we use 0 as price, because pmp is not changed for subproduct } if ($movestock && !$error) { // Appel des triggers include_once DOL_DOCUMENT_ROOT . '/core/class/interfaces.class.php'; $interface = new Interfaces($this->db); $this->product_id = $fk_product; $this->entrepot_id = $entrepot_id; $this->qty = $qty; $result = $interface->run_triggers('STOCK_MOVEMENT', $this, $user, $langs, $conf); if ($result < 0) { $error++; $this->errors = $interface->errors; } // Fin appel triggers } if (!$error) { $this->db->commit(); return $mvid; } else { $this->db->rollback(); dol_syslog(get_class($this) . "::_create error code=" . $error, LOG_ERR); return -6; } }
/** * Create object into database * @param User $user User that create * @param Array $toPrint Array with products to print * @return int <0 if KO, Id of created object if OK */ function multicreate($user, $toPrint) { global $conf, $langs; $error = 0; require_once DOL_DOCUMENT_ROOT . "/product/class/product.class.php"; $product = new Product($this->db); foreach ($toPrint as $prodid) { $result = $product->fetch($prodid); if ($result) { if ($conf->stock->enabled) { $product->load_stock(); $qty = $product->stock_reel; } } $res = $this->fetch($this->id, $product->id); if ($res == 1) { $qty = $this->qty + $qty; $this->qty = $qty; $res = $this->update($user, $notrigger); if ($res != 1) { $error++; $this->errors[] = "Error " . $this->db->lasterror(); } } else { // Insert request $sql = "INSERT INTO " . MAIN_DB_PREFIX . "labelprint("; $sql .= "entity,"; $sql .= "fk_product,"; $sql .= "qty,"; $sql .= "fk_user,"; $sql .= "datec,"; $sql .= "price_level"; $sql .= ") VALUES ("; $sql .= " " . $conf->entity . ","; $sql .= " " . $product->id . ","; $sql .= " " . $qty . ","; $sql .= " " . $user->id . ","; $sql .= " " . (!isset($this->datec) || dol_strlen($this->datec) == 0 ? 'NULL' : $this->db->idate($this->datec)) . ","; $sql .= " " . (!isset($this->price_level) ? 1 : $this->price_level) . ""; $sql .= ")"; //$this->db->begin(); dol_syslog(get_class($this) . "::create sql=" . $sql, LOG_DEBUG); $resql = $this->db->query($sql); if (!$resql) { $error++; $this->errors[] = "Error " . $this->db->lasterror(); } } } if (!$error) { $this->id = $this->db->last_insert_id(MAIN_DB_PREFIX . "labelprint"); } // Commit or rollback if ($error) { foreach ($this->errors as $errmsg) { dol_syslog(get_class($this) . "::multicreate " . $errmsg, LOG_ERR); $this->error .= $this->error ? ', ' . $errmsg : $errmsg; } //$this->db->rollback(); return -1 * $error; } else { //$this->db->commit(); return $this->id; } }
function import2Dolibarr($object, $typeimport) { global $conf; global $langs; $this->process_msg = ''; $error = 0; $fp = @fopen($this->filename, "r"); if ($fp) { switch ($object) { case 'ImportStock': $doliprod = new Product($this->db); $i = 0; while ($ligne = fgetcsv($fp, 1000, ";")) { $doliprod->id = ''; $i++; if ($this->firstline && $i == 1) { continue; } if ($conf->global->IMPORT_BARCODE) { $ligne[0] = $this->get_product_by_barcode($ligne[0]); } if ($doliprod->fetch('', $ligne[0]) <= 0) { $this->process_msg .= $langs->trans("ErrProdNoExist", $ligne[0], $doliprod->error) . "\n"; } else { $pid = $doliprod->id; $doliprod->ref = $ligne[0]; $entrepot = $ligne[1]; $newstock = $ligne[2]; $price = $ligne[3]; if ($conf->global->IMPORT_TOTAL_STOCK) { $doliprod->load_stock(); dol_syslog("stock produit " . $doliprod->stock_warehouse[$entrepot]->real . " entrepot " . $entrepot . " " . $doliprod->stock_reel, LOG_DEBUG); // correction de stock $delta = 0; if ($newstock > $doliprod->stock_warehouse[$entrepot]->real) { $delta = $newstock - $doliprod->stock_warehouse[$entrepot]->real; $sens = 0; } elseif ($newstock < $doliprod->stock_warehouse[$entrepot]->real) { $delta = $doliprod->stock_warehouse[$entrepot]->real - $newstock; $sens = 1; } if ($delta) { $res = $doliprod->correct_stock($this->user, $entrepot, $delta, $sens, $langs->trans("StockCorrection"), $price); if ($res < 0) { $this->process_msg .= $langs->trans("ErrMovStock", $ligne[0], $doliprod->error) . "\n"; $error++; } } dol_syslog("maj stock delta = " . $delta . " sens " . $sens, LOG_DEBUG); } else { $res = $doliprod->correct_stock($this->user, $entrepot, abs($newstock), $newstock > 0 ? 0 : 1, $langs->trans("StockCorrection"), $price); if ($res < 0) { $this->process_msg .= $langs->trans("ErrMovStock", $ligne[0], $doliprod->error) . "\n"; $error++; } } } } break; case 'ImportProduct': //$doliprod = new Product($this->db); $i = 0; while ($ligne = fgetcsv($fp, 1000, ";")) { $i++; $doliprod = new Product($this->db); $doliprod->id = ''; if ($this->firstline && $i == 1) { continue; } if ($doliprod->fetch('', $ligne[0]) < 0) { $this->process_msg .= $langs->trans("ErrProdNoExist", $ligne[0], $doliprod->error) . "\n"; } else { $pid = $doliprod->id; $doliprod->ref = $ligne[0]; if (!empty($ligne[1])) { $doliprod->libelle = $ligne[1]; } if (!empty($ligne[2])) { $doliprod->status = $ligne[2]; } $doliprod->status_buy = 1; if (!empty($ligne[3])) { $doliprod->description = $ligne[3]; } if (!empty($ligne[4])) { $doliprod->price = $ligne[4]; } if (!empty($ligne[5])) { $doliprod->tva_tx = $ligne[5]; } if (!empty($ligne[6])) { $doliprod->weight = $ligne[6]; } if (!empty($ligne[7])) { $doliprod->volume = $ligne[7]; } if (!empty($ligne[9])) { $doliprod->barcode = $ligne[9]; } if (!empty($ligne[9])) { $doliprod->barcode_type = dol_getIdFromCode($this->db, $ligne[10], 'c_barcode_type', 'libelle', 'rowid'); } if (!empty($ligne[10])) { $doliprod->type = $ligne[11]; } $doliprod->price_base_type = 'HT'; $this->db->begin; switch ($typeimport) { case 'C': if ($pid > 0) { if ($doliprod->update($pid, $this->user) < 0) { $this->process_msg .= $langs->trans("ErrProductUpdate", $ligne[0], $doliprod->error) . "\n"; $error++; } if ($doliprod->updatePrice($doliprod->price, $doliprod->price_base_type, $this->user) < 0) { $this->process_msg .= $langs->trans("ErrProductUpdate", $ligne[0], $doliprod->error) . "\n"; $error++; } } else { if ($doliprod->create($this->user) < 0) { $this->process_msg .= $langs->trans("ErrProductCreate", $ligne[0], $doliprod->error) . "\n"; $error++; } else { // image et code barre if ($ligne[8]) { $this->add_photo_web($conf->produit->dir_output, $ligne[8], $doliprod->id); } /*if ($ligne[9]) { if ($doliprod->setValueFrom('fk_barcode_type', 2) < 0){ $this->process_msg .= $langs->trans("ErrProductCreate", $ligne[0], $doliprod->error)."\n"; // TODO paramétrer $error++; } if ($doliprod->setValueFrom('barcode', $ligne[9]) < 0 ){ $this->process_msg .= $langs->trans("ErrProductCreate", $ligne[0], $doliprod->error)."\n"; $error++; } }*/ } } break; /*case 'M': if ($pid>0) { if ($doliprod->update($pid, $this->user) < 0){ $this->process_msg .= $langs->trans("ErrProductUpdate", $ligne[0], $doliprod->error)."\n"; $error++; } if (version_compare(DOL_VERSION, 3.5) >= 0){ if ($doliprod->updatePrice($doliprod->price, $doliprod->price_base_type, $this->user) < 0){ $this->process_msg .= $langs->trans("ErrProductUpdate", $ligne[0], $doliprod->error)."\n"; $error++; } } else{ if ($doliprod->updatePrice($doliprod->id, $doliprod->price, $doliprod->price_base_type, $this->user) < 0){ $this->process_msg .= $langs->trans("ErrProductUpdate", $ligne[0], $doliprod->error)."\n"; $error++; } } } else $this->process_msg .= $langs->trans("Untreated", $i).' '.$langs->trans("ErrProdNoExist", $ligne[0])."\n"; break;*/ /*case 'M': if ($pid>0) { if ($doliprod->update($pid, $this->user) < 0){ $this->process_msg .= $langs->trans("ErrProductUpdate", $ligne[0], $doliprod->error)."\n"; $error++; } if (version_compare(DOL_VERSION, 3.5) >= 0){ if ($doliprod->updatePrice($doliprod->price, $doliprod->price_base_type, $this->user) < 0){ $this->process_msg .= $langs->trans("ErrProductUpdate", $ligne[0], $doliprod->error)."\n"; $error++; } } else{ if ($doliprod->updatePrice($doliprod->id, $doliprod->price, $doliprod->price_base_type, $this->user) < 0){ $this->process_msg .= $langs->trans("ErrProductUpdate", $ligne[0], $doliprod->error)."\n"; $error++; } } } else $this->process_msg .= $langs->trans("Untreated", $i).' '.$langs->trans("ErrProdNoExist", $ligne[0])."\n"; break;*/ case 'D': if ($pid > 0) { if ($doliprod->delete($pid) < 0) { $this->process_msg .= $langs->trans("ErrProductDelete", $ligne[0], $doliprod->error) . "\n"; $error++; } } else { $this->process_msg .= $langs->trans("Untreated", $i) . ' ' . $langs->trans("ErrProdNoExist", $ligne[0]) . "\n"; } } if (!$error) { $this->db->commit(); } else { $this->db->rollback(); } } } // while break; case 'ImportThirtdparty': $i = 0; //$societe = new Societe($this->db); while ($ligne = fgetcsv($fp, 1000, ";")) { $i++; $societe = new Societe($this->db); if ($this->firstline && $i == 1) { continue; } if (!$ligne[0]) { $this->process_msg .= $langs->trans("Untreated", $i) . " " . $langs->trans("ErrNameRequired") . "\n"; continue; } // vérifier par code_client if ($ligne[13]) { $sid = $this->get_socbyclientcode($ligne[13]); } else { if ($ligne[14]) { $sid = $this->get_socbysuplliercode($ligne[14]); } } if ($sid > 0) { $societe->fetch($sid); } else { $sid = $societe->fetch('', $ligne[0]); } if ($ligne[12]) { $pid = dol_getIdFromCode($this->db, $ligne[12], "c_pays", "code", "rowid"); } else { $pid = ''; } if ($pid <= 0) { $pid = ''; } $did = ''; $societe->id = $sid; $societe->name = $ligne[0]; $societe->particulier = 0; //Société $societe->address = $ligne[1] . "\n" . $ligne[2] . "\n" . $ligne[3]; $societe->zip = $ligne[4]; $societe->town = $ligne[5]; $societe->state_id = $did; if ($ligne[12]) { $societe->country_code = $ligne[12]; } $societe->country_id = $pid; dol_syslog("codes {$pid} " . $lige[12], LOG_DEBUG); $societe->phone = $ligne[6]; $societe->fax = $ligne[7]; $societe->email = $ligne[8]; $societe->url = $ligne[9]; $societe->idprof1 = $ligne[10]; switch ($ligne[11]) { case '0': $societe->fournisseur = 0; $societe->client = $ligne[11]; break; case '1': $societe->fournisseur = 0; $societe->client = $ligne[11]; break; case '2': $societe->fournisseur = 0; $societe->client = $ligne[11]; break; case '10': $societe->client = 0; $societe->fournisseur = 1; break; default: break; } if ($ligne[13]) { $societe->code_client = $ligne[13]; } if ($ligne[14]) { $societe->code_fournisseur = $ligne[14]; } /*if ($ligne[15]) $societe->array_options["options_zone"]=$ligne[15]; if (!empty($ligne[16])) $societe->array_options["options_CA"]=$ligne[16]; if (!empty($ligne[17])) { if ($ligne[17] <= 5) $societe->effectif_id = 1; elseif ($ligne[17] <= 10) $societe->effectif_id = 2; elseif ($ligne[17] <= 50) $societe->effectif_id = 3; elseif ($ligne[17] <= 100) $societe->effectif_id = 4; elseif ($ligne[17] <= 500) $societe->effectif_id = 5; else $societe->effectif_id = 7; } dol_syslog("effectif " . $lige[17].' '.$societe->effectif_id." ".print_r($societe->array_options, true), LOG_DEBUG);*/ $this->db->begin; switch ($typeimport) { case 'C': if ($sid > 0) { if ($societe->update($sid, $this->user) < 0) { $this->process_msg .= $langs->trans("ErrCompanyUpdate", $ligne[0], $societe->error) . "\n"; $error++; } } elseif ($societe->create($this->user) < 0) { $this->process_msg .= $langs->trans("ErrCompanyCreate", $ligne[0], $societe->error) . "\n"; $error++; } break; /*case 'M': if ($sid>0) { if ($societe->update($sid, $this->user) < 0){ $this->process_msg .= $langs->trans("ErrCompanyUpdate", $ligne[0], $societe->error)."\n"; $error++; } } else $this->process_msg .= $langs->trans("Untreated", $i).' '.$langs->trans("CompanyNoExist", $ligne[0])."\n"; break;*/ /*case 'M': if ($sid>0) { if ($societe->update($sid, $this->user) < 0){ $this->process_msg .= $langs->trans("ErrCompanyUpdate", $ligne[0], $societe->error)."\n"; $error++; } } else $this->process_msg .= $langs->trans("Untreated", $i).' '.$langs->trans("CompanyNoExist", $ligne[0])."\n"; break;*/ case 'D': if ($sid > 0) { if ($societe->delete($sid) < 0) { $this->process_msg .= $langs->trans("ErrCompanyDelete", $ligne[0], $societe->error) . "\n"; $error++; } } else { $this->process_msg .= $langs->trans("Untreated", $i) . ' ' . $langs->trans("CompanyNoExist", $ligne[0]) . "\n"; } } if (!$error) { $this->db->commit(); } else { $this->db->rollback(); } } break; case 'ImportContact': $i = 0; //$contact=new Contact($this->db); //$societe = new Societe($this->db); while ($ligne = fgetcsv($fp, 1000, ";")) { $i++; $contact = new Contact($this->db); $societe = new Societe($this->db); if ($this->firstline && $i == 1) { continue; } //if ($societe->fetch('',$ligne[0]) < 0 ) $this->process_msg .= "erreur lecture Société "."\n"; if ($ligne[0]) { $socid = $this->get_socbyclientcode($ligne[0]); } else { if ($ligne[1]) { $socid = $this->get_socbysuplliercode($ligne[1]); } } if ($socid < 0) { $this->process_msg .= $i . " " . $langs->trans("ErrCompanyRequired") . "\n"; } else { $societe->fetch($socid); } if (!$societe->id) { $this->process_msg .= $langs->trans("ErrCompanyNoExist", $ligne[0] . " " . $ligne[1]) . "\n"; continue; } if (empty($ligne[2])) { $this->process_msg .= $langs->trans("Untreated", $i) . " " . $langs->trans("ErrNameRequired") . "\n"; continue; } $contactid = $this->get_contact_id($socid, $ligne[2], $ligne[3]); $contact->id = $contactid; $contact->civilite_id = $ligne[4]; $contact->lastname = $ligne[2]; $contact->firstname = $ligne[3]; if ($ligne[5] || $ligne[6] || $ligne[7]) { $contact->address = $ligne[5] . "\n" . $ligne[6] . "\n" . $ligne[7]; } else { $contact->address = $societe->address; } if ($ligne[8]) { $contact->zip = $ligne[8]; } else { $contact->zip = $societe->zip; } if ($ligne[9]) { $contact->town = $ligne[9]; } else { $contact->town = $societe->town; } if ($ligne[10]) { $pid = dol_getIdFromCode($this->db, $ligne[10], "c_pays", "code", "rowid"); if ($pid <= 0) { $pid = ''; } $contact->country_id = $pid; $contact->country_code = $ligne[10]; } else { $contact->country_id = $societe->country_id; $contact->country_code = $societe->country_code; } $contact->socid = $socid; // fk_soc $contact->status = 1; $contact->email = $ligne[11]; $contact->phone_pro = $ligne[12]; $contact->fax = $ligne[13]; $contact->phone_mobile = $ligne[14]; $contact->priv = 0; $this->db - begin; switch ($typeimport) { case 'C': if ($contactid > 0) { if ($contact->update($contactid, $this->user) < 0) { $this->process_msg .= $langs->trans("ErrContactUpdate", $ligne[2], $contact->error) . "\n"; $error++; } } elseif ($contact->create($this->user) < 0) { $this->process_msg .= $langs->trans("ErrContactCreate", $ligne[2], $contact->error) . "\n"; $error++; } break; /*case 'M': if ($contactid>0) { if ($contact->update($contactid, $this->user) < 0){ $this->process_msg .= $langs->trans("ErrContactUpdate", $ligne[2], $contact->error)."\n"; $error++; } } else $this->process_msg .= $langs->trans("Untreated", $i).' '.$langs->trans("ContactNoExist", $ligne[2])."\n"; break;*/ /*case 'M': if ($contactid>0) { if ($contact->update($contactid, $this->user) < 0){ $this->process_msg .= $langs->trans("ErrContactUpdate", $ligne[2], $contact->error)."\n"; $error++; } } else $this->process_msg .= $langs->trans("Untreated", $i).' '.$langs->trans("ContactNoExist", $ligne[2])."\n"; break;*/ case 'D': if ($contactid > 0) { if ($contact->delete($contactid) < 0) { $this->process_msg .= $langs->trans("ErrContactDelete", $ligne[2], $contact->error) . "\n"; $error++; } } else { $this->process_msg .= $langs->trans("Untreated", $i) . ' ' . $langs->trans("ContactNoExist", $ligne[2]) . "\n"; } } if (!$error) { $this->db->commit(); } else { $this->db->rollback(); } } break; /*case 'ImportActions': $i=0; $contact=new Contact($this->db); $societe = new Societe($this->db); $actioncomm = new ActionComm($this->db); $actuser = new User($this->db); while ($ligne = fgetcsv($fp,1000,";")) { $i++; if ($this->firstline && $i== 1) continue; //if ($societe->fetch('',$ligne[0]) < 0 ) $this->process_msg .= "erreur lecture Société "."\n"; //else $socid = $societe->id; $socid = $this->get_socbyclientcode($ligne[0]); if ($socid < 0 ) $this->process_msg .= $langs->trans("Untreated", $i).' '.$langs->trans("ErrCompanyRequired")."\n"; else $societe->fetch($socid); $socid = $societe->id; if (!$socid) { $this->process_msg .= $langs->trans("ErrCompanyNoExist", $ligne[0])."\n"; continue; } //action sur un contact de la soc if ($ligne[1]) { $contactid = $this->get_contact_id($socid, $ligne[1], $ligne[2]) ; if ($contactid < 0) { $this->process_msg .= $langs->trans("Untreated", $i).' '.$langs->trans("ContactNoExist", $ligne[1].' '. $ligne[2])."\n"; // réinitialiser ?? continue; } else $contact->fetch($contactid); } $usertodo = ''; if ($ligne[9]) { $usertodo=new User($this->db); if ( $usertodo->fetch('',$ligne[9]) < 0 ) $this->process_msg .= $langs->trans("ErrUserNoExist", $ligne[9])."\n"; } $userdone= '' ; if ($ligne[10]) { $usertodo=new User($this->db); if ( $usertodo->fetch('',$ligne[10]) < 0 ) $this->process_msg .= $langs->trans("ErrUserNoExist", $ligne[10])."\n"; } $datep = ''; if ($ligne[6]) { // voir date $n = sscanf($ligne[6],"%02d/%02d/%04d", $d_day, $d_mon, $d_year); if ($n==3) $datep=dol_mktime(12, 0, 0, $d_mon, $d_day, $d_year); if (!$datep) $this->process_msg .= $langs->trans("ErrDateConversion", $ligne[6])."\n"; } else $datep =''; $datef=''; if ($ligne[7]) { // voir la date $n = sscanf($ligne[7],"%02d/%02d/%04d", $d_day, $d_mon, $d_year); if ($n==3)$datef=dol_mktime(12, 0, 0, $d_mon, $d_day, $d_year); if (!$datef) $this->process_msg .= $langs->trans("ErrDateConversion", $ligne[7])."\n"; } else $datef =''; //$datef=''; $actioncomm->societe = $societe; if ($ligne[1]) $actioncomm->contact = $contact; else $actioncomm->contact = ''; $actioncomm->type_code = $ligne[3]; $actioncomm->priority = $ligne[4]; $actioncomm->location = '' ; $actioncomm->label = $ligne[5]; $actioncomm->datep = $datep; $actioncomm->datef = $datef; $actioncomm->percentage = $ligne[8]; $actioncomm->usertodo = $usertodo; $actioncomm->userdone = $userdone; $actioncomm->note =$ligne[11]; switch ($typeimport) { case 'C': $this->db->begin(); if ($actioncomm->add($this->user) < 0) { $this->process_msg .= $langs->trans("ErrActionCreate", $ligne[5], $actioncomm->error)."\n"; $this->db->rollback(); } else $this->db->commit(); break; case 'M': $this->db->begin(); if($actioncomm->update($user) < 0){ $this->process_msg .= $langs->trans("ErrActionUpdate", $ligne[5], $actioncomm->error)."\n"; $this->db->rollback(); } else $this->db->commit(); break; case 'D': $this->db->begin(); if($actioncomm->delete() < 0){ $this->process_msg .= $langs->trans("ErrActionDelete", $ligne[5], $actioncomm->error)."\n"; $this->db->rollback(); } else $this->db->commit(); break; } } break;*/ /*case 'ImportActions': $i=0; $contact=new Contact($this->db); $societe = new Societe($this->db); $actioncomm = new ActionComm($this->db); $actuser = new User($this->db); while ($ligne = fgetcsv($fp,1000,";")) { $i++; if ($this->firstline && $i== 1) continue; //if ($societe->fetch('',$ligne[0]) < 0 ) $this->process_msg .= "erreur lecture Société "."\n"; //else $socid = $societe->id; $socid = $this->get_socbyclientcode($ligne[0]); if ($socid < 0 ) $this->process_msg .= $langs->trans("Untreated", $i).' '.$langs->trans("ErrCompanyRequired")."\n"; else $societe->fetch($socid); $socid = $societe->id; if (!$socid) { $this->process_msg .= $langs->trans("ErrCompanyNoExist", $ligne[0])."\n"; continue; } //action sur un contact de la soc if ($ligne[1]) { $contactid = $this->get_contact_id($socid, $ligne[1], $ligne[2]) ; if ($contactid < 0) { $this->process_msg .= $langs->trans("Untreated", $i).' '.$langs->trans("ContactNoExist", $ligne[1].' '. $ligne[2])."\n"; // réinitialiser ?? continue; } else $contact->fetch($contactid); } $usertodo = ''; if ($ligne[9]) { $usertodo=new User($this->db); if ( $usertodo->fetch('',$ligne[9]) < 0 ) $this->process_msg .= $langs->trans("ErrUserNoExist", $ligne[9])."\n"; } $userdone= '' ; if ($ligne[10]) { $usertodo=new User($this->db); if ( $usertodo->fetch('',$ligne[10]) < 0 ) $this->process_msg .= $langs->trans("ErrUserNoExist", $ligne[10])."\n"; } $datep = ''; if ($ligne[6]) { // voir date $n = sscanf($ligne[6],"%02d/%02d/%04d", $d_day, $d_mon, $d_year); if ($n==3) $datep=dol_mktime(12, 0, 0, $d_mon, $d_day, $d_year); if (!$datep) $this->process_msg .= $langs->trans("ErrDateConversion", $ligne[6])."\n"; } else $datep =''; $datef=''; if ($ligne[7]) { // voir la date $n = sscanf($ligne[7],"%02d/%02d/%04d", $d_day, $d_mon, $d_year); if ($n==3)$datef=dol_mktime(12, 0, 0, $d_mon, $d_day, $d_year); if (!$datef) $this->process_msg .= $langs->trans("ErrDateConversion", $ligne[7])."\n"; } else $datef =''; //$datef=''; $actioncomm->societe = $societe; if ($ligne[1]) $actioncomm->contact = $contact; else $actioncomm->contact = ''; $actioncomm->type_code = $ligne[3]; $actioncomm->priority = $ligne[4]; $actioncomm->location = '' ; $actioncomm->label = $ligne[5]; $actioncomm->datep = $datep; $actioncomm->datef = $datef; $actioncomm->percentage = $ligne[8]; $actioncomm->usertodo = $usertodo; $actioncomm->userdone = $userdone; $actioncomm->note =$ligne[11]; switch ($typeimport) { case 'C': $this->db->begin(); if ($actioncomm->add($this->user) < 0) { $this->process_msg .= $langs->trans("ErrActionCreate", $ligne[5], $actioncomm->error)."\n"; $this->db->rollback(); } else $this->db->commit(); break; case 'M': $this->db->begin(); if($actioncomm->update($user) < 0){ $this->process_msg .= $langs->trans("ErrActionUpdate", $ligne[5], $actioncomm->error)."\n"; $this->db->rollback(); } else $this->db->commit(); break; case 'D': $this->db->begin(); if($actioncomm->delete() < 0){ $this->process_msg .= $langs->trans("ErrActionDelete", $ligne[5], $actioncomm->error)."\n"; $this->db->rollback(); } else $this->db->commit(); break; } } break;*/ case 'Importtarif': // ref four $i = 0; $this->process_msg = ''; $error = 0; /*$doliprod = new Product($this->db); $product = new ProductFournisseur($this->db); $societe = new Societe($this->db);*/ while ($ligne = fgetcsv($fp, 1000, ";")) { $doliprod->id = ''; $i++; $doliprod = new Product($this->db); $product = new ProductFournisseur($this->db); $societe = new Societe($this->db); if ($this->firstline && $i == 1) { continue; } // recherche du fournisseur if ($societe->fetch('', $ligne[2]) > 0) { $sid = $societe->id; } else { $this->process_msg .= $langs->trans("Untreated", $i) . " " . $langs->trans("ErrComppanyNoExist", $ligne[2]) . "\n"; $sid = ''; } if ($doliprod->fetch('', $ligne[0]) > 0) { $pid = $doliprod->id; } else { $this->process_msg .= $langs->trans("Untreated", $i) . " " . $langs->trans("ErrProductNoExist", $ligne[0], $doliprod->error) . "\n"; $pid = ''; } if ($sid > 0 && $pid > 0) { $result = $product->fetch($doliprod->id); if ($result > 0) { $this->db->begin(); switch ($typeimport) { case 'C': $ret = $product->add_fournisseur($this->user, $sid, $ligne[1], $ligne[3]); if ($ret < 0 && $ret != -3) { $this->process_msg .= $langs->trans("Untreated", $i) . " " . $langs->trans("ErrCreatePrice", $product->error) . "\n"; $error++; } $ret = $product->update_buyprice($ligne[3], $ligne[4], $this->user, 'HT', $supplier, '', $ligne[1], $ligne[5]); if ($ret < 0 && $ret != -3) { $this->process_msg .= $langs->trans("Untreated", $i) . " " . $langs->trans("ErrCreatePrice", $product->error) . "\n"; $error++; } break; /*case 'M': { // gestion du prix obligatoire $supplier=new Fournisseur($this->db); $result=$supplier->fetch($sid); $ret=$product->update_buyprice($ligne[3], $ligne[4] , $this->user, 'HT', $supplier, '', $ligne[1], $ligne[5] ); if ($ret < 0) { $this->process_msg .= $langs->trans("Untreated", $i)." ".$langs->trans("Qty").$ligne[3]. ", ".$langs->trans("Price").$ligne[4]." ".$langs->trans("ErrUpdatePrice", $product->error)."\n"; $error ++; } } break;*/ /*case 'M': { // gestion du prix obligatoire $supplier=new Fournisseur($this->db); $result=$supplier->fetch($sid); $ret=$product->update_buyprice($ligne[3], $ligne[4] , $this->user, 'HT', $supplier, '', $ligne[1], $ligne[5] ); if ($ret < 0) { $this->process_msg .= $langs->trans("Untreated", $i)." ".$langs->trans("Qty").$ligne[3]. ", ".$langs->trans("Price").$ligne[4]." ".$langs->trans("ErrUpdatePrice", $product->error)."\n"; $error ++; } } break;*/ case 'D': // suprresion de la ligne avec le même nb d'article et le même prix $sql = "SELECT pfp.rowid FROM " . MAIN_DB_PREFIX . "product_fournisseur_price as pfp"; $sql .= " WHERE pfp.quantity = '" . $ligne[3] . "' AND pfp.ref_fourn = '" . $ligne[1]; $sql .= "' AND pfp.fk_soc = '" . $sid . "' AND pfp.fk_product='" . $pid . "'"; $sql .= " AND pfp.entity = " . $conf->entity; $resql = $this->db->query($sql); if ($resql) { $obj = $this->db->fetch_object($resql); if ($obj->rowid > 0) { $result = $product->remove_product_fournisseur_price($obj->rowid); } else { $this->process_msg .= $langs->trans("Untreated", $i) . ' ' . $langs->trans("ErrDeletePrice", $product->error) . "\n"; $error++; } } else { $this->process_msg .= "Error SQL= " . $sql . "\n"; $error++; } break; } //switch } if (!$error) { $this->db->commit(); } else { $this->db->rollback(); } } // fournisseur trouvé } // traitement ligne // while reffour break; } // fin switch fclose($fp); } else { $this->error = $langs->trans("ErrOpenFile") . $nomfich; $error = -1; } return $error; }
function _fiche_ligne(&$form, &$of, $type) { global $db, $conf, $langs, $hookmanager; //TODO rules guys ! To Facto ! AA $formProduct = new FormProduct($db); $PDOdb = new TPDOdb(); $TRes = array(); foreach ($of->TAssetOFLine as $k => &$TAssetOFLine) { $product =& $TAssetOFLine->product; if (is_null($product)) { $product = new Product($db); $product->fetch($TAssetOFLine->fk_product); $product->fetch_optionals(); } $conditionnement = $TAssetOFLine->conditionnement; if (!empty($conf->asset->enabled)) { $TAssetType = new TAsset_type(); $TAssetType->load($PDOdb, $product->array_options['options_type_asset']); $conditionnement_unit = $TAssetType->measuring_units == 'unit' || $TAssetType->gestion_stock == 'UNIT' ? 'unité(s)' : $TAssetOFLine->libUnite(); } else { $conditionnement_unit = 'unité(s)'; // TODO translate } //$conditionnement_unit = $TAssetOFLine->libUnite(); if ($TAssetOFLine->measuring_units != 'unit' && !empty($TAssetOFLine->measuring_units)) { $conditionnement_label = ' / ' . $conditionnement . " " . $conditionnement_unit; $conditionnement_label_edit = ' par ' . $form->texte('', 'TAssetOFLine[' . $k . '][conditionnement]', $conditionnement, 5, 5, '', '') . $conditionnement_unit; } else { $conditionnement_label = $conditionnement_label_edit = ''; } if ($TAssetOFLine->type == "NEEDED" && $type == "NEEDED") { $stock_needed = TAssetOF::getProductStock($product->id); $TLine = array('id' => $TAssetOFLine->getId(), 'idprod' => $form->hidden('TAssetOFLine[' . $k . '][fk_product]', $product->id), 'lot_number' => $of->status == 'DRAFT' ? $form->texte('', 'TAssetOFLine[' . $k . '][lot_number]', $TAssetOFLine->lot_number, 15, 50, 'type_product="NEEDED" fk_product="' . $product->id . '" rel="lot-' . $TAssetOFLine->getId() . '" ', 'TAssetOFLineLot') : $TAssetOFLine->lot_number, 'libelle' => $product->getNomUrl(1) . ' ' . $product->label . ' - ' . ($stock_needed > 0 ? $langs->trans("Stock") . " : " . $stock_needed : '<span style="color:red;font-weight:bold;">' . $langs->trans("Stock") . " : " . $stock_needed . '</span>') . _fiche_ligne_asset($PDOdb, $form, $of, $TAssetOFLine, 'NEEDED'), 'qty_needed' => $TAssetOFLine->qty_needed . $conditionnement_label, 'qty' => $of->status == 'DRAFT' ? $form->texte('', 'TAssetOFLine[' . $k . '][qty]', $TAssetOFLine->qty, 5, 50) : $TAssetOFLine->qty, 'qty_used' => $of->status == 'OPEN' || $of->status == 'CLOSE' ? $form->texte('', 'TAssetOFLine[' . $k . '][qty_used]', $TAssetOFLine->qty_used, 5, 50) : $TAssetOFLine->qty_used, 'qty_toadd' => $TAssetOFLine->qty - $TAssetOFLine->qty_used, 'workstations' => $conf->workstation->enabled ? $TAssetOFLine->visu_checkbox_workstation($db, $of, $form, 'TAssetOFLine[' . $k . '][fk_workstation][]') : '', 'delete' => $form->type_aff == 'edit' && ($of->status == 'DRAFT' || !empty($conf->global->OF_USE_DESTOCKAGE_PARTIEL) && $of->status != 'CLOSE' && empty($TAssetOFLine->qty_used)) ? '<a href="javascript:deleteLine(' . $TAssetOFLine->getId() . ',\'NEEDED\');">' . img_picto('Supprimer', 'delete.png') . '</a>' : '', 'fk_entrepot' => !empty($conf->global->ASSET_MANUAL_WAREHOUSE) && ($of->status == 'DRAFT' || $of->status == 'VALID') && $form->type_aff == 'edit' ? $formProduct->selectWarehouses($TAssetOFLine->fk_entrepot, 'TAssetOFLine[' . $k . '][fk_entrepot]', '', 0, 0, $TAssetOFLine->fk_product) : $TAssetOFLine->getLibelleEntrepot($PDOdb), 'note_private' => $of->status == 'DRAFT' ? $form->zonetexte('', 'TAssetOFLine[' . $k . '][note_private]', $TAssetOFLine->note_private, 50, 1) : $TAssetOFLine->note_private); $action = $form->type_aff; $parameter = array('of' => &$of, 'line' => &$TLine, 'type' => 'NEEDED'); $res = $hookmanager->executeHooks('lineObjectOptions', $parameter, $TAssetOFLine, $action); if ($res > 0 && !empty($hookmanager->resArray)) { $TLine = $hookmanager->resArray; } $TRes[] = $TLine; } elseif ($TAssetOFLine->type == "TO_MAKE" && $type == "TO_MAKE") { if (empty($TAssetOFLine->TFournisseurPrice)) { $TAssetOFLine->loadFournisseurPrice($PDOdb); } // Permet de sélectionner par défaut "(Fournisseur "Interne" => Fabrication interne)" si le produit TO_MAKE n'a pas de stock lorsqu'on est en mode edit et que la ligne TO_MAKE n'a pas encore de prix fournisseur enregistré dol_include_once('/product/class/product.class.php'); $p = new Product($db); $selected = 0; if ($p->fetch($TAssetOFLine->fk_product)) { $p->load_stock(); $p->stock_reel; if ($TAssetOFLine->type === 'TO_MAKE' && $p->stock_reel <= 0 && $_REQUEST['action'] === 'edit') { $selected = -2; } } // ************************************************************* $Tab = array(); foreach ($TAssetOFLine->TFournisseurPrice as &$objPrice) { $label = ""; //Si on a un prix fournisseur pour le produit if ($objPrice->price > 0) { $unit = $objPrice->quantity == 1 ? 'Unité' : 'Unités'; $label .= floatval($objPrice->price) . ' ' . $conf->currency . ' - ' . $objPrice->quantity . ' ' . $unit . ' -'; } //Affiche le nom du fournisseur $label .= ' (Fournisseur "' . utf8_encode($objPrice->name) . '"'; //Prix unitaire minimum si renseigné dans le PF if ($objPrice->quantity > 0) { ' ' . $objPrice->quantity . ' pièce(s) min,'; } //Affiche le type du PF : if ($objPrice->compose_fourni) { // soit on fabrique les composants $label .= ' => Fabrication interne'; } elseif ($objPrice->quantity <= 0) { // soit on a le produit finis déjà en stock $label .= ' => Sortie de stock'; } if ($objPrice->quantity > 0) { // soit on commande a un fournisseur $label .= ' => Commande fournisseur'; } $label .= ")"; $Tab[$objPrice->rowid] = array('label' => $label, 'compose_fourni' => $objPrice->compose_fourni ? $objPrice->compose_fourni : 0); } if ($conf->nomenclature->enabled) { dol_include_once('/nomenclature/class/nomenclature.class.php'); if ($of->status == 'DRAFT' && !$TAssetOFLine->nomenclature_valide) { $TNomenclature = TNomenclature::get($PDOdb, $TAssetOFLine->fk_product, true); if (count($TNomenclature) > 0) { $nomenclature = '<div>' . $form->combo('', 'TAssetOFLine[' . $k . '][fk_nomenclature]', $TNomenclature, $TAssetOFLine->fk_nomenclature); if ($form->type_aff == 'edit') { $nomenclature .= '<a href="#" class="valider_nomenclature" data-id_of="' . $of->getId() . '" data-product="' . $TAssetOFLine->fk_product . '" data-of_line="' . $TAssetOFLine->rowid . '">Valider</a>'; } else { $nomenclature .= " - Nomenclature à sélectionner"; } $nomenclature .= '</div>'; } else { $nomenclature = ''; } } else { $n = new TNomenclature(); $n->load($PDOdb, $TAssetOFLine->fk_nomenclature); $nomenclature = '<div>' . (string) $n; $picture = $TAssetOFLine->nomenclature_valide ? 'ok.png' : 'no.png'; $nomenclature .= ' <img src="img/' . $picture . '" style="padding-left: 2px; vertical-align: middle;" /></div>'; } } //($of->status=='DRAFT') ? $form->combo('', 'TAssetOFLine['.$k.'][fk_nomenclature]', _getArrayNomenclature($PDOdb, $TAssetOFLine), $TAssetOFLine->fk_nomenclature) : _getTitleNomenclature($PDOdb, $TAssetOFLine->fk_nomenclature) $stock_tomake = TAssetOF::getProductStock($product->id); $TLine = array('id' => $TAssetOFLine->getId(), 'idprod' => $form->hidden('TAssetOFLine[' . $k . '][fk_product]', $product->id), 'lot_number' => $of->status == 'DRAFT' ? $form->texte('', 'TAssetOFLine[' . $k . '][lot_number]', $TAssetOFLine->lot_number, 15, 50, 'type_product="TO_MAKE" fk_product="' . $product->id . '"', 'TAssetOFLineLot') : $TAssetOFLine->lot_number, 'libelle' => $product->getNomUrl(1) . ' ' . $product->label . ' - ' . $langs->trans("Stock") . " : " . $stock_tomake . _fiche_ligne_asset($PDOdb, $form, $of, $TAssetOFLine, false), 'nomenclature' => $nomenclature, 'addneeded' => $form->type_aff == 'edit' && $of->status == 'DRAFT' ? '<a href="#null" statut="' . $of->status . '" onclick="addAllLines(' . $of->getId() . ',' . $TAssetOFLine->getId() . ',this);">' . img_picto('Mettre à jour les produits nécessaires', 'object_technic.png') . '</a>' : '', 'qty' => $of->status == 'DRAFT' ? $form->texte('', 'TAssetOFLine[' . $k . '][qty]', $TAssetOFLine->qty, 5, 5, '', '') . $conditionnement_label_edit : $TAssetOFLine->qty . $conditionnement_label, 'qty_used' => $of->status == 'OPEN' || $of->status == 'CLOSE' ? $form->texte('', 'TAssetOFLine[' . $k . '][qty_used]', $TAssetOFLine->qty_used, 5, 5, '', '') . $conditionnement_label_edit : $TAssetOFLine->qty_used . $conditionnement_label, 'fk_product_fournisseur_price' => $form->combo('', 'TAssetOFLine[' . $k . '][fk_product_fournisseur_price]', $Tab, $TAssetOFLine->fk_product_fournisseur_price != 0 ? $TAssetOFLine->fk_product_fournisseur_price : $selected, 1, '', 'style="max-width:250px;"'), 'delete' => $form->type_aff == 'edit' && $of->status == 'DRAFT' ? '<a href="#null" onclick="deleteLine(' . $TAssetOFLine->getId() . ',\'TO_MAKE\');">' . img_picto('Supprimer', 'delete.png') . '</a>' : '', 'fk_entrepot' => !empty($conf->global->ASSET_MANUAL_WAREHOUSE) && ($of->status == 'DRAFT' || $of->status == 'VALID' || $of->status == 'NEEDOFFER' || $of->status == 'ONORDER' || $of->status == 'OPEN') && $form->type_aff == 'edit' ? $formProduct->selectWarehouses($TAssetOFLine->fk_entrepot, 'TAssetOFLine[' . $k . '][fk_entrepot]', '', 0, 0, $TAssetOFLine->fk_product) : $TAssetOFLine->getLibelleEntrepot($PDOdb)); $action = $form->type_aff; $parameter = array('of' => &$of, 'line' => &$TLine, 'type' => 'TO_MAKE'); $res = $hookmanager->executeHooks('lineObjectOptions', $parameter, $TAssetOFLine, $action); if ($res > 0 && !empty($hookmanager->resArray)) { $TLine = $hookmanager->resArray; } $TRes[] = $TLine; } } return $TRes; }
function addMoreLine($parameters, &$object, &$action, $hookmanager) { global $db, $conf, $langs; if (!empty($conf->global->OF_SHOW_QTY_THEORIQUE_MOINS_OF)) { $langs->load('asset@asset'); dol_include_once('/product/class/procudt.class.php'); $product = new Product($db); $fk_product = GETPOST('id', 'int'); $ref_product = GETPOST('ref', 'alpha'); $f = $product->fetch($fk_product, $ref_product); if ($f > 0) { $product->load_stock(); list($qty_to_make, $qty_needed) = $this->_calcQtyOfProductInOf($db, $conf, $product); $qty = $product->stock_theorique + $qty_to_make - $qty_needed; print '<tr>'; print '<td>' . $langs->trans('ofLabelQtyTheoriqueMoinsOf') . '</td>'; print '<td>' . $langs->trans('ofResultQty', $qty, $qty_to_make, $qty_needed) . '</td>'; print '</tr>'; } } }
} } // Transfer stock from a warehouse to another warehouse if ($action == "transfert_stock" && ! $_POST["cancel"]) { if ($_POST["id_entrepot_source"] <> $_POST["id_entrepot_destination"]) { if (is_numeric($_POST["nbpiece"]) && $id) { $product = new Product($db); $result=$product->fetch($id); $db->begin(); $product->load_stock(); // Load array product->stock_warehouse // Define value of products moved $pricesrc=0; if (isset($product->stock_warehouse[$_POST["id_entrepot_source"]]->pmp)) $pricesrc=$product->stock_warehouse[$_POST["id_entrepot_source"]]->pmp; $pricedest=$pricesrc; //print 'price src='.$pricesrc.', price dest='.$pricedest;exit; // Remove stock $result1=$product->correct_stock( $user, $_POST["id_entrepot_source"], $_POST["nbpiece"], 1, $_POST["label"],
/** * Add ticket line into database (linked to product/service or not) * @param array $lines Ticket Lines * @return array Result of adding */ private function addFactureLines($lines, $idTicket, $isreturn = false) { global $db; $res = 0; $object = new Facture($db); $object->fetch($idTicket); $object->brouillon = 1; if (sizeof($lines) > 0) { foreach ($lines as $line) { if (sizeof($line) > 0) { if ($line['idProduct'] > 0) { $product_static = new Product($db); $product_static->id = $line['idProduct']; $product_static->load_stock(); if ($product_static->stock_reel < 1 || $product_static->stock_reel < $line['cant']) { $res = -4; } if (!$isreturn) { $qty = $line['cant']; } else { $qty = $line['cant'] * -1; } $object->brouillon = 1; $line['discount'] = $line['discount'] + $object->remise_percent; $line['description'] = $line['description'] . " " . $line['note']; // TODO buscar el pmp del producto para este almacén, si es cero, pmp en general. $terminal = $_SESSION['TERMINAL_ID']; $cash = new Cash($db); $cash->fetch($terminal); $warehouse = $cash->fk_warehouse; $sql = "SELECT\tp.pmp as totpmp, (select ps.pmp FROM " . MAIN_DB_PREFIX . "product_stock as ps "; $sql .= " WHERE ps.fk_product = " . $line["idProduct"] . " AND ps.fk_entrepot = " . $warehouse . ") as warepmp "; $sql .= " FROM " . MAIN_DB_PREFIX . "product as p WHERE p.rowid = " . $line["idProduct"]; $resql = $db->query($sql); if ($resql) { $objp = $db->fetch_object($resql); $pmp = $objp->warepmp; if ($pmp <= 0) { $pmp = $objp->totpmp; if ($pmp <= 0 && $conf->global->ForceBuyingPriceIfNull) { $pmp = $line['price']; } } } $res = $object->addline($line['description'], $line['price'], $qty, $line['tva_tx'], $line['localtax1_tx'], $line['localtax2_tx'], $line['idProduct'], $line['discount'], '', '', 0, 0, '', $line['price_base_type'], $line['price_ttc'], $line['fk_product_type'], -1, 0, '', 0, 0, null, $pmp); } } else { $res = -1; } } } return $res; }
if ($conf->stock->enabled) { $langs->load("stocks"); if ($objp->fk_statut > 0 && $objp->fk_statut < 3) { $notshippable = 0; $warning = 0; $text_info = ''; $nbprod = 0; $numlines = count($generic_commande->lines); // Loop on each line of order for ($lig = 0; $lig < $numlines; $lig++) { if ($generic_commande->lines[$lig]->product_type == 0 && $generic_commande->lines[$lig]->fk_product > 0) { $nbprod++; // order contains real products $generic_product->id = $generic_commande->lines[$lig]->fk_product; if (empty($productstat_cache[$generic_commande->lines[$lig]->fk_product])) { $generic_product->load_stock(); $generic_product->load_virtual_stock(); $productstat_cache[$generic_commande->lines[$lig]->fk_product]['stock_reel'] = $generic_product->stock_reel; $productstat_cachevirtual[$generic_commande->lines[$lig]->fk_product]['stock_reel'] = $generic_product->stock_theorique; } else { $generic_product->stock_reel = $productstat_cache[$generic_commande->lines[$lig]->fk_product]['stock_reel']; $generic_product->stock_theorique = $productstat_cachevirtual[$generic_commande->lines[$lig]->fk_product]['stock_reel'] = $generic_product->stock_theorique; } if (empty($conf->global->SHIPPABLE_ORDER_ICON_IN_LIST)) { $text_info .= $generic_commande->lines[$lig]->qty . ' X ' . $generic_commande->lines[$lig]->ref . ' ' . dol_trunc($generic_commande->lines[$lig]->product_label, 25); $text_info .= ' - ' . $langs->trans("Stock") . ': ' . $generic_product->stock_reel; $text_info .= ' - ' . $langs->trans("VirtualStock") . ': ' . $generic_product->stock_theorique; $text_info .= '<br>'; if ($generic_commande->lines[$lig]->qty > $generic_product->stock_reel) { $notshippable++; }
/** * Update a product or service * * @param array $authentication Array of authentication information * @param Product $product Product * @return array Array result */ function updateProductOrService($authentication, $product) { global $db, $conf, $langs; $now = dol_now(); dol_syslog("Function: updateProductOrService login="******"You must choose between price or price_net to provide price."; } if ($product['barcode'] && !$product['barcode_type']) { $errror++; $errorcode = 'KO'; $errorlabel = "You must set a barcode type when setting a barcode."; } if (!$error) { include_once DOL_DOCUMENT_ROOT . '/core/lib/company.lib.php'; $newobject = new Product($db); $newobject->fetch($product['id']); if (isset($product['ref'])) { $newobject->ref = $product['ref']; } if (isset($product['ref_ext'])) { $newobject->ref_ext = $product['ref_ext']; } $newobject->type = $product['type']; $newobject->libelle = $product['label']; // @deprecated $newobject->label = $product['label']; $newobject->description = $product['description']; $newobject->note = $product['note']; $newobject->status = $product['status_tosell']; $newobject->status_buy = $product['status_tobuy']; $newobject->price = $product['price_net']; $newobject->price_ttc = $product['price']; $newobject->tva_tx = $product['vat_rate']; $newobject->price_base_type = $product['price_base_type']; $newobject->date_creation = $now; if ($product['barcode']) { $newobject->barcode = $product['barcode']; $newobject->barcode_type = $product['barcode_type']; } $newobject->stock_reel = $product['stock_real']; $newobject->pmp = $product['pmp']; $newobject->seuil_stock_alert = $product['stock_alert']; $newobject->country_id = $product['country_id']; if ($product['country_code']) { $newobject->country_id = getCountry($product['country_code'], 3); } $newobject->customcode = $product['customcode']; $newobject->canvas = $product['canvas']; /*foreach($product['lines'] as $line) { $newline=new FactureLigne($db); $newline->type=$line['type']; $newline->desc=$line['desc']; $newline->fk_product=$line['fk_product']; $newline->total_ht=$line['total_net']; $newline->total_vat=$line['total_vat']; $newline->total_ttc=$line['total']; $newline->vat=$line['vat_rate']; $newline->qty=$line['qty']; $newline->fk_product=$line['product_id']; }*/ //var_dump($product['ref_ext']); //var_dump($product['lines'][0]['type']); $extrafields = new ExtraFields($db); $extralabels = $extrafields->fetch_name_optionals_label('product', true); foreach ($extrafields->attribute_label as $key => $label) { $key = 'options_' . $key; $newobject->array_options[$key] = $product[$key]; } $db->begin(); $result = $newobject->update($newobject->id, $fuser); if ($result <= 0) { $error++; } else { // Update stock if stock count is provided and differs from database after creation or update if (isset($product['stock_real']) && $product['stock_real'] != '' && !empty($conf->global->stock->enabled)) { require_once DOL_DOCUMENT_ROOT . '/product/stock/class/entrepot.class.php'; $savstockreal = $newobject->stock_reel; $newobject->load_stock(); // This overwrite ->stock_reel $getstockreal = $newobject->stock_reel; if ($savstockreal != $getstockreal) { $warehouse = new Entrepot($this->db); $warehouse->fetch(0, $product['warehouse_ref']); if ($warehouse->id > 0) { if ($savstockreal - $getstockreal > 0) { $result = $newobject->correct_stock($fuser, $warehouse->id, $savstockreal - $getstockreal, 0, 'Correction from external call (Web Service)', 0, 'WS' . dol_print_date($now, 'dayhourlog')); } if ($savstockreal - $getstockreal > 0) { $result = $newobject->correct_stock($fuser, $warehouse->id, $savstockreal - $getstockreal, 1, 'Correction from external call (Web Service)', 0, 'WS' . dol_print_date($now, 'dayhourlog')); } if ($result <= 0) { $error++; $newobject->error = 'You set a different value for stock, but correction of stock count (before=' . $getstockreal . ', after=' . $savstockreal . ') fails with error ' . $newobject->error; } } else { $error++; $newobject->error = 'You set a different value for stock but we failed to find warehouse ' . $product['warehouse_ref'] . ' to make correction.'; } } } } if (!$error) { if ($newobject->price_base_type == 'HT') { $result = $newobject->updatePrice($newobject->price, $newobject->price_base_type, $fuser); if ($result <= 0) { $error++; } } elseif ($newobject->price_base_type == 'TTC') { $result = $newobject->updatePrice($newobject->price_ttc, $newobject->price_base_type); if ($result <= 0) { $error++; } } } if (!$error) { $db->commit(); $objectresp = array('result' => array('result_code' => 'OK', 'result_label' => ''), 'id' => $newobject->id, 'ref' => $newobject->ref); } else { $db->rollback(); $error++; $errorcode = 'KO'; $errorlabel = $newobject->error; } } if ($error) { $objectresp = array('result' => array('result_code' => $errorcode, 'result_label' => $errorlabel)); } return $objectresp; }
/** * Get produt or service * * @param array $authentication Array of authentication information * @param int $id Id of object * @param string $ref Ref of object * @param string $ref_ext Ref external of object * @param string $lang Lang to force * @return mixed */ function getProductOrService($authentication, $id = '', $ref = '', $ref_ext = '', $lang = '') { global $db, $conf, $langs; dol_syslog("Function: getProductOrService login="******" id=" . $id . " ref=" . $ref . " ref_ext=" . $ref_ext); $langcode = $lang ? $lang : (empty($conf->global->MAIN_LANG_DEFAULT) ? 'auto' : $conf->global->MAIN_LANG_DEFAULT); $langs->setDefaultLang($langcode); if ($authentication['entity']) { $conf->entity = $authentication['entity']; } // Init and check authentication $objectresp = array(); $errorcode = ''; $errorlabel = ''; $error = 0; $fuser = check_authentication($authentication, $error, $errorcode, $errorlabel); // Check parameters if (!$error && ($id && $ref || $id && $ref_ext || $ref && $ref_ext)) { $error++; $errorcode = 'BAD_PARAMETERS'; $errorlabel = "Parameter id, ref and ref_ext can't be both provided. You must choose one or other but not both."; } if (!$error) { $langcode = $lang ? $lang : (empty($conf->global->MAIN_LANG_DEFAULT) ? 'auto' : $conf->global->MAIN_LANG_DEFAULT); $langs->setDefaultLang($langcode); $fuser->getrights(); if ($fuser->rights->produit->lire || $fuser->rights->service->lire) { $product = new Product($db); $result = $product->fetch($id, $ref, $ref_ext); if ($result > 0) { $product->load_stock(); $dir = !empty($conf->product->dir_output) ? $conf->product->dir_output : $conf->service->dir_output; $pdir = get_exdir($product->id, 2) . $product->id . "/photos/"; $dir = $dir . '/' . $pdir; if (!empty($product->multilangs[$langs->defaultlang]["label"])) { $product->label = $product->multilangs[$langs->defaultlang]["label"]; } if (!empty($product->multilangs[$langs->defaultlang]["description"])) { $product->description = $product->multilangs[$langs->defaultlang]["description"]; } if (!empty($product->multilangs[$langs->defaultlang]["note"])) { $product->note = $product->multilangs[$langs->defaultlang]["note"]; } $productorservice_result_fields = array('id' => $product->id, 'ref' => $product->ref, 'ref_ext' => $product->ref_ext, 'label' => $product->label, 'description' => $product->description, 'date_creation' => dol_print_date($product->date_creation, 'dayhourrfc'), 'date_modification' => dol_print_date($product->date_modification, 'dayhourrfc'), 'note' => $product->note, 'status_tosell' => $product->status, 'status_tobuy' => $product->status_buy, 'type' => $product->type, 'barcode' => $product->barcode, 'barcode_type' => $product->barcode_type, 'country_id' => $product->country_id > 0 ? $product->country_id : '', 'country_code' => $product->country_code, 'custom_code' => $product->customcode, 'price_net' => $product->price, 'price' => $product->price_ttc, 'price_min_net' => $product->price_min, 'price_min' => $product->price_min_ttc, 'price_base_type' => $product->price_base_type, 'vat_rate' => $product->tva_tx, 'vat_npr' => $product->tva_npr, 'localtax1_tx' => $product->localtax1_tx, 'localtax2_tx' => $product->localtax2_tx, 'stock_real' => $product->stock_reel, 'stock_alert' => $product->seuil_stock_alerte, 'pmp' => $product->pmp, 'import_key' => $product->import_key, 'dir' => $pdir, 'images' => $product->liste_photos($dir, $nbmax = 10)); //Retreive all extrafield for thirdsparty // fetch optionals attributes and labels $extrafields = new ExtraFields($db); $extralabels = $extrafields->fetch_name_optionals_label('product', true); //Get extrafield values $product->fetch_optionals($product->id, $extralabels); foreach ($extrafields->attribute_label as $key => $label) { $productorservice_result_fields = array_merge($productorservice_result_fields, array('options_' . $key => $product->array_options['options_' . $key])); } // Create $objectresp = array('result' => array('result_code' => 'OK', 'result_label' => ''), 'product' => $productorservice_result_fields); } else { $error++; $errorcode = 'NOT_FOUND'; $errorlabel = 'Object not found for id=' . $id . ' nor ref=' . $ref . ' nor ref_ext=' . $ref_ext; } } else { $error++; $errorcode = 'PERMISSION_DENIED'; $errorlabel = 'User does not have permission for this request'; } } if ($error) { $objectresp = array('result' => array('result_code' => $errorcode, 'result_label' => $errorlabel)); } //var_dump($objectresp);exit; return $objectresp; }
/** * Add a movement of stock (in one direction only) * * @param User $user User object * @param int $fk_product Id of product * @param int $entrepot_id Id of warehouse * @param int $qty Qty of movement (can be <0 or >0 depending on parameter type) * @param int $type Direction of movement: * 0=input (stock increase after stock transfert), 1=output (stock decrease after stock transfer), * 2=output (stock decrease), 3=input (stock increase) * Note that qty should be > 0 with 0 or 3, < 0 with 1 or 2. * @param int $price Unit price HT of product, used to calculate average weighted price (PMP in french). If 0, average weighted price is not changed. * @param string $label Label of stock movement * @param string $inventorycode Inventory code * @param string $datem Force date of movement * @param date $eatby eat-by date * @param date $sellby sell-by date * @param string $batch batch number * @param boolean $skip_batch If set to true, stock movement is done without impacting batch record * @return int <0 if KO, 0 if fk_product is null, >0 if OK */ function _create($user, $fk_product, $entrepot_id, $qty, $type, $price = 0, $label = '', $inventorycode = '', $datem = '', $eatby = '', $sellby = '', $batch = '', $skip_batch = false) { global $conf, $langs; require_once DOL_DOCUMENT_ROOT . '/product/class/product.class.php'; $error = 0; dol_syslog(get_class($this) . "::_create start userid={$user->id}, fk_product={$fk_product}, warehouse={$entrepot_id}, qty={$qty}, type={$type}, price={$price}, label={$label}, inventorycode={$inventorycode}, datem=" . $datem . ", eatby=" . $eatby . ", sellby=" . $sellby . ", batch=" . $batch . ", skip_batch=" . $skip_batch); // Clean parameters if (empty($price)) { $price = 0; } $now = !empty($datem) ? $datem : dol_now(); // Check parameters if (empty($fk_product)) { return 0; } if ($eatby < 0) { $this->errors[] = 'ErrorBadValueForParameterEatBy'; return -1; } if ($sellby < 0) { $this->errors[] = 'ErrorBadValueForParameterEatBy'; return -1; } // Set properties of movement $this->product_id = $fk_product; $this->entrepot_id = $entrepot_id; $this->qty = $qty; $this->type = $type; $mvid = 0; $product = new Product($this->db); $result = $product->fetch($fk_product); if ($result < 0) { dol_print_error('', "Failed to fetch product"); return -1; } $this->db->begin(); $product->load_stock(); // Test if product require batch data. If yes, and there is not, we throw an error. if (!empty($conf->productbatch->enabled) && $product->hasbatch() && !$skip_batch) { //if (empty($batch) && empty($eatby) && empty($sellby)) if (empty($batch)) { $this->errors[] = $langs->trans("ErrorTryToMakeMoveOnProductRequiringBatchData", $product->name); dol_syslog("Try to make a movement of a product with status_batch on without any batch data"); $this->db->rollback(); return -2; } // If a serial number is provided, we check that sellby and eatby match already existing serial $sql = "SELECT pb.rowid, pb.batch, pb.eatby, pb.sellby FROM " . MAIN_DB_PREFIX . "product_batch as pb, " . MAIN_DB_PREFIX . "product_stock as ps"; $sql .= " WHERE pb.fk_product_stock = ps.rowid AND ps.fk_product = " . $fk_product . " AND pb.batch = '" . $this->db->escape($batch) . "'"; dol_syslog(get_class($this) . "::_create scan serial for this product to check if eatby and sellby match", LOG_DEBUG); $resql = $this->db->query($sql); if ($resql) { $num = $this->db->num_rows($resql); $i = 0; while ($i < $num) { $obj = $this->db->fetch_object($resql); if ($this->db->jdate($obj->eatby) != $eatby) { $this->errors[] = $langs->trans("ThisSerialAlreadyExistWithDifferentDate", $batch, $this->db->jdate($obj->eatby), $eatby); dol_syslog($langs->trans("ThisSerialAlreadyExistWithDifferentDate", $batch, $this->db->jdate($obj->eatby), $eatby)); $this->db->rollback(); return -3; } if ($this->db->jdate($obj->sellby) != $sellby) { $this->errors[] = $langs->trans("ThisSerialAlreadyExistWithDifferentDate", $batch, $this->db->jdate($obj->sellby), $sellby); dol_syslog($langs->trans("ThisSerialAlreadyExistWithDifferentDate", $batch, $this->db->jdate($obj->sellby), $sellby)); $this->db->rollback(); return -3; } $i++; } } else { dol_print_error($this->db); $this->db->rollback(); return -1; } } // TODO Check qty is ok for stock move. if (!empty($conf->productbatch->enabled) && $product->hasbatch() && !$skip_batch) { } else { } // Define if we must make the stock change (If product type is a service or if stock is used also for services) $movestock = 0; if ($product->type != Product::TYPE_SERVICE || !empty($conf->global->STOCK_SUPPORTS_SERVICES)) { $movestock = 1; } if ($movestock && $entrepot_id > 0) { if (!empty($this->origin)) { // This is set by caller for tracking reason $origintype = $this->origin->element; $fk_origin = $this->origin->id; } else { $origintype = ''; $fk_origin = 0; } $sql = "INSERT INTO " . MAIN_DB_PREFIX . "stock_mouvement("; $sql .= " datem, fk_product, batch, eatby, sellby,"; $sql .= " fk_entrepot, value, type_mouvement, fk_user_author, label, inventorycode, price, fk_origin, origintype"; $sql .= ")"; $sql .= " VALUES ('" . $this->db->idate($now) . "', " . $this->product_id . ", "; $sql .= " " . ($batch ? "'" . $batch . "'" : "null") . ", "; $sql .= " " . ($eatby ? "'" . $this->db->idate($eatby) . "'" : "null") . ", "; $sql .= " " . ($sellby ? "'" . $this->db->idate($sellby) . "'" : "null") . ", "; $sql .= " " . $this->entrepot_id . ", " . $this->qty . ", " . $this->type . ","; $sql .= " " . $user->id . ","; $sql .= " '" . $this->db->escape($label) . "',"; $sql .= " " . ($inventorycode ? "'" . $this->db->escape($inventorycode) . "'" : "null") . ","; $sql .= " '" . price2num($price) . "',"; $sql .= " '" . $fk_origin . "',"; $sql .= " '" . $origintype . "'"; $sql .= ")"; dol_syslog(get_class($this) . "::_create", LOG_DEBUG); $resql = $this->db->query($sql); if ($resql) { $mvid = $this->db->last_insert_id(MAIN_DB_PREFIX . "stock_mouvement"); $this->id = $mvid; } else { $this->errors[] = $this->db->lasterror(); $error = -1; } // Define current values for qty and pmp $oldqty = $product->stock_reel; $oldpmp = $product->pmp; $oldqtywarehouse = 0; //$oldpmpwarehouse=0; // Test if there is already a record for couple (warehouse / product) $num = 0; if (!$error) { $sql = "SELECT rowid, reel FROM " . MAIN_DB_PREFIX . "product_stock"; $sql .= " WHERE fk_entrepot = " . $entrepot_id . " AND fk_product = " . $fk_product; // This is a unique key dol_syslog(get_class($this) . "::_create", LOG_DEBUG); $resql = $this->db->query($sql); if ($resql) { $obj = $this->db->fetch_object($resql); if ($obj) { $num = 1; $oldqtywarehouse = $obj->reel; //$oldpmpwarehouse = $obj->pmp; $fk_product_stock = $obj->rowid; } $this->db->free($resql); } else { $this->errors[] = $this->db->lasterror(); $error = -2; } } // Calculate new PMP. $newpmp = 0; //$newpmpwarehouse=0; if (!$error) { // Note: PMP is calculated on stock input only (type of movement = 0 or 3). If type == 0 or 3, qty should be > 0. // Note: Price should always be >0 or 0. PMP should be always >0 (calculated on input) if (($type == 0 || $type == 3) && $price > 0) { // If we will change PMP for the warehouse we edit and the product, we must first check/clean that PMP is defined // on every stock entry with old value (so global updated value will match recalculated value from product_stock) /* $sql = "UPDATE ".MAIN_DB_PREFIX."product_stock SET pmp = ".($oldpmp?$oldpmp:'0'); $sql.= " WHERE pmp = 0 AND fk_product = ".$fk_product; dol_syslog(get_class($this)."::_create", LOG_DEBUG); $resql=$this->db->query($sql); if (! $resql) { $this->errors[]=$this->db->lasterror(); $error = -4; } */ $oldqtytouse = $oldqty >= 0 ? $oldqty : 0; // We make a test on oldpmp>0 to avoid to use normal rule on old data with no pmp field defined if ($oldpmp > 0) { $newpmp = price2num(($oldqtytouse * $oldpmp + $qty * $price) / ($oldqtytouse + $qty), 'MU'); } else { $newpmp = $price; // For this product, PMP was not yet set. We set it to input price. } /* $oldqtywarehousetouse=$oldqtywarehouse; if ($oldpmpwarehouse > 0) $newpmpwarehouse=price2num((($oldqtywarehousetouse * $oldpmpwarehouse) + ($qty * $price)) / ($oldqtywarehousetouse + $qty), 'MU'); else $newpmpwarehouse=$price; */ //print "oldqtytouse=".$oldqtytouse." oldpmp=".$oldpmp." oldqtywarehousetouse=".$oldqtywarehousetouse." oldpmpwarehouse=".$oldpmpwarehouse." "; //print "qty=".$qty." newpmp=".$newpmp." newpmpwarehouse=".$newpmpwarehouse; //exit; } else { if ($type == 1 || $type == 2) { // After a stock decrease, we don't change value of PMP for product. $newpmp = $oldpmp; } else { $newpmp = $oldpmp; //$newpmpwarehouse = $oldpmpwarehouse; } } } // Update stock quantity if (!$error) { if ($num > 0) { //$sql = "UPDATE ".MAIN_DB_PREFIX."product_stock SET pmp = ".$newpmpwarehouse.", reel = reel + ".$qty; $sql = "UPDATE " . MAIN_DB_PREFIX . "product_stock SET reel = reel + " . $qty; $sql .= " WHERE fk_entrepot = " . $entrepot_id . " AND fk_product = " . $fk_product; } else { $sql = "INSERT INTO " . MAIN_DB_PREFIX . "product_stock"; //$sql.= " (pmp, reel, fk_entrepot, fk_product) VALUES "; //$sql.= " (".$newpmpwarehouse.", ".$qty.", ".$entrepot_id.", ".$fk_product.")"; $sql .= " (reel, fk_entrepot, fk_product) VALUES "; $sql .= " (" . $qty . ", " . $entrepot_id . ", " . $fk_product . ")"; } dol_syslog(get_class($this) . "::_create", LOG_DEBUG); $resql = $this->db->query($sql); if (!$resql) { $this->errors[] = $this->db->lasterror(); $error = -3; } else { if (empty($fk_product_stock)) { $fk_product_stock = $this->db->last_insert_id(MAIN_DB_PREFIX . "product_stock"); } } } // Update detail stock for batch product if (!$error && !empty($conf->productbatch->enabled) && $product->hasbatch() && !$skip_batch) { $param_batch = array('fk_product_stock' => $fk_product_stock, 'eatby' => $eatby, 'sellby' => $sellby, 'batchnumber' => $batch); $result = $this->_create_batch($param_batch, $qty); if ($result < 0) { $error++; } } // Update PMP and denormalized value of stock qty at product level if (!$error) { $sql = "UPDATE " . MAIN_DB_PREFIX . "product SET pmp = " . $newpmp . ", stock = " . $this->db->ifsql("stock IS NULL", 0, "stock") . " + " . $qty; $sql .= " WHERE rowid = " . $fk_product; // May be this request is better: // UPDATE llx_product p SET p.stock= (SELECT SUM(ps.reel) FROM llx_product_stock ps WHERE ps.fk_product = p.rowid); dol_syslog(get_class($this) . "::_create", LOG_DEBUG); $resql = $this->db->query($sql); if (!$resql) { $this->errors[] = $this->db->lasterror(); $error = -4; } } } // Add movement for sub products (recursive call) if (!$error && !empty($conf->global->PRODUIT_SOUSPRODUITS) && empty($conf->global->INDEPENDANT_SUBPRODUCT_STOCK)) { $error = $this->_createSubProduct($user, $fk_product, $entrepot_id, $qty, $type, 0, $label, $inventorycode); // we use 0 as price, because pmp is not changed for subproduct } if ($movestock && !$error) { // Call trigger $result = $this->call_trigger('STOCK_MOVEMENT', $user); if ($result < 0) { $error++; } // End call triggers } if (!$error) { $this->db->commit(); return $mvid; } else { $this->db->rollback(); dol_syslog(get_class($this) . "::_create error code=" . $error, LOG_ERR); return -6; } }
print '<td width="12%" align="center">'.$langs->trans("Stock").'</td>'; } print "</tr>\n"; } $var=true; while ($i < $num) { $product = new Product($db); $line = $commande->lines[$i]; $var=!$var; print "<tr $bc[$var]>\n"; if ($line->fk_product > 0) { $product->fetch($line->fk_product); $product->load_stock(); print '<td>'; print '<a href="'.DOL_URL_ROOT.'/product/fiche.php?id='.$line->fk_product.'">'.img_object($langs->trans("ShowProduct"),"product").' '.$product->ref.'</a> - '.$product->libelle; if ($line->description) print nl2br($line->description); print '</td>'; } else { print "<td>".nl2br($line->description)."</td>\n"; } print '<td align="center">'.$line->qty.'</td>'; /* * */
function createOfAndCommandesFourn(&$PDOdb) { global $db, $user; dol_include_once("fourn/class/fournisseur.commande.class.php"); $TabOF = array(); $TabOF[] = $this->rowid; $this->getListeOFEnfants($PDOdb, $TabOF); // Boucle pour chaque OF de l'arbre foreach ($TabOF as $idOf) { // On charge l'OF $assetOF = new TAssetOF(); $assetOF->load($PDOdb, $idOf); // Boucle pour chaque produit de l'OF foreach ($assetOF->TAssetOFLine as $ofLigne) { //pre($ofLigne,true); // On cherche le produit "TO_MAKE" if ($ofLigne->type == "TO_MAKE") { //pre($ofLigne,true); exit; if ($ofLigne->fk_product_fournisseur_price > 0) { // Fournisseur externe // On récupère la ligne prix fournisseur correspondante $sql = "SELECT rowid, fk_soc, fk_product, price, compose_fourni, quantity, ref_fourn"; $sql .= " FROM " . MAIN_DB_PREFIX . "product_fournisseur_price"; $sql .= " WHERE rowid = " . $ofLigne->fk_product_fournisseur_price; $resql = $db->query($sql); $res = $db->fetch_object($resql); // Si fabrication interne if ($res->compose_fourni) { // On charge le produit "TO_MAKE" $prod = new Product($db); $prod->fetch($ofLigne->fk_product); $prod->load_stock(); $stockProd = 0; // On récupère son stock foreach ($prod->stock_warehouse as $stock) { $stockProd += $stock->real; } // S'il y a suffisemment de stock, on destocke // Sinon, commande fournisseur : if ($stockProd < $ofLigne->qty_needed) { $this->addCommandeFourn($PDOdb, $ofLigne, $res); } else { // Suffisemment de stock, donc destockage : $assetOF->openOF($PDOdb); } } elseif (!$res->compose_fourni) { //Commande Fournisseur $this->addCommandeFourn($PDOdb, $ofLigne, $res); // On récupère les OF enfants pour les supprimer $TabIdEnfantsDirects = $assetOF->getEnfantsDirects(); foreach ($TabIdEnfantsDirects as $idOF) { $assetOF->removeChild("TAssetOF", $idOF); } //Suppression des lignes NEEDED puisque inutiles $assetOF->delLineNeeded($PDOdb); $assetOF->unsetChildDeleted = true; $assetOF->save($PDOdb); // On casse la boucle break; } } else { // Fournisseur interne (Bourguignon) [PH - 14/04/15 - FIXME c'est pas que pour bourguignon ?] if ($ofLigne->fk_product_fournisseur_price == -1) { // Sortie de stock, kill OF enfants $TabIdEnfantsDirects = $assetOF->getEnfantsDirects(); foreach ($TabIdEnfantsDirects as $idOF) { $assetOF->removeChild("TAssetOF", $idOF); } $assetOF->save($PDOdb); // On casse la boucle break; } elseif ($ofLigne->fk_product_fournisseur_price == -2) { // Fabrication interne //[PH] FIXME - pourquoi on destock maintenant ? On valide tt juste l'OF $prod = new Product($db); $prod->fetch($ofLigne->fk_product); $prod->load_stock(); $stockProd = 0; // On récupère son stock foreach ($prod->stock_warehouse as $stock) { $stockProd += $stock->real; } // S'il y a sufisemment de stock, on destocke if ($stockProd >= $ofLigne->qty_needed) { //$assetOF->openOF($PDOdb); $assetOF->status = 'VALID'; } } } } } } }