44require_once DOL_DOCUMENT_ROOT.
'/core/class/commonobject.class.php';
45require_once DOL_DOCUMENT_ROOT.
'/comm/propal/class/propaleligne.class.php';
46require_once DOL_DOCUMENT_ROOT.
'/product/class/product.class.php';
47require_once DOL_DOCUMENT_ROOT.
'/margin/lib/margins.lib.php';
48require_once DOL_DOCUMENT_ROOT.
'/multicurrency/class/multicurrency.class.php';
49require_once DOL_DOCUMENT_ROOT.
'/core/class/commonincoterm.class.php';
50require_once DOL_DOCUMENT_ROOT.
'/subtotals/class/commonsubtotal.class.php';
57 use CommonIncoterm, CommonSubtotal;
67 public $element =
'propal';
72 public $table_element =
'propal';
77 public $table_element_line =
'propaldet';
82 public $fk_element =
'fk_propal';
87 public $picto =
'propal';
93 public $restrictiononfksoc = 1;
124 public $ref_customer;
158 public $date_validation;
163 public $date_signature;
168 public $user_signature;
185 public $delivery_date;
191 public $fin_validite;
196 public $user_author_id;
227 public $cond_reglement_code;
232 public $cond_reglement;
237 public $cond_reglement_doc;
242 public $mode_reglement_code;
247 public $mode_reglement;
254 public $deposit_percent;
266 public $address_type;
277 public $availability_id;
284 public $fk_availability;
289 public $availability_code;
294 public $availability;
299 public $duree_validite;
304 public $demand_reason_id;
309 public $demand_reason_code;
314 public $demand_reason;
319 public $warehouse_id;
324 public $lines = array();
331 public $labelStatus = array();
332 public $labelStatusShort = array();
363 public $fields = array(
364 'rowid' => array(
'type' =>
'integer',
'label' =>
'TechnicalID',
'enabled' => 1,
'visible' => -1,
'notnull' => 1,
'position' => 10),
365 'entity' => array(
'type' =>
'integer',
'label' =>
'Entity',
'default' =>
'1',
'enabled' => 1,
'visible' => -2,
'notnull' => 1,
'position' => 15,
'index' => 1),
366 'ref' => array(
'type' =>
'varchar(30)',
'label' =>
'Ref',
'enabled' => 1,
'visible' => -1,
'notnull' => 1,
'showoncombobox' => 1,
'position' => 20),
367 'ref_client' => array(
'type' =>
'varchar(255)',
'label' =>
'RefCustomer',
'enabled' => 1,
'visible' => -1,
'position' => 22),
368 'ref_ext' => array(
'type' =>
'varchar(255)',
'label' =>
'RefExt',
'enabled' => 1,
'visible' => 0,
'position' => 40),
369 'fk_soc' => array(
'type' =>
'integer:Societe:societe/class/societe.class.php',
'label' =>
'ThirdParty',
'enabled' =>
'isModEnabled("societe")',
'visible' => -1,
'position' => 23),
370 'fk_projet' => array(
'type' =>
'integer:Project:projet/class/project.class.php:1:(fk_statut:=:1)',
'label' =>
'Fk projet',
'enabled' =>
"isModEnabled('project')",
'visible' => -1,
'position' => 24),
371 'tms' => array(
'type' =>
'timestamp',
'label' =>
'DateModification',
'enabled' => 1,
'visible' => -1,
'notnull' => 1,
'position' => 25),
372 'datec' => array(
'type' =>
'datetime',
'label' =>
'DateCreation',
'enabled' => 1,
'visible' => -1,
'position' => 55),
373 'datep' => array(
'type' =>
'date',
'label' =>
'Date',
'enabled' => 1,
'visible' => -1,
'position' => 60),
374 'fin_validite' => array(
'type' =>
'datetime',
'label' =>
'DateEnd',
'enabled' => 1,
'visible' => -1,
'position' => 65),
375 'date_valid' => array(
'type' =>
'datetime',
'label' =>
'DateValidation',
'enabled' => 1,
'visible' => -1,
'position' => 70),
376 'date_cloture' => array(
'type' =>
'datetime',
'label' =>
'DateClosing',
'enabled' => 1,
'visible' => -1,
'position' => 75),
377 'fk_user_author' => array(
'type' =>
'integer:User:user/class/user.class.php',
'label' =>
'Fk user author',
'enabled' => 1,
'visible' => -1,
'position' => 80),
378 'fk_user_modif' => array(
'type' =>
'integer:User:user/class/user.class.php',
'label' =>
'UserModif',
'enabled' => 1,
'visible' => -2,
'notnull' => -1,
'position' => 85),
379 'fk_user_valid' => array(
'type' =>
'integer:User:user/class/user.class.php',
'label' =>
'UserValidation',
'enabled' => 1,
'visible' => -1,
'position' => 90),
380 'fk_user_cloture' => array(
'type' =>
'integer:User:user/class/user.class.php',
'label' =>
'Fk user cloture',
'enabled' => 1,
'visible' => -1,
'position' => 95),
381 'price' => array(
'type' =>
'double',
'label' =>
'Price',
'enabled' => 1,
'visible' => -1,
'position' => 105),
382 'total_ht' => array(
'type' =>
'double(24,8)',
'label' =>
'TotalHT',
'enabled' => 1,
'visible' => -1,
'position' => 125,
'isameasure' => 1),
383 'total_tva' => array(
'type' =>
'double(24,8)',
'label' =>
'VAT',
'enabled' => 1,
'visible' => -1,
'position' => 130,
'isameasure' => 1),
384 'localtax1' => array(
'type' =>
'double(24,8)',
'label' =>
'LocalTax1',
'enabled' => 1,
'visible' => -1,
'position' => 135,
'isameasure' => 1),
385 'localtax2' => array(
'type' =>
'double(24,8)',
'label' =>
'LocalTax2',
'enabled' => 1,
'visible' => -1,
'position' => 140,
'isameasure' => 1),
386 'total_ttc' => array(
'type' =>
'double(24,8)',
'label' =>
'TotalTTC',
'enabled' => 1,
'visible' => -1,
'position' => 145,
'isameasure' => 1),
387 'fk_account' => array(
'type' =>
'integer',
'label' =>
'BankAccount',
'enabled' =>
'isModEnabled("bank")',
'visible' => -1,
'position' => 150),
388 'fk_currency' => array(
'type' =>
'varchar(3)',
'label' =>
'Currency',
'enabled' => 1,
'visible' => -1,
'position' => 155),
389 'fk_cond_reglement' => array(
'type' =>
'integer',
'label' =>
'PaymentTerm',
'enabled' => 1,
'visible' => -1,
'position' => 160),
390 'deposit_percent' => array(
'type' =>
'varchar(63)',
'label' =>
'DepositPercent',
'enabled' => 1,
'visible' => -1,
'position' => 161),
391 'fk_mode_reglement' => array(
'type' =>
'integer',
'label' =>
'PaymentMode',
'enabled' => 1,
'visible' => -1,
'position' => 165),
392 'note_private' => array(
'type' =>
'html',
'label' =>
'NotePrivate',
'enabled' => 1,
'visible' => 0,
'position' => 170),
393 'note_public' => array(
'type' =>
'html',
'label' =>
'NotePublic',
'enabled' => 1,
'visible' => 0,
'position' => 175),
394 'model_pdf' => array(
'type' =>
'varchar(255)',
'label' =>
'PDFTemplate',
'enabled' => 1,
'visible' => 0,
'position' => 180),
395 'date_livraison' => array(
'type' =>
'date',
'label' =>
'DateDeliveryPlanned',
'enabled' => 1,
'visible' => -1,
'position' => 185),
396 'fk_shipping_method' => array(
'type' =>
'integer',
'label' =>
'ShippingMethod',
'enabled' => 1,
'visible' => -1,
'position' => 190),
397 'fk_warehouse' => array(
'type' =>
'integer:Entrepot:product/stock/class/entrepot.class.php',
'label' =>
'Fk warehouse',
'enabled' =>
'isModEnabled("stock")',
'visible' => -1,
'position' => 191),
398 'fk_availability' => array(
'type' =>
'integer',
'label' =>
'Availability',
'enabled' => 1,
'visible' => -1,
'position' => 195),
399 'fk_delivery_address' => array(
'type' =>
'integer',
'label' =>
'DeliveryAddress',
'enabled' => 1,
'visible' => 0,
'position' => 200),
400 'fk_input_reason' => array(
'type' =>
'integer',
'label' =>
'InputReason',
'enabled' => 1,
'visible' => -1,
'position' => 205),
401 'extraparams' => array(
'type' =>
'varchar(255)',
'label' =>
'Extraparams',
'enabled' => 1,
'visible' => -1,
'position' => 215),
402 'fk_incoterms' => array(
'type' =>
'integer',
'label' =>
'IncotermCode',
'enabled' =>
'isModEnabled("incoterm")',
'visible' => -1,
'position' => 220),
403 'location_incoterms' => array(
'type' =>
'varchar(255)',
'label' =>
'IncotermLabel',
'enabled' =>
'isModEnabled("incoterm")',
'visible' => -1,
'position' => 225),
404 'fk_multicurrency' => array(
'type' =>
'integer',
'label' =>
'MulticurrencyID',
'enabled' => 1,
'visible' => -1,
'position' => 230),
405 'multicurrency_code' => array(
'type' =>
'varchar(255)',
'label' =>
'MulticurrencyCurrency',
'enabled' =>
'isModEnabled("multicurrency")',
'visible' => -1,
'position' => 235),
406 'multicurrency_tx' => array(
'type' =>
'double(24,8)',
'label' =>
'MulticurrencyRate',
'enabled' =>
'isModEnabled("multicurrency")',
'visible' => -1,
'position' => 240,
'isameasure' => 1),
407 'multicurrency_total_ht' => array(
'type' =>
'double(24,8)',
'label' =>
'MulticurrencyAmountHT',
'enabled' =>
'isModEnabled("multicurrency")',
'visible' => -1,
'position' => 245,
'isameasure' => 1),
408 'multicurrency_total_tva' => array(
'type' =>
'double(24,8)',
'label' =>
'MulticurrencyAmountVAT',
'enabled' =>
'isModEnabled("multicurrency")',
'visible' => -1,
'position' => 250,
'isameasure' => 1),
409 'multicurrency_total_ttc' => array(
'type' =>
'double(24,8)',
'label' =>
'MulticurrencyAmountTTC',
'enabled' =>
'isModEnabled("multicurrency")',
'visible' => -1,
'position' => 255,
'isameasure' => 1),
410 'last_main_doc' => array(
'type' =>
'varchar(255)',
'label' =>
'LastMainDoc',
'enabled' => 1,
'visible' => -1,
'position' => 260),
411 'fk_statut' => array(
'type' =>
'smallint(6)',
'label' =>
'Status',
'enabled' => 1,
'visible' => -1,
'notnull' => 1,
'position' => 500),
412 'import_key' => array(
'type' =>
'varchar(14)',
'label' =>
'ImportId',
'enabled' => 1,
'visible' => -2,
'position' => 900),
453 $this->ismultientitymanaged = 1;
454 $this->socid = $socid;
455 $this->
id = $propalid;
459 $this->fields[
'ref_ext'][
'visible'] =
getDolGlobalInt(
'MAIN_LIST_SHOW_REF_EXT');
475 public function add_product($idproduct, $qty, $remise_percent = 0)
478 global
$conf, $mysoc;
484 dol_syslog(get_class($this).
"::add_product $idproduct, $qty, $remise_percent");
485 if ($idproduct > 0) {
486 $prod =
new Product($this->db);
487 $prod->fetch($idproduct);
489 $productdesc = $prod->description;
491 $tva_tx = (string)
get_default_tva($mysoc, $this->thirdparty, $prod->id);
493 if (empty($tva_tx)) {
498 $localtax1_tx =
get_localtax($tva_tx, 1, $mysoc, $this->thirdparty, $tva_npr);
499 $localtax2_tx =
get_localtax($tva_tx, 2, $mysoc, $this->thirdparty, $tva_npr);
503 $price = $prod->multiprices[$this->thirdparty->price_level];
505 $price = $prod->price;
510 $line->fk_product = $idproduct;
511 $line->desc = $productdesc;
513 $line->subprice = $price;
514 $line->remise_percent = $remise_percent;
515 $line->vat_src_code = $vat_src_code;
516 $line->tva_tx = $tva_tx;
517 $line->fk_unit = $prod->fk_unit;
519 $line->info_bits = 1;
522 $this->lines[] = $line;
540 include_once DOL_DOCUMENT_ROOT.
'/core/lib/price.lib.php';
541 include_once DOL_DOCUMENT_ROOT.
'/core/class/discount.class.php';
546 $result = $remise->fetch($idremise);
549 if ($remise->fk_facture) {
550 $this->error = $langs->trans(
"ErrorDiscountAlreadyUsed");
551 $this->db->rollback();
557 $line->context = $this->context;
559 $line->fk_propal = $this->id;
560 $line->fk_remise_except = $remise->id;
561 $line->desc = $remise->description;
562 $line->vat_src_code = $remise->vat_src_code;
563 $line->tva_tx = $remise->tva_tx;
564 $line->subprice = -(float) $remise->amount_ht;
565 $line->fk_product = 0;
567 $line->remise_percent = 0;
569 $line->info_bits = 2;
572 $line->price = -(float) $remise->amount_ht;
574 $line->total_ht = -(float) $remise->amount_ht;
575 $line->total_tva = -(float) $remise->amount_tva;
576 $line->total_ttc = -(float) $remise->amount_ttc;
578 $result = $line->insert();
585 $this->db->rollback();
589 $this->error = $line->error;
590 $this->errors = $line->errors;
591 $this->db->rollback();
595 $this->db->rollback();
645 $remise_percent = 0.0,
646 $price_base_type =
'HT',
658 $array_options = array(),
663 $fk_remise_except = 0,
664 $noupdateafterinsertline = 0
666 global $mysoc, $langs;
668 dol_syslog(get_class($this).
"::addline propalid=$this->id, desc=$desc, pu_ht=$pu_ht, qty=$qty, txtva=$txtva, fk_product=$fk_product, remise_except=$remise_percent, price_base_type=$price_base_type, pu_ttc=$pu_ttc, info_bits=$info_bits, type=$type, fk_remise_except=".$fk_remise_except);
670 if ($this->
status == self::STATUS_DRAFT) {
671 include_once DOL_DOCUMENT_ROOT.
'/core/lib/price.lib.php';
674 if (empty($remise_percent)) {
680 if (empty($info_bits)) {
686 if (empty($fk_parent_line) || $fk_parent_line < 0) {
690 $remise_percent =
price2num($remise_percent);
693 $pu_ht_devise =
price2num($pu_ht_devise);
695 if (!preg_match(
'/\((.*)\)/', (
string) $txtva)) {
701 if ($price_base_type ==
'HT') {
712 if ($date_start && $date_end && $date_start > $date_end) {
713 $langs->load(
"errors");
714 $this->error = $langs->trans(
'ErrorStartDateGreaterEnd');
720 $product_type = $type;
721 if (!empty($fk_product) && $fk_product > 0) {
722 $product =
new Product($this->db);
723 $result = $product->fetch($fk_product);
724 $product_type = $product->type;
726 if (
getDolGlobalString(
'STOCK_MUST_BE_ENOUGH_FOR_PROPOSAL') && $product_type == 0 && $product->stock_reel < $qty) {
727 $langs->load(
"errors");
728 $this->error = $langs->trans(
'ErrorStockIsNotEnoughToAddProductOnProposal', $product->ref);
729 $this->db->rollback();
742 $tmpproduct =
new Product($this->db);
743 $result = $tmpproduct->fetch($fk_product);
744 if (abs($qty) < $tmpproduct->packaging) {
745 $qty = (float) $tmpproduct->packaging;
746 setEventMessages($langs->trans(
'QtyRecalculatedWithPackaging'),
null,
'mesgs');
748 if (!empty($tmpproduct->packaging) && $qty > $tmpproduct->packaging) {
749 $coeff = intval(abs($qty) / $tmpproduct->packaging) + 1;
750 $qty =
price2num((
float) $tmpproduct->packaging * $coeff,
'MS');
751 setEventMessages($langs->trans(
'QtyRecalculatedWithPackaging'),
null,
'mesgs');
759 if (preg_match(
'/\((.*)\)/', $txtva, $reg)) {
760 $vat_src_code = $reg[1];
761 $txtva = preg_replace(
'/\s*\(.*\)/',
'', $txtva);
764 $tabprice =
calcul_price_total($qty, (
float) $pu, (
float) $remise_percent, $txtva, (
float) $txlocaltax1, (
float) $txlocaltax2, 0, $price_base_type, $info_bits, $product_type, $mysoc, $localtaxes_type, 100, $this->multicurrency_tx, (
float) $pu_ht_devise);
766 $total_ht = $tabprice[0];
767 $total_tva = $tabprice[1];
768 $total_ttc = $tabprice[2];
769 $total_localtax1 = $tabprice[9];
770 $total_localtax2 = $tabprice[10];
771 $pu_ht = $tabprice[3];
772 $pu_tva = $tabprice[4];
773 $pu_ttc = $tabprice[5];
776 $multicurrency_total_ht = $tabprice[16];
777 $multicurrency_total_tva = $tabprice[17];
778 $multicurrency_total_ttc = $tabprice[18];
779 $pu_ht_devise = $tabprice[19];
783 if ($ranktouse == -1) {
784 $rangmax = $this->
line_max($fk_parent_line);
785 $ranktouse = $rangmax + 1;
792 if ((
float) $remise_percent > 0) {
793 $remise = round(((
float) $pu * (
float) $remise_percent / 100), 2);
794 $price = (float) $pu - $remise;
800 $this->line->context = $this->context;
802 $this->line->fk_propal = $this->id;
803 $this->line->label = $label;
804 $this->line->desc = $desc;
805 $this->line->qty = (float) $qty;
807 $this->line->vat_src_code = $vat_src_code;
808 $this->line->tva_tx = $txtva;
809 $this->line->localtax1_tx = ($total_localtax1 ? $localtaxes_type[1] : 0);
810 $this->line->localtax2_tx = ($total_localtax2 ? $localtaxes_type[3] : 0);
811 $this->line->localtax1_type = empty($localtaxes_type[0]) ?
'' : $localtaxes_type[0];
812 $this->line->localtax2_type = empty($localtaxes_type[2]) ?
'' : $localtaxes_type[2];
813 $this->line->fk_product = $fk_product;
814 $this->line->product_type = $type;
815 $this->line->fk_remise_except = $fk_remise_except;
816 $this->line->remise_percent = $remise_percent;
817 $this->line->subprice = (float) $pu_ht;
818 $this->line->rang = $ranktouse;
819 $this->line->info_bits = $info_bits;
820 $this->line->total_ht = (float) $total_ht;
821 $this->line->total_tva = (float) $total_tva;
822 $this->line->total_localtax1 = (float) $total_localtax1;
823 $this->line->total_localtax2 = (float) $total_localtax2;
824 $this->line->total_ttc = (float) $total_ttc;
825 $this->line->special_code = $special_code;
826 $this->line->fk_parent_line = $fk_parent_line;
827 $this->line->fk_unit = $fk_unit;
829 $this->line->date_start = $date_start;
830 $this->line->date_end = $date_end;
832 $this->line->fk_fournprice = $fk_fournprice;
833 $this->line->pa_ht = $pa_ht;
835 $this->line->origin_id = $origin_id;
836 $this->line->origin = $origin;
839 $this->line->fk_multicurrency = $this->fk_multicurrency;
840 $this->line->multicurrency_code = $this->multicurrency_code;
841 $this->line->multicurrency_subprice = (float) $pu_ht_devise;
842 $this->line->multicurrency_total_ht = (float) $multicurrency_total_ht;
843 $this->line->multicurrency_total_tva = (float) $multicurrency_total_tva;
844 $this->line->multicurrency_total_ttc = (float) $multicurrency_total_ttc;
847 if (empty($qty) && empty($special_code)) {
848 $this->line->special_code = 3;
852 $this->line->price = $price;
854 if (is_array($array_options) && count($array_options) > 0) {
855 $this->line->array_options = $array_options;
858 $result = $this->line->insert();
860 if (!isset($this->context[
'createfromclone'])) {
861 if (!empty($fk_parent_line)) {
864 } elseif ($ranktouse > 0 && $ranktouse <= count($this->lines)) {
866 $linecount = count($this->lines);
867 for ($ii = $ranktouse; $ii <= $linecount; $ii++) {
872 $this->lines[] = $this->line;
874 foreach ($this->lines as $line) {
875 if ($line->id == $origin_id) {
876 $this->line->extraparams = $line->extraparams;
877 $this->line->setExtraParameters();
883 if (empty($noupdateafterinsertline)) {
889 return $this->line->id;
891 $this->error = $this->db->error();
892 $this->db->rollback();
896 $this->error = $this->line->error;
897 $this->errors = $this->line->errors;
898 $this->db->rollback();
902 dol_syslog(get_class($this).
"::addline status of proposal must be Draft to allow use of ->addline()", LOG_ERR);
937 public 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_options = array(), $fk_unit =
null, $pu_ht_devise = 0, $notrigger = 0, $rang = 0)
939 global $mysoc, $langs;
941 dol_syslog(get_class($this).
"::updateLine rowid=$rowid, pu=$pu, qty=$qty, remise_percent=$remise_percent,
942 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=$pa_ht, type=$type, date_start=$date_start, date_end=$date_end");
943 include_once DOL_DOCUMENT_ROOT.
'/core/lib/price.lib.php';
946 $remise_percent =
price2num($remise_percent);
949 $pu_ht_devise =
price2num($pu_ht_devise);
950 if (!preg_match(
'/\((.*)\)/', (
string) $txtva)) {
956 if (empty($qty) && empty($special_code)) {
959 if (!empty($qty) && $special_code == 3) {
966 if ($date_start && $date_end && $date_start > $date_end) {
967 $langs->load(
"errors");
968 $this->error = $langs->trans(
'ErrorStartDateGreaterEnd');
972 if ($this->
status == self::STATUS_DRAFT) {
985 if (preg_match(
'/\((.*)\)/', $txtva, $reg)) {
986 $vat_src_code = $reg[1];
987 $txtva = preg_replace(
'/\s*\(.*\)/',
'', $txtva);
992 $tabprice =
calcul_price_total($qty, (
float) $pu, (
float) $remise_percent, $txtva, (
float) $txlocaltax1, (
float) $txlocaltax2, 0, $price_base_type, $info_bits, $type, $mysoc, $localtaxes_type, 100, $this->multicurrency_tx, (
float) $pu_ht_devise);
993 $total_ht = $tabprice[0];
994 $total_tva = $tabprice[1];
995 $total_ttc = $tabprice[2];
996 $total_localtax1 = $tabprice[9];
997 $total_localtax2 = $tabprice[10];
998 $pu_ht = $tabprice[3];
999 $pu_tva = $tabprice[4];
1000 $pu_ttc = $tabprice[5];
1003 $multicurrency_total_ht = $tabprice[16];
1004 $multicurrency_total_tva = $tabprice[17];
1005 $multicurrency_total_ttc = $tabprice[18];
1006 $pu_ht_devise = $tabprice[19];
1011 if ((
float) $remise_percent > 0) {
1012 $remise = round(((
float) $pu * (
float) $remise_percent / 100), 2);
1013 $price = (float) $pu - $remise;
1018 $line->fetch($rowid);
1020 $staticline = clone $line;
1022 $line->oldline = $staticline;
1023 $this->line = $line;
1024 $this->line->context = $this->context;
1025 $this->line->rang = $rang;
1028 if (!empty($fk_parent_line) && !empty($staticline->fk_parent_line) && $fk_parent_line != $staticline->fk_parent_line) {
1029 $rangmax = $this->
line_max($fk_parent_line);
1030 $this->line->rang = $rangmax + 1;
1034 if ($qty < $this->line->packaging) {
1035 $qty = $this->line->packaging;
1037 if (!empty($this->line->packaging)
1038 && is_numeric($this->line->packaging)
1039 && (
float) $this->line->packaging > 0
1040 && fmod((
float) $qty, (
float) $this->line->packaging) > 0) {
1041 $coeff = intval($qty / $this->line->packaging) + 1;
1042 $qty = $this->line->packaging * $coeff;
1043 setEventMessage($langs->trans(
'QtyRecalculatedWithPackaging'),
'mesgs');
1048 $this->line->id = $rowid;
1049 $this->line->label = $label;
1050 $this->line->desc = $desc;
1051 $this->line->qty = $qty;
1052 $this->line->product_type = $type;
1053 $this->line->vat_src_code = $vat_src_code;
1054 $this->line->tva_tx = $txtva;
1055 $this->line->localtax1_tx = $txlocaltax1;
1056 $this->line->localtax2_tx = $txlocaltax2;
1057 $this->line->localtax1_type = empty($localtaxes_type[0]) ?
'' : $localtaxes_type[0];
1058 $this->line->localtax2_type = empty($localtaxes_type[2]) ?
'' : $localtaxes_type[2];
1059 $this->line->remise_percent = $remise_percent;
1060 $this->line->subprice = (float) $pu_ht;
1061 $this->line->info_bits = $info_bits;
1063 $this->line->total_ht = (float) $total_ht;
1064 $this->line->total_tva = (float) $total_tva;
1065 $this->line->total_localtax1 = (float) $total_localtax1;
1066 $this->line->total_localtax2 = (float) $total_localtax2;
1067 $this->line->total_ttc = (float) $total_ttc;
1068 $this->line->special_code = $special_code;
1069 $this->line->fk_parent_line = $fk_parent_line;
1070 $this->line->skip_update_total = $skip_update_total;
1071 $this->line->fk_unit = $fk_unit;
1073 $this->line->fk_fournprice = $fk_fournprice;
1074 $this->line->pa_ht = $pa_ht;
1076 $this->line->date_start = $date_start;
1077 $this->line->date_end = $date_end;
1079 if (is_array($array_options) && count($array_options) > 0) {
1081 foreach ($array_options as $key => $value) {
1082 $this->line->array_options[$key] = $array_options[$key];
1087 $this->line->multicurrency_subprice = (float) $pu_ht_devise;
1088 $this->line->multicurrency_total_ht = (float) $multicurrency_total_ht;
1089 $this->line->multicurrency_total_tva = (float) $multicurrency_total_tva;
1090 $this->line->multicurrency_total_ttc = (float) $multicurrency_total_ttc;
1092 $result = $this->line->update($notrigger);
1095 if (!empty($fk_parent_line)) {
1105 $this->db->commit();
1108 $this->error = $this->line->error;
1109 $this->errors = $this->line->errors;
1110 $this->db->rollback();
1114 dol_syslog(get_class($this).
"::updateline Erreur -2 Propal en mode incompatible pour cette action");
1131 if ($this->
status == self::STATUS_DRAFT) {
1136 $line->context = $this->context;
1139 $line->fetch($lineid);
1144 if ($id > 0 && (
int) $line->fk_propal !== (
int) $id) {
1145 $this->db->rollback();
1146 $this->error =
'ErrorLineIDDoesNotMatchWithObjectID';
1151 $staticline = clone $line;
1152 $line->oldline = $staticline;
1154 if ($line->delete($user) > 0) {
1157 $this->db->commit();
1160 $this->error = $line->error;
1161 $this->errors = $line->errors;
1162 $this->db->rollback();
1166 $this->error =
'ErrorDeleteLineNotAllowedByObjectStatus';
1180 public function create($user, $notrigger = 0)
1182 global
$conf, $hookmanager, $mysoc;
1188 if (empty($this->date)) {
1189 $this->date = $this->datep;
1191 $this->fin_validite = $this->date + ($this->duree_validite * 24 * 3600);
1192 if (empty($this->availability_id)) {
1193 $this->availability_id = 0;
1195 if (empty($this->demand_reason_id)) {
1196 $this->demand_reason_id = 0;
1200 if (!empty($this->multicurrency_code) && empty($this->multicurrency_tx)) {
1205 if (empty($this->fk_multicurrency)) {
1206 $this->multicurrency_code =
$conf->currency;
1207 $this->fk_multicurrency = 0;
1208 $this->multicurrency_tx = 1;
1214 $delivery_date = $this->delivery_date;
1221 $this->error =
"Failed to fetch company";
1222 dol_syslog(get_class($this).
"::create ".$this->error, LOG_ERR);
1227 if (!empty($this->
ref)) {
1230 $this->error =
'ErrorRefAlreadyExists';
1231 dol_syslog(get_class($this).
"::create ".$this->error, LOG_WARNING);
1232 $this->db->rollback();
1237 if (empty($this->date)) {
1238 $this->error =
"Date of proposal is required";
1239 dol_syslog(get_class($this).
"::create ".$this->error, LOG_ERR);
1247 $sql =
"INSERT INTO ".MAIN_DB_PREFIX.$this->table_element.
" (";
1250 $sql .=
", total_tva";
1251 $sql .=
", total_ttc";
1255 $sql .=
", fk_user_author";
1256 $sql .=
", note_private";
1257 $sql .=
", note_public";
1258 $sql .=
", model_pdf";
1259 $sql .=
", fin_validite";
1260 $sql .=
", fk_cond_reglement";
1261 $sql .=
", deposit_percent";
1262 $sql .=
", fk_mode_reglement";
1263 $sql .=
", fk_account";
1264 $sql .=
", ref_client";
1265 $sql .=
", ref_ext";
1266 $sql .=
", date_livraison";
1267 $sql .=
", fk_shipping_method";
1268 $sql .=
", fk_warehouse";
1269 $sql .=
", fk_availability";
1270 $sql .=
", fk_input_reason";
1271 $sql .=
", fk_projet";
1272 $sql .=
", fk_incoterms";
1273 $sql .=
", location_incoterms";
1275 $sql .=
", fk_multicurrency";
1276 $sql .=
", multicurrency_code";
1277 $sql .=
", multicurrency_tx";
1279 $sql .=
" VALUES (";
1280 $sql .= $this->socid;
1284 $sql .=
", '".$this->db->idate($this->date).
"'";
1285 $sql .=
", '".$this->db->idate($now).
"'";
1286 $sql .=
", '(PROV)'";
1287 $sql .=
", ".($user->id > 0 ? ((int) $user->id) :
"NULL");
1288 $sql .=
", '".$this->db->escape($this->note_private).
"'";
1289 $sql .=
", '".$this->db->escape($this->note_public).
"'";
1290 $sql .=
", '".$this->db->escape($this->model_pdf).
"'";
1291 $sql .=
", ".($this->fin_validite !=
'' ?
"'".$this->db->idate($this->fin_validite).
"'" :
"NULL");
1292 $sql .=
", ".($this->cond_reglement_id > 0 ? ((int) $this->cond_reglement_id) :
'NULL');
1293 $sql .=
", ".(!empty($this->deposit_percent) ?
"'".$this->db->escape($this->deposit_percent).
"'" :
'NULL');
1294 $sql .=
", ".($this->mode_reglement_id > 0 ? ((int) $this->mode_reglement_id) :
'NULL');
1295 $sql .=
", ".($this->fk_account > 0 ? ((int) $this->fk_account) :
'NULL');
1296 $sql .=
", '".$this->db->escape($this->ref_client).
"'";
1297 $sql .=
", '".$this->db->escape($this->ref_ext).
"'";
1298 $sql .=
", ".(!
isDolTms($delivery_date) ?
"NULL" :
"'".$this->db->idate($delivery_date).
"'");
1299 $sql .=
", ".($this->shipping_method_id > 0 ? $this->shipping_method_id :
'NULL');
1300 $sql .=
", ".($this->warehouse_id > 0 ? $this->warehouse_id :
'NULL');
1301 $sql .=
", ".((int) $this->availability_id);
1302 $sql .=
", ".((int) $this->demand_reason_id);
1303 $sql .=
", ".($this->fk_project ? $this->fk_project :
"null");
1304 $sql .=
", ".(int) $this->fk_incoterms;
1305 $sql .=
", '".$this->db->escape($this->location_incoterms).
"'";
1306 $sql .=
", ".(int) $this->entity;
1307 $sql .=
", ".(int) $this->fk_multicurrency;
1308 $sql .=
", '".$this->db->escape($this->multicurrency_code).
"'";
1309 $sql .=
", ".(float) $this->multicurrency_tx;
1312 dol_syslog(get_class($this).
"::create", LOG_DEBUG);
1313 $resql = $this->db->query($sql);
1315 $this->
id = $this->db->last_insert_id(MAIN_DB_PREFIX.$this->table_element);
1318 $this->
ref =
'(PROV'.$this->id.
')';
1319 $sql =
'UPDATE '.MAIN_DB_PREFIX.$this->table_element.
" SET ref='".$this->db->escape($this->
ref).
"' WHERE rowid=".((int) $this->
id);
1321 dol_syslog(get_class($this).
"::create", LOG_DEBUG);
1322 $resql = $this->db->query($sql);
1327 if (!empty($this->linkedObjectsIds) && empty($this->linked_objects)) {
1328 $this->linked_objects = $this->linkedObjectsIds;
1332 if (!$error && $this->
id && !empty($this->linked_objects) && is_array($this->linked_objects)) {
1333 foreach ($this->linked_objects as $origin => $tmp_origin_id) {
1334 if (is_array($tmp_origin_id)) {
1335 foreach ($tmp_origin_id as $origin_id) {
1338 $this->error = $this->db->lasterror();
1343 $origin_id = $tmp_origin_id;
1346 $this->error = $this->db->lasterror();
1358 $fk_parent_line = 0;
1359 $num = count($this->lines);
1361 for ($i = 0; $i < $num; $i++) {
1362 if (!is_object($this->lines[$i])) {
1364 $line = (object) $this->lines[$i];
1366 $line = $this->lines[$i];
1369 if (($line->product_type != 9 && empty($line->fk_parent_line)) || $line->product_type == 9) {
1370 $fk_parent_line = 0;
1373 $vatrate = $line->tva_tx;
1374 if ($line->vat_src_code && !preg_match(
'/\(.*\)/', $vatrate)) {
1375 $vatrate .=
' ('.$line->vat_src_code.
')';
1379 $originid = $line->origin_id;
1380 $origintype = $line->origin;
1382 $originid = $line->id;
1383 $origintype = $this->element;
1391 $line->localtax1_tx,
1392 $line->localtax2_tx,
1394 $line->remise_percent,
1398 $line->product_type,
1400 $line->special_code,
1402 $line->fk_fournprice,
1407 $line->array_options,
1409 (
string) $origintype,
1418 $this->error = $this->db->error;
1424 $line->id = $result;
1427 if ($result > 0 && $line->product_type == 9) {
1428 $fk_parent_line = $result;
1458 if (!$error && !$notrigger) {
1467 $this->error = $this->db->lasterror();
1472 $this->error = $this->db->lasterror();
1477 $this->db->commit();
1478 dol_syslog(get_class($this).
"::create done id=".$this->
id);
1481 $this->db->rollback();
1485 $this->error = $this->db->lasterror();
1486 $this->db->rollback();
1501 public function createFromClone(
User $user, $socid = 0, $forceentity =
null, $update_prices =
false, $update_desc =
false)
1503 global
$conf, $hookmanager, $mysoc;
1512 $object =
new self($this->db);
1519 $objsoc =
new Societe($this->db);
1522 if (!empty($socid) && $socid !=
$object->socid) {
1523 if ($objsoc->fetch($socid) > 0) {
1525 $object->cond_reglement_id = (!empty($objsoc->cond_reglement_id) ? $objsoc->cond_reglement_id : 0);
1526 $object->deposit_percent = (!empty($objsoc->deposit_percent) ? $objsoc->deposit_percent :
null);
1527 $object->mode_reglement_id = (!empty($objsoc->mode_reglement_id) ? $objsoc->mode_reglement_id : 0);
1528 $object->fk_delivery_address = 0;
1551 $objsoc->fetch(
$object->socid);
1555 if ($update_prices ===
true || $update_desc ===
true) {
1556 if ($objsoc->id > 0 && !empty(
$object->lines)) {
1559 require_once DOL_DOCUMENT_ROOT .
'/product/class/productcustomerprice.class.php';
1562 foreach (
$object->lines as $line) {
1565 if ($line->fk_product > 0) {
1566 $prod =
new Product($this->db);
1567 $res = $prod->fetch($line->fk_product);
1569 if ($update_prices ===
true) {
1570 $pu_ht = $prod->price;
1572 $remise_percent = $objsoc->remise_percent;
1575 $pu_ht = $prod->multiprices[$objsoc->price_level];
1577 if (isset($prod->multiprices_tva_tx[$objsoc->price_level])) {
1578 $tva_tx = (string) $prod->multiprices_tva_tx[$objsoc->price_level];
1583 $filter = array(
't.fk_product' => (
string) $prod->id,
't.fk_soc' => (
string) $objsoc->id);
1584 $result = $prodcustprice->fetchAll(
'',
'', 0, 0, $filter);
1587 if (count($prodcustprice->lines) > 0) {
1588 $date_now = (int) floor(
dol_now() / 86400) * 86400;
1589 foreach ($prodcustprice->lines as $k => $custprice_line) {
1590 if ($custprice_line->date_begin <= $date_now && (empty($custprice_line->date_end) || $date_now <= $custprice_line->date_end)) {
1591 $pu_ht =
price($custprice_line->price);
1592 $tva_tx = ($custprice_line->default_vat_code ? $custprice_line->tva_tx .
' (' . $custprice_line->default_vat_code .
' )' : $custprice_line->tva_tx);
1593 if ($custprice_line->default_vat_code && !preg_match(
'/\(.*\)/', $tva_tx)) {
1594 $tva_tx .=
' (' . $custprice_line->default_vat_code .
')';
1596 $remise_percent = $custprice_line->discount_percent;
1604 $line->subprice = $pu_ht;
1605 $line->tva_tx = $tva_tx;
1606 $line->remise_percent = $remise_percent;
1609 if ($line->fk_fournprice > 0) {
1610 require_once DOL_DOCUMENT_ROOT.
'/fourn/class/fournisseur.product.class.php';
1612 if ($prodfourn->fetch_product_fournisseur_price($line->fk_fournprice) > 0) {
1613 $line->pa_ht =
price2num($prodfourn->fourn_unitprice * (1 - $prodfourn->fourn_remise_percent / 100),
'MU');
1615 $line->fk_fournprice = 0;
1619 if ($update_desc ===
true) {
1620 $line->desc = $prod->description;
1630 $object->entity = (!empty($forceentity) ? $forceentity :
$object->entity);
1635 $object->user_creation_id = $user->id;
1636 $object->user_validation_id = 0;
1649 $object->context[
'createfromclone'] =
'createfromclone';
1650 $result =
$object->create($user);
1652 $this->error =
$object->error;
1653 $this->errors = array_merge($this->errors,
$object->errors);
1659 if (
$object->copy_linked_contact($this,
'internal') < 0) {
1666 if ($this->socid ==
$object->socid) {
1667 if (
$object->copy_linked_contact($this,
'external') < 0) {
1675 if (is_object($hookmanager)) {
1676 $parameters = array(
'objFrom' => $this,
'clonedObj' =>
$object);
1678 $reshook = $hookmanager->executeHooks(
'createFrom', $parameters,
$object, $action);
1686 unset(
$object->context[
'createfromclone']);
1690 $this->db->commit();
1693 $this->db->rollback();
1707 public function fetch($rowid, $ref =
'', $ref_ext =
'', $forceentity = 0)
1709 $sql =
"SELECT p.rowid, p.ref, p.entity, p.fk_soc";
1710 $sql .=
", p.total_ttc, p.total_tva, p.localtax1, p.localtax2, p.total_ht";
1711 $sql .=
", p.datec";
1712 $sql .=
", p.date_signature as dates";
1713 $sql .=
", p.date_valid as datev";
1714 $sql .=
", p.datep as dp";
1715 $sql .=
", p.fin_validite as dfv";
1716 $sql .=
", p.date_livraison as delivery_date";
1717 $sql .=
", p.model_pdf, p.last_main_doc, p.ref_client, ref_ext, p.extraparams";
1718 $sql .=
", p.note_private, p.note_public";
1719 $sql .=
", p.fk_projet as fk_project, p.fk_statut";
1720 $sql .=
", p.fk_user_author, p.fk_user_valid, p.fk_user_cloture";
1721 $sql .=
", p.fk_delivery_address";
1722 $sql .=
", p.fk_availability";
1723 $sql .=
", p.fk_input_reason";
1724 $sql .=
", p.fk_cond_reglement";
1725 $sql .=
", p.fk_mode_reglement";
1726 $sql .=
', p.fk_account';
1727 $sql .=
", p.fk_shipping_method";
1728 $sql .=
", p.fk_warehouse";
1729 $sql .=
", p.fk_incoterms, p.location_incoterms";
1730 $sql .=
", p.fk_multicurrency, p.multicurrency_code, p.multicurrency_tx, p.multicurrency_total_ht, p.multicurrency_total_tva, p.multicurrency_total_ttc";
1731 $sql .=
", p.tms as date_modification";
1732 $sql .=
", i.libelle as label_incoterms";
1733 $sql .=
", c.label as statut_label";
1734 $sql .=
", ca.code as availability_code, ca.label as availability";
1735 $sql .=
", dr.code as demand_reason_code, dr.label as demand_reason";
1736 $sql .=
", cr.code as cond_reglement_code, cr.libelle as cond_reglement, cr.libelle_facture as cond_reglement_libelle_doc, p.deposit_percent";
1737 $sql .=
", cp.code as mode_reglement_code, cp.libelle as mode_reglement";
1738 $sql .=
" FROM ".MAIN_DB_PREFIX.$this->table_element.
" as p";
1739 $sql .=
' LEFT JOIN '.MAIN_DB_PREFIX.
'c_propalst as c ON p.fk_statut = c.id';
1740 $sql .=
' LEFT JOIN '.MAIN_DB_PREFIX.
'c_paiement as cp ON p.fk_mode_reglement = cp.id AND cp.entity IN ('.
getEntity(
'c_paiement').
')';
1741 $sql .=
' LEFT JOIN '.MAIN_DB_PREFIX.
'c_payment_term as cr ON p.fk_cond_reglement = cr.rowid AND cr.entity IN ('.
getEntity(
'c_payment_term').
')';
1742 $sql .=
' LEFT JOIN '.MAIN_DB_PREFIX.
'c_availability as ca ON p.fk_availability = ca.rowid';
1743 $sql .=
' LEFT JOIN '.MAIN_DB_PREFIX.
'c_input_reason as dr ON p.fk_input_reason = dr.rowid';
1744 $sql .=
' LEFT JOIN '.MAIN_DB_PREFIX.
'c_incoterms as i ON p.fk_incoterms = i.rowid';
1747 if (!empty($forceentity)) {
1748 $sql .=
" WHERE p.entity = ".(int) $forceentity;
1750 $sql .=
" WHERE p.entity IN (".getEntity(
'propal').
")";
1752 $sql .=
" AND p.ref='".$this->db->escape($ref).
"'";
1755 $sql .=
" WHERE p.rowid = ".((int) $rowid);
1758 dol_syslog(get_class($this).
"::fetch", LOG_DEBUG);
1759 $resql = $this->db->query($sql);
1761 if ($this->db->num_rows($resql)) {
1762 $obj = $this->db->fetch_object($resql);
1764 $this->
id = $obj->rowid;
1765 $this->entity = $obj->entity;
1767 $this->
ref = $obj->ref;
1768 $this->ref_client = $obj->ref_client;
1769 $this->ref_customer = $obj->ref_client;
1770 $this->ref_ext = $obj->ref_ext;
1772 $this->total = $obj->total_ttc;
1773 $this->total_ttc = $obj->total_ttc;
1774 $this->total_ht = $obj->total_ht;
1775 $this->total_tva = $obj->total_tva;
1776 $this->total_localtax1 = $obj->localtax1;
1777 $this->total_localtax2 = $obj->localtax2;
1779 $this->socid = $obj->fk_soc;
1780 $this->thirdparty =
null;
1782 $this->fk_project = $obj->fk_project;
1783 $this->project =
null;
1785 $this->model_pdf = $obj->model_pdf;
1786 $this->last_main_doc = $obj->last_main_doc;
1787 $this->note = $obj->note_private;
1788 $this->note_private = $obj->note_private;
1789 $this->note_public = $obj->note_public;
1791 $this->
status = (int) $obj->fk_statut;
1792 $this->statut = $this->status;
1794 $this->datec = $this->db->jdate($obj->datec);
1795 $this->datev = $this->db->jdate($obj->datev);
1796 $this->date_creation = $this->db->jdate($obj->datec);
1797 $this->date_validation = $this->db->jdate($obj->datev);
1798 $this->date_modification = $this->db->jdate($obj->date_modification);
1799 $this->date_signature = $this->db->jdate($obj->dates);
1800 $this->date = $this->db->jdate($obj->dp);
1801 $this->datep = $this->db->jdate($obj->dp);
1802 $this->fin_validite = $this->db->jdate($obj->dfv);
1803 $this->delivery_date = $this->db->jdate($obj->delivery_date);
1804 $this->shipping_method_id = ($obj->fk_shipping_method > 0) ? $obj->fk_shipping_method :
null;
1805 $this->warehouse_id = ($obj->fk_warehouse > 0) ? $obj->fk_warehouse :
null;
1806 $this->availability_id = $obj->fk_availability;
1807 $this->availability_code = $obj->availability_code;
1809 $this->demand_reason_id = $obj->fk_input_reason;
1810 $this->demand_reason_code = $obj->demand_reason_code;
1812 $this->fk_address = $obj->fk_delivery_address;
1814 $this->mode_reglement_id = $obj->fk_mode_reglement;
1815 $this->mode_reglement_code = $obj->mode_reglement_code;
1816 $this->mode_reglement = $obj->mode_reglement;
1817 $this->fk_account = ($obj->fk_account > 0) ? $obj->fk_account :
null;
1818 $this->cond_reglement_id = $obj->fk_cond_reglement;
1819 $this->cond_reglement_code = $obj->cond_reglement_code;
1820 $this->cond_reglement = $obj->cond_reglement;
1821 $this->cond_reglement_doc = $obj->cond_reglement_libelle_doc;
1822 $this->deposit_percent = $obj->deposit_percent;
1824 $this->extraparams = !empty($obj->extraparams) ? (array) json_decode($obj->extraparams,
true) : array();
1826 $this->user_author_id = $obj->fk_user_author;
1827 $this->user_validation_id = $obj->fk_user_valid;
1828 $this->user_closing_id = $obj->fk_user_cloture;
1831 $this->fk_incoterms = $obj->fk_incoterms;
1832 $this->location_incoterms = $obj->location_incoterms;
1833 $this->label_incoterms = $obj->label_incoterms;
1836 $this->fk_multicurrency = $obj->fk_multicurrency;
1837 $this->multicurrency_code = $obj->multicurrency_code;
1838 $this->multicurrency_tx = $obj->multicurrency_tx;
1839 $this->multicurrency_total_ht = $obj->multicurrency_total_ht;
1840 $this->multicurrency_total_tva = $obj->multicurrency_total_tva;
1841 $this->multicurrency_total_ttc = $obj->multicurrency_total_ttc;
1847 $this->db->free($resql);
1849 $this->lines = array();
1860 $this->error =
"Record Not Found";
1863 $this->error = $this->db->lasterror();
1882 if (isset($this->
ref)) {
1883 $this->
ref = trim($this->
ref);
1885 if (isset($this->ref_client)) {
1886 $this->ref_client = trim($this->ref_client);
1888 if (isset($this->note) || isset($this->note_private)) {
1889 $this->note_private = (isset($this->note_private) ? trim($this->note_private) : trim($this->note));
1891 if (isset($this->note_public)) {
1892 $this->note_public = trim($this->note_public);
1894 if (isset($this->model_pdf)) {
1895 $this->model_pdf = trim($this->model_pdf);
1897 if (isset($this->import_key)) {
1898 $this->import_key = trim($this->import_key);
1900 if (!empty($this->duree_validite) && is_numeric($this->duree_validite)) {
1901 $this->fin_validite = $this->date + ($this->duree_validite * 24 * 3600);
1908 $sql =
"UPDATE ".MAIN_DB_PREFIX.$this->table_element.
" SET";
1909 $sql =
"UPDATE ".MAIN_DB_PREFIX.
"propal SET";
1910 $sql .=
" ref = ".(isset($this->
ref) ?
"'".$this->db->escape($this->
ref).
"'" :
"null").
",";
1911 $sql .=
" ref_client = ".(isset($this->ref_client) ?
"'".$this->db->escape($this->ref_client).
"'" :
"null").
",";
1912 $sql .=
" ref_ext = ".(isset($this->ref_ext) ?
"'".$this->db->escape($this->ref_ext).
"'" :
"null").
",";
1913 $sql .=
" fk_soc = ".(!empty($this->socid) ? (int) $this->socid :
"null").
",";
1914 $sql .=
" datep = ".(strval($this->date) !=
'' ?
"'".$this->db->idate($this->date).
"'" :
'null').
",";
1915 if (!empty($this->fin_validite)) {
1916 $sql .=
" fin_validite = ".(strval($this->fin_validite) !=
'' ?
"'".$this->db->idate($this->fin_validite).
"'" :
'null').
",";
1918 $sql .=
" date_valid = ".(strval($this->date_validation) !=
'' ?
"'".$this->db->idate($this->date_validation).
"'" :
'null').
",";
1919 $sql .=
" total_tva = ".(isset($this->total_tva) ? (float) $this->total_tva :
"null").
",";
1920 $sql .=
" localtax1 = ".(isset($this->total_localtax1) ? (float) $this->total_localtax1 :
"null").
",";
1921 $sql .=
" localtax2 = ".(isset($this->total_localtax2) ? (float) $this->total_localtax2 :
"null").
",";
1922 $sql .=
" total_ht = ".(isset($this->total_ht) ? (float) $this->total_ht :
"null").
",";
1923 $sql .=
" total_ttc = ".(isset($this->total_ttc) ? (float) $this->total_ttc :
"null").
",";
1924 $sql .=
" fk_statut = ".(isset($this->
status) ? (int) $this->
status :
"null").
",";
1925 $sql .=
" fk_user_author = ".(!empty($this->user_author_id) ? (int) $this->user_author_id :
"null").
",";
1926 $sql .=
" fk_user_valid = ".(!empty($this->user_validation_id) ? (int) $this->user_validation_id :
"null").
",";
1928 $sql .=
" fk_projet = ".(!empty($this->fk_project) ? (int) $this->fk_project :
"null").
",";
1929 $sql .=
" fk_cond_reglement = ".(!empty($this->cond_reglement_id) ? (int) $this->cond_reglement_id :
"null").
",";
1930 $sql .=
" deposit_percent = ".(!empty($this->deposit_percent) ?
"'".$this->db->escape($this->deposit_percent).
"'" :
"null").
",";
1931 $sql .=
" fk_mode_reglement = ".(!empty($this->mode_reglement_id) ? (int) $this->mode_reglement_id :
"null").
",";
1932 $sql .=
" fk_input_reason = ".(!empty($this->demand_reason_id) ? (int) $this->demand_reason_id :
"null").
",";
1933 $sql .=
" fk_shipping_method=".(isset($this->shipping_method_id) ? (int) $this->shipping_method_id :
"null").
",";
1934 $sql .=
" fk_availability=".(isset($this->availability_id) ? (int) $this->availability_id :
"null").
",";
1935 $sql .=
" note_private = ".(isset($this->note_private) ?
"'".$this->db->escape($this->note_private).
"'" :
"null").
",";
1936 $sql .=
" note_public = ".(isset($this->note_public) ?
"'".$this->db->escape($this->note_public).
"'" :
"null").
",";
1937 $sql .=
" model_pdf = ".(isset($this->model_pdf) ?
"'".$this->db->escape($this->model_pdf).
"'" :
"null").
",";
1938 $sql .=
" import_key = ".(isset($this->import_key) ?
"'".$this->db->escape($this->import_key).
"'" :
"null");
1939 $sql .=
" WHERE rowid = ".((int) $this->
id);
1943 dol_syslog(get_class($this).
"::update", LOG_DEBUG);
1944 $resql = $this->db->query($sql);
1947 $this->errors[] =
"Error ".$this->db->lasterror();
1957 if (!$error && !$notrigger) {
1968 foreach ($this->errors as $errmsg) {
1969 dol_syslog(get_class($this).
"::update ".$errmsg, LOG_ERR);
1970 $this->error .= ($this->error ?
', '.$errmsg : $errmsg);
1972 $this->db->rollback();
1975 $this->db->commit();
1990 public function fetch_lines($only_product = 0, $loadalsotranslation = 0, $sqlforgedfilters =
'')
1993 $this->lines = array();
1995 $sql =
'SELECT d.rowid, d.fk_propal, d.fk_parent_line, d.label as custom_label, d.description, d.price, d.vat_src_code, d.tva_tx, d.localtax1_tx, d.localtax2_tx, d.localtax1_type, d.localtax2_type, d.qty, d.fk_remise_except, d.remise_percent, d.subprice, d.fk_product,';
1996 $sql .=
' d.info_bits, d.total_ht, d.total_tva, d.total_localtax1, d.total_localtax2, d.total_ttc, d.fk_product_fournisseur_price as fk_fournprice, d.buy_price_ht as pa_ht, d.special_code, d.rang, d.product_type,';
1997 $sql .=
' d.fk_unit,';
1998 $sql .=
' p.ref as product_ref, p.description as product_desc, p.fk_product_type, p.label as product_label, p.tobatch as product_tobatch, p.barcode as product_barcode,';
1999 $sql .=
' p.weight, p.weight_units, p.volume, p.volume_units,';
2000 $sql .=
' d.date_start, d.date_end, d.extraparams,';
2001 $sql .=
' d.fk_multicurrency, d.multicurrency_code, d.multicurrency_subprice, d.multicurrency_total_ht, d.multicurrency_total_tva, d.multicurrency_total_ttc';
2002 $sql .=
' FROM '.MAIN_DB_PREFIX.$this->table_element_line.
' as d';
2003 $sql .=
' LEFT JOIN '.MAIN_DB_PREFIX.
'product as p ON (d.fk_product = p.rowid)';
2004 $sql .=
' WHERE d.fk_propal = '.((int) $this->
id);
2005 if ($only_product) {
2006 $sql .=
' AND p.fk_product_type = 0';
2008 if ($sqlforgedfilters) {
2009 $sql .= $sqlforgedfilters;
2011 $sql .=
' ORDER by d.rang';
2013 dol_syslog(get_class($this).
"::fetch_lines", LOG_DEBUG);
2014 $result = $this->db->query($sql);
2016 require_once DOL_DOCUMENT_ROOT.
'/core/class/extrafields.class.php';
2018 $num = $this->db->num_rows($result);
2022 $objp = $this->db->fetch_object($result);
2026 $line->rowid = $objp->rowid;
2027 $line->id = $objp->rowid;
2028 $line->fk_propal = $objp->fk_propal;
2029 $line->fk_parent_line = $objp->fk_parent_line;
2030 $line->product_type = $objp->product_type;
2031 $line->label = $objp->custom_label;
2032 $line->desc = $objp->description;
2033 $line->description = $objp->description;
2034 $line->qty = $objp->qty;
2035 $line->vat_src_code = $objp->vat_src_code;
2036 $line->tva_tx = $objp->tva_tx;
2037 $line->localtax1_tx = $objp->localtax1_tx;
2038 $line->localtax2_tx = $objp->localtax2_tx;
2039 $line->localtax1_type = $objp->localtax1_type;
2040 $line->localtax2_type = $objp->localtax2_type;
2041 $line->subprice = $objp->subprice;
2042 $line->fk_remise_except = $objp->fk_remise_except;
2043 $line->remise_percent = $objp->remise_percent;
2044 $line->price = $objp->price;
2046 $line->info_bits = $objp->info_bits;
2047 $line->total_ht = $objp->total_ht;
2048 $line->total_tva = $objp->total_tva;
2049 $line->total_localtax1 = $objp->total_localtax1;
2050 $line->total_localtax2 = $objp->total_localtax2;
2051 $line->total_ttc = $objp->total_ttc;
2052 $line->fk_fournprice = $objp->fk_fournprice;
2053 $marginInfos =
getMarginInfos($objp->subprice, $objp->remise_percent, $objp->tva_tx, $objp->localtax1_tx, $objp->localtax2_tx, $line->fk_fournprice, $objp->pa_ht);
2054 $line->pa_ht = $marginInfos[0];
2055 $line->marge_tx = $marginInfos[1];
2056 $line->marque_tx = $marginInfos[2];
2057 $line->special_code = $objp->special_code;
2058 $line->rang = $objp->rang;
2060 $line->fk_product = $objp->fk_product;
2062 $line->ref = $objp->product_ref;
2063 $line->libelle = $objp->product_label;
2065 $line->product_ref = $objp->product_ref;
2066 $line->product_label = $objp->product_label;
2067 $line->product_desc = $objp->product_desc;
2068 $line->product_tobatch = $objp->product_tobatch;
2069 $line->product_barcode = $objp->product_barcode;
2071 $line->fk_product_type = $objp->fk_product_type;
2072 $line->fk_unit = $objp->fk_unit;
2073 $line->weight = $objp->weight;
2074 $line->weight_units = $objp->weight_units;
2075 $line->volume = $objp->volume;
2076 $line->volume_units = $objp->volume_units;
2078 $line->date_start = $this->db->jdate($objp->date_start);
2079 $line->date_end = $this->db->jdate($objp->date_end);
2081 $line->extraparams = !empty($objp->extraparams) ? (array) json_decode($objp->extraparams,
true) : array();
2084 $line->fk_multicurrency = $objp->fk_multicurrency;
2085 $line->multicurrency_code = $objp->multicurrency_code;
2086 $line->multicurrency_subprice = $objp->multicurrency_subprice;
2087 $line->multicurrency_total_ht = $objp->multicurrency_total_ht;
2088 $line->multicurrency_total_tva = $objp->multicurrency_total_tva;
2089 $line->multicurrency_total_ttc = $objp->multicurrency_total_ttc;
2091 $line->fetch_optionals();
2094 if (
getDolGlobalInt(
'MAIN_MULTILANGS') && !empty($objp->fk_product) && !empty($loadalsotranslation)) {
2095 $tmpproduct =
new Product($this->db);
2096 $tmpproduct->fetch($objp->fk_product);
2097 $tmpproduct->getMultiLangs();
2099 $line->multilangs = $tmpproduct->multilangs;
2102 $this->lines[$i] = $line;
2107 $this->db->free($result);
2111 $this->error = $this->db->lasterror();
2123 public function valid($user, $notrigger = 0)
2127 require_once DOL_DOCUMENT_ROOT.
'/core/lib/files.lib.php';
2132 if ($this->
status == self::STATUS_VALIDATED) {
2133 dol_syslog(get_class($this).
"::valid action abandoned: already validated", LOG_WARNING);
2137 if (!((!
getDolGlobalString(
'MAIN_USE_ADVANCED_PERMS') && $user->hasRight(
'propal',
'creer'))
2138 || (
getDolGlobalString(
'MAIN_USE_ADVANCED_PERMS') && $user->hasRight(
'propal',
'propal_advance',
'validate')))) {
2139 $this->error =
'ErrorPermissionDenied';
2140 dol_syslog(get_class($this).
"::valid ".$this->error, LOG_ERR);
2149 $soc =
new Societe($this->db);
2150 $soc->fetch($this->socid);
2153 if (!$error && (preg_match(
'/^[\(]?PROV/i', $this->
ref) || empty($this->
ref))) {
2160 $sql =
"UPDATE ".MAIN_DB_PREFIX.$this->table_element;
2161 $sql .=
" SET ref = '".$this->db->escape($num).
"',";
2162 $sql .=
" fk_statut = ".self::STATUS_VALIDATED.
", date_valid='".$this->db->idate($now).
"', fk_user_valid=".((int) $user->id);
2165 dol_syslog(get_class($this).
"::valid", LOG_DEBUG);
2166 $resql = $this->db->query($sql);
2173 if (!$error && !$notrigger) {
2175 $result = $this->
call_trigger(
'PROPAL_VALIDATE', $user);
2183 $this->oldref = $this->ref;
2186 if (preg_match(
'/^[\(]?PROV/i', $this->
ref)) {
2188 $sql =
'UPDATE '.MAIN_DB_PREFIX.
"ecm_files set filename = CONCAT('".$this->db->escape($this->newref).
"', SUBSTR(filename, ".(strlen($this->
ref) + 1).
")), filepath = 'propale/".$this->db->escape($this->newref).
"'";
2189 $sql .=
" WHERE filename LIKE '".$this->db->escape($this->
ref).
"%' AND filepath = 'propale/".$this->db->escape($this->
ref).
"' and entity = ".((int)
$conf->entity);
2190 $resql = $this->db->query($sql);
2193 $this->error = $this->db->lasterror();
2195 $sql =
'UPDATE '.MAIN_DB_PREFIX.
"ecm_files set filepath = 'propale/".$this->db->escape($this->newref).
"'";
2196 $sql .=
" WHERE filepath = 'propale/".$this->db->escape($this->
ref).
"' and entity = ".$conf->entity;
2197 $resql = $this->db->query($sql);
2200 $this->error = $this->db->lasterror();
2206 $dirsource =
$conf->propal->multidir_output[$this->entity].
'/'.$oldref;
2207 $dirdest =
$conf->propal->multidir_output[$this->entity].
'/'.$newref;
2208 if (!$error && file_exists($dirsource)) {
2209 dol_syslog(get_class($this).
"::validate rename dir ".$dirsource.
" into ".$dirdest);
2210 if (@rename($dirsource, $dirdest)) {
2213 $listoffiles =
dol_dir_list($dirdest,
'files', 1,
'^'.preg_quote($oldref,
'/'));
2214 foreach ($listoffiles as $fileentry) {
2215 $dirsource = $fileentry[
'name'];
2216 $dirdest = preg_replace(
'/^'.preg_quote($oldref,
'/').
'/', $newref, $dirsource);
2217 $dirsource = $fileentry[
'path'].
'/'.$dirsource;
2218 $dirdest = $fileentry[
'path'].
'/'.$dirdest;
2219 @rename($dirsource, $dirdest);
2227 $this->user_validation_id = $user->id;
2228 $this->datev = $now;
2229 $this->date_validation = $now;
2231 $this->db->commit();
2234 $this->db->rollback();
2253 $this->error =
'ErrorBadParameter';
2254 dol_syslog(get_class($this).
"::set_date ".$this->error, LOG_ERR);
2258 if ($user->hasRight(
'propal',
'creer')) {
2263 $sql =
"UPDATE ".MAIN_DB_PREFIX.$this->table_element;
2264 $sql .=
" SET datep = '".$this->db->idate($date).
"'";
2265 $sql .=
" WHERE rowid = ".((int) $this->
id);
2268 $resql = $this->db->query($sql);
2270 $this->errors[] = $this->db->error();
2275 $this->oldcopy = clone $this;
2276 $this->date = $date;
2277 $this->datep = $date;
2280 if (!$notrigger && empty($error)) {
2290 $this->db->commit();
2293 foreach ($this->errors as $errmsg) {
2294 dol_syslog(__METHOD__.
' Error: '.$errmsg, LOG_ERR);
2295 $this->error .= ($this->error ?
', '.$errmsg : $errmsg);
2297 $this->db->rollback();
2317 if ($user->hasRight(
'propal',
'creer')) {
2322 $sql =
"UPDATE ".MAIN_DB_PREFIX.$this->table_element;
2323 $sql .=
" SET fin_validite = ".($date_end_validity !=
'' ?
"'".$this->db->idate($date_end_validity).
"'" :
'null');
2324 $sql .=
" WHERE rowid = ".((int) $this->
id);
2328 $resql = $this->db->query($sql);
2330 $this->errors[] = $this->db->error();
2336 $this->oldcopy = clone $this;
2337 $this->fin_validite = $date_end_validity;
2340 if (!$notrigger && empty($error)) {
2350 $this->db->commit();
2353 foreach ($this->errors as $errmsg) {
2354 dol_syslog(__METHOD__.
' Error: '.$errmsg, LOG_ERR);
2355 $this->error .= ($this->error ?
', '.$errmsg : $errmsg);
2357 $this->db->rollback();
2391 if ($user->hasRight(
'propal',
'creer')) {
2396 $sql =
"UPDATE ".MAIN_DB_PREFIX.$this->table_element;
2397 $sql .=
" SET date_livraison = ".(isDolTms($delivery_date) ?
"'".$this->db->idate($delivery_date).
"'" :
'null');
2398 $sql .=
" WHERE rowid = ".((int) $this->
id);
2401 $resql = $this->db->query($sql);
2403 $this->errors[] = $this->db->error();
2408 $this->oldcopy = clone $this;
2409 $this->delivery_date = $delivery_date;
2412 if (!$notrigger && empty($error)) {
2422 $this->db->commit();
2425 foreach ($this->errors as $errmsg) {
2426 dol_syslog(__METHOD__.
' Error: '.$errmsg, LOG_ERR);
2427 $this->error .= ($this->error ?
', '.$errmsg : $errmsg);
2429 $this->db->rollback();
2449 if ($user->hasRight(
'propal',
'creer') && $this->status >= self::STATUS_DRAFT) {
2454 $sql =
"UPDATE ".MAIN_DB_PREFIX.$this->table_element;
2455 $sql .=
" SET fk_availability = ".((int) $id);
2456 $sql .=
" WHERE rowid = ".((int) $this->
id);
2458 dol_syslog(__METHOD__.
' availability('.$id.
')', LOG_DEBUG);
2459 $resql = $this->db->query($sql);
2461 $this->errors[] = $this->db->error();
2466 $this->oldcopy = clone $this;
2467 $this->fk_availability = $id;
2468 $this->availability_id = $id;
2471 if (!$notrigger && empty($error)) {
2481 $this->db->commit();
2484 foreach ($this->errors as $errmsg) {
2485 dol_syslog(__METHOD__.
' Error: '.$errmsg, LOG_ERR);
2486 $this->error .= ($this->error ?
', '.$errmsg : $errmsg);
2488 $this->db->rollback();
2492 $error_str =
'Propal status do not meet requirement '.$this->status;
2494 $this->error = $error_str;
2495 $this->errors[] = $this->error;
2512 if ($user->hasRight(
'propal',
'creer') && $this->status >= self::STATUS_DRAFT) {
2517 $sql =
"UPDATE ".MAIN_DB_PREFIX.$this->table_element;
2518 $sql .=
" SET fk_input_reason = ".((int) $id);
2519 $sql .=
" WHERE rowid = ".((int) $this->
id);
2522 $resql = $this->db->query($sql);
2524 $this->errors[] = $this->db->error();
2530 $this->oldcopy = clone $this;
2532 $this->demand_reason_id = $id;
2536 if (!$notrigger && empty($error)) {
2546 $this->db->commit();
2549 foreach ($this->errors as $errmsg) {
2550 dol_syslog(__METHOD__.
' Error: '.$errmsg, LOG_ERR);
2551 $this->error .= ($this->error ?
', '.$errmsg : $errmsg);
2553 $this->db->rollback();
2557 $error_str =
'Propal status do not meet requirement '.$this->status;
2559 $this->error = $error_str;
2560 $this->errors[] = $this->error;
2577 if ($user->hasRight(
'propal',
'creer')) {
2582 $sql =
"UPDATE ".MAIN_DB_PREFIX.$this->table_element;
2583 $sql .=
" SET ref_client = ".(empty($ref_client) ?
'NULL' :
"'".$this->db->escape($ref_client).
"'");
2584 $sql .=
" WHERE rowid = ".((int) $this->
id);
2586 dol_syslog(__METHOD__.
' $this->id='.$this->id.
', ref_client='.$ref_client, LOG_DEBUG);
2587 $resql = $this->db->query($sql);
2589 $this->errors[] = $this->db->error();
2594 $this->oldcopy = clone $this;
2595 $this->ref_client = $ref_client;
2598 if (!$notrigger && empty($error)) {
2608 $this->db->commit();
2611 foreach ($this->errors as $errmsg) {
2612 dol_syslog(__METHOD__.
' Error: '.$errmsg, LOG_ERR);
2613 $this->error .= ($this->error ?
', '.$errmsg : $errmsg);
2615 $this->db->rollback();
2633 public function reopen($user, $status, $note =
'', $notrigger = 0)
2637 $sql =
"UPDATE ".MAIN_DB_PREFIX.$this->table_element;
2638 $sql .=
" SET fk_statut = ".((int) $status).
",";
2639 if (!empty($note)) {
2640 $sql .=
" note_private = '".$this->db->escape($note).
"',";
2642 $sql .=
" date_cloture=NULL, fk_user_cloture=NULL";
2643 $sql .=
" WHERE rowid = ".((int) $this->
id);
2647 dol_syslog(get_class($this).
"::reopen", LOG_DEBUG);
2648 $resql = $this->db->query($sql);
2651 $this->errors[] =
"Error ".$this->db->lasterror();
2666 if (!empty($this->errors)) {
2667 foreach ($this->errors as $errmsg) {
2668 dol_syslog(get_class($this).
"::update ".$errmsg, LOG_ERR);
2669 $this->error .= ($this->error ?
', '.$errmsg : $errmsg);
2672 $this->db->rollback();
2675 $this->statut = $status;
2678 $this->db->commit();
2693 public function closeProposal($user, $status, $note_private =
'', $notrigger = 0, $note_public =
'')
2695 global $langs,
$conf;
2702 $newprivatenote =
dol_concatdesc($this->note_private, $note_private);
2703 $newpublicnote =
dol_concatdesc($this->note_public, $note_public);
2706 $date_signature = $now;
2707 $fk_user_signature = $user->id;
2709 $this->
info($this->
id);
2710 if (!isset($this->date_signature) || $this->date_signature ==
'') {
2711 $date_signature = $now;
2712 $fk_user_signature = $user->id;
2714 $date_signature = $this->date_signature;
2715 $fk_user_signature = $this->user_signature->id;
2719 $sql =
"UPDATE ".MAIN_DB_PREFIX.$this->table_element;
2720 $sql .=
" SET fk_statut = ".((int) $status).
", note_private = '".$this->db->escape($newprivatenote).
"', note_public = '".$this->db->escape($newpublicnote).
"'";
2721 if ($status == self::STATUS_SIGNED) {
2722 $sql .=
", date_signature='".$this->db->idate($now).
"', fk_user_signature = ".($fk_user_signature);
2724 $sql .=
" WHERE rowid = ".((int) $this->
id);
2726 $resql = $this->db->query($sql);
2730 $triggerName =
'PROPAL_CLOSE_REFUSED';
2732 if ($status == self::STATUS_SIGNED) {
2733 $triggerName =
'PROPAL_CLOSE_SIGNED';
2737 $soc =
new Societe($this->db);
2738 $soc->id = $this->socid;
2739 $result = $soc->setAsCustomer();
2742 $this->error = $this->db->lasterror();
2743 $this->db->rollback();
2750 $outputlangs = $langs;
2753 $newlang = (
GETPOST(
'lang_id',
'aZ09') ?
GETPOST(
'lang_id',
'aZ09') : $this->thirdparty->default_lang);
2754 $outputlangs->setDefaultLang($newlang);
2763 $this->
generateDocument($modelpdf, $outputlangs, $hidedetails, $hidedesc, $hideref);
2767 $this->oldcopy = clone $this;
2768 $this->statut = $status;
2770 $this->date_signature = $date_signature;
2771 $this->note_private = $newprivatenote;
2774 if (!$notrigger && empty($error)) {
2784 $this->db->commit();
2787 foreach ($this->errors as $errmsg) {
2788 dol_syslog(__METHOD__.
' Error: '.$errmsg, LOG_ERR);
2789 $this->error .= ($this->error ?
', '.$errmsg : $errmsg);
2791 if (!empty($this->oldcopy)) {
2792 $this->statut = $this->oldcopy->status;
2793 $this->
status = $this->oldcopy->status;
2794 $this->date_signature = $this->oldcopy->date_signature;
2795 $this->note_private = $this->oldcopy->note_private;
2798 $this->db->rollback();
2802 $this->error = $this->db->lasterror();
2803 $this->db->rollback();
2818 global
$conf, $langs;
2825 $triggerName =
'PROPAL_CLASSIFY_BILLED';
2831 $sql =
'UPDATE '.MAIN_DB_PREFIX.$this->table_element;
2832 $sql .=
" SET fk_statut = ".self::STATUS_BILLED.
", ";
2833 $sql .=
" note_private = '".$this->db->escape($newprivatenote).
"', date_cloture='".$this->db->idate($now).
"', fk_user_cloture=".((int) $user->id);
2834 $sql .=
' WHERE rowid = '.((int) $this->
id).
' AND fk_statut = '.((int) self::STATUS_SIGNED);
2837 $resql = $this->db->query($sql);
2839 $this->errors[] = $this->db->error();
2842 $num = $this->db->affected_rows($resql);
2850 $outputlangs = $langs;
2853 $newlang = (
GETPOST(
'lang_id',
'aZ09') ?
GETPOST(
'lang_id',
'aZ09') : $this->thirdparty->default_lang);
2854 $outputlangs->setDefaultLang($newlang);
2863 $this->
generateDocument($modelpdf, $outputlangs, $hidedetails, $hidedesc, $hideref);
2866 $this->oldcopy = clone $this;
2869 $this->date_cloture = $now;
2870 $this->note_private = $newprivatenote;
2873 if (!$notrigger && empty($error)) {
2883 $this->db->commit();
2886 foreach ($this->errors as $errmsg) {
2887 dol_syslog(__METHOD__.
' Error: '.$errmsg, LOG_ERR);
2888 $this->error .= ($this->error ?
', '.$errmsg : $errmsg);
2890 $this->db->rollback();
2907 $sql =
"UPDATE ". MAIN_DB_PREFIX . $this->table_element;
2908 $sql .=
" SET fk_statut = " . self::STATUS_CANCELED .
",";
2909 $sql .=
" fk_user_modif = " . ((int) $user->id);
2910 $sql .=
" WHERE rowid = " . ((int) $this->
id);
2912 dol_syslog(get_class($this).
"::cancel", LOG_DEBUG);
2913 if ($this->db->query($sql)) {
2926 $this->db->commit();
2929 foreach ($this->errors as $errmsg) {
2930 dol_syslog(get_class($this).
"::cancel ".$errmsg, LOG_ERR);
2931 $this->error .= ($this->error ?
', '.$errmsg : $errmsg);
2933 $this->db->rollback();
2937 $this->error = $this->db->error();
2938 $this->db->rollback();
2957 if ($this->
status <= self::STATUS_DRAFT) {
2961 dol_syslog(get_class($this).
"::setDraft", LOG_DEBUG);
2965 $sql =
"UPDATE ".MAIN_DB_PREFIX.$this->table_element;
2966 $sql .=
" SET fk_statut = ".self::STATUS_DRAFT;
2967 $sql .=
", online_sign_ip = NULL , online_sign_name = NULL";
2968 $sql .=
" WHERE rowid = ".((int) $this->
id);
2970 $resql = $this->db->query($sql);
2972 $this->errors[] = $this->db->error();
2977 $this->oldcopy = clone $this;
2980 if (!$notrigger && empty($error)) {
2993 $this->db->commit();
2996 foreach ($this->errors as $errmsg) {
2997 dol_syslog(__METHOD__.
' Error: '.$errmsg, LOG_ERR);
2998 $this->error .= ($this->error ?
', '.$errmsg : $errmsg);
3000 $this->db->rollback();
3020 public function liste_array($shortlist = 0, $draft = 0, $notcurrentuser = 0, $socid = 0, $limit = 0, $offset = 0, $sortfield =
'p.datep', $sortorder =
'DESC')
3027 $sql =
"SELECT s.rowid, s.nom as name, s.client,";
3028 $sql .=
" p.rowid as propalid, p.fk_statut, p.total_ht, p.ref, p.remise, ";
3029 $sql .=
" p.datep as dp, p.fin_validite as datelimite";
3030 $sql .=
" FROM ".MAIN_DB_PREFIX.
"societe as s, ".MAIN_DB_PREFIX.$this->table_element.
" as p, ".MAIN_DB_PREFIX.
"c_propalst as c";
3031 $sql .=
" WHERE p.entity IN (".getEntity(
'propal').
")";
3032 $sql .=
" AND p.fk_soc = s.rowid";
3033 $sql .=
" AND p.fk_statut = c.id";
3037 if (empty($user->socid) && !$user->hasRight(
'societe',
'client',
'voir')) {
3038 $search_sale = $user->id;
3041 if ($search_sale && $search_sale !=
'-1') {
3042 if ($search_sale == -2) {
3043 $sql .=
" AND NOT EXISTS (SELECT sc.fk_soc FROM ".MAIN_DB_PREFIX.
"societe_commerciaux as sc WHERE sc.fk_soc = p.fk_soc)";
3044 } elseif ($search_sale > 0) {
3045 $sql .=
" AND EXISTS (SELECT sc.fk_soc FROM ".MAIN_DB_PREFIX.
"societe_commerciaux as sc WHERE sc.fk_soc = p.fk_soc AND sc.fk_user = ".((int) $search_sale).
")";
3050 $sql .=
" AND p.fk_soc = ".((int) $socid);
3053 $sql .=
" AND p.fk_statut = ".((int) self::STATUS_DRAFT);
3055 if ($notcurrentuser > 0) {
3056 $sql .=
" AND p.fk_user_author <> ".((int) $user->id);
3058 $sql .= $this->db->order($sortfield, $sortorder);
3059 $sql .= $this->db->plimit($limit, $offset);
3061 $result = $this->db->query($sql);
3063 $num = $this->db->num_rows($result);
3067 $obj = $this->db->fetch_object($result);
3069 if ($shortlist == 1) {
3070 $ga[$obj->propalid] = $obj->ref;
3071 } elseif ($shortlist == 2) {
3072 $ga[$obj->propalid] = $obj->ref.
' ('.$obj->name.
')';
3074 $ga[$i][
'id'] = $obj->propalid;
3075 $ga[$i][
'ref'] = $obj->ref;
3076 $ga[$i][
'name'] = $obj->name;
3110 $linkedInvoices = array();
3113 foreach ($this->linkedObjectsIds as $objecttype => $objectid) {
3116 foreach ($objectid as $key =>
$object) {
3118 if ($objecttype ==
'facture') {
3123 foreach ($this->linkedObjectsIds as $subobjecttype => $subobjectid) {
3124 foreach ($subobjectid as $subkey => $subobject) {
3125 if ($subobjecttype ==
'facture') {
3126 $linkedInvoices[] = $subobject;
3134 if (count($linkedInvoices) > 0) {
3135 $sql =
"SELECT rowid as facid, ref, total_ht as total, datef as df, fk_user_author, fk_statut, paye";
3136 $sql .=
" FROM ".MAIN_DB_PREFIX.
"facture";
3137 $sql .=
" WHERE rowid IN (".$this->db->sanitize(implode(
',', $linkedInvoices)).
")";
3139 dol_syslog(get_class($this).
"::InvoiceArrayList", LOG_DEBUG);
3140 $resql = $this->db->query($sql);
3143 $tab_sqlobj = array();
3144 $nump = $this->db->num_rows($resql);
3145 for ($i = 0; $i < $nump; $i++) {
3146 $sqlobj = $this->db->fetch_object($resql);
3147 $tab_sqlobj[] = $sqlobj;
3149 $this->db->free($resql);
3151 $nump = count($tab_sqlobj);
3155 while ($i < $nump) {
3156 $obj = array_shift($tab_sqlobj);
3179 public function delete($user, $notrigger = 0)
3182 require_once DOL_DOCUMENT_ROOT.
'/core/lib/files.lib.php';
3198 if (!$error && !empty($this->table_element_line)) {
3199 $tabletodelete = $this->table_element_line;
3200 $sqlef =
"DELETE FROM ".MAIN_DB_PREFIX.$tabletodelete.
"_extrafields WHERE fk_object IN (SELECT rowid FROM ".MAIN_DB_PREFIX.$tabletodelete.
" WHERE ".$this->fk_element.
" = ".((int) $this->
id).
")";
3201 $sql =
"DELETE FROM ".MAIN_DB_PREFIX.$tabletodelete.
" WHERE ".$this->fk_element.
" = ".((int) $this->
id);
3202 if (!$this->db->query($sqlef) || !$this->db->query($sql)) {
3204 $this->error = $this->db->lasterror();
3205 $this->errors[] = $this->error;
3206 dol_syslog(get_class($this).
"::delete error ".$this->error, LOG_ERR);
3231 dol_syslog(get_class($this).
"::delete error ".$this->error, LOG_ERR);
3237 $sql =
"DELETE FROM ".MAIN_DB_PREFIX.$this->table_element.
" WHERE rowid = ".((int) $this->
id);
3238 $res = $this->db->query($sql);
3241 $this->error = $this->db->lasterror();
3242 $this->errors[] = $this->error;
3243 dol_syslog(get_class($this).
"::delete error ".$this->error, LOG_ERR);
3259 if ($conf->propal->multidir_output[$this->entity] && !empty($this->
ref)) {
3260 $dir =
$conf->propal->multidir_output[$this->entity].
"/".$ref;
3261 $file = $dir.
"/".$ref.
".pdf";
3262 if (file_exists($file)) {
3266 $this->error =
'ErrorFailToDeleteFile';
3267 $this->errors[] = $this->error;
3268 $this->db->rollback();
3272 if (file_exists($dir)) {
3275 $this->error =
'ErrorFailToDeleteDir';
3276 $this->errors[] = $this->error;
3277 $this->db->rollback();
3285 dol_syslog(get_class($this).
"::delete ".$this->
id.
" by ".$user->id, LOG_DEBUG);
3286 $this->db->commit();
3289 $this->db->rollback();
3306 if ($this->
status >= self::STATUS_DRAFT) {
3311 $sql =
'UPDATE '.MAIN_DB_PREFIX.$this->table_element;
3312 $sql .=
' SET fk_availability = '.((int) $availability_id);
3313 $sql .=
' WHERE rowid='.((int) $this->
id);
3315 dol_syslog(__METHOD__.
' availability('.$availability_id.
')', LOG_DEBUG);
3316 $resql = $this->db->query($sql);
3318 $this->errors[] = $this->db->error();
3323 $this->oldcopy = clone $this;
3324 $this->availability_id = $availability_id;
3327 if (!$notrigger && empty($error)) {
3337 $this->db->commit();
3340 foreach ($this->errors as $errmsg) {
3341 dol_syslog(__METHOD__.
' Error: '.$errmsg, LOG_ERR);
3342 $this->error .= ($this->error ?
', '.$errmsg : $errmsg);
3344 $this->db->rollback();
3348 $error_str =
'Propal status do not meet requirement '.$this->status;
3350 $this->error = $error_str;
3351 $this->errors[] = $this->error;
3370 if ($this->
status >= self::STATUS_DRAFT) {
3375 $sql =
'UPDATE '.MAIN_DB_PREFIX.$this->table_element;
3376 $sql .=
' SET fk_input_reason = '.((int) $demand_reason_id);
3377 $sql .=
' WHERE rowid='.((int) $this->
id);
3379 dol_syslog(__METHOD__.
' demand_reason('.$demand_reason_id.
')', LOG_DEBUG);
3380 $resql = $this->db->query($sql);
3382 $this->errors[] = $this->db->error();
3387 $this->oldcopy = clone $this;
3388 $this->demand_reason_id = $demand_reason_id;
3391 if (!$notrigger && empty($error)) {
3401 $this->db->commit();
3404 foreach ($this->errors as $errmsg) {
3405 dol_syslog(__METHOD__.
' Error: '.$errmsg, LOG_ERR);
3406 $this->error .= ($this->error ?
', '.$errmsg : $errmsg);
3408 $this->db->rollback();
3412 $error_str =
'Propal status do not meet requirement '.$this->status;
3414 $this->error = $error_str;
3415 $this->errors[] = $this->error;
3429 $sql =
"SELECT c.rowid, ";
3430 $sql .=
" c.datec, c.date_valid as datev, c.date_signature, c.date_cloture,";
3431 $sql .=
" c.fk_user_author, c.fk_user_valid, c.fk_user_signature, c.fk_user_cloture";
3432 $sql .=
" FROM ".MAIN_DB_PREFIX.$this->table_element.
" as c";
3433 $sql .=
" WHERE c.rowid = ".((int) $id);
3435 $result = $this->db->query($sql);
3438 if ($this->db->num_rows($result)) {
3439 $obj = $this->db->fetch_object($result);
3441 $this->
id = $obj->rowid;
3443 $this->date_creation = $this->db->jdate($obj->datec);
3444 $this->date_validation = $this->db->jdate($obj->datev);
3445 $this->date_signature = $this->db->jdate($obj->date_signature);
3446 $this->date_cloture = $this->db->jdate($obj->date_cloture);
3448 $this->user_creation_id = $obj->fk_user_author;
3449 $this->user_validation_id = $obj->fk_user_valid;
3451 if ($obj->fk_user_signature) {
3452 $user_signature =
new User($this->db);
3453 $user_signature->fetch($obj->fk_user_signature);
3454 $this->user_signature = $user_signature;
3457 $this->user_closing_id = $obj->fk_user_cloture;
3459 $this->db->free($result);
3488 global $hookmanager;
3491 if (empty($this->labelStatus) || empty($this->labelStatusShort)) {
3493 $langs->load(
"propal");
3494 $this->labelStatus[-1] = $langs->transnoentitiesnoconv(
"PropalStatusCanceled");
3495 $this->labelStatus[0] = $langs->transnoentitiesnoconv(
"PropalStatusDraft");
3496 $this->labelStatus[1] = $langs->transnoentitiesnoconv(
"PropalStatusValidated");
3497 $this->labelStatus[2] = $langs->transnoentitiesnoconv(
"PropalStatusSigned");
3498 $this->labelStatus[3] = $langs->transnoentitiesnoconv(
"PropalStatusNotSigned");
3499 $this->labelStatus[4] = $langs->transnoentitiesnoconv(
"PropalStatusBilled");
3500 $this->labelStatusShort[-1] = $langs->transnoentitiesnoconv(
"PropalStatusCanceledShort");
3501 $this->labelStatusShort[0] = $langs->transnoentitiesnoconv(
"PropalStatusDraftShort");
3502 $this->labelStatusShort[1] = $langs->transnoentitiesnoconv(
"PropalStatusValidatedShort");
3503 $this->labelStatusShort[2] = $langs->transnoentitiesnoconv(
"PropalStatusSignedShort");
3504 $this->labelStatusShort[3] = $langs->transnoentitiesnoconv(
"PropalStatusNotSignedShort");
3505 $this->labelStatusShort[4] = $langs->transnoentitiesnoconv(
"PropalStatusBilledShort");
3509 if ($status == self::STATUS_CANCELED) {
3510 $statusType =
'status9';
3511 } elseif ($status == self::STATUS_DRAFT) {
3512 $statusType =
'status0';
3513 } elseif ($status == self::STATUS_VALIDATED) {
3514 $statusType =
'status1';
3515 } elseif ($status == self::STATUS_SIGNED) {
3516 $statusType =
'status4';
3517 } elseif ($status == self::STATUS_NOTSIGNED) {
3518 $statusType =
'status9';
3519 } elseif ($status == self::STATUS_BILLED) {
3520 $statusType =
'status6';
3523 $parameters = array(
'status' => $status,
'mode' => $mode);
3524 $reshook = $hookmanager->executeHooks(
'LibStatut', $parameters, $this);
3527 return $hookmanager->resPrint;
3530 return dolGetStatus($this->labelStatus[$status], $this->labelStatusShort[$status],
'', $statusType, $mode);
3545 global
$conf, $langs;
3547 $sql =
"SELECT p.rowid, p.ref, p.datec as datec, p.fin_validite as datefin, p.total_ht";
3548 $sql .=
" FROM ".MAIN_DB_PREFIX.$this->table_element.
" as p";
3549 $sql .=
" WHERE p.entity IN (".getEntity(
'propal').
")";
3550 if ($mode ==
'opened') {
3551 $sql .=
" AND p.fk_statut = ".self::STATUS_VALIDATED;
3553 if ($mode ==
'signed') {
3554 $sql .=
" AND p.fk_statut = ".self::STATUS_SIGNED;
3558 if (empty($user->socid) && !$user->hasRight(
'societe',
'client',
'voir')) {
3559 $search_sale = $user->id;
3562 if ($search_sale && $search_sale !=
'-1') {
3563 if ($search_sale == -2) {
3564 $sql .=
" AND NOT EXISTS (SELECT sc.fk_soc FROM ".MAIN_DB_PREFIX.
"societe_commerciaux as sc WHERE sc.fk_soc = p.fk_soc)";
3565 } elseif ($search_sale > 0) {
3566 $sql .=
" AND EXISTS (SELECT sc.fk_soc FROM ".MAIN_DB_PREFIX.
"societe_commerciaux as sc WHERE sc.fk_soc = p.fk_soc AND sc.fk_user = ".((int) $search_sale).
")";
3570 $sql .=
" AND p.fk_soc = ".((int) $user->socid);
3573 $resql = $this->db->query($sql);
3575 $langs->load(
"propal");
3580 $label = $labelShort =
'';
3581 if ($mode ==
'opened') {
3582 $delay_warning =
$conf->propal->cloture->warning_delay;
3584 $label = $langs->transnoentitiesnoconv(
"PropalsToClose");
3585 $labelShort = $langs->transnoentitiesnoconv(
"ToAcceptRefuse");
3587 if ($mode ==
'signed') {
3588 $delay_warning =
$conf->propal->facturation->warning_delay;
3590 $label = $langs->trans(
"PropalsToBill");
3591 $labelShort = $langs->trans(
"ToBill");
3595 $response->warning_delay = $delay_warning / 60 / 60 / 24;
3596 $response->label = $label;
3597 $response->labelShort = $labelShort;
3598 $response->url = DOL_URL_ROOT.
'/comm/propal/list.php?search_status='.$status.
'&mainmenu=commercial&leftmenu=propals';
3599 $response->url_late = DOL_URL_ROOT.
'/comm/propal/list.php?search_option=late&mainmenu=commercial&leftmenu=propals&sortfield=p.datep&sortorder=asc';
3603 while ($obj = $this->db->fetch_object($resql)) {
3604 $response->nbtodo++;
3605 $response->total += $obj->total_ht;
3607 if ($mode ==
'opened') {
3608 $datelimit = $this->db->jdate($obj->datefin);
3609 if ($datelimit < ($now - $delay_warning)) {
3610 $response->nbtodolate++;
3619 $this->error = $this->db->error();
3634 global
$conf, $langs;
3639 $sql =
"SELECT rowid";
3640 $sql .=
" FROM ".MAIN_DB_PREFIX.
"product";
3641 $sql .=
" WHERE entity IN (".getEntity(
'product').
")";
3642 $sql .= $this->db->plimit(100);
3644 $resql = $this->db->query($sql);
3646 $num_prods = $this->db->num_rows($resql);
3648 while ($i < $num_prods) {
3650 $row = $this->db->fetch_row($resql);
3651 $prodids[$i] = $row[0];
3657 $this->
ref =
'SPECIMEN';
3658 $this->ref_client =
'NEMICEPS';
3659 $this->specimen = 1;
3661 $this->date = time();
3662 $this->fin_validite = $this->date + 3600 * 24 * 30;
3663 $this->cond_reglement_id = 1;
3664 $this->cond_reglement_code =
'RECEP';
3665 $this->mode_reglement_id = 7;
3666 $this->mode_reglement_code =
'CHQ';
3667 $this->availability_id = 1;
3668 $this->availability_code =
'AV_NOW';
3669 $this->demand_reason_id = 1;
3670 $this->demand_reason_code =
'SRC_00';
3671 $this->note_public =
'This is a comment (public)';
3672 $this->note_private =
'This is a comment (private)';
3674 $this->multicurrency_tx = 1;
3675 $this->multicurrency_code =
$conf->currency;
3680 while ($xnbp < $nbp) {
3682 $line->desc = $langs->trans(
"Description").
" ".$xnbp;
3684 $line->subprice = 100;
3687 $line->localtax1_tx = 0;
3688 $line->localtax2_tx = 0;
3690 $line->total_ht = 50;
3691 $line->total_ttc = 60;
3692 $line->total_tva = 10;
3693 $line->remise_percent = 50;
3695 $line->total_ht = 100;
3696 $line->total_ttc = 120;
3697 $line->total_tva = 20;
3698 $line->remise_percent = 00;
3701 if ($num_prods > 0) {
3702 $prodid = mt_rand(1, $num_prods);
3703 $line->fk_product = $prodids[$prodid];
3704 $line->product_ref =
'SPECIMEN';
3707 $this->lines[$xnbp] = $line;
3709 $this->total_ht += $line->total_ht;
3710 $this->total_tva += $line->total_tva;
3711 $this->total_ttc += $line->total_ttc;
3728 $this->nb = array();
3730 $sql =
"SELECT count(p.rowid) as nb";
3731 $sql .=
" FROM ".MAIN_DB_PREFIX.$this->table_element.
" as p";
3732 $sql .=
" LEFT JOIN ".MAIN_DB_PREFIX.
"societe as s ON p.fk_soc = s.rowid";
3733 $sql .=
" WHERE p.entity IN (".getEntity(
'propal').
")";
3737 if (empty($user->socid) && !$user->hasRight(
'societe',
'client',
'voir')) {
3738 $search_sale = $user->id;
3741 if ($search_sale && $search_sale !=
'-1') {
3742 if ($search_sale == -2) {
3743 $sql .=
" AND NOT EXISTS (SELECT sc.fk_soc FROM ".MAIN_DB_PREFIX.
"societe_commerciaux as sc WHERE sc.fk_soc = p.fk_soc)";
3744 } elseif ($search_sale > 0) {
3745 $sql .=
" AND EXISTS (SELECT sc.fk_soc FROM ".MAIN_DB_PREFIX.
"societe_commerciaux as sc WHERE sc.fk_soc = p.fk_soc AND sc.fk_user = ".((int) $search_sale).
")";
3749 $resql = $this->db->query($sql);
3752 while ($obj = $this->db->fetch_object($resql)) {
3753 $this->nb[
"proposals"] = $obj->nb;
3755 $this->db->free($resql);
3759 $this->error = $this->db->error();
3774 global
$conf, $langs;
3775 $langs->load(
"propal");
3779 if (!empty($classname)) {
3782 $file = $classname.
".php";
3785 $dirmodels = array_merge(array(
'/'), (array)
$conf->modules_parts[
'models']);
3786 foreach ($dirmodels as $reldir) {
3790 $mybool = ((bool) @include_once $dir.$file) || $mybool;
3798 $obj =
new $classname();
3799 '@phan-var-force ModeleNumRefPropales $obj';
3801 $numref = $obj->getNextValue($soc, $this);
3803 if ($numref !=
"") {
3806 $this->error = $obj->error;
3811 $langs->load(
"errors");
3812 print $langs->trans(
"Error").
" ".$langs->trans(
"ErrorModuleSetupNotComplete", $langs->transnoentitiesnoconv(
"Proposal"));
3825 global
$conf, $langs, $user;
3827 $langs->load(
'propal');
3829 $nofetch = !empty($params[
'nofetch']);
3832 return [
'optimize' => $langs->trans(
"Proposal")];
3834 if ($user->hasRight(
'propal',
'lire')) {
3835 $datas[
'picto'] =
img_picto(
'', $this->picto,
'', 0, 0, 0,
'',
'paddingrightonly').
'<u>'.$langs->trans(
"Proposal").
'</u>';
3836 if (isset($this->
status)) {
3837 $datas[
'status'] =
' '.$this->getLibStatut(5);
3839 if (!empty($this->
ref)) {
3840 $datas[
'ref'] =
'<br><b>'.$langs->trans(
'Ref').
':</b> '.$this->ref;
3843 $langs->load(
'companies');
3844 if (empty($this->thirdparty)) {
3847 $datas[
'customer'] =
'<br><b>'.$langs->trans(
'Customer').
':</b> '.$this->thirdparty->getNomUrl(1,
'', 0, 1);
3849 if (!empty($this->ref_customer)) {
3850 $datas[
'refcustomer'] =
'<br><b>'.$langs->trans(
'RefCustomer').
':</b> '.$this->ref_customer;
3853 $langs->load(
'project');
3854 if (is_null($this->project) || (is_object($this->project) && $this->project->isEmpty())) {
3856 if ($res > 0 && $this->project instanceof
Project) {
3857 $datas[
'project'] =
'<br><b>'.$langs->trans(
'Project').
':</b> '.$this->project->getNomUrl(1,
'', 0,
'1');
3861 if (!empty($this->total_ht)) {
3862 $datas[
'amountht'] =
'<br><b>'.$langs->trans(
'AmountHT').
':</b> '.
price($this->total_ht, 0, $langs, 0, -1, -1,
$conf->currency);
3864 if (!empty($this->total_tva)) {
3865 $datas[
'vat'] =
'<br><b>'.$langs->trans(
'VAT').
':</b> '.
price($this->total_tva, 0, $langs, 0, -1, -1,
$conf->currency);
3867 if (!empty($this->total_ttc)) {
3868 $datas[
'amountttc'] =
'<br><b>'.$langs->trans(
'AmountTTC').
':</b> '.
price($this->total_ttc, 0, $langs, 0, -1, -1,
$conf->currency);
3870 if (!empty($this->date)) {
3871 $datas[
'date'] =
'<br><b>'.$langs->trans(
'Date').
':</b> '.
dol_print_date($this->date,
'day');
3873 if (!empty($this->date_signature)) {
3874 $datas[
'datesignature'] =
'<br><b>'.$langs->trans(
'DateSigning').
':</b> '.
dol_print_date($this->date_signature,
'day');
3876 if (!empty($this->delivery_date)) {
3877 $datas[
'deliverydate'] =
'<br><b>'.$langs->trans(
'DeliveryDate').
':</b> '.
dol_print_date($this->delivery_date,
'dayhour');
3895 public function getNomUrl($withpicto = 0, $option =
'', $get_params =
'', $notooltip = 0, $save_lastsearch_value = -1, $addlinktonotes = -1)
3897 global $langs,
$conf, $user, $hookmanager;
3899 if (!empty(
$conf->dol_no_mouse_hover)) {
3906 'objecttype' => $this->element,
3907 'option' => $option,
3910 $classfortooltip =
'classfortooltip';
3913 $classfortooltip =
'classforajaxtooltip';
3914 $dataparams =
' data-params="'.dol_escape_htmltag(json_encode($params)).
'"';
3921 if ($user->hasRight(
'propal',
'lire')) {
3922 if ($option ==
'') {
3923 $url = DOL_URL_ROOT.
'/comm/propal/card.php?id='.$this->
id.$get_params;
3924 } elseif ($option ==
'compta') {
3925 $url = DOL_URL_ROOT.
'/comm/propal/card.php?id='.$this->
id.$get_params;
3926 } elseif ($option ==
'expedition') {
3927 $url = DOL_URL_ROOT.
'/expedition/propal.php?id='.$this->
id.$get_params;
3928 } elseif ($option ==
'document') {
3929 $url = DOL_URL_ROOT.
'/comm/propal/document.php?id='.$this->
id.$get_params;
3932 if ($option !=
'nolink') {
3934 $add_save_lastsearch_values = ($save_lastsearch_value == 1 ? 1 : 0);
3935 if ($save_lastsearch_value == -1 && isset($_SERVER[
"PHP_SELF"]) && preg_match(
'/list\.php/', $_SERVER[
"PHP_SELF"])) {
3936 $add_save_lastsearch_values = 1;
3938 if ($add_save_lastsearch_values) {
3939 $url .=
'&save_lastsearch_values=1';
3945 if (empty($notooltip) && $user->hasRight(
'propal',
'lire')) {
3947 $label = $langs->trans(
"Proposal");
3948 $linkclose .=
' alt="'.dolPrintHTMLForAttribute($label).
'"';
3950 $linkclose .= ($label ?
' title="'.dolPrintHTMLForAttribute($label).
'"' :
' title="tocomplete"');
3951 $linkclose .= $dataparams.
' class="'.$classfortooltip.
'"';
3954 $linkstart =
'<a href="'.$url.
'"';
3955 $linkstart .= $linkclose.
'>';
3958 $result .= $linkstart;
3960 $result .=
img_object(($notooltip ?
'' : $label), ($this->picto ? $this->picto :
'generic'), (($withpicto != 2) ?
'class="paddingright"' :
''), 0, 0, $notooltip ? 0 : 1);
3962 if ($withpicto != 2) {
3963 $result .= $this->ref;
3965 $result .= $linkend;
3967 if ($addlinktonotes >= 0) {
3970 if ($addlinktonotes == 0) {
3971 if (!empty($this->note_private) || !empty($this->note_public)) {
3972 $txttoshow = $langs->trans(
'ViewPrivateNote');
3974 } elseif ($addlinktonotes == 1) {
3975 if (!empty($this->note_private)) {
3978 } elseif ($addlinktonotes == 2) {
3979 if (!empty($this->note_public)) {
3982 } elseif ($addlinktonotes == 3) {
3983 if ($user->socid > 0) {
3984 if (!empty($this->note_public)) {
3988 if (!empty($this->note_public)) {
3991 if (!empty($this->note_private)) {
3992 if (!empty($txttoshow)) {
3993 $txttoshow .=
'<br><br>';
4001 $result .=
' <span class="note inline-block">';
4002 $result .=
'<a href="'.DOL_URL_ROOT.
'/comm/propal/note.php?id='.$this->
id.
'" class="classfortooltip" title="'.
dol_escape_htmltag($txttoshow).
'">';
4005 $result .=
'</span>';
4010 $hookmanager->initHooks(array($this->element .
'dao'));
4011 $parameters = array(
'id' => $this->
id,
'getnomurl' => &$result);
4012 $reshook = $hookmanager->executeHooks(
'getNomUrl', $parameters, $this, $action);
4014 $result = $hookmanager->resPrint;
4016 $result .= $hookmanager->resPrint;
4029 return $this->
fetch_lines(0, 0, $sqlforgedfilters);
4043 public function generateDocument($modele, $outputlangs, $hidedetails = 0, $hidedesc = 0, $hideref = 0, $moreparams =
null)
4045 $outputlangs->loadLangs(array(
"propale",
"products"));
4050 if ($this->model_pdf) {
4051 $modele = $this->model_pdf;
4057 $modelpath =
"core/modules/propale/doc/";
4059 return $this->
commonGenerateDocument($modelpath, $modele, $outputlangs, $hidedetails, $hidedesc, $hideref, $moreparams);
4107 $selected = (empty($arraydata[
'selected']) ? 0 : $arraydata[
'selected']);
4109 $return =
'<div class="box-flex-item box-flex-grow-zero">';
4110 $return .=
'<div class="info-box info-box-sm">';
4111 $return .=
'<div class="info-box-icon bg-infobox-action">';
4113 $return .=
'</div>';
4114 $return .=
'<div class="info-box-content">';
4115 $return .=
'<span class="info-box-ref inline-block tdoverflowmax150 valignmiddle">'.(method_exists($this,
'getNomUrl') ? $this->
getNomUrl() : $this->ref).
'</span>';
4116 if ($selected >= 0) {
4117 $return .=
'<input id="cb'.$this->id.
'" class="flat checkforselect fright" type="checkbox" name="toselect[]" value="'.$this->
id.
'"'.($selected ?
' checked="checked"' :
'').
'>';
4119 if (!empty($arraydata[
'projectlink'])) {
4120 $return .=
'<span class="info-box-ref"> | '.$arraydata[
'projectlink'].
'</span>';
4123 if (property_exists($this,
'thirdparty') && is_object($this->thirdparty)) {
4124 $return .=
'<div class="info-box-ref tdoverflowmax150">'.$this->thirdparty->getNomUrl(1).
'</div>';
4126 if (property_exists($this,
'total_ht')) {
4127 $return .=
'<span class="info-box-label amount" title="'.$langs->trans(
"AmountHT").
'">'.
price($this->total_ht).
'</span>';
4129 if (!empty($arraydata[
'authorlink'])) {
4130 $return .=
' <span class="info-box-label">'.$arraydata[
'authorlink'].
'</span>';
4132 if (method_exists($this,
'getLibStatut')) {
4133 $return .=
'<br><div class="info-box-status">'.$this->getLibStatut(3).
'</div>';
4135 $return .=
'</div>';
4136 $return .=
'</div>';
4137 $return .=
'</div>';
if( $user->socid > 0) if(! $user->hasRight('accounting', 'chartofaccount')) $object
Parent class of all other business classes (invoices, contracts, proposals, orders,...
fetch_optionals($rowid=null, $optionsArray=null)
Function to get extra fields of an object into $this->array_options This method is in most cases call...
line_order($renum=false, $rowidorder='ASC', $fk_parent_line=true)
Save a new position (field rang) for details lines.
deleteEcmFiles($mode=0)
Delete related files of object in database.
update_price($exclspec=0, $roundingadjust='auto', $nodatabaseupdate=0, $seller=null)
Update total_ht, total_ttc, total_vat, total_localtax1, total_localtax2 for an object (sum of lines).
add_object_linked($origin=null, $origin_id=null, $f_user=null, $notrigger=0)
Add an object link into llx_element_element.
commonGenerateDocument($modelspath, $modele, $outputlangs, $hidedetails, $hidedesc, $hideref, $moreparams=null)
Common function for all objects extending CommonObject for generating documents.
fetchProject()
Load the project with id $this->fk_project into this->project.
fetch_thirdparty($force_thirdparty_id=0)
Load the third party of object, from id $this->socid or $this->fk_soc, into this->thirdparty.
deleteObjectLinked($sourceid=null, $sourcetype='', $targetid=null, $targettype='', $rowid=0, $f_user=null, $notrigger=0)
Delete all links between an object $this.
setErrorsFromObject($object)
setErrorsFromObject
static isExistingObject($element, $id, $ref='', $ref_ext='')
Check if an object id or ref exists If you don't need or want to instantiate the object and just need...
updateRangOfLine($rowid, $rang)
Update position of line (rang)
deleteExtraFields()
Delete all extra fields values for the current object.
fetchObjectLinked($sourceid=null, $sourcetype='', $targetid=null, $targettype='', $clause='OR', $alsosametype=1, $orderby='sourcetype', $loadalsoobjects=1)
Fetch array of objects linked to current object (object of enabled modules only).
static commonReplaceThirdparty(DoliDB $dbs, $origin_id, $dest_id, array $tables, $ignoreerrors=0)
Function used to replace a thirdparty id with another one.
static commonReplaceProduct(DoliDB $dbs, $origin_id, $dest_id, array $tables, $ignoreerrors=0)
Function used to replace a product id with another one.
line_max($fk_parent_line=0)
Get max value used for position of line (rang)
insertExtraFields($trigger='', $userused=null)
Add/Update all extra fields values for the current object.
delete_linked_contact($source='', $code='')
Delete all links between an object $this and all its contacts in llx_element_contact.
call_trigger($triggerName, $user)
Call trigger based on this instance.
Class to manage absolute discounts.
Class to manage Dolibarr database access.
static getIdAndTxFromCode($dbs, $code, $date_document=0)
Get id and rate of currency from code.
static getIdFromCode($dbs, $code)
Get id of currency from code.
File of class to manage predefined price products or services by customer.
Class to manage predefined suppliers products.
Class to manage products or services.
Class to manage projects.
Class to manage proposals.
getTooltipContentArray($params)
getTooltipContentArray
const STATUS_DRAFT
Draft status.
set_date($user, $date, $notrigger=0)
Define proposal date.
const STATUS_SIGNED
Signed quote.
getNomUrl($withpicto=0, $option='', $get_params='', $notooltip=0, $save_lastsearch_value=-1, $addlinktonotes=-1)
Return clickable link of object (with eventually picto)
getKanbanView($option='', $arraydata=null)
Return clickable link of object (with eventually picto)
InvoiceArrayList($id)
Returns an array with id and ref of related invoices.
availability($availability_id, $notrigger=0)
Change the delivery time.
const STATUS_NOTSIGNED
Not signed quote.
setDeliveryDate($user, $delivery_date, $notrigger=0)
Set delivery date.
classifyBilled(User $user, $notrigger=0, $note='')
Classify the proposal to status Billed.
getLinesArray($sqlforgedfilters='')
Retrieve an array of proposal lines.
fetch($rowid, $ref='', $ref_ext='', $forceentity=0)
Load a proposal from database.
set_availability($user, $id, $notrigger=0)
Set delivery.
fetch_lines($only_product=0, $loadalsotranslation=0, $sqlforgedfilters='')
Load array lines.
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_options=array(), $fk_unit=null, $pu_ht_devise=0, $notrigger=0, $rang=0)
Update a proposal line.
update(User $user, $notrigger=0)
Update database.
addline( $desc, $pu_ht, $qty, $txtva, $txlocaltax1=0.0, $txlocaltax2=0.0, $fk_product=0, $remise_percent=0.0, $price_base_type='HT', $pu_ttc=0.0, $info_bits=0, $type=0, $rang=-1, $special_code=0, $fk_parent_line=0, $fk_fournprice=0, $pa_ht=0, $label='', $date_start='', $date_end='', $array_options=array(), $fk_unit=null, $origin='', $origin_id=0, $pu_ht_devise=0, $fk_remise_except=0, $noupdateafterinsertline=0)
Add a proposal line into database (linked to product/service or not) The parameters are already suppo...
closeProposal($user, $status, $note_private='', $notrigger=0, $note_public='')
Close/set the commercial proposal to status signed or refused (fill also date signature)
demand_reason($demand_reason_id, $notrigger=0)
Change source demand.
info($id)
Object Proposal Information.
const STATUS_BILLED
Billed or processed quote.
static replaceThirdparty(DoliDB $dbs, $origin_id, $dest_id)
Function used to replace a thirdparty id with another one.
getLibStatut($mode=0)
Return label of status of proposal (draft, validated, ...)
const STATUS_CANCELED
Canceled status.
insert_discount($idremise)
Add a discount line into an proposal (as a proposal line) using an existing absolute discount (Consum...
getNextNumRef($soc)
Returns the reference to the following non used Proposal used depending on the active numbering modul...
LibStatut($status, $mode=1)
Return label of a status (draft, validated, ...)
valid($user, $notrigger=0)
Set status to validated.
static replaceProduct(DoliDB $db, $origin_id, $dest_id)
Function used to replace a product id with another one.
set_ref_client($user, $ref_client, $notrigger=0)
Set customer reference number.
setDraft($user, $notrigger=0)
Set draft status.
set_echeance($user, $date_end_validity, $notrigger=0)
Define end validity date.
set_demand_reason($user, $id, $notrigger=0)
Set source of demand.
generateDocument($modele, $outputlangs, $hidedetails=0, $hidedesc=0, $hideref=0, $moreparams=null)
Create a document onto disk according to template module.
create($user, $notrigger=0)
Create commercial proposal into database this->ref can be set or empty.
liste_array($shortlist=0, $draft=0, $notcurrentuser=0, $socid=0, $limit=0, $offset=0, $sortfield='p.datep', $sortorder='DESC')
Return list of proposal (eventually filtered on user) into an array.
add_product($idproduct, $qty, $remise_percent=0)
Add line into array ->lines $this->thirdparty should be loaded.
initAsSpecimen()
Initialise an instance with random values.
reopen($user, $status, $note='', $notrigger=0)
Reopen the commercial proposal.
deleteLine($lineid, $id=0)
Delete detail line.
__construct($db, $socid=0, $propalid=0)
Constructor.
load_board($user, $mode)
Load indicators for dashboard (this->nbtodo and this->nbtodolate)
setCancel(User $user)
Cancel the proposal.
getInvoiceArrayList()
Returns an array with the numbers of related invoices.
set_date_livraison($user, $delivery_date, $notrigger=0)
Set delivery date.
const STATUS_VALIDATED
Validated status.
loadStateBoard()
Load the indicators this->nb for the state board.
createFromClone(User $user, $socid=0, $forceentity=null, $update_prices=false, $update_desc=false)
Load an object from its id and create a new one in database.
Class to manage commercial proposal lines.
Class to manage third parties objects (customers, suppliers, prospects...)
Class to manage translations.
Class to manage Dolibarr users.
print $langs trans("Ref").' m titre as m m statut as status
Or an array listing all the potential status of the object: array: int of the status => translated la...
dol_delete_file($file, $disableglob=0, $nophperrors=0, $nohook=0, $object=null, $allowdotdot=false, $indexdatabase=1, $nolog=0)
Remove a file or several files with a mask.
dol_delete_dir_recursive($dir, $count=0, $nophperrors=0, $onlysub=0, &$countdeleted=0, $indexdatabase=1, $nolog=0, $level=0)
Remove a directory $dir and its subdirectories (or only files and subdirectories)
dol_dir_list($utf8_path, $types="all", $recursive=0, $filter="", $excludefilter=null, $sortcriteria="name", $sortorder=SORT_ASC, $mode=0, $nohook=0, $relativename="", $donotfollowsymlinks=0, $nbsecondsold=0)
Scan a directory and return a list of files/directories.
dol_delete_preview($object)
Delete all preview files linked to object instance.
setEventMessages($mesg, $mesgs, $style='mesgs', $messagekey='', $noduplicate=0, $attop=0)
Set event messages in dol_events session object.
setEntity($currentobject)
Set entity id to use when to create an object.
img_picto($titlealt, $picto, $moreatt='', $pictoisfullpath=0, $srconly=0, $notitle=0, $alt='', $morecss='', $marginleftonlyshort=2, $allowothertags=array())
Show picto whatever it's its name (generic function)
GETPOSTINT($paramname, $method=0)
Return the value of a $_GET or $_POST supervariable, converted into integer.
dol_string_nohtmltag($stringtoclean, $removelinefeed=1, $pagecodeto='UTF-8', $strip_tags=0, $removedoublespaces=1)
Clean a string from all HTML tags and entities.
price2num($amount, $rounding='', $option=0)
Function that return a number with universal decimal format (decimal separator is '.
isDolTms($timestamp)
isDolTms check if a timestamp is valid.
img_object($titlealt, $picto, $moreatt='', $pictoisfullpath=0, $srconly=0, $notitle=0, $allowothertags=array())
Show a picto called object_picto (generic function)
setEventMessage($mesgs, $style='mesgs', $noduplicate=0, $attop=0)
Set event message in dol_events session object.
dol_strlen($string, $stringencoding='UTF-8')
Make a strlen call.
price($amount, $form=0, $outlangs='', $trunc=1, $rounding=-1, $forcerounding=-1, $currency_code='')
Function to format a value into an amount for visual output Function used into PDF and HTML pages.
dol_now($mode='auto')
Return date for now.
getDolGlobalInt($key, $default=0)
Return a Dolibarr global constant int value.
getLocalTaxesFromRate($vatrate, $local, $buyer, $seller, $firstparamisid=0)
Get type and rate of localtaxes for a particular vat rate/country of a thirdparty.
dol_print_date($time, $format='', $tzoutput='auto', $outputlangs=null, $encodetooutput=false)
Output date in a string format according to outputlangs (or langs if not defined).
if(!function_exists( 'dol_getprefix')) dol_include_once($relpath, $classname='')
Make an include_once using default root and alternate root if it fails.
get_default_npr(Societe $thirdparty_seller, Societe $thirdparty_buyer, $idprod=0, $idprodfournprice=0)
Function that returns whether VAT must be recoverable collected VAT (e.g.: VAT NPR in France)
dol_concatdesc($text1, $text2, $forxml=false, $invert=false)
Concat 2 descriptions with a new line between them (second operand after first one with appropriate n...
dolGetStatus($statusLabel='', $statusLabelShort='', $html='', $statusType='status0', $displayMode=0, $url='', $params=array())
Output the badge of a status.
GETPOST($paramname, $check='alphanohtml', $method=0, $filter=null, $options=null, $noreplace=0)
Return value of a param into GET or POST supervariable.
dol_buildpath($path, $type=0, $returnemptyifnotfound=0)
Return path of url or filesystem.
dol_print_error($db=null, $error='', $errors=null)
Displays error message system with all the information to facilitate the diagnosis and the escalation...
dol_sanitizeFileName($str, $newstr='_', $unaccent=1, $includequotes=0)
Clean a string to use it as a file name.
getDolGlobalString($key, $default='')
Return a Dolibarr global constant string value.
get_default_tva(Societe $thirdparty_seller, Societe $thirdparty_buyer, $idprod=0, $idprodfournprice=0)
Function that return vat rate of a product line (according to seller, buyer and product vat rate) VAT...
get_localtax($vatrate, $local, $thirdparty_buyer=null, $thirdparty_seller=null, $vatnpr=0)
Return localtax rate for a particular vat, when selling a product with vat $vatrate,...
dol_syslog($message, $level=LOG_INFO, $ident=0, $suffixinfilename='', $restricttologhandler='', $logcontext=null)
Write log message into outputs.
getEntity($element, $shared=1, $currentobject=null)
Get list of entity id to use.
dol_escape_htmltag($stringtoescape, $keepb=0, $keepn=0, $noescapetags='', $escapeonlyhtmltags=0, $cleanalsojavascript=0)
Returns text escaped for inclusion in HTML alt or title or value tags, or into values of HTML input f...
getMarginInfos($pv_ht, $remise_percent, $tva_tx, $localtax1_tx, $localtax2_tx, $fk_pa, $pa_ht)
Return an array with margins information of a line.
global $conf
The following vars must be defined: $type2label $form $conf, $lang, The following vars may also be de...
calcul_price_total($qty, $pu, $remise_percent_ligne, $txtva, $uselocaltax1_rate, $uselocaltax2_rate, $remise_percent_global, $price_base_type, $info_bits, $type, $seller=null, $localtaxes_array=[], $progress=100, $multicurrency_tx=1, $pu_devise=0, $multicurrency_code='')
Calculate totals (net, vat, ...) of a line.