function _calcTotaux(&$object, &$line, &$qty_dispatched, &$total_ht, &$total_tva, &$total_ttc, &$total_localtax1, &$total_localtax2, $debug) { if ($debug) { print 'fk_product = ' . $line->fk_product . ' :: qty cmd = ' . $line->qty . ' :: qty ventilés = ' . $qty_dispatched . '<br />'; } $line->qty = $qty_dispatched; // Ceci est important de le faire, j'update la qty de la ligne courante qui sera repris sur l'affichage de Dolibarr $tabprice = calcul_price_total($line->qty, $line->subprice, $line->remise_percent, $line->tva_tx, $line->localtax1_tx, $line->localtax2_tx, 0, 'HT', $line->info_bits, $line->product_type, $object->thirdparty, array()); $total_ht += $tabprice[0]; $total_tva += $tabprice[1]; $total_ttc += $tabprice[2]; $total_localtax1 += $tabprice[9]; $total_localtax2 += $tabprice[10]; }
/** * Update a detail line * * @param int $rowid Id of line to update * @param string $desc Description of line * @param double $pu Prix unitaire (HT ou TTC selon price_base_type) (> 0 even for credit note lines) * @param double $qty Quantity * @param double $remise_percent Pourcentage de remise de la ligne * @param int $date_start Date de debut de validite du service * @param int $date_end Date de fin de validite du service * @param double $txtva VAT Rate * @param double $txlocaltax1 Local tax 1 rate * @param double $txlocaltax2 Local tax 2 rate * @param string $price_base_type HT or TTC * @param int $info_bits Miscellaneous informations * @param int $type Type of line (0=product, 1=service) * @param int $fk_parent_line Id of parent line (0 in most cases, used by modules adding sublevels into lines). * @param int $skip_update_total Keep fields total_xxx to 0 (used for special lines by some modules) * @param int $fk_fournprice Id of origin supplier price * @param int $pa_ht Price (without tax) of product when it was bought * @param string $label Label of the line (deprecated, do not use) * @param int $special_code Special code (also used by externals modules!) * @param array $array_option extrafields array * @return int < 0 if KO, > 0 if OK */ function updateline($rowid, $desc, $pu, $qty, $remise_percent, $date_start, $date_end, $txtva, $txlocaltax1 = 0, $txlocaltax2 = 0, $price_base_type = 'HT', $info_bits = 0, $type = self::TYPE_STANDARD, $fk_parent_line = 0, $skip_update_total = 0, $fk_fournprice = null, $pa_ht = 0, $label = '', $special_code = 0, $array_option = 0) { include_once DOL_DOCUMENT_ROOT . '/core/lib/price.lib.php'; global $mysoc; dol_syslog(get_class($this) . "::updateline rowid={$rowid}, desc={$desc}, pu={$pu}, qty={$qty}, remise_percent={$remise_percent}, date_start={$date_start}, date_end={$date_end}, txtva={$txtva}, txlocaltax1={$txlocaltax1}, txlocaltax2={$txlocaltax2}, price_base_type={$price_base_type}, info_bits={$info_bits}, type={$type}, fk_parent_line={$fk_parent_line} pa_ht={$pa_ht}, special_code={$special_code}", LOG_DEBUG); if ($this->brouillon) { $this->db->begin(); // Clean parameters if (empty($qty)) { $qty = 0; } if (empty($fk_parent_line) || $fk_parent_line < 0) { $fk_parent_line = 0; } if (empty($special_code) || $special_code == 3) { $special_code = 0; } $remise_percent = price2num($remise_percent); $qty = price2num($qty); $pu = price2num($pu); $pa_ht = price2num($pa_ht); $txtva = price2num($txtva); $txlocaltax1 = price2num($txlocaltax1); $txlocaltax2 = price2num($txlocaltax2); // Check parameters if ($type < 0) { return -1; } // Calculate total with, without tax and tax from qty, pu, remise_percent and txtva // TRES IMPORTANT: C'est au moment de l'insertion ligne qu'on doit stocker // la part ht, tva et ttc, et ce au niveau de la ligne qui a son propre taux tva. $localtaxes_type = getLocalTaxesFromRate($txtva, 0, $this->thirdparty, $mysoc); $tabprice = calcul_price_total($qty, $pu, $remise_percent, $txtva, $txlocaltax1, $txlocaltax2, 0, $price_base_type, $info_bits, $type, $mysoc, $localtaxes_type); $total_ht = $tabprice[0]; $total_tva = $tabprice[1]; $total_ttc = $tabprice[2]; $total_localtax1 = $tabprice[9]; $total_localtax2 = $tabprice[10]; $pu_ht = $tabprice[3]; $pu_tva = $tabprice[4]; $pu_ttc = $tabprice[5]; // Update line into database $this->line = new FactureLigne($this->db); $this->line->context = $this->context; // Stock previous line records $staticline = new FactureLigne($this->db); $staticline->fetch($rowid); $this->line->oldline = $staticline; // Reorder if fk_parent_line change if (!empty($fk_parent_line) && !empty($staticline->fk_parent_line) && $fk_parent_line != $staticline->fk_parent_line) { $rangmax = $this->line_max($fk_parent_line); $this->line->rang = $rangmax + 1; } $this->line->rowid = $rowid; $this->line->label = $label; $this->line->desc = $desc; $this->line->qty = $this->type == self::TYPE_CREDIT_NOTE ? abs($qty) : $qty; // For credit note, quantity is always positive and unit price negative $this->line->tva_tx = $txtva; $this->line->localtax1_tx = $txlocaltax1; $this->line->localtax2_tx = $txlocaltax2; $this->line->localtax1_type = $localtaxes_type[0]; $this->line->localtax2_type = $localtaxes_type[2]; $this->line->remise_percent = $remise_percent; $this->line->subprice = $this->type == 2 ? -abs($pu_ht) : $pu_ht; // For credit note, unit price always negative, always positive otherwise $this->line->date_start = $date_start; $this->line->date_end = $date_end; $this->line->total_ht = $this->type == self::TYPE_CREDIT_NOTE || $qty < 0 ? -abs($total_ht) : $total_ht; // For credit note and if qty is negative, total is negative $this->line->total_tva = $this->type == self::TYPE_CREDIT_NOTE || $qty < 0 ? -abs($total_tva) : $total_tva; $this->line->total_localtax1 = $this->type == self::TYPE_CREDIT_NOTE || $qty < 0 ? -abs($total_localtax1) : $total_localtax1; $this->line->total_localtax2 = $this->type == self::TYPE_CREDIT_NOTE || $qty < 0 ? -abs($total_localtax2) : $total_localtax2; $this->line->total_ttc = $this->type == self::TYPE_CREDIT_NOTE || $qty < 0 ? -abs($total_ttc) : $total_ttc; $this->line->info_bits = $info_bits; $this->line->special_code = $special_code; $this->line->product_type = $type; $this->line->fk_parent_line = $fk_parent_line; $this->line->skip_update_total = $skip_update_total; // infos marge if (!empty($fk_product) && empty($fk_fournprice) && empty($pa_ht)) { // POS or external module, take lowest buying price include_once DOL_DOCUMENT_ROOT . '/fourn/class/fournisseur.product.class.php'; $productFournisseur = new ProductFournisseur($this->db); $productFournisseur->find_min_price_product_fournisseur($fk_product); $this->line->fk_fournprice = $productFournisseur->product_fourn_price_id; } else { $this->line->fk_fournprice = $fk_fournprice; } $this->line->pa_ht = $pa_ht; if (is_array($array_option) && count($array_option) > 0) { $this->line->array_options = $array_option; } $result = $this->line->update(); if ($result > 0) { // Reorder if child line if (!empty($fk_parent_line)) { $this->line_order(true, 'DESC'); } // Mise a jour info denormalisees au niveau facture $this->update_price(1); $this->db->commit(); return $result; } else { $this->error = $this->line->error; $this->db->rollback(); return -1; } } else { $this->error = "Invoice statut makes operation forbidden"; return -2; } }
/** * Update invoice line with percentage * * @param FactureLigne $line Invoice line * @param int $percent Percentage * @return void */ function update_percent($line, $percent) { include_once DOL_DOCUMENT_ROOT . '/core/lib/price.lib.php'; // Cap percentages to 100 if ($percent > 100) { $percent = 100; } $line->situation_percent = $percent; $tabprice = calcul_price_total($line->qty, $line->subprice, $line->remise_percent, $line->tva_tx, $line->localtax1_tx, $line->localtax2_tx, $line->product_type, 'HT', 0, 0, '', '', $percent); $line->total_ht = $tabprice[0]; $line->total_tva = $tabprice[1]; $line->total_ttc = $tabprice[2]; $line->total_localtax1 = $tabprice[9]; $line->total_localtax2 = $tabprice[10]; $line->update(); $this->update_price(1); $this->db->commit(); }
/** * \brief Update a line in database * \param rowid Id of line to update * \param desc Description de la ligne * \param pu Prix unitaire * \param qty Quantity * \param remise_percent Pourcentage de remise de la ligne * \param tva_tx Taux TVA * \param txlocaltax1 Local tax 1 rate * \param txlocaltax2 Local tax 2 rate * \param price_base_type HT or TTC * \param info_bits Miscellanous informations on line * \param date_start Start date of the line * \param date_end End date of the line * \param type Type of line (0=product, 1=service) * \return int < 0 si erreur, > 0 si ok */ function updateline($rowid, $desc, $pu, $qty, $remise_percent = 0, $txtva, $txlocaltax1 = 0, $txlocaltax2 = 0, $price_base_type = 'HT', $info_bits = 0, $date_start = '', $date_end = '', $type = 0, $fk_parent_line = 0, $skip_update_total = 0) { global $conf; dol_syslog("CustomerOrder::UpdateLine {$rowid}, {$desc}, {$pu}, {$qty}, {$remise_percent}, {$txtva}, {$txlocaltax1}, {$txlocaltax2}, {$price_base_type}, {$info_bits}, {$date_start}, {$date_end}, {$type}"); include_once DOL_DOCUMENT_ROOT . '/lib/price.lib.php'; if ($this->brouillon) { $this->db->begin(); // Clean parameters if (empty($qty)) { $qty = 0; } if (empty($info_bits)) { $info_bits = 0; } if (empty($txtva)) { $txtva = 0; } if (empty($txlocaltax1)) { $txlocaltax1 = 0; } if (empty($txlocaltax2)) { $txlocaltax2 = 0; } if (empty($remise)) { $remise = 0; } if (empty($remise_percent)) { $remise_percent = 0; } $remise_percent = price2num($remise_percent); $qty = price2num($qty); $pu = price2num($pu); $txtva = price2num($txtva); $txlocaltax1 = price2num($txtlocaltax1); $txlocaltax2 = price2num($txtlocaltax2); // Calcul du total TTC et de la TVA pour la ligne a partir de // qty, pu, remise_percent et txtva // TRES IMPORTANT: C'est au moment de l'insertion ligne qu'on doit stocker // la part ht, tva et ttc, et ce au niveau de la ligne qui a son propre taux tva. $tabprice = calcul_price_total($qty, $pu, $remise_percent, $txtva, $txlocaltax1, $txlocaltax2, 0, $price_base_type, $info_bits); $total_ht = $tabprice[0]; $total_tva = $tabprice[1]; $total_ttc = $tabprice[2]; $total_localtax1 = $tabprice[9]; $total_localtax2 = $tabprice[10]; // Anciens indicateurs: $price, $subprice, $remise (a ne plus utiliser) $price = $pu; $subprice = $pu; $remise = 0; if ($remise_percent > 0) { $remise = round($pu * $remise_percent / 100, 2); $price = $pu - $remise; } // Update line $this->line = new OrderLine($this->db); // Stock previous line records $staticline = new OrderLine($this->db); $staticline->fetch($rowid); $this->line->oldline = $staticline; $this->line->rowid = $rowid; $this->line->desc = $desc; $this->line->qty = $qty; $this->line->tva_tx = $txtva; $this->line->localtax1_tx = $txlocaltax1; $this->line->localtax2_tx = $txlocaltax2; $this->line->remise_percent = $remise_percent; $this->line->subprice = $subprice; $this->line->info_bits = $info_bits; $this->line->total_ht = $total_ht; $this->line->total_tva = $total_tva; $this->line->total_localtax1 = $total_localtax1; $this->line->total_localtax2 = $total_localtax2; $this->line->total_ttc = $total_ttc; $this->line->date_start = $date_start; $this->line->date_end = $date_end; $this->line->product_type = $type; $this->line->fk_parent_line = $fk_parent_line; $this->line->skip_update_total = $skip_update_total; // TODO deprecated $this->line->price = $price; $this->line->remise = $remise; $result = $this->line->update(); if ($result > 0) { // Mise a jour info denormalisees $this->update_price(1); $this->db->commit(); return $result; } else { $this->error = $this->db->error(); $this->db->rollback(); dol_syslog("CustomerOrder::UpdateLine Error=" . $this->error, LOG_ERR); return -1; } } else { $this->error = "CustomerOrder::Updateline Order status makes operation forbidden"; return -2; } }
/** * Add a product into cart * * @return void */ public function ajoutArticle() { global $conf, $db, $mysoc; $thirdpartyid = $_SESSION['CASHDESK_ID_THIRDPARTY']; $societe = new Societe($db); $societe->fetch($thirdpartyid); $product = new Product($db); $product->fetch($this->id); $sql = "SELECT taux"; $sql .= " FROM " . MAIN_DB_PREFIX . "c_tva"; $sql .= " WHERE rowid = " . $this->tva(); dol_syslog("ajoutArticle", LOG_DEBUG); $resql = $db->query($sql); if ($resql) { $obj = $db->fetch_object($resql); $vat_rate = $obj->taux; //var_dump($vat_rate);exit; } else { dol_print_error($db); } // Define part of HT, VAT, TTC $resultarray = calcul_price_total($this->qte, $this->prix(), $this->remisePercent(), $vat_rate, 0, 0, 0, 'HT', 0, $product->type, $mysoc); // Calcul du total ht sans remise $total_ht = $resultarray[0]; $total_vat = $resultarray[1]; $total_ttc = $resultarray[2]; // Calcul du montant de la remise if ($this->remisePercent()) { $remise_percent = $this->remisePercent(); } else { $remise_percent = 0; } $montant_remise_ht = $resultarray[6] - $resultarray[0]; $this->montantRemise($montant_remise_ht); $newcartarray = $_SESSION['poscart']; $i = count($newcartarray); $newcartarray[$i]['id'] = $i; $newcartarray[$i]['ref'] = $product->ref; $newcartarray[$i]['label'] = $product->label; $newcartarray[$i]['price'] = $product->price; $newcartarray[$i]['price_ttc'] = $product->price_ttc; if (!empty($conf->global->PRODUIT_MULTIPRICES)) { if (isset($product->multiprices[$societe->price_level])) { $newcartarray[$i]['price'] = $product->multiprices[$societe->price_level]; $newcartarray[$i]['price_ttc'] = $product->multiprices_ttc[$societe->price_level]; } } $newcartarray[$i]['fk_article'] = $this->id; $newcartarray[$i]['qte'] = $this->qte(); $newcartarray[$i]['fk_tva'] = $this->tva(); $newcartarray[$i]['remise_percent'] = $remise_percent; $newcartarray[$i]['remise'] = price2num($montant_remise_ht); $newcartarray[$i]['total_ht'] = price2num($total_ht, 'MT'); $newcartarray[$i]['total_ttc'] = price2num($total_ttc, 'MT'); $_SESSION['poscart'] = $newcartarray; $this->raz(); }
/** * Update a proposal line * * @param int $rowid Id de la ligne * @param float $pu Prix unitaire (HT ou TTC selon price_base_type) * @param float $qty Quantity * @param float $remise_percent Remise effectuee sur le produit * @param float $txtva Taux de TVA * @param float $txlocaltax1 Local tax 1 rate * @param float $txlocaltax2 Local tax 2 rate * @param string $desc Description * @param string $price_base_type HT ou TTC * @param int $info_bits Miscellaneous informations * @param int $special_code Special code (also used by externals modules!) * @param int $fk_parent_line Id of parent line (0 in most cases, used by modules adding sublevels into lines). * @param int $skip_update_total Keep fields total_xxx to 0 (used for special lines by some modules) * @param int $fk_fournprice Id of origin supplier price * @param int $pa_ht Price (without tax) of product when it was bought * @param string $label ??? * @param int $type 0/1=Product/service * @param int $date_start Start date of the line * @param int $date_end End date of the line * @param array $array_option extrafields array * @return int 0 if OK, <0 if KO */ function updateline($rowid, $pu, $qty, $remise_percent, $txtva, $txlocaltax1 = 0.0, $txlocaltax2 = 0.0, $desc = '', $price_base_type = 'HT', $info_bits = 0, $special_code = 0, $fk_parent_line = 0, $skip_update_total = 0, $fk_fournprice = 0, $pa_ht = 0, $label = '', $type = 0, $date_start = '', $date_end = '', $array_option = 0) { global $mysoc; dol_syslog(get_class($this) . "::updateLine rowid={$rowid}, pu={$pu}, qty={$qty}, remise_percent={$remise_percent}, txtva={$txtva}, desc={$desc}, price_base_type={$price_base_type}, info_bits={$info_bits}, special_code={$special_code}, fk_parent_line={$fk_parent_line}, pa_ht={$a_ht}, type={$type}, date_start={$date_start}, date_end={$date_end}"); include_once DOL_DOCUMENT_ROOT . '/core/lib/price.lib.php'; // Clean parameters $remise_percent = price2num($remise_percent); $qty = price2num($qty); $pu = price2num($pu); $txtva = price2num($txtva); $txlocaltax1 = price2num($txlocaltax1); $txlocaltax2 = price2num($txlocaltax2); $pa_ht = price2num($pa_ht); if (empty($qty) && empty($special_code)) { $special_code = 3; } // Set option tag if (!empty($qty) && $special_code == 3) { $special_code = 0; } // Remove option tag if ($this->statut == 0) { $this->db->begin(); // Calcul du total TTC et de la TVA pour la ligne a partir de // qty, pu, remise_percent et txtva // TRES IMPORTANT: C'est au moment de l'insertion ligne qu'on doit stocker // la part ht, tva et ttc, et ce au niveau de la ligne qui a son propre taux tva. $localtaxes_type = getLocalTaxesFromRate($txtva, 0, $this->thirdparty, $mysoc); $tabprice = calcul_price_total($qty, $pu, $remise_percent, $txtva, $txlocaltax1, $txlocaltax2, 0, $price_base_type, $info_bits, $type, $mysoc, $localtaxes_type); $total_ht = $tabprice[0]; $total_tva = $tabprice[1]; $total_ttc = $tabprice[2]; $total_localtax1 = $tabprice[9]; $total_localtax2 = $tabprice[10]; // Anciens indicateurs: $price, $remise (a ne plus utiliser) $price = $pu; if ($remise_percent > 0) { $remise = round($pu * $remise_percent / 100, 2); $price = $pu - $remise; } // Update line $this->line = new PropaleLigne($this->db); $this->line->context = $this->context; // Stock previous line records $staticline = new PropaleLigne($this->db); $staticline->fetch($rowid); $this->line->oldline = $staticline; // Reorder if fk_parent_line change if (!empty($fk_parent_line) && !empty($staticline->fk_parent_line) && $fk_parent_line != $staticline->fk_parent_line) { $rangmax = $this->line_max($fk_parent_line); $this->line->rang = $rangmax + 1; } $this->line->rowid = $rowid; $this->line->label = $label; $this->line->desc = $desc; $this->line->qty = $qty; $this->line->product_type = $type; $this->line->tva_tx = $txtva; $this->line->localtax1_tx = $txlocaltax1; $this->line->localtax2_tx = $txlocaltax2; $this->line->localtax1_type = $localtaxes_type[0]; $this->line->localtax2_type = $localtaxes_type[2]; $this->line->remise_percent = $remise_percent; $this->line->subprice = $pu; $this->line->info_bits = $info_bits; $this->line->total_ht = $total_ht; $this->line->total_tva = $total_tva; $this->line->total_localtax1 = $total_localtax1; $this->line->total_localtax2 = $total_localtax2; $this->line->total_ttc = $total_ttc; $this->line->special_code = $special_code; $this->line->fk_parent_line = $fk_parent_line; $this->line->skip_update_total = $skip_update_total; // infos marge if (!empty($fk_product) && empty($fk_fournprice) && empty($pa_ht)) { // by external module, take lowest buying price include_once DOL_DOCUMENT_ROOT . '/fourn/class/fournisseur.product.class.php'; $productFournisseur = new ProductFournisseur($this->db); $productFournisseur->find_min_price_product_fournisseur($fk_product); $this->line->fk_fournprice = $productFournisseur->product_fourn_price_id; } else { $this->line->fk_fournprice = $fk_fournprice; } $this->line->pa_ht = $pa_ht; $this->line->date_start = $date_start; $this->line->date_end = $date_end; // TODO deprecated $this->line->price = $price; $this->line->remise = $remise; if (is_array($array_option) && count($array_option) > 0) { $this->line->array_options = $array_option; } $result = $this->line->update(); if ($result > 0) { // Reorder if child line if (!empty($fk_parent_line)) { $this->line_order(true, 'DESC'); } $this->update_price(1); $this->fk_propal = $this->id; $this->rowid = $rowid; $this->db->commit(); return $result; } else { $this->error = $this->line->error; $this->db->rollback(); return -1; } } else { dol_syslog(get_class($this) . "::updateline Erreur -2 Propal en mode incompatible pour cette action"); return -2; } }
/** * Update line * * @param int $rowid Id de la ligne de facture * @param string $desc Description de la ligne * @param double $pu Prix unitaire * @param double $qty Quantity * @param double $remise_percent Pourcentage de remise de la ligne * @param double $txtva Taux TVA * @param double $txlocaltax1 Localtax1 tax * @param double $txlocaltax2 Localtax2 tax * @param double $price_base_type Type of price base * @param int $info_bits Miscellaneous informations * @param int $type Type of line (0=product, 1=service) * @param int $notrigger Disable triggers * @param timestamp $date_start Date start of service * @param timestamp $date_end Date end of service * @param array $array_options Extrafields array * @param string $fk_unit Code of the unit to use. Null to use the default one * @return int < 0 if error, > 0 if ok */ function updateline($rowid, $desc, $pu, $qty, $remise_percent, $txtva, $txlocaltax1 = 0, $txlocaltax2 = 0, $price_base_type = 'HT', $info_bits = 0, $type = 0, $notrigger = false, $date_start = '', $date_end = '', $array_options = 0, $fk_unit = null) { global $mysoc; dol_syslog(get_class($this) . "::updateline {$rowid}, {$desc}, {$pu}, {$qty}, {$remise_percent}, {$txtva}, {$price_base_type}, {$info_bits}, {$type}, {$fk_unit}"); include_once DOL_DOCUMENT_ROOT . '/core/lib/price.lib.php'; if ($this->brouillon) { $this->db->begin(); // Clean parameters if (empty($qty)) { $qty = 0; } if (empty($info_bits)) { $info_bits = 0; } if (empty($txtva)) { $txtva = 0; } if (empty($txlocaltax1)) { $txlocaltax1 = 0; } if (empty($txlocaltax2)) { $txlocaltax2 = 0; } if (empty($remise)) { $remise = 0; } if (empty($remise_percent)) { $remise_percent = 0; } $remise_percent = price2num($remise_percent); $qty = price2num($qty); if (!$qty) { $qty = 1; } $pu = price2num($pu); $txtva = price2num($txtva); $txlocaltax1 = price2num($txlocaltax1); $txlocaltax2 = price2num($txlocaltax2); // Check parameters if ($type < 0) { return -1; } // Calcul du total TTC et de la TVA pour la ligne a partir de // qty, pu, remise_percent et txtva // TRES IMPORTANT: C'est au moment de l'insertion ligne qu'on doit stocker // la part ht, tva et ttc, et ce au niveau de la ligne qui a son propre taux tva. $localtaxes_type = getLocalTaxesFromRate($txtva, 0, $mysoc, $this->thirdparty); $txtva = preg_replace('/\\s*\\(.*\\)/', '', $txtva); // Remove code into vatrate. $tabprice = calcul_price_total($qty, $pu, $remise_percent, $txtva, $txlocaltax1, $txlocaltax2, 0, $price_base_type, $info_bits, $type, $this->thirdparty, $localtaxes_type); $total_ht = $tabprice[0]; $total_tva = $tabprice[1]; $total_ttc = $tabprice[2]; $total_localtax1 = $tabprice[9]; $total_localtax2 = $tabprice[10]; $localtax1_type = $localtaxes_type[0]; $localtax2_type = $localtaxes_type[2]; $subprice = price2num($pu, 'MU'); // Mise a jour ligne en base $sql = "UPDATE " . MAIN_DB_PREFIX . "commande_fournisseurdet SET"; $sql .= " description='" . $this->db->escape($desc) . "'"; $sql .= ",subprice='" . price2num($subprice) . "'"; //$sql.= ",remise='".price2num($remise)."'"; $sql .= ",remise_percent='" . price2num($remise_percent) . "'"; $sql .= ",tva_tx='" . price2num($txtva) . "'"; $sql .= ",localtax1_tx='" . price2num($txlocaltax1) . "'"; $sql .= ",localtax2_tx='" . price2num($txlocaltax2) . "'"; $sql .= ",localtax1_type='" . $localtax1_type . "'"; $sql .= ",localtax2_type='" . $localtax2_type . "'"; $sql .= ",qty='" . price2num($qty) . "'"; $sql .= ",date_start=" . (!empty($date_start) ? "'" . $this->db->idate($date_start) . "'" : "null"); $sql .= ",date_end=" . (!empty($date_end) ? "'" . $this->db->idate($date_end) . "'" : "null"); $sql .= ",info_bits='" . $info_bits . "'"; $sql .= ",total_ht='" . price2num($total_ht) . "'"; $sql .= ",total_tva='" . price2num($total_tva) . "'"; $sql .= ",total_localtax1='" . price2num($total_localtax1) . "'"; $sql .= ",total_localtax2='" . price2num($total_localtax2) . "'"; $sql .= ",total_ttc='" . price2num($total_ttc) . "'"; $sql .= ",product_type=" . $type; $sql .= $fk_unit ? ",fk_unit='" . $this->db->escape($fk_unit) . "'" : ", fk_unit=null"; $sql .= " WHERE rowid = " . $rowid; dol_syslog(get_class($this) . "::updateline", LOG_DEBUG); $result = $this->db->query($sql); if ($result > 0) { $this->rowid = $rowid; if (empty($conf->global->MAIN_EXTRAFIELDS_DISABLED)) { $tmpline = new CommandeFournisseurLigne($this->db); $tmpline->id = $this->rowid; $tmpline->array_options = $array_options; $result = $tmpline->insertExtraFields(); if ($result < 0) { $error++; } } if (!$error && !$notrigger) { global $conf, $langs, $user; // Call trigger $result = $this->call_trigger('LINEORDER_SUPPLIER_UPDATE', $user); if ($result < 0) { $this->db->rollback(); return -1; } // End call triggers } // Mise a jour info denormalisees au niveau facture if (!$error) { $this->update_price('', 'auto'); } if (!$error) { $this->db->commit(); return $result; } else { $this->db->rollback(); return -1; } } else { $this->error = $this->db->lasterror(); $this->db->rollback(); return -1; } } else { $this->error = "Order status makes operation forbidden"; dol_syslog(get_class($this) . "::updateline " . $this->error, LOG_ERR); return -2; } }
public static function calculePrice($product) { global $db, $mysoc; require_once DOL_DOCUMENT_ROOT . "/core/lib/price.lib.php"; $qty = $product["cant"]; if ($product["price_base_type"] == "HT") { $pu = $product["price"]; } else { $pu = $product["price_ttc"]; } $remise_percent_ligne = $product["discount"] ? $product["discount"] : 0; $txtva = $product["tva_tx"]; $uselocaltax1_rate = $product["localtax1_tx"] > 0 ? $product["localtax1_tx"] : 0; $uselocaltax2_rate = $product["localtax2_tx"] > 0 ? $product["localtax2_tx"] : 0; $remise_percent_global = $product["remise_percent_global"] ? $product["remise_percent_global"] : 0; $price_base_type = $product["price_base_type"]; $type = $product["fk_product_type"] ? $product["fk_product_type"] : 0; $info_bits = 0; $remise_percent_ligne = $remise_percent_global + $remise_percent_ligne; $remise_percent_global = 0; $localtaxes_type = getLocalTaxesFromRate($txtva, 0, $mysoc); $tabprice = calcul_price_total($qty, $pu, $remise_percent_ligne, $txtva, $uselocaltax1_rate, $uselocaltax2_rate, $remise_percent_global, $price_base_type, $info_bits, $type, $mysoc, $localtaxes_type); $result["total_ht"] = $tabprice[0]; $result["total_tva"] = $tabprice[1]; $result["total_ttc"] = $tabprice[2]; $result["total_localtax1"] = $tabprice[9]; $result["total_localtax2"] = $tabprice[10]; $result["pu_ht"] = $tabprice[3]; $result["pu_tva"] = $tabprice[4]; $result["pu_ttc"] = $tabprice[5]; $result["total_ttc_without_discount"] = $tabprice[8]; return $result; }
/** * Update a line detail into database * @param id Id of line invoice * @param label Description of line * @param pu Prix unitaire (HT ou TTC selon price_base_type) * @param vatrate VAT Rate * @param txlocaltax1 LocalTax1 Rate * @param txlocaltax2 LocalTax2 Rate * @param qty Quantity * @param idproduct Id produit * @param price_base_type HT or TTC * @param info_bits Miscellanous informations of line * @param type Type of line (0=product, 1=service) * @return int <0 if KO, >0 if OK */ function updateline($id, $label, $pu, $vatrate, $txlocaltax1=0, $txlocaltax2=0, $qty=1, $idproduct=0, $price_base_type='HT', $info_bits=0, $type=0) { include_once(DOL_DOCUMENT_ROOT.'/lib/price.lib.php'); $pu = price2num($pu); $qty = price2num($qty); // Check parameters if (! is_numeric($pu) || ! is_numeric($qty)) return -1; if ($type < 0) return -1; // Clean parameters if (empty($txlocaltax1)) $txlocaltax1=0; if (empty($txlocaltax2)) $txlocaltax2=0; $txlocaltax1=price2num($txlocaltax1); $txlocaltax2=price2num($txlocaltax2); // Calcul du total TTC et de la TVA pour la ligne a partir de // qty, pu, remise_percent et txtva // TRES IMPORTANT: C'est au moment de l'insertion ligne qu'on doit stocker // la part ht, tva et ttc, et ce au niveau de la ligne qui a son propre taux tva. $tabprice = calcul_price_total($qty, $pu, 0, $vatrate, $txlocaltax1, $txlocaltax2, 0, $price_base_type, $info_bits); $total_ht = $tabprice[0]; $total_tva = $tabprice[1]; $total_ttc = $tabprice[2]; $pu_ht = $tabprice[3]; $pu_tva = $tabprice[4]; $pu_ttc = $tabprice[5]; $total_localtax1 = $tabprice[9]; $total_localtax2 = $tabprice[10]; if ($idproduct) { $product=new Product($this->db); $result=$product->fetch($idproduct); $product_type = $product->type; } else { $product_type = $type; } $sql = "UPDATE ".MAIN_DB_PREFIX."facture_fourn_det SET"; $sql.= " description ='".$this->db->escape($label)."'"; $sql.= ", pu_ht = ".price2num($pu_ht); $sql.= ", pu_ttc = ".price2num($pu_ttc); $sql.= ", qty = ".price2num($qty); $sql.= ", tva_tx = ".price2num($vatrate); $sql.= ", localtax1_tx = ".price2num($txlocaltax1); $sql.= ", localtax2_tx = ".price2num($txlocaltax2); $sql.= ", total_ht = ".price2num($total_ht); $sql.= ", tva= ".price2num($total_tva); $sql.= ", total_localtax1= ".price2num($total_localtax1); $sql.= ", total_localtax2= ".price2num($total_localtax2); $sql.= ", total_ttc = ".price2num($total_ttc); if ($idproduct) $sql.= ", fk_product = ".$idproduct; else $sql.= ", fk_product = null"; $sql.= ", product_type = ".$product_type; $sql.= " WHERE rowid = ".$id; dol_syslog("Fournisseur.facture::updateline sql=".$sql); $resql=$this->db->query($sql); if ($resql) { // Update total price into invoice record $result=$this->update_price(); return $result; } else { $this->error=$this->db->lasterror(); dol_syslog("Fournisseur.facture::updateline error=".$this->error, LOG_ERR); return -1; } }
/** * Update database for contract line * * @param User $user User that modify * @param int $notrigger 0=no, 1=yes (no update trigger) * @return int <0 if KO, >0 if OK */ function update($user, $notrigger = 0) { global $conf, $langs; $error = 0; // Clean parameters $this->fk_contrat = trim($this->fk_contrat); $this->fk_product = trim($this->fk_product); $this->statut = trim($this->statut); $this->label = trim($this->label); $this->description = trim($this->description); $this->tva_tx = trim($this->tva_tx); $this->localtax1_tx = trim($this->localtax1_tx); $this->localtax2_tx = trim($this->localtax2_tx); $this->qty = trim($this->qty); $this->remise_percent = trim($this->remise_percent); $this->remise = trim($this->remise); $this->fk_remise_except = trim($this->fk_remise_except); $this->subprice = price2num($this->subprice); $this->price_ht = price2num($this->price_ht); $this->total_ht = trim($this->total_ht); $this->total_tva = trim($this->total_tva); $this->total_localtax1 = trim($this->total_localtax1); $this->total_localtax2 = trim($this->total_localtax2); $this->total_ttc = trim($this->total_ttc); $this->info_bits = trim($this->info_bits); $this->fk_user_author = trim($this->fk_user_author); $this->fk_user_ouverture = trim($this->fk_user_ouverture); $this->fk_user_cloture = trim($this->fk_user_cloture); $this->commentaire = trim($this->commentaire); // Check parameters // Put here code to add control on parameters values // Calcul du total TTC et de la TVA pour la ligne a partir de // qty, pu, remise_percent et txtva // TRES IMPORTANT: C'est au moment de l'insertion ligne qu'on doit stocker // la part ht, tva et ttc, et ce au niveau de la ligne qui a son propre taux tva. $tabprice = calcul_price_total($this->qty, $this->price_ht, $this->remise_percent, $this->tva_tx, $this->localtax1_tx, $this->localtax2_tx, 0, 'HT', 0); $this->total_ht = $tabprice[0]; $this->total_tva = $tabprice[1]; $this->total_ttc = $tabprice[2]; $this->total_localtax1 = $tabprice[9]; $this->total_localtax2 = $tabprice[10]; // Update request $sql = "UPDATE " . MAIN_DB_PREFIX . "contratdet SET"; $sql .= " fk_contrat='" . $this->fk_contrat . "',"; $sql .= " fk_product=" . ($this->fk_product ? "'" . $this->fk_product . "'" : 'null') . ","; $sql .= " statut='" . $this->statut . "',"; $sql .= " label='" . $this->db->escape($this->label) . "',"; $sql .= " description='" . $this->db->escape($this->description) . "',"; $sql .= " date_commande=" . ($this->date_commande != '' ? "'" . $this->db->idate($this->date_commande) . "'" : "null") . ","; $sql .= " date_ouverture_prevue=" . ($this->date_ouverture_prevue != '' ? "'" . $this->db->idate($this->date_ouverture_prevue) . "'" : "null") . ","; $sql .= " date_ouverture=" . ($this->date_ouverture != '' ? "'" . $this->db->idate($this->date_ouverture) . "'" : "null") . ","; $sql .= " date_fin_validite=" . ($this->date_fin_validite != '' ? "'" . $this->db->idate($this->date_fin_validite) . "'" : "null") . ","; $sql .= " date_cloture=" . ($this->date_cloture != '' ? "'" . $this->db->idate($this->date_cloture) . "'" : "null") . ","; $sql .= " tva_tx='" . $this->tva_tx . "',"; $sql .= " localtax1_tx='" . $this->localtax1_tx . "',"; $sql .= " localtax2_tx='" . $this->localtax2_tx . "',"; $sql .= " qty='" . $this->qty . "',"; $sql .= " remise_percent='" . $this->remise_percent . "',"; $sql .= " remise=" . ($this->remise ? "'" . $this->remise . "'" : "null") . ","; $sql .= " fk_remise_except=" . ($this->fk_remise_except ? "'" . $this->fk_remise_except . "'" : "null") . ","; $sql .= " subprice='" . $this->subprice . "',"; $sql .= " price_ht='" . $this->price_ht . "',"; $sql .= " total_ht='" . $this->total_ht . "',"; $sql .= " total_tva='" . $this->total_tva . "',"; $sql .= " total_localtax1='" . $this->total_localtax1 . "',"; $sql .= " total_localtax2='" . $this->total_localtax2 . "',"; $sql .= " total_ttc='" . $this->total_ttc . "',"; $sql .= " info_bits='" . $this->info_bits . "',"; $sql .= " fk_user_author=" . ($this->fk_user_author >= 0 ? $this->fk_user_author : "NULL") . ","; $sql .= " fk_user_ouverture=" . ($this->fk_user_ouverture > 0 ? $this->fk_user_ouverture : "NULL") . ","; $sql .= " fk_user_cloture=" . ($this->fk_user_cloture > 0 ? $this->fk_user_cloture : "NULL") . ","; $sql .= " commentaire='" . $this->db->escape($this->commentaire) . "'"; $sql .= " WHERE rowid=" . $this->id; dol_syslog(get_class($this) . "::update sql=" . $sql, LOG_DEBUG); $resql = $this->db->query($sql); if ($resql) { $contrat = new Contrat($this->db); $contrat->fetch($this->fk_contrat); $result = $contrat->update_statut($user); } else { $this->error = "Error " . $this->db->lasterror(); dol_syslog(get_class($this) . "::update " . $this->error, LOG_ERR); return -1; } if (!$notrigger) { // Appel des triggers include_once DOL_DOCUMENT_ROOT . "/core/class/interfaces.class.php"; $interface = new Interfaces($this->db); $result = $interface->run_triggers('MYOBJECT_MODIFY', $this, $user, $langs, $conf); if ($result < 0) { $error++; $this->errors = $interface->errors; } // Fin appel triggers } return 1; }
/** * Update line * * @param int $rowid Id de la ligne de facture * @param string $desc Description de la ligne * @param double $pu Prix unitaire * @param double $qty Quantity * @param double $remise_percent Pourcentage de remise de la ligne * @param double $txtva Taux TVA * @param double $txlocaltax1 Localtax1 tax * @param double $txlocaltax2 Localtax2 tax * @param double $price_base_type Type of price base * @param int $info_bits Miscellaneous informations * @param int $type Type of line (0=product, 1=service) * @param int $notrigger Disable triggers * @return int < 0 if error, > 0 if ok */ function updateline($rowid, $desc, $pu, $qty, $remise_percent, $txtva, $txlocaltax1 = 0, $txlocaltax2 = 0, $price_base_type = 'HT', $info_bits = 0, $type = 0, $notrigger = false) { dol_syslog(get_class($this) . "::updateline {$rowid}, {$desc}, {$pu}, {$qty}, {$remise_percent}, {$txtva}, {$price_base_type}, {$info_bits}, {$type}"); include_once DOL_DOCUMENT_ROOT . '/core/lib/price.lib.php'; if ($this->brouillon) { $this->db->begin(); // Clean parameters if (empty($qty)) { $qty = 0; } if (empty($info_bits)) { $info_bits = 0; } if (empty($txtva)) { $txtva = 0; } if (empty($txlocaltax1)) { $txlocaltax1 = 0; } if (empty($txlocaltax2)) { $txlocaltax2 = 0; } if (empty($remise)) { $remise = 0; } if (empty($remise_percent)) { $remise_percent = 0; } $remise_percent = price2num($remise_percent); $qty = price2num($qty); if (!$qty) { $qty = 1; } $pu = price2num($pu); $txtva = price2num($txtva); $txlocaltax1 = price2num($txlocaltax1); $txlocaltax2 = price2num($txlocaltax2); // Check parameters if ($type < 0) { return -1; } // Calcul du total TTC et de la TVA pour la ligne a partir de // qty, pu, remise_percent et txtva // TRES IMPORTANT: C'est au moment de l'insertion ligne qu'on doit stocker // la part ht, tva et ttc, et ce au niveau de la ligne qui a son propre taux tva. $localtaxes_type = getLocalTaxesFromRate($txtva, 0, $this->thirdparty); $tabprice = calcul_price_total($qty, $pu, $remise_percent, $txtva, $txlocaltax1, $txlocaltax2, 0, $price_base_type, $info_bits, $type, $this->thirdparty, $localtaxes_type); $total_ht = $tabprice[0]; $total_tva = $tabprice[1]; $total_ttc = $tabprice[2]; $total_localtax1 = $tabprice[9]; $total_localtax2 = $tabprice[10]; $localtax1_type = $localtaxes_type[0]; $localtax2_type = $localtaxes_type[2]; $subprice = price2num($pu, 'MU'); // Mise a jour ligne en base $sql = "UPDATE " . MAIN_DB_PREFIX . "commande_fournisseurdet SET"; $sql .= " description='" . $this->db->escape($desc) . "'"; $sql .= ",subprice='" . price2num($subprice) . "'"; //$sql.= ",remise='".price2num($remise)."'"; $sql .= ",remise_percent='" . price2num($remise_percent) . "'"; $sql .= ",tva_tx='" . price2num($txtva) . "'"; $sql .= ",localtax1_tx='" . price2num($txlocaltax1) . "'"; $sql .= ",localtax2_tx='" . price2num($txlocaltax2) . "'"; $sql .= ",localtax1_type='" . $localtax1_type . "'"; $sql .= ",localtax2_type='" . $localtax2_type . "'"; $sql .= ",qty='" . price2num($qty) . "'"; /*if ($date_end) { $sql.= ",date_start='$date_end'"; } else { $sql.=',date_start=null'; } if ($date_end) { $sql.= ",date_end='$date_end'"; } else { $sql.=',date_end=null'; }*/ $sql .= ",info_bits='" . $info_bits . "'"; $sql .= ",total_ht='" . price2num($total_ht) . "'"; $sql .= ",total_tva='" . price2num($total_tva) . "'"; $sql .= ",total_localtax1='" . price2num($total_localtax1) . "'"; $sql .= ",total_localtax2='" . price2num($total_localtax2) . "'"; $sql .= ",total_ttc='" . price2num($total_ttc) . "'"; $sql .= ",product_type=" . $type; $sql .= " WHERE rowid = " . $rowid; dol_syslog(get_class($this) . "::updateline sql=" . $sql); $result = $this->db->query($sql); if ($result > 0) { $this->rowid = $rowid; if (!$notrigger) { global $conf, $langs, $user; // Appel des triggers include_once DOL_DOCUMENT_ROOT . '/core/class/interfaces.class.php'; $interface = new Interfaces($this->db); $result = $interface->run_triggers('LINEORDER_SUPPLIER_UPDATE', $this, $user, $langs, $conf); if ($result < 0) { $error++; $this->errors = $interface->errors; $this->db->rollback(); return -1; } // Fin appel triggers } // Mise a jour info denormalisees au niveau facture $this->update_price('', 'auto'); $this->db->commit(); return $result; } else { $this->error = $this->db->error(); dol_syslog(get_class($this) . "::updateline " . $this->error, LOG_ERR); $this->db->rollback(); return -1; } } else { $this->error = "Order status makes operation forbidden"; dol_syslog(get_class($this) . "::updateline " . $this->error, LOG_ERR); return -2; } }
/** * Mise a jour des totaux lignes de commande fournisseur * * @param DoliDB $db Database handler * @param Translate $langs Object langs * @param Conf $conf Object conf * @return void */ function migrate_price_commande_fournisseur($db, $langs, $conf) { $db->begin(); print '<tr><td colspan="4">'; print '<br>'; print '<b>' . $langs->trans('MigrationSupplierOrder') . "</b><br>\n"; // Liste des lignes commande non a jour $sql = "SELECT cd.rowid, cd.qty, cd.subprice, cd.remise_percent, cd.tva_tx as tva_taux, cd.info_bits,"; $sql .= " c.rowid as commandeid, c.remise_percent as remise_percent_global"; $sql .= " FROM " . MAIN_DB_PREFIX . "commande_fournisseurdet as cd, " . MAIN_DB_PREFIX . "commande_fournisseur as c"; $sql .= " WHERE cd.fk_commande = c.rowid"; $sql .= " AND ((cd.total_ttc = 0 AND cd.remise_percent != 100) or cd.total_ttc IS NULL)"; dolibarr_install_syslog("upgrade2::migrate_price_commande_fournisseur", LOG_DEBUG); $resql = $db->query($sql); if ($resql) { $num = $db->num_rows($resql); $i = 0; if ($num) { while ($i < $num) { $obj = $db->fetch_object($resql); $rowid = $obj->rowid; $qty = $obj->qty; $pu = $obj->subprice; $txtva = $obj->tva_taux; $remise_percent = $obj->remise_percent; $remise_percent_global = $obj->remise_percent_global; $info_bits = $obj->info_bits; // On met a jour les 3 nouveaux champs $commandeligne = new CommandeFournisseurLigne($db); $commandeligne->fetch($rowid); $result = calcul_price_total($qty, $pu, $remise_percent, $txtva, 0, 0, $remise_percent_global, 'HT', $info_bits, 0); $total_ht = $result[0]; $total_tva = $result[1]; $total_ttc = $result[2]; $commandeligne->total_ht = $total_ht; $commandeligne->total_tva = $total_tva; $commandeligne->total_ttc = $total_ttc; dolibarr_install_syslog("upgrade2: Line {$rowid}: commandeid={$obj->rowid} pu={$pu} qty={$qty} tva_taux={$txtva} remise_percent={$remise_percent} remise_global={$remise_percent_global} -> {$total_ht}, {$total_tva}, {$total_ttc}"); print ". "; $commandeligne->update_total(); /* On touche pas a facture mere $commande = new Commande($db); $commande->id = $obj->rowid; if ( $commande->fetch($commande->id) >= 0 ) { if ( $commande->update_price() > 0 ) { print ". "; } else { print "Error id=".$commande->id; } } else { print "Error #3"; } */ $i++; } } else { print $langs->trans("AlreadyDone"); } $db->free($resql); /* $sql = "DELETE FROM ".MAIN_DB_PREFIX."commande_fournisseurdet"; $sql.= " WHERE subprice = 0 and total_ttc = 0 and total_tva = 0 and total_ht = 0"; $resql=$db->query($sql); if (! $resql) { dol_print_error($db); } */ $db->commit(); } else { print "Error #1 " . $db->error(); $db->rollback(); } print '<br>'; print '</td></tr>'; }
/** * Update a line detail into database * * @param int $id Id of line invoice * @param string $desc Description of line * @param double $pu Prix unitaire (HT ou TTC selon price_base_type) * @param double $vatrate VAT Rate * @param double $txlocaltax1 LocalTax1 Rate * @param double $txlocaltax2 LocalTax2 Rate * @param double $qty Quantity * @param int $idproduct Id produit * @param double $price_base_type HT or TTC * @param int $info_bits Miscellaneous informations of line * @param int $type Type of line (0=product, 1=service) * @param double $remise_percent Pourcentage de remise de la ligne * @param int $notrigger Disable triggers * @return int <0 if KO, >0 if OK */ function updateline($id, $desc, $pu, $vatrate, $txlocaltax1 = 0, $txlocaltax2 = 0, $qty = 1, $idproduct = 0, $price_base_type = 'HT', $info_bits = 0, $type = 0, $remise_percent = 0, $notrigger = false) { dol_syslog(get_class($this) . "::updateline {$id},{$desc},{$pu},{$vatrate},{$qty},{$idproduct},{$price_base_type},{$info_bits},{$type},{$remise_percent}", LOG_DEBUG); include_once DOL_DOCUMENT_ROOT . '/core/lib/price.lib.php'; $pu = price2num($pu); $qty = price2num($qty); $remise_percent = price2num($remise_percent); // Check parameters if (!is_numeric($pu) || !is_numeric($qty)) { return -1; } if ($type < 0) { return -1; } // Clean parameters if (empty($vatrate)) { $vatrate = 0; } if (empty($txlocaltax1)) { $txlocaltax1 = 0; } if (empty($txlocaltax2)) { $txlocaltax2 = 0; } $txlocaltax1 = price2num($txlocaltax1); $txlocaltax2 = price2num($txlocaltax2); // Calcul du total TTC et de la TVA pour la ligne a partir de // qty, pu, remise_percent et txtva // TRES IMPORTANT: C'est au moment de l'insertion ligne qu'on doit stocker // la part ht, tva et ttc, et ce au niveau de la ligne qui a son propre taux tva. $localtaxes_type = getLocalTaxesFromRate($vatrate, 0, $this->thirdparty); $tabprice = calcul_price_total($qty, $pu, $remise_percent, $vatrate, $txlocaltax1, $txlocaltax2, 0, $price_base_type, $info_bits, $type, $this->thirdparty, $localtaxes_type); $total_ht = $tabprice[0]; $total_tva = $tabprice[1]; $total_ttc = $tabprice[2]; $pu_ht = $tabprice[3]; $pu_tva = $tabprice[4]; $pu_ttc = $tabprice[5]; $total_localtax1 = $tabprice[9]; $total_localtax2 = $tabprice[10]; if (empty($info_bits)) { $info_bits = 0; } if ($idproduct) { $product = new Product($this->db); $result = $product->fetch($idproduct); $product_type = $product->type; } else { $product_type = $type; } $this->db->begin(); $sql = "UPDATE " . MAIN_DB_PREFIX . "facture_fourn_det SET"; $sql .= " description ='" . $this->db->escape($desc) . "'"; $sql .= ", pu_ht = " . price2num($pu_ht); $sql .= ", pu_ttc = " . price2num($pu_ttc); $sql .= ", qty = " . price2num($qty); $sql .= ", remise_percent = " . price2num($remise_percent); $sql .= ", tva_tx = " . price2num($vatrate); $sql .= ", localtax1_tx = " . price2num($txlocaltax1); $sql .= ", localtax2_tx = " . price2num($txlocaltax2); $sql .= ", localtax1_type = '" . $localtaxes_type[0] . "'"; $sql .= ", localtax2_type = '" . $localtaxes_type[2] . "'"; $sql .= ", total_ht = " . price2num($total_ht); $sql .= ", tva= " . price2num($total_tva); $sql .= ", total_localtax1= " . price2num($total_localtax1); $sql .= ", total_localtax2= " . price2num($total_localtax2); $sql .= ", total_ttc = " . price2num($total_ttc); if ($idproduct) { $sql .= ", fk_product = " . $idproduct; } else { $sql .= ", fk_product = null"; } $sql .= ", product_type = " . $product_type; $sql .= ", info_bits = " . $info_bits; $sql .= " WHERE rowid = " . $id; dol_syslog(get_class($this) . "::updateline sql=" . $sql); $resql = $this->db->query($sql); if ($resql) { $this->rowid = $id; if (!$notrigger) { global $conf, $langs, $user; // Appel des triggers include_once DOL_DOCUMENT_ROOT . '/core/class/interfaces.class.php'; $interface = new Interfaces($this->db); $result = $interface->run_triggers('LINEBILL_SUPPLIER_UPDATE', $this, $user, $langs, $conf); if ($result < 0) { $error++; $this->errors = $interface->errors; $this->db->rollback(); return -1; } // Fin appel triggers } // Update total price into invoice record $result = $this->update_price('', 'auto'); $this->db->commit(); return $result; } else { $this->db->rollback(); $this->error = $this->db->lasterror(); dol_syslog(get_class($this) . "::updateline error=" . $this->error, LOG_ERR); return -1; } }
} else { // More examples if not specific vat rate found // This example must be kept for test purpose with current value because value used (2/7, 10/3, and vat 0, 10) // were calculated to show all possible cases of rounding. If we change this, examples becomes useless or show the same rounding rule. $s = 10 / 3; $qty = 1; $vat = 10; $tmparray = calcul_price_total(1, $qty * price2num($s, 'MU'), 0, $vat, 0, 0, 0, 'HT', 0); print $langs->trans("UnitPriceOfProduct") . ": " . price2num($s, 'MU'); print " x " . $langs->trans("Quantity") . ": " . $qty; print " - " . $langs->trans("VAT") . ": " . $vat . '%'; print " -> " . $langs->trans("TotalPriceAfterRounding") . ": " . $tmparray[0] . ' / ' . $tmparray[1] . ' / ' . $tmparray[2] . "<br>\n"; $s = 10 / 3; $qty = 2; $vat = 10; $tmparray = calcul_price_total(1, $qty * price2num($s, 'MU'), 0, $vat, 0, 0, 0, 'HT', 0); print $langs->trans("UnitPriceOfProduct") . ": " . price2num($s, 'MU'); print " x " . $langs->trans("Quantity") . ": " . $qty; print " - " . $langs->trans("VAT") . ": " . $vat . '%'; print " -> " . $langs->trans("TotalPriceAfterRounding") . ": " . $tmparray[0] . ' / ' . $tmparray[1] . ' / ' . $tmparray[2] . "<br>\n"; } // Important: can debug rounding, to simulate the rounded total /* print '<br><b>'.$langs->trans("VATRoundedByLine").' ('.$langs->trans("DolibarrDefault").')</b><br>'; foreach($vat_rates as $vat) { for ($qty=1; $qty<=2; $qty++) { $s1=10/3; $s2=2/7;
/** * Update database for contract line * * @param User $user User that modify * @param int $notrigger 0=no, 1=yes (no update trigger) * @return int <0 if KO, >0 if OK */ function update($user, $notrigger = 0) { global $conf, $langs, $mysoc; $error = 0; // Clean parameters $this->fk_contrat = trim($this->fk_contrat); $this->fk_product = trim($this->fk_product); $this->statut = (int) $this->statut; $this->label = trim($this->label); $this->description = trim($this->description); $this->tva_tx = trim($this->tva_tx); $this->localtax1_tx = trim($this->localtax1_tx); $this->localtax2_tx = trim($this->localtax2_tx); $this->qty = trim($this->qty); $this->remise_percent = trim($this->remise_percent); $this->remise = trim($this->remise); $this->fk_remise_except = trim($this->fk_remise_except); $this->subprice = price2num($this->subprice); $this->price_ht = price2num($this->price_ht); $this->total_ht = trim($this->total_ht); $this->total_tva = trim($this->total_tva); $this->total_localtax1 = trim($this->total_localtax1); $this->total_localtax2 = trim($this->total_localtax2); $this->total_ttc = trim($this->total_ttc); $this->info_bits = trim($this->info_bits); $this->fk_user_author = trim($this->fk_user_author); $this->fk_user_ouverture = trim($this->fk_user_ouverture); $this->fk_user_cloture = trim($this->fk_user_cloture); $this->commentaire = trim($this->commentaire); //if (empty($this->subprice)) $this->subprice = 0; if (empty($this->price_ht)) { $this->price_ht = 0; } if (empty($this->total_ht)) { $this->total_ht = 0; } if (empty($this->total_tva)) { $this->total_tva = 0; } if (empty($this->total_ttc)) { $this->total_ttc = 0; } // Check parameters // Put here code to add control on parameters values // Calcul du total TTC et de la TVA pour la ligne a partir de // qty, pu, remise_percent et txtva // TRES IMPORTANT: C'est au moment de l'insertion ligne qu'on doit stocker // la part ht, tva et ttc, et ce au niveau de la ligne qui a son propre taux tva. $localtaxes_type = getLocalTaxesFromRate($this->txtva, 0, $this->societe, $mysoc); $tabprice = calcul_price_total($this->qty, $this->price_ht, $this->remise_percent, $this->tva_tx, $this->localtax1_tx, $this->localtax2_tx, 0, 'HT', 0, 1, $mysoc, $localtaxes_type); $this->total_ht = $tabprice[0]; $this->total_tva = $tabprice[1]; $this->total_ttc = $tabprice[2]; $this->total_localtax1 = $tabprice[9]; $this->total_localtax2 = $tabprice[10]; if (empty($this->pa_ht)) { $this->pa_ht = 0; } // if buy price not defined, define buyprice as configured in margin admin if ($this->pa_ht == 0) { if (($result = $this->defineBuyPrice($this->subprice, $this->remise_percent, $this->fk_product)) < 0) { return $result; } else { $this->pa_ht = $result; } } $this->db->begin(); // Update request $sql = "UPDATE " . MAIN_DB_PREFIX . "contratdet SET"; $sql .= " fk_contrat='" . $this->fk_contrat . "',"; $sql .= " fk_product=" . ($this->fk_product ? "'" . $this->fk_product . "'" : 'null') . ","; $sql .= " statut='" . $this->statut . "',"; $sql .= " label='" . $this->db->escape($this->label) . "',"; $sql .= " description='" . $this->db->escape($this->description) . "',"; $sql .= " date_commande=" . ($this->date_commande != '' ? "'" . $this->db->idate($this->date_commande) . "'" : "null") . ","; $sql .= " date_ouverture_prevue=" . ($this->date_ouverture_prevue != '' ? "'" . $this->db->idate($this->date_ouverture_prevue) . "'" : "null") . ","; $sql .= " date_ouverture=" . ($this->date_ouverture != '' ? "'" . $this->db->idate($this->date_ouverture) . "'" : "null") . ","; $sql .= " date_fin_validite=" . ($this->date_fin_validite != '' ? "'" . $this->db->idate($this->date_fin_validite) . "'" : "null") . ","; $sql .= " date_cloture=" . ($this->date_cloture != '' ? "'" . $this->db->idate($this->date_cloture) . "'" : "null") . ","; $sql .= " tva_tx='" . $this->tva_tx . "',"; $sql .= " localtax1_tx='" . $this->localtax1_tx . "',"; $sql .= " localtax2_tx='" . $this->localtax2_tx . "',"; $sql .= " qty='" . $this->qty . "',"; $sql .= " remise_percent='" . $this->remise_percent . "',"; $sql .= " remise=" . ($this->remise ? "'" . $this->remise . "'" : "null") . ","; $sql .= " fk_remise_except=" . ($this->fk_remise_except ? "'" . $this->fk_remise_except . "'" : "null") . ","; $sql .= " subprice=" . ($this->subprice != '' ? $this->subprice : "null") . ","; $sql .= " price_ht=" . ($this->price_ht != '' ? $this->price_ht : "null") . ","; $sql .= " total_ht='" . $this->total_ht . "',"; $sql .= " total_tva='" . $this->total_tva . "',"; $sql .= " total_localtax1='" . $this->total_localtax1 . "',"; $sql .= " total_localtax2='" . $this->total_localtax2 . "',"; $sql .= " total_ttc='" . $this->total_ttc . "',"; $sql .= " fk_product_fournisseur_price=" . (!empty($this->fk_fournprice) ? $this->fk_fournprice : "NULL") . ","; $sql .= " buy_price_ht='" . price2num($this->pa_ht) . "',"; $sql .= " info_bits='" . $this->info_bits . "',"; $sql .= " fk_user_author=" . ($this->fk_user_author >= 0 ? $this->fk_user_author : "NULL") . ","; $sql .= " fk_user_ouverture=" . ($this->fk_user_ouverture > 0 ? $this->fk_user_ouverture : "NULL") . ","; $sql .= " fk_user_cloture=" . ($this->fk_user_cloture > 0 ? $this->fk_user_cloture : "NULL") . ","; $sql .= " commentaire='" . $this->db->escape($this->commentaire) . "'"; $sql .= ", fk_unit=" . (!$this->fk_unit ? 'NULL' : $this->fk_unit); $sql .= " WHERE rowid=" . $this->id; dol_syslog(get_class($this) . "::update", LOG_DEBUG); $resql = $this->db->query($sql); if ($resql) { $contrat = new Contrat($this->db); $contrat->fetch($this->fk_contrat); $result = $contrat->update_statut($user); } else { $this->error = "Error " . $this->db->lasterror(); $error++; //return -1; } if (empty($conf->global->MAIN_EXTRAFIELDS_DISABLED) && is_array($this->array_options) && count($this->array_options) > 0) { $result = $this->insertExtraFields(); if ($result < 0) { $error++; } } if (empty($error)) { if (!$notrigger) { // Call trigger $result = $this->call_trigger('LINECONTRACT_UPDATE', $user); if ($result < 0) { $error++; $this->db->rollback(); return -1; } // End call triggers } } if (empty($error)) { $this->db->commit(); return 1; } else { $this->db->rollback(); $this->errors[] = $this->error; return -1; } }
/** * Update a line in database * * @param int $rowid Id of line to update * @param string $desc Description de la ligne * @param float $pu Prix unitaire * @param float $qty Quantity * @param float $remise_percent Pourcentage de remise de la ligne * @param float $txtva Taux TVA * @param float $txlocaltax1 Local tax 1 rate * @param float $txlocaltax2 Local tax 2 rate * @param string $price_base_type HT or TTC * @param int $info_bits Miscellaneous informations on line * @param int $date_start Start date of the line * @param int $date_end End date of the line * @param int $type Type of line (0=product, 1=service) * @param int $fk_parent_line Id of parent line (0 in most cases, used by modules adding sublevels into lines). * @param int $skip_update_total Keep fields total_xxx to 0 (used for special lines by some modules) * @param int $fk_fournprice Id of origin supplier price * @param int $pa_ht Price (without tax) of product when it was bought * @param string $label Label * @param int $special_code Special code (also used by externals modules!) * @param array $array_options extrafields array * @param string $fk_unit Code of the unit to use. Null to use the default one * @return int < 0 if KO, > 0 if OK */ function updateline($rowid, $desc, $pu, $qty, $remise_percent, $txtva, $txlocaltax1 = 0.0, $txlocaltax2 = 0.0, $price_base_type = 'HT', $info_bits = 0, $date_start = '', $date_end = '', $type = 0, $fk_parent_line = 0, $skip_update_total = 0, $fk_fournprice = null, $pa_ht = 0, $label = '', $special_code = 0, $array_options = 0, $fk_unit = null) { global $conf, $mysoc; dol_syslog(get_class($this) . "::updateline id={$rowid}, desc={$desc}, pu={$pu}, qty={$qty}, remise_percent={$remise_percent}, txtva={$txtva}, txlocaltax1={$txlocaltax1}, txlocaltax2={$txlocaltax2}, price_base_type={$price_base_type}, info_bits={$info_bits}, date_start={$date_start}, date_end={$date_end}, type={$type}, fk_parent_line={$fk_parent_line}, pa_ht={$pa_ht}, special_code={$special_code}"); include_once DOL_DOCUMENT_ROOT . '/core/lib/price.lib.php'; if (!empty($this->brouillon)) { $this->db->begin(); // Clean parameters if (empty($qty)) { $qty = 0; } if (empty($info_bits)) { $info_bits = 0; } if (empty($txtva)) { $txtva = 0; } if (empty($txlocaltax1)) { $txlocaltax1 = 0; } if (empty($txlocaltax2)) { $txlocaltax2 = 0; } if (empty($remise)) { $remise = 0; } if (empty($remise_percent)) { $remise_percent = 0; } if (empty($special_code) || $special_code == 3) { $special_code = 0; } $remise_percent = price2num($remise_percent); $qty = price2num($qty); $pu = price2num($pu); $pa_ht = price2num($pa_ht); $txtva = price2num($txtva); $txlocaltax1 = price2num($txlocaltax1); $txlocaltax2 = price2num($txlocaltax2); // Calcul du total TTC et de la TVA pour la ligne a partir de // qty, pu, remise_percent et txtva // TRES IMPORTANT: C'est au moment de l'insertion ligne qu'on doit stocker // la part ht, tva et ttc, et ce au niveau de la ligne qui a son propre taux tva. $localtaxes_type = getLocalTaxesFromRate($txtva, 0, $this->thirdparty, $mysoc); $txtva = preg_replace('/\\s*\\(.*\\)/', '', $txtva); // Remove code into vatrate. $tabprice = calcul_price_total($qty, $pu, $remise_percent, $txtva, $txlocaltax1, $txlocaltax2, 0, $price_base_type, $info_bits, $type, $mysoc, $localtaxes_type); $total_ht = $tabprice[0]; $total_tva = $tabprice[1]; $total_ttc = $tabprice[2]; $total_localtax1 = $tabprice[9]; $total_localtax2 = $tabprice[10]; // Anciens indicateurs: $price, $subprice, $remise (a ne plus utiliser) $price = $pu; $subprice = $pu; $remise = 0; if ($remise_percent > 0) { $remise = round($pu * $remise_percent / 100, 2); $price = $pu - $remise; } //Fetch current line from the database and then clone the object and set it in $oldline property $line = new OrderLine($this->db); $line->fetch($rowid); $staticline = clone $line; $line->oldline = $staticline; $this->line = $line; $this->line->context = $this->context; // Reorder if fk_parent_line change if (!empty($fk_parent_line) && !empty($staticline->fk_parent_line) && $fk_parent_line != $staticline->fk_parent_line) { $rangmax = $this->line_max($fk_parent_line); $this->line->rang = $rangmax + 1; } $this->line->rowid = $rowid; $this->line->label = $label; $this->line->desc = $desc; $this->line->qty = $qty; $this->line->tva_tx = $txtva; $this->line->localtax1_tx = $txlocaltax1; $this->line->localtax2_tx = $txlocaltax2; $this->line->localtax1_type = $localtaxes_type[0]; $this->line->localtax2_type = $localtaxes_type[2]; $this->line->remise_percent = $remise_percent; $this->line->subprice = $subprice; $this->line->info_bits = $info_bits; $this->line->special_code = $special_code; $this->line->total_ht = $total_ht; $this->line->total_tva = $total_tva; $this->line->total_localtax1 = $total_localtax1; $this->line->total_localtax2 = $total_localtax2; $this->line->total_ttc = $total_ttc; $this->line->date_start = $date_start; $this->line->date_end = $date_end; $this->line->product_type = $type; $this->line->fk_parent_line = $fk_parent_line; $this->line->skip_update_total = $skip_update_total; $this->line->fk_unit = $fk_unit; $this->line->fk_fournprice = $fk_fournprice; $this->line->pa_ht = $pa_ht; // TODO deprecated $this->line->price = $price; $this->line->remise = $remise; if (is_array($array_options) && count($array_options) > 0) { $this->line->array_options = $array_options; } $result = $this->line->update(); if ($result > 0) { // Reorder if child line if (!empty($fk_parent_line)) { $this->line_order(true, 'DESC'); } // Mise a jour info denormalisees $this->update_price(1); $this->db->commit(); return $result; } else { $this->error = $this->line->error; $this->db->rollback(); return -1; } } else { $this->error = get_class($this) . "::updateline Order status makes operation forbidden"; $this->errors = array('OrderStatusMakeOperationForbidden'); return -2; } }
/** * Update a proposal line * * @param int $rowid Id de la ligne * @param double $pu Prix unitaire (HT ou TTC selon price_base_type) * @param double $qty Quantity * @param double $remise_percent Remise effectuee sur le produit * @param double $txtva Taux de TVA * @param double $txlocaltax1 Local tax 1 rate * @param double $txlocaltax2 Local tax 2 rate * @param string $desc Description * @param double $price_base_type HT ou TTC * @param int $info_bits Miscellanous informations * @param int $special_code Set special code ('' = we don't change it) * @param int $fk_parent_line Id of line parent * @param int $skip_update_total Skip update total * @param int $fk_fournprice Id supplier price * @param int $pa_ht Buying price without tax * @return int 0 if OK, <0 if KO */ function updateline($rowid, $pu, $qty, $remise_percent, $txtva, $txlocaltax1 = 0, $txlocaltax2 = 0, $desc = '', $price_base_type = 'HT', $info_bits = 0, $special_code = 0, $fk_parent_line = 0, $skip_update_total = 0, $fk_fournprice = null, $pa_ht = 0) { global $conf, $user, $langs; dol_syslog(get_class($this) . "::updateLine {$rowid}, {$pu}, {$qty}, {$remise_percent}, {$txtva}, {$desc}, {$price_base_type}, {$info_bits}"); include_once DOL_DOCUMENT_ROOT . '/core/lib/price.lib.php'; // Clean parameters $remise_percent = price2num($remise_percent); $qty = price2num($qty); $pu = price2num($pu); $txtva = price2num($txtva); $txlocaltax1 = price2num($txlocaltax1); $txlocaltax2 = price2num($txlocaltax2); $pa_ht = price2num($pa_ht); if (empty($qty) && empty($special_code)) { $special_code = 3; } // Set option tag if (!empty($qty) && $special_code == 3) { $special_code = 0; } // Remove option tag if ($this->statut == 0) { $this->db->begin(); // Calcul du total TTC et de la TVA pour la ligne a partir de // qty, pu, remise_percent et txtva // TRES IMPORTANT: C'est au moment de l'insertion ligne qu'on doit stocker // la part ht, tva et ttc, et ce au niveau de la ligne qui a son propre taux tva. $tabprice = calcul_price_total($qty, $pu, $remise_percent, $txtva, $txlocaltax1, $txlocaltax2, 0, $price_base_type, $info_bits); $total_ht = $tabprice[0]; $total_tva = $tabprice[1]; $total_ttc = $tabprice[2]; $total_localtax1 = $tabprice[9]; $total_localtax2 = $tabprice[10]; // Anciens indicateurs: $price, $remise (a ne plus utiliser) $price = $pu; if ($remise_percent > 0) { $remise = round($pu * $remise_percent / 100, 2); $price = $pu - $remise; } // Update line $this->line = new PropaleLigne($this->db); // Stock previous line records $staticline = new PropaleLigne($this->db); $staticline->fetch($rowid); $this->line->oldline = $staticline; // Reorder if fk_parent_line change if (!empty($fk_parent_line) && !empty($staticline->fk_parent_line) && $fk_parent_line != $staticline->fk_parent_line) { $rangmax = $this->line_max($fk_parent_line); $this->line->rang = $rangmax + 1; } $this->line->rowid = $rowid; $this->line->desc = $desc; $this->line->qty = $qty; $this->line->tva_tx = $txtva; $this->line->localtax1_tx = $txlocaltax1; $this->line->localtax2_tx = $txlocaltax2; $this->line->remise_percent = $remise_percent; $this->line->subprice = $pu; $this->line->info_bits = $info_bits; $this->line->total_ht = $total_ht; $this->line->total_tva = $total_tva; $this->line->total_localtax1 = $total_localtax1; $this->line->total_localtax2 = $total_localtax2; $this->line->total_ttc = $total_ttc; $this->line->special_code = $special_code; $this->line->fk_parent_line = $fk_parent_line; $this->line->skip_update_total = $skip_update_total; // infos marge $this->line->fk_fournprice = $fk_fournprice; $this->line->pa_ht = $pa_ht; // TODO deprecated $this->line->price = $price; $this->line->remise = $remise; $result = $this->line->update(); if ($result > 0) { // Reorder if child line if (!empty($fk_parent_line)) { $this->line_order(true, 'DESC'); } $this->update_price(1); $this->fk_propal = $this->id; $this->rowid = $rowid; $this->db->commit(); return $result; } else { $this->error = $this->db->error(); $this->db->rollback(); dol_syslog("Propal::UpdateLine Error=" . $this->error, LOG_ERR); return -1; } } else { dol_syslog("Propal::UpdateLigne Erreur -2 Propal en mode incompatible pour cette action"); return -2; } }
/** * Update a detail line * @param rowid Id of line to update * @param desc Description of line * @param pu Prix unitaire (HT ou TTC selon price_base_type) (> 0 even for credit note lines) * @param qty Quantity * @param remise_percent Pourcentage de remise de la ligne * @param date_start Date de debut de validite du service * @param date_end Date de fin de validite du service * @param tva_tx VAT Rate * @param txlocaltax1 Local tax 1 rate * @param txlocaltax2 Local tax 2 rate * @param price_base_type HT or TTC * @param info_bits Miscellanous informations * @param type Type of line (0=product, 1=service) * @return int < 0 if KO, > 0 if OK */ function updateline($rowid, $desc, $pu, $qty, $remise_percent=0, $date_start, $date_end, $txtva, $txlocaltax1=0, $txlocaltax2=0,$price_base_type='HT', $info_bits=0, $type=0, $fk_parent_line=0, $skip_update_total=0) { include_once(DOL_DOCUMENT_ROOT.'/lib/price.lib.php'); dol_syslog("Facture::UpdateLine $rowid, $desc, $pu, $qty, $remise_percent, $date_start, $date_end, $txtva, $txlocaltax1, $txlocaltax2, $price_base_type, $info_bits, $type", LOG_DEBUG); if ($this->brouillon) { $this->db->begin(); // Clean parameters $remise_percent=price2num($remise_percent); $qty=price2num($qty); if (! $qty) $qty=0; $pu = price2num($pu); $txtva=price2num($txtva); $txlocaltax1=price2num($txlocaltax1); $txlocaltax2=price2num($txlocaltax2); // Check parameters if ($type < 0) return -1; // Calculate total with, without tax and tax from qty, pu, remise_percent and txtva // TRES IMPORTANT: C'est au moment de l'insertion ligne qu'on doit stocker // la part ht, tva et ttc, et ce au niveau de la ligne qui a son propre taux tva. $tabprice=calcul_price_total($qty, $pu, $remise_percent, $txtva, $txlocaltax1, $txlocaltax2, 0, $price_base_type, $info_bits); $total_ht = $tabprice[0]; $total_tva = $tabprice[1]; $total_ttc = $tabprice[2]; $total_localtax1=$tabprice[9]; $total_localtax2=$tabprice[10]; $pu_ht = $tabprice[3]; $pu_tva = $tabprice[4]; $pu_ttc = $tabprice[5]; // Old properties: $price, $remise (deprecated) $price = $pu; $remise = 0; if ($remise_percent > 0) { $remise = round(($pu * $remise_percent / 100),2); $price = ($pu - $remise); } $price = price2num($price); // Update line into database $this->line=new FactureLigne($this->db); // Stock previous line records $staticline=new FactureLigne($this->db); $staticline->fetch($rowid); $this->line->oldline = $staticline; $this->line->rowid = $rowid; $this->line->desc = $desc; $this->line->qty = $qty; $this->line->tva_tx = $txtva; $this->line->localtax1_tx = $txlocaltax1; $this->line->localtax2_tx = $txlocaltax2; $this->line->remise_percent = $remise_percent; $this->line->subprice = ($this->type==2?-1:1)*abs($pu); $this->line->date_start = $date_start; $this->line->date_end = $date_end; $this->line->total_ht = ($this->type==2?-1:1)*abs($total_ht); $this->line->total_tva = ($this->type==2?-1:1)*abs($total_tva); $this->line->total_localtax1 = ($this->type==2?-1:1)*abs($total_localtax1); $this->line->total_localtax2 = ($this->type==2?-1:1)*abs($total_localtax2); $this->line->total_ttc = ($this->type==2?-1:1)*abs($total_ttc); $this->line->info_bits = $info_bits; $this->line->product_type = $type; $this->line->fk_parent_line = $fk_parent_line; $this->line->skip_update_total = $skip_update_total; // A ne plus utiliser $this->line->price=$price; $this->line->remise=$remise; $result=$this->line->update(); if ($result > 0) { // Mise a jour info denormalisees au niveau facture $this->update_price(1); $this->db->commit(); return $result; } else { $this->db->rollback(); return -1; } } else { $this->error="Facture::UpdateLine Invoice statut makes operation forbidden"; return -2; } }
/** * Load lines * * @return int >0 if OK, Otherwise if KO */ function fetch_lines() { global $conf, $mysoc; // TODO: recuperer les champs du document associe a part $sql = "SELECT cd.rowid, cd.fk_product, cd.label as custom_label, cd.description, cd.qty as qty_asked"; $sql .= ", cd.total_ht, cd.total_localtax1, cd.total_localtax2, cd.total_ttc, cd.total_tva"; $sql .= ", cd.tva_tx, cd.localtax1_tx, cd.localtax2_tx, cd.price, cd.subprice, cd.remise_percent"; $sql .= ", ed.rowid as line_id, ed.qty as qty_shipped, ed.fk_origin_line, ed.fk_entrepot"; $sql .= ", p.ref as product_ref, p.label as product_label, p.fk_product_type"; $sql .= ", p.weight, p.weight_units, p.length, p.length_units, p.surface, p.surface_units, p.volume, p.volume_units, p.tobatch as product_tobatch"; $sql .= " FROM (" . MAIN_DB_PREFIX . "expeditiondet as ed,"; $sql .= " " . MAIN_DB_PREFIX . "commandedet as cd)"; $sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "product as p ON p.rowid = cd.fk_product"; $sql .= " WHERE ed.fk_expedition = " . $this->id; $sql .= " AND ed.fk_origin_line = cd.rowid"; $sql .= " ORDER BY cd.rang, ed.fk_origin_line"; dol_syslog(get_class($this) . "::fetch_lines", LOG_DEBUG); $resql = $this->db->query($sql); if ($resql) { include_once DOL_DOCUMENT_ROOT . '/core/lib/price.lib.php'; $num = $this->db->num_rows($resql); $i = 0; $lineindex = 0; $originline = 0; $this->total_ht = 0; $this->total_tva = 0; $this->total_ttc = 0; $this->total_localtax1 = 0; $this->total_localtax2 = 0; while ($i < $num) { $obj = $this->db->fetch_object($resql); if ($originline == $obj->fk_origin_line) { $line->entrepot_id = 0; // entrepod_id in details_entrepot $line->qty_shipped += $obj->qty_shipped; } else { $line = new ExpeditionLigne($this->db); $line->entrepot_id = $obj->fk_entrepot; $line->qty_shipped = $obj->qty_shipped; } $detail_entrepot = new stdClass(); $detail_entrepot->entrepot_id = $obj->fk_entrepot; $detail_entrepot->qty_shipped = $obj->qty_shipped; $line->details_entrepot[] = $detail_entrepot; $line->line_id = $obj->line_id; $line->rowid = $obj->line_id; // TODO deprecated $line->id = $obj->line_id; $line->fk_origin_line = $obj->fk_origin_line; $line->origin_line_id = $obj->fk_origin_line; // TODO deprecated $line->fk_product = $obj->fk_product; $line->fk_product_type = $obj->fk_product_type; $line->ref = $obj->product_ref; // TODO deprecated $line->product_ref = $obj->product_ref; $line->product_label = $obj->product_label; $line->libelle = $obj->product_label; // TODO deprecated $line->product_tobatch = $obj->product_tobatch; $line->label = $obj->custom_label; $line->description = $obj->description; $line->qty_asked = $obj->qty_asked; $line->weight = $obj->weight; $line->weight_units = $obj->weight_units; $line->length = $obj->length; $line->length_units = $obj->length_units; $line->surface = $obj->surface; $line->surface_units = $obj->surface_units; $line->volume = $obj->volume; $line->volume_units = $obj->volume_units; // For invoicing $tabprice = calcul_price_total($obj->qty_shipped, $obj->subprice, $obj->remise_percent, $obj->tva_tx, $obj->localtax1_tx, $obj->localtax2_tx, 0, 'HT', $obj->info_bits, $obj->fk_product_type, $mysoc); // We force type to 0 $line->desc = $obj->description; // We need ->desc because some code into CommonObject use desc (property defined for other elements) $line->qty = $line->qty_shipped; $line->total_ht = $tabprice[0]; $line->total_localtax1 = $tabprice[9]; $line->total_localtax2 = $tabprice[10]; $line->total_ttc = $tabprice[2]; $line->total_tva = $tabprice[1]; $line->tva_tx = $obj->tva_tx; $line->localtax1_tx = $obj->localtax1_tx; $line->localtax2_tx = $obj->localtax2_tx; $line->price = $obj->price; $line->subprice = $obj->subprice; $line->remise_percent = $obj->remise_percent; $this->total_ht += $tabprice[0]; $this->total_tva += $tabprice[1]; $this->total_ttc += $tabprice[2]; $this->total_localtax1 += $tabprice[9]; $this->total_localtax2 += $tabprice[10]; $line->detail_batch = array(); // Eat-by date if (!empty($conf->productbatch->enabled) && $obj->line_id > 0) { require_once DOL_DOCUMENT_ROOT . '/expedition/class/expeditionbatch.class.php'; $newdetailbatch = ExpeditionLineBatch::fetchAll($this->db, $obj->line_id); if (is_array($newdetailbatch)) { if ($originline != $obj->fk_origin_line) { $line->detail_batch = $newdetailbatch; } else { $line->detail_batch = array_merge($line->detail_batch, $newdetailbatch); } } } if ($originline != $obj->fk_origin_line) { $this->lines[$lineindex] = $line; $lineindex++; } else { $line->total_ht += $tabprice[0]; $line->total_localtax1 += $tabprice[9]; $line->total_localtax2 += $tabprice[10]; $line->total_ttc += $tabprice[2]; $line->total_tva += $tabprice[1]; } $i++; $originline = $obj->fk_origin_line; } $this->db->free($resql); return 1; } else { $this->error = $this->db->error(); return -3; } }
/** * Update total_ht, total_ttc, total_vat, total_localtax1, total_localtax2 for an object (sum of lines). * Must be called at end of methods addline or updateline. * * @param int $exclspec >0 = Exclude special product (product_type=9) * @param string $roundingadjust 'none'=Do nothing, 'auto'=Use default method (MAIN_ROUNDOFTOTAL_NOT_TOTALOFROUND if defined, or '0'), '0'=Force use total of rounding, '1'=Force use rounding of total * @param int $nodatabaseupdate 1=Do not update database. Update only properties of object. * @param Societe $seller If roundingadjust is '0' or '1', it means we recalculate total for lines before calculating total for object and for this, we need seller object. * @return int <0 if KO, >0 if OK */ function update_price($exclspec = 0, $roundingadjust = 'none', $nodatabaseupdate = 0, $seller = null) { global $conf; include_once DOL_DOCUMENT_ROOT . '/core/lib/price.lib.php'; if ($roundingadjust == '-1') { $roundingadjust = 'auto'; } // For backward compatibility $forcedroundingmode = $roundingadjust; if ($forcedroundingmode == 'auto' && isset($conf->global->MAIN_ROUNDOFTOTAL_NOT_TOTALOFROUND)) { $forcedroundingmode = $conf->global->MAIN_ROUNDOFTOTAL_NOT_TOTALOFROUND; } if ($forcedroundingmode == 'auto') { $forcedroundingmode = '0'; } $error = 0; // Define constants to find lines to sum $fieldtva = 'total_tva'; $fieldlocaltax1 = 'total_localtax1'; $fieldlocaltax2 = 'total_localtax2'; $fieldup = 'subprice'; if ($this->element == 'facture_fourn' || $this->element == 'invoice_supplier') { $fieldtva = 'tva'; $fieldup = 'pu_ht'; } if ($this->element == 'expensereport') { $fieldup = 'value_unit'; } $sql = 'SELECT rowid, qty, ' . $fieldup . ' as up, remise_percent, total_ht, ' . $fieldtva . ' as total_tva, total_ttc, ' . $fieldlocaltax1 . ' as total_localtax1, ' . $fieldlocaltax2 . ' as total_localtax2,'; $sql .= ' tva_tx as vatrate, localtax1_tx, localtax2_tx, localtax1_type, localtax2_type, info_bits, product_type'; $sql .= ' FROM ' . MAIN_DB_PREFIX . $this->table_element_line; $sql .= ' WHERE ' . $this->fk_element . ' = ' . $this->id; if ($exclspec) { $product_field = 'product_type'; if ($this->table_element_line == 'contratdet') { $product_field = ''; } // contratdet table has no product_type field if ($product_field) { $sql .= ' AND ' . $product_field . ' <> 9'; } } $sql .= ' ORDER by rowid'; // We want to be sure to always use same order of line to not change lines differently when option MAIN_ROUNDOFTOTAL_NOT_TOTALOFROUND is used dol_syslog(get_class($this) . "::update_price", LOG_DEBUG); $resql = $this->db->query($sql); if ($resql) { $this->total_ht = 0; $this->total_tva = 0; $this->total_localtax1 = 0; $this->total_localtax2 = 0; $this->total_ttc = 0; $total_ht_by_vats = array(); $total_tva_by_vats = array(); $total_ttc_by_vats = array(); $num = $this->db->num_rows($resql); $i = 0; while ($i < $num) { $obj = $this->db->fetch_object($resql); // Note: There is no check on detail line and no check on total, if $forcedroundingmode = 'none' if ($forcedroundingmode == '0') { $localtax_array = array($obj->localtax1_type, $obj->localtax1_tx, $obj->localtax2_type, $obj->localtax2_tx); $tmpcal = calcul_price_total($obj->qty, $obj->up, $obj->remise_percent, $obj->vatrate, $obj->localtax1_tx, $obj->localtax2_tx, 0, 'HT', $obj->info_bits, $obj->product_type, $seller, $localtax_array); $diff = price2num($tmpcal[1] - $obj->total_tva, 'MT', 1); if ($diff) { $sqlfix = "UPDATE " . MAIN_DB_PREFIX . $this->table_element_line . " SET " . $fieldtva . " = " . $tmpcal[1] . ", total_ttc = " . $tmpcal[2] . " WHERE rowid = " . $obj->rowid; dol_syslog('We found unconsistent data into detailed line (difference of ' . $diff . ') for line rowid = ' . $obj->rowid . " (total vat of line calculated=" . $tmpcal[1] . ", database=" . $obj->total_tva . "). We fix the total_vat and total_ttc of line by running sqlfix = " . $sqlfix); $resqlfix = $this->db->query($sqlfix); if (!$resqlfix) { dol_print_error($this->db, 'Failed to update line'); } $obj->total_tva = $tmpcal[1]; $obj->total_ttc = $tmpcal[2]; // } } $this->total_ht += $obj->total_ht; // The only field visible at end of line detail $this->total_tva += $obj->total_tva; $this->total_localtax1 += $obj->total_localtax1; $this->total_localtax2 += $obj->total_localtax2; $this->total_ttc += $obj->total_ttc; if (!isset($total_ht_by_vats[$obj->vatrate])) { $total_ht_by_vats[$obj->vatrate] = 0; } if (!isset($total_tva_by_vats[$obj->vatrate])) { $total_tva_by_vats[$obj->vatrate] = 0; } if (!isset($total_ttc_by_vats[$obj->vatrate])) { $total_ttc_by_vats[$obj->vatrate] = 0; } $total_ht_by_vats[$obj->vatrate] += $obj->total_ht; $total_tva_by_vats[$obj->vatrate] += $obj->total_tva; $total_ttc_by_vats[$obj->vatrate] += $obj->total_ttc; if ($forcedroundingmode == '1') { $tmpvat = price2num($total_ht_by_vats[$obj->vatrate] * $obj->vatrate / 100, 'MT', 1); $diff = price2num($total_tva_by_vats[$obj->vatrate] - $tmpvat, 'MT', 1); //print 'Line '.$i.' rowid='.$obj->rowid.' vat_rate='.$obj->vatrate.' total_ht='.$obj->total_ht.' total_tva='.$obj->total_tva.' total_ttc='.$obj->total_ttc.' total_ht_by_vats='.$total_ht_by_vats[$obj->vatrate].' total_tva_by_vats='.$total_tva_by_vats[$obj->vatrate].' (new calculation = '.$tmpvat.') total_ttc_by_vats='.$total_ttc_by_vats[$obj->vatrate].($diff?" => DIFF":"")."<br>\n"; if ($diff) { if (abs($diff) > 0.1) { dol_syslog('A rounding difference was detected into TOTAL but is too high to be corrected', LOG_WARNING); exit; } $sqlfix = "UPDATE " . MAIN_DB_PREFIX . $this->table_element_line . " SET " . $fieldtva . " = " . ($obj->total_tva - $diff) . ", total_ttc = " . ($obj->total_ttc - $diff) . " WHERE rowid = " . $obj->rowid; dol_syslog('We found a difference of ' . $diff . ' for line rowid = ' . $obj->rowid . ". We fix the total_vat and total_ttc of line by running sqlfix = " . $sqlfix); $resqlfix = $this->db->query($sqlfix); if (!$resqlfix) { dol_print_error($this->db, 'Failed to update line'); } $this->total_tva -= $diff; $this->total_ttc -= $diff; $total_tva_by_vats[$obj->vatrate] -= $diff; $total_ttc_by_vats[$obj->vatrate] -= $diff; } } $i++; } // Add revenue stamp to total $this->total_ttc += isset($this->revenuestamp) ? $this->revenuestamp : 0; // Situations totals if ($this->situation_cycle_ref && $this->situation_counter > 1) { $prev_sits = $this->get_prev_sits(); foreach ($prev_sits as $sit) { $this->total_ht -= $sit->total_ht; $this->total_tva -= $sit->total_tva; $this->total_localtax1 -= $sit->total_localtax1; $this->total_localtax2 -= $sit->total_localtax2; $this->total_ttc -= $sit->total_ttc; } } $this->db->free($resql); // Now update global field total_ht, total_ttc and tva $fieldht = 'total_ht'; $fieldtva = 'tva'; $fieldlocaltax1 = 'localtax1'; $fieldlocaltax2 = 'localtax2'; $fieldttc = 'total_ttc'; // Specific code for backward compatibility with old field names if ($this->element == 'facture' || $this->element == 'facturerec') { $fieldht = 'total'; } if ($this->element == 'facture_fourn' || $this->element == 'invoice_supplier') { $fieldtva = 'total_tva'; } if ($this->element == 'propal') { $fieldttc = 'total'; } if ($this->element == 'expensereport') { $fieldtva = 'total_tva'; } if ($this->element == 'supplier_proposal') { $fieldttc = 'total'; } if (empty($nodatabaseupdate)) { $sql = 'UPDATE ' . MAIN_DB_PREFIX . $this->table_element . ' SET'; $sql .= " " . $fieldht . "='" . price2num($this->total_ht) . "',"; $sql .= " " . $fieldtva . "='" . price2num($this->total_tva) . "',"; $sql .= " " . $fieldlocaltax1 . "='" . price2num($this->total_localtax1) . "',"; $sql .= " " . $fieldlocaltax2 . "='" . price2num($this->total_localtax2) . "',"; $sql .= " " . $fieldttc . "='" . price2num($this->total_ttc) . "'"; $sql .= ' WHERE rowid = ' . $this->id; //print "xx".$sql; dol_syslog(get_class($this) . "::update_price", LOG_DEBUG); $resql = $this->db->query($sql); if (!$resql) { $error++; $this->error = $this->db->lasterror(); $this->error[] = $this->db->lasterror(); } } if (!$error) { return 1; } else { return -1; } } else { dol_print_error($this->db, 'Bad request in update_price'); return -1; } }
// Si aucune date n'est rentrée if (empty($object_ligne->date) || $object_ligne->date == "--") { $error++; setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("Date")), null, 'errors'); } // Si aucun prix n'est rentré if ($object_ligne->value_unit == 0) { $error++; setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("PriceUTTC")), null, 'errors'); } // S'il y'a eu au moins une erreur if (!$error) { $object_ligne->fk_expensereport = $_POST['fk_expensereport']; $type = 0; // TODO What if service ? $tmp = calcul_price_total($qty, $up, 0, $vatrate, 0, 0, 0, 'TTC', 0, $type); $object_ligne->vatrate = price2num($vatrate); $object_ligne->total_ttc = $tmp[2]; $object_ligne->total_ht = $tmp[0]; $object_ligne->total_tva = $tmp[1]; $result = $object_ligne->insert(); if ($result > 0) { $db->commit(); header("Location: " . $_SERVER["PHP_SELF"] . "?id=" . $id); exit; } else { dol_print_error($db, $object->error); $db->rollback(); } } $action = '';
/** * Update a line detail into database * * @param int $id Id of line invoice * @param string $desc Description of line * @param double $pu Prix unitaire (HT ou TTC selon price_base_type) * @param double $vatrate VAT Rate * @param double $txlocaltax1 LocalTax1 Rate * @param double $txlocaltax2 LocalTax2 Rate * @param double $qty Quantity * @param int $idproduct Id produit * @param double $price_base_type HT or TTC * @param int $info_bits Miscellaneous informations of line * @param int $type Type of line (0=product, 1=service) * @param double $remise_percent Pourcentage de remise de la ligne * @param int $notrigger Disable triggers * @param timestamp $date_start Date start of service * @param timestamp $date_end Date end of service * @param array $array_options extrafields array * @param string $fk_unit Code of the unit to use. Null to use the default one * @return int <0 if KO, >0 if OK */ function updateline($id, $desc, $pu, $vatrate, $txlocaltax1 = 0, $txlocaltax2 = 0, $qty = 1, $idproduct = 0, $price_base_type = 'HT', $info_bits = 0, $type = 0, $remise_percent = 0, $notrigger = false, $date_start = '', $date_end = '', $array_options = 0, $fk_unit = null) { global $mysoc; dol_syslog(get_class($this) . "::updateline {$id},{$desc},{$pu},{$vatrate},{$qty},{$idproduct},{$price_base_type},{$info_bits},{$type},{$remise_percent},{$fk_unit}", LOG_DEBUG); include_once DOL_DOCUMENT_ROOT . '/core/lib/price.lib.php'; $pu = price2num($pu); $qty = price2num($qty); $remise_percent = price2num($remise_percent); // Check parameters if (!is_numeric($pu) || !is_numeric($qty)) { return -1; } if ($type < 0) { return -1; } // Clean parameters if (empty($vatrate)) { $vatrate = 0; } if (empty($txlocaltax1)) { $txlocaltax1 = 0; } if (empty($txlocaltax2)) { $txlocaltax2 = 0; } $txlocaltax1 = price2num($txlocaltax1); $txlocaltax2 = price2num($txlocaltax2); // Calcul du total TTC et de la TVA pour la ligne a partir de // qty, pu, remise_percent et txtva // TRES IMPORTANT: C'est au moment de l'insertion ligne qu'on doit stocker // la part ht, tva et ttc, et ce au niveau de la ligne qui a son propre taux tva. $localtaxes_type = getLocalTaxesFromRate($vatrate, 0, $mysoc, $this->thirdparty); $tabprice = calcul_price_total($qty, $pu, $remise_percent, $vatrate, $txlocaltax1, $txlocaltax2, 0, $price_base_type, $info_bits, $type, $this->thirdparty, $localtaxes_type); $total_ht = $tabprice[0]; $total_tva = $tabprice[1]; $total_ttc = $tabprice[2]; $pu_ht = $tabprice[3]; $pu_tva = $tabprice[4]; $pu_ttc = $tabprice[5]; $total_localtax1 = $tabprice[9]; $total_localtax2 = $tabprice[10]; if (empty($info_bits)) { $info_bits = 0; } if ($idproduct) { $product = new Product($this->db); $result = $product->fetch($idproduct); $product_type = $product->type; } else { $product_type = $type; } $line = new SupplierInvoiceLine($this->db); if ($line->fetch($id) < 1) { return -1; } $line->description = $desc; $line->subprice = $pu_ht; $line->pu_ht = $pu_ht; $line->pu_ttc = $pu_ttc; $line->qty = $qty; $line->remise_percent = $remise_percent; $line->tva_tx = $vatrate; $line->localtax1_tx = $txlocaltax1; $line->localtax2_tx = $txlocaltax2; $line->localtax1_type = $localtaxes_type[0]; $line->localtax2_type = $localtaxes_type[2]; $line->total_ht = $total_ht; $line->total_tva = $total_tva; $line->total_localtax1 = $total_localtax1; $line->total_localtax2 = $total_localtax2; $line->total_ttc = $total_ttc; $line->fk_product = $idproduct; $line->product_type = $product_type; $line->info_bits = $info_bits; $line->fk_unit = $fk_unit; $line->array_options = $array_options; $res = $line->update($notrigger); if ($res < 1) { $this->errors[] = $line->error; } else { // Update total price into invoice record $res = $this->update_price('', 'auto'); } return $res; }
/** * Update a detail line * * @param int $rowid Id of line to update * @param string $desc Description of line * @param double $pu Prix unitaire (HT ou TTC selon price_base_type) (> 0 even for credit note lines) * @param double $qty Quantity * @param double $remise_percent Pourcentage de remise de la ligne * @param date $date_start Date de debut de validite du service * @param date $date_end Date de fin de validite du service * @param double $txtva VAT Rate * @param double $txlocaltax1 Local tax 1 rate * @param double $txlocaltax2 Local tax 2 rate * @param string $price_base_type HT or TTC * @param int $info_bits Miscellanous informations * @param int $type Type of line (0=product, 1=service) * @param int $fk_parent_line ??? * @param int $skip_update_total ??? * @param int $fk_fournprice To calculate margin * @param int $pa_ht Buying price of line * @return int < 0 if KO, > 0 if OK */ function updateline($rowid, $desc, $pu, $qty, $remise_percent, $date_start, $date_end, $txtva, $txlocaltax1 = 0, $txlocaltax2 = 0, $price_base_type = 'HT', $info_bits = 0, $type = 0, $fk_parent_line = 0, $skip_update_total = 0, $fk_fournprice = null, $pa_ht = 0) { include_once DOL_DOCUMENT_ROOT . '/core/lib/price.lib.php'; dol_syslog(get_class($this) . "::updateline {$rowid}, {$desc}, {$pu}, {$qty}, {$remise_percent}, {$date_start}, {$date_end}, {$txtva}, {$txlocaltax1}, {$txlocaltax2}, {$price_base_type}, {$info_bits}, {$type}, {$fk_parent_line}", LOG_DEBUG); if ($this->brouillon) { $this->db->begin(); // Clean parameters if (empty($qty)) { $qty = 0; } if (empty($fk_parent_line) || $fk_parent_line < 0) { $fk_parent_line = 0; } $remise_percent = price2num($remise_percent); $qty = price2num($qty); $pu = price2num($pu); $pa_ht = price2num($pa_ht); $txtva = price2num($txtva); $txlocaltax1 = price2num($txlocaltax1); $txlocaltax2 = price2num($txlocaltax2); // Check parameters if ($type < 0) { return -1; } // Calculate total with, without tax and tax from qty, pu, remise_percent and txtva // TRES IMPORTANT: C'est au moment de l'insertion ligne qu'on doit stocker // la part ht, tva et ttc, et ce au niveau de la ligne qui a son propre taux tva. $tabprice = calcul_price_total($qty, $pu, $remise_percent, $txtva, $txlocaltax1, $txlocaltax2, 0, $price_base_type, $info_bits); $total_ht = $tabprice[0]; $total_tva = $tabprice[1]; $total_ttc = $tabprice[2]; $total_localtax1 = $tabprice[9]; $total_localtax2 = $tabprice[10]; $pu_ht = $tabprice[3]; $pu_tva = $tabprice[4]; $pu_ttc = $tabprice[5]; // Old properties: $price, $remise (deprecated) $price = $pu; $remise = 0; if ($remise_percent > 0) { $remise = round($pu * $remise_percent / 100, 2); $price = $pu - $remise; } $price = price2num($price); // Update line into database $this->line = new FactureLigne($this->db); // Stock previous line records $staticline = new FactureLigne($this->db); $staticline->fetch($rowid); $this->line->oldline = $staticline; // Reorder if fk_parent_line change if (!empty($fk_parent_line) && !empty($staticline->fk_parent_line) && $fk_parent_line != $staticline->fk_parent_line) { $rangmax = $this->line_max($fk_parent_line); $this->line->rang = $rangmax + 1; } $this->line->rowid = $rowid; $this->line->desc = $desc; $this->line->qty = $this->type == 2 ? abs($qty) : $qty; // For credit note, quantity is always positive and unit price negative $this->line->tva_tx = $txtva; $this->line->localtax1_tx = $txlocaltax1; $this->line->localtax2_tx = $txlocaltax2; $this->line->remise_percent = $remise_percent; $this->line->subprice = $this->type == 2 ? -abs($pu_ht) : $pu_ht; // For credit note, unit price always negative, always positive otherwise $this->line->date_start = $date_start; $this->line->date_end = $date_end; $this->line->total_ht = $this->type == 2 || $qty < 0 ? -abs($total_ht) : $total_ht; // For credit note and if qty is negative, total is negative $this->line->total_tva = $this->type == 2 || $qty < 0 ? -abs($total_tva) : $total_tva; $this->line->total_localtax1 = $this->type == 2 || $qty < 0 ? -abs($total_localtax1) : $total_localtax1; $this->line->total_localtax2 = $this->type == 2 || $qty < 0 ? -abs($total_localtax2) : $total_localtax2; $this->line->total_ttc = $this->type == 2 || $qty < 0 ? -abs($total_ttc) : $total_ttc; $this->line->info_bits = $info_bits; $this->line->product_type = $type; $this->line->fk_parent_line = $fk_parent_line; $this->line->skip_update_total = $skip_update_total; // infos marge $this->line->fk_fournprice = $fk_fournprice; $this->line->pa_ht = $pa_ht; // A ne plus utiliser //$this->line->price=$price; //$this->line->remise=$remise; $result = $this->line->update(); if ($result > 0) { // Reorder if child line if (!empty($fk_parent_line)) { $this->line_order(true, 'DESC'); } // Mise a jour info denormalisees au niveau facture $this->update_price(1); $this->db->commit(); return $result; } else { $this->db->rollback(); return -1; } } else { $this->error = "Invoice statut makes operation forbidden"; return -2; } }
/** * Test function calcul_price_total * * @return boolean * @see http://wiki.dolibarr.org/index.php/Draft:VAT_calculation_and_rounding#Standard_usage */ public function testCalculPriceTotal() { global $conf, $user, $langs, $db; $this->savconf = $conf; $this->savuser = $user; $this->savlangs = $langs; $this->savdb = $db; global $mysoc; $mysoc = new Societe($db); /* * Country France */ // qty=1, unit_price=1.24, discount_line=0, vat_rate=10, price_base_type='HT' (method we provide value) $mysoc->country_code = 'FR'; $mysoc->country_id = 1; $result1 = calcul_price_total(1, 1.24, 0, 10, 0, 0, 0, 'HT', 0, 0); print __METHOD__ . " result1=" . join(', ', $result1) . "\n"; // result[0,1,2,3,4,5,6,7,8] (total_ht, total_vat, total_ttc, pu_ht, pu_tva, pu_ttc, total_ht_without_discount, total_vat_without_discount, total_ttc_without_discount) $this->assertEquals(array(1.24, 0.12, 1.36, 1.24, 0.124, 1.364, 1.24, 0.12, 1.36, 0, 0, 0, 0, 0, 0, 0), $result1, 'Test1 FR'); /* * Country Spain */ // 10 * 10 HT - 0% discount with 10% vat, seller not using localtax1, not localtax2 (method we provide value) $mysoc->country_code = 'ES'; $mysoc->country_id = 4; $mysoc->localtax1_assuj = 0; $mysoc->localtax2_assuj = 0; $result2 = calcul_price_total(10, 10, 0, 10, 0, 0, 0, 'HT', 0, 0); // 10 * 10 HT - 0% discount with 10% vat and 1.4% localtax1, 0% localtax2 print __METHOD__ . " result2=" . join(', ', $result2) . "\n"; // result[0,1,2,3,4,5,6,7,8] (total_ht, total_vat, total_ttc, pu_ht, pu_tva, pu_ttc, total_ht_without_discount, total_vat_without_discount, total_ttc_without_discount) $this->assertEquals(array(100, 10, 110, 10, 1, 11, 100, 10, 110, 0, 0, 0, 0, 0, 0, 0), $result2, 'Test1 ES'); // 10 * 10 HT - 0% discount with 10% vat, seller not using localtax1, not localtax2 (other method autodetect) $mysoc->country_code = 'ES'; $mysoc->country_id = 4; $mysoc->localtax1_assuj = 0; $mysoc->localtax2_assuj = 0; $result2 = calcul_price_total(10, 10, 0, 10, -1, -1, 0, 'HT', 0, 0); // 10 * 10 HT - 0% discount with 10% vat and 1.4% localtax1, 0% localtax2 print __METHOD__ . " result2=" . join(', ', $result2) . "\n"; // result[0,1,2,3,4,5,6,7,8] (total_ht, total_vat, total_ttc, pu_ht, pu_tva, pu_ttc, total_ht_without_discount, total_vat_without_discount, total_ttc_without_discount) $this->assertEquals(array(100, 10, 110, 10, 1, 11, 100, 10, 110, 0, 0, 0, 0, 0, 0, 0), $result2, 'Test2 ES'); // -------------------------------------------------------- // 10 * 10 HT - 0% discount with 10% vat and 1.4% localtax1 type 3, 0% localtax2 type 5 (method we provide value) $mysoc->country_code = 'ES'; $mysoc->country_id = 4; $mysoc->localtax1_assuj = 1; $mysoc->localtax2_assuj = 0; $result2 = calcul_price_total(10, 10, 0, 10, 1.4, 0, 0, 'HT', 0, 0); print __METHOD__ . " result2=" . join(', ', $result2) . "\n"; // result[0,1,2,3,4,5,6,7,8] (total_ht, total_vat, total_ttc, pu_ht, pu_tva, pu_ttc, total_ht_without_discount, total_vat_without_discount, total_ttc_without_discount) $this->assertEquals(array(100, 10, 111.4, 10, 1, 11.14, 100, 10, 111.4, 1.4, 0, 0.14, 0, 0, 1.4, 0), $result2, 'Test3 ES'); // 10 * 10 HT - 0% discount with 10% vat and 1.4% localtax1 type 3, 0% localtax2 type 5 (other method autodetect) $mysoc->country_code = 'ES'; $mysoc->country_id = 4; $mysoc->localtax1_assuj = 1; $mysoc->localtax2_assuj = 0; $result2 = calcul_price_total(10, 10, 0, 10, -1, -1, 0, 'HT', 0, 0); print __METHOD__ . " result2=" . join(', ', $result2) . "\n"; // result[0,1,2,3,4,5,6,7,8] (total_ht, total_vat, total_ttc, pu_ht, pu_tva, pu_ttc, total_ht_without_discount, total_vat_without_discount, total_ttc_without_discount) $this->assertEquals(array(100, 10, 111.4, 10, 1, 11.14, 100, 10, 111.4, 1.4, 0, 0.14, 0, 0, 1.4, 0), $result2, 'Test4 ES'); // -------------------------------------------------------- // 10 * 10 HT - 0% discount with 10% vat and 0% localtax1 type 3, 19% localtax2 type 5 (method we provide value), we provide a service and not a product $mysoc->country_code = 'ES'; $mysoc->country_id = 4; $mysoc->localtax1_assuj = 0; $mysoc->localtax2_assuj = 1; $result2 = calcul_price_total(10, 10, 0, 10, 0, -19, 0, 'HT', 0, 1); // result[0,1,2,3,4,5,6,7,8] (total_ht, total_vat, total_ttc, pu_ht, pu_tva, pu_ttc, total_ht_without_discount, total_vat_without_discount, total_ttc_without_discount) $this->assertEquals(array(100, 10, 91, 10, 1, 9.1, 100, 10, 91, 0, -19, 0, -1.9, 0, 0, -19), $result2, 'Test5 ES for service'); // 10 * 10 HT - 0% discount with 10% vat and 0% localtax1 type 3, 21% localtax2 type 5 (other method autodetect), we provide a service and not a product $mysoc->country_code = 'ES'; $mysoc->country_id = 4; $mysoc->localtax1_assuj = 0; $mysoc->localtax2_assuj = 1; $result2 = calcul_price_total(10, 10, 0, 10, -1, -1, 0, 'HT', 0, 0); print __METHOD__ . " result2=" . join(', ', $result2) . "\n"; // result[0,1,2,3,4,5,6,7,8] (total_ht, total_vat, total_ttc, pu_ht, pu_tva, pu_ttc, total_ht_without_discount, total_vat_without_discount, total_ttc_without_discount) $this->assertEquals(array(100, 10, 110, 10, 1, 11, 100, 10, 110, 0, 0, 0, 0, 0, 0, 0), $result2, 'Test6 ES for product'); // 10 * 10 HT - 0% discount with 10% vat and 0% localtax1 type 3, 21% localtax2 type 5 (other method autodetect), we provide a product and not a service $mysoc->country_code = 'ES'; $mysoc->country_id = 4; $mysoc->localtax1_assuj = 0; $mysoc->localtax2_assuj = 1; $result2 = calcul_price_total(10, 10, 0, 10, -1, -1, 0, 'HT', 0, 1); print __METHOD__ . " result2=" . join(', ', $result2) . "\n"; // result[0,1,2,3,4,5,6,7,8] (total_ht, total_vat, total_ttc, pu_ht, pu_tva, pu_ttc, total_ht_without_discount, total_vat_without_discount, total_ttc_without_discount) $this->assertEquals(array(100, 10, 91, 10, 1, 9.1, 100, 10, 91, 0, -19, 0, -1.9, 0, 0, -19), $result2, 'Test6 ES for service'); // -------------------------------------------------------- // Credit Note: 10 * -10 HT - 0% discount with 10% vat and 0% localtax1 type 3, 19% localtax2 type 5 (method we provide value), we provide a product and not a service $mysoc->country_code = 'ES'; $mysoc->country_id = 4; $mysoc->localtax1_assuj = 0; $mysoc->localtax2_assuj = 1; $result2 = calcul_price_total(10, -10, 0, 10, 0, 19, 0, 'HT', 0, 0); print __METHOD__ . " result2=" . join(', ', $result2) . "\n"; // result[0,1,2,3,4,5,6,7,8] (total_ht, total_vat, total_ttc, pu_ht, pu_tva, pu_ttc, total_ht_without_discount, total_vat_without_discount, total_ttc_without_discount) $this->assertEquals(array(-100, -10, -110, -10, -1, -11, -100, -10, -110, 0, 0, 0, 0, 0, 0, 0), $result2, 'Test7 ES for product'); // Credit Note: 10 * -10 HT - 0% discount with 10% vat and 1.4% localtax1 type 3, 0% localtax2 type 5 (other method autodetect), we provide a service and not a product $mysoc->country_code = 'ES'; $mysoc->country_id = 4; $mysoc->localtax1_assuj = 0; $mysoc->localtax2_assuj = 1; $result2 = calcul_price_total(10, -10, 0, 10, -1, -1, 0, 'HT', 0, 1); print __METHOD__ . " result2=" . join(', ', $result2) . "\n"; $this->assertEquals(array(-100, -10, -91, -10, -1, -9.1, -100, -10, -91, 0, 19, 0, 1.9, 0, 0, 19), $result2, 'Test8 ES for service'); /* * Country Côte d'Ivoire */ // 10 * 10 HT - 0% discount with 18% vat, seller using localtax1 type 2, not localtax2 (method we provide value) $mysoc->country_code = 'CI'; $mysoc->country_id = 21; $mysoc->localtax1_assuj = 1; $mysoc->localtax2_assuj = 0; //$localtaxes=getLocalTaxesFromRate(18, 0, null, $mysoc); //var_dump($locataxes); $result3 = calcul_price_total(10, 10, 0, 18, 7.5, 0, 0, 'HT', 0, 0); // 10 * 10 HT - 0% discount with 18% vat and 7.5% localtax1, 0% localtax2 print __METHOD__ . " result3=" . join(', ', $result3) . "\n"; // result[0,1,2,3,4,5,6,7,8] (total_ht, total_vat, total_ttc, pu_ht, pu_tva, pu_ttc, total_ht_without_discount, total_vat_without_discount, total_ttc_without_discount) $this->assertEquals(array(100, 18, 126.85, 10, 1.8, 12.685, 100, 18, 126.85, 8.85, 0, 0.885, 0, 0, 8.85, 0), $result3, 'Test9 CI'); // 10 * 10 HT - 0% discount with 18% vat, seller using localtax1 type 2, not localtax2 (other method autodetect) $mysoc->country_code = 'CI'; $mysoc->country_id = 21; $mysoc->localtax1_assuj = 1; $mysoc->localtax2_assuj = 0; $result3 = calcul_price_total(10, 10, 0, 18, -1, -1, 0, 'HT', 0, 0); // 10 * 10 HT - 0% discount with 18% vat and 7.5% localtax1, 0% localtax2 print __METHOD__ . " result3=" . join(', ', $result3) . "\n"; // result[0,1,2,3,4,5,6,7,8] (total_ht, total_vat, total_ttc, pu_ht, pu_tva, pu_ttc, total_ht_without_discount, total_vat_without_discount, total_ttc_without_discount) $this->assertEquals(array(100, 18, 126.85, 10, 1.8, 12.685, 100, 18, 126.85, 8.85, 0, 0.885, 0, 0, 8.85, 0), $result3, 'Test10 CI'); return true; }
/** * Add a line to invoice * * @param int $facid Id de la facture * @param string $desc Description de la ligne * @param double $pu_ht Prix unitaire HT (> 0 even for credit note) * @param double $qty Quantite * @param double $txtva Taux de tva force, sinon -1 * @param int $fk_product Id du produit/service predefini * @param double $remise_percent Pourcentage de remise de la ligne * @param string $price_base_type HT or TTC * @param int $info_bits Bits de type de lignes * @param int $fk_remise_except Id remise * @param double $pu_ttc Prix unitaire TTC (> 0 even for credit note) * @param int $type Type of line (0=product, 1=service) * @param int $rang Position of line * @param int $special_code Special code * @return int <0 if KO, Id of line if OK */ function addline($facid, $desc, $pu_ht, $qty, $txtva, $fk_product = 0, $remise_percent = 0, $price_base_type = 'HT', $info_bits = 0, $fk_remise_except = '', $pu_ttc = 0, $type = 0, $rang = -1, $special_code = 0) { dol_syslog("FactureRec::addline facid={$facid},desc={$desc},pu_ht={$pu_ht},qty={$qty},txtva={$txtva},fk_product={$fk_product},remise_percent={$remise_percent},date_start={$date_start},date_end={$date_end},ventil={$ventil},info_bits={$info_bits},fk_remise_except={$fk_remise_except},price_base_type={$price_base_type},pu_ttc={$pu_ttc},type={$type}", LOG_DEBUG); include_once DOL_DOCUMENT_ROOT . '/core/lib/price.lib.php'; // Check parameters if ($type < 0) { return -1; } if ($this->brouillon) { // Clean parameters $remise_percent = price2num($remise_percent); $qty = price2num($qty); if (!$qty) { $qty = 1; } if (!$info_bits) { $info_bits = 0; } $pu_ht = price2num($pu_ht); $pu_ttc = price2num($pu_ttc); $txtva = price2num($txtva); if ($price_base_type == 'HT') { $pu = $pu_ht; } else { $pu = $pu_ttc; } // Calcul du total TTC et de la TVA pour la ligne a partir de // qty, pu, remise_percent et txtva // TRES IMPORTANT: C'est au moment de l'insertion ligne qu'on doit stocker // la part ht, tva et ttc, et ce au niveau de la ligne qui a son propre taux tva. $tabprice = calcul_price_total($qty, $pu, $remise_percent, $txtva, 0, 0, 0, $price_base_type, $info_bits); $total_ht = $tabprice[0]; $total_tva = $tabprice[1]; $total_ttc = $tabprice[2]; $product_type = $type; if ($fk_product) { $product = new Product($this->db); $result = $product->fetch($fk_product); $product_type = $product->type; } $sql = "INSERT INTO " . MAIN_DB_PREFIX . "facturedet_rec ("; $sql .= "fk_facture"; $sql .= ", description"; $sql .= ", price"; $sql .= ", qty"; $sql .= ", tva_tx"; $sql .= ", fk_product"; $sql .= ", product_type"; $sql .= ", remise_percent"; $sql .= ", subprice"; $sql .= ", remise"; $sql .= ", total_ht"; $sql .= ", total_tva"; $sql .= ", total_ttc"; $sql .= ", rang"; $sql .= ", special_code"; $sql .= ") VALUES ("; $sql .= "'" . $facid . "'"; $sql .= ", '" . $this->db->escape($desc) . "'"; $sql .= ", " . price2num($pu_ht); $sql .= ", " . price2num($qty); $sql .= ", " . price2num($txtva); $sql .= ", " . ($fk_product ? "'" . $fk_product . "'" : "null"); $sql .= ", " . $product_type; $sql .= ", '" . price2num($remise_percent) . "'"; $sql .= ", '" . price2num($pu_ht) . "'"; $sql .= ", null"; $sql .= ", '" . price2num($total_ht) . "'"; $sql .= ", '" . price2num($total_tva) . "'"; $sql .= ", '" . price2num($total_ttc) . "'"; $sql .= ", " . $rang; $sql .= ", " . $special_code . ")"; dol_syslog(get_class($this) . "::addline sql=" . $sql, LOG_DEBUG); if ($this->db->query($sql)) { $this->id = $facid; $this->update_price(); return 1; } else { $this->error = $this->db->lasterror(); dol_syslog("FactureRec::addline sql=" . $this->error, LOG_ERR); return -1; } } }
/** * getMarginInfos * * @param float $pvht Buying price with tax * @param float $remise_percent Discount percent * @param float $tva_tx Vat rate * @param float $localtax1_tx Vat rate special 1 * @param float $localtax2_tx Vat rate special 2 * @param int $fk_pa ??? * @param float $paht Buying price without tax * @return array Array of margin info */ function getMarginInfos($pvht, $remise_percent, $tva_tx, $localtax1_tx, $localtax2_tx, $fk_pa, $paht) { global $db, $conf; $marge_tx_ret=''; $marque_tx_ret=''; if($fk_pa > 0) { require_once DOL_DOCUMENT_ROOT."/fourn/class/fournisseur.product.class.php"; $product = new ProductFournisseur($db); if ($product->fetch_product_fournisseur_price($fk_pa)) { $paht_ret = $product->fourn_unitprice; if ($conf->global->MARGIN_TYPE == "2" && $product->fourn_unitcharges > 0) $paht_ret += $product->fourn_unitcharges; } else $paht_ret = $paht; } else $paht_ret = $paht; require_once(DOL_DOCUMENT_ROOT.'/core/lib/price.lib.php'); // calcul pu_ht remisés $tabprice=calcul_price_total(1, $pvht, $remise_percent, $tva_tx, $localtax1_tx, $localtax2_tx, 0, 'HT'); $pu_ht_remise = $tabprice[0]; // calcul taux marge if ($paht_ret != 0) $marge_tx_ret = round((100 * ($pu_ht_remise - $paht_ret)) / $paht_ret, 3); // calcul taux marque if ($pu_ht_remise != 0) $marque_tx_ret = round((100 * ($pu_ht_remise - $paht_ret)) / $pu_ht_remise, 3); return array($paht_ret, $marge_tx_ret, $marque_tx_ret); }
/** * Update database for contract line * * @param User $user User that modify * @param int $notrigger 0=no, 1=yes (no update trigger) * @return int <0 if KO, >0 if OK */ function update($user, $notrigger = 0) { global $conf, $langs; $error = 0; // Clean parameters $this->fk_contrat = trim($this->fk_contrat); $this->fk_product = trim($this->fk_product); $this->statut = trim($this->statut); $this->label = trim($this->label); $this->description = trim($this->description); $this->tva_tx = trim($this->tva_tx); $this->localtax1_tx = trim($this->localtax1_tx); $this->localtax2_tx = trim($this->localtax2_tx); $this->qty = trim($this->qty); $this->remise_percent = trim($this->remise_percent); $this->remise = trim($this->remise); $this->fk_remise_except = trim($this->fk_remise_except); $this->subprice = price2num($this->subprice); $this->price_ht = price2num($this->price_ht); $this->total_ht = trim($this->total_ht); $this->total_tva = trim($this->total_tva); $this->total_localtax1 = trim($this->total_localtax1); $this->total_localtax2 = trim($this->total_localtax2); $this->total_ttc = trim($this->total_ttc); $this->info_bits = trim($this->info_bits); $this->fk_user_author = trim($this->fk_user_author); $this->fk_user_ouverture = trim($this->fk_user_ouverture); $this->fk_user_cloture = trim($this->fk_user_cloture); $this->commentaire = trim($this->commentaire); // Check parameters // Put here code to add control on parameters values // Calcul du total TTC et de la TVA pour la ligne a partir de // qty, pu, remise_percent et txtva // TRES IMPORTANT: C'est au moment de l'insertion ligne qu'on doit stocker // la part ht, tva et ttc, et ce au niveau de la ligne qui a son propre taux tva. $tabprice = calcul_price_total($this->qty, $this->price_ht, $this->remise_percent, $this->tva_tx, $this->localtax1_tx, $this->localtax2_tx, 0, 'HT', 0, 1); $this->total_ht = $tabprice[0]; $this->total_tva = $tabprice[1]; $this->total_ttc = $tabprice[2]; $this->total_localtax1 = $tabprice[9]; $this->total_localtax2 = $tabprice[10]; if (empty($this->pa_ht)) { $this->pa_ht = 0; } // si prix d'achat non renseigné et utilisé pour calcul des marges alors prix achat = prix vente if ($this->pa_ht == 0) { if ($this->subprice > 0 && (isset($conf->global->ForceBuyingPriceIfNull) && $conf->global->ForceBuyingPriceIfNull == 1)) { $this->pa_ht = $this->subprice * (1 - $this->remise_percent / 100); } } $this->db->begin(); // Update request $sql = "UPDATE " . MAIN_DB_PREFIX . "contratdet SET"; $sql .= " fk_contrat='" . $this->fk_contrat . "',"; $sql .= " fk_product=" . ($this->fk_product ? "'" . $this->fk_product . "'" : 'null') . ","; $sql .= " statut='" . $this->statut . "',"; $sql .= " label='" . $this->db->escape($this->label) . "',"; $sql .= " description='" . $this->db->escape($this->description) . "',"; $sql .= " date_commande=" . ($this->date_commande != '' ? "'" . $this->db->idate($this->date_commande) . "'" : "null") . ","; $sql .= " date_ouverture_prevue=" . ($this->date_ouverture_prevue != '' ? "'" . $this->db->idate($this->date_ouverture_prevue) . "'" : "null") . ","; $sql .= " date_ouverture=" . ($this->date_ouverture != '' ? "'" . $this->db->idate($this->date_ouverture) . "'" : "null") . ","; $sql .= " date_fin_validite=" . ($this->date_fin_validite != '' ? "'" . $this->db->idate($this->date_fin_validite) . "'" : "null") . ","; $sql .= " date_cloture=" . ($this->date_cloture != '' ? "'" . $this->db->idate($this->date_cloture) . "'" : "null") . ","; $sql .= " tva_tx='" . $this->tva_tx . "',"; $sql .= " localtax1_tx='" . $this->localtax1_tx . "',"; $sql .= " localtax2_tx='" . $this->localtax2_tx . "',"; $sql .= " qty='" . $this->qty . "',"; $sql .= " remise_percent='" . $this->remise_percent . "',"; $sql .= " remise=" . ($this->remise ? "'" . $this->remise . "'" : "null") . ","; $sql .= " fk_remise_except=" . ($this->fk_remise_except ? "'" . $this->fk_remise_except . "'" : "null") . ","; $sql .= " subprice='" . $this->subprice . "',"; $sql .= " price_ht='" . $this->price_ht . "',"; $sql .= " total_ht='" . $this->total_ht . "',"; $sql .= " total_tva='" . $this->total_tva . "',"; $sql .= " total_localtax1='" . $this->total_localtax1 . "',"; $sql .= " total_localtax2='" . $this->total_localtax2 . "',"; $sql .= " total_ttc='" . $this->total_ttc . "',"; $sql .= " fk_product_fournisseur_price=" . (!empty($this->fk_fournprice) ? $this->fk_fournprice : "NULL") . ","; $sql .= " buy_price_ht='" . price2num($this->pa_ht) . "',"; $sql .= " info_bits='" . $this->info_bits . "',"; $sql .= " fk_user_author=" . ($this->fk_user_author >= 0 ? $this->fk_user_author : "NULL") . ","; $sql .= " fk_user_ouverture=" . ($this->fk_user_ouverture > 0 ? $this->fk_user_ouverture : "NULL") . ","; $sql .= " fk_user_cloture=" . ($this->fk_user_cloture > 0 ? $this->fk_user_cloture : "NULL") . ","; $sql .= " commentaire='" . $this->db->escape($this->commentaire) . "'"; $sql .= " WHERE rowid=" . $this->id; dol_syslog(get_class($this) . "::update", LOG_DEBUG); $resql = $this->db->query($sql); if ($resql) { $contrat = new Contrat($this->db); $contrat->fetch($this->fk_contrat); $result = $contrat->update_statut($user); } else { $this->error = "Error " . $this->db->lasterror(); $this->db->rollback(); return -1; } if (!$notrigger) { // Call trigger $result = $this->call_trigger('LINECONTRACT_UPDATE', $user); if ($result < 0) { $error++; $this->db->rollback(); return -1; } // End call triggers } $this->db->commit(); return 1; }
/** * Update line * @param rowid Id de la ligne de facture * @param desc Description de la ligne * @param pu Prix unitaire * @param qty Quantity * @param remise_percent Pourcentage de remise de la ligne * @param tva_tx Taux TVA * @param localtax1_tx Localtax1 tax * @param localtax2_tx Localtax2 tax * @param price_base_type Type of price base * @param info_bits Miscellanous informations * @param type Type of line (0=product, 1=service) * @return int < 0 if error, > 0 if ok */ function updateline($rowid, $desc, $pu, $qty, $remise_percent=0, $txtva, $txlocaltax1=0, $txlocaltax2=0, $price_base_type='HT', $info_bits=0, $type=0) { dol_syslog("CommandeFournisseur::UpdateLine $rowid, $desc, $pu, $qty, $remise_percent, $txtva, $price_base_type, $info_bits, $type"); include_once(DOL_DOCUMENT_ROOT.'/lib/price.lib.php'); if ($this->brouillon) { $this->db->begin(); // Clean parameters if (empty($qty)) $qty=0; if (empty($info_bits)) $info_bits=0; if (empty($txtva)) $txtva=0; if (empty($txlocaltax1)) $txlocaltax1=0; if (empty($txlocaltax2)) $txlocaltax2=0; if (empty($remise)) $remise=0; if (empty($remise_percent)) $remise_percent=0; $remise_percent=price2num($remise_percent); $qty=price2num($qty); if (! $qty) $qty=1; $pu = price2num($pu); $txtva=price2num($txtva); $txlocaltax1=price2num($txlocaltax1); $txlocaltax2=price2num($txlocaltax2); // Check parameters if ($type < 0) return -1; // Calcul du total TTC et de la TVA pour la ligne a partir de // qty, pu, remise_percent et txtva // TRES IMPORTANT: C'est au moment de l'insertion ligne qu'on doit stocker // la part ht, tva et ttc, et ce au niveau de la ligne qui a son propre taux tva. $tabprice=calcul_price_total($qty, $pu, $remise_percent, $txtva, $txlocaltax1, $txlocaltax2, 0, $price_base_type, $info_bits); $total_ht = $tabprice[0]; $total_tva = $tabprice[1]; $total_ttc = $tabprice[2]; $total_localtax1 = $tabprice[9]; $total_localtax2 = $tabprice[10]; // Anciens indicateurs: $price, $subprice, $remise (a ne plus utiliser) $subprice = $pu; $remise = 0; if ($remise_percent > 0) { $remise = round(($pu * $remise_percent / 100),2); } $subprice = price2num($subprice); // Mise a jour ligne en base $sql = "UPDATE ".MAIN_DB_PREFIX."commande_fournisseurdet SET"; $sql.= " description='".$this->db->escape($desc)."'"; $sql.= ",subprice='".price2num($subprice)."'"; $sql.= ",remise='".price2num($remise)."'"; $sql.= ",remise_percent='".price2num($remise_percent)."'"; $sql.= ",tva_tx='".price2num($txtva)."'"; $sql.= ",localtax1_tx='".price2num($txlocaltax1)."'"; $sql.= ",localtax2_tx='".price2num($txlocaltax2)."'"; $sql.= ",qty='".price2num($qty)."'"; if ($date_end) { $sql.= ",date_start='$date_end'"; } else { $sql.=',date_start=null'; } if ($date_end) { $sql.= ",date_end='$date_end'"; } else { $sql.=',date_end=null'; } $sql.= ",info_bits='".$info_bits."'"; $sql.= ",total_ht='".price2num($total_ht)."'"; $sql.= ",total_tva='".price2num($total_tva)."'"; $sql.= ",total_localtax1='".price2num($total_localtax1)."'"; $sql.= ",total_localtax2='".price2num($total_localtax2)."'"; $sql.= ",total_ttc='".price2num($total_ttc)."'"; $sql.= ",product_type='".$type."'"; $sql.= " WHERE rowid = ".$rowid; dol_syslog("CommandeFournisseur::updateline sql=".$sql); $result = $this->db->query( $sql); if ($result > 0) { // Mise a jour info denormalisees au niveau facture $this->update_price(); $this->db->commit(); return $result; } else { $this->error=$this->db->error(); dol_syslog("CommandeFournisseur::updateline ".$this->error, LOG_ERR); $this->db->rollback(); return -1; } } else { $this->error="Order status makes operation forbidden"; dol_syslog("CommandeFournisseur::updateline ".$this->error, LOG_ERR); return -2; } }
/** * \brief Ajoute une ligne de contrat en base * \param desc Description de la ligne * \param pu_ht Prix unitaire HT * \param qty Quantite * \param txtva Taux tva * \param txlocaltax1 Local tax 1 rate * \param txlocaltax2 Local tax 2 rate * \param fk_product Id produit * \param remise_percent Pourcentage de remise de la ligne * \param date_start Date de debut prevue * \param date_end Date de fin prevue * \param price_base_type HT ou TTC * \param pu_ttc Prix unitaire TTC * \param info_bits Bits de type de lignes * \return int <0 si erreur, >0 si ok */ function addline($desc, $pu_ht, $qty, $txtva, $txlocaltax1=0, $txlocaltax2=0, $fk_product=0, $remise_percent=0, $date_start, $date_end, $price_base_type='HT', $pu_ttc=0, $info_bits=0) { global $user, $langs, $conf; dol_syslog("Contrat::addline $desc, $pu_ht, $qty, $txtva, $txlocaltax1, $txlocaltax2, $fk_product, $remise_percent, $date_start, $date_end, $price_base_type, $pu_ttc, $info_bits"); if ($this->statut >= 0) { $this->db->begin(); // Clean parameters $remise_percent=price2num($remise_percent); $qty=price2num($qty); if (! $qty) $qty=1; if (! $ventil) $ventil=0; if (! $info_bits) $info_bits=0; if (! $pu_ht) $pu_ht=0; if (! $pu_ttc) $pu_ttc=0; $pu_ht=price2num($pu_ht); $pu_ttc=price2num($pu_ttc); $txtva=price2num($txtva); $txlocaltax1=price2num($txlocaltax1); $txlocaltax2=price2num($txlocaltax2); if ($price_base_type=='HT') { $pu=$pu_ht; } else { $pu=$pu_ttc; } // Calcul du total TTC et de la TVA pour la ligne a partir de // qty, pu, remise_percent et txtva // TRES IMPORTANT: C'est au moment de l'insertion ligne qu'on doit stocker // la part ht, tva et ttc, et ce au niveau de la ligne qui a son propre taux tva. $tabprice=calcul_price_total($qty, $pu, $remise_percent, $txtva, $txlocaltax1, $txlocaltax2, 0, $price_base_type, $info_bits); $total_ht = $tabprice[0]; $total_tva = $tabprice[1]; $total_ttc = $tabprice[2]; $total_localtax1= $tabprice[9]; $total_localtax2= $tabprice[10]; // TODO A virer // Anciens indicateurs: $price, $remise (a ne plus utiliser) $remise = 0; $price = price2num(round($pu_ht, 2)); if (dol_strlen($remise_percent) > 0) { $remise = round(($pu_ht * $remise_percent / 100), 2); $price = $pu_ht - $remise; } // Insertion dans la base $sql = "INSERT INTO ".MAIN_DB_PREFIX."contratdet"; $sql.= " (fk_contrat, label, description, fk_product, qty, tva_tx,"; $sql.= " localtax1_tx, localtax2_tx, remise_percent, subprice,"; $sql.= " total_ht, total_tva, total_localtax1, total_localtax2, total_ttc,"; $sql.= " info_bits,"; $sql.= " price_ht, remise"; // TODO A virer if ($date_start > 0) { $sql.= ",date_ouverture_prevue"; } if ($date_end > 0) { $sql.= ",date_fin_validite"; } $sql.= ") VALUES ($this->id, '" . $this->db->escape($label) . "','" . $this->db->escape($desc) . "',"; $sql.= ($fk_product>0 ? $fk_product : "null").","; $sql.= " '".$qty."',"; $sql.= " '".$txtva."',"; $sql.= " '".$txlocaltax1."',"; $sql.= " '".$txlocaltax2."',"; $sql.= " ".price2num($remise_percent).",".price2num($pu_ht).","; $sql.= " ".price2num($total_ht).",".price2num($total_tva).",".price2num($total_localtax1).",".price2num($total_localtax2).",".price2num($total_ttc).","; $sql.= " '".$info_bits."',"; $sql.= " ".price2num($price).",".price2num( $remise); // TODO A virer if ($date_start > 0) { $sql.= ",".$this->db->idate($date_start); } if ($date_end > 0) { $sql.= ",".$this->db->idate($date_end); } $sql.= ")"; dol_syslog("Contrat::addline sql=".$sql); $resql=$this->db->query($sql); if ($resql) { $result=$this->update_statut($user); if ($result > 0) { $this->db->commit(); return 1; } else { dol_syslog("Error sql=$sql, error=".$this->error,LOG_ERR); $this->db->rollback(); return -1; } } else { $this->db->rollback(); $this->error=$this->db->error()." sql=".$sql; dol_syslog("Contrat::addline ".$this->error,LOG_ERR); return -1; } } else { dol_syslog("Contrat::addline ErrorTryToAddLineOnValidatedContract", LOG_ERR); return -2; } }
/** * Load lines * * @return int >0 if OK, Otherwise if KO */ function fetch_lines() { // TODO: recuperer les champs du document associe a part $sql = "SELECT cd.rowid, cd.fk_product, cd.description, cd.qty as qty_asked"; $sql .= ", cd.total_ht, cd.total_localtax1, cd.total_localtax2, cd.total_ttc, cd.total_tva"; $sql .= ", cd.tva_tx, cd.localtax1_tx, cd.localtax2_tx, cd.price, cd.subprice"; $sql .= ", ed.qty as qty_shipped, ed.fk_origin_line, ed.fk_entrepot"; $sql .= ", p.ref as product_ref, p.label as product_label, p.fk_product_type, p.weight, p.weight_units, p.volume, p.volume_units"; $sql .= " FROM (" . MAIN_DB_PREFIX . "expeditiondet as ed,"; $sql .= " " . MAIN_DB_PREFIX . "commandedet as cd)"; $sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "product as p ON p.rowid = cd.fk_product"; $sql .= " WHERE ed.fk_expedition = " . $this->id; $sql .= " AND ed.fk_origin_line = cd.rowid"; dol_syslog(get_class($this) . "::fetch_lines sql=" . $sql); $resql = $this->db->query($sql); if ($resql) { include_once DOL_DOCUMENT_ROOT . '/core/lib/price.lib.php'; $num = $this->db->num_rows($resql); $i = 0; $this->total_ht = 0; $this->total_tva = 0; $this->total_ttc = 0; $this->total_localtax1 = 0; $this->total_localtax2 = 0; while ($i < $num) { $line = new ExpeditionLigne($this->db); $obj = $this->db->fetch_object($resql); $line->fk_origin_line = $obj->fk_origin_line; $line->origin_line_id = $obj->fk_origin_line; // TODO deprecated $line->entrepot_id = $obj->fk_entrepot; $line->fk_product = $obj->fk_product; $line->fk_product_type = $obj->fk_product_type; $line->ref = $obj->product_ref; // TODO deprecated $line->product_ref = $obj->product_ref; $line->product_label = $obj->product_label; //$line->label = $obj->product_label; $line->libelle = $obj->product_label; // TODO deprecated $line->description = $obj->description; $line->qty_asked = $obj->qty_asked; $line->qty_shipped = $obj->qty_shipped; $line->weight = $obj->weight; $line->weight_units = $obj->weight_units; $line->volume = $obj->volume; $line->volume_units = $obj->volume_units; //Invoicing $line->desc = $obj->product_label; $line->qty = $obj->qty_shipped; $line->total_ht = $obj->total_ht; $line->total_localtax1 = $obj->total_localtax1; $line->total_localtax2 = $obj->total_localtax2; $line->total_ttc = $obj->total_ttc; $line->total_tva = $obj->total_tva; $line->tva_tx = $obj->tva_tx; $line->localtax1_tx = $obj->localtax1_tx; $line->localtax2_tx = $obj->localtax2_tx; $line->price = $obj->price; $line->subprice = $obj->subprice; $line->remise_percent = $obj->remise_percent; $tabprice = calcul_price_total($obj->qty_shipped, $obj->subprice, $obj->remise_percent, $obj->tva_tx, $obj->localtax1_tx, $obj->localtax2_tx, 0, 'HT', $info_bits); $this->total_ht += $tabprice[0]; $this->total_tva += $tabprice[1]; $this->total_ttc += $tabprice[2]; $this->total_localtax1 += $tabprice[9]; $this->total_localtax2 += $tabprice[10]; $this->lines[$i] = $line; $i++; } $this->db->free($resql); return 1; } else { $this->error = $this->db->error(); dol_syslog(get_class($this) . '::fetch_lines: Error ' . $this->error, LOG_ERR); return -3; } }