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) {
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->localtax1_tx = $remise->localtax1_tx;
572 $line->localtax1_type = $remise->localtax1_type;
573 $line->localtax2_tx = $remise->localtax1_tx;
574 $line->localtax2_type = $remise->localtax1_type;
575 $line->subprice = -(float) $remise->amount_ht;
576 $line->fk_product = 0;
578 $line->remise_percent = 0;
580 $line->info_bits = 2;
582 $line->total_ht = -(float) $remise->amount_ht;
583 $line->total_tva = -(float) $remise->amount_tva;
584 $line->total_ttc = -(float) $remise->amount_ttc;
585 $line->total_localtax1 = -(float) $remise->total_localtax1;
586 $line->total_localtax2 = -(float) $remise->total_localtax2;
588 $result = $line->insert();
595 $this->db->rollback();
600 $this->db->rollback();
604 $this->db->rollback();
654 $remise_percent = 0.0,
655 $price_base_type =
'HT',
667 $array_options = array(),
672 $fk_remise_except = 0,
673 $noupdateafterinsertline = 0
677 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);
679 if ($this->
status == self::STATUS_DRAFT) {
680 include_once DOL_DOCUMENT_ROOT.
'/core/lib/price.lib.php';
683 if (empty($remise_percent)) {
689 if (empty($info_bits)) {
695 if (empty($fk_parent_line) || $fk_parent_line < 0) {
699 $remise_percent =
price2num($remise_percent);
702 $pu_ht_devise =
price2num($pu_ht_devise);
704 if (!preg_match(
'/\((.*)\)/', (
string) $txtva)) {
710 if ($price_base_type ==
'HT') {
722 $langs->load(
"errors");
723 $this->error = $langs->trans(
'ErrorStartDateGreaterEnd');
729 $product_type = $type;
730 if (!empty($fk_product) && $fk_product > 0) {
731 $product =
new Product($this->db);
732 $result = $product->fetch($fk_product);
733 $product_type = $product->type;
735 if ($product->isStockManaged() && $product->stock_reel < $qty &&
getDolGlobalString(
'STOCK_MUST_BE_ENOUGH_FOR_PROPOSAL')) {
736 $langs->load(
"errors");
737 $this->error = $langs->trans(
'ErrorStockIsNotEnoughToAddProductOnProposal', $product->ref);
738 $this->db->rollback();
750 $tmpproduct =
new Product($this->db);
751 $result = $tmpproduct->fetch($fk_product);
753 if ($newqty != $qty) {
755 setEventMessages($langs->trans(
'QtyRecalculatedWithPackaging'),
null,
'warnings');
762 if (preg_match(
'/\((.*)\)/', $txtva, $reg)) {
763 $vat_src_code = $reg[1];
764 $txtva = preg_replace(
'/\s*\(.*\)/',
'', $txtva);
767 $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);
769 $total_ht = $tabprice[0];
770 $total_tva = $tabprice[1];
771 $total_ttc = $tabprice[2];
772 $total_localtax1 = $tabprice[9];
773 $total_localtax2 = $tabprice[10];
774 $pu_ht = $tabprice[3];
775 $pu_tva = $tabprice[4];
776 $pu_ttc = $tabprice[5];
779 $multicurrency_total_ht = $tabprice[16];
780 $multicurrency_total_tva = $tabprice[17];
781 $multicurrency_total_ttc = $tabprice[18];
782 $pu_ht_devise = $tabprice[19];
786 if (empty($ranktouse) || $ranktouse == -1) {
787 $rangmax = $this->
line_max($fk_parent_line);
788 $ranktouse = $rangmax + 1;
794 $this->line->context = $this->context;
796 $this->line->fk_propal = $this->id;
797 $this->line->label = $label;
798 $this->line->desc = $desc;
799 $this->line->qty = (float) $qty;
801 $this->line->vat_src_code = $vat_src_code;
802 $this->line->tva_tx = $txtva;
803 $this->line->localtax1_tx = ($total_localtax1 ? $localtaxes_type[1] : 0);
804 $this->line->localtax2_tx = ($total_localtax2 ? $localtaxes_type[3] : 0);
805 $this->line->localtax1_type = empty($localtaxes_type[0]) ?
'' : $localtaxes_type[0];
806 $this->line->localtax2_type = empty($localtaxes_type[2]) ?
'' : $localtaxes_type[2];
807 $this->line->fk_product = $fk_product;
808 $this->line->product_type = $type;
809 $this->line->fk_remise_except = $fk_remise_except;
810 $this->line->remise_percent = $remise_percent;
811 $this->line->subprice = (float) $pu_ht;
813 $this->line->subprice_ttc = ($price_base_type ===
'TTC') ? (
float) $pu_ttc : 0;
814 $this->line->rang = $ranktouse;
815 $this->line->info_bits = $info_bits;
816 $this->line->total_ht = (float) $total_ht;
817 $this->line->total_tva = (float) $total_tva;
818 $this->line->total_localtax1 = (float) $total_localtax1;
819 $this->line->total_localtax2 = (float) $total_localtax2;
820 $this->line->total_ttc = (float) $total_ttc;
821 $this->line->special_code = $special_code;
822 $this->line->fk_parent_line = $fk_parent_line;
823 $this->line->fk_unit = $fk_unit;
826 $this->line->date_end = $date_end;
828 $this->line->fk_fournprice = $fk_fournprice;
829 $this->line->pa_ht = $pa_ht;
831 $this->line->origin_id = $origin_id;
832 $this->line->origin = $origin;
835 $this->line->fk_multicurrency = $this->fk_multicurrency;
836 $this->line->multicurrency_code = $this->multicurrency_code;
837 $this->line->multicurrency_subprice = (float) $pu_ht_devise;
838 $this->line->multicurrency_total_ht = (float) $multicurrency_total_ht;
839 $this->line->multicurrency_total_tva = (float) $multicurrency_total_tva;
840 $this->line->multicurrency_total_ttc = (float) $multicurrency_total_ttc;
843 if (empty($qty) && empty($special_code)) {
844 $this->line->special_code = 3;
847 if (is_array($array_options) && count($array_options) > 0) {
848 $this->line->array_options = $array_options;
851 $result = $this->line->insert();
853 if (!isset($this->context[
'createfromclone'])) {
854 if (!empty($fk_parent_line)) {
857 } elseif ($ranktouse > 0 && $ranktouse <= count($this->lines)) {
859 $linecount = count($this->lines);
860 for ($ii = $ranktouse; $ii <= $linecount; $ii++) {
865 $this->lines[] = $this->line;
868 foreach ($this->lines as $tmpline) {
869 if ($tmpline->id == $origin_id && $tmpline->element == $origin) {
870 $this->line->extraparams = $tmpline->extraparams;
871 $this->line->setExtraParameters();
877 if (empty($noupdateafterinsertline)) {
883 return $this->line->id;
885 $this->error = $this->db->error();
886 $this->db->rollback();
891 $this->db->rollback();
895 dol_syslog(get_class($this).
"::addline status of proposal must be Draft to allow use of ->addline()", LOG_ERR);
930 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)
935 $this->error =
'ErrorLineIDDoesNotMatchWithObjectID';
939 dol_syslog(get_class($this).
"::updateLine rowid=$rowid, pu=$pu, qty=$qty, remise_percent=$remise_percent,
940 txtva=$txtva, desc=".
dol_trunc($desc, 16).
", 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");
941 include_once DOL_DOCUMENT_ROOT.
'/core/lib/price.lib.php';
944 $remise_percent =
price2num($remise_percent);
947 $pu_ht_devise =
price2num($pu_ht_devise);
948 if (!preg_match(
'/\((.*)\)/', (
string) $txtva)) {
954 if (empty($qty) && empty($special_code)) {
957 if (!empty($qty) && $special_code == 3) {
965 $langs->load(
"errors");
966 $this->error = $langs->trans(
'ErrorStartDateGreaterEnd');
970 if ($this->
status == self::STATUS_DRAFT) {
982 if (preg_match(
'/\((.*)\)/', $txtva, $reg)) {
983 $vat_src_code = $reg[1];
984 $txtva = preg_replace(
'/\s*\(.*\)/',
'', $txtva);
993 if ($tmpline->fetch($rowid) > 0) {
995 if ($newqty != $qty) {
997 setEventMessages($langs->trans(
'QtyRecalculatedWithPackaging'),
null,
'warnings');
1002 $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);
1003 $total_ht = $tabprice[0];
1004 $total_tva = $tabprice[1];
1005 $total_ttc = $tabprice[2];
1006 $total_localtax1 = $tabprice[9];
1007 $total_localtax2 = $tabprice[10];
1008 $pu_ht = $tabprice[3];
1009 $pu_tva = $tabprice[4];
1010 $pu_ttc = $tabprice[5];
1013 $multicurrency_total_ht = $tabprice[16];
1014 $multicurrency_total_tva = $tabprice[17];
1015 $multicurrency_total_ttc = $tabprice[18];
1016 $pu_ht_devise = $tabprice[19];
1020 $line->fetch($rowid);
1022 $staticline = clone $line;
1024 $line->oldline = $staticline;
1025 $this->line = $line;
1026 $this->line->context = $this->context;
1027 $this->line->rang = $rang;
1030 if (!empty($fk_parent_line) && !empty($staticline->fk_parent_line) && $fk_parent_line != $staticline->fk_parent_line) {
1031 $rangmax = $this->
line_max($fk_parent_line);
1032 $this->line->rang = $rangmax + 1;
1036 $this->line->id = $rowid;
1037 $this->line->label = $label;
1038 $this->line->desc = $desc;
1039 $this->line->qty = $qty;
1040 $this->line->product_type = $type;
1041 $this->line->vat_src_code = $vat_src_code;
1042 $this->line->tva_tx = $txtva;
1043 $this->line->localtax1_tx = $txlocaltax1;
1044 $this->line->localtax2_tx = $txlocaltax2;
1045 $this->line->localtax1_type = empty($localtaxes_type[0]) ?
'' : $localtaxes_type[0];
1046 $this->line->localtax2_type = empty($localtaxes_type[2]) ?
'' : $localtaxes_type[2];
1047 $this->line->remise_percent = $remise_percent;
1048 $this->line->subprice = (float) $pu_ht;
1050 $this->line->subprice_ttc = ($price_base_type ===
'TTC') ? (
float) $pu_ttc : 0;
1051 $this->line->info_bits = $info_bits;
1053 $this->line->total_ht = (float) $total_ht;
1054 $this->line->total_tva = (float) $total_tva;
1055 $this->line->total_localtax1 = (float) $total_localtax1;
1056 $this->line->total_localtax2 = (float) $total_localtax2;
1057 $this->line->total_ttc = (float) $total_ttc;
1058 $this->line->special_code = $special_code;
1059 $this->line->fk_parent_line = $fk_parent_line;
1060 $this->line->skip_update_total = $skip_update_total;
1061 $this->line->fk_unit = $fk_unit;
1063 $this->line->fk_fournprice = $fk_fournprice;
1064 $this->line->pa_ht = $pa_ht;
1067 $this->line->date_end = $date_end;
1069 if (is_array($array_options) && count($array_options) > 0) {
1071 foreach ($array_options as $key => $value) {
1072 $this->line->array_options[$key] = $array_options[$key];
1077 $this->line->multicurrency_subprice = (float) $pu_ht_devise;
1078 $this->line->multicurrency_total_ht = (float) $multicurrency_total_ht;
1079 $this->line->multicurrency_total_tva = (float) $multicurrency_total_tva;
1080 $this->line->multicurrency_total_ttc = (float) $multicurrency_total_ttc;
1082 $result = $this->line->update($notrigger);
1085 if (!empty($fk_parent_line)) {
1095 $this->db->commit();
1099 $this->db->rollback();
1103 dol_syslog(get_class($this).
"::updateline Erreur -2 Propal en mode incompatible pour cette action");
1120 if ($this->
status == self::STATUS_DRAFT) {
1125 $line->context = $this->context;
1128 $line->fetch($lineid);
1133 if ($id > 0 && (
int) $line->fk_propal !== (
int) $id) {
1134 $this->db->rollback();
1135 $this->error =
'ErrorLineIDDoesNotMatchWithObjectID';
1140 $staticline = clone $line;
1141 $line->oldline = $staticline;
1143 if ($line->delete($user) > 0) {
1146 $this->db->commit();
1150 $this->db->rollback();
1154 $this->error =
'ErrorDeleteLineNotAllowedByObjectStatus';
1168 public function create($user, $notrigger = 0)
1177 if (empty($this->
date)) {
1178 $this->
date = $this->datep;
1180 $this->fin_validite = $this->
date + ($this->duree_validite * 24 * 3600);
1181 if (empty($this->availability_id)) {
1182 $this->availability_id = 0;
1184 if (empty($this->demand_reason_id)) {
1185 $this->demand_reason_id = 0;
1189 if (!empty($this->multicurrency_code) && empty($this->multicurrency_tx)) {
1194 if (empty($this->fk_multicurrency)) {
1196 $this->fk_multicurrency = 0;
1197 $this->multicurrency_tx = 1;
1203 $delivery_date = $this->delivery_date;
1210 $this->error =
"Failed to fetch company";
1211 dol_syslog(get_class($this).
"::create ".$this->error, LOG_ERR);
1216 if (!empty($this->
ref)) {
1219 $this->error =
'ErrorRefAlreadyExists';
1220 dol_syslog(get_class($this).
"::create ".$this->error, LOG_WARNING);
1221 $this->db->rollback();
1226 if (empty($this->
date)) {
1227 $this->error =
"Date of proposal is required";
1228 dol_syslog(get_class($this).
"::create ".$this->error, LOG_ERR);
1236 $sql =
"INSERT INTO ".MAIN_DB_PREFIX.$this->table_element.
" (";
1239 $sql .=
", total_tva";
1240 $sql .=
", total_ttc";
1244 $sql .=
", fk_user_author";
1245 $sql .=
", note_private";
1246 $sql .=
", note_public";
1247 $sql .=
", model_pdf";
1248 $sql .=
", fin_validite";
1249 $sql .=
", fk_cond_reglement";
1250 $sql .=
", deposit_percent";
1251 $sql .=
", fk_mode_reglement";
1252 $sql .=
", fk_account";
1253 $sql .=
", ref_client";
1254 $sql .=
", ref_ext";
1255 $sql .=
", date_livraison";
1256 $sql .=
", fk_shipping_method";
1257 $sql .=
", fk_warehouse";
1258 $sql .=
", fk_availability";
1259 $sql .=
", fk_input_reason";
1260 $sql .=
", fk_projet";
1261 $sql .=
", fk_incoterms";
1262 $sql .=
", location_incoterms";
1264 $sql .=
", fk_multicurrency";
1265 $sql .=
", multicurrency_code";
1266 $sql .=
", multicurrency_tx";
1268 $sql .=
" VALUES (";
1269 $sql .= ((int) $this->socid);
1273 $sql .=
", '".$this->db->idate($this->
date).
"'";
1274 $sql .=
", '".$this->db->idate($now).
"'";
1275 $sql .=
", '(PROV)'";
1276 $sql .=
", ".($user->id > 0 ? ((int) $user->id) :
"NULL");
1277 $sql .=
", '".$this->db->escape($this->note_private).
"'";
1278 $sql .=
", '".$this->db->escape($this->note_public).
"'";
1279 $sql .=
", '".$this->db->escape($this->model_pdf).
"'";
1280 $sql .=
", ".($this->fin_validite !=
'' ?
"'".$this->db->idate($this->fin_validite).
"'" :
"NULL");
1281 $sql .=
", ".($this->cond_reglement_id > 0 ? ((int) $this->cond_reglement_id) :
'NULL');
1282 $sql .=
", ".(!empty($this->deposit_percent) ?
"'".$this->db->escape($this->deposit_percent).
"'" :
'NULL');
1283 $sql .=
", ".($this->mode_reglement_id > 0 ? ((int) $this->mode_reglement_id) :
'NULL');
1284 $sql .=
", ".($this->fk_account > 0 ? ((int) $this->fk_account) :
'NULL');
1285 $sql .=
", '".$this->db->escape((
string) $this->ref_client).
"'";
1286 $sql .=
", '".$this->db->escape((
string) $this->ref_ext).
"'";
1287 $sql .=
", ".(!
isDolTms($delivery_date) ?
"NULL" :
"'".$this->db->idate($delivery_date).
"'");
1288 $sql .=
", ".($this->shipping_method_id > 0 ? ((int) $this->shipping_method_id) :
'NULL');
1289 $sql .=
", ".($this->warehouse_id > 0 ? ((int) $this->warehouse_id) :
'NULL');
1290 $sql .=
", ".((int) $this->availability_id);
1291 $sql .=
", ".((int) $this->demand_reason_id);
1292 $sql .=
", ".($this->fk_project ? ((int) $this->fk_project) :
"null");
1293 $sql .=
", ".(int) $this->fk_incoterms;
1294 $sql .=
", '".$this->db->escape($this->location_incoterms).
"'";
1295 $sql .=
", ".(int) $this->entity;
1296 $sql .=
", ".(int) $this->fk_multicurrency;
1297 $sql .=
", '".$this->db->escape($this->multicurrency_code).
"'";
1298 $sql .=
", ".(float) $this->multicurrency_tx;
1301 dol_syslog(get_class($this).
"::create", LOG_DEBUG);
1302 $resql = $this->db->query($sql);
1304 $this->
id = $this->db->last_insert_id(MAIN_DB_PREFIX.$this->table_element);
1307 $this->
ref =
'(PROV'.$this->id.
')';
1308 $sql =
'UPDATE '.MAIN_DB_PREFIX.$this->table_element.
" SET ref='".$this->db->escape($this->
ref).
"' WHERE rowid=".((int) $this->
id);
1310 dol_syslog(get_class($this).
"::create", LOG_DEBUG);
1311 $resql = $this->db->query($sql);
1316 if (!empty($this->linkedObjectsIds) && empty($this->linked_objects)) {
1317 $this->linked_objects = $this->linkedObjectsIds;
1321 if (!$error && !empty($this->linked_objects) && is_array($this->linked_objects)) {
1322 foreach ($this->linked_objects as $origin => $tmp_origin_id) {
1323 if (is_array($tmp_origin_id)) {
1324 foreach ($tmp_origin_id as $origin_id) {
1327 $this->error = $this->db->lasterror();
1332 $origin_id = $tmp_origin_id;
1335 $this->error = $this->db->lasterror();
1346 $fk_parent_line = 0;
1347 $num = count($this->lines);
1349 for ($i = 0; $i < $num; $i++) {
1350 if (!is_object($this->lines[$i])) {
1352 $line = (object) $this->lines[$i];
1354 $line = $this->lines[$i];
1357 if (($line->product_type != 9 && empty($line->fk_parent_line)) || $line->product_type == 9) {
1358 $fk_parent_line = 0;
1361 $vatrate = $line->tva_tx;
1362 if ($line->vat_src_code && !preg_match(
'/\(.*\)/', $vatrate)) {
1363 $vatrate .=
' ('.$line->vat_src_code.
')';
1367 $originid = $line->origin_id;
1368 $origintype = empty($line->origin_type) ? $line->origin : $line->origin_type;
1370 $originid = $line->id;
1371 $origintype = $this->element;
1379 $line->localtax1_tx,
1380 $line->localtax2_tx,
1382 $line->remise_percent,
1386 $line->product_type,
1388 $line->special_code,
1390 $line->fk_fournprice,
1395 $line->array_options,
1397 (
string) $origintype,
1406 $this->error = $this->db->error;
1412 $line->id = $result;
1416 if ($result > 0 && !empty($line->extraparams)) {
1418 $newline->id = $result;
1419 $newline->extraparams = $line->extraparams;
1420 $newline->setExtraParameters();
1424 if ($result > 0 && $line->product_type == 9) {
1425 $fk_parent_line = $result;
1440 if (!$error && !$notrigger) {
1442 $result = $this->call_trigger(
'PROPAL_CREATE', $user);
1449 $this->error = $this->db->lasterror();
1454 $this->error = $this->db->lasterror();
1459 $this->db->commit();
1460 dol_syslog(get_class($this).
"::create done id=".$this->
id);
1463 $this->db->rollback();
1467 $this->error = $this->db->lasterror();
1468 $this->db->rollback();
1483 public function createFromClone(
User $user, $socid = 0, $forceentity =
null, $update_prices =
false, $update_desc =
false)
1494 $object =
new self($this->db);
1501 $objsoc =
new Societe($this->db);
1504 if (!empty($socid) && $socid !=
$object->socid) {
1505 if ($objsoc->fetch($socid) > 0) {
1507 $object->cond_reglement_id = (!empty($objsoc->cond_reglement_id) ? $objsoc->cond_reglement_id : 0);
1508 $object->deposit_percent = (!empty($objsoc->deposit_percent) ? $objsoc->deposit_percent :
null);
1509 $object->mode_reglement_id = (!empty($objsoc->mode_reglement_id) ? $objsoc->mode_reglement_id : 0);
1510 $object->fk_delivery_address = 0;
1533 $objsoc->fetch(
$object->socid);
1537 if ($update_prices ===
true || $update_desc ===
true) {
1538 if ($objsoc->id > 0 && !empty(
$object->lines)) {
1541 require_once DOL_DOCUMENT_ROOT .
'/product/class/productcustomerprice.class.php';
1544 foreach (
$object->lines as $line) {
1547 if ($line->fk_product > 0) {
1549 $res =
$prod->fetch($line->fk_product);
1551 if ($update_prices ===
true) {
1552 $pu_ht =
$prod->price;
1554 $remise_percent = $objsoc->remise_percent;
1557 $pu_ht =
$prod->multiprices[$objsoc->price_level];
1559 if (isset(
$prod->multiprices_tva_tx[$objsoc->price_level])) {
1560 $tva_tx = (
string)
$prod->multiprices_tva_tx[$objsoc->price_level];
1565 $filter = array(
't.fk_product' => (
string)
$prod->id,
't.fk_soc' => (
string) $objsoc->id);
1566 $result = $prodcustprice->fetchAll(
'',
'', 0, 0, $filter);
1569 if (count($prodcustprice->lines) > 0) {
1570 $date_now = (int) floor(
dol_now() / 86400) * 86400;
1571 foreach ($prodcustprice->lines as $k => $custprice_line) {
1572 if ($custprice_line->date_begin <= $date_now && (empty($custprice_line->date_end) || $date_now <= $custprice_line->date_end)) {
1573 $pu_ht =
price($custprice_line->price);
1574 $tva_tx = ($custprice_line->default_vat_code ? $custprice_line->tva_tx .
' (' . $custprice_line->default_vat_code .
' )' : $custprice_line->tva_tx);
1575 if ($custprice_line->default_vat_code && !preg_match(
'/\(.*\)/', $tva_tx)) {
1576 $tva_tx .=
' (' . $custprice_line->default_vat_code .
')';
1578 $remise_percent = $custprice_line->discount_percent;
1586 $line->subprice = $pu_ht;
1587 $line->tva_tx = $tva_tx;
1588 $line->remise_percent = $remise_percent;
1591 if ($line->fk_fournprice > 0) {
1592 require_once DOL_DOCUMENT_ROOT.
'/fourn/class/fournisseur.product.class.php';
1594 if ($prodfourn->fetch_product_fournisseur_price($line->fk_fournprice) > 0) {
1595 $line->pa_ht =
price2num($prodfourn->fourn_unitprice * (1 - $prodfourn->fourn_remise_percent / 100),
'MU');
1597 $line->fk_fournprice = 0;
1601 if ($update_desc ===
true) {
1602 $line->desc =
$prod->description;
1612 $object->entity = (!empty($forceentity) ? $forceentity :
$object->entity);
1617 $object->user_creation_id = $user->id;
1618 $object->user_validation_id = 0;
1631 $object->context[
'createfromclone'] =
'createfromclone';
1632 $result =
$object->create($user);
1640 if (
$object->copy_linked_contact($this,
'internal') < 0) {
1647 if ($this->socid ==
$object->socid) {
1648 if (
$object->copy_linked_contact($this,
'external') < 0) {
1656 if (is_object($hookmanager)) {
1657 $parameters = array(
'objFrom' => $this,
'clonedObj' =>
$object);
1659 $reshook = $hookmanager->executeHooks(
'createFrom', $parameters,
$object, $action);
1667 unset(
$object->context[
'createfromclone']);
1671 $this->db->commit();
1674 $this->db->rollback();
1688 public function fetch($rowid, $ref =
'', $ref_ext =
'', $forceentity = 0)
1690 $sql =
"SELECT p.rowid, p.ref, p.entity, p.fk_soc";
1691 $sql .=
", p.total_ttc, p.total_tva, p.localtax1, p.localtax2, p.total_ht";
1692 $sql .=
", p.datec";
1693 $sql .=
", p.date_signature as dates";
1694 $sql .=
", p.date_valid as datev";
1695 $sql .=
", p.date_cloture";
1696 $sql .=
", p.datep as dp";
1697 $sql .=
", p.fin_validite as dfv";
1698 $sql .=
", p.date_livraison as delivery_date";
1699 $sql .=
", p.model_pdf, p.last_main_doc, p.ref_client, ref_ext, p.extraparams";
1700 $sql .=
", p.note_private, p.note_public";
1701 $sql .=
", p.fk_projet as fk_project, p.fk_statut";
1702 $sql .=
", p.fk_user_author, p.fk_user_valid, p.fk_user_cloture";
1703 $sql .=
", p.fk_delivery_address";
1704 $sql .=
", p.fk_availability";
1705 $sql .=
", p.fk_input_reason";
1706 $sql .=
", p.fk_cond_reglement";
1707 $sql .=
", p.fk_mode_reglement";
1708 $sql .=
', p.fk_account';
1709 $sql .=
", p.fk_shipping_method";
1710 $sql .=
", p.fk_warehouse";
1711 $sql .=
", p.fk_incoterms, p.location_incoterms";
1712 $sql .=
", p.fk_multicurrency, p.multicurrency_code, p.multicurrency_tx, p.multicurrency_total_ht, p.multicurrency_total_tva, p.multicurrency_total_ttc";
1713 $sql .=
", p.tms as date_modification";
1714 $sql .=
", i.libelle as label_incoterms";
1715 $sql .=
", c.label as statut_label";
1716 $sql .=
", ca.code as availability_code, ca.label as availability";
1717 $sql .=
", dr.code as demand_reason_code, dr.label as demand_reason";
1718 $sql .=
", cr.code as cond_reglement_code, cr.libelle as cond_reglement, cr.libelle_facture as cond_reglement_libelle_doc, p.deposit_percent";
1719 $sql .=
", cp.code as mode_reglement_code, cp.libelle as mode_reglement";
1720 $sql .=
" FROM ".MAIN_DB_PREFIX.$this->table_element.
" as p";
1721 $sql .=
' LEFT JOIN '.MAIN_DB_PREFIX.
'c_propalst as c ON p.fk_statut = c.id';
1722 $sql .=
' LEFT JOIN '.MAIN_DB_PREFIX.
'c_paiement as cp ON p.fk_mode_reglement = cp.id AND cp.entity IN ('.
getEntity(
'c_paiement').
')';
1723 $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').
')';
1724 $sql .=
' LEFT JOIN '.MAIN_DB_PREFIX.
'c_availability as ca ON p.fk_availability = ca.rowid';
1725 $sql .=
' LEFT JOIN '.MAIN_DB_PREFIX.
'c_input_reason as dr ON p.fk_input_reason = dr.rowid';
1726 $sql .=
' LEFT JOIN '.MAIN_DB_PREFIX.
'c_incoterms as i ON p.fk_incoterms = i.rowid';
1729 if (!empty($forceentity)) {
1730 $sql .=
" WHERE p.entity = ".(int) $forceentity;
1732 $sql .=
" WHERE p.entity IN (".getEntity(
'propal').
")";
1734 $sql .=
" AND p.ref='".$this->db->escape($ref).
"'";
1737 $sql .=
" WHERE p.rowid = ".((int) $rowid);
1740 dol_syslog(get_class($this).
"::fetch", LOG_DEBUG);
1741 $resql = $this->db->query($sql);
1743 if ($this->db->num_rows($resql)) {
1744 $obj = $this->db->fetch_object($resql);
1746 $this->
id = $obj->rowid;
1747 $this->entity = $obj->entity;
1749 $this->
ref = $obj->ref;
1750 $this->ref_client = $obj->ref_client;
1751 $this->ref_customer = $obj->ref_client;
1752 $this->ref_ext = $obj->ref_ext;
1754 $this->total = $obj->total_ttc;
1755 $this->total_ttc = $obj->total_ttc;
1756 $this->total_ht = $obj->total_ht;
1757 $this->total_tva = $obj->total_tva;
1758 $this->total_localtax1 = $obj->localtax1;
1759 $this->total_localtax2 = $obj->localtax2;
1761 $this->socid = $obj->fk_soc;
1762 $this->thirdparty =
null;
1764 $this->fk_project = $obj->fk_project;
1765 $this->project =
null;
1767 $this->model_pdf = $obj->model_pdf;
1768 $this->last_main_doc = $obj->last_main_doc;
1769 $this->note = $obj->note_private;
1770 $this->note_private = $obj->note_private;
1771 $this->note_public = $obj->note_public;
1773 $this->
status = (int) $obj->fk_statut;
1774 $this->statut = $this->status;
1776 $this->datec = $this->db->jdate($obj->datec);
1777 $this->datev = $this->db->jdate($obj->datev);
1778 $this->date_creation = $this->db->jdate($obj->datec);
1779 $this->date_validation = $this->db->jdate($obj->datev);
1780 $this->date_modification = $this->db->jdate($obj->date_modification);
1781 $this->date_signature = $this->db->jdate($obj->dates);
1782 $this->date_cloture = $this->db->jdate($obj->date_cloture);
1783 $this->
date = $this->db->jdate($obj->dp);
1784 $this->datep = $this->db->jdate($obj->dp);
1785 $this->fin_validite = $this->db->jdate($obj->dfv);
1786 $this->delivery_date = $this->db->jdate($obj->delivery_date);
1787 $this->shipping_method_id = ($obj->fk_shipping_method > 0) ? $obj->fk_shipping_method :
null;
1788 $this->warehouse_id = ($obj->fk_warehouse > 0) ? $obj->fk_warehouse :
null;
1789 $this->availability_id = $obj->fk_availability;
1790 $this->availability_code = $obj->availability_code;
1792 $this->demand_reason_id = $obj->fk_input_reason;
1793 $this->demand_reason_code = $obj->demand_reason_code;
1795 $this->fk_address = $obj->fk_delivery_address;
1797 $this->mode_reglement_id = $obj->fk_mode_reglement;
1798 $this->mode_reglement_code = $obj->mode_reglement_code;
1799 $this->mode_reglement = $obj->mode_reglement;
1800 $this->fk_account = ($obj->fk_account > 0) ? $obj->fk_account :
null;
1801 $this->cond_reglement_id = $obj->fk_cond_reglement;
1802 $this->cond_reglement_code = $obj->cond_reglement_code;
1803 $this->cond_reglement = $obj->cond_reglement;
1804 $this->cond_reglement_doc = $obj->cond_reglement_libelle_doc;
1805 $this->deposit_percent = $obj->deposit_percent;
1807 $this->extraparams = !empty($obj->extraparams) ? (array) json_decode($obj->extraparams,
true) : array();
1809 $this->user_author_id = $obj->fk_user_author;
1810 $this->user_validation_id = $obj->fk_user_valid;
1811 $this->user_closing_id = $obj->fk_user_cloture;
1814 $this->fk_incoterms = $obj->fk_incoterms;
1815 $this->location_incoterms = $obj->location_incoterms;
1816 $this->label_incoterms = $obj->label_incoterms;
1819 $this->fk_multicurrency = $obj->fk_multicurrency;
1820 $this->multicurrency_code = $obj->multicurrency_code;
1821 $this->multicurrency_tx = $obj->multicurrency_tx;
1822 $this->multicurrency_total_ht = $obj->multicurrency_total_ht;
1823 $this->multicurrency_total_tva = $obj->multicurrency_total_tva;
1824 $this->multicurrency_total_ttc = $obj->multicurrency_total_ttc;
1830 $this->db->free($resql);
1832 $this->lines = array();
1843 $this->error =
"Record Not Found";
1846 $this->error = $this->db->lasterror();
1863 if (isset($this->
ref)) {
1864 $this->
ref = trim($this->
ref);
1866 if (isset($this->ref_client)) {
1867 $this->ref_client = trim($this->ref_client);
1869 if (isset($this->note) || isset($this->note_private)) {
1870 $this->note_private = (isset($this->note_private) ? trim($this->note_private) : trim($this->note));
1872 if (isset($this->note_public)) {
1873 $this->note_public = trim($this->note_public);
1875 if (isset($this->model_pdf)) {
1876 $this->model_pdf = trim($this->model_pdf);
1878 if (isset($this->import_key)) {
1879 $this->import_key = trim($this->import_key);
1881 if (!empty($this->duree_validite) && is_numeric($this->duree_validite)) {
1882 $this->fin_validite = $this->
date + ($this->duree_validite * 24 * 3600);
1889 $sql =
"UPDATE ".MAIN_DB_PREFIX.$this->table_element.
" SET";
1890 $sql =
"UPDATE ".MAIN_DB_PREFIX.
"propal SET";
1891 $sql .=
" ref = ".(isset($this->
ref) ?
"'".$this->db->escape($this->
ref).
"'" :
"null").
",";
1892 $sql .=
" ref_client = ".(isset($this->ref_client) ?
"'".$this->db->escape($this->ref_client).
"'" :
"null").
",";
1893 $sql .=
" ref_ext = ".(isset($this->ref_ext) ?
"'".$this->db->escape($this->ref_ext).
"'" :
"null").
",";
1894 $sql .=
" fk_soc = ".(!empty($this->socid) ? (int) $this->socid :
"null").
",";
1895 $sql .=
" datep = ".(strval($this->
date) !=
'' ?
"'".$this->db->idate($this->
date).
"'" :
'null').
",";
1896 if (!empty($this->fin_validite)) {
1897 $sql .=
" fin_validite = ".(strval($this->fin_validite) !=
'' ?
"'".$this->db->idate($this->fin_validite).
"'" :
'null').
",";
1899 $sql .=
" date_valid = ".(strval($this->date_validation) !=
'' ?
"'".$this->db->idate($this->date_validation).
"'" :
'null').
",";
1900 $sql .=
" total_tva = ".(isset($this->total_tva) ? (float) $this->total_tva :
"null").
",";
1901 $sql .=
" localtax1 = ".(isset($this->total_localtax1) ? (float) $this->total_localtax1 :
"null").
",";
1902 $sql .=
" localtax2 = ".(isset($this->total_localtax2) ? (float) $this->total_localtax2 :
"null").
",";
1903 $sql .=
" total_ht = ".(isset($this->total_ht) ? (float) $this->total_ht :
"null").
",";
1904 $sql .=
" total_ttc = ".(isset($this->total_ttc) ? (float) $this->total_ttc :
"null").
",";
1905 $sql .=
" fk_statut = ".(isset($this->
status) ? (int) $this->
status :
"null").
",";
1906 $sql .=
" fk_user_author = ".(!empty($this->user_author_id) ? (int) $this->user_author_id :
"null").
",";
1907 $sql .=
" fk_user_valid = ".(!empty($this->user_validation_id) ? (int) $this->user_validation_id :
"null").
",";
1909 $sql .=
" fk_projet = ".(!empty($this->fk_project) ? (int) $this->fk_project :
"null").
",";
1910 $sql .=
" fk_cond_reglement = ".(!empty($this->cond_reglement_id) ? (int) $this->cond_reglement_id :
"null").
",";
1911 $sql .=
" deposit_percent = ".(!empty($this->deposit_percent) ?
"'".$this->db->escape($this->deposit_percent).
"'" :
"null").
",";
1912 $sql .=
" fk_mode_reglement = ".(!empty($this->mode_reglement_id) ? (int) $this->mode_reglement_id :
"null").
",";
1913 $sql .=
" fk_input_reason = ".(!empty($this->demand_reason_id) ? (int) $this->demand_reason_id :
"null").
",";
1914 $sql .=
" fk_shipping_method = ".(isset($this->shipping_method_id) ? (int) $this->shipping_method_id :
"null").
",";
1915 $sql .=
" fk_availability = ".(!empty($this->availability_id) ? (int) $this->availability_id :
"null").
",";
1916 $sql .=
" note_private = ".(isset($this->note_private) ?
"'".$this->db->escape($this->note_private).
"'" :
"null").
",";
1917 $sql .=
" note_public = ".(isset($this->note_public) ?
"'".$this->db->escape($this->note_public).
"'" :
"null").
",";
1918 $sql .=
" model_pdf = ".(isset($this->model_pdf) ?
"'".$this->db->escape($this->model_pdf).
"'" :
"null").
",";
1919 $sql .=
" import_key = ".(isset($this->import_key) ?
"'".$this->db->escape($this->import_key).
"'" :
"null");
1920 $sql .=
" WHERE rowid = ".((int) $this->
id);
1924 dol_syslog(get_class($this).
"::update", LOG_DEBUG);
1925 $resql = $this->db->query($sql);
1928 $this->errors[] =
"Error ".$this->db->lasterror();
1938 if (!$error && !$notrigger) {
1940 $result = $this->call_trigger(
'PROPAL_MODIFY', $user);
1949 foreach ($this->errors as $errmsg) {
1950 dol_syslog(get_class($this).
"::update ".$errmsg, LOG_ERR);
1951 $this->error .= ($this->error ?
', '.$errmsg : $errmsg);
1953 $this->db->rollback();
1956 $this->db->commit();
1971 public function fetch_lines($only_product = 0, $loadalsotranslation = 0, $sqlforgedfilters =
'')
1974 $this->lines = array();
1976 $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.subprice_ttc, d.fk_product,';
1977 $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,';
1978 $sql .=
' d.fk_unit,';
1979 $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,';
1980 $sql .=
' p.weight, p.weight_units, p.volume, p.volume_units,';
1981 $sql .=
' p.customcode, p.fk_country as country_id, c.code as country_code,';
1982 $sql .=
' d.date_start, d.date_end, d.extraparams,';
1983 $sql .=
' d.fk_multicurrency, d.multicurrency_code, d.multicurrency_subprice, d.multicurrency_total_ht, d.multicurrency_total_tva, d.multicurrency_total_ttc';
1984 $sql .=
' FROM '.MAIN_DB_PREFIX.$this->table_element_line.
' as d';
1985 $sql .=
' LEFT JOIN '.MAIN_DB_PREFIX.
'product as p ON (d.fk_product = p.rowid)';
1986 $sql .=
' LEFT JOIN '.MAIN_DB_PREFIX.
'c_country as c ON c.rowid = p.fk_country';
1987 $sql .=
' WHERE d.fk_propal = '.((int) $this->
id);
1988 if ($only_product) {
1989 $sql .=
' AND p.fk_product_type = 0';
1991 if ($sqlforgedfilters) {
1992 $sql .= $sqlforgedfilters;
1994 $sql .=
' ORDER BY d.rang, d.rowid';
1996 dol_syslog(get_class($this).
"::fetch_lines", LOG_DEBUG);
1997 $result = $this->db->query($sql);
1999 require_once DOL_DOCUMENT_ROOT.
'/core/class/extrafields.class.php';
2001 $num = $this->db->num_rows($result);
2005 $objp = $this->db->fetch_object($result);
2009 $line->rowid = $objp->rowid;
2010 $line->id = $objp->rowid;
2011 $line->fk_propal = $objp->fk_propal;
2012 $line->fk_parent_line = $objp->fk_parent_line;
2013 $line->label = $objp->custom_label;
2014 $line->desc = $objp->description;
2015 $line->description = $objp->description;
2016 $line->qty = $objp->qty;
2017 $line->vat_src_code = $objp->vat_src_code;
2018 $line->tva_tx = $objp->tva_tx;
2019 $line->localtax1_tx = $objp->localtax1_tx;
2020 $line->localtax2_tx = $objp->localtax2_tx;
2021 $line->localtax1_type = $objp->localtax1_type;
2022 $line->localtax2_type = $objp->localtax2_type;
2023 $line->subprice = $objp->subprice;
2024 $line->subprice_ttc = $objp->subprice_ttc;
2025 $line->fk_remise_except = $objp->fk_remise_except;
2026 $line->remise_percent = $objp->remise_percent;
2028 $line->info_bits = $objp->info_bits;
2029 $line->total_ht = $objp->total_ht;
2030 $line->total_tva = $objp->total_tva;
2031 $line->total_localtax1 = $objp->total_localtax1;
2032 $line->total_localtax2 = $objp->total_localtax2;
2033 $line->total_ttc = $objp->total_ttc;
2034 $line->fk_fournprice = $objp->fk_fournprice;
2035 $marginInfos =
getMarginInfos($objp->subprice, $objp->remise_percent, $objp->tva_tx, $objp->localtax1_tx, $objp->localtax2_tx, $line->fk_fournprice, $objp->pa_ht);
2036 $line->pa_ht = $marginInfos[0];
2037 $line->marge_tx = $marginInfos[1];
2038 $line->marque_tx = $marginInfos[2];
2039 $line->special_code = $objp->special_code;
2040 $line->rang = $objp->rang;
2042 $line->fk_product = $objp->fk_product;
2044 $line->ref = $objp->product_ref;
2045 $line->libelle = $objp->product_label;
2047 $line->product_ref = $objp->product_ref;
2048 $line->product_label = $objp->product_label;
2049 $line->product_desc = $objp->product_desc;
2050 $line->product_tobatch = $objp->product_tobatch;
2051 $line->product_barcode = $objp->product_barcode;
2052 $line->product_custom_code = $objp->customcode;
2053 $line->product_custom_country_id = $objp->country_id;
2054 $line->product_custom_country_code = $objp->country_code;
2055 $line->product_type = $objp->product_type;
2056 $line->fk_product_type = $objp->fk_product_type;
2058 $line->fk_unit = $objp->fk_unit;
2059 $line->weight = $objp->weight;
2060 $line->weight_units = $objp->weight_units;
2061 $line->volume = $objp->volume;
2062 $line->volume_units = $objp->volume_units;
2064 $line->date_start = $this->db->jdate($objp->date_start);
2065 $line->date_end = $this->db->jdate($objp->date_end);
2067 $line->extraparams = !empty($objp->extraparams) ? (array) json_decode($objp->extraparams,
true) : array();
2070 $line->fk_multicurrency = $objp->fk_multicurrency;
2071 $line->multicurrency_code = $objp->multicurrency_code;
2072 $line->multicurrency_subprice = $objp->multicurrency_subprice;
2073 $line->multicurrency_total_ht = $objp->multicurrency_total_ht;
2074 $line->multicurrency_total_tva = $objp->multicurrency_total_tva;
2075 $line->multicurrency_total_ttc = $objp->multicurrency_total_ttc;
2077 $line->fetch_optionals();
2080 if (
getDolGlobalInt(
'MAIN_MULTILANGS') && !empty($objp->fk_product) && !empty($loadalsotranslation)) {
2081 $tmpproduct =
new Product($this->db);
2082 $tmpproduct->fetch($objp->fk_product);
2083 $tmpproduct->getMultiLangs();
2085 $line->multilangs = $tmpproduct->multilangs;
2088 $this->lines[$i] = $line;
2093 $this->db->free($result);
2097 $this->error = $this->db->lasterror();
2109 public function valid($user, $notrigger = 0)
2113 require_once DOL_DOCUMENT_ROOT.
'/core/lib/files.lib.php';
2118 if ($this->
status == self::STATUS_VALIDATED) {
2119 dol_syslog(get_class($this).
"::valid action abandoned: already validated", LOG_WARNING);
2123 if (!((!
getDolGlobalString(
'MAIN_USE_ADVANCED_PERMS') && $user->hasRight(
'propal',
'creer'))
2124 || (
getDolGlobalString(
'MAIN_USE_ADVANCED_PERMS') && $user->hasRight(
'propal',
'propal_advance',
'validate')))) {
2125 $this->error =
'ErrorPermissionDenied';
2126 dol_syslog(get_class($this).
"::valid ".$this->error, LOG_ERR);
2131 dol_syslog(get_class($this).
"::valid checkActiveProductInLines ".$this->error, LOG_INFO);
2140 $soc =
new Societe($this->db);
2141 $soc->fetch($this->socid);
2144 if (preg_match(
'/^[\(]?PROV/i', $this->
ref) || empty($this->
ref)) {
2145 $num = $this->getNextNumRef($soc);
2151 $sql =
"UPDATE ".MAIN_DB_PREFIX.$this->table_element;
2152 $sql .=
" SET ref = '".$this->db->escape($num).
"',";
2153 $sql .=
" fk_statut = ".self::STATUS_VALIDATED.
", date_valid='".$this->db->idate($now).
"', fk_user_valid=".((int) $user->id);
2156 dol_syslog(get_class($this).
"::valid", LOG_DEBUG);
2157 $resql = $this->db->query($sql);
2164 if (!$error && !$notrigger) {
2166 $result = $this->call_trigger(
'PROPAL_VALIDATE', $user);
2174 $this->oldref = $this->ref;
2177 if (preg_match(
'/^[\(]?PROV/i', $this->
ref)) {
2179 $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).
"'";
2180 $sql .=
" WHERE filename LIKE '".$this->db->escape($this->
ref).
"%' AND filepath = 'propale/".$this->db->escape($this->
ref).
"' and entity = ".((int)
$conf->entity);
2181 $resql = $this->db->query($sql);
2184 $this->error = $this->db->lasterror();
2186 $sql =
'UPDATE '.MAIN_DB_PREFIX.
"ecm_files set filepath = 'propale/".$this->db->escape($this->newref).
"'";
2187 $sql .=
" WHERE filepath = 'propale/".$this->db->escape($this->
ref).
"' and entity = ".((int)
$conf->entity);
2188 $resql = $this->db->query($sql);
2191 $this->error = $this->db->lasterror();
2197 $dirsource =
$conf->propal->multidir_output[$this->entity].
'/'.$oldref;
2198 $dirdest =
$conf->propal->multidir_output[$this->entity].
'/'.$newref;
2199 if (!$error && file_exists($dirsource)) {
2200 dol_syslog(get_class($this).
"::validate rename dir ".$dirsource.
" into ".$dirdest);
2201 if (@rename($dirsource, $dirdest)) {
2204 $listoffiles =
dol_dir_list($dirdest,
'files', 1,
'^'.preg_quote($oldref,
'/'));
2205 foreach ($listoffiles as $fileentry) {
2206 $dirsource = $fileentry[
'name'];
2207 $dirdest = preg_replace(
'/^'.preg_quote($oldref,
'/').
'/', $newref, $dirsource);
2208 $dirsource = $fileentry[
'path'].
'/'.$dirsource;
2209 $dirdest = $fileentry[
'path'].
'/'.$dirdest;
2210 @rename($dirsource, $dirdest);
2219 $this->user_validation_id = $user->id;
2220 $this->datev = $now;
2221 $this->date_validation = $now;
2223 $this->db->commit();
2226 $this->db->rollback();
2245 $this->error =
'ErrorBadParameter';
2246 dol_syslog(get_class($this).
"::set_date ".$this->error, LOG_ERR);
2250 if ($user->hasRight(
'propal',
'creer')) {
2255 $sql =
"UPDATE ".MAIN_DB_PREFIX.$this->table_element;
2256 $sql .=
" SET datep = '".$this->db->idate($date).
"'";
2257 $sql .=
" WHERE rowid = ".((int) $this->
id);
2260 $resql = $this->db->query($sql);
2262 $this->errors[] = $this->db->error();
2267 $this->oldcopy = clone $this;
2268 $this->
date = $date;
2269 $this->datep = $date;
2272 if (!$notrigger && empty($error)) {
2274 $result = $this->call_trigger(
'PROPAL_MODIFY', $user);
2282 $this->db->commit();
2285 foreach ($this->errors as $errmsg) {
2286 dol_syslog(__METHOD__.
' Error: '.$errmsg, LOG_ERR);
2287 $this->error .= ($this->error ?
', '.$errmsg : $errmsg);
2289 $this->db->rollback();
2309 if ($user->hasRight(
'propal',
'creer')) {
2314 $sql =
"UPDATE ".MAIN_DB_PREFIX.$this->table_element;
2315 $sql .=
" SET fin_validite = ".($date_end_validity !=
'' ?
"'".$this->db->idate($date_end_validity).
"'" :
'null');
2316 $sql .=
" WHERE rowid = ".((int) $this->
id);
2320 $resql = $this->db->query($sql);
2322 $this->errors[] = $this->db->error();
2328 $this->oldcopy = clone $this;
2329 $this->fin_validite = $date_end_validity;
2332 if (!$notrigger && empty($error)) {
2334 $result = $this->call_trigger(
'PROPAL_MODIFY', $user);
2342 $this->db->commit();
2345 foreach ($this->errors as $errmsg) {
2346 dol_syslog(__METHOD__.
' Error: '.$errmsg, LOG_ERR);
2347 $this->error .= ($this->error ?
', '.$errmsg : $errmsg);
2349 $this->db->rollback();
2383 if ($user->hasRight(
'propal',
'creer')) {
2388 $sql =
"UPDATE ".MAIN_DB_PREFIX.$this->table_element;
2389 $sql .=
" SET date_livraison = ".(isDolTms($delivery_date) ?
"'".$this->db->idate($delivery_date).
"'" :
'null');
2390 $sql .=
" WHERE rowid = ".((int) $this->
id);
2393 $resql = $this->db->query($sql);
2395 $this->errors[] = $this->db->error();
2400 $this->oldcopy = clone $this;
2401 $this->delivery_date = $delivery_date;
2404 if (!$notrigger && empty($error)) {
2406 $result = $this->call_trigger(
'PROPAL_MODIFY', $user);
2414 $this->db->commit();
2417 foreach ($this->errors as $errmsg) {
2418 dol_syslog(__METHOD__.
' Error: '.$errmsg, LOG_ERR);
2419 $this->error .= ($this->error ?
', '.$errmsg : $errmsg);
2421 $this->db->rollback();
2441 if ($this->
status >= self::STATUS_DRAFT) {
2446 $sql =
"UPDATE ".MAIN_DB_PREFIX.$this->table_element;
2447 $sql .=
" SET fk_availability = ".((int) ($id > 0 ? ((
int) $id) : 0));
2448 $sql .=
" WHERE rowid = ".((int) $this->
id);
2451 $resql = $this->db->query($sql);
2453 $this->errors[] = $this->db->error();
2458 $this->oldcopy = clone $this;
2459 $this->fk_availability =
$id;
2460 $this->availability_id =
$id;
2463 if (!$notrigger && empty($error)) {
2465 $result = $this->call_trigger(
'PROPAL_MODIFY', $user);
2473 $this->db->commit();
2476 foreach ($this->errors as $errmsg) {
2477 dol_syslog(__METHOD__.
' Error: '.$errmsg, LOG_ERR);
2478 $this->error .= ($this->error ?
', '.$errmsg : $errmsg);
2480 $this->db->rollback();
2484 $error_str =
'Propal status do not meet requirement '.$this->status;
2486 $this->error = $error_str;
2487 $this->errors[] = $this->error;
2504 if ($user->hasRight(
'propal',
'creer') && $this->status >= self::STATUS_DRAFT) {
2509 $sql =
"UPDATE ".MAIN_DB_PREFIX.$this->table_element;
2510 $sql .=
" SET fk_input_reason = ".((int) $id);
2511 $sql .=
" WHERE rowid = ".((int) $this->
id);
2514 $resql = $this->db->query($sql);
2516 $this->errors[] = $this->db->error();
2522 $this->oldcopy = clone $this;
2524 $this->demand_reason_id = $id;
2528 if (!$notrigger && empty($error)) {
2530 $result = $this->call_trigger(
'PROPAL_MODIFY', $user);
2538 $this->db->commit();
2541 foreach ($this->errors as $errmsg) {
2542 dol_syslog(__METHOD__.
' Error: '.$errmsg, LOG_ERR);
2543 $this->error .= ($this->error ?
', '.$errmsg : $errmsg);
2545 $this->db->rollback();
2549 $error_str =
'Propal status do not meet requirement '.$this->status;
2551 $this->error = $error_str;
2552 $this->errors[] = $this->error;
2569 if ($user->hasRight(
'propal',
'creer')) {
2574 $sql =
"UPDATE ".MAIN_DB_PREFIX.$this->table_element;
2575 $sql .=
" SET ref_client = ".(empty($ref_client) ?
'NULL' :
"'".$this->db->escape($ref_client).
"'");
2576 $sql .=
" WHERE rowid = ".((int) $this->
id);
2578 dol_syslog(__METHOD__.
' $this->id='.$this->id.
', ref_client='.$ref_client, LOG_DEBUG);
2579 $resql = $this->db->query($sql);
2581 $this->errors[] = $this->db->error();
2586 $this->oldcopy = clone $this;
2587 $this->ref_customer = $ref_client;
2588 $this->ref_client = $ref_client;
2591 if (!$notrigger && empty($error)) {
2593 $result = $this->call_trigger(
'PROPAL_MODIFY', $user);
2601 $this->db->commit();
2604 foreach ($this->errors as $errmsg) {
2605 dol_syslog(__METHOD__.
' Error: '.$errmsg, LOG_ERR);
2606 $this->error .= ($this->error ?
', '.$errmsg : $errmsg);
2608 $this->db->rollback();
2626 public function reopen($user, $status, $note =
'', $notrigger = 0)
2630 $sql =
"UPDATE ".MAIN_DB_PREFIX.$this->table_element;
2631 $sql .=
" SET fk_statut = ".((int) $status).
",";
2632 if (!empty($note)) {
2633 $sql .=
" note_private = '".$this->db->escape($note).
"',";
2635 $sql .=
" date_cloture=NULL, fk_user_cloture=NULL";
2636 $sql .=
" WHERE rowid = ".((int) $this->
id);
2640 dol_syslog(get_class($this).
"::reopen", LOG_DEBUG);
2641 $resql = $this->db->query($sql);
2644 $this->errors[] =
"Error ".$this->db->lasterror();
2649 $result = $this->call_trigger(
'PROPAL_REOPEN', $user);
2659 if (!empty($this->errors)) {
2660 foreach ($this->errors as $errmsg) {
2661 dol_syslog(get_class($this).
"::update ".$errmsg, LOG_ERR);
2662 $this->error .= ($this->error ?
', '.$errmsg : $errmsg);
2665 $this->db->rollback();
2668 $this->statut = $status;
2671 $this->db->commit();
2686 public function closeProposal($user, $status, $note_private =
'', $notrigger = 0, $note_public =
'')
2688 global $langs,
$conf;
2695 $newprivatenote =
dol_concatdesc($this->note_private, $note_private);
2696 $newpublicnote =
dol_concatdesc($this->note_public, $note_public);
2699 $date_signature = $now;
2700 $fk_user_signature = $user->id;
2702 $this->
info($this->
id);
2703 if (!isset($this->date_signature) || $this->date_signature ==
'') {
2704 $date_signature = $now;
2705 $fk_user_signature = $user->id;
2707 $date_signature = $this->date_signature;
2708 $fk_user_signature = $this->user_signature->id;
2712 $sql =
"UPDATE ".MAIN_DB_PREFIX.$this->table_element;
2713 $sql .=
" SET fk_statut = ".((int) $status).
", note_private = '".$this->db->escape($newprivatenote).
"', note_public = '".$this->db->escape($newpublicnote).
"'";
2714 if ($status == self::STATUS_SIGNED) {
2715 $sql .=
", date_signature='".$this->db->idate($now).
"', fk_user_signature = ".((int) $fk_user_signature);
2717 $sql .=
" WHERE rowid = ".((int) $this->
id);
2719 $resql = $this->db->query($sql);
2723 $triggerName =
'PROPAL_CLOSE_REFUSED';
2725 if ($status == self::STATUS_SIGNED) {
2726 $triggerName =
'PROPAL_CLOSE_SIGNED';
2730 $soc =
new Societe($this->db);
2731 $soc->id = $this->socid;
2732 $result = $soc->setAsCustomer();
2735 $this->error = $this->db->lasterror();
2736 $this->db->rollback();
2743 $outputlangs = $langs;
2746 $newlang = (
GETPOST(
'lang_id',
'aZ09') ?
GETPOST(
'lang_id',
'aZ09') : $this->thirdparty->default_lang);
2747 $outputlangs->setDefaultLang($newlang);
2756 $this->
generateDocument($modelpdf, $outputlangs, $hidedetails, $hidedesc, $hideref);
2759 $this->oldcopy = clone $this;
2760 $this->statut = $status;
2762 $this->date_signature = $date_signature;
2763 $this->note_private = $newprivatenote;
2765 if (!$notrigger && empty($error)) {
2767 $result = $this->call_trigger($triggerName, $user);
2775 $this->db->commit();
2778 foreach ($this->errors as $errmsg) {
2779 dol_syslog(__METHOD__.
' Error: '.$errmsg, LOG_ERR);
2780 $this->error .= ($this->error ?
', '.$errmsg : $errmsg);
2782 if (!empty($this->oldcopy)) {
2783 $this->statut = $this->oldcopy->status;
2784 $this->
status = $this->oldcopy->status;
2785 $this->date_signature = $this->oldcopy->date_signature;
2786 $this->note_private = $this->oldcopy->note_private;
2789 $this->db->rollback();
2793 $this->error = $this->db->lasterror();
2794 $this->db->rollback();
2809 global
$conf, $langs;
2816 $triggerName =
'PROPAL_CLASSIFY_BILLED';
2822 $sql =
'UPDATE '.MAIN_DB_PREFIX.$this->table_element;
2823 $sql .=
" SET fk_statut = ".self::STATUS_BILLED.
", ";
2824 $sql .=
" note_private = '".$this->db->escape($newprivatenote).
"', date_cloture='".$this->db->idate($now).
"', fk_user_cloture=".((int) $user->id);
2825 $sql .=
' WHERE rowid = '.((int) $this->
id).
' AND fk_statut = '.((int) self::STATUS_SIGNED);
2828 $resql = $this->db->query($sql);
2830 $this->errors[] = $this->db->error();
2833 $num = $this->db->affected_rows($resql);
2841 $outputlangs = $langs;
2844 $newlang = (
GETPOST(
'lang_id',
'aZ09') ?
GETPOST(
'lang_id',
'aZ09') : $this->thirdparty->default_lang);
2845 $outputlangs->setDefaultLang($newlang);
2854 $this->
generateDocument($modelpdf, $outputlangs, $hidedetails, $hidedesc, $hideref);
2857 $this->oldcopy = clone $this;
2860 $this->date_cloture = $now;
2861 $this->note_private = $newprivatenote;
2864 if (!$notrigger && empty($error)) {
2866 $result = $this->call_trigger($triggerName, $user);
2874 $this->db->commit();
2877 foreach ($this->errors as $errmsg) {
2878 dol_syslog(__METHOD__.
' Error: '.$errmsg, LOG_ERR);
2879 $this->error .= ($this->error ?
', '.$errmsg : $errmsg);
2881 $this->db->rollback();
2898 $sql =
"UPDATE ". MAIN_DB_PREFIX . $this->table_element;
2899 $sql .=
" SET fk_statut = " . self::STATUS_CANCELED .
",";
2900 $sql .=
" fk_user_modif = " . ((int) $user->id);
2901 $sql .=
" WHERE rowid = " . ((int) $this->
id);
2903 dol_syslog(get_class($this).
"::cancel", LOG_DEBUG);
2904 if ($this->db->query($sql)) {
2906 $result = $this->call_trigger(
'PROPAL_CANCEL', $user);
2915 $this->db->commit();
2918 foreach ($this->errors as $errmsg) {
2919 dol_syslog(get_class($this).
"::cancel ".$errmsg, LOG_ERR);
2920 $this->error .= ($this->error ?
', '.$errmsg : $errmsg);
2922 $this->db->rollback();
2926 $this->error = $this->db->error();
2927 $this->db->rollback();
2946 if ($this->
status <= self::STATUS_DRAFT) {
2950 dol_syslog(get_class($this).
"::setDraft", LOG_DEBUG);
2954 $sql =
"UPDATE ".MAIN_DB_PREFIX.$this->table_element;
2955 $sql .=
" SET fk_statut = ".self::STATUS_DRAFT;
2956 $sql .=
", online_sign_ip = NULL , online_sign_name = NULL";
2957 $sql .=
" WHERE rowid = ".((int) $this->
id);
2959 $resql = $this->db->query($sql);
2961 $this->errors[] = $this->db->error();
2966 $this->oldcopy = clone $this;
2969 if (!$notrigger && empty($error)) {
2971 $result = $this->call_trigger(
'PROPAL_MODIFY', $user);
2982 $this->db->commit();
2985 foreach ($this->errors as $errmsg) {
2986 dol_syslog(__METHOD__.
' Error: '.$errmsg, LOG_ERR);
2987 $this->error .= ($this->error ?
', '.$errmsg : $errmsg);
2989 $this->db->rollback();
3009 public function liste_array($shortlist = 0, $draft = 0, $notcurrentuser = 0, $socid = 0, $limit = 0, $offset = 0, $sortfield =
'p.datep', $sortorder =
'DESC')
3016 $sql =
"SELECT s.rowid, s.nom as name, s.client,";
3017 $sql .=
" p.rowid as propalid, p.fk_statut, p.total_ht, p.ref, p.remise, ";
3018 $sql .=
" p.datep as dp, p.fin_validite as datelimite";
3019 $sql .=
" FROM ".MAIN_DB_PREFIX.
"societe as s, ".MAIN_DB_PREFIX.$this->table_element.
" as p, ".MAIN_DB_PREFIX.
"c_propalst as c";
3020 $sql .=
" WHERE p.entity IN (".getEntity(
'propal').
")";
3021 $sql .=
" AND p.fk_soc = s.rowid";
3022 $sql .=
" AND p.fk_statut = c.id";
3026 if (empty($user->socid) && !$user->hasRight(
'societe',
'client',
'voir')) {
3027 $search_sale = $user->id;
3030 if ($search_sale && $search_sale !=
'-1') {
3031 if ($search_sale == -2) {
3032 $sql .=
" AND NOT EXISTS (SELECT sc.fk_soc FROM ".MAIN_DB_PREFIX.
"societe_commerciaux as sc WHERE sc.fk_soc = p.fk_soc)";
3033 } elseif ($search_sale > 0) {
3034 $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).
")";
3039 $sql .=
" AND p.fk_soc = ".((int) $socid);
3042 $sql .=
" AND p.fk_statut = ".((int) self::STATUS_DRAFT);
3044 if ($notcurrentuser > 0) {
3045 $sql .=
" AND p.fk_user_author <> ".((int) $user->id);
3047 $sql .= $this->db->order($sortfield, $sortorder);
3048 $sql .= $this->db->plimit($limit, $offset);
3050 $result = $this->db->query($sql);
3052 $num = $this->db->num_rows($result);
3056 $obj = $this->db->fetch_object($result);
3058 if ($shortlist == 1) {
3059 $ga[$obj->propalid] = $obj->ref;
3060 } elseif ($shortlist == 2) {
3061 $ga[$obj->propalid] = $obj->ref.
' ('.$obj->name.
')';
3063 $ga[$i][
'id'] = $obj->propalid;
3064 $ga[$i][
'ref'] = $obj->ref;
3065 $ga[$i][
'name'] = $obj->name;
3099 $linkedInvoices = array();
3102 foreach ($this->linkedObjectsIds as $objecttype => $objectid) {
3105 foreach ($objectid as $key =>
$object) {
3107 if ($objecttype ==
'facture') {
3112 foreach ($this->linkedObjectsIds as $subobjecttype => $subobjectid) {
3113 foreach ($subobjectid as $subkey => $subobject) {
3114 if ($subobjecttype ==
'facture') {
3115 $linkedInvoices[] = $subobject;
3123 if (count($linkedInvoices) > 0) {
3124 $sql =
"SELECT rowid as facid, ref, total_ht as total, datef as df, fk_user_author, fk_statut, paye";
3125 $sql .=
" FROM ".MAIN_DB_PREFIX.
"facture";
3126 $sql .=
" WHERE rowid IN (".$this->db->sanitize(implode(
',', $linkedInvoices)).
")";
3128 dol_syslog(get_class($this).
"::InvoiceArrayList", LOG_DEBUG);
3129 $resql = $this->db->query($sql);
3132 $tab_sqlobj = array();
3133 $nump = $this->db->num_rows($resql);
3134 for ($i = 0; $i < $nump; $i++) {
3135 $obj = $this->db->fetch_object($resql);
3136 $tab_sqlobj[] = $obj;
3138 $this->db->free($resql);
3140 $nump = count($tab_sqlobj);
3144 while ($i < $nump) {
3145 $obj = array_shift($tab_sqlobj);
3168 public function delete($user, $notrigger = 0)
3171 require_once DOL_DOCUMENT_ROOT.
'/core/lib/files.lib.php';
3179 $result = $this->call_trigger(
'PROPAL_DELETE', $user);
3188 $sql =
"DELETE FROM ".MAIN_DB_PREFIX.
"categorie_propal";
3189 $sql .=
" WHERE fk_propal = ".((int) $this->
id);
3191 $result = $this->db->query($sql);
3194 $this->error = $this->db->lasterror();
3195 $this->errors[] = $this->error;
3200 if (!$error && !empty($this->table_element_line)) {
3201 $tabletodelete = $this->table_element_line;
3202 $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).
")";
3203 $sql =
"DELETE FROM ".MAIN_DB_PREFIX.$tabletodelete.
" WHERE ".$this->fk_element.
" = ".((int) $this->
id);
3204 if (!$this->db->query($sqlef) || !$this->db->query($sql)) {
3206 $this->error = $this->db->lasterror();
3207 $this->errors[] = $this->error;
3208 dol_syslog(get_class($this).
"::delete error ".$this->error, LOG_ERR);
3233 dol_syslog(get_class($this).
"::delete error ".$this->error, LOG_ERR);
3239 $sql =
"DELETE FROM ".MAIN_DB_PREFIX.$this->table_element.
" WHERE rowid = ".((int) $this->
id);
3240 $res = $this->db->query($sql);
3243 $this->error = $this->db->lasterror();
3244 $this->errors[] = $this->error;
3245 dol_syslog(get_class($this).
"::delete error ".$this->error, LOG_ERR);
3261 if ($conf->propal->multidir_output[$this->entity] && !empty($this->
ref)) {
3262 $dir =
$conf->propal->multidir_output[$this->entity].
"/".$ref;
3263 $file = $dir.
"/".$ref.
".pdf";
3264 if (file_exists($file)) {
3268 $this->error =
'ErrorFailToDeleteFile';
3269 $this->errors[] = $this->error;
3270 $this->db->rollback();
3274 if (file_exists($dir)) {
3277 $this->error =
'ErrorFailToDeleteDir';
3278 $this->errors[] = $this->error;
3279 $this->db->rollback();
3287 dol_syslog(get_class($this).
"::delete ".$this->
id.
" by ".$user->id, LOG_DEBUG);
3288 $this->db->commit();
3291 $this->db->rollback();
3308 if ($this->
status >= self::STATUS_DRAFT) {
3313 $sql =
'UPDATE '.MAIN_DB_PREFIX.$this->table_element;
3314 $sql .=
' SET fk_availability = '.((int) $availability_id);
3315 $sql .=
' WHERE rowid='.((int) $this->
id);
3317 dol_syslog(__METHOD__.
' availability('.$availability_id.
')', LOG_DEBUG);
3318 $resql = $this->db->query($sql);
3320 $this->errors[] = $this->db->error();
3325 $this->oldcopy = clone $this;
3326 $this->availability_id = $availability_id;
3329 if (!$notrigger && empty($error)) {
3331 $result = $this->call_trigger(
'PROPAL_MODIFY', $user);
3339 $this->db->commit();
3342 foreach ($this->errors as $errmsg) {
3343 dol_syslog(__METHOD__.
' Error: '.$errmsg, LOG_ERR);
3344 $this->error .= ($this->error ?
', '.$errmsg : $errmsg);
3346 $this->db->rollback();
3350 $error_str =
'Propal status do not meet requirement '.$this->status;
3352 $this->error = $error_str;
3353 $this->errors[] = $this->error;
3372 if ($this->
status >= self::STATUS_DRAFT) {
3377 $sql =
'UPDATE '.MAIN_DB_PREFIX.$this->table_element;
3378 $sql .=
' SET fk_input_reason = '.((int) $demand_reason_id);
3379 $sql .=
' WHERE rowid='.((int) $this->
id);
3381 dol_syslog(__METHOD__.
' demand_reason('.$demand_reason_id.
')', LOG_DEBUG);
3382 $resql = $this->db->query($sql);
3384 $this->errors[] = $this->db->error();
3389 $this->oldcopy = clone $this;
3390 $this->demand_reason_id = $demand_reason_id;
3393 if (!$notrigger && empty($error)) {
3395 $result = $this->call_trigger(
'PROPAL_MODIFY', $user);
3403 $this->db->commit();
3406 foreach ($this->errors as $errmsg) {
3407 dol_syslog(__METHOD__.
' Error: '.$errmsg, LOG_ERR);
3408 $this->error .= ($this->error ?
', '.$errmsg : $errmsg);
3410 $this->db->rollback();
3414 $error_str =
'Propal status do not meet requirement '.$this->status;
3416 $this->error = $error_str;
3417 $this->errors[] = $this->error;
3431 $sql =
"SELECT c.rowid, ";
3432 $sql .=
" c.datec, c.date_valid as datev, c.date_signature, c.date_cloture,";
3433 $sql .=
" c.fk_user_author, c.fk_user_valid, c.fk_user_signature, c.fk_user_cloture";
3434 $sql .=
" FROM ".MAIN_DB_PREFIX.$this->table_element.
" as c";
3435 $sql .=
" WHERE c.rowid = ".((int) $id);
3437 $result = $this->db->query($sql);
3440 if ($this->db->num_rows($result)) {
3441 $obj = $this->db->fetch_object($result);
3443 $this->
id = $obj->rowid;
3445 $this->date_creation = $this->db->jdate($obj->datec);
3446 $this->date_validation = $this->db->jdate($obj->datev);
3447 $this->date_signature = $this->db->jdate($obj->date_signature);
3448 $this->date_cloture = $this->db->jdate($obj->date_cloture);
3450 $this->user_creation_id = $obj->fk_user_author;
3451 $this->user_validation_id = $obj->fk_user_valid;
3453 if ($obj->fk_user_signature) {
3454 $user_signature =
new User($this->db);
3455 $user_signature->fetch($obj->fk_user_signature);
3456 $this->user_signature = $user_signature;
3459 $this->user_closing_id = $obj->fk_user_cloture;
3461 $this->db->free($result);
3490 global $hookmanager;
3493 if (empty($this->labelStatus) || empty($this->labelStatusShort)) {
3495 $langs->load(
"propal");
3496 $this->labelStatus[-1] = $langs->transnoentitiesnoconv(
"PropalStatusCanceled");
3497 $this->labelStatus[0] = $langs->transnoentitiesnoconv(
"PropalStatusDraft");
3498 $this->labelStatus[1] = $langs->transnoentitiesnoconv(
"PropalStatusValidated");
3499 $this->labelStatus[2] = $langs->transnoentitiesnoconv(
"PropalStatusSigned");
3500 $this->labelStatus[3] = $langs->transnoentitiesnoconv(
"PropalStatusNotSigned");
3501 $this->labelStatus[4] = $langs->transnoentitiesnoconv(
"PropalStatusBilled");
3502 $this->labelStatusShort[-1] = $langs->transnoentitiesnoconv(
"PropalStatusCanceledShort");
3503 $this->labelStatusShort[0] = $langs->transnoentitiesnoconv(
"PropalStatusDraftShort");
3504 $this->labelStatusShort[1] = $langs->transnoentitiesnoconv(
"PropalStatusValidatedShort");
3505 $this->labelStatusShort[2] = $langs->transnoentitiesnoconv(
"PropalStatusSignedShort");
3506 $this->labelStatusShort[3] = $langs->transnoentitiesnoconv(
"PropalStatusNotSignedShort");
3507 $this->labelStatusShort[4] = $langs->transnoentitiesnoconv(
"PropalStatusBilledShort");
3511 if ($status == self::STATUS_CANCELED) {
3512 $statusType =
'status9';
3513 } elseif ($status == self::STATUS_DRAFT) {
3514 $statusType =
'status0';
3515 } elseif ($status == self::STATUS_VALIDATED) {
3516 $statusType =
'status1';
3517 } elseif ($status == self::STATUS_SIGNED) {
3518 $statusType =
'status4';
3519 } elseif ($status == self::STATUS_NOTSIGNED) {
3520 $statusType =
'status9';
3521 } elseif ($status == self::STATUS_BILLED) {
3522 $statusType =
'status6';
3525 $parameters = array(
'status' => $status,
'mode' => $mode);
3526 $reshook = $hookmanager->executeHooks(
'LibStatut', $parameters, $this);
3529 return $hookmanager->resPrint;
3532 return dolGetStatus($this->labelStatus[$status], $this->labelStatusShort[$status],
'', $statusType, $mode);
3547 global $langs, $hookmanager;
3549 $sql =
"SELECT p.rowid, p.ref, p.datec as datec, p.fin_validite as datefin, p.total_ht";
3550 if (empty($user->socid) && !$user->hasRight(
'societe',
'client',
'voir')) {
3551 $sql .=
" FROM ".MAIN_DB_PREFIX.$this->table_element.
" as p";
3552 $sql .=
" LEFT JOIN ".MAIN_DB_PREFIX.
"societe_commerciaux as sc ON p.fk_soc = sc.fk_soc";
3554 $sql .=
" FROM ".MAIN_DB_PREFIX.
"propal as p";
3556 $sql .=
" WHERE p.entity IN (".getEntity(
'propal').
")";
3557 if ($mode ==
'opened') {
3558 $sql .=
" AND p.fk_statut = ".self::STATUS_VALIDATED;
3560 if ($mode ==
'signed') {
3561 $sql .=
" AND p.fk_statut = ".self::STATUS_SIGNED;
3564 if (empty($user->socid) && !$user->hasRight(
'societe',
'client',
'voir')) {
3565 $sql .=
" AND sc.fk_user = ".((int) $user->id);
3568 $sql .=
" AND p.fk_soc = ".((int) $user->socid);
3573 if (empty($user->socid) && !$user->hasRight(
'societe',
'client',
'voir')) {
3574 $search_sale = $user->id;
3577 if ($search_sale && $search_sale !=
'-1') {
3578 if ($search_sale == -2) {
3579 $sql .=
" AND NOT EXISTS (SELECT sc.fk_soc FROM ".MAIN_DB_PREFIX.
"societe_commerciaux as sc WHERE sc.fk_soc = p.fk_soc)";
3580 } elseif ($search_sale > 0) {
3581 $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).
")";
3585 $sql .=
" AND p.fk_soc = ".((int) $user->socid);
3588 $parameters = array(
'socid' => $user->socid);
3589 $reshook = $hookmanager->executeHooks(
'printFieldListWhere', $parameters, $this);
3590 $sql .= $hookmanager->resPrint;
3592 $resql = $this->db->query($sql);
3594 $langs->load(
"propal");
3599 $label = $labelShort =
'';
3600 if ($mode ==
'opened') {
3603 $label = $langs->transnoentitiesnoconv(
"PropalsToClose");
3604 $labelShort = $langs->transnoentitiesnoconv(
"ToAcceptRefuse");
3606 if ($mode ==
'signed') {
3609 $label = $langs->trans(
"PropalsToBill");
3610 $labelShort = $langs->trans(
"ToBill");
3614 $response->warning_delay = $delay_warning / 60 / 60 / 24;
3615 $response->label = $label;
3616 $response->labelShort = $labelShort;
3617 $response->url =
dolBuildUrl(DOL_URL_ROOT.
'/comm/propal/list.php', [
'search_status' => $status,
'mainmenu' =>
'commercial',
'leftmenu' =>
'propals']);
3618 $response->url_late =
dolBuildUrl(DOL_URL_ROOT.
'/comm/propal/list.php', [
'search_option' =>
'late',
'mainmenu' =>
'commercial',
'leftmenu' =>
'propals',
'sortfield' =>
'p.datep',
'sortorder' =>
'asc']);
3622 while ($obj = $this->db->fetch_object($resql)) {
3623 $response->nbtodo++;
3624 $response->total += $obj->total_ht;
3626 if ($mode ==
'opened') {
3627 $datelimit = $this->db->jdate($obj->datefin);
3628 if ($datelimit < ($now - $delay_warning)) {
3629 $response->nbtodolate++;
3638 $this->error = $this->db->error();
3654 global
$conf, $langs;
3659 $sql =
"SELECT rowid";
3660 $sql .=
" FROM ".MAIN_DB_PREFIX.
"product";
3661 $sql .=
" WHERE entity IN (".getEntity(
'product').
")";
3662 if (array_key_exists(
'tosell', $param)) {
3663 $sql .=
" AND tosell = ".((int) $param[
'tosell']);
3665 $sql .= $this->db->plimit(100);
3667 $resql = $this->db->query($sql);
3669 $num_prods = $this->db->num_rows($resql);
3671 while ($i < $num_prods) {
3673 $row = $this->db->fetch_row($resql);
3674 $prodids[$i] = $row[0];
3680 $this->
ref =
'SPECIMEN';
3681 $this->ref_customer =
'NEMICEPS';
3682 $this->ref_client =
'NEMICEPS';
3683 $this->specimen = 1;
3685 $this->
date = time();
3686 $this->fin_validite = $this->
date + 3600 * 24 * 30;
3687 $this->cond_reglement_id = 1;
3688 $this->cond_reglement_code =
'RECEP';
3689 $this->mode_reglement_id = 7;
3690 $this->mode_reglement_code =
'CHQ';
3691 $this->availability_id = 1;
3692 $this->availability_code =
'AV_NOW';
3693 $this->demand_reason_id = 1;
3694 $this->demand_reason_code =
'SRC_00';
3695 $this->note_public =
'This is a comment (public)';
3696 $this->note_private =
'This is a comment (private)';
3698 $this->multicurrency_tx = 1;
3704 while ($xnbp < $nbp) {
3706 $line->desc = $langs->trans(
"Description").
" ".$xnbp;
3708 $line->subprice = 100;
3710 $line->localtax1_tx = 0;
3711 $line->localtax2_tx = 0;
3713 $line->total_ht = 50;
3714 $line->total_ttc = 60;
3715 $line->total_tva = 10;
3716 $line->remise_percent = 50;
3718 $line->total_ht = 100;
3719 $line->total_ttc = 120;
3720 $line->total_tva = 20;
3721 $line->remise_percent = 00;
3724 if ($num_prods > 0) {
3725 $prodid = mt_rand(1, $num_prods);
3726 $line->fk_product = $prodids[$prodid];
3727 $line->product_ref =
'SPECIMEN';
3730 $this->lines[$xnbp] = $line;
3732 $this->total_ht += $line->total_ht;
3733 $this->total_tva += $line->total_tva;
3734 $this->total_ttc += $line->total_ttc;
3749 global $user, $hookmanager;
3751 $this->nb = array();
3753 $sql =
"SELECT count(p.rowid) as nb";
3754 $sql .=
" FROM ".MAIN_DB_PREFIX.$this->table_element.
" as p";
3755 $sql .=
" LEFT JOIN ".MAIN_DB_PREFIX.
"societe as s ON p.fk_soc = s.rowid";
3756 $sql .=
" WHERE p.entity IN (".getEntity(
'propal').
")";
3760 if (empty($user->socid) && !$user->hasRight(
'societe',
'client',
'voir')) {
3761 $search_sale = $user->id;
3764 if ($search_sale && $search_sale !=
'-1') {
3765 if ($search_sale == -2) {
3766 $sql .=
" AND NOT EXISTS (SELECT sc.fk_soc FROM ".MAIN_DB_PREFIX.
"societe_commerciaux as sc WHERE sc.fk_soc = p.fk_soc)";
3767 } elseif ($search_sale > 0) {
3768 $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).
")";
3773 $parameters = array();
3774 $hookmanager->executeHooks(
'printFieldListWhere', $parameters, $this);
3775 $sql .= $hookmanager->resPrint;
3776 $resql = $this->db->query($sql);
3779 while ($obj = $this->db->fetch_object($resql)) {
3780 $this->nb[
"proposals"] = $obj->nb;
3782 $this->db->free($resql);
3786 $this->error = $this->db->error();
3799 public function getNextNumRef($soc)
3801 global
$conf, $langs;
3802 $langs->load(
"propal");
3806 if (!empty($classname)) {
3809 $file = $classname.
".php";
3812 $dirmodels = array_merge(array(
'/'), (array)
$conf->modules_parts[
'models']);
3813 foreach ($dirmodels as $reldir) {
3817 $mybool = ((bool) @include_once $dir.$file) || $mybool;
3825 $obj =
new $classname();
3826 '@phan-var-force ModeleNumRefPropales $obj';
3829 $numref = $obj->getNextValue($soc, $this);
3831 if ($numref !=
"") {
3834 $this->error = $obj->error;
3839 $langs->load(
"errors");
3840 print $langs->trans(
"Error").
" ".$langs->trans(
"ErrorModuleSetupNotComplete", $langs->transnoentitiesnoconv(
"Proposal"));
3853 global
$conf, $langs, $user;
3855 $langs->load(
'propal');
3857 $nofetch = !empty($params[
'nofetch']);
3860 return [
'optimize' => $langs->trans(
"Proposal")];
3862 if ($user->hasRight(
'propal',
'lire')) {
3863 $datas[
'picto'] =
img_picto(
'', $this->picto,
'', 0, 0, 0,
'',
'paddingrightonly').
'<u>'.$langs->trans(
"Proposal").
'</u>';
3864 if (isset($this->
status)) {
3865 $datas[
'status'] =
' '.$this->getLibStatut(5);
3867 if (!empty($this->
ref)) {
3868 $datas[
'ref'] =
'<br><b>'.$langs->trans(
'Ref').
':</b> '.$this->ref;
3871 $langs->load(
'companies');
3872 if (empty($this->thirdparty)) {
3875 $datas[
'customer'] =
'<br><b>'.$langs->trans(
'Customer').
':</b> '.$this->thirdparty->getNomUrl(1,
'', 0, 1);
3877 if (!empty($this->ref_customer)) {
3878 $datas[
'refcustomer'] =
'<br><b>'.$langs->trans(
'RefCustomer').
':</b> '.$this->ref_customer;
3881 $langs->load(
'project');
3882 if (is_null($this->project) || (is_object($this->project) && empty($this->project->id))) {
3884 if ($res > 0 && $this->project instanceof
Project) {
3885 $datas[
'project'] =
'<br><b>'.$langs->trans(
'Project').
':</b> '.$this->project->getNomUrl(1,
'', 0,
'1');
3889 if (!empty($this->total_ht)) {
3890 $datas[
'amountht'] =
'<br><b>'.$langs->trans(
'AmountHT').
':</b> '.
price($this->total_ht, 0, $langs, 0, -1, -1,
$conf->currency);
3892 if (!empty($this->total_tva)) {
3893 $datas[
'vat'] =
'<br><b>'.$langs->trans(
'VAT').
':</b> '.
price($this->total_tva, 0, $langs, 0, -1, -1,
$conf->currency);
3895 if (!empty($this->total_ttc)) {
3896 $datas[
'amountttc'] =
'<br><b>'.$langs->trans(
'AmountTTC').
':</b> '.
price($this->total_ttc, 0, $langs, 0, -1, -1,
$conf->currency);
3898 if (!empty($this->
date)) {
3899 $datas[
'date'] =
'<br><b>'.$langs->trans(
'Date').
':</b> '.
dol_print_date($this->
date,
'day');
3901 if (!empty($this->date_signature)) {
3902 $datas[
'datesignature'] =
'<br><b>'.$langs->trans(
'DateSigning').
':</b> '.
dol_print_date($this->date_signature,
'day');
3904 if (!empty($this->delivery_date)) {
3905 $datas[
'deliverydate'] =
'<br><b>'.$langs->trans(
'DeliveryDate').
':</b> '.
dol_print_date($this->delivery_date,
'dayhour');
3923 public function getNomUrl($withpicto = 0, $option =
'', $get_params =
'', $notooltip = 0, $save_lastsearch_value = -1, $addlinktonotes = -1)
3925 global $langs,
$conf, $user, $hookmanager;
3927 if (!empty(
$conf->dol_no_mouse_hover)) {
3934 'objecttype' => $this->element,
3935 'option' => $option,
3938 $classfortooltip =
'classfortooltip';
3941 $classfortooltip =
'classforajaxtooltip';
3942 $dataparams =
' data-params="'.dol_escape_htmltag(json_encode($params)).
'"';
3950 if ($user->hasRight(
'propal',
'lire')) {
3951 parse_str($get_params, $query);
3952 $query = array_merge($query, [
'id' => $this->
id]);
3953 if ($option ==
'') {
3954 $baseurl = DOL_URL_ROOT .
'/comm/propal/card.php';
3955 } elseif ($option ==
'compta') {
3956 $baseurl = DOL_URL_ROOT .
'/comm/propal/card.php';
3957 } elseif ($option ==
'expedition') {
3958 $baseurl = DOL_URL_ROOT .
'/expedition/propal.php';
3959 } elseif ($option ==
'document') {
3960 $baseurl = DOL_URL_ROOT .
'/comm/propal/document.php';
3963 if ($option !=
'nolink') {
3965 $add_save_lastsearch_values = ($save_lastsearch_value == 1 ? 1 : 0);
3966 if ($save_lastsearch_value == -1 && isset($_SERVER[
"PHP_SELF"]) && preg_match(
'/list\.php/', $_SERVER[
"PHP_SELF"])) {
3967 $add_save_lastsearch_values = 1;
3969 if ($add_save_lastsearch_values) {
3970 $query = array_merge($query, [
'save_lastsearch_values' => 1]);
3977 if (empty($notooltip) && $user->hasRight(
'propal',
'lire')) {
3979 $label = $langs->trans(
"Proposal");
3980 $linkclose .=
' alt="'.dolPrintHTMLForAttribute($label).
'"';
3982 $linkclose .= ($label ?
' title="'.dolPrintHTMLForAttribute($label).
'"' :
' title="tocomplete"');
3983 $linkclose .= $dataparams.
' class="'.$classfortooltip.
'"';
3986 $linkstart =
'<a href="'.$url.
'"';
3987 $linkstart .= $linkclose.
'>';
3990 $result .= $linkstart;
3992 $result .=
img_object(($notooltip ?
'' : $label), ($this->picto ? $this->picto :
'generic'), (($withpicto != 2) ?
'class="paddingright"' :
''), 0, 0, $notooltip ? 0 : 1);
3994 if ($withpicto != 2) {
3995 $result .= $this->ref;
3997 $result .= $linkend;
3999 if ($addlinktonotes >= 0) {
4002 if ($addlinktonotes == 0) {
4003 if (!empty($this->note_private) || !empty($this->note_public)) {
4004 $txttoshow = $langs->trans(
'ViewPrivateNote');
4006 } elseif ($addlinktonotes == 1) {
4007 if (!empty($this->note_private)) {
4010 } elseif ($addlinktonotes == 2) {
4011 if (!empty($this->note_public)) {
4014 } elseif ($addlinktonotes == 3) {
4015 if ($user->socid > 0) {
4016 if (!empty($this->note_public)) {
4020 if (!empty($this->note_public)) {
4023 if (!empty($this->note_private)) {
4024 if (!empty($txttoshow)) {
4025 $txttoshow .=
'<br><br>';
4033 $result .=
' <span class="note inline-block">';
4034 $result .=
'<a href="'.dolBuildUrl(DOL_URL_ROOT.
'/comm/propal/note.php', [
'id' => $this->id]).
'" class="classfortooltip" title="'.
dol_escape_htmltag($txttoshow).
'">';
4037 $result .=
'</span>';
4042 $hookmanager->initHooks(array($this->element .
'dao'));
4043 $parameters = array(
'id' => $this->
id,
'getnomurl' => &$result);
4044 $reshook = $hookmanager->executeHooks(
'getNomUrl', $parameters, $this, $action);
4046 $result = $hookmanager->resPrint;
4048 $result .= $hookmanager->resPrint;
4061 return $this->
fetch_lines(0, 0, $sqlforgedfilters);
4075 public function generateDocument($modele, $outputlangs, $hidedetails = 0, $hidedesc = 0, $hideref = 0, $moreparams =
null)
4077 $outputlangs->loadLangs(array(
"propale",
"products"));
4082 if ($this->model_pdf) {
4083 $modele = $this->model_pdf;
4087 $modelpath =
"core/modules/propale/doc/";
4089 return $this->
commonGenerateDocument($modelpath, $modele, $outputlangs, $hidedetails, $hidedesc, $hideref, $moreparams);
4137 $selected = (empty($arraydata[
'selected']) ? 0 : $arraydata[
'selected']);
4139 $return =
'<div class="box-flex-item box-flex-grow-zero">';
4140 $return .=
'<div class="info-box info-box-sm">';
4141 $return .=
'<div class="info-box-icon bg-infobox-action">';
4143 $return .=
'</div>';
4144 $return .=
'<div class="info-box-content">';
4145 $return .=
'<span class="info-box-ref inline-block tdoverflowmax150 valignmiddle">' . $this->
getNomUrl() .
'</span>';
4146 if ($selected >= 0) {
4147 $return .=
'<input id="cb'.$this->id.
'" class="flat checkforselect fright" type="checkbox" name="toselect[]" value="'.$this->
id.
'"'.($selected ?
' checked="checked"' :
'').
'>';
4149 if (!empty($arraydata[
'projectlink'])) {
4150 $return .=
'<span class="info-box-ref"> | '.$arraydata[
'projectlink'].
'</span>';
4153 if (is_object($this->thirdparty)) {
4154 $return .=
'<div class="info-box-ref tdoverflowmax150">'.$this->thirdparty->getNomUrl(1).
'</div>';
4156 $return .=
'<span class="info-box-label amount" title="'.$langs->trans(
"AmountHT").
'">'.
price($this->total_ht).
'</span>';
4157 if (!empty($arraydata[
'authorlink'])) {
4158 $return .=
' <span class="info-box-label">'.$arraydata[
'authorlink'].
'</span>';
4160 $return .=
'<br><div class="info-box-status">'.$this->getLibStatut(3).
'</div>';
4161 $return .=
'</div>';
4162 $return .=
'</div>';
4163 $return .=
'</div>';
4179 require_once DOL_DOCUMENT_ROOT.
'/categories/class/categorie.class.php';
4180 return parent::setCategoriesCommon($categories, Categorie::TYPE_PROPOSAL);
$id
Support class for third parties, contacts, members, users or resources.
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.
$date_start
Variables from include:
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)
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 '.
dolBuildUrl($url, $params=[], $addtoken=false, $anchor='')
Return path of url.
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.
GETPOST($paramname, $check='alphanohtml', $method=0, $filter=null, $options=null, $noreplace=0, $nodefault=0)
Return value of a param into GET or POST supervariable.
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.
GETPOSTINT($paramname, $method=0, $nodefault=0)
Return the value of a $_GET or $_POST supervariable, converted into integer.
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...
dol_trunc($string, $size=40, $trunc='right', $stringencoding='UTF-8', $nodot=0, $display=0)
Truncate a string to a particular length adding '...' if string larger than length.
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...
print $langs trans("Show") . '< td style="' . $timeColor . '" align="center"> s</td > badge status0 badge status4 badge status3 Error badge status8< td align="center">< span class="badge ' . $badge . '"></span ></td >< td align="center">< a href="#" class="button button-small" onclick="openLogModal(this)" data-req="' . dol_escape_htmltag($reqSafe) . '" data-res="' . dol_escape_htmltag($resSafe) . '" data-err="' . dol_escape_htmltag($errSafe) . '">< span class="fa fa-search-plus"></span ></a ></td ></tr >< tr >< td colspan="' . $colspan . '" class="opacitymedium"></td ></tr ></table ></div ></form > logModal none logModal none s a JSON string
buildzip.php
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, $notused, $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.
print $langs trans('Date')." left Ref 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 Paid right PaymentTypeShortLIQ right SELECT p pos_change as p datep as date