Пример #1
0
 /**
  *  Mets a jour une ligne de contrat
  *
  *  @param	int			$rowid            	Id de la ligne de facture
  *  @param  string		$desc             	Description de la ligne
  *  @param  float		$pu               	Prix unitaire
  *  @param  int			$qty              	Quantite
  *  @param  float		$remise_percent   	Pourcentage de remise de la ligne
  *  @param  int			$date_start       	Date de debut prevue
  *  @param  int			$date_end         	Date de fin prevue
  *  @param  float		$tvatx            	Taux TVA
  *  @param  float		$localtax1tx      	Local tax 1 rate
  *  @param  float		$localtax2tx      	Local tax 2 rate
  *  @param  int|string	$date_debut_reel  	Date de debut reelle
  *  @param  int|string	$date_fin_reel    	Date de fin reelle
  *	@param	string		$price_base_type	HT or TTC
  * 	@param  int			$info_bits			Bits de type de lignes
  * 	@param  int			$fk_fournprice		Fourn price id
  *  @param  int			$pa_ht				Buying price HT
  *  @return int              				< 0 si erreur, > 0 si ok
  */
 function updateline($rowid, $desc, $pu, $qty, $remise_percent, $date_start, $date_end, $tvatx, $localtax1tx = 0.0, $localtax2tx = 0.0, $date_debut_reel = '', $date_fin_reel = '', $price_base_type = 'HT', $info_bits = 0, $fk_fournprice = null, $pa_ht = 0)
 {
     global $user, $conf, $langs, $mysoc;
     // Nettoyage parametres
     $qty = trim($qty);
     $desc = trim($desc);
     $desc = trim($desc);
     $price = price2num($pu);
     $tvatx = price2num($tvatx);
     $localtax1tx = price2num($localtax1tx);
     $localtax2tx = price2num($localtax2tx);
     $pa_ht = price2num($pa_ht);
     $subprice = $price;
     $remise = 0;
     if (dol_strlen($remise_percent) > 0) {
         $remise = round($pu * $remise_percent / 100, 2);
         $price = $pu - $remise;
     } else {
         $remise_percent = 0;
     }
     dol_syslog(get_class($this) . "::updateline {$rowid}, {$desc}, {$pu}, {$qty}, {$remise_percent}, {$date_start}, {$date_end}, {$date_debut_reel}, {$date_fin_reel}, {$tvatx}, {$localtax1tx}, {$localtax2tx}, {$price_base_type}, {$info_bits}");
     $this->db->begin();
     // Calcul du total TTC et de la TVA pour la ligne a partir de
     // qty, pu, remise_percent et tvatx
     // 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($tvatx, 0, $this->societe, $mysoc);
     $tabprice = calcul_price_total($qty, $pu, $remise_percent, $tvatx, $localtax1tx, $localtax2tx, 0, $price_base_type, $info_bits, 1, '', $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];
     // TODO A virer
     // Anciens indicateurs: $price, $remise (a ne plus utiliser)
     $remise = 0;
     $price = price2num(round($pu, 2));
     if (dol_strlen($remise_percent) > 0) {
         $remise = round($pu * $remise_percent / 100, 2);
         $price = $pu - $remise;
     }
     if (empty($pa_ht)) {
         $pa_ht = 0;
     }
     // si prix d'achat non renseigne et utilise pour calcul des marges alors prix achat = prix vente
     if ($pa_ht == 0) {
         if ($pu > 0 && (isset($conf->global->ForceBuyingPriceIfNull) && $conf->global->ForceBuyingPriceIfNull == 1)) {
             $pa_ht = $pu * (1 - $remise_percent / 100);
         }
     }
     $sql = "UPDATE " . MAIN_DB_PREFIX . "contratdet set description='" . $this->db->escape($desc) . "'";
     $sql .= ",price_ht='" . price2num($price) . "'";
     $sql .= ",subprice='" . price2num($subprice) . "'";
     $sql .= ",remise='" . price2num($remise) . "'";
     $sql .= ",remise_percent='" . price2num($remise_percent) . "'";
     $sql .= ",qty='" . $qty . "'";
     $sql .= ",tva_tx='" . price2num($tvatx) . "'";
     $sql .= ",localtax1_tx='" . price2num($localtax1tx) . "'";
     $sql .= ",localtax2_tx='" . price2num($localtax2tx) . "'";
     $sql .= ",localtax1_type='" . $localtax1_type . "'";
     $sql .= ",localtax2_type='" . $localtax2_type . "'";
     $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 .= ", fk_product_fournisseur_price='" . $fk_fournprice . "'";
     $sql .= ", buy_price_ht='" . price2num($pa_ht) . "'";
     if ($date_start > 0) {
         $sql .= ",date_ouverture_prevue='" . $this->db->idate($date_start) . "'";
     } else {
         $sql .= ",date_ouverture_prevue=null";
     }
     if ($date_end > 0) {
         $sql .= ",date_fin_validite='" . $this->db->idate($date_end) . "'";
     } else {
         $sql .= ",date_fin_validite=null";
     }
     if ($date_debut_reel > 0) {
         $sql .= ",date_ouverture='" . $this->db->idate($date_debut_reel) . "'";
     } else {
         $sql .= ",date_ouverture=null";
     }
     if ($date_fin_reel > 0) {
         $sql .= ",date_cloture='" . $this->db->idate($date_fin_reel) . "'";
     } else {
         $sql .= ",date_cloture=null";
     }
     $sql .= " WHERE rowid = " . $rowid;
     dol_syslog(get_class($this) . "::updateline", LOG_DEBUG);
     $result = $this->db->query($sql);
     if ($result) {
         $result = $this->update_statut($user);
         if ($result >= 0) {
             // Call trigger
             $result = $this->call_trigger('LINECONTRACT_UPDATE', $user);
             if ($result < 0) {
                 $this->db->rollback();
                 return -3;
             }
             // End call triggers
             $this->db->commit();
             return 1;
         } else {
             $this->db->rollback();
             dol_syslog(get_class($this) . "::updateligne Erreur -2");
             return -2;
         }
     } else {
         $this->db->rollback();
         $this->error = $this->db->error();
         dol_syslog(get_class($this) . "::updateligne Erreur -1");
         return -1;
     }
 }
