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';
68 public $element =
'propal';
73 public $table_element =
'propal';
78 public $table_element_line =
'propaldet';
83 public $fk_element =
'fk_propal';
88 public $picto =
'propal';
94 public $TRIGGER_PREFIX =
'PROPAL';
100 public $restrictiononfksoc = 1;
131 public $ref_customer;
165 public $date_validation;
170 public $date_signature;
175 public $user_signature;
192 public $delivery_date;
198 public $fin_validite;
203 public $user_author_id;
234 public $cond_reglement_code;
239 public $cond_reglement;
244 public $cond_reglement_doc;
249 public $mode_reglement_code;
254 public $mode_reglement;
261 public $deposit_percent;
273 public $address_type;
284 public $availability_id;
291 public $fk_availability;
296 public $availability_code;
301 public $availability;
306 public $duree_validite;
311 public $demand_reason_id;
316 public $demand_reason_code;
321 public $demand_reason;
326 public $warehouse_id;
331 public $lines = array();
338 public $labelStatus = array();
339 public $labelStatusShort = array();
370 public $fields = array(
371 'rowid' => array(
'type' =>
'integer',
'label' =>
'TechnicalID',
'enabled' => 1,
'visible' => -1,
'notnull' => 1,
'position' => 10),
372 'entity' => array(
'type' =>
'integer',
'label' =>
'Entity',
'default' =>
'1',
'enabled' => 1,
'visible' => -2,
'notnull' => 1,
'position' => 15,
'index' => 1),
373 'ref' => array(
'type' =>
'varchar(30)',
'label' =>
'Ref',
'enabled' => 1,
'visible' => -1,
'notnull' => 1,
'showoncombobox' => 1,
'position' => 20),
374 'ref_client' => array(
'type' =>
'varchar(255)',
'label' =>
'RefCustomer',
'enabled' => 1,
'visible' => -1,
'position' => 22),
375 'ref_ext' => array(
'type' =>
'varchar(255)',
'label' =>
'RefExt',
'enabled' => 1,
'visible' => 0,
'position' => 40),
376 'fk_soc' => array(
'type' =>
'integer:Societe:societe/class/societe.class.php',
'label' =>
'ThirdParty',
'enabled' =>
'isModEnabled("societe")',
'visible' => -1,
'position' => 23),
377 '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),
378 'tms' => array(
'type' =>
'timestamp',
'label' =>
'DateModification',
'enabled' => 1,
'visible' => -1,
'notnull' => 1,
'position' => 25),
379 'datec' => array(
'type' =>
'datetime',
'label' =>
'DateCreation',
'enabled' => 1,
'visible' => -1,
'position' => 55),
380 'datep' => array(
'type' =>
'date',
'label' =>
'Date',
'enabled' => 1,
'visible' => -1,
'position' => 60),
381 'fin_validite' => array(
'type' =>
'datetime',
'label' =>
'DateEnd',
'enabled' => 1,
'visible' => -1,
'position' => 65),
382 'date_valid' => array(
'type' =>
'datetime',
'label' =>
'DateValidation',
'enabled' => 1,
'visible' => -1,
'position' => 70),
383 'date_cloture' => array(
'type' =>
'datetime',
'label' =>
'DateClosing',
'enabled' => 1,
'visible' => -1,
'position' => 75),
384 'fk_user_author' => array(
'type' =>
'integer:User:user/class/user.class.php',
'label' =>
'UserAuthor',
'enabled' => 1,
'visible' => -1,
'position' => 80),
385 'fk_user_modif' => array(
'type' =>
'integer:User:user/class/user.class.php',
'label' =>
'UserModif',
'enabled' => 1,
'visible' => -2,
'notnull' => -1,
'position' => 85),
386 'fk_user_valid' => array(
'type' =>
'integer:User:user/class/user.class.php',
'label' =>
'UserValidation',
'enabled' => 1,
'visible' => -1,
'position' => 90),
387 'fk_user_cloture' => array(
'type' =>
'integer:User:user/class/user.class.php',
'label' =>
'UserClosing',
'enabled' => 1,
'visible' => -1,
'position' => 95),
388 'price' => array(
'type' =>
'double',
'label' =>
'Price',
'enabled' => 1,
'visible' => -1,
'position' => 105),
389 'total_ht' => array(
'type' =>
'double(24,8)',
'label' =>
'TotalHT',
'enabled' => 1,
'visible' => -1,
'position' => 125,
'isameasure' => 1),
390 'total_tva' => array(
'type' =>
'double(24,8)',
'label' =>
'VAT',
'enabled' => 1,
'visible' => -1,
'position' => 130,
'isameasure' => 1),
391 'localtax1' => array(
'type' =>
'double(24,8)',
'label' =>
'LocalTax1',
'enabled' => 1,
'visible' => -1,
'position' => 135,
'isameasure' => 1),
392 'localtax2' => array(
'type' =>
'double(24,8)',
'label' =>
'LocalTax2',
'enabled' => 1,
'visible' => -1,
'position' => 140,
'isameasure' => 1),
393 'total_ttc' => array(
'type' =>
'double(24,8)',
'label' =>
'TotalTTC',
'enabled' => 1,
'visible' => -1,
'position' => 145,
'isameasure' => 1),
394 'fk_account' => array(
'type' =>
'integer',
'label' =>
'BankAccount',
'enabled' =>
'isModEnabled("bank")',
'visible' => -1,
'position' => 150),
395 'fk_currency' => array(
'type' =>
'varchar(3)',
'label' =>
'Currency',
'enabled' => 1,
'visible' => -1,
'position' => 155),
396 'fk_cond_reglement' => array(
'type' =>
'integer',
'label' =>
'PaymentTerm',
'enabled' => 1,
'visible' => -1,
'position' => 160),
397 'deposit_percent' => array(
'type' =>
'varchar(63)',
'label' =>
'DepositPercent',
'enabled' => 1,
'visible' => -1,
'position' => 161),
398 'fk_mode_reglement' => array(
'type' =>
'integer',
'label' =>
'PaymentMode',
'enabled' => 1,
'visible' => -1,
'position' => 165),
399 'note_private' => array(
'type' =>
'html',
'label' =>
'NotePrivate',
'enabled' => 1,
'visible' => 0,
'position' => 170),
400 'note_public' => array(
'type' =>
'html',
'label' =>
'NotePublic',
'enabled' => 1,
'visible' => 0,
'position' => 175),
401 'model_pdf' => array(
'type' =>
'varchar(255)',
'label' =>
'PDFTemplate',
'enabled' => 1,
'visible' => 0,
'position' => 180),
402 'date_livraison' => array(
'type' =>
'date',
'label' =>
'DateDeliveryPlanned',
'enabled' => 1,
'visible' => -1,
'position' => 185),
403 'fk_shipping_method' => array(
'type' =>
'integer',
'label' =>
'ShippingMethod',
'enabled' => 1,
'visible' => -1,
'position' => 190),
404 'fk_warehouse' => array(
'type' =>
'integer:Entrepot:product/stock/class/entrepot.class.php',
'label' =>
'Fk warehouse',
'enabled' =>
'isModEnabled("stock")',
'visible' => -1,
'position' => 191),
405 'fk_availability' => array(
'type' =>
'integer',
'label' =>
'Availability',
'enabled' => 1,
'visible' => -1,
'position' => 195),
406 'fk_delivery_address' => array(
'type' =>
'integer',
'label' =>
'DeliveryAddress',
'enabled' => 1,
'visible' => 0,
'position' => 200),
407 'fk_input_reason' => array(
'type' =>
'integer',
'label' =>
'InputReason',
'enabled' => 1,
'visible' => -1,
'position' => 205),
408 'extraparams' => array(
'type' =>
'varchar(255)',
'label' =>
'Extraparams',
'enabled' => 1,
'visible' => -1,
'position' => 215),
409 'fk_incoterms' => array(
'type' =>
'integer',
'label' =>
'IncotermCode',
'enabled' =>
'isModEnabled("incoterm")',
'visible' => -1,
'position' => 220),
410 'location_incoterms' => array(
'type' =>
'varchar(255)',
'label' =>
'IncotermLabel',
'enabled' =>
'isModEnabled("incoterm")',
'visible' => -1,
'position' => 225),
411 'fk_multicurrency' => array(
'type' =>
'integer',
'label' =>
'MulticurrencyID',
'enabled' => 1,
'visible' => -1,
'position' => 230),
412 'multicurrency_code' => array(
'type' =>
'varchar(255)',
'label' =>
'MulticurrencyCurrency',
'enabled' =>
'isModEnabled("multicurrency")',
'visible' => -1,
'position' => 235),
413 'multicurrency_tx' => array(
'type' =>
'double(24,8)',
'label' =>
'MulticurrencyRate',
'enabled' =>
'isModEnabled("multicurrency")',
'visible' => -1,
'position' => 240,
'isameasure' => 1),
414 'multicurrency_total_ht' => array(
'type' =>
'double(24,8)',
'label' =>
'MulticurrencyAmountHT',
'enabled' =>
'isModEnabled("multicurrency")',
'visible' => -1,
'position' => 245,
'isameasure' => 1),
415 'multicurrency_total_tva' => array(
'type' =>
'double(24,8)',
'label' =>
'MulticurrencyAmountVAT',
'enabled' =>
'isModEnabled("multicurrency")',
'visible' => -1,
'position' => 250,
'isameasure' => 1),
416 'multicurrency_total_ttc' => array(
'type' =>
'double(24,8)',
'label' =>
'MulticurrencyAmountTTC',
'enabled' =>
'isModEnabled("multicurrency")',
'visible' => -1,
'position' => 255,
'isameasure' => 1),
417 'last_main_doc' => array(
'type' =>
'varchar(255)',
'label' =>
'LastMainDoc',
'enabled' => 1,
'visible' => -1,
'position' => 260),
418 'fk_statut' => array(
'type' =>
'smallint(6)',
'label' =>
'Status',
'enabled' => 1,
'visible' => -1,
'notnull' => 1,
'position' => 500),
419 'import_key' => array(
'type' =>
'varchar(14)',
'label' =>
'ImportId',
'enabled' => 1,
'visible' => -2,
'position' => 900),
460 $this->ismultientitymanaged = 1;
461 $this->socid = $socid;
462 $this->
id = $propalid;
466 $this->fields[
'ref_ext'][
'visible'] =
getDolGlobalInt(
'MAIN_LIST_SHOW_REF_EXT');
482 public function add_product($idproduct, $qty, $remise_percent = 0)
491 dol_syslog(get_class($this).
"::add_product $idproduct, $qty, $remise_percent");
492 if ($idproduct > 0) {
493 $prod =
new Product($this->db);
494 $prod->fetch($idproduct);
496 $productdesc = $prod->description;
500 if (empty($tva_tx)) {
510 $price = $prod->multiprices[$this->thirdparty->price_level];
512 $price = $prod->price;
517 $line->fk_product = $idproduct;
518 $line->desc = $productdesc;
520 $line->subprice = $price;
521 $line->remise_percent = $remise_percent;
522 $line->vat_src_code = $vat_src_code;
523 $line->tva_tx = $tva_tx;
524 $line->fk_unit = $prod->fk_unit;
526 $line->info_bits = 1;
529 $this->lines[] = $line;
547 include_once DOL_DOCUMENT_ROOT.
'/core/lib/price.lib.php';
548 include_once DOL_DOCUMENT_ROOT.
'/core/class/discount.class.php';
553 $result = $remise->fetch($idremise);
556 if ($remise->fk_facture) {
557 $this->error = $langs->trans(
"ErrorDiscountAlreadyUsed");
558 $this->db->rollback();
564 $line->context = $this->context;
566 $line->fk_propal = $this->id;
567 $line->fk_remise_except = $remise->id;
568 $line->desc = $remise->description;
569 $line->vat_src_code = $remise->vat_src_code;
570 $line->tva_tx = $remise->tva_tx;
571 $line->subprice = -(float) $remise->amount_ht;
572 $line->fk_product = 0;
574 $line->remise_percent = 0;
576 $line->info_bits = 2;
578 $line->total_ht = -(float) $remise->amount_ht;
579 $line->total_tva = -(float) $remise->amount_tva;
580 $line->total_ttc = -(float) $remise->amount_ttc;
582 $result = $line->insert();
589 $this->db->rollback();
594 $this->db->rollback();
598 $this->db->rollback();
648 $remise_percent = 0.0,
649 $price_base_type =
'HT',
661 $array_options = array(),
666 $fk_remise_except = 0,
667 $noupdateafterinsertline = 0
671 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);
673 if ($this->
status == self::STATUS_DRAFT) {
674 include_once DOL_DOCUMENT_ROOT.
'/core/lib/price.lib.php';
677 if (empty($remise_percent)) {
683 if (empty($info_bits)) {
689 if (empty($fk_parent_line) || $fk_parent_line < 0) {
693 $remise_percent =
price2num($remise_percent);
696 $pu_ht_devise =
price2num($pu_ht_devise);
698 if (!preg_match(
'/\((.*)\)/', (
string) $txtva)) {
704 if ($price_base_type ==
'HT') {
715 if ($date_start && $date_end && $date_start > $date_end) {
716 $langs->load(
"errors");
717 $this->error = $langs->trans(
'ErrorStartDateGreaterEnd');
723 $product_type = $type;
724 if (!empty($fk_product) && $fk_product > 0) {
725 $product =
new Product($this->db);
726 $result = $product->fetch($fk_product);
727 $product_type = $product->type;
729 if ($product->isStockManaged() && $product->stock_reel < $qty &&
getDolGlobalString(
'STOCK_MUST_BE_ENOUGH_FOR_PROPOSAL')) {
730 $langs->load(
"errors");
731 $this->error = $langs->trans(
'ErrorStockIsNotEnoughToAddProductOnProposal', $product->ref);
732 $this->db->rollback();
745 $tmpproduct =
new Product($this->db);
746 $result = $tmpproduct->fetch($fk_product);
748 if ($newqty != $qty) {
750 setEventMessages($langs->trans(
'QtyRecalculatedWithPackaging'),
null,
'warnings');
757 if (preg_match(
'/\((.*)\)/', $txtva, $reg)) {
758 $vat_src_code = $reg[1];
759 $txtva = preg_replace(
'/\s*\(.*\)/',
'', $txtva);
762 $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);
764 $total_ht = $tabprice[0];
765 $total_tva = $tabprice[1];
766 $total_ttc = $tabprice[2];
767 $total_localtax1 = $tabprice[9];
768 $total_localtax2 = $tabprice[10];
769 $pu_ht = $tabprice[3];
770 $pu_tva = $tabprice[4];
771 $pu_ttc = $tabprice[5];
774 $multicurrency_total_ht = $tabprice[16];
775 $multicurrency_total_tva = $tabprice[17];
776 $multicurrency_total_ttc = $tabprice[18];
777 $pu_ht_devise = $tabprice[19];
781 if (empty($ranktouse) || $ranktouse == -1) {
782 $rangmax = $this->
line_max($fk_parent_line);
783 $ranktouse = $rangmax + 1;
789 $this->line->context = $this->context;
791 $this->line->fk_propal = $this->id;
792 $this->line->label = $label;
793 $this->line->desc = $desc;
794 $this->line->qty = (float) $qty;
796 $this->line->vat_src_code = $vat_src_code;
797 $this->line->tva_tx = $txtva;
798 $this->line->localtax1_tx = ($total_localtax1 ? $localtaxes_type[1] : 0);
799 $this->line->localtax2_tx = ($total_localtax2 ? $localtaxes_type[3] : 0);
800 $this->line->localtax1_type = empty($localtaxes_type[0]) ?
'' : $localtaxes_type[0];
801 $this->line->localtax2_type = empty($localtaxes_type[2]) ?
'' : $localtaxes_type[2];
802 $this->line->fk_product = $fk_product;
803 $this->line->product_type = $type;
804 $this->line->fk_remise_except = $fk_remise_except;
805 $this->line->remise_percent = $remise_percent;
806 $this->line->subprice = (float) $pu_ht;
807 $this->line->rang = $ranktouse;
808 $this->line->info_bits = $info_bits;
809 $this->line->total_ht = (float) $total_ht;
810 $this->line->total_tva = (float) $total_tva;
811 $this->line->total_localtax1 = (float) $total_localtax1;
812 $this->line->total_localtax2 = (float) $total_localtax2;
813 $this->line->total_ttc = (float) $total_ttc;
814 $this->line->special_code = $special_code;
815 $this->line->fk_parent_line = $fk_parent_line;
816 $this->line->fk_unit = $fk_unit;
818 $this->line->date_start = $date_start;
819 $this->line->date_end = $date_end;
821 $this->line->fk_fournprice = $fk_fournprice;
822 $this->line->pa_ht = $pa_ht;
824 $this->line->origin_id = $origin_id;
825 $this->line->origin = $origin;
828 $this->line->fk_multicurrency = $this->fk_multicurrency;
829 $this->line->multicurrency_code = $this->multicurrency_code;
830 $this->line->multicurrency_subprice = (float) $pu_ht_devise;
831 $this->line->multicurrency_total_ht = (float) $multicurrency_total_ht;
832 $this->line->multicurrency_total_tva = (float) $multicurrency_total_tva;
833 $this->line->multicurrency_total_ttc = (float) $multicurrency_total_ttc;
836 if (empty($qty) && empty($special_code)) {
837 $this->line->special_code = 3;
840 if (is_array($array_options) && count($array_options) > 0) {
841 $this->line->array_options = $array_options;
844 $result = $this->line->insert();
846 if (!isset($this->context[
'createfromclone'])) {
847 if (!empty($fk_parent_line)) {
850 } elseif ($ranktouse > 0 && $ranktouse <= count($this->lines)) {
852 $linecount = count($this->lines);
853 for ($ii = $ranktouse; $ii <= $linecount; $ii++) {
858 $this->lines[] = $this->line;
860 foreach ($this->lines as $line) {
861 if ($line->id == $origin_id) {
862 $this->line->extraparams = $line->extraparams;
863 $this->line->setExtraParameters();
869 if (empty($noupdateafterinsertline)) {
875 return $this->line->id;
877 $this->error = $this->db->error();
878 $this->db->rollback();
883 $this->db->rollback();
887 dol_syslog(get_class($this).
"::addline status of proposal must be Draft to allow use of ->addline()", LOG_ERR);
922 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)
927 $this->error =
'ErrorLineIDDoesNotMatchWithObjectID';
931 dol_syslog(get_class($this).
"::updateLine rowid=$rowid, pu=$pu, qty=$qty, remise_percent=$remise_percent,
932 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");
933 include_once DOL_DOCUMENT_ROOT.
'/core/lib/price.lib.php';
936 $remise_percent =
price2num($remise_percent);
939 $pu_ht_devise =
price2num($pu_ht_devise);
940 if (!preg_match(
'/\((.*)\)/', (
string) $txtva)) {
946 if (empty($qty) && empty($special_code)) {
949 if (!empty($qty) && $special_code == 3) {
956 if ($date_start && $date_end && $date_start > $date_end) {
957 $langs->load(
"errors");
958 $this->error = $langs->trans(
'ErrorStartDateGreaterEnd');
962 if ($this->
status == self::STATUS_DRAFT) {
975 if (preg_match(
'/\((.*)\)/', $txtva, $reg)) {
976 $vat_src_code = $reg[1];
977 $txtva = preg_replace(
'/\s*\(.*\)/',
'', $txtva);
986 if ($tmpline->fetch($rowid) > 0) {
988 if ($newqty != $qty) {
990 setEventMessages($langs->trans(
'QtyRecalculatedWithPackaging'),
null,
'warnings');
995 $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);
996 $total_ht = $tabprice[0];
997 $total_tva = $tabprice[1];
998 $total_ttc = $tabprice[2];
999 $total_localtax1 = $tabprice[9];
1000 $total_localtax2 = $tabprice[10];
1001 $pu_ht = $tabprice[3];
1002 $pu_tva = $tabprice[4];
1003 $pu_ttc = $tabprice[5];
1006 $multicurrency_total_ht = $tabprice[16];
1007 $multicurrency_total_tva = $tabprice[17];
1008 $multicurrency_total_ttc = $tabprice[18];
1009 $pu_ht_devise = $tabprice[19];
1013 $line->fetch($rowid);
1015 $staticline = clone $line;
1017 $line->oldline = $staticline;
1018 $this->line = $line;
1019 $this->line->context = $this->context;
1020 $this->line->rang = $rang;
1023 if (!empty($fk_parent_line) && !empty($staticline->fk_parent_line) && $fk_parent_line != $staticline->fk_parent_line) {
1024 $rangmax = $this->
line_max($fk_parent_line);
1025 $this->line->rang = $rangmax + 1;
1029 $this->line->id = $rowid;
1030 $this->line->label = $label;
1031 $this->line->desc = $desc;
1032 $this->line->qty = $qty;
1033 $this->line->product_type = $type;
1034 $this->line->vat_src_code = $vat_src_code;
1035 $this->line->tva_tx = $txtva;
1036 $this->line->localtax1_tx = $txlocaltax1;
1037 $this->line->localtax2_tx = $txlocaltax2;
1038 $this->line->localtax1_type = empty($localtaxes_type[0]) ?
'' : $localtaxes_type[0];
1039 $this->line->localtax2_type = empty($localtaxes_type[2]) ?
'' : $localtaxes_type[2];
1040 $this->line->remise_percent = $remise_percent;
1041 $this->line->subprice = (float) $pu_ht;
1042 $this->line->info_bits = $info_bits;
1044 $this->line->total_ht = (float) $total_ht;
1045 $this->line->total_tva = (float) $total_tva;
1046 $this->line->total_localtax1 = (float) $total_localtax1;
1047 $this->line->total_localtax2 = (float) $total_localtax2;
1048 $this->line->total_ttc = (float) $total_ttc;
1049 $this->line->special_code = $special_code;
1050 $this->line->fk_parent_line = $fk_parent_line;
1051 $this->line->skip_update_total = $skip_update_total;
1052 $this->line->fk_unit = $fk_unit;
1054 $this->line->fk_fournprice = $fk_fournprice;
1055 $this->line->pa_ht = $pa_ht;
1057 $this->line->date_start = $date_start;
1058 $this->line->date_end = $date_end;
1060 if (is_array($array_options) && count($array_options) > 0) {
1062 foreach ($array_options as $key => $value) {
1063 $this->line->array_options[$key] = $array_options[$key];
1068 $this->line->multicurrency_subprice = (float) $pu_ht_devise;
1069 $this->line->multicurrency_total_ht = (float) $multicurrency_total_ht;
1070 $this->line->multicurrency_total_tva = (float) $multicurrency_total_tva;
1071 $this->line->multicurrency_total_ttc = (float) $multicurrency_total_ttc;
1073 $result = $this->line->update($notrigger);
1076 if (!empty($fk_parent_line)) {
1086 $this->db->commit();
1090 $this->db->rollback();
1094 dol_syslog(get_class($this).
"::updateline Erreur -2 Propal en mode incompatible pour cette action");
1111 if ($this->
status == self::STATUS_DRAFT) {
1116 $line->context = $this->context;
1119 $line->fetch($lineid);
1124 if ($id > 0 && (
int) $line->fk_propal !== (
int) $id) {
1125 $this->db->rollback();
1126 $this->error =
'ErrorLineIDDoesNotMatchWithObjectID';
1131 $staticline = clone $line;
1132 $line->oldline = $staticline;
1134 if ($line->delete($user) > 0) {
1137 $this->db->commit();
1141 $this->db->rollback();
1145 $this->error =
'ErrorDeleteLineNotAllowedByObjectStatus';
1159 public function create($user, $notrigger = 0)
1168 if (empty($this->
date)) {
1169 $this->
date = $this->datep;
1171 $this->fin_validite = $this->
date + ($this->duree_validite * 24 * 3600);
1172 if (empty($this->availability_id)) {
1173 $this->availability_id = 0;
1175 if (empty($this->demand_reason_id)) {
1176 $this->demand_reason_id = 0;
1180 if (!empty($this->multicurrency_code) && empty($this->multicurrency_tx)) {
1185 if (empty($this->fk_multicurrency)) {
1187 $this->fk_multicurrency = 0;
1188 $this->multicurrency_tx = 1;
1194 $delivery_date = $this->delivery_date;
1201 $this->error =
"Failed to fetch company";
1202 dol_syslog(get_class($this).
"::create ".$this->error, LOG_ERR);
1207 if (!empty($this->
ref)) {
1210 $this->error =
'ErrorRefAlreadyExists';
1211 dol_syslog(get_class($this).
"::create ".$this->error, LOG_WARNING);
1212 $this->db->rollback();
1217 if (empty($this->
date)) {
1218 $this->error =
"Date of proposal is required";
1219 dol_syslog(get_class($this).
"::create ".$this->error, LOG_ERR);
1227 $sql =
"INSERT INTO ".MAIN_DB_PREFIX.$this->table_element.
" (";
1230 $sql .=
", total_tva";
1231 $sql .=
", total_ttc";
1235 $sql .=
", fk_user_author";
1236 $sql .=
", note_private";
1237 $sql .=
", note_public";
1238 $sql .=
", model_pdf";
1239 $sql .=
", fin_validite";
1240 $sql .=
", fk_cond_reglement";
1241 $sql .=
", deposit_percent";
1242 $sql .=
", fk_mode_reglement";
1243 $sql .=
", fk_account";
1244 $sql .=
", ref_client";
1245 $sql .=
", ref_ext";
1246 $sql .=
", date_livraison";
1247 $sql .=
", fk_shipping_method";
1248 $sql .=
", fk_warehouse";
1249 $sql .=
", fk_availability";
1250 $sql .=
", fk_input_reason";
1251 $sql .=
", fk_projet";
1252 $sql .=
", fk_incoterms";
1253 $sql .=
", location_incoterms";
1255 $sql .=
", fk_multicurrency";
1256 $sql .=
", multicurrency_code";
1257 $sql .=
", multicurrency_tx";
1259 $sql .=
" VALUES (";
1260 $sql .= $this->socid;
1264 $sql .=
", '".$this->db->idate($this->
date).
"'";
1265 $sql .=
", '".$this->db->idate($now).
"'";
1266 $sql .=
", '(PROV)'";
1267 $sql .=
", ".($user->id > 0 ? ((int) $user->id) :
"NULL");
1268 $sql .=
", '".$this->db->escape($this->note_private).
"'";
1269 $sql .=
", '".$this->db->escape($this->note_public).
"'";
1270 $sql .=
", '".$this->db->escape($this->model_pdf).
"'";
1271 $sql .=
", ".($this->fin_validite !=
'' ?
"'".$this->db->idate($this->fin_validite).
"'" :
"NULL");
1272 $sql .=
", ".($this->cond_reglement_id > 0 ? ((int) $this->cond_reglement_id) :
'NULL');
1273 $sql .=
", ".(!empty($this->deposit_percent) ?
"'".$this->db->escape($this->deposit_percent).
"'" :
'NULL');
1274 $sql .=
", ".($this->mode_reglement_id > 0 ? ((int) $this->mode_reglement_id) :
'NULL');
1275 $sql .=
", ".($this->fk_account > 0 ? ((int) $this->fk_account) :
'NULL');
1276 $sql .=
", '".$this->db->escape((
string) $this->ref_client).
"'";
1277 $sql .=
", '".$this->db->escape((
string) $this->ref_ext).
"'";
1278 $sql .=
", ".(!
isDolTms($delivery_date) ?
"NULL" :
"'".$this->db->idate($delivery_date).
"'");
1279 $sql .=
", ".($this->shipping_method_id > 0 ? $this->shipping_method_id :
'NULL');
1280 $sql .=
", ".($this->warehouse_id > 0 ? $this->warehouse_id :
'NULL');
1281 $sql .=
", ".((int) $this->availability_id);
1282 $sql .=
", ".((int) $this->demand_reason_id);
1283 $sql .=
", ".($this->fk_project ? $this->fk_project :
"null");
1284 $sql .=
", ".(int) $this->fk_incoterms;
1285 $sql .=
", '".$this->db->escape($this->location_incoterms).
"'";
1286 $sql .=
", ".(int) $this->entity;
1287 $sql .=
", ".(int) $this->fk_multicurrency;
1288 $sql .=
", '".$this->db->escape($this->multicurrency_code).
"'";
1289 $sql .=
", ".(float) $this->multicurrency_tx;
1292 dol_syslog(get_class($this).
"::create", LOG_DEBUG);
1293 $resql = $this->db->query($sql);
1295 $this->
id = $this->db->last_insert_id(MAIN_DB_PREFIX.$this->table_element);
1298 $this->
ref =
'(PROV'.$this->id.
')';
1299 $sql =
'UPDATE '.MAIN_DB_PREFIX.$this->table_element.
" SET ref='".$this->db->escape($this->
ref).
"' WHERE rowid=".((int) $this->
id);
1301 dol_syslog(get_class($this).
"::create", LOG_DEBUG);
1302 $resql = $this->db->query($sql);
1307 if (!empty($this->linkedObjectsIds) && empty($this->linked_objects)) {
1308 $this->linked_objects = $this->linkedObjectsIds;
1312 if (!$error && !empty($this->linked_objects) && is_array($this->linked_objects)) {
1313 foreach ($this->linked_objects as $origin => $tmp_origin_id) {
1314 if (is_array($tmp_origin_id)) {
1315 foreach ($tmp_origin_id as $origin_id) {
1318 $this->error = $this->db->lasterror();
1323 $origin_id = $tmp_origin_id;
1326 $this->error = $this->db->lasterror();
1338 $fk_parent_line = 0;
1339 $num = count($this->lines);
1341 for ($i = 0; $i < $num; $i++) {
1342 if (!is_object($this->lines[$i])) {
1344 $line = (object) $this->lines[$i];
1346 $line = $this->lines[$i];
1349 if (($line->product_type != 9 && empty($line->fk_parent_line)) || $line->product_type == 9) {
1350 $fk_parent_line = 0;
1353 $vatrate = $line->tva_tx;
1354 if ($line->vat_src_code && !preg_match(
'/\(.*\)/', $vatrate)) {
1355 $vatrate .=
' ('.$line->vat_src_code.
')';
1359 $originid = $line->origin_id;
1360 $origintype = $line->origin;
1362 $originid = $line->id;
1363 $origintype = $this->element;
1371 $line->localtax1_tx,
1372 $line->localtax2_tx,
1374 $line->remise_percent,
1378 $line->product_type,
1380 $line->special_code,
1382 $line->fk_fournprice,
1387 $line->array_options,
1389 (
string) $origintype,
1398 $this->error = $this->db->error;
1404 $line->id = $result;
1407 if ($result > 0 && $line->product_type == 9) {
1408 $fk_parent_line = $result;
1423 if (!$error && !$notrigger) {
1425 $result = $this->call_trigger(
'PROPAL_CREATE', $user);
1432 $this->error = $this->db->lasterror();
1437 $this->error = $this->db->lasterror();
1442 $this->db->commit();
1443 dol_syslog(get_class($this).
"::create done id=".$this->
id);
1446 $this->db->rollback();
1450 $this->error = $this->db->lasterror();
1451 $this->db->rollback();
1466 public function createFromClone(
User $user, $socid = 0, $forceentity =
null, $update_prices =
false, $update_desc =
false)
1468 global $conf, $hookmanager,
$mysoc;
1477 $object =
new self($this->db);
1484 $objsoc =
new Societe($this->db);
1487 if (!empty($socid) && $socid !=
$object->socid) {
1488 if ($objsoc->fetch($socid) > 0) {
1490 $object->cond_reglement_id = (!empty($objsoc->cond_reglement_id) ? $objsoc->cond_reglement_id : 0);
1491 $object->deposit_percent = (!empty($objsoc->deposit_percent) ? $objsoc->deposit_percent :
null);
1492 $object->mode_reglement_id = (!empty($objsoc->mode_reglement_id) ? $objsoc->mode_reglement_id : 0);
1493 $object->fk_delivery_address = 0;
1516 $objsoc->fetch(
$object->socid);
1520 if ($update_prices ===
true || $update_desc ===
true) {
1521 if ($objsoc->id > 0 && !empty(
$object->lines)) {
1524 require_once DOL_DOCUMENT_ROOT .
'/product/class/productcustomerprice.class.php';
1527 foreach (
$object->lines as $line) {
1530 if ($line->fk_product > 0) {
1531 $prod =
new Product($this->db);
1532 $res = $prod->fetch($line->fk_product);
1534 if ($update_prices ===
true) {
1535 $pu_ht = $prod->price;
1537 $remise_percent = $objsoc->remise_percent;
1540 $pu_ht = $prod->multiprices[$objsoc->price_level];
1542 if (isset($prod->multiprices_tva_tx[$objsoc->price_level])) {
1543 $tva_tx = (string) $prod->multiprices_tva_tx[$objsoc->price_level];
1548 $filter = array(
't.fk_product' => (
string) $prod->id,
't.fk_soc' => (
string) $objsoc->id);
1549 $result = $prodcustprice->fetchAll(
'',
'', 0, 0, $filter);
1552 if (count($prodcustprice->lines) > 0) {
1553 $date_now = (int) floor(
dol_now() / 86400) * 86400;
1554 foreach ($prodcustprice->lines as $k => $custprice_line) {
1555 if ($custprice_line->date_begin <= $date_now && (empty($custprice_line->date_end) || $date_now <= $custprice_line->date_end)) {
1556 $pu_ht =
price($custprice_line->price);
1557 $tva_tx = ($custprice_line->default_vat_code ? $custprice_line->tva_tx .
' (' . $custprice_line->default_vat_code .
' )' : $custprice_line->tva_tx);
1558 if ($custprice_line->default_vat_code && !preg_match(
'/\(.*\)/', $tva_tx)) {
1559 $tva_tx .=
' (' . $custprice_line->default_vat_code .
')';
1561 $remise_percent = $custprice_line->discount_percent;
1569 $line->subprice = $pu_ht;
1570 $line->tva_tx = $tva_tx;
1571 $line->remise_percent = $remise_percent;
1574 if ($line->fk_fournprice > 0) {
1575 require_once DOL_DOCUMENT_ROOT.
'/fourn/class/fournisseur.product.class.php';
1577 if ($prodfourn->fetch_product_fournisseur_price($line->fk_fournprice) > 0) {
1578 $line->pa_ht =
price2num($prodfourn->fourn_unitprice * (1 - $prodfourn->fourn_remise_percent / 100),
'MU');
1580 $line->fk_fournprice = 0;
1584 if ($update_desc ===
true) {
1585 $line->desc = $prod->description;
1595 $object->entity = (!empty($forceentity) ? $forceentity :
$object->entity);
1600 $object->user_creation_id = $user->id;
1601 $object->user_validation_id = 0;
1614 $object->context[
'createfromclone'] =
'createfromclone';
1615 $result =
$object->create($user);
1623 if (
$object->copy_linked_contact($this,
'internal') < 0) {
1630 if ($this->socid ==
$object->socid) {
1631 if (
$object->copy_linked_contact($this,
'external') < 0) {
1639 if (is_object($hookmanager)) {
1640 $parameters = array(
'objFrom' => $this,
'clonedObj' =>
$object);
1642 $reshook = $hookmanager->executeHooks(
'createFrom', $parameters,
$object, $action);
1650 unset(
$object->context[
'createfromclone']);
1654 $this->db->commit();
1657 $this->db->rollback();
1671 public function fetch($rowid, $ref =
'', $ref_ext =
'', $forceentity = 0)
1673 $sql =
"SELECT p.rowid, p.ref, p.entity, p.fk_soc";
1674 $sql .=
", p.total_ttc, p.total_tva, p.localtax1, p.localtax2, p.total_ht";
1675 $sql .=
", p.datec";
1676 $sql .=
", p.date_signature as dates";
1677 $sql .=
", p.date_valid as datev";
1678 $sql .=
", p.datep as dp";
1679 $sql .=
", p.fin_validite as dfv";
1680 $sql .=
", p.date_livraison as delivery_date";
1681 $sql .=
", p.model_pdf, p.last_main_doc, p.ref_client, ref_ext, p.extraparams";
1682 $sql .=
", p.note_private, p.note_public";
1683 $sql .=
", p.fk_projet as fk_project, p.fk_statut";
1684 $sql .=
", p.fk_user_author, p.fk_user_valid, p.fk_user_cloture";
1685 $sql .=
", p.fk_delivery_address";
1686 $sql .=
", p.fk_availability";
1687 $sql .=
", p.fk_input_reason";
1688 $sql .=
", p.fk_cond_reglement";
1689 $sql .=
", p.fk_mode_reglement";
1690 $sql .=
', p.fk_account';
1691 $sql .=
", p.fk_shipping_method";
1692 $sql .=
", p.fk_warehouse";
1693 $sql .=
", p.fk_incoterms, p.location_incoterms";
1694 $sql .=
", p.fk_multicurrency, p.multicurrency_code, p.multicurrency_tx, p.multicurrency_total_ht, p.multicurrency_total_tva, p.multicurrency_total_ttc";
1695 $sql .=
", p.tms as date_modification";
1696 $sql .=
", i.libelle as label_incoterms";
1697 $sql .=
", c.label as statut_label";
1698 $sql .=
", ca.code as availability_code, ca.label as availability";
1699 $sql .=
", dr.code as demand_reason_code, dr.label as demand_reason";
1700 $sql .=
", cr.code as cond_reglement_code, cr.libelle as cond_reglement, cr.libelle_facture as cond_reglement_libelle_doc, p.deposit_percent";
1701 $sql .=
", cp.code as mode_reglement_code, cp.libelle as mode_reglement";
1702 $sql .=
" FROM ".MAIN_DB_PREFIX.$this->table_element.
" as p";
1703 $sql .=
' LEFT JOIN '.MAIN_DB_PREFIX.
'c_propalst as c ON p.fk_statut = c.id';
1704 $sql .=
' LEFT JOIN '.MAIN_DB_PREFIX.
'c_paiement as cp ON p.fk_mode_reglement = cp.id AND cp.entity IN ('.
getEntity(
'c_paiement').
')';
1705 $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').
')';
1706 $sql .=
' LEFT JOIN '.MAIN_DB_PREFIX.
'c_availability as ca ON p.fk_availability = ca.rowid';
1707 $sql .=
' LEFT JOIN '.MAIN_DB_PREFIX.
'c_input_reason as dr ON p.fk_input_reason = dr.rowid';
1708 $sql .=
' LEFT JOIN '.MAIN_DB_PREFIX.
'c_incoterms as i ON p.fk_incoterms = i.rowid';
1711 if (!empty($forceentity)) {
1712 $sql .=
" WHERE p.entity = ".(int) $forceentity;
1714 $sql .=
" WHERE p.entity IN (".getEntity(
'propal').
")";
1716 $sql .=
" AND p.ref='".$this->db->escape($ref).
"'";
1719 $sql .=
" WHERE p.rowid = ".((int) $rowid);
1722 dol_syslog(get_class($this).
"::fetch", LOG_DEBUG);
1723 $resql = $this->db->query($sql);
1725 if ($this->db->num_rows($resql)) {
1726 $obj = $this->db->fetch_object($resql);
1728 $this->
id = $obj->rowid;
1729 $this->entity = $obj->entity;
1731 $this->
ref = $obj->ref;
1732 $this->ref_client = $obj->ref_client;
1733 $this->ref_customer = $obj->ref_client;
1734 $this->ref_ext = $obj->ref_ext;
1736 $this->total = $obj->total_ttc;
1737 $this->total_ttc = $obj->total_ttc;
1738 $this->total_ht = $obj->total_ht;
1739 $this->total_tva = $obj->total_tva;
1740 $this->total_localtax1 = $obj->localtax1;
1741 $this->total_localtax2 = $obj->localtax2;
1743 $this->socid = $obj->fk_soc;
1744 $this->thirdparty =
null;
1746 $this->fk_project = $obj->fk_project;
1747 $this->project =
null;
1749 $this->model_pdf = $obj->model_pdf;
1750 $this->last_main_doc = $obj->last_main_doc;
1751 $this->note = $obj->note_private;
1752 $this->note_private = $obj->note_private;
1753 $this->note_public = $obj->note_public;
1755 $this->
status = (int) $obj->fk_statut;
1756 $this->statut = $this->status;
1758 $this->datec = $this->db->jdate($obj->datec);
1759 $this->datev = $this->db->jdate($obj->datev);
1760 $this->date_creation = $this->db->jdate($obj->datec);
1761 $this->date_validation = $this->db->jdate($obj->datev);
1762 $this->date_modification = $this->db->jdate($obj->date_modification);
1763 $this->date_signature = $this->db->jdate($obj->dates);
1764 $this->
date = $this->db->jdate($obj->dp);
1765 $this->datep = $this->db->jdate($obj->dp);
1766 $this->fin_validite = $this->db->jdate($obj->dfv);
1767 $this->delivery_date = $this->db->jdate($obj->delivery_date);
1768 $this->shipping_method_id = ($obj->fk_shipping_method > 0) ? $obj->fk_shipping_method :
null;
1769 $this->warehouse_id = ($obj->fk_warehouse > 0) ? $obj->fk_warehouse :
null;
1770 $this->availability_id = $obj->fk_availability;
1771 $this->availability_code = $obj->availability_code;
1773 $this->demand_reason_id = $obj->fk_input_reason;
1774 $this->demand_reason_code = $obj->demand_reason_code;
1776 $this->fk_address = $obj->fk_delivery_address;
1778 $this->mode_reglement_id = $obj->fk_mode_reglement;
1779 $this->mode_reglement_code = $obj->mode_reglement_code;
1780 $this->mode_reglement = $obj->mode_reglement;
1781 $this->fk_account = ($obj->fk_account > 0) ? $obj->fk_account :
null;
1782 $this->cond_reglement_id = $obj->fk_cond_reglement;
1783 $this->cond_reglement_code = $obj->cond_reglement_code;
1784 $this->cond_reglement = $obj->cond_reglement;
1785 $this->cond_reglement_doc = $obj->cond_reglement_libelle_doc;
1786 $this->deposit_percent = $obj->deposit_percent;
1788 $this->extraparams = !empty($obj->extraparams) ? (array) json_decode($obj->extraparams,
true) : array();
1790 $this->user_author_id = $obj->fk_user_author;
1791 $this->user_validation_id = $obj->fk_user_valid;
1792 $this->user_closing_id = $obj->fk_user_cloture;
1795 $this->fk_incoterms = $obj->fk_incoterms;
1796 $this->location_incoterms = $obj->location_incoterms;
1797 $this->label_incoterms = $obj->label_incoterms;
1800 $this->fk_multicurrency = $obj->fk_multicurrency;
1801 $this->multicurrency_code = $obj->multicurrency_code;
1802 $this->multicurrency_tx = $obj->multicurrency_tx;
1803 $this->multicurrency_total_ht = $obj->multicurrency_total_ht;
1804 $this->multicurrency_total_tva = $obj->multicurrency_total_tva;
1805 $this->multicurrency_total_ttc = $obj->multicurrency_total_ttc;
1811 $this->db->free($resql);
1813 $this->lines = array();
1824 $this->error =
"Record Not Found";
1827 $this->error = $this->db->lasterror();
1846 if (isset($this->
ref)) {
1847 $this->
ref = trim($this->
ref);
1849 if (isset($this->ref_client)) {
1850 $this->ref_client = trim($this->ref_client);
1852 if (isset($this->note) || isset($this->note_private)) {
1853 $this->note_private = (isset($this->note_private) ? trim($this->note_private) : trim($this->note));
1855 if (isset($this->note_public)) {
1856 $this->note_public = trim($this->note_public);
1858 if (isset($this->model_pdf)) {
1859 $this->model_pdf = trim($this->model_pdf);
1861 if (isset($this->import_key)) {
1862 $this->import_key = trim($this->import_key);
1864 if (!empty($this->duree_validite) && is_numeric($this->duree_validite)) {
1865 $this->fin_validite = $this->
date + ($this->duree_validite * 24 * 3600);
1872 $sql =
"UPDATE ".MAIN_DB_PREFIX.$this->table_element.
" SET";
1873 $sql =
"UPDATE ".MAIN_DB_PREFIX.
"propal SET";
1874 $sql .=
" ref = ".(isset($this->
ref) ?
"'".$this->db->escape($this->
ref).
"'" :
"null").
",";
1875 $sql .=
" ref_client = ".(isset($this->ref_client) ?
"'".$this->db->escape($this->ref_client).
"'" :
"null").
",";
1876 $sql .=
" ref_ext = ".(isset($this->ref_ext) ?
"'".$this->db->escape($this->ref_ext).
"'" :
"null").
",";
1877 $sql .=
" fk_soc = ".(!empty($this->socid) ? (int) $this->socid :
"null").
",";
1878 $sql .=
" datep = ".(strval($this->
date) !=
'' ?
"'".$this->db->idate($this->
date).
"'" :
'null').
",";
1879 if (!empty($this->fin_validite)) {
1880 $sql .=
" fin_validite = ".(strval($this->fin_validite) !=
'' ?
"'".$this->db->idate($this->fin_validite).
"'" :
'null').
",";
1882 $sql .=
" date_valid = ".(strval($this->date_validation) !=
'' ?
"'".$this->db->idate($this->date_validation).
"'" :
'null').
",";
1883 $sql .=
" total_tva = ".(isset($this->total_tva) ? (float) $this->total_tva :
"null").
",";
1884 $sql .=
" localtax1 = ".(isset($this->total_localtax1) ? (float) $this->total_localtax1 :
"null").
",";
1885 $sql .=
" localtax2 = ".(isset($this->total_localtax2) ? (float) $this->total_localtax2 :
"null").
",";
1886 $sql .=
" total_ht = ".(isset($this->total_ht) ? (float) $this->total_ht :
"null").
",";
1887 $sql .=
" total_ttc = ".(isset($this->total_ttc) ? (float) $this->total_ttc :
"null").
",";
1888 $sql .=
" fk_statut = ".(isset($this->
status) ? (int) $this->
status :
"null").
",";
1889 $sql .=
" fk_user_author = ".(!empty($this->user_author_id) ? (int) $this->user_author_id :
"null").
",";
1890 $sql .=
" fk_user_valid = ".(!empty($this->user_validation_id) ? (int) $this->user_validation_id :
"null").
",";
1892 $sql .=
" fk_projet = ".(!empty($this->fk_project) ? (int) $this->fk_project :
"null").
",";
1893 $sql .=
" fk_cond_reglement = ".(!empty($this->cond_reglement_id) ? (int) $this->cond_reglement_id :
"null").
",";
1894 $sql .=
" deposit_percent = ".(!empty($this->deposit_percent) ?
"'".$this->db->escape($this->deposit_percent).
"'" :
"null").
",";
1895 $sql .=
" fk_mode_reglement = ".(!empty($this->mode_reglement_id) ? (int) $this->mode_reglement_id :
"null").
",";
1896 $sql .=
" fk_input_reason = ".(!empty($this->demand_reason_id) ? (int) $this->demand_reason_id :
"null").
",";
1897 $sql .=
" fk_shipping_method = ".(isset($this->shipping_method_id) ? (int) $this->shipping_method_id :
"null").
",";
1898 $sql .=
" fk_availability = ".(!empty($this->availability_id) ? (int) $this->availability_id :
"null").
",";
1899 $sql .=
" note_private = ".(isset($this->note_private) ?
"'".$this->db->escape($this->note_private).
"'" :
"null").
",";
1900 $sql .=
" note_public = ".(isset($this->note_public) ?
"'".$this->db->escape($this->note_public).
"'" :
"null").
",";
1901 $sql .=
" model_pdf = ".(isset($this->model_pdf) ?
"'".$this->db->escape($this->model_pdf).
"'" :
"null").
",";
1902 $sql .=
" import_key = ".(isset($this->import_key) ?
"'".$this->db->escape($this->import_key).
"'" :
"null");
1903 $sql .=
" WHERE rowid = ".((int) $this->
id);
1907 dol_syslog(get_class($this).
"::update", LOG_DEBUG);
1908 $resql = $this->db->query($sql);
1911 $this->errors[] =
"Error ".$this->db->lasterror();
1921 if (!$error && !$notrigger) {
1923 $result = $this->call_trigger(
'PROPAL_MODIFY', $user);
1932 foreach ($this->errors as $errmsg) {
1933 dol_syslog(get_class($this).
"::update ".$errmsg, LOG_ERR);
1934 $this->error .= ($this->error ?
', '.$errmsg : $errmsg);
1936 $this->db->rollback();
1939 $this->db->commit();
1954 public function fetch_lines($only_product = 0, $loadalsotranslation = 0, $sqlforgedfilters =
'')
1957 $this->lines = array();
1959 $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,';
1960 $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,';
1961 $sql .=
' d.fk_unit,';
1962 $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,';
1963 $sql .=
' p.weight, p.weight_units, p.volume, p.volume_units,';
1964 $sql .=
' p.customcode, p.fk_country as country_id, c.code as country_code,';
1965 $sql .=
' d.date_start, d.date_end, d.extraparams,';
1966 $sql .=
' d.fk_multicurrency, d.multicurrency_code, d.multicurrency_subprice, d.multicurrency_total_ht, d.multicurrency_total_tva, d.multicurrency_total_ttc';
1967 $sql .=
' FROM '.MAIN_DB_PREFIX.$this->table_element_line.
' as d';
1968 $sql .=
' LEFT JOIN '.MAIN_DB_PREFIX.
'product as p ON (d.fk_product = p.rowid)';
1969 $sql .=
' LEFT JOIN '.MAIN_DB_PREFIX.
'c_country as c ON c.rowid = p.fk_country';
1970 $sql .=
' WHERE d.fk_propal = '.((int) $this->
id);
1971 if ($only_product) {
1972 $sql .=
' AND p.fk_product_type = 0';
1974 if ($sqlforgedfilters) {
1975 $sql .= $sqlforgedfilters;
1977 $sql .=
' ORDER BY d.rang, d.rowid';
1979 dol_syslog(get_class($this).
"::fetch_lines", LOG_DEBUG);
1980 $result = $this->db->query($sql);
1982 require_once DOL_DOCUMENT_ROOT.
'/core/class/extrafields.class.php';
1984 $num = $this->db->num_rows($result);
1988 $objp = $this->db->fetch_object($result);
1992 $line->rowid = $objp->rowid;
1993 $line->id = $objp->rowid;
1994 $line->fk_propal = $objp->fk_propal;
1995 $line->fk_parent_line = $objp->fk_parent_line;
1996 $line->label = $objp->custom_label;
1997 $line->desc = $objp->description;
1998 $line->description = $objp->description;
1999 $line->qty = $objp->qty;
2000 $line->vat_src_code = $objp->vat_src_code;
2001 $line->tva_tx = $objp->tva_tx;
2002 $line->localtax1_tx = $objp->localtax1_tx;
2003 $line->localtax2_tx = $objp->localtax2_tx;
2004 $line->localtax1_type = $objp->localtax1_type;
2005 $line->localtax2_type = $objp->localtax2_type;
2006 $line->subprice = $objp->subprice;
2007 $line->fk_remise_except = $objp->fk_remise_except;
2008 $line->remise_percent = $objp->remise_percent;
2010 $line->info_bits = $objp->info_bits;
2011 $line->total_ht = $objp->total_ht;
2012 $line->total_tva = $objp->total_tva;
2013 $line->total_localtax1 = $objp->total_localtax1;
2014 $line->total_localtax2 = $objp->total_localtax2;
2015 $line->total_ttc = $objp->total_ttc;
2016 $line->fk_fournprice = $objp->fk_fournprice;
2017 $marginInfos =
getMarginInfos($objp->subprice, $objp->remise_percent, $objp->tva_tx, $objp->localtax1_tx, $objp->localtax2_tx, $line->fk_fournprice, $objp->pa_ht);
2018 $line->pa_ht = $marginInfos[0];
2019 $line->marge_tx = $marginInfos[1];
2020 $line->marque_tx = $marginInfos[2];
2021 $line->special_code = $objp->special_code;
2022 $line->rang = $objp->rang;
2024 $line->fk_product = $objp->fk_product;
2026 $line->ref = $objp->product_ref;
2027 $line->libelle = $objp->product_label;
2029 $line->product_ref = $objp->product_ref;
2030 $line->product_label = $objp->product_label;
2031 $line->product_desc = $objp->product_desc;
2032 $line->product_tobatch = $objp->product_tobatch;
2033 $line->product_barcode = $objp->product_barcode;
2034 $line->product_custom_code = $objp->customcode;
2035 $line->product_custom_country_id = $objp->country_id;
2036 $line->product_custom_country_code = $objp->country_code;
2037 $line->product_type = $objp->product_type;
2038 $line->fk_product_type = $objp->fk_product_type;
2040 $line->fk_unit = $objp->fk_unit;
2041 $line->weight = $objp->weight;
2042 $line->weight_units = $objp->weight_units;
2043 $line->volume = $objp->volume;
2044 $line->volume_units = $objp->volume_units;
2046 $line->date_start = $this->db->jdate($objp->date_start);
2047 $line->date_end = $this->db->jdate($objp->date_end);
2049 $line->extraparams = !empty($objp->extraparams) ? (array) json_decode($objp->extraparams,
true) : array();
2052 $line->fk_multicurrency = $objp->fk_multicurrency;
2053 $line->multicurrency_code = $objp->multicurrency_code;
2054 $line->multicurrency_subprice = $objp->multicurrency_subprice;
2055 $line->multicurrency_total_ht = $objp->multicurrency_total_ht;
2056 $line->multicurrency_total_tva = $objp->multicurrency_total_tva;
2057 $line->multicurrency_total_ttc = $objp->multicurrency_total_ttc;
2059 $line->fetch_optionals();
2062 if (
getDolGlobalInt(
'MAIN_MULTILANGS') && !empty($objp->fk_product) && !empty($loadalsotranslation)) {
2063 $tmpproduct =
new Product($this->db);
2064 $tmpproduct->fetch($objp->fk_product);
2065 $tmpproduct->getMultiLangs();
2067 $line->multilangs = $tmpproduct->multilangs;
2070 $this->lines[$i] = $line;
2075 $this->db->free($result);
2079 $this->error = $this->db->lasterror();
2091 public function valid($user, $notrigger = 0)
2095 require_once DOL_DOCUMENT_ROOT.
'/core/lib/files.lib.php';
2100 if ($this->
status == self::STATUS_VALIDATED) {
2101 dol_syslog(get_class($this).
"::valid action abandoned: already validated", LOG_WARNING);
2105 if (!((!
getDolGlobalString(
'MAIN_USE_ADVANCED_PERMS') && $user->hasRight(
'propal',
'creer'))
2106 || (
getDolGlobalString(
'MAIN_USE_ADVANCED_PERMS') && $user->hasRight(
'propal',
'propal_advance',
'validate')))) {
2107 $this->error =
'ErrorPermissionDenied';
2108 dol_syslog(get_class($this).
"::valid ".$this->error, LOG_ERR);
2113 dol_syslog(get_class($this).
"::valid checkActiveProductInLines ".$this->error, LOG_INFO);
2122 $soc =
new Societe($this->db);
2123 $soc->fetch($this->socid);
2126 if (preg_match(
'/^[\(]?PROV/i', $this->
ref) || empty($this->
ref)) {
2127 $num = $this->getNextNumRef($soc);
2129 $num = (string) $this->
ref;
2133 $sql =
"UPDATE ".MAIN_DB_PREFIX.$this->table_element;
2134 $sql .=
" SET ref = '".$this->db->escape($num).
"',";
2135 $sql .=
" fk_statut = ".self::STATUS_VALIDATED.
", date_valid='".$this->db->idate($now).
"', fk_user_valid=".((int) $user->id);
2138 dol_syslog(get_class($this).
"::valid", LOG_DEBUG);
2139 $resql = $this->db->query($sql);
2146 if (!$error && !$notrigger) {
2148 $result = $this->call_trigger(
'PROPAL_VALIDATE', $user);
2156 $this->oldref = $this->ref;
2159 if (preg_match(
'/^[\(]?PROV/i', $this->
ref)) {
2161 $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).
"'";
2162 $sql .=
" WHERE filename LIKE '".$this->db->escape($this->
ref).
"%' AND filepath = 'propale/".$this->db->escape($this->
ref).
"' and entity = ".((int) $conf->entity);
2163 $resql = $this->db->query($sql);
2166 $this->error = $this->db->lasterror();
2168 $sql =
'UPDATE '.MAIN_DB_PREFIX.
"ecm_files set filepath = 'propale/".$this->db->escape($this->newref).
"'";
2169 $sql .=
" WHERE filepath = 'propale/".$this->db->escape($this->
ref).
"' and entity = ".$conf->entity;
2170 $resql = $this->db->query($sql);
2173 $this->error = $this->db->lasterror();
2179 $dirsource = $conf->propal->multidir_output[$this->entity].
'/'.$oldref;
2180 $dirdest = $conf->propal->multidir_output[$this->entity].
'/'.$newref;
2181 if (!$error && file_exists($dirsource)) {
2182 dol_syslog(get_class($this).
"::validate rename dir ".$dirsource.
" into ".$dirdest);
2183 if (@rename($dirsource, $dirdest)) {
2186 $listoffiles =
dol_dir_list($dirdest,
'files', 1,
'^'.preg_quote($oldref,
'/'));
2187 foreach ($listoffiles as $fileentry) {
2188 $dirsource = $fileentry[
'name'];
2189 $dirdest = preg_replace(
'/^'.preg_quote($oldref,
'/').
'/', $newref, $dirsource);
2190 $dirsource = $fileentry[
'path'].
'/'.$dirsource;
2191 $dirdest = $fileentry[
'path'].
'/'.$dirdest;
2192 @rename($dirsource, $dirdest);
2200 $this->user_validation_id = $user->id;
2201 $this->datev = $now;
2202 $this->date_validation = $now;
2204 $this->db->commit();
2207 $this->db->rollback();
2226 $this->error =
'ErrorBadParameter';
2227 dol_syslog(get_class($this).
"::set_date ".$this->error, LOG_ERR);
2231 if ($user->hasRight(
'propal',
'creer')) {
2236 $sql =
"UPDATE ".MAIN_DB_PREFIX.$this->table_element;
2237 $sql .=
" SET datep = '".$this->db->idate($date).
"'";
2238 $sql .=
" WHERE rowid = ".((int) $this->
id);
2241 $resql = $this->db->query($sql);
2243 $this->errors[] = $this->db->error();
2248 $this->oldcopy = clone $this;
2249 $this->
date = $date;
2250 $this->datep = $date;
2253 if (!$notrigger && empty($error)) {
2255 $result = $this->call_trigger(
'PROPAL_MODIFY', $user);
2263 $this->db->commit();
2266 foreach ($this->errors as $errmsg) {
2267 dol_syslog(__METHOD__.
' Error: '.$errmsg, LOG_ERR);
2268 $this->error .= ($this->error ?
', '.$errmsg : $errmsg);
2270 $this->db->rollback();
2290 if ($user->hasRight(
'propal',
'creer')) {
2295 $sql =
"UPDATE ".MAIN_DB_PREFIX.$this->table_element;
2296 $sql .=
" SET fin_validite = ".($date_end_validity !=
'' ?
"'".$this->db->idate($date_end_validity).
"'" :
'null');
2297 $sql .=
" WHERE rowid = ".((int) $this->
id);
2301 $resql = $this->db->query($sql);
2303 $this->errors[] = $this->db->error();
2309 $this->oldcopy = clone $this;
2310 $this->fin_validite = $date_end_validity;
2313 if (!$notrigger && empty($error)) {
2315 $result = $this->call_trigger(
'PROPAL_MODIFY', $user);
2323 $this->db->commit();
2326 foreach ($this->errors as $errmsg) {
2327 dol_syslog(__METHOD__.
' Error: '.$errmsg, LOG_ERR);
2328 $this->error .= ($this->error ?
', '.$errmsg : $errmsg);
2330 $this->db->rollback();
2364 if ($user->hasRight(
'propal',
'creer')) {
2369 $sql =
"UPDATE ".MAIN_DB_PREFIX.$this->table_element;
2370 $sql .=
" SET date_livraison = ".(isDolTms($delivery_date) ?
"'".$this->db->idate($delivery_date).
"'" :
'null');
2371 $sql .=
" WHERE rowid = ".((int) $this->
id);
2374 $resql = $this->db->query($sql);
2376 $this->errors[] = $this->db->error();
2381 $this->oldcopy = clone $this;
2382 $this->delivery_date = $delivery_date;
2385 if (!$notrigger && empty($error)) {
2387 $result = $this->call_trigger(
'PROPAL_MODIFY', $user);
2395 $this->db->commit();
2398 foreach ($this->errors as $errmsg) {
2399 dol_syslog(__METHOD__.
' Error: '.$errmsg, LOG_ERR);
2400 $this->error .= ($this->error ?
', '.$errmsg : $errmsg);
2402 $this->db->rollback();
2422 if ($user->hasRight(
'propal',
'creer') && $this->status >= self::STATUS_DRAFT) {
2427 $sql =
"UPDATE ".MAIN_DB_PREFIX.$this->table_element;
2428 $sql .=
" SET fk_availability = ".((int) $id);
2429 $sql .=
" WHERE rowid = ".((int) $this->
id);
2431 dol_syslog(__METHOD__.
' availability('.$id.
')', LOG_DEBUG);
2432 $resql = $this->db->query($sql);
2434 $this->errors[] = $this->db->error();
2439 $this->oldcopy = clone $this;
2440 $this->fk_availability = $id;
2441 $this->availability_id = $id;
2444 if (!$notrigger && empty($error)) {
2446 $result = $this->call_trigger(
'PROPAL_MODIFY', $user);
2454 $this->db->commit();
2457 foreach ($this->errors as $errmsg) {
2458 dol_syslog(__METHOD__.
' Error: '.$errmsg, LOG_ERR);
2459 $this->error .= ($this->error ?
', '.$errmsg : $errmsg);
2461 $this->db->rollback();
2465 $error_str =
'Propal status do not meet requirement '.$this->status;
2467 $this->error = $error_str;
2468 $this->errors[] = $this->error;
2485 if ($user->hasRight(
'propal',
'creer') && $this->status >= self::STATUS_DRAFT) {
2490 $sql =
"UPDATE ".MAIN_DB_PREFIX.$this->table_element;
2491 $sql .=
" SET fk_input_reason = ".((int) $id);
2492 $sql .=
" WHERE rowid = ".((int) $this->
id);
2495 $resql = $this->db->query($sql);
2497 $this->errors[] = $this->db->error();
2503 $this->oldcopy = clone $this;
2505 $this->demand_reason_id = $id;
2509 if (!$notrigger && empty($error)) {
2511 $result = $this->call_trigger(
'PROPAL_MODIFY', $user);
2519 $this->db->commit();
2522 foreach ($this->errors as $errmsg) {
2523 dol_syslog(__METHOD__.
' Error: '.$errmsg, LOG_ERR);
2524 $this->error .= ($this->error ?
', '.$errmsg : $errmsg);
2526 $this->db->rollback();
2530 $error_str =
'Propal status do not meet requirement '.$this->status;
2532 $this->error = $error_str;
2533 $this->errors[] = $this->error;
2550 if ($user->hasRight(
'propal',
'creer')) {
2555 $sql =
"UPDATE ".MAIN_DB_PREFIX.$this->table_element;
2556 $sql .=
" SET ref_client = ".(empty($ref_client) ?
'NULL' :
"'".$this->db->escape($ref_client).
"'");
2557 $sql .=
" WHERE rowid = ".((int) $this->
id);
2559 dol_syslog(__METHOD__.
' $this->id='.$this->id.
', ref_client='.$ref_client, LOG_DEBUG);
2560 $resql = $this->db->query($sql);
2562 $this->errors[] = $this->db->error();
2567 $this->oldcopy = clone $this;
2568 $this->ref_customer = $ref_client;
2569 $this->ref_client = $ref_client;
2572 if (!$notrigger && empty($error)) {
2574 $result = $this->call_trigger(
'PROPAL_MODIFY', $user);
2582 $this->db->commit();
2585 foreach ($this->errors as $errmsg) {
2586 dol_syslog(__METHOD__.
' Error: '.$errmsg, LOG_ERR);
2587 $this->error .= ($this->error ?
', '.$errmsg : $errmsg);
2589 $this->db->rollback();
2607 public function reopen($user, $status, $note =
'', $notrigger = 0)
2611 $sql =
"UPDATE ".MAIN_DB_PREFIX.$this->table_element;
2612 $sql .=
" SET fk_statut = ".((int) $status).
",";
2613 if (!empty($note)) {
2614 $sql .=
" note_private = '".$this->db->escape($note).
"',";
2616 $sql .=
" date_cloture=NULL, fk_user_cloture=NULL";
2617 $sql .=
" WHERE rowid = ".((int) $this->
id);
2621 dol_syslog(get_class($this).
"::reopen", LOG_DEBUG);
2622 $resql = $this->db->query($sql);
2625 $this->errors[] =
"Error ".$this->db->lasterror();
2630 $result = $this->call_trigger(
'PROPAL_REOPEN', $user);
2640 if (!empty($this->errors)) {
2641 foreach ($this->errors as $errmsg) {
2642 dol_syslog(get_class($this).
"::update ".$errmsg, LOG_ERR);
2643 $this->error .= ($this->error ?
', '.$errmsg : $errmsg);
2646 $this->db->rollback();
2649 $this->statut = $status;
2652 $this->db->commit();
2667 public function closeProposal($user, $status, $note_private =
'', $notrigger = 0, $note_public =
'')
2669 global $langs,$conf;
2676 $newprivatenote =
dol_concatdesc($this->note_private, $note_private);
2677 $newpublicnote =
dol_concatdesc($this->note_public, $note_public);
2680 $date_signature = $now;
2681 $fk_user_signature = $user->id;
2683 $this->
info($this->
id);
2684 if (!isset($this->date_signature) || $this->date_signature ==
'') {
2685 $date_signature = $now;
2686 $fk_user_signature = $user->id;
2688 $date_signature = $this->date_signature;
2689 $fk_user_signature = $this->user_signature->id;
2693 $sql =
"UPDATE ".MAIN_DB_PREFIX.$this->table_element;
2694 $sql .=
" SET fk_statut = ".((int) $status).
", note_private = '".$this->db->escape($newprivatenote).
"', note_public = '".$this->db->escape($newpublicnote).
"'";
2695 if ($status == self::STATUS_SIGNED) {
2696 $sql .=
", date_signature='".$this->db->idate($now).
"', fk_user_signature = ".($fk_user_signature);
2698 $sql .=
" WHERE rowid = ".((int) $this->
id);
2700 $resql = $this->db->query($sql);
2704 $triggerName =
'PROPAL_CLOSE_REFUSED';
2706 if ($status == self::STATUS_SIGNED) {
2707 $triggerName =
'PROPAL_CLOSE_SIGNED';
2711 $soc =
new Societe($this->db);
2712 $soc->id = $this->socid;
2713 $result = $soc->setAsCustomer();
2716 $this->error = $this->db->lasterror();
2717 $this->db->rollback();
2724 $outputlangs = $langs;
2726 $outputlangs =
new Translate(
"", $conf);
2727 $newlang = (
GETPOST(
'lang_id',
'aZ09') ?
GETPOST(
'lang_id',
'aZ09') : $this->thirdparty->default_lang);
2728 $outputlangs->setDefaultLang($newlang);
2737 $this->
generateDocument($modelpdf, $outputlangs, $hidedetails, $hidedesc, $hideref);
2740 $this->oldcopy = clone $this;
2741 $this->statut = $status;
2743 $this->date_signature = $date_signature;
2744 $this->note_private = $newprivatenote;
2746 if (!$notrigger && empty($error)) {
2748 $result = $this->call_trigger($triggerName, $user);
2756 $this->db->commit();
2759 foreach ($this->errors as $errmsg) {
2760 dol_syslog(__METHOD__.
' Error: '.$errmsg, LOG_ERR);
2761 $this->error .= ($this->error ?
', '.$errmsg : $errmsg);
2763 if (!empty($this->oldcopy)) {
2764 $this->statut = $this->oldcopy->status;
2765 $this->
status = $this->oldcopy->status;
2766 $this->date_signature = $this->oldcopy->date_signature;
2767 $this->note_private = $this->oldcopy->note_private;
2770 $this->db->rollback();
2774 $this->error = $this->db->lasterror();
2775 $this->db->rollback();
2790 global $conf, $langs;
2797 $triggerName =
'PROPAL_CLASSIFY_BILLED';
2803 $sql =
'UPDATE '.MAIN_DB_PREFIX.$this->table_element;
2804 $sql .=
" SET fk_statut = ".self::STATUS_BILLED.
", ";
2805 $sql .=
" note_private = '".$this->db->escape($newprivatenote).
"', date_cloture='".$this->db->idate($now).
"', fk_user_cloture=".((int) $user->id);
2806 $sql .=
' WHERE rowid = '.((int) $this->
id).
' AND fk_statut = '.((int) self::STATUS_SIGNED);
2809 $resql = $this->db->query($sql);
2811 $this->errors[] = $this->db->error();
2814 $num = $this->db->affected_rows($resql);
2822 $outputlangs = $langs;
2824 $outputlangs =
new Translate(
"", $conf);
2825 $newlang = (
GETPOST(
'lang_id',
'aZ09') ?
GETPOST(
'lang_id',
'aZ09') : $this->thirdparty->default_lang);
2826 $outputlangs->setDefaultLang($newlang);
2835 $this->
generateDocument($modelpdf, $outputlangs, $hidedetails, $hidedesc, $hideref);
2838 $this->oldcopy = clone $this;
2841 $this->date_cloture = $now;
2842 $this->note_private = $newprivatenote;
2845 if (!$notrigger && empty($error)) {
2847 $result = $this->call_trigger($triggerName, $user);
2855 $this->db->commit();
2858 foreach ($this->errors as $errmsg) {
2859 dol_syslog(__METHOD__.
' Error: '.$errmsg, LOG_ERR);
2860 $this->error .= ($this->error ?
', '.$errmsg : $errmsg);
2862 $this->db->rollback();
2879 $sql =
"UPDATE ". MAIN_DB_PREFIX . $this->table_element;
2880 $sql .=
" SET fk_statut = " . self::STATUS_CANCELED .
",";
2881 $sql .=
" fk_user_modif = " . ((int) $user->id);
2882 $sql .=
" WHERE rowid = " . ((int) $this->
id);
2884 dol_syslog(get_class($this).
"::cancel", LOG_DEBUG);
2885 if ($this->db->query($sql)) {
2887 $result = $this->call_trigger(
'PROPAL_CANCEL', $user);
2896 $this->db->commit();
2899 foreach ($this->errors as $errmsg) {
2900 dol_syslog(get_class($this).
"::cancel ".$errmsg, LOG_ERR);
2901 $this->error .= ($this->error ?
', '.$errmsg : $errmsg);
2903 $this->db->rollback();
2907 $this->error = $this->db->error();
2908 $this->db->rollback();
2927 if ($this->
status <= self::STATUS_DRAFT) {
2931 dol_syslog(get_class($this).
"::setDraft", LOG_DEBUG);
2935 $sql =
"UPDATE ".MAIN_DB_PREFIX.$this->table_element;
2936 $sql .=
" SET fk_statut = ".self::STATUS_DRAFT;
2937 $sql .=
", online_sign_ip = NULL , online_sign_name = NULL";
2938 $sql .=
" WHERE rowid = ".((int) $this->
id);
2940 $resql = $this->db->query($sql);
2942 $this->errors[] = $this->db->error();
2947 $this->oldcopy = clone $this;
2950 if (!$notrigger && empty($error)) {
2952 $result = $this->call_trigger(
'PROPAL_MODIFY', $user);
2963 $this->db->commit();
2966 foreach ($this->errors as $errmsg) {
2967 dol_syslog(__METHOD__.
' Error: '.$errmsg, LOG_ERR);
2968 $this->error .= ($this->error ?
', '.$errmsg : $errmsg);
2970 $this->db->rollback();
2990 public function liste_array($shortlist = 0, $draft = 0, $notcurrentuser = 0, $socid = 0, $limit = 0, $offset = 0, $sortfield =
'p.datep', $sortorder =
'DESC')
2997 $sql =
"SELECT s.rowid, s.nom as name, s.client,";
2998 $sql .=
" p.rowid as propalid, p.fk_statut, p.total_ht, p.ref, p.remise, ";
2999 $sql .=
" p.datep as dp, p.fin_validite as datelimite";
3000 $sql .=
" FROM ".MAIN_DB_PREFIX.
"societe as s, ".MAIN_DB_PREFIX.$this->table_element.
" as p, ".MAIN_DB_PREFIX.
"c_propalst as c";
3001 $sql .=
" WHERE p.entity IN (".getEntity(
'propal').
")";
3002 $sql .=
" AND p.fk_soc = s.rowid";
3003 $sql .=
" AND p.fk_statut = c.id";
3007 if (empty($user->socid) && !$user->hasRight(
'societe',
'client',
'voir')) {
3008 $search_sale = $user->id;
3011 if ($search_sale && $search_sale !=
'-1') {
3012 if ($search_sale == -2) {
3013 $sql .=
" AND NOT EXISTS (SELECT sc.fk_soc FROM ".MAIN_DB_PREFIX.
"societe_commerciaux as sc WHERE sc.fk_soc = p.fk_soc)";
3014 } elseif ($search_sale > 0) {
3015 $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).
")";
3020 $sql .=
" AND p.fk_soc = ".((int) $socid);
3023 $sql .=
" AND p.fk_statut = ".((int) self::STATUS_DRAFT);
3025 if ($notcurrentuser > 0) {
3026 $sql .=
" AND p.fk_user_author <> ".((int) $user->id);
3028 $sql .= $this->db->order($sortfield, $sortorder);
3029 $sql .= $this->db->plimit($limit, $offset);
3031 $result = $this->db->query($sql);
3033 $num = $this->db->num_rows($result);
3037 $obj = $this->db->fetch_object($result);
3039 if ($shortlist == 1) {
3040 $ga[$obj->propalid] = $obj->ref;
3041 } elseif ($shortlist == 2) {
3042 $ga[$obj->propalid] = $obj->ref.
' ('.$obj->name.
')';
3044 $ga[$i][
'id'] = $obj->propalid;
3045 $ga[$i][
'ref'] = $obj->ref;
3046 $ga[$i][
'name'] = $obj->name;
3080 $linkedInvoices = array();
3083 foreach ($this->linkedObjectsIds as $objecttype => $objectid) {
3086 foreach ($objectid as $key =>
$object) {
3088 if ($objecttype ==
'facture') {
3093 foreach ($this->linkedObjectsIds as $subobjecttype => $subobjectid) {
3094 foreach ($subobjectid as $subkey => $subobject) {
3095 if ($subobjecttype ==
'facture') {
3096 $linkedInvoices[] = $subobject;
3104 if (count($linkedInvoices) > 0) {
3105 $sql =
"SELECT rowid as facid, ref, total_ht as total, datef as df, fk_user_author, fk_statut, paye";
3106 $sql .=
" FROM ".MAIN_DB_PREFIX.
"facture";
3107 $sql .=
" WHERE rowid IN (".$this->db->sanitize(implode(
',', $linkedInvoices)).
")";
3109 dol_syslog(get_class($this).
"::InvoiceArrayList", LOG_DEBUG);
3110 $resql = $this->db->query($sql);
3113 $tab_sqlobj = array();
3114 $nump = $this->db->num_rows($resql);
3115 for ($i = 0; $i < $nump; $i++) {
3116 $sqlobj = $this->db->fetch_object($resql);
3117 $tab_sqlobj[] = $sqlobj;
3119 $this->db->free($resql);
3121 $nump = count($tab_sqlobj);
3125 while ($i < $nump) {
3126 $obj = array_shift($tab_sqlobj);
3149 public function delete($user, $notrigger = 0)
3152 require_once DOL_DOCUMENT_ROOT.
'/core/lib/files.lib.php';
3160 $result = $this->call_trigger(
'PROPAL_DELETE', $user);
3169 $sql =
"DELETE FROM ".MAIN_DB_PREFIX.
"categorie_propal";
3170 $sql .=
" WHERE fk_propal = ".((int) $this->
id);
3172 $result = $this->db->query($sql);
3175 $this->error = $this->db->lasterror();
3176 $this->errors[] = $this->error;
3181 if (!$error && !empty($this->table_element_line)) {
3182 $tabletodelete = $this->table_element_line;
3183 $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).
")";
3184 $sql =
"DELETE FROM ".MAIN_DB_PREFIX.$tabletodelete.
" WHERE ".$this->fk_element.
" = ".((int) $this->
id);
3185 if (!$this->db->query($sqlef) || !$this->db->query($sql)) {
3187 $this->error = $this->db->lasterror();
3188 $this->errors[] = $this->error;
3189 dol_syslog(get_class($this).
"::delete error ".$this->error, LOG_ERR);
3214 dol_syslog(get_class($this).
"::delete error ".$this->error, LOG_ERR);
3220 $sql =
"DELETE FROM ".MAIN_DB_PREFIX.$this->table_element.
" WHERE rowid = ".((int) $this->
id);
3221 $res = $this->db->query($sql);
3224 $this->error = $this->db->lasterror();
3225 $this->errors[] = $this->error;
3226 dol_syslog(get_class($this).
"::delete error ".$this->error, LOG_ERR);
3242 if ($conf->propal->multidir_output[$this->entity] && !empty($this->
ref)) {
3243 $dir = $conf->propal->multidir_output[$this->entity].
"/".$ref;
3244 $file = $dir.
"/".$ref.
".pdf";
3245 if (file_exists($file)) {
3249 $this->error =
'ErrorFailToDeleteFile';
3250 $this->errors[] = $this->error;
3251 $this->db->rollback();
3255 if (file_exists($dir)) {
3258 $this->error =
'ErrorFailToDeleteDir';
3259 $this->errors[] = $this->error;
3260 $this->db->rollback();
3268 dol_syslog(get_class($this).
"::delete ".$this->
id.
" by ".$user->id, LOG_DEBUG);
3269 $this->db->commit();
3272 $this->db->rollback();
3289 if ($this->
status >= self::STATUS_DRAFT) {
3294 $sql =
'UPDATE '.MAIN_DB_PREFIX.$this->table_element;
3295 $sql .=
' SET fk_availability = '.((int) $availability_id);
3296 $sql .=
' WHERE rowid='.((int) $this->
id);
3298 dol_syslog(__METHOD__.
' availability('.$availability_id.
')', LOG_DEBUG);
3299 $resql = $this->db->query($sql);
3301 $this->errors[] = $this->db->error();
3306 $this->oldcopy = clone $this;
3307 $this->availability_id = $availability_id;
3310 if (!$notrigger && empty($error)) {
3312 $result = $this->call_trigger(
'PROPAL_MODIFY', $user);
3320 $this->db->commit();
3323 foreach ($this->errors as $errmsg) {
3324 dol_syslog(__METHOD__.
' Error: '.$errmsg, LOG_ERR);
3325 $this->error .= ($this->error ?
', '.$errmsg : $errmsg);
3327 $this->db->rollback();
3331 $error_str =
'Propal status do not meet requirement '.$this->status;
3333 $this->error = $error_str;
3334 $this->errors[] = $this->error;
3353 if ($this->
status >= self::STATUS_DRAFT) {
3358 $sql =
'UPDATE '.MAIN_DB_PREFIX.$this->table_element;
3359 $sql .=
' SET fk_input_reason = '.((int) $demand_reason_id);
3360 $sql .=
' WHERE rowid='.((int) $this->
id);
3362 dol_syslog(__METHOD__.
' demand_reason('.$demand_reason_id.
')', LOG_DEBUG);
3363 $resql = $this->db->query($sql);
3365 $this->errors[] = $this->db->error();
3370 $this->oldcopy = clone $this;
3371 $this->demand_reason_id = $demand_reason_id;
3374 if (!$notrigger && empty($error)) {
3376 $result = $this->call_trigger(
'PROPAL_MODIFY', $user);
3384 $this->db->commit();
3387 foreach ($this->errors as $errmsg) {
3388 dol_syslog(__METHOD__.
' Error: '.$errmsg, LOG_ERR);
3389 $this->error .= ($this->error ?
', '.$errmsg : $errmsg);
3391 $this->db->rollback();
3395 $error_str =
'Propal status do not meet requirement '.$this->status;
3397 $this->error = $error_str;
3398 $this->errors[] = $this->error;
3412 $sql =
"SELECT c.rowid, ";
3413 $sql .=
" c.datec, c.date_valid as datev, c.date_signature, c.date_cloture,";
3414 $sql .=
" c.fk_user_author, c.fk_user_valid, c.fk_user_signature, c.fk_user_cloture";
3415 $sql .=
" FROM ".MAIN_DB_PREFIX.$this->table_element.
" as c";
3416 $sql .=
" WHERE c.rowid = ".((int) $id);
3418 $result = $this->db->query($sql);
3421 if ($this->db->num_rows($result)) {
3422 $obj = $this->db->fetch_object($result);
3424 $this->
id = $obj->rowid;
3426 $this->date_creation = $this->db->jdate($obj->datec);
3427 $this->date_validation = $this->db->jdate($obj->datev);
3428 $this->date_signature = $this->db->jdate($obj->date_signature);
3429 $this->date_cloture = $this->db->jdate($obj->date_cloture);
3431 $this->user_creation_id = $obj->fk_user_author;
3432 $this->user_validation_id = $obj->fk_user_valid;
3434 if ($obj->fk_user_signature) {
3435 $user_signature =
new User($this->db);
3436 $user_signature->fetch($obj->fk_user_signature);
3437 $this->user_signature = $user_signature;
3440 $this->user_closing_id = $obj->fk_user_cloture;
3442 $this->db->free($result);
3471 global $hookmanager;
3474 if (empty($this->labelStatus) || empty($this->labelStatusShort)) {
3476 $langs->load(
"propal");
3477 $this->labelStatus[-1] = $langs->transnoentitiesnoconv(
"PropalStatusCanceled");
3478 $this->labelStatus[0] = $langs->transnoentitiesnoconv(
"PropalStatusDraft");
3479 $this->labelStatus[1] = $langs->transnoentitiesnoconv(
"PropalStatusValidated");
3480 $this->labelStatus[2] = $langs->transnoentitiesnoconv(
"PropalStatusSigned");
3481 $this->labelStatus[3] = $langs->transnoentitiesnoconv(
"PropalStatusNotSigned");
3482 $this->labelStatus[4] = $langs->transnoentitiesnoconv(
"PropalStatusBilled");
3483 $this->labelStatusShort[-1] = $langs->transnoentitiesnoconv(
"PropalStatusCanceledShort");
3484 $this->labelStatusShort[0] = $langs->transnoentitiesnoconv(
"PropalStatusDraftShort");
3485 $this->labelStatusShort[1] = $langs->transnoentitiesnoconv(
"PropalStatusValidatedShort");
3486 $this->labelStatusShort[2] = $langs->transnoentitiesnoconv(
"PropalStatusSignedShort");
3487 $this->labelStatusShort[3] = $langs->transnoentitiesnoconv(
"PropalStatusNotSignedShort");
3488 $this->labelStatusShort[4] = $langs->transnoentitiesnoconv(
"PropalStatusBilledShort");
3492 if ($status == self::STATUS_CANCELED) {
3493 $statusType =
'status9';
3494 } elseif ($status == self::STATUS_DRAFT) {
3495 $statusType =
'status0';
3496 } elseif ($status == self::STATUS_VALIDATED) {
3497 $statusType =
'status1';
3498 } elseif ($status == self::STATUS_SIGNED) {
3499 $statusType =
'status4';
3500 } elseif ($status == self::STATUS_NOTSIGNED) {
3501 $statusType =
'status9';
3502 } elseif ($status == self::STATUS_BILLED) {
3503 $statusType =
'status6';
3506 $parameters = array(
'status' => $status,
'mode' => $mode);
3507 $reshook = $hookmanager->executeHooks(
'LibStatut', $parameters, $this);
3510 return $hookmanager->resPrint;
3513 return dolGetStatus($this->labelStatus[$status], $this->labelStatusShort[$status],
'', $statusType, $mode);
3528 global $conf, $langs, $hookmanager;
3530 $sql =
"SELECT p.rowid, p.ref, p.datec as datec, p.fin_validite as datefin, p.total_ht";
3531 $sql .=
" FROM ".MAIN_DB_PREFIX.$this->table_element.
" as p";
3532 $sql .=
" WHERE p.entity IN (".getEntity(
'propal').
")";
3533 if ($mode ==
'opened') {
3534 $sql .=
" AND p.fk_statut = ".self::STATUS_VALIDATED;
3536 if ($mode ==
'signed') {
3537 $sql .=
" AND p.fk_statut = ".self::STATUS_SIGNED;
3541 if (empty($user->socid) && !$user->hasRight(
'societe',
'client',
'voir')) {
3542 $search_sale = $user->id;
3545 if ($search_sale && $search_sale !=
'-1') {
3546 if ($search_sale == -2) {
3547 $sql .=
" AND NOT EXISTS (SELECT sc.fk_soc FROM ".MAIN_DB_PREFIX.
"societe_commerciaux as sc WHERE sc.fk_soc = p.fk_soc)";
3548 } elseif ($search_sale > 0) {
3549 $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).
")";
3553 $sql .=
" AND p.fk_soc = ".((int) $user->socid);
3556 $parameters = array(
'socid' => $user->socid);
3557 $reshook = $hookmanager->executeHooks(
'printFieldListWhere', $parameters, $this);
3558 $sql .= $hookmanager->resPrint;
3560 $resql = $this->db->query($sql);
3562 $langs->load(
"propal");
3567 $label = $labelShort =
'';
3568 if ($mode ==
'opened') {
3571 $label = $langs->transnoentitiesnoconv(
"PropalsToClose");
3572 $labelShort = $langs->transnoentitiesnoconv(
"ToAcceptRefuse");
3574 if ($mode ==
'signed') {
3577 $label = $langs->trans(
"PropalsToBill");
3578 $labelShort = $langs->trans(
"ToBill");
3582 $response->warning_delay = $delay_warning / 60 / 60 / 24;
3583 $response->label = $label;
3584 $response->labelShort = $labelShort;
3585 $response->url = DOL_URL_ROOT.
'/comm/propal/list.php?search_status='.$status.
'&mainmenu=commercial&leftmenu=propals';
3586 $response->url_late = DOL_URL_ROOT.
'/comm/propal/list.php?search_option=late&mainmenu=commercial&leftmenu=propals&sortfield=p.datep&sortorder=asc';
3590 while ($obj = $this->db->fetch_object($resql)) {
3591 $response->nbtodo++;
3592 $response->total += $obj->total_ht;
3594 if ($mode ==
'opened') {
3595 $datelimit = $this->db->jdate($obj->datefin);
3596 if ($datelimit < ($now - $delay_warning)) {
3597 $response->nbtodolate++;
3606 $this->error = $this->db->error();
3622 global $conf, $langs;
3627 $sql =
"SELECT rowid";
3628 $sql .=
" FROM ".MAIN_DB_PREFIX.
"product";
3629 $sql .=
" WHERE entity IN (".getEntity(
'product').
")";
3630 if (array_key_exists(
'tosell', $param)) {
3631 $sql .=
" AND tosell = ".((int) $param[
'tosell']);
3633 $sql .= $this->db->plimit(100);
3635 $resql = $this->db->query($sql);
3637 $num_prods = $this->db->num_rows($resql);
3639 while ($i < $num_prods) {
3641 $row = $this->db->fetch_row($resql);
3642 $prodids[$i] = $row[0];
3648 $this->
ref =
'SPECIMEN';
3649 $this->ref_customer =
'NEMICEPS';
3650 $this->ref_client =
'NEMICEPS';
3651 $this->specimen = 1;
3653 $this->
date = time();
3654 $this->fin_validite = $this->
date + 3600 * 24 * 30;
3655 $this->cond_reglement_id = 1;
3656 $this->cond_reglement_code =
'RECEP';
3657 $this->mode_reglement_id = 7;
3658 $this->mode_reglement_code =
'CHQ';
3659 $this->availability_id = 1;
3660 $this->availability_code =
'AV_NOW';
3661 $this->demand_reason_id = 1;
3662 $this->demand_reason_code =
'SRC_00';
3663 $this->note_public =
'This is a comment (public)';
3664 $this->note_private =
'This is a comment (private)';
3666 $this->multicurrency_tx = 1;
3672 while ($xnbp < $nbp) {
3674 $line->desc = $langs->trans(
"Description").
" ".$xnbp;
3676 $line->subprice = 100;
3678 $line->localtax1_tx = 0;
3679 $line->localtax2_tx = 0;
3681 $line->total_ht = 50;
3682 $line->total_ttc = 60;
3683 $line->total_tva = 10;
3684 $line->remise_percent = 50;
3686 $line->total_ht = 100;
3687 $line->total_ttc = 120;
3688 $line->total_tva = 20;
3689 $line->remise_percent = 00;
3692 if ($num_prods > 0) {
3693 $prodid = mt_rand(1, $num_prods);
3694 $line->fk_product = $prodids[$prodid];
3695 $line->product_ref =
'SPECIMEN';
3698 $this->lines[$xnbp] = $line;
3700 $this->total_ht += $line->total_ht;
3701 $this->total_tva += $line->total_tva;
3702 $this->total_ttc += $line->total_ttc;
3717 global $user, $hookmanager;
3719 $this->nb = array();
3721 $sql =
"SELECT count(p.rowid) as nb";
3722 $sql .=
" FROM ".MAIN_DB_PREFIX.$this->table_element.
" as p";
3723 $sql .=
" LEFT JOIN ".MAIN_DB_PREFIX.
"societe as s ON p.fk_soc = s.rowid";
3724 $sql .=
" WHERE p.entity IN (".getEntity(
'propal').
")";
3728 if (empty($user->socid) && !$user->hasRight(
'societe',
'client',
'voir')) {
3729 $search_sale = $user->id;
3732 if ($search_sale && $search_sale !=
'-1') {
3733 if ($search_sale == -2) {
3734 $sql .=
" AND NOT EXISTS (SELECT sc.fk_soc FROM ".MAIN_DB_PREFIX.
"societe_commerciaux as sc WHERE sc.fk_soc = p.fk_soc)";
3735 } elseif ($search_sale > 0) {
3736 $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).
")";
3741 $parameters = array();
3742 $hookmanager->executeHooks(
'printFieldListWhere', $parameters, $this);
3743 $sql .= $hookmanager->resPrint;
3744 $resql = $this->db->query($sql);
3747 while ($obj = $this->db->fetch_object($resql)) {
3748 $this->nb[
"proposals"] = $obj->nb;
3750 $this->db->free($resql);
3754 $this->error = $this->db->error();
3767 public function getNextNumRef($soc)
3769 global $conf, $langs;
3770 $langs->load(
"propal");
3774 if (!empty($classname)) {
3777 $file = $classname.
".php";
3780 $dirmodels = array_merge(array(
'/'), (array) $conf->modules_parts[
'models']);
3781 foreach ($dirmodels as $reldir) {
3785 $mybool = ((bool) @include_once $dir.$file) || $mybool;
3793 $obj =
new $classname();
3794 '@phan-var-force ModeleNumRefPropales $obj';
3797 $numref = $obj->getNextValue($soc, $this);
3799 if ($numref !=
"") {
3802 $this->error = $obj->error;
3807 $langs->load(
"errors");
3808 print $langs->trans(
"Error").
" ".$langs->trans(
"ErrorModuleSetupNotComplete", $langs->transnoentitiesnoconv(
"Proposal"));
3821 global $conf, $langs, $user;
3823 $langs->load(
'propal');
3825 $nofetch = !empty($params[
'nofetch']);
3828 return [
'optimize' => $langs->trans(
"Proposal")];
3830 if ($user->hasRight(
'propal',
'lire')) {
3831 $datas[
'picto'] =
img_picto(
'', $this->picto,
'', 0, 0, 0,
'',
'paddingrightonly').
'<u>'.$langs->trans(
"Proposal").
'</u>';
3832 if (isset($this->
status)) {
3833 $datas[
'status'] =
' '.$this->getLibStatut(5);
3835 if (!empty($this->
ref)) {
3836 $datas[
'ref'] =
'<br><b>'.$langs->trans(
'Ref').
':</b> '.$this->ref;
3839 $langs->load(
'companies');
3840 if (empty($this->thirdparty)) {
3843 $datas[
'customer'] =
'<br><b>'.$langs->trans(
'Customer').
':</b> '.$this->thirdparty->getNomUrl(1,
'', 0, 1);
3845 if (!empty($this->ref_customer)) {
3846 $datas[
'refcustomer'] =
'<br><b>'.$langs->trans(
'RefCustomer').
':</b> '.$this->ref_customer;
3849 $langs->load(
'project');
3850 if (is_null($this->project) || (is_object($this->project) && $this->project->isEmpty())) {
3852 if ($res > 0 && $this->project instanceof
Project) {
3853 $datas[
'project'] =
'<br><b>'.$langs->trans(
'Project').
':</b> '.$this->project->getNomUrl(1,
'', 0,
'1');
3857 if (!empty($this->total_ht)) {
3858 $datas[
'amountht'] =
'<br><b>'.$langs->trans(
'AmountHT').
':</b> '.
price($this->total_ht, 0, $langs, 0, -1, -1, $conf->currency);
3860 if (!empty($this->total_tva)) {
3861 $datas[
'vat'] =
'<br><b>'.$langs->trans(
'VAT').
':</b> '.
price($this->total_tva, 0, $langs, 0, -1, -1, $conf->currency);
3863 if (!empty($this->total_ttc)) {
3864 $datas[
'amountttc'] =
'<br><b>'.$langs->trans(
'AmountTTC').
':</b> '.
price($this->total_ttc, 0, $langs, 0, -1, -1, $conf->currency);
3866 if (!empty($this->
date)) {
3867 $datas[
'date'] =
'<br><b>'.$langs->trans(
'Date').
':</b> '.
dol_print_date($this->
date,
'day');
3869 if (!empty($this->date_signature)) {
3870 $datas[
'datesignature'] =
'<br><b>'.$langs->trans(
'DateSigning').
':</b> '.
dol_print_date($this->date_signature,
'day');
3872 if (!empty($this->delivery_date)) {
3873 $datas[
'deliverydate'] =
'<br><b>'.$langs->trans(
'DeliveryDate').
':</b> '.
dol_print_date($this->delivery_date,
'dayhour');
3891 public function getNomUrl($withpicto = 0, $option =
'', $get_params =
'', $notooltip = 0, $save_lastsearch_value = -1, $addlinktonotes = -1)
3893 global $langs, $conf, $user, $hookmanager;
3895 if (!empty($conf->dol_no_mouse_hover)) {
3902 'objecttype' => $this->element,
3903 'option' => $option,
3906 $classfortooltip =
'classfortooltip';
3909 $classfortooltip =
'classforajaxtooltip';
3910 $dataparams =
' data-params="'.dol_escape_htmltag(json_encode($params)).
'"';
3918 if ($user->hasRight(
'propal',
'lire')) {
3919 parse_str($get_params, $query);
3920 $query = array_merge($query, [
'id' => $this->
id]);
3921 if ($option ==
'') {
3922 $baseurl = DOL_URL_ROOT .
'/comm/propal/card.php';
3923 } elseif ($option ==
'compta') {
3924 $baseurl = DOL_URL_ROOT .
'/comm/propal/card.php';
3925 } elseif ($option ==
'expedition') {
3926 $baseurl = DOL_URL_ROOT .
'/expedition/propal.php';
3927 } elseif ($option ==
'document') {
3928 $baseurl = DOL_URL_ROOT .
'/comm/propal/document.php';
3931 if ($option !=
'nolink') {
3933 $add_save_lastsearch_values = ($save_lastsearch_value == 1 ? 1 : 0);
3934 if ($save_lastsearch_value == -1 && isset($_SERVER[
"PHP_SELF"]) && preg_match(
'/list\.php/', $_SERVER[
"PHP_SELF"])) {
3935 $add_save_lastsearch_values = 1;
3937 if ($add_save_lastsearch_values) {
3938 $query = array_merge($query, [
'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">' . $this->
getNomUrl() .
'</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 (is_object($this->thirdparty)) {
4124 $return .=
'<div class="info-box-ref tdoverflowmax150">'.$this->thirdparty->getNomUrl(1).
'</div>';
4126 $return .=
'<span class="info-box-label amount" title="'.$langs->trans(
"AmountHT").
'">'.
price($this->total_ht).
'</span>';
4127 if (!empty($arraydata[
'authorlink'])) {
4128 $return .=
' <span class="info-box-label">'.$arraydata[
'authorlink'].
'</span>';
4130 $return .=
'<br><div class="info-box-status">'.$this->getLibStatut(3).
'</div>';
4131 $return .=
'</div>';
4132 $return .=
'</div>';
4133 $return .=
'</div>';
4149 require_once DOL_DOCUMENT_ROOT.
'/categories/class/categorie.class.php';
4150 return parent::setCategoriesCommon($categories, Categorie::TYPE_PROPOSAL);
if(! $sortfield) if(! $sortorder) $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.
roundQtyToPackaging($qty, $packaging)
Round a quantity up to the next multiple of a packaging quantity (options PRODUCT_USE_CUSTOMER_PACKAG...
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
isLineOfObject($lineid)
Check that a line belongs to this object, using $this->table_element_line and $this->fk_element.
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)
checkActiveProductInLines($status='onsale')
Check if all products have the right status (on sale, on buy) called during validation of propal,...
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.
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.
initAsSpecimen($param=array())
Initialise an instance with random values.
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...
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.
setCategories($categories)
Sets object to supplied categories.
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.
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.
dol_now($mode='gmt')
Return date for now.
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.
dolBuildUrl($url, $params=[], $addtoken=false)
Return path of url.
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)
dol_sanitizeFileName($str, $newstr='_', $unaccent=1, $includequotes=0, $allowdash=0)
Clean a string to use it as a file name.
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.
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.
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...
getDolCurrency()
Return the main currency ('EUR', 'USD', ...)
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_date($time, $format='', $tzoutput='auto', $outputlangs=null, $encodetooutput=false, $decorate=0)
Output date in a string format according to outputlangs (or langs if not defined).
getDolGlobalBool($key, $default=false)
Return a Dolibarr global constant boolean value.
dol_print_error($db=null, $error='', $errors=null)
Displays error message system with all the information to facilitate the diagnosis and the escalation...
getDolGlobalString($key, $default='')
Return a Dolibarr global constant string value.
getWarningDelay($module, $parmlevel1, $parmlevel2='')
Return a warning delay You can use it like this: if (getWarningDelay('module', 'paramlevel1')) It rep...
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 rate, 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.
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.
if(getDolGlobalString( 'TAKEPOS_SHOW_CUSTOMER')) print $langs trans('Date')." left Label right Qty right Price right TotalHT right TotalTTC right right right right right right right right right centpercent right TotalHT right n right VAT right n right TotalVAT right n No sujeto a RE IRPF right TotalLT1 right n right TotalLT2 right n right TotalTTC right n takeposcustomercurrency takeposcustomercurrency takeposcustomercurrency takeposcustomercurrency right TotalTTC takeposcustomercurrency right takeposcustomercurrency n right PaymentTypeShortLIQ right SELECT p pos_change as p datep as date