} // Same behaviour than with combolist. When not select idprodfournprice is now -2 (to avoid conflict with next action that may return -1) if (GETPOST('idprodfournprice') > 0) { $idprod = $productsupplier->get_buyprice(GETPOST('idprodfournprice'), $qty); // Just to see if a price exists for the quantity. Not used to found vat. } //Replaces $fk_unit with the product's if ($idprod > 0) { $result = $productsupplier->fetch($idprod); $label = $productsupplier->label; $desc = $productsupplier->description; if (trim($product_desc) != trim($desc)) { $desc = dol_concatdesc($desc, $product_desc); } $tvatx = get_default_tva($object->thirdparty, $mysoc, $productsupplier->id, $_POST['idprodfournprice']); $npr = get_default_npr($object->thirdparty, $mysoc, $productsupplier->id, $_POST['idprodfournprice']); $localtax1_tx = get_localtax($tvatx, 1, $mysoc, $object->thirdparty); $localtax2_tx = get_localtax($tvatx, 2, $mysoc, $object->thirdparty); $type = $productsupplier->type; $price_base_type = 'HT'; // TODO Save the product supplier ref into database into field ref_supplier (must rename field ref into ref_supplier first) $result = $object->addline($desc, $productsupplier->fourn_pu, $tvatx, $localtax1_tx, $localtax2_tx, $qty, $idprod, $remise_percent, $date_start, $date_end, 0, $npr, $price_base_type, $type, -1, 0, $array_options, $productsupplier->fk_unit); } if ($idprod == -2 || $idprod == 0) { // Product not selected $error++; $langs->load("errors"); setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("ProductOrService")), null, 'errors'); } if ($idprod == -1) { // Quantity too low
$price_base_type = GETPOST('price_base_type', 'alpha') ? GETPOST('price_base_type', 'alpha') : 'HT'; // Define special_code for special lines $special_code = 0; // if (empty($_POST['qty'])) $special_code=3; // Options should not exists on invoices // Ecrase $pu par celui du produit // Ecrase $desc par celui du produit // Ecrase $txtva par celui du produit // Ecrase $base_price_type par celui du produit // Replaces $fk_unit with the product's if (!empty($idprod)) { $prod = new Product($db); $prod->fetch($idprod); $label = GETPOST('product_label') && GETPOST('product_label') != $prod->label ? GETPOST('product_label') : ''; // Update if prices fields are defined $tva_tx = get_default_tva($mysoc, $object->thirdparty, $prod->id); $tva_npr = get_default_npr($mysoc, $object->thirdparty, $prod->id); $pu_ht = $prod->price; $pu_ttc = $prod->price_ttc; $price_min = $prod->price_min; $price_base_type = $prod->price_base_type; // We define price for product if (!empty($conf->global->PRODUIT_MULTIPRICES) && !empty($object->thirdparty->price_level)) { $pu_ht = $prod->multiprices[$object->thirdparty->price_level]; $pu_ttc = $prod->multiprices_ttc[$object->thirdparty->price_level]; $price_min = $prod->multiprices_min[$object->thirdparty->price_level]; $price_base_type = $prod->multiprices_base_type[$object->thirdparty->price_level]; if (!empty($conf->global->PRODUIT_MULTIPRICES_USE_VAT_PER_LEVEL)) { if (isset($prod->multiprices_tva_tx[$object->thirdparty->price_level])) { $tva_tx = $prod->multiprices_tva_tx[$object->thirdparty->price_level]; } if (isset($prod->multiprices_recuperableonly[$object->thirdparty->price_level])) {
$date_start=dol_mktime($_POST['date_start'.$suffixe.'hour'],$_POST['date_start'.$suffixe.'min'],$_POST['date_start'.$suffixe.'sec'],$_POST['date_start'.$suffixe.'month'],$_POST['date_start'.$suffixe.'day'],$_POST['date_start'.$suffixe.'year']); $date_end=dol_mktime($_POST['date_end'.$suffixe.'hour'],$_POST['date_end'.$suffixe.'min'],$_POST['date_end'.$suffixe.'sec'],$_POST['date_end'.$suffixe.'month'],$_POST['date_end'.$suffixe.'day'],$_POST['date_end'.$suffixe.'year']); $price_base_type = 'HT'; // Ecrase $pu par celui du produit // Ecrase $desc par celui du produit // Ecrase $txtva par celui du produit // Ecrase $base_price_type par celui du produit if ($_POST['idprod']) { $prod = new Product($db, $_POST['idprod']); $prod->fetch($_POST['idprod']); $tva_tx = get_default_tva($mysoc,$object->client,$prod->id); $tva_npr = get_default_npr($mysoc,$object->client,$prod->id); // We define price for product if ($conf->global->PRODUIT_MULTIPRICES && $object->client->price_level) { $pu_ht = $prod->multiprices[$object->client->price_level]; $pu_ttc = $prod->multiprices_ttc[$object->client->price_level]; $price_min = $prod->multiprices_min[$object->client->price_level]; $price_base_type = $prod->multiprices_base_type[$object->client->price_level]; } else { $pu_ht = $prod->price; $pu_ttc = $prod->price_ttc; $price_min = $prod->price_min; $price_base_type = $prod->price_base_type;
if ($result <= 0) { dol_print_error($db, $facture->error); exit; } $thirpdartyid = $facture->socid; } if ($thirpdartyid > 0) { $soc = new Societe($db); $result = $soc->fetch($thirpdartyid); if ($result <= 0) { dol_print_error($db, $soc->error); exit; } $desc = $object->description; $tva_tx = get_default_tva($mysoc, $soc, $object->id); $tva_npr = get_default_npr($mysoc, $soc, $object->id); if (empty($tva_tx)) { $tva_npr = 0; } $localtax1_tx = get_localtax($tva_tx, 1, $soc, $mysoc, $tva_npr); $localtax2_tx = get_localtax($tva_tx, 2, $soc, $mysoc, $tva_npr); $pu_ht = $object->price; $pu_ttc = $object->price_ttc; $price_base_type = $object->price_base_type; // If multiprice if ($conf->global->PRODUIT_MULTIPRICES && $soc->price_level) { $pu_ht = $object->multiprices[$soc->price_level]; $pu_ttc = $object->multiprices_ttc[$soc->price_level]; $price_base_type = $object->multiprices_base_type[$soc->price_level]; } elseif (!empty($conf->global->PRODUIT_CUSTOMER_PRICES)) { require_once DOL_DOCUMENT_ROOT . '/product/class/productcustomerprice.class.php';
} // Same behaviour than with combolist. When not select idprodfournprice is now -99 (to avoid conflict with next action that may return -1, -2, ...) if (GETPOST('idprodfournprice') > 0) { $idprod = $productsupplier->get_buyprice(GETPOST('idprodfournprice'), $qty); // Just to see if a price exists for the quantity. Not used to found vat. } if ($idprod > 0) { $res = $productsupplier->fetch($idprod); $label = $productsupplier->label; $desc = $productsupplier->description; if (trim($product_desc) != trim($desc)) { $desc = dol_concatdesc($desc, $product_desc); } $type = $productsupplier->type; $tva_tx = get_default_tva($object->thirdparty, $mysoc, $productsupplier->id, GETPOST('idprodfournprice')); $tva_npr = get_default_npr($object->thirdparty, $mysoc, $productsupplier->id, GETPOST('idprodfournprice')); if (empty($tva_tx)) { $tva_npr = 0; } $localtax1_tx = get_localtax($tva_tx, 1, $mysoc, $object->thirdparty, $tva_npr); $localtax2_tx = get_localtax($tva_tx, 2, $mysoc, $object->thirdparty, $tva_npr); $result = $object->addline($desc, $productsupplier->fourn_pu, $qty, $tva_tx, $localtax1_tx, $localtax2_tx, $productsupplier->id, GETPOST('idprodfournprice'), $productsupplier->fourn_ref, $remise_percent, 'HT', $pu_ttc, $type, $tva_npr, '', $date_start, $date_end, $array_options, $productsupplier->fk_unit); } if ($idprod == -99 || $idprod == 0) { // Product not selected $error++; $langs->load("errors"); setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("ProductOrService")) . ' ' . $langs->trans("or") . ' ' . $langs->trans("NoPriceDefinedForThisSupplier"), null, 'errors'); } if ($idprod == -1) { // Quantity too low
/** * Add line into array * $this->client must be loaded * * @param int $idproduct Product Id * @param float $qty Quantity * @param float $remise_percent Product discount relative * @param int $date_start Start date of the line - Added by Matelli (See http://matelli.fr/showcases/patchs-dolibarr/add-dates-in-order-lines.html) * @param int $date_end End date of the line - Added by Matelli (See http://matelli.fr/showcases/patchs-dolibarr/add-dates-in-order-lines.html) * @return void * * TODO Remplacer les appels a cette fonction par generation objet Ligne * insere dans tableau $this->products */ function add_product($idproduct, $qty, $remise_percent = 0.0, $date_start = '', $date_end = '') { global $conf, $mysoc; if (!$qty) { $qty = 1; } if ($idproduct > 0) { $prod = new Product($this->db); $prod->fetch($idproduct); $tva_tx = get_default_tva($mysoc, $this->client, $prod->id); $tva_npr = get_default_npr($mysoc, $this->client, $prod->id); if (empty($tva_tx)) { $tva_npr = 0; } $localtax1_tx = get_localtax($tva_tx, 1, $this->client, $mysoc, $tva_npr); $localtax2_tx = get_localtax($tva_tx, 2, $this->client, $mysoc, $tva_npr); // multiprix if ($conf->global->PRODUIT_MULTIPRICES && $this->client->price_level) { $price = $prod->multiprices[$this->client->price_level]; } else { $price = $prod->price; } $line = new OrderLine($this->db); $line->context = $this->context; $line->fk_product = $idproduct; $line->desc = $prod->description; $line->qty = $qty; $line->subprice = $price; $line->remise_percent = $remise_percent; $line->tva_tx = $tva_tx; $line->localtax1_tx = $localtax1_tx; $line->localtax2_tx = $localtax2_tx; $line->ref = $prod->ref; $line->libelle = $prod->label; $line->product_desc = $prod->description; $line->fk_unit = $prod->fk_unit; // Added by Matelli (See http://matelli.fr/showcases/patchs-dolibarr/add-dates-in-order-lines.html) // Save the start and end date of the line in the object if ($date_start) { $line->date_start = $date_start; } if ($date_end) { $line->date_end = $date_end; } $this->lines[] = $line; /** POUR AJOUTER AUTOMATIQUEMENT LES SOUSPRODUITS a LA COMMANDE if (! empty($conf->global->PRODUIT_SOUSPRODUITS)) { $prod = new Product($this->db); $prod->fetch($idproduct); $prod -> get_sousproduits_arbo (); $prods_arbo = $prod->get_each_prod(); if(count($prods_arbo) > 0) { foreach($prods_arbo as $key => $value) { // print "id : ".$value[1].' :qty: '.$value[0].'<br>'; if(! in_array($value[1],$this->products)) $this->add_product($value[1], $value[0]); } } } **/ } }
/** * \brief Output an HTML select vat rate * \param htmlname Nom champ html * \param selectedrate Forcage du taux tva pre-selectionne. Mettre '' pour aucun forcage. * \param societe_vendeuse Objet societe vendeuse * \param societe_acheteuse Objet societe acheteuse * \param idprod Id product * \param info_bits Miscellanous information on line * \param type ''=Unknown, 0=Product, 1=Service (Used if idprod not defined) * \remarks Si vendeur non assujeti a TVA, TVA par defaut=0. Fin de regle. * Si le (pays vendeur = pays acheteur) alors la TVA par defaut=TVA du produit vendu. Fin de regle. * Si (vendeur et acheteur dans Communaute europeenne) et bien vendu = moyen de transports neuf (auto, bateau, avion), TVA par defaut=0 (La TVA doit etre paye par l'acheteur au centre d'impots de son pays et non au vendeur). Fin de regle. * Si (vendeur et acheteur dans Communaute europeenne) et bien vendu autre que transport neuf alors la TVA par defaut=TVA du produit vendu. Fin de regle. * Sinon la TVA proposee par defaut=0. Fin de regle. */ function load_tva($htmlname = 'tauxtva', $selectedrate = '', $societe_vendeuse = '', $societe_acheteuse = '', $idprod = 0, $info_bits = 0, $type = '') { global $langs, $conf, $mysoc; $return = ''; $txtva = array(); $libtva = array(); $nprtva = array(); // Define defaultnpr and defaultttx $defaultnpr = $info_bits & 0x1; $defaultnpr = preg_match('/\\*/', $selectedrate) ? 1 : $defaultnpr; $defaulttx = str_replace('*', '', $selectedrate); // Check parameters if (is_object($societe_vendeuse) && !$societe_vendeuse->pays_code) { if ($societe_vendeuse->id == $mysoc->id) { $return .= '<font class="error">' . $langs->trans("ErrorYourCountryIsNotDefined") . '</div>'; } else { $return .= '<font class="error">' . $langs->trans("ErrorSupplierCountryIsNotDefined") . '</div>'; } return $return; } //var_dump($societe_acheteuse); //print "name=$name, selectedrate=$selectedrate, seller=".$societe_vendeuse->pays_code." buyer=".$societe_acheteuse->pays_code." buyer is company=".$societe_acheteuse->isACompany()." idprod=$idprod, info_bits=$info_bits type=$type"; //exit; // Get list of all VAT rates to show // First we defined code_pays to use to find list if (is_object($societe_vendeuse)) { $code_pays = "'" . $societe_vendeuse->pays_code . "'"; } else { $code_pays = "'" . $mysoc->pays_code . "'"; // Pour compatibilite ascendente } if (!empty($conf->global->SERVICE_ARE_ECOMMERCE_200238EC)) { if (!$societe_vendeuse->isInEEC() && $societe_acheteuse->isInEEC() && !$societe_acheteuse->isACompany()) { // We also add the buyer if (is_numeric($type)) { if ($type == 1) { $code_pays .= ",'" . $societe_acheteuse->pays_code . "'"; } } else { if (!$idprod) { $code_pays .= ",'" . $societe_acheteuse->pays_code . "'"; } else { $prodstatic = new Product($this->db); $prodstatic->fetch($idprod); if ($prodstatic->type == 1) { $code_pays .= ",'" . $societe_acheteuse->pays_code . "'"; } } } } } // Now we get list $sql = "SELECT DISTINCT t.taux, t.recuperableonly"; $sql .= " FROM " . MAIN_DB_PREFIX . "c_tva as t, " . MAIN_DB_PREFIX . "c_pays as p"; $sql .= " WHERE t.fk_pays = p.rowid"; $sql .= " AND t.active = 1"; $sql .= " AND p.code in (" . $code_pays . ")"; $sql .= " ORDER BY t.taux ASC, t.recuperableonly ASC"; $resql = $this->db->query($sql); if ($resql) { $num = $this->db->num_rows($resql); if ($num) { for ($i = 0; $i < $num; $i++) { $obj = $this->db->fetch_object($resql); $txtva[$i] = $obj->taux; $libtva[$i] = $obj->taux . '%'; $nprtva[$i] = $obj->recuperableonly; } } else { $return .= '<font class="error">' . $langs->trans("ErrorNoVATRateDefinedForSellerCountry", $code_pays) . '</font>'; } } else { $return .= '<font class="error">' . $this->db->error() . '</font>'; } // Definition du taux a pre-selectionner (si defaulttx non force et donc vaut -1 ou '') if ($defaulttx < 0 || dol_strlen($defaulttx) == 0) { $defaulttx = get_default_tva($societe_vendeuse, $societe_acheteuse, $idprod); $defaultnpr = get_default_npr($societe_vendeuse, $societe_acheteuse, $idprod); } // Si taux par defaut n'a pu etre determine, on prend dernier de la liste. // Comme ils sont tries par ordre croissant, dernier = plus eleve = taux courant if ($defaulttx < 0 || dol_strlen($defaulttx) == 0) { $defaulttx = $txtva[sizeof($txtva) - 1]; } $nbdetaux = sizeof($txtva); if ($nbdetaux > 0) { $return .= '<select class="flat" id="' . $htmlname . '" name="' . $htmlname . '">'; for ($i = 0; $i < $nbdetaux; $i++) { //print "xxxxx".$txtva[$i]."-".$nprtva[$i]; $return .= '<option value="' . $txtva[$i]; $return .= $nprtva[$i] ? '*' : ''; $return .= '"'; if ($txtva[$i] == $defaulttx && $nprtva[$i] == $defaultnpr) { $return .= ' selected="selected"'; } $return .= '>' . vatrate($libtva[$i]); $return .= $nprtva[$i] ? ' *' : ''; $return .= '</option>'; $this->tva_taux_value[$i] = $txtva[$i]; $this->tva_taux_libelle[$i] = $libtva[$i]; $this->tva_taux_npr[$i] = $nprtva[$i]; } $return .= '</select>'; } return $return; }
/** * Adds a product to the order * * @param Commande $object Order object * @param Product $prod Product to add * @param int $qty Quantity of the product * @throws Exception */ public static function addOrderLine(Commande $object, Product $prod, $qty) { global $db, $conf, $mysoc, $langs; require_once DOL_DOCUMENT_ROOT . '/core/lib/admin.lib.php'; $tva_tx = get_default_tva($mysoc, $object->thirdparty, $prod->id); $tva_npr = get_default_npr($mysoc, $object->thirdparty, $prod->id); if (!empty($conf->global->PRODUIT_MULTIPRICES) && !empty($object->thirdparty->price_level)) { $pu_ht = $prod->multiprices[$object->thirdparty->price_level]; $pu_ttc = $prod->multiprices_ttc[$object->thirdparty->price_level]; $price_base_type = $prod->multiprices_base_type[$object->thirdparty->price_level]; if (isset($prod->multiprices_tva_tx[$object->thirdparty->price_level])) { $tva_tx = $prod->multiprices_tva_tx[$object->thirdparty->price_level]; } if (isset($prod->multiprices_recuperableonly[$object->thirdparty->price_level])) { $tva_npr = $prod->multiprices_recuperableonly[$object->thirdparty->price_level]; } } elseif (!empty($conf->global->PRODUIT_CUSTOMER_PRICES)) { require_once DOL_DOCUMENT_ROOT . '/product/class/productcustomerprice.class.php'; $prodcustprice = new Productcustomerprice($db); $filter = array('t.fk_product' => $prod->id, 't.fk_soc' => $object->thirdparty->id); $result = $prodcustprice->fetch_all('', '', 0, 0, $filter); if ($result >= 0) { if (count($prodcustprice->lines) > 0) { $pu_ht = price($prodcustprice->lines[0]->price); $pu_ttc = price($prodcustprice->lines[0]->price_ttc); $price_base_type = $prodcustprice->lines[0]->price_base_type; $prod->tva_tx = $prodcustprice->lines[0]->tva_tx; } else { $pu_ht = $prod->price; $pu_ttc = $prod->price_ttc; $price_base_type = $prod->price_base_type; } } else { throw new Exception($prodcustprice->error); } } else { $pu_ht = $prod->price; $pu_ttc = $prod->price_ttc; $price_base_type = $prod->price_base_type; } // if price ht is forced (ie: calculated by margin rate and cost price) if (!empty($price_ht)) { $pu_ht = price2num($price_ht, 'MU'); $pu_ttc = price2num($pu_ht * (1 + $tva_tx / 100), 'MU'); } elseif ($tva_tx != $prod->tva_tx) { if ($price_base_type != 'HT') { $pu_ht = price2num($pu_ttc / (1 + $tva_tx / 100), 'MU'); } else { $pu_ttc = price2num($pu_ht * (1 + $tva_tx / 100), 'MU'); } } // Define output language if (!empty($conf->global->MAIN_MULTILANGS) && !empty($conf->global->PRODUIT_TEXTS_IN_THIRDPARTY_LANGUAGE)) { $outputlangs = $langs; $newlang = ''; if (empty($newlang) && GETPOST('lang_id')) { $newlang = GETPOST('lang_id'); } if (empty($newlang)) { $newlang = $object->thirdparty->default_lang; } if (!empty($newlang)) { $outputlangs = new Translate("", $conf); $outputlangs->setDefaultLang($newlang); } $desc = !empty($prod->multilangs[$outputlangs->defaultlang]["description"]) ? $prod->multilangs[$outputlangs->defaultlang]["description"] : $prod->description; } else { $desc = $prod->description; } // Add custom code and origin country into description if (empty($conf->global->MAIN_PRODUCT_DISABLE_CUSTOMCOUNTRYCODE) && (!empty($prod->customcode) || !empty($prod->country_code))) { $tmptxt = '('; if (!empty($prod->customcode)) { $tmptxt .= $langs->transnoentitiesnoconv("CustomCode") . ': ' . $prod->customcode; } if (!empty($prod->customcode) && !empty($prod->country_code)) { $tmptxt .= ' - '; } if (!empty($prod->country_code)) { $tmptxt .= $langs->transnoentitiesnoconv("CountryOrigin") . ': ' . getCountry($prod->country_code, 0, $db, $langs, 0); } $tmptxt .= ')'; $desc = dol_concatdesc($desc, $tmptxt); } //3.9.0 version added support for price units if (versioncompare(versiondolibarrarray(), array(3, 9, 0)) >= 0) { $fk_unit = $prod->fk_unit; } else { $fk_unit = null; } // Local Taxes $localtax1_tx = get_localtax($tva_tx, 1, $object->thirdparty); $localtax2_tx = get_localtax($tva_tx, 2, $object->thirdparty); $info_bits = 0; if ($tva_npr) { $info_bits |= 0x1; } //Percent remise if (!empty($object->thirdparty->remise_percent)) { $percent_remise = $object->thirdparty->remise_percent; } else { $percent_remise = 0; } // Insert line $result = $object->addline($desc, $pu_ht, $qty, $tva_tx, $localtax1_tx, $localtax2_tx, $prod->id, $percent_remise, $info_bits, 0, $price_base_type, $pu_ttc, '', '', $prod->type, -1, 0, 0, null, 0, '', 0, $fk_unit); if ($result < 0) { throw new Exception($langs->trans('ErrorAddOrderLine', $prod->ref)); } }
/** * Add line into array products * $this->client doit etre charge * * @param int $idproduct Product Id to add * @param int $qty Quantity * @param int $remise_percent Discount effected on Product * @return int <0 if KO, >0 if OK * * TODO Remplacer les appels a cette fonction par generation objet Ligne * insere dans tableau $this->products */ function add_product($idproduct, $qty, $remise_percent = 0) { global $conf, $mysoc; if (!$qty) { $qty = 1; } dol_syslog(get_class($this) . "::add_product {$idproduct}, {$qty}, {$remise_percent}"); if ($idproduct > 0) { $prod = new Product($this->db); $prod->fetch($idproduct); $productdesc = $prod->description; $tva_tx = get_default_tva($mysoc, $this->client, $prod->id); $tva_npr = get_default_npr($mysoc, $this->client, $prod->id); if (empty($tva_tx)) { $tva_npr = 0; } $localtax1_tx = get_localtax($tva_tx, 1, $mysoc, $this->client, $tva_npr); $localtax2_tx = get_localtax($tva_tx, 2, $mysoc, $this->client, $tva_npr); // multiprix if ($conf->global->PRODUIT_MULTIPRICES && $this->client->price_level) { $price = $prod->multiprices[$this->client->price_level]; } else { $price = $prod->price; } $line = new SupplierProposalLine($this->db); $line->fk_product = $idproduct; $line->desc = $productdesc; $line->qty = $qty; $line->subprice = $price; $line->remise_percent = $remise_percent; $line->tva_tx = $tva_tx; $this->lines[] = $line; } }
/** * Create invoice in database * Note: this->ref can be set or empty. If empty, we will use "(PROV)" * * @param User $user Object user that create * @param int $notrigger 1=Does not execute triggers, 0 otherwise * @param int $forceduedate 1=Do not recalculate due date from payment condition but force it with value * @return int <0 if KO, >0 if OK */ function create($user, $notrigger = 0, $forceduedate = 0) { global $langs, $conf, $mysoc, $hookmanager; $error = 0; // Clean parameters if (empty($this->type)) { $this->type = self::TYPE_STANDARD; } $this->ref_client = trim($this->ref_client); $this->note = isset($this->note) ? trim($this->note) : trim($this->note_private); // deprecated $this->note_private = isset($this->note_private) ? trim($this->note_private) : trim($this->note_private); $this->note_public = trim($this->note_public); if (!$this->cond_reglement_id) { $this->cond_reglement_id = 0; } if (!$this->mode_reglement_id) { $this->mode_reglement_id = 0; } $this->brouillon = 1; dol_syslog(get_class($this) . "::create user="******"ErrorBadParameter"; dol_syslog(get_class($this) . "::create Try to create an invoice with an empty parameter (user, date, ...)", LOG_ERR); return -3; } $soc = new Societe($this->db); $result = $soc->fetch($this->socid); if ($result < 0) { $this->error = "Failed to fetch company"; dol_syslog(get_class($this) . "::create " . $this->error, LOG_ERR); return -2; } $now = dol_now(); $this->db->begin(); // Create invoice from a predefined invoice if ($this->fac_rec > 0) { require_once DOL_DOCUMENT_ROOT . '/compta/facture/class/facture-rec.class.php'; $_facrec = new FactureRec($this->db); $result = $_facrec->fetch($this->fac_rec); $this->fk_project = $_facrec->fk_project; $this->cond_reglement_id = $_facrec->cond_reglement_id; $this->mode_reglement_id = $_facrec->mode_reglement_id; $this->remise_absolue = $_facrec->remise_absolue; $this->remise_percent = $_facrec->remise_percent; $this->fk_incoterms = $_facrec->fk_incoterms; $this->location_incoterms = $_facrec->location_incoterms; // Clean parameters if (!$this->type) { $this->type = self::TYPE_STANDARD; } $this->ref_client = trim($this->ref_client); $this->note_private = trim($this->note_private); $this->note_public = trim($this->note_public); //if (! $this->remise) $this->remise = 0; if (!$this->mode_reglement_id) { $this->mode_reglement_id = 0; } $this->brouillon = 1; } // Define due date if not already defined $datelim = empty($forceduedate) ? $this->calculate_date_lim_reglement() : $forceduedate; // Insert into database $socid = $this->socid; $sql = "INSERT INTO " . MAIN_DB_PREFIX . "facture ("; $sql .= " facnumber"; $sql .= ", entity"; $sql .= ", ref_ext"; $sql .= ", type"; $sql .= ", fk_soc"; $sql .= ", datec"; $sql .= ", remise_absolue"; $sql .= ", remise_percent"; $sql .= ", datef"; $sql .= ", note_private"; $sql .= ", note_public"; $sql .= ", ref_client, ref_int"; $sql .= ", fk_account"; $sql .= ", fk_facture_source, fk_user_author, fk_projet"; $sql .= ", fk_cond_reglement, fk_mode_reglement, date_lim_reglement, model_pdf"; $sql .= ", situation_cycle_ref, situation_counter, situation_final"; $sql .= ", fk_incoterms, location_incoterms"; $sql .= ")"; $sql .= " VALUES ("; $sql .= "'(PROV)'"; $sql .= ", " . $conf->entity; $sql .= ", " . ($this->ref_ext ? "'" . $this->db->escape($this->ref_ext) . "'" : "null"); $sql .= ", '" . $this->db->escape($this->type) . "'"; $sql .= ", '" . $socid . "'"; $sql .= ", '" . $this->db->idate($now) . "'"; $sql .= ", " . ($this->remise_absolue > 0 ? $this->remise_absolue : 'NULL'); $sql .= ", " . ($this->remise_percent > 0 ? $this->remise_percent : 'NULL'); $sql .= ", '" . $this->db->idate($this->date) . "'"; $sql .= ", " . ($this->note_private ? "'" . $this->db->escape($this->note_private) . "'" : "null"); $sql .= ", " . ($this->note_public ? "'" . $this->db->escape($this->note_public) . "'" : "null"); $sql .= ", " . ($this->ref_client ? "'" . $this->db->escape($this->ref_client) . "'" : "null"); $sql .= ", " . ($this->ref_int ? "'" . $this->db->escape($this->ref_int) . "'" : "null"); $sql .= ", " . ($this->fk_account > 0 ? $this->fk_account : 'NULL'); $sql .= ", " . ($this->fk_facture_source ? "'" . $this->db->escape($this->fk_facture_source) . "'" : "null"); $sql .= ", " . ($user->id > 0 ? "'" . $user->id . "'" : "null"); $sql .= ", " . ($this->fk_project ? $this->fk_project : "null"); $sql .= ", " . $this->cond_reglement_id; $sql .= ", " . $this->mode_reglement_id; $sql .= ", '" . $this->db->idate($datelim) . "', '" . $this->db->escape($this->modelpdf) . "'"; $sql .= ", " . ($this->situation_cycle_ref ? "'" . $this->db->escape($this->situation_cycle_ref) . "'" : "null"); $sql .= ", " . ($this->situation_counter ? "'" . $this->db->escape($this->situation_counter) . "'" : "null"); $sql .= ", " . ($this->situation_final ? $this->situation_final : 0); $sql .= ", " . (int) $this->fk_incoterms; $sql .= ", '" . $this->db->escape($this->location_incoterms) . "'"; $sql .= ")"; dol_syslog(get_class($this) . "::create", LOG_DEBUG); $resql = $this->db->query($sql); if ($resql) { $this->id = $this->db->last_insert_id(MAIN_DB_PREFIX . 'facture'); // Update ref with new one $this->ref = '(PROV' . $this->id . ')'; $sql = 'UPDATE ' . MAIN_DB_PREFIX . "facture SET facnumber='" . $this->ref . "' WHERE rowid=" . $this->id; dol_syslog(get_class($this) . "::create", LOG_DEBUG); $resql = $this->db->query($sql); if (!$resql) { $error++; } // Add object linked if (!$error && $this->id && is_array($this->linked_objects) && !empty($this->linked_objects)) { foreach ($this->linked_objects as $origin => $origin_id) { $ret = $this->add_object_linked($origin, $origin_id); if (!$ret) { dol_print_error($this->db); $error++; } // TODO mutualiser if ($origin == 'commande') { // On recupere les differents contact interne et externe $order = new Commande($this->db); $order->id = $origin_id; // On recupere le commercial suivi propale $this->userid = $order->getIdcontact('internal', 'SALESREPFOLL'); if ($this->userid) { //On passe le commercial suivi commande en commercial suivi paiement $this->add_contact($this->userid[0], 'SALESREPFOLL', 'internal'); } // On recupere le contact client facturation commande $this->contactid = $order->getIdcontact('external', 'BILLING'); if ($this->contactid) { //On passe le contact client facturation commande en contact client facturation $this->add_contact($this->contactid[0], 'BILLING', 'external'); } } } } /* * Insert lines of invoices into database */ if (count($this->lines) && is_object($this->lines[0])) { $fk_parent_line = 0; dol_syslog("There is " . count($this->lines) . " lines that are invoice lines objects"); foreach ($this->lines as $i => $val) { $newinvoiceline = $this->lines[$i]; $newinvoiceline->fk_facture = $this->id; $newinvoiceline->origin = $this->element; $newinvoiceline->origin_id = $this->lines[$i]->id; if ($result >= 0 && ($newinvoiceline->info_bits & 0x1) == 0) { // Reset fk_parent_line for no child products and special product if ($newinvoiceline->product_type != 9 && empty($newinvoiceline->fk_parent_line) || $newinvoiceline->product_type == 9) { $fk_parent_line = 0; } $newinvoiceline->fk_parent_line = $fk_parent_line; $result = $newinvoiceline->insert(); // Defined the new fk_parent_line if ($result > 0 && $newinvoiceline->product_type == 9) { $fk_parent_line = $result; } } if ($result < 0) { $this->error = $newinvoiceline->error; $error++; break; } } } else { $fk_parent_line = 0; dol_syslog("There is " . count($this->lines) . " lines that are array lines"); foreach ($this->lines as $i => $val) { if (($this->lines[$i]->info_bits & 0x1) == 0) { // Reset fk_parent_line for no child products and special product if ($this->lines[$i]->product_type != 9 && empty($this->lines[$i]->fk_parent_line) || $this->lines[$i]->product_type == 9) { $fk_parent_line = 0; } $result = $this->addline($this->lines[$i]->desc, $this->lines[$i]->subprice, $this->lines[$i]->qty, $this->lines[$i]->tva_tx, $this->lines[$i]->localtax1_tx, $this->lines[$i]->localtax2_tx, $this->lines[$i]->fk_product, $this->lines[$i]->remise_percent, $this->lines[$i]->date_start, $this->lines[$i]->date_end, $this->lines[$i]->fk_code_ventilation, $this->lines[$i]->info_bits, $this->lines[$i]->fk_remise_except, 'HT', 0, $this->lines[$i]->product_type, $this->lines[$i]->rang, $this->lines[$i]->special_code, $this->element, $this->lines[$i]->id, $fk_parent_line, $this->lines[$i]->fk_fournprice, $this->lines[$i]->pa_ht, $this->lines[$i]->label, $this->lines[$i]->array_options, $this->lines[$i]->situation_percent, $this->lines[$i]->fk_prev_id, $this->lines[$i]->fk_unit); if ($result < 0) { $this->error = $this->db->lasterror(); dol_print_error($this->db); $this->db->rollback(); return -1; } // Defined the new fk_parent_line if ($result > 0 && $this->lines[$i]->product_type == 9) { $fk_parent_line = $result; } } } } /* * Insert lines of predefined invoices */ if (!$error && $this->fac_rec > 0) { foreach ($_facrec->lines as $i => $val) { if ($_facrec->lines[$i]->fk_product) { $prod = new Product($this->db); $res = $prod->fetch($_facrec->lines[$i]->fk_product); } $tva_tx = get_default_tva($mysoc, $soc, $prod->id); $tva_npr = get_default_npr($mysoc, $soc, $prod->id); if (empty($tva_tx)) { $tva_npr = 0; } $localtax1_tx = get_localtax($tva_tx, 1, $soc, $mysoc, $tva_npr); $localtax2_tx = get_localtax($tva_tx, 2, $soc, $mysoc, $tva_npr); $result_insert = $this->addline($_facrec->lines[$i]->desc, $_facrec->lines[$i]->subprice, $_facrec->lines[$i]->qty, $tva_tx, $localtax1_tx, $localtax2_tx, $_facrec->lines[$i]->fk_product, $_facrec->lines[$i]->remise_percent, '', '', 0, $tva_npr, '', 'HT', 0, $_facrec->lines[$i]->product_type, $_facrec->lines[$i]->rang, $_facrec->lines[$i]->special_code, '', 0, 0, null, 0, $_facrec->lines[$i]->label, null, $_facrec->lines[$i]->situation_percent, '', $_facrec->lines[$i]->fk_unit); if ($result_insert < 0) { $error++; $this->error = $this->db->error(); break; } } } if (!$error) { $result = $this->update_price(1); if ($result > 0) { $action = 'create'; // Actions on extra fields (by external module or standard code) // TODO le hook fait double emploi avec le trigger !! $hookmanager->initHooks(array('invoicedao')); $parameters = array('invoiceid' => $this->id); $reshook = $hookmanager->executeHooks('insertExtraFields', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks if (empty($reshook)) { if (empty($conf->global->MAIN_EXTRAFIELDS_DISABLED)) { $result = $this->insertExtraFields(); if ($result < 0) { $error++; } } } else { if ($reshook < 0) { $error++; } } // Call trigger $result = $this->call_trigger('BILL_CREATE', $user); if ($result < 0) { $error++; } // End call triggers if (!$error) { $this->db->commit(); return $this->id; } else { $this->db->rollback(); return -4; } } else { $this->error = $langs->trans('FailedToUpdatePrice'); $this->db->rollback(); return -3; } } else { dol_syslog(get_class($this) . "::create error " . $this->error, LOG_ERR); $this->db->rollback(); return -2; } } else { $this->error = $this->db->error(); $this->db->rollback(); return -1; } }
/** * Output an HTML select vat rate * * @param string $htmlname Nom champ html * @param float $selectedrate Forcage du taux tva pre-selectionne. Mettre '' pour aucun forcage. * @param Societe $societe_vendeuse Objet societe vendeuse * @param Societe $societe_acheteuse Objet societe acheteuse * @param int $idprod Id product * @param int $info_bits Miscellaneous information on line (1 for NPR) * @param int $type ''=Unknown, 0=Product, 1=Service (Used if idprod not defined) * Si vendeur non assujeti a TVA, TVA par defaut=0. Fin de regle. * Si le (pays vendeur = pays acheteur) alors la TVA par defaut=TVA du produit vendu. Fin de regle. * Si (vendeur et acheteur dans Communaute europeenne) et bien vendu = moyen de transports neuf (auto, bateau, avion), TVA par defaut=0 (La TVA doit etre paye par l'acheteur au centre d'impots de son pays et non au vendeur). Fin de regle. * Si vendeur et acheteur dans Communauté européenne et acheteur= particulier alors TVA par défaut=TVA du produit vendu. Fin de règle. * Si vendeur et acheteur dans Communauté européenne et acheteur= entreprise alors TVA par défaut=0. Fin de règle. * Sinon la TVA proposee par defaut=0. Fin de regle. * @param bool $options_only Return options only (for ajax treatment) * @return string */ function load_tva($htmlname = 'tauxtva', $selectedrate = '', $societe_vendeuse = '', $societe_acheteuse = '', $idprod = 0, $info_bits = 0, $type = '', $options_only = false) { global $langs, $conf, $mysoc; $return = ''; $txtva = array(); $libtva = array(); $nprtva = array(); // Define defaultnpr and defaultttx $defaultnpr = $info_bits & 0x1; $defaultnpr = preg_match('/\\*/', $selectedrate) ? 1 : $defaultnpr; $defaulttx = str_replace('*', '', $selectedrate); // Check parameters if (is_object($societe_vendeuse) && !$societe_vendeuse->country_code) { if ($societe_vendeuse->id == $mysoc->id) { $return .= '<font class="error">' . $langs->trans("ErrorYourCountryIsNotDefined") . '</div>'; } else { $return .= '<font class="error">' . $langs->trans("ErrorSupplierCountryIsNotDefined") . '</div>'; } return $return; } //var_dump($societe_acheteuse); //print "name=$name, selectedrate=$selectedrate, seller=".$societe_vendeuse->country_code." buyer=".$societe_acheteuse->country_code." buyer is company=".$societe_acheteuse->isACompany()." idprod=$idprod, info_bits=$info_bits type=$type"; //exit; // Define list of countries to use to search VAT rates to show // First we defined code_country to use to find list if (is_object($societe_vendeuse)) { $code_country = "'" . $societe_vendeuse->country_code . "'"; } else { $code_country = "'" . $mysoc->country_code . "'"; // Pour compatibilite ascendente } if (!empty($conf->global->SERVICE_ARE_ECOMMERCE_200238EC)) { if (!$societe_vendeuse->isInEEC() && (!is_object($societe_acheteuse) || $societe_acheteuse->isInEEC() && !$societe_acheteuse->isACompany())) { // We also add the buyer if (is_numeric($type)) { if ($type == 1) { $code_country .= ",'" . $societe_acheteuse->country_code . "'"; } } else { if (!$idprod) { $code_country .= ",'" . $societe_acheteuse->country_code . "'"; } else { $prodstatic = new Product($this->db); $prodstatic->fetch($idprod); if ($prodstatic->type == 1) { $code_country .= ",'" . $societe_acheteuse->country_code . "'"; } } } } } // Now we get list $num = $this->load_cache_vatrates($code_country); if ($num > 0) { // Definition du taux a pre-selectionner (si defaulttx non force et donc vaut -1 ou '') if ($defaulttx < 0 || dol_strlen($defaulttx) == 0) { $defaulttx = get_default_tva($societe_vendeuse, $societe_acheteuse, $idprod); $defaultnpr = get_default_npr($societe_vendeuse, $societe_acheteuse, $idprod); } // Si taux par defaut n'a pu etre determine, on prend dernier de la liste. // Comme ils sont tries par ordre croissant, dernier = plus eleve = taux courant if ($defaulttx < 0 || dol_strlen($defaulttx) == 0) { if (empty($conf->global->MAIN_VAT_DEFAULT_IF_AUTODETECT_FAILS)) { $defaulttx = $this->cache_vatrates[$num - 1]['txtva']; } else { $defaulttx = $conf->global->MAIN_VAT_DEFAULT_IF_AUTODETECT_FAILS == 'none' ? '' : $conf->global->MAIN_VAT_DEFAULT_IF_AUTODETECT_FAILS; } } // Disabled if seller is not subject to VAT $disabled = false; $title = ''; if (is_object($societe_vendeuse) && $societe_vendeuse->id == $mysoc->id && $societe_vendeuse->tva_assuj == "0") { $title = ' title="' . $langs->trans('VATIsNotUsed') . '"'; $disabled = true; } if (!$options_only) { $return .= '<select class="flat" id="' . $htmlname . '" name="' . $htmlname . '"' . ($disabled ? ' disabled="disabled"' : '') . $title . '>'; } foreach ($this->cache_vatrates as $rate) { // Keep only 0 if seller is not subject to VAT if ($disabled && $rate['txtva'] != 0) { continue; } $return .= '<option value="' . $rate['txtva']; $return .= $rate['nprtva'] ? '*' : ''; $return .= '"'; if ($rate['txtva'] == $defaulttx && $rate['nprtva'] == $defaultnpr) { $return .= ' selected="selected"'; } $return .= '>' . vatrate($rate['libtva']); $return .= $rate['nprtva'] ? ' *' : ''; $return .= '</option>'; $this->tva_taux_value[] = $rate['txtva']; $this->tva_taux_libelle[] = $rate['libtva']; $this->tva_taux_npr[] = $rate['nprtva']; } if (!$options_only) { $return .= '</select>'; } } else { $return .= $this->error; } $this->num = $num; return $return; }
if ($rowid) { print '<input type="hidden" name="qty" value="' . $object->fourn_qty . '">'; print $object->fourn_qty; } else { print '<input class="flat" name="qty" size="5" value="' . $quantity . '">'; } print '</td></tr>'; // Vat rate $default_vat = ''; // We don't have supplier, so we try to guess. // For this we build a fictive supplier with same properties than user but using vat) $mysoc2 = clone $mysoc; $mysoc2->name = 'Fictive seller with same country'; $mysoc2->tva_assuj = 1; $default_vat = get_default_tva($mysoc2, $mysoc, $object->id, 0); $default_npr = get_default_npr($mysoc2, $mysoc, $object->id, 0); if (empty($default_vat)) { $default_npr = $default_vat; } print '<tr><td class="fieldrequired">' . $langs->trans("VATRateForSupplierProduct") . '</td>'; print '<td>'; //print $form->load_tva('tva_tx',$object->tva_tx,$supplier,$mysoc); // Do not use list here as it may be any vat rates for any country if (!empty($rowid)) { $tmpproductsupplier = new ProductFournisseur($db); $tmpproductsupplier->fetch_product_fournisseur_price($rowid, 1); $default_vat = $tmpproductsupplier->fourn_tva_tx; $default_npr = $tmpproductsupplier->fourn_tva_npr; } else { if (empty($default_vat)) { $default_vat = $object->tva_tx; }
/** * Output an HTML select vat rate * * @param string $htmlname Nom champ html * @param float $selectedrate Forcage du taux tva pre-selectionne. Mettre '' pour aucun forcage. * @param Societe $societe_vendeuse Objet societe vendeuse * @param Societe $societe_acheteuse Objet societe acheteuse * @param int $idprod Id product * @param int $info_bits Miscellaneous information on line (1 for NPR) * @param int $type ''=Unknown, 0=Product, 1=Service (Used if idprod not defined) * Si vendeur non assujeti a TVA, TVA par defaut=0. Fin de regle. * Si le (pays vendeur = pays acheteur) alors la TVA par defaut=TVA du produit vendu. Fin de regle. * Si (vendeur et acheteur dans Communaute europeenne) et bien vendu = moyen de transports neuf (auto, bateau, avion), TVA par defaut=0 (La TVA doit etre paye par l'acheteur au centre d'impots de son pays et non au vendeur). Fin de regle. * Si (vendeur et acheteur dans Communaute europeenne) et bien vendu autre que transport neuf alors la TVA par defaut=TVA du produit vendu. Fin de regle. * Sinon la TVA proposee par defaut=0. Fin de regle. * @param bool $options_only Return options only (for ajax treatment) * @return void */ function load_tva($htmlname = 'tauxtva', $selectedrate = '', $societe_vendeuse = '', $societe_acheteuse = '', $idprod = 0, $info_bits = 0, $type = '', $options_only = false) { global $langs, $conf, $mysoc; $return = ''; $txtva = array(); $libtva = array(); $nprtva = array(); // Define defaultnpr and defaultttx $defaultnpr = $info_bits & 0x1; $defaultnpr = preg_match('/\\*/', $selectedrate) ? 1 : $defaultnpr; $defaulttx = str_replace('*', '', $selectedrate); // Check parameters if (is_object($societe_vendeuse) && !$societe_vendeuse->country_code) { if ($societe_vendeuse->id == $mysoc->id) { $return .= '<font class="error">' . $langs->trans("ErrorYourCountryIsNotDefined") . '</div>'; } else { $return .= '<font class="error">' . $langs->trans("ErrorSupplierCountryIsNotDefined") . '</div>'; } return $return; } //var_dump($societe_acheteuse); //print "name=$name, selectedrate=$selectedrate, seller=".$societe_vendeuse->country_code." buyer=".$societe_acheteuse->country_code." buyer is company=".$societe_acheteuse->isACompany()." idprod=$idprod, info_bits=$info_bits type=$type"; //exit; // Get list of all VAT rates to show // First we defined code_pays to use to find list if (is_object($societe_vendeuse)) { $code_pays = "'" . $societe_vendeuse->country_code . "'"; } else { $code_pays = "'" . $mysoc->country_code . "'"; // Pour compatibilite ascendente } if (!empty($conf->global->SERVICE_ARE_ECOMMERCE_200238EC)) { // If option to have vat for end customer for services is on if (!$societe_vendeuse->isInEEC() && $societe_acheteuse->isInEEC() && !$societe_acheteuse->isACompany()) { // We also add the buyer if (is_numeric($type)) { if ($type == 1) { // We know product is a service $code_pays .= ",'" . $societe_acheteuse->country_code . "'"; } } else { if (!$idprod) { // We don't know type of product $code_pays .= ",'" . $societe_acheteuse->country_code . "'"; } else { $prodstatic = new Product($this->db); $prodstatic->fetch($idprod); if ($prodstatic->type == 1) { // We know product is a service $code_pays .= ",'" . $societe_acheteuse->country_code . "'"; } } } } } // Now we get list $num = $this->load_cache_vatrates($code_pays); if ($num > 0) { // Definition du taux a pre-selectionner (si defaulttx non force et donc vaut -1 ou '') if ($defaulttx < 0 || dol_strlen($defaulttx) == 0) { $defaulttx = get_default_tva($societe_vendeuse, $societe_acheteuse, $idprod); $defaultnpr = get_default_npr($societe_vendeuse, $societe_acheteuse, $idprod); } // Si taux par defaut n'a pu etre determine, on prend dernier de la liste. // Comme ils sont tries par ordre croissant, dernier = plus eleve = taux courant if ($defaulttx < 0 || dol_strlen($defaulttx) == 0) { $defaulttx = $this->cache_vatrates[$num - 1]['txtva']; } if (!$options_only) { $return .= '<select class="flat" id="' . $htmlname . '" name="' . $htmlname . '">'; } foreach ($this->cache_vatrates as $rate) { $return .= '<option value="' . $rate['txtva']; $return .= $rate['nprtva'] ? '*' : ''; $return .= '"'; if ($rate['txtva'] == $defaulttx && $rate['nprtva'] == $defaultnpr) { $return .= ' selected="selected"'; } $return .= '>' . vatrate($rate['libtva']); $return .= $rate['nprtva'] ? ' *' : ''; $return .= '</option>'; $this->tva_taux_value[] = $rate['txtva']; $this->tva_taux_libelle[] = $rate['libtva']; $this->tva_taux_npr[] = $rate['nprtva']; } if (!$options_only) { $return .= '</select>'; } } else { $return .= $this->error; } $this->num = $num; return $return; }