Пример #2
0
 /**
  *  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_options		extrafields array
  * 	@param      int         $situation_percent  Situation advance percentage
  * 	@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, $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_options = 0, $situation_percent = 0, $fk_unit = null)
 {
     // Deprecation warning
     if ($label) {
         dol_syslog(__METHOD__ . ": using line label is deprecated", LOG_WARNING);
     }
     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} fk_unit={$fk_unit}", 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;
         }
         if ($situation_percent > 100 || is_null($situation_percent) || $situation_percent == "") {
             $situation_percent = 100;
         }
         $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);
         $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, $situation_percent);
         $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);
         //Fetch current line from the database and then clone the object and set it in $oldline property
         $line = new FactureLigne($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 = $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 = $total_tva;
         $this->line->total_localtax1 = $total_localtax1;
         $this->line->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;
         $this->line->situation_percent = $situation_percent;
         $this->line->fk_unit = $fk_unit;
         $this->line->fk_fournprice = $fk_fournprice;
         $this->line->pa_ht = $pa_ht;
         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 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 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;
     }
 }
Пример #4
0
 /**
  *  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;
     }
 }
Пример #5
0
 /**
  *  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;
     }
 }
 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;
 }
 // les variables
 $cptcli = !empty($conf->global->COMPTA_ACCOUNT_CUSTOMER) ? $conf->global->COMPTA_ACCOUNT_CUSTOMER : $langs->trans("CodeNotDef");
 $compta_soc = !empty($obj->code_compta) ? $obj->code_compta : $cptcli;
 $compta_prod = $obj->accountancy_code_sell;
 if (empty($compta_prod)) {
     if ($obj->product_type == 0) {
         $compta_prod = !empty($conf->global->COMPTA_PRODUCT_SOLD_ACCOUNT) ? $conf->global->COMPTA_PRODUCT_SOLD_ACCOUNT : $langs->trans("CodeNotDef");
     } else {
         $compta_prod = !empty($conf->global->COMPTA_SERVICE_SOLD_ACCOUNT) ? $conf->global->COMPTA_SERVICE_SOLD_ACCOUNT : $langs->trans("CodeNotDef");
     }
 }
 $cpttva = !empty($conf->global->COMPTA_VAT_ACCOUNT) ? $conf->global->COMPTA_VAT_ACCOUNT : $langs->trans("CodeNotDef");
 $compta_tva = !empty($obj->account_tva) ? $obj->account_tva : $cpttva;
 $account_localtax1 = getLocalTaxesFromRate($obj->tva_tx, 1, $mysoc);
 $compta_localtax1 = !empty($account_localtax1[3]) ? $account_localtax1[3] : $langs->trans("CodeNotDef");
 $account_localtax2 = getLocalTaxesFromRate($obj->tva_tx, 2, $mysoc);
 $compta_localtax2 = !empty($account_localtax2[3]) ? $account_localtax2[3] : $langs->trans("CodeNotDef");
 //la ligne facture
 $tabfac[$obj->rowid]["date"] = $obj->datef;
 $tabfac[$obj->rowid]["ref"] = $obj->facnumber;
 $tabfac[$obj->rowid]["type"] = $obj->type;
 if (!isset($tabttc[$obj->rowid][$compta_soc])) {
     $tabttc[$obj->rowid][$compta_soc] = 0;
 }
 if (!isset($tabht[$obj->rowid][$compta_prod])) {
     $tabht[$obj->rowid][$compta_prod] = 0;
 }
 if (!isset($tabtva[$obj->rowid][$compta_tva])) {
     $tabtva[$obj->rowid][$compta_tva] = 0;
 }
 if (!isset($tablocaltax1[$obj->rowid][$compta_localtax1])) {
Пример #8
0
     // contrôles
     $compta_soc = !empty($obj->code_compta_fournisseur) ? $obj->code_compta_fournisseur : $cptfour;
     $compta_prod = $obj->accountancy_code_buy;
     if (empty($compta_prod)) {
         if ($obj->product_type == 0) {
             $compta_prod = !empty($conf->global->ACCOUNTING_PRODUCT_BUY_ACCOUNT) ? $conf->global->ACCOUNTING_PRODUCT_BUY_ACCOUNT : $langs->trans("CodeNotDef");
         } else {
             $compta_prod = !empty($conf->global->ACCOUNTING_SERVICE_BUY_ACCOUNT) ? $conf->global->ACCOUNTING_SERVICE_BUY_ACCOUNT : $langs->trans("CodeNotDef");
         }
     }
     $compta_tva = !empty($obj->account_tva) ? $obj->account_tva : $cpttva;
     $compta_localtax1 = !empty($obj->account_localtax1) ? $obj->account_localtax1 : $langs->trans("CodeNotDef");
     $compta_localtax2 = !empty($obj->account_localtax2) ? $obj->account_localtax2 : $langs->trans("CodeNotDef");
     $account_localtax1 = getLocalTaxesFromRate($obj->tva_tx, 1, $mysoc, $obj->thirdparty);
     $compta_localtax1 = !empty($account_localtax1[2]) ? $account_localtax1[2] : $langs->trans("CodeNotDef");
     $account_localtax2 = getLocalTaxesFromRate($obj->tva_tx, 2, $mysoc, $obj->thirdparty);
     $compta_localtax2 = !empty($account_localtax2[2]) ? $account_localtax2[2] : $langs->trans("CodeNotDef");
     $tabfac[$obj->rowid]["date"] = $obj->datef;
     $tabfac[$obj->rowid]["ref"] = $obj->ref_supplier;
     $tabfac[$obj->rowid]["type"] = $obj->type;
     $tabfac[$obj->rowid]["lib"] = $obj->libelle;
     $tabttc[$obj->rowid][$compta_soc] += $obj->total_ttc;
     $tabht[$obj->rowid][$compta_prod] += $obj->total_ht;
     if ($obj->recuperableonly != 1) {
         $tabtva[$obj->rowid][$compta_tva] += $obj->total_tva;
     }
     $tablocaltax1[$obj->rowid][$compta_localtax1] += $obj->total_localtax1;
     $tablocaltax2[$obj->rowid][$compta_localtax2] += $obj->total_localtax2;
     $tabcompany[$obj->rowid] = array('id' => $obj->socid, 'name' => $obj->name);
     $i++;
 }
 /**
  * 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;
     }
 }
 /**
  *	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;
     }
 }
     if (!empty($conf->global->MAIN_USE_LOCALTAX_TYPE_7)) {
         if ($this->total_localtax1 == 0) {
             global $mysoc;
             $localtax1_array = getLocalTaxesFromRate($vatrate, 1, $mysoc);
             if (empty($obj->localtax1_type)) {
                 $obj->localtax1_type = $localtax1_array[0];
                 $obj->localtax1_tx = $localtax1_array[1];
             }
             if ($obj->localtax1_type == '7') {
                 $total_localtax1 += $obj->localtax1_tx;
                 $total_ttc += $obj->localtax1_tx;
             }
         }
         if ($this->total_localtax2 == 0) {
             global $mysoc;
             $localtax2_array = getLocalTaxesFromRate($vatrate, 2, $mysoc);
             if (empty($obj->localtax2_type)) {
                 $obj->localtax2_type = $localtax2_array[0];
                 $obj->localtax2_tx = $localtax2_array[1];
             }
             if ($obj->localtax2_type == '7') {
                 $total_localtax2 += $obj->localtax2_tx;
                 $total_ttc += $obj->localtax2_tx;
             }
         }
     }
     $i++;
 }
 $db->free($resql);
 $fieldht = 'total_ht';
 $fieldtva = 'tva';
Пример #12
0
 /**
  *      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;
     }
 }
Пример #13
0
 /**
  *  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;
     }
 }
 /**
  *  Function to build pdf onto disk
  *
  *  @param		Object		$object				Object to generate
  *  @param		Translate	$outputlangs		Lang output object
  *  @param		string		$srctemplatepath	Full path of source filename for generator using a template file
  *  @param		int			$hidedetails		Do not show line details
  *  @param		int			$hidedesc			Do not show desc
  *  @param		int			$hideref			Do not show ref
  *  @param		object		$hookmanager		Hookmanager object
  *  @return     int         	    			1=OK, 0=KO
  */
 function write_file($object, $outputlangs, $srctemplatepath = '', $hidedetails = 0, $hidedesc = 0, $hideref = 0, $hookmanager = false)
 {
     global $user, $langs, $conf, $mysoc, $db;
     if (!is_object($outputlangs)) {
         $outputlangs = $langs;
     }
     // For backward compatibility with FPDF, force output charset to ISO, because FPDF expect text to be encoded in ISO
     if (!empty($conf->global->MAIN_USE_FPDF)) {
         $outputlangs->charset_output = 'ISO-8859-1';
     }
     $outputlangs->load("main");
     $outputlangs->load("dict");
     $outputlangs->load("companies");
     $outputlangs->load("bills");
     $outputlangs->load("products");
     if ($conf->facture->dir_output) {
         $object->fetch_thirdparty();
         $deja_regle = $object->getSommePaiement();
         $amount_credit_notes_included = $object->getSumCreditNotesUsed();
         $amount_deposits_included = $object->getSumDepositsUsed();
         // Definition of $dir and $file
         if ($object->specimen) {
             $dir = $conf->facture->dir_output;
             $file = $dir . "/SPECIMEN.pdf";
         } else {
             $objectref = dol_sanitizeFileName($object->ref);
             $dir = $conf->facture->dir_output . "/" . $objectref;
             $file = $dir . "/" . $objectref . ".pdf";
         }
         if (!file_exists($dir)) {
             if (dol_mkdir($dir) < 0) {
                 $this->error = $langs->transnoentities("ErrorCanNotCreateDir", $dir);
                 return 0;
             }
         }
         if (file_exists($dir)) {
             $nblignes = count($object->lines);
             $pdf = pdf_getInstance($this->format);
             $default_font_size = pdf_getPDFFontSize($outputlangs);
             // Must be after pdf_getInstance
             $heightforinfotot = 50;
             // Height reserved to output the info and total part
             $heightforfreetext = isset($conf->global->MAIN_PDF_FREETEXT_HEIGHT) ? $conf->global->MAIN_PDF_FREETEXT_HEIGHT : 5;
             // Height reserved to output the free text on last page
             $heightforfooter = $this->marge_basse + 8;
             // Height reserved to output the footer (value include bottom margin)
             $pdf->SetAutoPageBreak(1, 0);
             if (class_exists('TCPDF')) {
                 $pdf->setPrintHeader(false);
                 $pdf->setPrintFooter(false);
             }
             $pdf->SetFont(pdf_getPDFFont($outputlangs));
             // Set path to the background PDF File
             if (empty($conf->global->MAIN_DISABLE_FPDI) && !empty($conf->global->MAIN_ADD_PDF_BACKGROUND)) {
                 $pagecount = $pdf->setSourceFile($conf->mycompany->dir_output . '/' . $conf->global->MAIN_ADD_PDF_BACKGROUND);
                 $tplidx = $pdf->importPage(1);
             }
             $pdf->Open();
             $pagenb = 0;
             $pdf->SetDrawColor(128, 128, 128);
             $pdf->SetTitle($outputlangs->convToOutputCharset($object->ref));
             $pdf->SetSubject($outputlangs->transnoentities("Invoice"));
             $pdf->SetCreator("Dolibarr " . DOL_VERSION);
             $pdf->SetAuthor($outputlangs->convToOutputCharset($user->getFullName($outputlangs)));
             $pdf->SetKeyWords($outputlangs->convToOutputCharset($object->ref) . " " . $outputlangs->transnoentities("Invoice"));
             if (!empty($conf->global->MAIN_DISABLE_PDF_COMPRESSION)) {
                 $pdf->SetCompression(false);
             }
             $pdf->SetMargins($this->marge_gauche, $this->marge_haute, $this->marge_droite);
             // Left, Top, Right
             // Positionne $this->atleastonediscount si on a au moins une remise
             for ($i = 0; $i < $nblignes; $i++) {
                 if ($object->lines[$i]->remise_percent) {
                     $this->atleastonediscount++;
                 }
             }
             // New page
             $pdf->AddPage();
             if (!empty($tplidx)) {
                 $pdf->useTemplate($tplidx);
             }
             $pagenb++;
             $this->_pagehead($pdf, $object, 1, $outputlangs, $hookmanager);
             $pdf->SetFont('', '', $default_font_size - 1);
             $pdf->MultiCell(0, 3, '');
             // Set interline to 3
             $pdf->SetTextColor(0, 0, 0);
             $tab_top = 90;
             $tab_top_newpage = empty($conf->global->MAIN_PDF_DONOTREPEAT_HEAD) ? 42 : 10;
             $tab_height = 130;
             $tab_height_newpage = 150;
             // Affiche notes
             if (!empty($object->note_public)) {
                 $tab_top = 88;
                 $pdf->SetFont('', '', $default_font_size - 1);
                 $pdf->writeHTMLCell(190, 3, $this->posxdesc - 1, $tab_top, dol_htmlentitiesbr($object->note_public), 0, 1);
                 $nexY = $pdf->GetY();
                 $height_note = $nexY - $tab_top;
                 // Rect prend une longueur en 3eme param
                 $pdf->SetDrawColor(192, 192, 192);
                 $pdf->Rect($this->marge_gauche, $tab_top - 1, $this->page_largeur - $this->marge_gauche - $this->marge_droite, $height_note + 1);
                 $tab_height = $tab_height - $height_note;
                 $tab_top = $nexY + 6;
             } else {
                 $height_note = 0;
             }
             $iniY = $tab_top + 7;
             $curY = $tab_top + 7;
             $nexY = $tab_top + 7;
             // Loop on each lines
             for ($i = 0; $i < $nblignes; $i++) {
                 $curY = $nexY;
                 $pdf->SetFont('', '', $default_font_size - 1);
                 // Into loop to work with multipage
                 $pdf->SetTextColor(0, 0, 0);
                 $pdf->setTopMargin($tab_top_newpage);
                 $pdf->setPageOrientation('', 1, $heightforfooter + $heightforfreetext + $heightforinfotot);
                 // The only function to edit the bottom margin of current page to set it.
                 $pageposbefore = $pdf->getPage();
                 // Description of product line
                 $curX = $this->posxdesc - 1;
                 $showpricebeforepagebreak = 1;
                 $pdf->startTransaction();
                 pdf_writelinedesc($pdf, $object, $i, $outputlangs, $this->posxtva - $curX, 3, $curX, $curY, $hideref, $hidedesc, 0, $hookmanager);
                 $pageposafter = $pdf->getPage();
                 if ($pageposafter > $pageposbefore) {
                     $pdf->rollbackTransaction(true);
                     $pageposafter = $pageposbefore;
                     //print $pageposafter.'-'.$pageposbefore;exit;
                     $pdf->setPageOrientation('', 1, $heightforfooter);
                     // The only function to edit the bottom margin of current page to set it.
                     pdf_writelinedesc($pdf, $object, $i, $outputlangs, $this->posxtva - $curX, 4, $curX, $curY, $hideref, $hidedesc, 0, $hookmanager);
                     $pageposafter = $pdf->getPage();
                     $posyafter = $pdf->GetY();
                     //var_dump($posyafter); var_dump(($this->page_hauteur - ($heightforfooter+$heightforfreetext+$heightforinfotot))); exit;
                     if ($posyafter > $this->page_hauteur - ($heightforfooter + $heightforfreetext + $heightforinfotot)) {
                         if ($i == $nblignes - 1) {
                             $pdf->AddPage('', '', true);
                             if (!empty($tplidx)) {
                                 $pdf->useTemplate($tplidx);
                             }
                             if (empty($conf->global->MAIN_PDF_DONOTREPEAT_HEAD)) {
                                 $this->_pagehead($pdf, $object, 0, $outputlangs, $hookmanager);
                             }
                             $pdf->setPage($pagenb + 1);
                         }
                     } else {
                         // We found a page break
                         $showpricebeforepagebreak = 0;
                     }
                 } else {
                     $pdf->commitTransaction();
                 }
                 $nexY = $pdf->GetY();
                 $pageposafter = $pdf->getPage();
                 $pdf->setPage($pageposbefore);
                 $pdf->setTopMargin($this->marge_haute);
                 $pdf->setPageOrientation('', 1, 0);
                 // The only function to edit the bottom margin of current page to set it.
                 // We suppose that a too long description is moved completely on next page
                 if ($pageposafter > $pageposbefore && empty($showpricebeforepagebreak)) {
                     $pdf->setPage($pageposafter);
                     $curY = $tab_top_newpage;
                 }
                 $pdf->SetFont('', '', $default_font_size - 1);
                 // On repositionne la police par defaut
                 // VAT Rate
                 if (empty($conf->global->MAIN_GENERATE_DOCUMENTS_WITHOUT_VAT)) {
                     $vat_rate = pdf_getlinevatrate($object, $i, $outputlangs, $hidedetails, $hookmanager);
                     $pdf->SetXY($this->posxtva, $curY);
                     $pdf->MultiCell($this->posxup - $this->posxtva - 1, 3, $vat_rate, 0, 'R');
                 }
                 // Unit price before discount
                 $up_excl_tax = pdf_getlineupexcltax($object, $i, $outputlangs, $hidedetails, $hookmanager);
                 $pdf->SetXY($this->posxup, $curY);
                 $pdf->MultiCell($this->posxqty - $this->posxup - 1, 3, $up_excl_tax, 0, 'R', 0);
                 // Quantity
                 $qty = pdf_getlineqty($object, $i, $outputlangs, $hidedetails, $hookmanager);
                 $pdf->SetXY($this->posxqty, $curY);
                 $pdf->MultiCell($this->posxdiscount - $this->posxqty - 1, 3, $qty, 0, 'R');
                 // Enough for 6 chars
                 // Discount on line
                 if ($object->lines[$i]->remise_percent) {
                     $pdf->SetXY($this->posxdiscount - 2, $curY);
                     $remise_percent = pdf_getlineremisepercent($object, $i, $outputlangs, $hidedetails, $hookmanager);
                     $pdf->MultiCell($this->postotalht - $this->posxdiscount + 2, 3, $remise_percent, 0, 'R');
                 }
                 // Total HT line
                 $total_excl_tax = pdf_getlinetotalexcltax($object, $i, $outputlangs, $hidedetails, $hookmanager);
                 $pdf->SetXY($this->postotalht, $curY);
                 $pdf->MultiCell($this->page_largeur - $this->marge_droite - $this->postotalht, 3, $total_excl_tax, 0, 'R', 0);
                 // Collecte des totaux par valeur de tva dans $this->tva["taux"]=total_tva
                 $tvaligne = $object->lines[$i]->total_tva;
                 $localtax1ligne = $object->lines[$i]->total_localtax1;
                 $localtax2ligne = $object->lines[$i]->total_localtax2;
                 $localtax1_rate = $object->lines[$i]->localtax1_tx;
                 $localtax2_rate = $object->lines[$i]->localtax2_tx;
                 $localtax1_type = $object->lines[$i]->localtax1_type;
                 $localtax2_type = $object->lines[$i]->localtax2_type;
                 if ($object->remise_percent) {
                     $tvaligne -= $tvaligne * $object->remise_percent / 100;
                 }
                 if ($object->remise_percent) {
                     $localtax1ligne -= $localtax1ligne * $object->remise_percent / 100;
                 }
                 if ($object->remise_percent) {
                     $localtax2ligne -= $localtax2ligne * $object->remise_percent / 100;
                 }
                 $vatrate = (string) $object->lines[$i]->tva_tx;
                 // TODO : store local taxes types into object lines and remove this
                 $localtax1_array = getLocalTaxesFromRate($vatrate, 1, $mysoc);
                 $localtax2_array = getLocalTaxesFromRate($vatrate, 2, $mysoc);
                 if (!isset($localtax1_type)) {
                     $localtax1_type = $localtax1_array[0];
                 }
                 if (!isset($localtax2_type)) {
                     $localtax2_type = $localtax2_array[0];
                 }
                 //end TODO
                 // retrieve global local tax
                 if ($localtax1_type == '7') {
                     $localtax1_rate = $localtax1_array[1];
                 }
                 if ($localtax2_type == '7') {
                     $localtax2_rate = $localtax2_array[1];
                 }
                 if ($localtax1_type && ($localtax1ligne != 0 || $localtax1_type == '7')) {
                     $this->localtax1[$localtax1_type][$localtax1_rate] += $localtax1ligne;
                 }
                 if ($localtax2_type && ($localtax2ligne != 0 || $localtax2_type == '7')) {
                     $this->localtax2[$localtax2_type][$localtax2_rate] += $localtax2ligne;
                 }
                 if (($object->lines[$i]->info_bits & 0x1) == 0x1) {
                     $vatrate .= '*';
                 }
                 if (!isset($this->tva[$vatrate])) {
                     $this->tva[$vatrate] = '';
                 }
                 $this->tva[$vatrate] += $tvaligne;
                 // Add line
                 if (!empty($conf->global->MAIN_PDF_DASH_BETWEEN_LINES) && $i < $nblignes - 1) {
                     $pdf->SetLineStyle(array('dash' => '1,1', 'color' => array(210, 210, 210)));
                     //$pdf->SetDrawColor(190,190,200);
                     $pdf->line($this->marge_gauche, $nexY + 1, $this->page_largeur - $this->marge_droite, $nexY + 1);
                     $pdf->SetLineStyle(array('dash' => 0));
                 }
                 $nexY += 2;
                 // Passe espace entre les lignes
                 // Detect if some page were added automatically and output _tableau for past pages
                 while ($pagenb < $pageposafter) {
                     $pdf->setPage($pagenb);
                     if ($pagenb == 1) {
                         $this->_tableau($pdf, $tab_top, $this->page_hauteur - $tab_top - $heightforfooter, 0, $outputlangs, 0, 1);
                     } else {
                         $this->_tableau($pdf, $tab_top_newpage, $this->page_hauteur - $tab_top_newpage - $heightforfooter, 0, $outputlangs, 1, 1);
                     }
                     $this->_pagefoot($pdf, $object, $outputlangs, 1);
                     $pagenb++;
                     $pdf->setPage($pagenb);
                     $pdf->setPageOrientation('', 1, 0);
                     // The only function to edit the bottom margin of current page to set it.
                     if (empty($conf->global->MAIN_PDF_DONOTREPEAT_HEAD)) {
                         $this->_pagehead($pdf, $object, 0, $outputlangs, $hookmanager);
                     }
                 }
                 if (isset($object->lines[$i + 1]->pagebreak) && $object->lines[$i + 1]->pagebreak) {
                     if ($pagenb == 1) {
                         $this->_tableau($pdf, $tab_top, $this->page_hauteur - $tab_top - $heightforfooter, 0, $outputlangs, 0, 1);
                     } else {
                         $this->_tableau($pdf, $tab_top_newpage, $this->page_hauteur - $tab_top_newpage - $heightforfooter, 0, $outputlangs, 1, 1);
                     }
                     $this->_pagefoot($pdf, $object, $outputlangs, 1);
                     // New page
                     $pdf->AddPage();
                     if (!empty($tplidx)) {
                         $pdf->useTemplate($tplidx);
                     }
                     $pagenb++;
                     if (empty($conf->global->MAIN_PDF_DONOTREPEAT_HEAD)) {
                         $this->_pagehead($pdf, $object, 0, $outputlangs, $hookmanager);
                     }
                 }
             }
             // Show square
             if ($pagenb == 1) {
                 $this->_tableau($pdf, $tab_top, $this->page_hauteur - $tab_top - $heightforinfotot - $heightforfreetext - $heightforfooter, 0, $outputlangs, 0, 0);
                 $bottomlasttab = $this->page_hauteur - $heightforinfotot - $heightforfreetext - $heightforfooter + 1;
             } else {
                 $this->_tableau($pdf, $tab_top_newpage, $this->page_hauteur - $tab_top_newpage - $heightforinfotot - $heightforfreetext - $heightforfooter, 0, $outputlangs, 1, 0);
                 $bottomlasttab = $this->page_hauteur - $heightforinfotot - $heightforfreetext - $heightforfooter + 1;
             }
             // Affiche zone infos
             $posy = $this->_tableau_info($pdf, $object, $bottomlasttab, $outputlangs);
             // Affiche zone totaux
             $posy = $this->_tableau_tot($pdf, $object, $deja_regle, $bottomlasttab, $outputlangs);
             // Affiche zone versements
             if ($deja_regle || $amount_credit_notes_included || $amount_deposits_included) {
                 $posy = $this->_tableau_versements($pdf, $object, $posy, $outputlangs);
             }
             // Pied de page
             $this->_pagefoot($pdf, $object, $outputlangs);
             //$pdf->AliasNbPages();
             $pdf->Close();
             $pdf->Output($file, 'F');
             // Add pdfgeneration hook
             if (!is_object($hookmanager)) {
                 include_once DOL_DOCUMENT_ROOT . '/core/class/hookmanager.class.php';
                 $hookmanager = new HookManager($this->db);
             }
             $hookmanager->initHooks(array('pdfgeneration'));
             $parameters = array('file' => $file, 'object' => $object, 'outputlangs' => $outputlangs);
             global $action;
             $reshook = $hookmanager->executeHooks('afterPDFCreation', $parameters, $this, $action);
             // Note that $action and $object may have been modified by some hooks
             if (!empty($conf->global->MAIN_UMASK)) {
                 @chmod($file, octdec($conf->global->MAIN_UMASK));
             }
             return 1;
             // Pas d'erreur
         } else {
             $this->error = $langs->trans("ErrorCanNotCreateDir", $dir);
             return 0;
         }
     } else {
         $this->error = $langs->trans("ErrorConstantNotDefined", "FAC_OUTPUTDIR");
         return 0;
     }
     $this->error = $langs->trans("ErrorUnknown");
     return 0;
     // Erreur par defaut
 }
 /**
  * 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;
 }
Пример #16
0
 /**
  *  Function to build pdf onto disk
  *
  *  @param		Object		$object				Object to generate
  *  @param		Translate	$outputlangs		Lang output object
  *  @param		string		$srctemplatepath	Full path of source filename for generator using a template file
  *  @param		int			$hidedetails		Do not show line details
  *  @param		int			$hidedesc			Do not show desc
  *  @param		int			$hideref			Do not show ref
  *  @return     int         	    			1=OK, 0=KO
  */
 function write_file($object, $outputlangs, $srctemplatepath = '', $hidedetails = 0, $hidedesc = 0, $hideref = 0)
 {
     global $user, $langs, $conf, $mysoc, $db, $hookmanager;
     if (!is_object($outputlangs)) {
         $outputlangs = $langs;
     }
     // For backward compatibility with FPDF, force output charset to ISO, because FPDF expect text to be encoded in ISO
     if (!empty($conf->global->MAIN_USE_FPDF)) {
         $outputlangs->charset_output = 'ISO-8859-1';
     }
     $outputlangs->load("main");
     $outputlangs->load("dict");
     $outputlangs->load("companies");
     $outputlangs->load("bills");
     $outputlangs->load("products");
     $nblignes = count($object->lines);
     // Loop on each lines to detect if there is at least one image to show
     $realpatharray = array();
     if (!empty($conf->global->MAIN_GENERATE_INVOICES_WITH_PICTURE)) {
         for ($i = 0; $i < $nblignes; $i++) {
             if (empty($object->lines[$i]->fk_product)) {
                 continue;
             }
             $objphoto = new Product($this->db);
             $objphoto->fetch($object->lines[$i]->fk_product);
             $pdir = get_exdir($object->lines[$i]->fk_product, 2, 0, 0, $objphoto, 'product') . $object->lines[$i]->fk_product . "/photos/";
             $dir = $conf->product->dir_output . '/' . $pdir;
             $realpath = '';
             foreach ($objphoto->liste_photos($dir, 1) as $key => $obj) {
                 $filename = $obj['photo'];
                 //if ($obj['photo_vignette']) $filename='thumbs/'.$obj['photo_vignette'];
                 $realpath = $dir . $filename;
                 break;
             }
             if ($realpath) {
                 $realpatharray[$i] = $realpath;
             }
         }
     }
     if (count($realpatharray) == 0) {
         $this->posxpicture = $this->posxtva;
     }
     if ($conf->facture->dir_output) {
         $object->fetch_thirdparty();
         $deja_regle = $object->getSommePaiement();
         $amount_credit_notes_included = $object->getSumCreditNotesUsed();
         $amount_deposits_included = $object->getSumDepositsUsed();
         // Definition of $dir and $file
         if ($object->specimen) {
             $dir = $conf->facture->dir_output;
             $file = $dir . "/SPECIMEN.pdf";
         } else {
             $objectref = dol_sanitizeFileName($object->ref);
             $dir = $conf->facture->dir_output . "/" . $objectref;
             $file = $dir . "/" . $objectref . ".pdf";
         }
         if (!file_exists($dir)) {
             if (dol_mkdir($dir) < 0) {
                 $this->error = $langs->transnoentities("ErrorCanNotCreateDir", $dir);
                 return 0;
             }
         }
         if (file_exists($dir)) {
             // Add pdfgeneration hook
             if (!is_object($hookmanager)) {
                 include_once DOL_DOCUMENT_ROOT . '/core/class/hookmanager.class.php';
                 $hookmanager = new HookManager($this->db);
             }
             $hookmanager->initHooks(array('pdfgeneration'));
             $parameters = array('file' => $file, 'object' => $object, 'outputlangs' => $outputlangs);
             global $action;
             $reshook = $hookmanager->executeHooks('beforePDFCreation', $parameters, $object, $action);
             // Note that $action and $object may have been modified by some hooks
             // Set nblignes with the new facture lines content after hook
             $nblignes = count($object->lines);
             // Create pdf instance
             $pdf = pdf_getInstance($this->format);
             $default_font_size = pdf_getPDFFontSize($outputlangs);
             // Must be after pdf_getInstance
             $heightforinfotot = 50;
             // Height reserved to output the info and total part
             $heightforfreetext = isset($conf->global->MAIN_PDF_FREETEXT_HEIGHT) ? $conf->global->MAIN_PDF_FREETEXT_HEIGHT : 5;
             // Height reserved to output the free text on last page
             $heightforfooter = $this->marge_basse + 8;
             // Height reserved to output the footer (value include bottom margin)
             $pdf->SetAutoPageBreak(1, 0);
             if (class_exists('TCPDF')) {
                 $pdf->setPrintHeader(false);
                 $pdf->setPrintFooter(false);
             }
             $pdf->SetFont(pdf_getPDFFont($outputlangs));
             // Set path to the background PDF File
             if (empty($conf->global->MAIN_DISABLE_FPDI) && !empty($conf->global->MAIN_ADD_PDF_BACKGROUND)) {
                 $pagecount = $pdf->setSourceFile($conf->mycompany->dir_output . '/' . $conf->global->MAIN_ADD_PDF_BACKGROUND);
                 $tplidx = $pdf->importPage(1);
             }
             $pdf->Open();
             $pagenb = 0;
             $pdf->SetDrawColor(128, 128, 128);
             $pdf->SetTitle($outputlangs->convToOutputCharset($object->ref));
             $pdf->SetSubject($outputlangs->transnoentities("Invoice"));
             $pdf->SetCreator("Dolibarr " . DOL_VERSION);
             $pdf->SetAuthor($outputlangs->convToOutputCharset($user->getFullName($outputlangs)));
             $pdf->SetKeyWords($outputlangs->convToOutputCharset($object->ref) . " " . $outputlangs->transnoentities("Invoice"));
             if (!empty($conf->global->MAIN_DISABLE_PDF_COMPRESSION)) {
                 $pdf->SetCompression(false);
             }
             $pdf->SetMargins($this->marge_gauche, $this->marge_haute, $this->marge_droite);
             // Left, Top, Right
             // Positionne $this->atleastonediscount si on a au moins une remise
             for ($i = 0; $i < $nblignes; $i++) {
                 if ($object->lines[$i]->remise_percent) {
                     $this->atleastonediscount++;
                 }
             }
             if (empty($this->atleastonediscount) && empty($conf->global->PRODUCT_USE_UNITS)) {
                 $this->posxpicture += $this->postotalht - $this->posxdiscount;
                 $this->posxtva += $this->postotalht - $this->posxdiscount;
                 $this->posxup += $this->postotalht - $this->posxdiscount;
                 $this->posxqty += $this->postotalht - $this->posxdiscount;
                 $this->posxdiscount += $this->postotalht - $this->posxdiscount;
                 //$this->postotalht;
             }
             // Situation invoice handling
             if ($object->situation_cycle_ref) {
                 $this->situationinvoice = True;
                 $progress_width = 14;
                 $this->posxtva -= $progress_width;
                 $this->posxup -= $progress_width;
                 $this->posxqty -= $progress_width;
                 $this->posxdiscount -= $progress_width;
                 $this->posxprogress -= $progress_width;
             }
             // New page
             $pdf->AddPage();
             if (!empty($tplidx)) {
                 $pdf->useTemplate($tplidx);
             }
             $pagenb++;
             $this->_pagehead($pdf, $object, 1, $outputlangs);
             $pdf->SetFont('', '', $default_font_size - 1);
             $pdf->MultiCell(0, 3, '');
             // Set interline to 3
             $pdf->SetTextColor(0, 0, 0);
             $tab_top = 90;
             $tab_top_newpage = empty($conf->global->MAIN_PDF_DONOTREPEAT_HEAD) ? 42 : 10;
             $tab_height = 130;
             $tab_height_newpage = 150;
             // Incoterm
             $height_incoterms = 0;
             if ($conf->incoterm->enabled) {
                 $desc_incoterms = $object->getIncotermsForPDF();
                 if ($desc_incoterms) {
                     $tab_top = 88;
                     $pdf->SetFont('', '', $default_font_size - 1);
                     $pdf->writeHTMLCell(190, 3, $this->posxdesc - 1, $tab_top - 1, dol_htmlentitiesbr($desc_incoterms), 0, 1);
                     $nexY = $pdf->GetY();
                     $height_incoterms = $nexY - $tab_top;
                     // Rect prend une longueur en 3eme param
                     $pdf->SetDrawColor(192, 192, 192);
                     $pdf->Rect($this->marge_gauche, $tab_top - 1, $this->page_largeur - $this->marge_gauche - $this->marge_droite, $height_incoterms + 1);
                     $tab_top = $nexY + 6;
                     $height_incoterms += 4;
                 }
             }
             // Affiche notes
             $notetoshow = empty($object->note_public) ? '' : $object->note_public;
             if (!empty($conf->global->MAIN_ADD_SALE_REP_SIGNATURE_IN_NOTE)) {
                 // Get first sale rep
                 if (is_object($object->thirdparty)) {
                     $salereparray = $object->thirdparty->getSalesRepresentatives($user);
                     $salerepobj = new User($this->db);
                     $salerepobj->fetch($salereparray[0]['id']);
                     if (!empty($salerepobj->signature)) {
                         $notetoshow = dol_concatdesc($notetoshow, $salerepobj->signature);
                     }
                 }
             }
             if ($notetoshow) {
                 $tab_top = 88 + $height_incoterms;
                 $pdf->SetFont('', '', $default_font_size - 1);
                 $pdf->writeHTMLCell(190, 3, $this->posxdesc - 1, $tab_top, dol_htmlentitiesbr($notetoshow), 0, 1);
                 $nexY = $pdf->GetY();
                 $height_note = $nexY - $tab_top;
                 // Rect prend une longueur en 3eme param
                 $pdf->SetDrawColor(192, 192, 192);
                 $pdf->Rect($this->marge_gauche, $tab_top - 1, $this->page_largeur - $this->marge_gauche - $this->marge_droite, $height_note + 1);
                 $tab_height = $tab_height - $height_note;
                 $tab_top = $nexY + 6;
             } else {
                 $height_note = 0;
             }
             $iniY = $tab_top + 7;
             $curY = $tab_top + 7;
             $nexY = $tab_top + 7;
             // Loop on each lines
             for ($i = 0; $i < $nblignes; $i++) {
                 $curY = $nexY;
                 $pdf->SetFont('', '', $default_font_size - 1);
                 // Into loop to work with multipage
                 $pdf->SetTextColor(0, 0, 0);
                 // Define size of image if we need it
                 $imglinesize = array();
                 if (!empty($realpatharray[$i])) {
                     $imglinesize = pdf_getSizeForImage($realpatharray[$i]);
                 }
                 $pdf->setTopMargin($tab_top_newpage);
                 $pdf->setPageOrientation('', 1, $heightforfooter + $heightforfreetext + $heightforinfotot);
                 // The only function to edit the bottom margin of current page to set it.
                 $pageposbefore = $pdf->getPage();
                 $showpricebeforepagebreak = 1;
                 $posYAfterImage = 0;
                 $posYAfterDescription = 0;
                 // We start with Photo of product line
                 if (isset($imglinesize['width']) && isset($imglinesize['height']) && $curY + $imglinesize['height'] > $this->page_hauteur - ($heightforfooter + $heightforfreetext + $heightforinfotot)) {
                     $pdf->AddPage('', '', true);
                     if (!empty($tplidx)) {
                         $pdf->useTemplate($tplidx);
                     }
                     if (empty($conf->global->MAIN_PDF_DONOTREPEAT_HEAD)) {
                         $this->_pagehead($pdf, $object, 0, $outputlangs);
                     }
                     $pdf->setPage($pageposbefore + 1);
                     $curY = $tab_top_newpage;
                     $showpricebeforepagebreak = 0;
                 }
                 if (isset($imglinesize['width']) && isset($imglinesize['height'])) {
                     $curX = $this->posxpicture - 1;
                     $pdf->Image($realpatharray[$i], $curX + ($this->posxtva - $this->posxpicture - $imglinesize['width']) / 2, $curY, $imglinesize['width'], $imglinesize['height'], '', '', '', 2, 300);
                     // Use 300 dpi
                     // $pdf->Image does not increase value return by getY, so we save it manually
                     $posYAfterImage = $curY + $imglinesize['height'];
                 }
                 // Description of product line
                 $curX = $this->posxdesc - 1;
                 $pdf->startTransaction();
                 pdf_writelinedesc($pdf, $object, $i, $outputlangs, $this->posxpicture - $curX, 3, $curX, $curY, $hideref, $hidedesc);
                 $pageposafter = $pdf->getPage();
                 if ($pageposafter > $pageposbefore) {
                     $pdf->rollbackTransaction(true);
                     $pageposafter = $pageposbefore;
                     //print $pageposafter.'-'.$pageposbefore;exit;
                     $pdf->setPageOrientation('', 1, $heightforfooter);
                     // The only function to edit the bottom margin of current page to set it.
                     pdf_writelinedesc($pdf, $object, $i, $outputlangs, $this->posxpicture - $curX, 3, $curX, $curY, $hideref, $hidedesc);
                     $pageposafter = $pdf->getPage();
                     $posyafter = $pdf->GetY();
                     //var_dump($posyafter); var_dump(($this->page_hauteur - ($heightforfooter+$heightforfreetext+$heightforinfotot))); exit;
                     if ($posyafter > $this->page_hauteur - ($heightforfooter + $heightforfreetext + $heightforinfotot)) {
                         if ($i == $nblignes - 1) {
                             $pdf->AddPage('', '', true);
                             if (!empty($tplidx)) {
                                 $pdf->useTemplate($tplidx);
                             }
                             if (empty($conf->global->MAIN_PDF_DONOTREPEAT_HEAD)) {
                                 $this->_pagehead($pdf, $object, 0, $outputlangs);
                             }
                             $pdf->setPage($pageposafter + 1);
                         }
                     } else {
                         // We found a page break
                         $showpricebeforepagebreak = 0;
                     }
                 } else {
                     $pdf->commitTransaction();
                 }
                 $posYAfterDescription = $pdf->GetY();
                 $nexY = $pdf->GetY();
                 $pageposafter = $pdf->getPage();
                 $pdf->setPage($pageposbefore);
                 $pdf->setTopMargin($this->marge_haute);
                 $pdf->setPageOrientation('', 1, 0);
                 // The only function to edit the bottom margin of current page to set it.
                 // We suppose that a too long description or photo were moved completely on next page
                 if ($pageposafter > $pageposbefore && empty($showpricebeforepagebreak)) {
                     $pdf->setPage($pageposafter);
                     $curY = $tab_top_newpage;
                 }
                 $pdf->SetFont('', '', $default_font_size - 1);
                 // On repositionne la police par defaut
                 // VAT Rate
                 if (empty($conf->global->MAIN_GENERATE_DOCUMENTS_WITHOUT_VAT)) {
                     $vat_rate = pdf_getlinevatrate($object, $i, $outputlangs, $hidedetails);
                     $pdf->SetXY($this->posxtva, $curY);
                     $pdf->MultiCell($this->posxup - $this->posxtva - 0.8, 3, $vat_rate, 0, 'R');
                 }
                 // Unit price before discount
                 $up_excl_tax = pdf_getlineupexcltax($object, $i, $outputlangs, $hidedetails);
                 $pdf->SetXY($this->posxup, $curY);
                 $pdf->MultiCell($this->posxqty - $this->posxup - 0.8, 3, $up_excl_tax, 0, 'R', 0);
                 // Quantity
                 $qty = pdf_getlineqty($object, $i, $outputlangs, $hidedetails);
                 $pdf->SetXY($this->posxqty, $curY);
                 // Enough for 6 chars
                 if ($conf->global->PRODUCT_USE_UNITS) {
                     $pdf->MultiCell($this->posxunit - $this->posxqty - 0.8, 4, $qty, 0, 'R');
                 } else {
                     $pdf->MultiCell($this->posxdiscount - $this->posxqty - 0.8, 4, $qty, 0, 'R');
                 }
                 // Unit
                 if ($conf->global->PRODUCT_USE_UNITS) {
                     $unit = pdf_getlineunit($object, $i, $outputlangs, $hidedetails, $hookmanager);
                     $pdf->SetXY($this->posxunit, $curY);
                     $pdf->MultiCell($this->posxdiscount - $this->posxunit - 0.8, 4, $unit, 0, 'L');
                 }
                 // Discount on line
                 if ($object->lines[$i]->remise_percent) {
                     $pdf->SetXY($this->posxdiscount - 2, $curY);
                     $remise_percent = pdf_getlineremisepercent($object, $i, $outputlangs, $hidedetails);
                     $pdf->MultiCell($this->posxprogress - $this->posxdiscount + 2, 3, $remise_percent, 0, 'R');
                 }
                 if ($this->situationinvoice) {
                     // Situation progress
                     $progress = pdf_getlineprogress($object, $i, $outputlangs, $hidedetails);
                     $pdf->SetXY($this->posxprogress, $curY);
                     $pdf->MultiCell($this->postotalht - $this->posxprogress, 3, $progress, 0, 'R');
                 }
                 // Total HT line
                 $total_excl_tax = pdf_getlinetotalexcltax($object, $i, $outputlangs, $hidedetails);
                 $pdf->SetXY($this->postotalht, $curY);
                 $pdf->MultiCell($this->page_largeur - $this->marge_droite - $this->postotalht, 3, $total_excl_tax, 0, 'R', 0);
                 // Collecte des totaux par valeur de tva dans $this->tva["taux"]=total_tva
                 $prev_progress = $object->lines[$i]->get_prev_progress();
                 if ($prev_progress > 0) {
                     if ($conf->multicurrency->enabled && $object->multicurrency_tx != 1) {
                         $tvaligne = $object->lines[$i]->multicurrency_total_tva * ($object->lines[$i]->situation_percent - $prev_progress) / $object->lines[$i]->situation_percent;
                     } else {
                         $tvaligne = $object->lines[$i]->total_tva * ($object->lines[$i]->situation_percent - $prev_progress) / $object->lines[$i]->situation_percent;
                     }
                 } else {
                     if ($conf->multicurrency->enabled && $object->multicurrency_tx != 1) {
                         $tvaligne = $object->lines[$i]->multicurrency_total_tva;
                     } else {
                         $tvaligne = $object->lines[$i]->total_tva;
                     }
                 }
                 $localtax1ligne = $object->lines[$i]->total_localtax1;
                 $localtax2ligne = $object->lines[$i]->total_localtax2;
                 $localtax1_rate = $object->lines[$i]->localtax1_tx;
                 $localtax2_rate = $object->lines[$i]->localtax2_tx;
                 $localtax1_type = $object->lines[$i]->localtax1_type;
                 $localtax2_type = $object->lines[$i]->localtax2_type;
                 if ($object->remise_percent) {
                     $tvaligne -= $tvaligne * $object->remise_percent / 100;
                 }
                 if ($object->remise_percent) {
                     $localtax1ligne -= $localtax1ligne * $object->remise_percent / 100;
                 }
                 if ($object->remise_percent) {
                     $localtax2ligne -= $localtax2ligne * $object->remise_percent / 100;
                 }
                 $vatrate = (string) $object->lines[$i]->tva_tx;
                 // Retrieve type from database for backward compatibility with old records
                 if ((!isset($localtax1_type) || $localtax1_type == '' || !isset($localtax2_type) || $localtax2_type == '') && (!empty($localtax1_rate) || !empty($localtax2_rate))) {
                     $localtaxtmp_array = getLocalTaxesFromRate($vatrate, 0, $object->thirdparty, $mysoc);
                     $localtax1_type = $localtaxtmp_array[0];
                     $localtax2_type = $localtaxtmp_array[2];
                 }
                 // retrieve global local tax
                 if ($localtax1_type && $localtax1ligne != 0) {
                     $this->localtax1[$localtax1_type][$localtax1_rate] += $localtax1ligne;
                 }
                 if ($localtax2_type && $localtax2ligne != 0) {
                     $this->localtax2[$localtax2_type][$localtax2_rate] += $localtax2ligne;
                 }
                 if (($object->lines[$i]->info_bits & 0x1) == 0x1) {
                     $vatrate .= '*';
                 }
                 if (!isset($this->tva[$vatrate])) {
                     $this->tva[$vatrate] = '';
                 }
                 $this->tva[$vatrate] += $tvaligne;
                 if ($posYAfterImage > $posYAfterDescription) {
                     $nexY = $posYAfterImage;
                 }
                 // Add line
                 if ($conf->global->MAIN_PDF_DASH_BETWEEN_LINES && $i < $nblignes - 1) {
                     $pdf->setPage($pageposafter);
                     $pdf->SetLineStyle(array('dash' => '1,1', 'color' => array(80, 80, 80)));
                     //$pdf->SetDrawColor(190,190,200);
                     $pdf->line($this->marge_gauche, $nexY + 1, $this->page_largeur - $this->marge_droite, $nexY + 1);
                     $pdf->SetLineStyle(array('dash' => 0));
                 }
                 $nexY += 2;
                 // Passe espace entre les lignes
                 // Detect if some page were added automatically and output _tableau for past pages
                 while ($pagenb < $pageposafter) {
                     $pdf->setPage($pagenb);
                     if ($pagenb == 1) {
                         $this->_tableau($pdf, $tab_top, $this->page_hauteur - $tab_top - $heightforfooter, 0, $outputlangs, 0, 1, $object->multicurrency_code);
                     } else {
                         $this->_tableau($pdf, $tab_top_newpage, $this->page_hauteur - $tab_top_newpage - $heightforfooter, 0, $outputlangs, 1, 1, $object->multicurrency_code);
                     }
                     $this->_pagefoot($pdf, $object, $outputlangs, 1);
                     $pagenb++;
                     $pdf->setPage($pagenb);
                     $pdf->setPageOrientation('', 1, 0);
                     // The only function to edit the bottom margin of current page to set it.
                     if (empty($conf->global->MAIN_PDF_DONOTREPEAT_HEAD)) {
                         $this->_pagehead($pdf, $object, 0, $outputlangs);
                     }
                 }
                 if (isset($object->lines[$i + 1]->pagebreak) && $object->lines[$i + 1]->pagebreak) {
                     if ($pagenb == 1) {
                         $this->_tableau($pdf, $tab_top, $this->page_hauteur - $tab_top - $heightforfooter, 0, $outputlangs, 0, 1, $object->multicurrency_code);
                     } else {
                         $this->_tableau($pdf, $tab_top_newpage, $this->page_hauteur - $tab_top_newpage - $heightforfooter, 0, $outputlangs, 1, 1, $object->multicurrency_code);
                     }
                     $this->_pagefoot($pdf, $object, $outputlangs, 1);
                     // New page
                     $pdf->AddPage();
                     if (!empty($tplidx)) {
                         $pdf->useTemplate($tplidx);
                     }
                     $pagenb++;
                     if (empty($conf->global->MAIN_PDF_DONOTREPEAT_HEAD)) {
                         $this->_pagehead($pdf, $object, 0, $outputlangs);
                     }
                 }
             }
             // Show square
             if ($pagenb == 1) {
                 $this->_tableau($pdf, $tab_top, $this->page_hauteur - $tab_top - $heightforinfotot - $heightforfreetext - $heightforfooter, 0, $outputlangs, 0, 0, $object->multicurrency_code);
                 $bottomlasttab = $this->page_hauteur - $heightforinfotot - $heightforfreetext - $heightforfooter + 1;
             } else {
                 $this->_tableau($pdf, $tab_top_newpage, $this->page_hauteur - $tab_top_newpage - $heightforinfotot - $heightforfreetext - $heightforfooter, 0, $outputlangs, 1, 0, $object->multicurrency_code);
                 $bottomlasttab = $this->page_hauteur - $heightforinfotot - $heightforfreetext - $heightforfooter + 1;
             }
             // Affiche zone infos
             $posy = $this->_tableau_info($pdf, $object, $bottomlasttab, $outputlangs);
             // Affiche zone totaux
             $posy = $this->_tableau_tot($pdf, $object, $deja_regle, $bottomlasttab, $outputlangs);
             // Affiche zone versements
             if ($deja_regle || $amount_credit_notes_included || $amount_deposits_included) {
                 $posy = $this->_tableau_versements($pdf, $object, $posy, $outputlangs);
             }
             // Pied de page
             $this->_pagefoot($pdf, $object, $outputlangs);
             if (method_exists($pdf, 'AliasNbPages')) {
                 $pdf->AliasNbPages();
             }
             $pdf->Close();
             $pdf->Output($file, 'F');
             // Add pdfgeneration hook
             $hookmanager->initHooks(array('pdfgeneration'));
             $parameters = array('file' => $file, 'object' => $object, 'outputlangs' => $outputlangs);
             global $action;
             $reshook = $hookmanager->executeHooks('afterPDFCreation', $parameters, $this, $action);
             // Note that $action and $object may have been modified by some hooks
             if (!empty($conf->global->MAIN_UMASK)) {
                 @chmod($file, octdec($conf->global->MAIN_UMASK));
             }
             return 1;
             // Pas d'erreur
         } else {
             $this->error = $langs->trans("ErrorCanNotCreateDir", $dir);
             return 0;
         }
     } else {
         $this->error = $langs->trans("ErrorConstantNotDefined", "FAC_OUTPUTDIR");
         return 0;
     }
     $this->error = $langs->trans("ErrorUnknown");
     return 0;
     // Erreur par defaut
 }
 /**
  *  Function to build pdf onto disk
  *
  *  @param		Object		$object				Object to generate
  *  @param		Translate	$outputlangs		Lang output object
  *  @param		string		$srctemplatepath	Full path of source filename for generator using a template file
  *  @param		int			$hidedetails		Do not show line details
  *  @param		int			$hidedesc			Do not show desc
  *  @param		int			$hideref			Do not show ref
  *  @return     int             			1=OK, 0=KO
  */
 function write_file($object, $outputlangs, $srctemplatepath = '', $hidedetails = 0, $hidedesc = 0, $hideref = 0)
 {
     global $user, $langs, $conf, $mysoc, $db, $hookmanager;
     if (!is_object($outputlangs)) {
         $outputlangs = $langs;
     }
     // For backward compatibility with FPDF, force output charset to ISO, because FPDF expect text to be encoded in ISO
     if (!empty($conf->global->MAIN_USE_FPDF)) {
         $outputlangs->charset_output = 'ISO-8859-1';
     }
     $outputlangs->load("main");
     $outputlangs->load("dict");
     $outputlangs->load("companies");
     $outputlangs->load("bills");
     $outputlangs->load("products");
     $outputlangs->load("orders");
     $outputlangs->load("deliveries");
     $nblignes = count($object->lines);
     if ($conf->commande->dir_output) {
         $object->fetch_thirdparty();
         $deja_regle = "";
         // Definition of $dir and $file
         if ($object->specimen) {
             $dir = $conf->commande->dir_output;
             $file = $dir . "/SPECIMEN.pdf";
         } else {
             $objectref = dol_sanitizeFileName($object->ref);
             $dir = $conf->commande->dir_output . "/" . $objectref;
             $file = $dir . "/" . $objectref . ".pdf";
         }
         if (!file_exists($dir)) {
             if (dol_mkdir($dir) < 0) {
                 $this->error = $langs->transnoentities("ErrorCanNotCreateDir", $dir);
                 return 0;
             }
         }
         if (file_exists($dir)) {
             // Add pdfgeneration hook
             if (!is_object($hookmanager)) {
                 include_once DOL_DOCUMENT_ROOT . '/core/class/hookmanager.class.php';
                 $hookmanager = new HookManager($this->db);
             }
             $hookmanager->initHooks(array('pdfgeneration'));
             $parameters = array('file' => $file, 'object' => $object, 'outputlangs' => $outputlangs);
             global $action;
             $reshook = $hookmanager->executeHooks('beforePDFCreation', $parameters, $object, $action);
             // Note that $action and $object may have been modified by some hooks
             // Create pdf instance
             $pdf = pdf_getInstance($this->format);
             $default_font_size = pdf_getPDFFontSize($outputlangs);
             // Must be after pdf_getInstance
             $heightforinfotot = 50;
             // Height reserved to output the info and total part
             $heightforfreetext = isset($conf->global->MAIN_PDF_FREETEXT_HEIGHT) ? $conf->global->MAIN_PDF_FREETEXT_HEIGHT : 5;
             // Height reserved to output the free text on last page
             $heightforfooter = $this->marge_basse + 8;
             // Height reserved to output the footer (value include bottom margin)
             $pdf->SetAutoPageBreak(1, 0);
             if (class_exists('TCPDF')) {
                 $pdf->setPrintHeader(false);
                 $pdf->setPrintFooter(false);
             }
             $pdf->SetFont(pdf_getPDFFont($outputlangs));
             // Set path to the background PDF File
             if (empty($conf->global->MAIN_DISABLE_FPDI) && !empty($conf->global->MAIN_ADD_PDF_BACKGROUND)) {
                 $pagecount = $pdf->setSourceFile($conf->mycompany->dir_output . '/' . $conf->global->MAIN_ADD_PDF_BACKGROUND);
                 $tplidx = $pdf->importPage(1);
             }
             $pdf->Open();
             $pagenb = 0;
             $pdf->SetDrawColor(128, 128, 128);
             $pdf->SetTitle($outputlangs->convToOutputCharset($object->ref));
             $pdf->SetSubject($outputlangs->transnoentities("Order"));
             $pdf->SetCreator("Dolibarr " . DOL_VERSION);
             $pdf->SetAuthor($outputlangs->convToOutputCharset($user->getFullName($outputlangs)));
             $pdf->SetKeyWords($outputlangs->convToOutputCharset($object->ref) . " " . $outputlangs->transnoentities("Order"));
             if (!empty($conf->global->MAIN_DISABLE_PDF_COMPRESSION)) {
                 $pdf->SetCompression(false);
             }
             $pdf->SetMargins($this->marge_gauche, $this->marge_haute, $this->marge_droite);
             // Left, Top, Right
             // Positionne $this->atleastonediscount si on a au moins une remise
             for ($i = 0; $i < $nblignes; $i++) {
                 if ($object->lines[$i]->remise_percent) {
                     $this->atleastonediscount++;
                 }
             }
             if (empty($this->atleastonediscount)) {
                 $this->posxpicture += $this->postotalht - $this->posxdiscount;
                 $this->posxtva += $this->postotalht - $this->posxdiscount;
                 $this->posxup += $this->postotalht - $this->posxdiscount;
                 $this->posxqty += $this->postotalht - $this->posxdiscount;
                 $this->posxdiscount += $this->postotalht - $this->posxdiscount;
                 //$this->postotalht;
             }
             // New page
             $pdf->AddPage();
             if (!empty($tplidx)) {
                 $pdf->useTemplate($tplidx);
             }
             $pagenb++;
             $this->_pagehead($pdf, $object, 1, $outputlangs);
             $pdf->SetFont('', '', $default_font_size - 1);
             $pdf->MultiCell(0, 3, '');
             // Set interline to 3
             $pdf->SetTextColor(0, 0, 0);
             $tab_top = 90;
             $tab_top_newpage = empty($conf->global->MAIN_PDF_DONOTREPEAT_HEAD) ? 42 : 10;
             $tab_height = 130;
             $tab_height_newpage = 150;
             // Affiche notes
             $notetoshow = empty($object->note_public) ? '' : $object->note_public;
             if (!empty($conf->global->MAIN_ADD_SALE_REP_SIGNATURE_IN_NOTE)) {
                 // Get first sale rep
                 if (is_object($object->thirdparty)) {
                     $salereparray = $object->thirdparty->getSalesRepresentatives($user);
                     $salerepobj = new User($this->db);
                     $salerepobj->fetch($salereparray[0]['id']);
                     if (!empty($salerepobj->signature)) {
                         $notetoshow = dol_concatdesc($notetoshow, $salerepobj->signature);
                     }
                 }
             }
             if ($notetoshow) {
                 $tab_top = 88;
                 $pdf->SetFont('', '', $default_font_size - 1);
                 $pdf->writeHTMLCell(190, 3, $this->posxdesc - 1, $tab_top, dol_htmlentitiesbr($notetoshow), 0, 1);
                 $nexY = $pdf->GetY();
                 $height_note = $nexY - $tab_top;
                 // Rect prend une longueur en 3eme param
                 $pdf->SetDrawColor(192, 192, 192);
                 $pdf->Rect($this->marge_gauche, $tab_top - 1, $this->page_largeur - $this->marge_gauche - $this->marge_droite, $height_note + 1);
                 $tab_height = $tab_height - $height_note;
                 $tab_top = $nexY + 6;
             } else {
                 $height_note = 0;
             }
             $iniY = $tab_top + 7;
             $curY = $tab_top + 7;
             $nexY = $tab_top + 7;
             $inPackage = false;
             $TPackageInfos = array();
             $TChilds = array();
             $package_qty = 0;
             $TStack = array();
             // Loop on each lines
             for ($i = 0; $i < $nblignes; $i++) {
                 $package_qty = $TStack[count($TStack) - 1]['package_qty'];
                 $inPackage = count($TStack) > 0;
                 // Ligne de titre
                 if ($object->lines[$i]->product_type == 9 && $object->lines[$i]->qty < 97 && $object->lines[$i]->fk_product > 0) {
                     $inPackage = true;
                     if ($conf->global->SUBTOTAL_SHOW_QTY_ON_TITLES) {
                         if (!empty($object->lines[$i]->fk_product)) {
                             $product = new Product($db);
                             $product->fetch($object->lines[$i]->fk_product);
                             $TChilds = $product->getChildsArbo($product->id);
                             $TStack[count($TStack)] = array('childs' => $TChilds, 'package' => array(), 'package_qty' => 0);
                             // Si on se trouvait déjà dans un package, on rajoute ce produit à la liste des produits
                             // du précédent package
                             if (count($TStack) > 1) {
                                 $TStack[count($TStack) - 2]['package'][$object->lines[$i]->fk_product] += $object->lines[$i]->qty;
                             }
                         }
                     }
                 }
                 if ($conf->global->SUBTOTAL_SHOW_QTY_ON_TITLES) {
                     if ($inPackage && $object->lines[$i]->product_type != 9 && $object->lines[$i]->fk_product > 0) {
                         $TStack[count($TStack) - 1]['package'][$object->lines[$i]->fk_product] += $object->lines[$i]->qty;
                     }
                 }
                 // Ligne de sous-total
                 if ($inPackage && $object->lines[$i]->product_type == 9 && $object->lines[$i]->qty >= 97) {
                     if (count($TStack) <= 1) {
                         $inPackage = false;
                     }
                     if ($conf->global->SUBTOTAL_SHOW_QTY_ON_TITLES) {
                         // Comparaison pour déterminer la quantité de package
                         $TProducts = array_keys($TStack[count($TStack) - 1]['package']);
                         $TProductsChilds = array_keys($TStack[count($TStack) - 1]['childs']);
                         if ($TProductsChilds == $TProducts) {
                             // Il s'agit d'un package
                             // On récupére la quantité
                             $first_child_id = $TProducts[0];
                             $document_qty = $TStack[count($TStack) - 1]['package'][$first_child_id];
                             $base_qty = $TStack[count($TStack) - 1]['childs'][$first_child_id][1];
                             $TStack[count($TStack) - 1]['package_qty'] = $document_qty / $base_qty;
                             $package_qty = $TStack[count($TStack) - 1]['package_qty'];
                         }
                         array_pop($TStack);
                     }
                 }
                 $curY = $nexY;
                 $pdf->SetFont('', '', $default_font_size - 1);
                 // Into loop to work with multipage
                 $pdf->SetTextColor(0, 0, 0);
                 $pdf->setTopMargin($tab_top_newpage);
                 $pdf->setPageOrientation('', 1, $heightforfooter + $heightforfreetext + $heightforinfotot);
                 // The only function to edit the bottom margin of current page to set it.
                 $pageposbefore = $pdf->getPage();
                 // Description of product line
                 $curX = $this->posxdesc - 1;
                 $showpricebeforepagebreak = 1;
                 $pdf->startTransaction();
                 pdf_writelinedesc($pdf, $object, $i, $outputlangs, $this->posxtva - $curX, 3, $curX, $curY, $hideref, $hidedesc);
                 $pageposafter = $pdf->getPage();
                 if ($pageposafter > $pageposbefore) {
                     $pdf->rollbackTransaction(true);
                     $pageposafter = $pageposbefore;
                     //print $pageposafter.'-'.$pageposbefore;exit;
                     $pdf->setPageOrientation('', 1, $heightforfooter);
                     // The only function to edit the bottom margin of current page to set it.
                     pdf_writelinedesc($pdf, $object, $i, $outputlangs, $this->posxtva - $curX, 4, $curX, $curY, $hideref, $hidedesc);
                     $pageposafter = $pdf->getPage();
                     $posyafter = $pdf->GetY();
                     if ($posyafter > $this->page_hauteur - ($heightforfooter + $heightforfreetext + $heightforinfotot)) {
                         if ($i == $nblignes - 1) {
                             $pdf->AddPage('', '', true);
                             if (!empty($tplidx)) {
                                 $pdf->useTemplate($tplidx);
                             }
                             if (empty($conf->global->MAIN_PDF_DONOTREPEAT_HEAD)) {
                                 $this->_pagehead($pdf, $object, 0, $outputlangs);
                             }
                             $pdf->setPage($pageposafter + 1);
                         }
                     } else {
                         // We found a page break
                         $showpricebeforepagebreak = 0;
                     }
                 } else {
                     $pdf->commitTransaction();
                 }
                 $nexY = $pdf->GetY();
                 $pageposafter = $pdf->getPage();
                 $pdf->setPage($pageposbefore);
                 $pdf->setTopMargin($this->marge_haute);
                 $pdf->setPageOrientation('', 1, 0);
                 // The only function to edit the bottom margin of current page to set it.
                 // We suppose that a too long description is moved completely on next page
                 if ($pageposafter > $pageposbefore && empty($showpricebeforepagebreak)) {
                     $pdf->setPage($pageposafter);
                     $curY = $tab_top_newpage;
                 }
                 $pdf->SetFont('', '', $default_font_size - 1);
                 // On repositionne la police par defaut
                 // VAT Rate
                 if (empty($conf->global->MAIN_GENERATE_DOCUMENTS_WITHOUT_VAT)) {
                     // Si on ne doit masquer que les sous-produits
                     if ($hidedetails && !$inPackage && $conf->global->SUBTOTAL_ONLY_HIDE_SUBPRODUCTS_PRICES) {
                         $vat_rate = pdf_getlinevatrate($object, $i, $outputlangs, 0);
                     } else {
                         $vat_rate = pdf_getlinevatrate($object, $i, $outputlangs, $hidedetails);
                     }
                     $pdf->SetXY($this->posxtva, $curY);
                     $pdf->MultiCell($this->posxup - $this->posxtva - 0.8, 3, $vat_rate, 0, 'R');
                 }
                 // Unit price before discount
                 if ($hidedetails && !$inPackage && $conf->global->SUBTOTAL_ONLY_HIDE_SUBPRODUCTS_PRICES) {
                     $up_excl_tax = pdf_getlineupexcltax($object, $i, $outputlangs, 0);
                 } else {
                     $up_excl_tax = pdf_getlineupexcltax($object, $i, $outputlangs, $hidedetails);
                 }
                 $pdf->SetXY($this->posxup, $curY);
                 $pdf->MultiCell($this->posxqty - $this->posxup - 0.8, 3, $up_excl_tax, 0, 'R', 0);
                 // Booléen pour déterminer s'il s'agit d'une ligne de titre ou non
                 $isTitle = false;
                 // Quantity
                 // Récupération de la quantité à afficher
                 if ($conf->global->SUBTOTAL_IF_HIDE_PRICES_SHOW_QTY) {
                     if ($conf->global->SUBTOTAL_SHOW_QTY_ON_TITLES && $package_qty > 0) {
                         $qty = $package_qty;
                     } else {
                         $qty = pdf_getlineqty($object, $i, $outputlangs, 0);
                     }
                 } else {
                     if ($conf->global->SUBTOTAL_SHOW_QTY_ON_TITLES && $package_qty > 0) {
                         $qty = $package_qty;
                     } else {
                         $qty = pdf_getlineqty($object, $i, $outputlangs, $hidedetails);
                     }
                 }
                 $pdf->SetXY($this->posxqty, $curY);
                 $pdf->MultiCell($this->posxdiscount - $this->posxqty - 0.8, 3, $qty, 0, 'R');
                 // Enough for 6 chars
                 // Discount on line
                 if ($object->lines[$i]->remise_percent) {
                     $pdf->SetXY($this->posxdiscount - 2, $curY);
                     $remise_percent = pdf_getlineremisepercent($object, $i, $outputlangs, $hidedetails);
                     $pdf->MultiCell($this->postotalht - $this->posxdiscount + 2, 3, $remise_percent, 0, 'R');
                 }
                 // Total HT line
                 if ($hidedetails && !$inPackage && $conf->global->SUBTOTAL_ONLY_HIDE_SUBPRODUCTS_PRICES) {
                     $total_excl_tax = pdf_getlinetotalexcltax($object, $i, $outputlangs, 0);
                 } else {
                     $total_excl_tax = pdf_getlinetotalexcltax($object, $i, $outputlangs, $hidedetails);
                 }
                 $pdf->SetXY($this->postotalht, $curY);
                 $pdf->MultiCell($this->page_largeur - $this->marge_droite - $this->postotalht, 3, $total_excl_tax, 0, 'R', 0);
                 // Collecte des totaux par valeur de tva dans $this->tva["taux"]=total_tva
                 $tvaligne = $object->lines[$i]->total_tva;
                 $localtax1ligne = $object->lines[$i]->total_localtax1;
                 $localtax2ligne = $object->lines[$i]->total_localtax2;
                 $localtax1_rate = $object->lines[$i]->localtax1_tx;
                 $localtax2_rate = $object->lines[$i]->localtax2_tx;
                 $localtax1_type = $object->lines[$i]->localtax1_type;
                 $localtax2_type = $object->lines[$i]->localtax2_type;
                 if ($object->remise_percent) {
                     $tvaligne -= $tvaligne * $object->remise_percent / 100;
                 }
                 if ($object->remise_percent) {
                     $localtax1ligne -= $localtax1ligne * $object->remise_percent / 100;
                 }
                 if ($object->remise_percent) {
                     $localtax2ligne -= $localtax2ligne * $object->remise_percent / 100;
                 }
                 $vatrate = (string) $object->lines[$i]->tva_tx;
                 // Retrieve type from database for backward compatibility with old records
                 if ((!isset($localtax1_type) || $localtax1_type == '' || !isset($localtax2_type) || $localtax2_type == '') && (!empty($localtax1_rate) || !empty($localtax2_rate))) {
                     $localtaxtmp_array = getLocalTaxesFromRate($vatrate, 0, $object->thirdparty, $mysoc);
                     $localtax1_type = $localtaxtmp_array[0];
                     $localtax2_type = $localtaxtmp_array[2];
                 }
                 // retrieve global local tax
                 if ($localtax1_type && $localtax1ligne != 0) {
                     $this->localtax1[$localtax1_type][$localtax1_rate] += $localtax1ligne;
                 }
                 if ($localtax2_type && $localtax2ligne != 0) {
                     $this->localtax2[$localtax2_type][$localtax2_rate] += $localtax2ligne;
                 }
                 if (($object->lines[$i]->info_bits & 0x1) == 0x1) {
                     $vatrate .= '*';
                 }
                 if (!isset($this->tva[$vatrate])) {
                     $this->tva[$vatrate] = '';
                 }
                 $this->tva[$vatrate] += $tvaligne;
                 // Add line
                 if (!empty($conf->global->MAIN_PDF_DASH_BETWEEN_LINES) && $i < $nblignes - 1) {
                     $pdf->setPage($pageposafter);
                     $pdf->SetLineStyle(array('dash' => '1,1', 'color' => array(210, 210, 210)));
                     //$pdf->SetDrawColor(190,190,200);
                     $pdf->line($this->marge_gauche, $nexY + 1, $this->page_largeur - $this->marge_droite, $nexY + 1);
                     $pdf->SetLineStyle(array('dash' => 0));
                 }
                 $nexY += 2;
                 // Passe espace entre les lignes
                 // Detect if some page were added automatically and output _tableau for past pages
                 while ($pagenb < $pageposafter) {
                     $pdf->setPage($pagenb);
                     if ($pagenb == 1) {
                         $this->_tableau($pdf, $tab_top, $this->page_hauteur - $tab_top - $heightforfooter, 0, $outputlangs, 0, 1);
                     } else {
                         $this->_tableau($pdf, $tab_top_newpage, $this->page_hauteur - $tab_top_newpage - $heightforfooter, 0, $outputlangs, 1, 1);
                     }
                     $this->_pagefoot($pdf, $object, $outputlangs, 1);
                     $pagenb++;
                     $pdf->setPage($pagenb);
                     $pdf->setPageOrientation('', 1, 0);
                     // The only function to edit the bottom margin of current page to set it.
                     if (empty($conf->global->MAIN_PDF_DONOTREPEAT_HEAD)) {
                         $this->_pagehead($pdf, $object, 0, $outputlangs);
                     }
                 }
                 if (isset($object->lines[$i + 1]->pagebreak) && $object->lines[$i + 1]->pagebreak) {
                     if ($pagenb == 1) {
                         $this->_tableau($pdf, $tab_top, $this->page_hauteur - $tab_top - $heightforfooter, 0, $outputlangs, 0, 1);
                     } else {
                         $this->_tableau($pdf, $tab_top_newpage, $this->page_hauteur - $tab_top_newpage - $heightforfooter, 0, $outputlangs, 1, 1);
                     }
                     $this->_pagefoot($pdf, $object, $outputlangs, 1);
                     // New page
                     $pdf->AddPage();
                     if (!empty($tplidx)) {
                         $pdf->useTemplate($tplidx);
                     }
                     $pagenb++;
                     if (empty($conf->global->MAIN_PDF_DONOTREPEAT_HEAD)) {
                         $this->_pagehead($pdf, $object, 0, $outputlangs);
                     }
                 }
             }
             // Show square
             if ($pagenb == 1) {
                 $this->_tableau($pdf, $tab_top, $this->page_hauteur - $tab_top - $heightforinfotot - $heightforfreetext - $heightforfooter, 0, $outputlangs, 0, 0);
                 $bottomlasttab = $this->page_hauteur - $heightforinfotot - $heightforfreetext - $heightforfooter + 1;
             } else {
                 $this->_tableau($pdf, $tab_top_newpage, $this->page_hauteur - $tab_top_newpage - $heightforinfotot - $heightforfreetext - $heightforfooter, 0, $outputlangs, 1, 0);
                 $bottomlasttab = $this->page_hauteur - $heightforinfotot - $heightforfreetext - $heightforfooter + 1;
             }
             // Affiche zone infos
             $posy = $this->_tableau_info($pdf, $object, $bottomlasttab, $outputlangs);
             if (!$conf->global->SUBTOTAL_HIDE_DOCUMENT_TOTAL) {
                 // Affiche zone totaux
                 $posy = $this->_tableau_tot($pdf, $object, $deja_regle, $bottomlasttab, $outputlangs);
             }
             // Affiche zone versements
             if ($deja_regle) {
                 $posy = $this->_tableau_versements($pdf, $object, $posy, $outputlangs);
             }
             // Pied de page
             $this->_pagefoot($pdf, $object, $outputlangs);
             if (method_exists($pdf, 'AliasNbPages')) {
                 $pdf->AliasNbPages();
             }
             $pdf->Close();
             $pdf->Output($file, 'F');
             // Add pdfgeneration hook
             $hookmanager->initHooks(array('pdfgeneration'));
             $parameters = array('file' => $file, 'object' => $object, 'outputlangs' => $outputlangs);
             global $action;
             $reshook = $hookmanager->executeHooks('afterPDFCreation', $parameters, $this, $action);
             // Note that $action and $object may have been modified by some hooks
             if (!empty($conf->global->MAIN_UMASK)) {
                 @chmod($file, octdec($conf->global->MAIN_UMASK));
             }
             return 1;
             // Pas d'erreur
         } else {
             $this->error = $langs->trans("ErrorCanNotCreateDir", $dir);
             return 0;
         }
     } else {
         $this->error = $langs->trans("ErrorConstantNotDefined", "COMMANDE_OUTPUTDIR");
         return 0;
     }
     $this->error = $langs->trans("ErrorUnknown");
     return 0;
     // Erreur par defaut
 }