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);
752 if (abs((
float) $qty) < $tmpproduct->packaging) {
753 $qty = (float) $tmpproduct->packaging;
754 setEventMessages($langs->trans(
'QtyRecalculatedWithPackaging'),
null,
'warnings');
756 if (!empty($tmpproduct->packaging) && (
float)
price2num(fmod((
float) $qty, (
float) $tmpproduct->packaging),
'MS')) {
757 $coeff = intval(abs((
float) $qty) / $tmpproduct->packaging) + 1;
758 $qty =
price2num((
float) $tmpproduct->packaging * $coeff,
'MS');
759 setEventMessages($langs->trans(
'QtyRecalculatedWithPackaging'),
null,
'warnings');
767 if (preg_match(
'/\((.*)\)/', $txtva, $reg)) {
768 $vat_src_code = $reg[1];
769 $txtva = preg_replace(
'/\s*\(.*\)/',
'', $txtva);
772 $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);
774 $total_ht = $tabprice[0];
775 $total_tva = $tabprice[1];
776 $total_ttc = $tabprice[2];
777 $total_localtax1 = $tabprice[9];
778 $total_localtax2 = $tabprice[10];
779 $pu_ht = $tabprice[3];
780 $pu_tva = $tabprice[4];
781 $pu_ttc = $tabprice[5];
784 $multicurrency_total_ht = $tabprice[16];
785 $multicurrency_total_tva = $tabprice[17];
786 $multicurrency_total_ttc = $tabprice[18];
787 $pu_ht_devise = $tabprice[19];
791 if (empty($ranktouse) || $ranktouse == -1) {
792 $rangmax = $this->
line_max($fk_parent_line);
793 $ranktouse = $rangmax + 1;
799 $this->line->context = $this->context;
801 $this->line->fk_propal = $this->id;
802 $this->line->label = $label;
803 $this->line->desc = $desc;
804 $this->line->qty = (float) $qty;
806 $this->line->vat_src_code = $vat_src_code;
807 $this->line->tva_tx = $txtva;
808 $this->line->localtax1_tx = ($total_localtax1 ? $localtaxes_type[1] : 0);
809 $this->line->localtax2_tx = ($total_localtax2 ? $localtaxes_type[3] : 0);
810 $this->line->localtax1_type = empty($localtaxes_type[0]) ?
'' : $localtaxes_type[0];
811 $this->line->localtax2_type = empty($localtaxes_type[2]) ?
'' : $localtaxes_type[2];
812 $this->line->fk_product = $fk_product;
813 $this->line->product_type = $type;
814 $this->line->fk_remise_except = $fk_remise_except;
815 $this->line->remise_percent = $remise_percent;
816 $this->line->subprice = (float) $pu_ht;
818 $this->line->subprice_ttc = ($price_base_type ===
'TTC') ? (
float) $pu_ttc : 0;
819 $this->line->rang = $ranktouse;
820 $this->line->info_bits = $info_bits;
821 $this->line->total_ht = (float) $total_ht;
822 $this->line->total_tva = (float) $total_tva;
823 $this->line->total_localtax1 = (float) $total_localtax1;
824 $this->line->total_localtax2 = (float) $total_localtax2;
825 $this->line->total_ttc = (float) $total_ttc;
826 $this->line->special_code = $special_code;
827 $this->line->fk_parent_line = $fk_parent_line;
828 $this->line->fk_unit = $fk_unit;
831 $this->line->date_end = $date_end;
833 $this->line->fk_fournprice = $fk_fournprice;
834 $this->line->pa_ht = $pa_ht;
836 $this->line->origin_id = $origin_id;
837 $this->line->origin = $origin;
840 $this->line->fk_multicurrency = $this->fk_multicurrency;
841 $this->line->multicurrency_code = $this->multicurrency_code;
842 $this->line->multicurrency_subprice = (float) $pu_ht_devise;
843 $this->line->multicurrency_total_ht = (float) $multicurrency_total_ht;
844 $this->line->multicurrency_total_tva = (float) $multicurrency_total_tva;
845 $this->line->multicurrency_total_ttc = (float) $multicurrency_total_ttc;
848 if (empty($qty) && empty($special_code)) {
849 $this->line->special_code = 3;
852 if (is_array($array_options) && count($array_options) > 0) {
853 $this->line->array_options = $array_options;
856 $result = $this->line->insert();
858 if (!isset($this->context[
'createfromclone'])) {
859 if (!empty($fk_parent_line)) {
862 } elseif ($ranktouse > 0 && $ranktouse <= count($this->lines)) {
864 $linecount = count($this->lines);
865 for ($ii = $ranktouse; $ii <= $linecount; $ii++) {
870 $this->lines[] = $this->line;
873 foreach ($this->lines as $tmpline) {
874 if ($tmpline->id == $origin_id && $tmpline->element == $origin) {
875 $this->line->extraparams = $tmpline->extraparams;
876 $this->line->setExtraParameters();
882 if (empty($noupdateafterinsertline)) {
888 return $this->line->id;
890 $this->error = $this->db->error();
891 $this->db->rollback();
896 $this->db->rollback();
900 dol_syslog(get_class($this).
"::addline status of proposal must be Draft to allow use of ->addline()", LOG_ERR);
935 public function updateline($rowid, $pu, $qty, $remise_percent, $txtva, $txlocaltax1 = 0.0, $txlocaltax2 = 0.0, $desc =
'', $price_base_type =
'HT', $info_bits = 0, $special_code = 0, $fk_parent_line = 0, $skip_update_total = 0, $fk_fournprice = 0, $pa_ht = 0, $label =
'', $type = 0,
$date_start =
'', $date_end =
'', $array_options = array(), $fk_unit =
null, $pu_ht_devise = 0, $notrigger = 0, $rang = 0)
939 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);
989 $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);
990 $total_ht = $tabprice[0];
991 $total_tva = $tabprice[1];
992 $total_ttc = $tabprice[2];
993 $total_localtax1 = $tabprice[9];
994 $total_localtax2 = $tabprice[10];
995 $pu_ht = $tabprice[3];
996 $pu_tva = $tabprice[4];
997 $pu_ttc = $tabprice[5];
1000 $multicurrency_total_ht = $tabprice[16];
1001 $multicurrency_total_tva = $tabprice[17];
1002 $multicurrency_total_ttc = $tabprice[18];
1003 $pu_ht_devise = $tabprice[19];
1007 $line->fetch($rowid);
1009 $staticline = clone $line;
1011 $line->oldline = $staticline;
1012 $this->line = $line;
1013 $this->line->context = $this->context;
1014 $this->line->rang = $rang;
1017 if (!empty($fk_parent_line) && !empty($staticline->fk_parent_line) && $fk_parent_line != $staticline->fk_parent_line) {
1018 $rangmax = $this->
line_max($fk_parent_line);
1019 $this->line->rang = $rangmax + 1;
1023 if (abs((
float) $qty) < $this->line->packaging) {
1024 $qty = $this->line->packaging;
1025 setEventMessage($langs->trans(
'QtyRecalculatedWithPackaging'),
'warnings');
1027 if (!empty($this->line->packaging)
1028 && is_numeric($this->line->packaging)
1029 && (
float) $this->line->packaging > 0
1030 && (
float)
price2num(fmod((
float) $qty, (
float) $this->line->packaging),
'MS')) {
1031 $coeff = intval(abs((
float) $qty) / $this->line->packaging) + 1;
1032 $qty = $this->line->packaging * $coeff;
1033 setEventMessage($langs->trans(
'QtyRecalculatedWithPackaging'),
'warnings');
1038 $this->line->id = $rowid;
1039 $this->line->label = $label;
1040 $this->line->desc = $desc;
1041 $this->line->qty = $qty;
1042 $this->line->product_type = $type;
1043 $this->line->vat_src_code = $vat_src_code;
1044 $this->line->tva_tx = $txtva;
1045 $this->line->localtax1_tx = $txlocaltax1;
1046 $this->line->localtax2_tx = $txlocaltax2;
1047 $this->line->localtax1_type = empty($localtaxes_type[0]) ?
'' : $localtaxes_type[0];
1048 $this->line->localtax2_type = empty($localtaxes_type[2]) ?
'' : $localtaxes_type[2];
1049 $this->line->remise_percent = $remise_percent;
1050 $this->line->subprice = (float) $pu_ht;
1052 $this->line->subprice_ttc = ($price_base_type ===
'TTC') ? (
float) $pu_ttc : 0;
1053 $this->line->info_bits = $info_bits;
1055 $this->line->total_ht = (float) $total_ht;
1056 $this->line->total_tva = (float) $total_tva;
1057 $this->line->total_localtax1 = (float) $total_localtax1;
1058 $this->line->total_localtax2 = (float) $total_localtax2;
1059 $this->line->total_ttc = (float) $total_ttc;
1060 $this->line->special_code = $special_code;
1061 $this->line->fk_parent_line = $fk_parent_line;
1062 $this->line->skip_update_total = $skip_update_total;
1063 $this->line->fk_unit = $fk_unit;
1065 $this->line->fk_fournprice = $fk_fournprice;
1066 $this->line->pa_ht = $pa_ht;
1069 $this->line->date_end = $date_end;
1071 if (is_array($array_options) && count($array_options) > 0) {
1073 foreach ($array_options as $key => $value) {
1074 $this->line->array_options[$key] = $array_options[$key];
1079 $this->line->multicurrency_subprice = (float) $pu_ht_devise;
1080 $this->line->multicurrency_total_ht = (float) $multicurrency_total_ht;
1081 $this->line->multicurrency_total_tva = (float) $multicurrency_total_tva;
1082 $this->line->multicurrency_total_ttc = (float) $multicurrency_total_ttc;
1084 $result = $this->line->update($notrigger);
1087 if (!empty($fk_parent_line)) {
1097 $this->db->commit();
1101 $this->db->rollback();
1105 dol_syslog(get_class($this).
"::updateline Erreur -2 Propal en mode incompatible pour cette action");
1122 if ($this->
status == self::STATUS_DRAFT) {
1127 $line->context = $this->context;
1130 $line->fetch($lineid);
1132 if ($id > 0 && $line->fk_propal != $id) {
1133 $this->error =
'ErrorLineIDDoesNotMatchWithObjectID';
1138 $staticline = clone $line;
1139 $line->oldline = $staticline;
1141 if ($line->delete($user) > 0) {
1144 $this->db->commit();
1148 $this->db->rollback();
1152 $this->error =
'ErrorDeleteLineNotAllowedByObjectStatus';
1166 public function create($user, $notrigger = 0)
1175 if (empty($this->
date)) {
1176 $this->
date = $this->datep;
1178 $this->fin_validite = $this->
date + ($this->duree_validite * 24 * 3600);
1179 if (empty($this->availability_id)) {
1180 $this->availability_id = 0;
1182 if (empty($this->demand_reason_id)) {
1183 $this->demand_reason_id = 0;
1187 if (!empty($this->multicurrency_code) && empty($this->multicurrency_tx)) {
1192 if (empty($this->fk_multicurrency)) {
1194 $this->fk_multicurrency = 0;
1195 $this->multicurrency_tx = 1;
1201 $delivery_date = $this->delivery_date;
1208 $this->error =
"Failed to fetch company";
1209 dol_syslog(get_class($this).
"::create ".$this->error, LOG_ERR);
1214 if (!empty($this->
ref)) {
1217 $this->error =
'ErrorRefAlreadyExists';
1218 dol_syslog(get_class($this).
"::create ".$this->error, LOG_WARNING);
1219 $this->db->rollback();
1224 if (empty($this->
date)) {
1225 $this->error =
"Date of proposal is required";
1226 dol_syslog(get_class($this).
"::create ".$this->error, LOG_ERR);
1234 $sql =
"INSERT INTO ".MAIN_DB_PREFIX.$this->table_element.
" (";
1237 $sql .=
", total_tva";
1238 $sql .=
", total_ttc";
1242 $sql .=
", fk_user_author";
1243 $sql .=
", note_private";
1244 $sql .=
", note_public";
1245 $sql .=
", model_pdf";
1246 $sql .=
", fin_validite";
1247 $sql .=
", fk_cond_reglement";
1248 $sql .=
", deposit_percent";
1249 $sql .=
", fk_mode_reglement";
1250 $sql .=
", fk_account";
1251 $sql .=
", ref_client";
1252 $sql .=
", ref_ext";
1253 $sql .=
", date_livraison";
1254 $sql .=
", fk_shipping_method";
1255 $sql .=
", fk_warehouse";
1256 $sql .=
", fk_availability";
1257 $sql .=
", fk_input_reason";
1258 $sql .=
", fk_projet";
1259 $sql .=
", fk_incoterms";
1260 $sql .=
", location_incoterms";
1262 $sql .=
", fk_multicurrency";
1263 $sql .=
", multicurrency_code";
1264 $sql .=
", multicurrency_tx";
1266 $sql .=
" VALUES (";
1267 $sql .= ((int) $this->socid);
1271 $sql .=
", '".$this->db->idate($this->
date).
"'";
1272 $sql .=
", '".$this->db->idate($now).
"'";
1273 $sql .=
", '(PROV)'";
1274 $sql .=
", ".($user->id > 0 ? ((int) $user->id) :
"NULL");
1275 $sql .=
", '".$this->db->escape($this->note_private).
"'";
1276 $sql .=
", '".$this->db->escape($this->note_public).
"'";
1277 $sql .=
", '".$this->db->escape($this->model_pdf).
"'";
1278 $sql .=
", ".($this->fin_validite !=
'' ?
"'".$this->db->idate($this->fin_validite).
"'" :
"NULL");
1279 $sql .=
", ".($this->cond_reglement_id > 0 ? ((int) $this->cond_reglement_id) :
'NULL');
1280 $sql .=
", ".(!empty($this->deposit_percent) ?
"'".$this->db->escape($this->deposit_percent).
"'" :
'NULL');
1281 $sql .=
", ".($this->mode_reglement_id > 0 ? ((int) $this->mode_reglement_id) :
'NULL');
1282 $sql .=
", ".($this->fk_account > 0 ? ((int) $this->fk_account) :
'NULL');
1283 $sql .=
", '".$this->db->escape((
string) $this->ref_client).
"'";
1284 $sql .=
", '".$this->db->escape((
string) $this->ref_ext).
"'";
1285 $sql .=
", ".(!
isDolTms($delivery_date) ?
"NULL" :
"'".$this->db->idate($delivery_date).
"'");
1286 $sql .=
", ".($this->shipping_method_id > 0 ? ((int) $this->shipping_method_id) :
'NULL');
1287 $sql .=
", ".($this->warehouse_id > 0 ? ((int) $this->warehouse_id) :
'NULL');
1288 $sql .=
", ".((int) $this->availability_id);
1289 $sql .=
", ".((int) $this->demand_reason_id);
1290 $sql .=
", ".($this->fk_project ? ((int) $this->fk_project) :
"null");
1291 $sql .=
", ".(int) $this->fk_incoterms;
1292 $sql .=
", '".$this->db->escape($this->location_incoterms).
"'";
1293 $sql .=
", ".(int) $this->entity;
1294 $sql .=
", ".(int) $this->fk_multicurrency;
1295 $sql .=
", '".$this->db->escape($this->multicurrency_code).
"'";
1296 $sql .=
", ".(float) $this->multicurrency_tx;
1299 dol_syslog(get_class($this).
"::create", LOG_DEBUG);
1300 $resql = $this->db->query($sql);
1302 $this->
id = $this->db->last_insert_id(MAIN_DB_PREFIX.$this->table_element);
1305 $this->
ref =
'(PROV'.$this->id.
')';
1306 $sql =
'UPDATE '.MAIN_DB_PREFIX.$this->table_element.
" SET ref='".$this->db->escape($this->
ref).
"' WHERE rowid=".((int) $this->
id);
1308 dol_syslog(get_class($this).
"::create", LOG_DEBUG);
1309 $resql = $this->db->query($sql);
1314 if (!empty($this->linkedObjectsIds) && empty($this->linked_objects)) {
1315 $this->linked_objects = $this->linkedObjectsIds;
1319 if (!$error && !empty($this->linked_objects) && is_array($this->linked_objects)) {
1320 foreach ($this->linked_objects as $origin => $tmp_origin_id) {
1321 if (is_array($tmp_origin_id)) {
1322 foreach ($tmp_origin_id as $origin_id) {
1325 $this->error = $this->db->lasterror();
1330 $origin_id = $tmp_origin_id;
1333 $this->error = $this->db->lasterror();
1344 $fk_parent_line = 0;
1345 $num = count($this->lines);
1347 for ($i = 0; $i < $num; $i++) {
1348 if (!is_object($this->lines[$i])) {
1350 $line = (object) $this->lines[$i];
1352 $line = $this->lines[$i];
1355 if (($line->product_type != 9 && empty($line->fk_parent_line)) || $line->product_type == 9) {
1356 $fk_parent_line = 0;
1359 $vatrate = $line->tva_tx;
1360 if ($line->vat_src_code && !preg_match(
'/\(.*\)/', $vatrate)) {
1361 $vatrate .=
' ('.$line->vat_src_code.
')';
1365 $originid = $line->origin_id;
1366 $origintype = empty($line->origin_type) ? $line->origin : $line->origin_type;
1368 $originid = $line->id;
1369 $origintype = $this->element;
1373 $line_price_base_type = $line->getPriceBaseType();
1376 (
float) $line->subprice,
1379 $line->localtax1_tx,
1380 $line->localtax2_tx,
1382 $line->remise_percent,
1383 $line_price_base_type,
1384 (
float) $line->subprice_ttc,
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;
1415 if ($result > 0 && $line->product_type == 9) {
1416 $fk_parent_line = $result;
1431 if (!$error && !$notrigger) {
1433 $result = $this->call_trigger(
'PROPAL_CREATE', $user);
1440 $this->error = $this->db->lasterror();
1445 $this->error = $this->db->lasterror();
1450 $this->db->commit();
1451 dol_syslog(get_class($this).
"::create done id=".$this->
id);
1454 $this->db->rollback();
1458 $this->error = $this->db->lasterror();
1459 $this->db->rollback();
1474 public function createFromClone(
User $user, $socid = 0, $forceentity =
null, $update_prices =
false, $update_desc =
false)
1485 $object =
new self($this->db);
1492 $objsoc =
new Societe($this->db);
1495 if (!empty($socid) && $socid !=
$object->socid) {
1496 if ($objsoc->fetch($socid) > 0) {
1498 $object->cond_reglement_id = (!empty($objsoc->cond_reglement_id) ? $objsoc->cond_reglement_id : 0);
1499 $object->deposit_percent = (!empty($objsoc->deposit_percent) ? $objsoc->deposit_percent :
null);
1500 $object->mode_reglement_id = (!empty($objsoc->mode_reglement_id) ? $objsoc->mode_reglement_id : 0);
1501 $object->fk_delivery_address = 0;
1524 $objsoc->fetch(
$object->socid);
1528 if ($update_prices ===
true || $update_desc ===
true) {
1529 if ($objsoc->id > 0 && !empty(
$object->lines)) {
1532 require_once DOL_DOCUMENT_ROOT .
'/product/class/productcustomerprice.class.php';
1535 foreach (
$object->lines as $line) {
1538 if ($line->fk_product > 0) {
1540 $res =
$prod->fetch($line->fk_product);
1542 if ($update_prices ===
true) {
1543 $pu_ht =
$prod->price;
1545 $remise_percent = $objsoc->remise_percent;
1548 $pu_ht =
$prod->multiprices[$objsoc->price_level];
1550 if (isset(
$prod->multiprices_tva_tx[$objsoc->price_level])) {
1551 $tva_tx = (
string)
$prod->multiprices_tva_tx[$objsoc->price_level];
1556 $filter = array(
't.fk_product' => (
string)
$prod->id,
't.fk_soc' => (
string) $objsoc->id);
1557 $result = $prodcustprice->fetchAll(
'',
'', 0, 0, $filter);
1560 if (count($prodcustprice->lines) > 0) {
1561 $date_now = (int) floor(
dol_now() / 86400) * 86400;
1562 foreach ($prodcustprice->lines as $k => $custprice_line) {
1563 if ($custprice_line->date_begin <= $date_now && (empty($custprice_line->date_end) || $date_now <= $custprice_line->date_end)) {
1564 $pu_ht =
price($custprice_line->price);
1565 $tva_tx = ($custprice_line->default_vat_code ? $custprice_line->tva_tx .
' (' . $custprice_line->default_vat_code .
' )' : $custprice_line->tva_tx);
1566 if ($custprice_line->default_vat_code && !preg_match(
'/\(.*\)/', $tva_tx)) {
1567 $tva_tx .=
' (' . $custprice_line->default_vat_code .
')';
1569 $remise_percent = $custprice_line->discount_percent;
1577 $line->subprice = $pu_ht;
1578 $line->tva_tx = $tva_tx;
1579 $line->remise_percent = $remise_percent;
1581 if ($update_desc ===
true) {
1582 $line->desc =
$prod->description;
1592 $object->entity = (!empty($forceentity) ? $forceentity :
$object->entity);
1597 $object->user_creation_id = $user->id;
1598 $object->user_validation_id = 0;
1611 $object->context[
'createfromclone'] =
'createfromclone';
1612 $result =
$object->create($user);
1620 if (
$object->copy_linked_contact($this,
'internal') < 0) {
1627 if ($this->socid ==
$object->socid) {
1628 if (
$object->copy_linked_contact($this,
'external') < 0) {
1636 if (is_object($hookmanager)) {
1637 $parameters = array(
'objFrom' => $this,
'clonedObj' =>
$object);
1639 $reshook = $hookmanager->executeHooks(
'createFrom', $parameters,
$object, $action);
1647 unset(
$object->context[
'createfromclone']);
1651 $this->db->commit();
1654 $this->db->rollback();
1668 public function fetch($rowid, $ref =
'', $ref_ext =
'', $forceentity = 0)
1670 $sql =
"SELECT p.rowid, p.ref, p.entity, p.fk_soc";
1671 $sql .=
", p.total_ttc, p.total_tva, p.localtax1, p.localtax2, p.total_ht";
1672 $sql .=
", p.datec";
1673 $sql .=
", p.date_signature as dates";
1674 $sql .=
", p.date_valid as datev";
1675 $sql .=
", p.date_cloture";
1676 $sql .=
", p.datep as dp";
1677 $sql .=
", p.fin_validite as dfv";
1678 $sql .=
", p.date_livraison as delivery_date";
1679 $sql .=
", p.model_pdf, p.last_main_doc, p.ref_client, ref_ext, p.extraparams";
1680 $sql .=
", p.note_private, p.note_public";
1681 $sql .=
", p.fk_projet as fk_project, p.fk_statut";
1682 $sql .=
", p.fk_user_author, p.fk_user_valid, p.fk_user_cloture";
1683 $sql .=
", p.fk_delivery_address";
1684 $sql .=
", p.fk_availability";
1685 $sql .=
", p.fk_input_reason";
1686 $sql .=
", p.fk_cond_reglement";
1687 $sql .=
", p.fk_mode_reglement";
1688 $sql .=
', p.fk_account';
1689 $sql .=
", p.fk_shipping_method";
1690 $sql .=
", p.fk_warehouse";
1691 $sql .=
", p.fk_incoterms, p.location_incoterms";
1692 $sql .=
", p.fk_multicurrency, p.multicurrency_code, p.multicurrency_tx, p.multicurrency_total_ht, p.multicurrency_total_tva, p.multicurrency_total_ttc";
1693 $sql .=
", p.tms as date_modification";
1694 $sql .=
", i.libelle as label_incoterms";
1695 $sql .=
", c.label as statut_label";
1696 $sql .=
", ca.code as availability_code, ca.label as availability";
1697 $sql .=
", dr.code as demand_reason_code, dr.label as demand_reason";
1698 $sql .=
", cr.code as cond_reglement_code, cr.libelle as cond_reglement, cr.libelle_facture as cond_reglement_libelle_doc, p.deposit_percent";
1699 $sql .=
", cp.code as mode_reglement_code, cp.libelle as mode_reglement";
1700 $sql .=
" FROM ".MAIN_DB_PREFIX.$this->table_element.
" as p";
1701 $sql .=
' LEFT JOIN '.MAIN_DB_PREFIX.
'c_propalst as c ON p.fk_statut = c.id';
1702 $sql .=
' LEFT JOIN '.MAIN_DB_PREFIX.
'c_paiement as cp ON p.fk_mode_reglement = cp.id AND cp.entity IN ('.
getEntity(
'c_paiement').
')';
1703 $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').
')';
1704 $sql .=
' LEFT JOIN '.MAIN_DB_PREFIX.
'c_availability as ca ON p.fk_availability = ca.rowid';
1705 $sql .=
' LEFT JOIN '.MAIN_DB_PREFIX.
'c_input_reason as dr ON p.fk_input_reason = dr.rowid';
1706 $sql .=
' LEFT JOIN '.MAIN_DB_PREFIX.
'c_incoterms as i ON p.fk_incoterms = i.rowid';
1709 if (!empty($forceentity)) {
1710 $sql .=
" WHERE p.entity = ".(int) $forceentity;
1712 $sql .=
" WHERE p.entity IN (".getEntity(
'propal').
")";
1714 $sql .=
" AND p.ref='".$this->db->escape($ref).
"'";
1717 $sql .=
" WHERE p.rowid = ".((int) $rowid);
1720 dol_syslog(get_class($this).
"::fetch", LOG_DEBUG);
1721 $resql = $this->db->query($sql);
1723 if ($this->db->num_rows($resql)) {
1724 $obj = $this->db->fetch_object($resql);
1726 $this->
id = $obj->rowid;
1727 $this->entity = $obj->entity;
1729 $this->
ref = $obj->ref;
1730 $this->ref_client = $obj->ref_client;
1731 $this->ref_customer = $obj->ref_client;
1732 $this->ref_ext = $obj->ref_ext;
1734 $this->total = $obj->total_ttc;
1735 $this->total_ttc = $obj->total_ttc;
1736 $this->total_ht = $obj->total_ht;
1737 $this->total_tva = $obj->total_tva;
1738 $this->total_localtax1 = $obj->localtax1;
1739 $this->total_localtax2 = $obj->localtax2;
1741 $this->socid = $obj->fk_soc;
1742 $this->thirdparty =
null;
1744 $this->fk_project = $obj->fk_project;
1745 $this->project =
null;
1747 $this->model_pdf = $obj->model_pdf;
1748 $this->last_main_doc = $obj->last_main_doc;
1749 $this->note = $obj->note_private;
1750 $this->note_private = $obj->note_private;
1751 $this->note_public = $obj->note_public;
1753 $this->
status = (int) $obj->fk_statut;
1754 $this->statut = $this->status;
1756 $this->datec = $this->db->jdate($obj->datec);
1757 $this->datev = $this->db->jdate($obj->datev);
1758 $this->date_creation = $this->db->jdate($obj->datec);
1759 $this->date_validation = $this->db->jdate($obj->datev);
1760 $this->date_modification = $this->db->jdate($obj->date_modification);
1761 $this->date_signature = $this->db->jdate($obj->dates);
1762 $this->date_cloture = $this->db->jdate($obj->date_cloture);
1763 $this->
date = $this->db->jdate($obj->dp);
1764 $this->datep = $this->db->jdate($obj->dp);
1765 $this->fin_validite = $this->db->jdate($obj->dfv);
1766 $this->delivery_date = $this->db->jdate($obj->delivery_date);
1767 $this->shipping_method_id = ($obj->fk_shipping_method > 0) ? $obj->fk_shipping_method :
null;
1768 $this->warehouse_id = ($obj->fk_warehouse > 0) ? $obj->fk_warehouse :
null;
1769 $this->availability_id = $obj->fk_availability;
1770 $this->availability_code = $obj->availability_code;
1772 $this->demand_reason_id = $obj->fk_input_reason;
1773 $this->demand_reason_code = $obj->demand_reason_code;
1775 $this->fk_address = $obj->fk_delivery_address;
1777 $this->mode_reglement_id = $obj->fk_mode_reglement;
1778 $this->mode_reglement_code = $obj->mode_reglement_code;
1779 $this->mode_reglement = $obj->mode_reglement;
1780 $this->fk_account = ($obj->fk_account > 0) ? $obj->fk_account :
null;
1781 $this->cond_reglement_id = $obj->fk_cond_reglement;
1782 $this->cond_reglement_code = $obj->cond_reglement_code;
1783 $this->cond_reglement = $obj->cond_reglement;
1784 $this->cond_reglement_doc = $obj->cond_reglement_libelle_doc;
1785 $this->deposit_percent = $obj->deposit_percent;
1787 $this->extraparams = !empty($obj->extraparams) ? (array) json_decode($obj->extraparams,
true) : array();
1789 $this->user_author_id = $obj->fk_user_author;
1790 $this->user_validation_id = $obj->fk_user_valid;
1791 $this->user_closing_id = $obj->fk_user_cloture;
1794 $this->fk_incoterms = $obj->fk_incoterms;
1795 $this->location_incoterms = $obj->location_incoterms;
1796 $this->label_incoterms = $obj->label_incoterms;
1799 $this->fk_multicurrency = $obj->fk_multicurrency;
1800 $this->multicurrency_code = $obj->multicurrency_code;
1801 $this->multicurrency_tx = $obj->multicurrency_tx;
1802 $this->multicurrency_total_ht = $obj->multicurrency_total_ht;
1803 $this->multicurrency_total_tva = $obj->multicurrency_total_tva;
1804 $this->multicurrency_total_ttc = $obj->multicurrency_total_ttc;
1810 $this->db->free($resql);
1812 $this->lines = array();
1823 $this->error =
"Record Not Found";
1826 $this->error = $this->db->lasterror();
1843 if (isset($this->
ref)) {
1844 $this->
ref = trim($this->
ref);
1846 if (isset($this->ref_client)) {
1847 $this->ref_client = trim($this->ref_client);
1849 if (isset($this->note) || isset($this->note_private)) {
1850 $this->note_private = (isset($this->note_private) ? trim($this->note_private) : trim($this->note));
1852 if (isset($this->note_public)) {
1853 $this->note_public = trim($this->note_public);
1855 if (isset($this->model_pdf)) {
1856 $this->model_pdf = trim($this->model_pdf);
1858 if (isset($this->import_key)) {
1859 $this->import_key = trim($this->import_key);
1861 if (!empty($this->duree_validite) && is_numeric($this->duree_validite)) {
1862 $this->fin_validite = $this->
date + ($this->duree_validite * 24 * 3600);
1869 $sql =
"UPDATE ".MAIN_DB_PREFIX.$this->table_element.
" SET";
1870 $sql =
"UPDATE ".MAIN_DB_PREFIX.
"propal SET";
1871 $sql .=
" ref = ".(isset($this->
ref) ?
"'".$this->db->escape($this->
ref).
"'" :
"null").
",";
1872 $sql .=
" ref_client = ".(isset($this->ref_client) ?
"'".$this->db->escape($this->ref_client).
"'" :
"null").
",";
1873 $sql .=
" ref_ext = ".(isset($this->ref_ext) ?
"'".$this->db->escape($this->ref_ext).
"'" :
"null").
",";
1874 $sql .=
" fk_soc = ".(!empty($this->socid) ? (int) $this->socid :
"null").
",";
1875 $sql .=
" datep = ".(strval($this->
date) !=
'' ?
"'".$this->db->idate($this->
date).
"'" :
'null').
",";
1876 if (!empty($this->fin_validite)) {
1877 $sql .=
" fin_validite = ".(strval($this->fin_validite) !=
'' ?
"'".$this->db->idate($this->fin_validite).
"'" :
'null').
",";
1879 $sql .=
" date_valid = ".(strval($this->date_validation) !=
'' ?
"'".$this->db->idate($this->date_validation).
"'" :
'null').
",";
1880 $sql .=
" total_tva = ".(isset($this->total_tva) ? (float) $this->total_tva :
"null").
",";
1881 $sql .=
" localtax1 = ".(isset($this->total_localtax1) ? (float) $this->total_localtax1 :
"null").
",";
1882 $sql .=
" localtax2 = ".(isset($this->total_localtax2) ? (float) $this->total_localtax2 :
"null").
",";
1883 $sql .=
" total_ht = ".(isset($this->total_ht) ? (float) $this->total_ht :
"null").
",";
1884 $sql .=
" total_ttc = ".(isset($this->total_ttc) ? (float) $this->total_ttc :
"null").
",";
1885 $sql .=
" fk_statut = ".(isset($this->
status) ? (int) $this->
status :
"null").
",";
1886 $sql .=
" fk_user_author = ".(!empty($this->user_author_id) ? (int) $this->user_author_id :
"null").
",";
1887 $sql .=
" fk_user_valid = ".(!empty($this->user_validation_id) ? (int) $this->user_validation_id :
"null").
",";
1889 $sql .=
" fk_projet = ".(!empty($this->fk_project) ? (int) $this->fk_project :
"null").
",";
1890 $sql .=
" fk_cond_reglement = ".(!empty($this->cond_reglement_id) ? (int) $this->cond_reglement_id :
"null").
",";
1891 $sql .=
" deposit_percent = ".(!empty($this->deposit_percent) ?
"'".$this->db->escape($this->deposit_percent).
"'" :
"null").
",";
1892 $sql .=
" fk_mode_reglement = ".(!empty($this->mode_reglement_id) ? (int) $this->mode_reglement_id :
"null").
",";
1893 $sql .=
" fk_input_reason = ".(!empty($this->demand_reason_id) ? (int) $this->demand_reason_id :
"null").
",";
1894 $sql .=
" fk_shipping_method = ".(isset($this->shipping_method_id) ? (int) $this->shipping_method_id :
"null").
",";
1895 $sql .=
" fk_availability = ".(!empty($this->availability_id) ? (int) $this->availability_id :
"null").
",";
1896 $sql .=
" note_private = ".(isset($this->note_private) ?
"'".$this->db->escape($this->note_private).
"'" :
"null").
",";
1897 $sql .=
" note_public = ".(isset($this->note_public) ?
"'".$this->db->escape($this->note_public).
"'" :
"null").
",";
1898 $sql .=
" model_pdf = ".(isset($this->model_pdf) ?
"'".$this->db->escape($this->model_pdf).
"'" :
"null").
",";
1899 $sql .=
" import_key = ".(isset($this->import_key) ?
"'".$this->db->escape($this->import_key).
"'" :
"null");
1900 $sql .=
" WHERE rowid = ".((int) $this->
id);
1904 dol_syslog(get_class($this).
"::update", LOG_DEBUG);
1905 $resql = $this->db->query($sql);
1908 $this->errors[] =
"Error ".$this->db->lasterror();
1918 if (!$error && !$notrigger) {
1920 $result = $this->call_trigger(
'PROPAL_MODIFY', $user);
1929 foreach ($this->errors as $errmsg) {
1930 dol_syslog(get_class($this).
"::update ".$errmsg, LOG_ERR);
1931 $this->error .= ($this->error ?
', '.$errmsg : $errmsg);
1933 $this->db->rollback();
1936 $this->db->commit();
1951 public function fetch_lines($only_product = 0, $loadalsotranslation = 0, $sqlforgedfilters =
'')
1954 $this->lines = array();
1956 $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,';
1957 $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,';
1958 $sql .=
' d.fk_unit,';
1959 $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,';
1960 $sql .=
' p.weight, p.weight_units, p.volume, p.volume_units,';
1961 $sql .=
' p.customcode, p.fk_country as country_id, c.code as country_code,';
1962 $sql .=
' d.date_start, d.date_end, d.extraparams,';
1963 $sql .=
' d.fk_multicurrency, d.multicurrency_code, d.multicurrency_subprice, d.multicurrency_total_ht, d.multicurrency_total_tva, d.multicurrency_total_ttc';
1964 $sql .=
' FROM '.MAIN_DB_PREFIX.$this->table_element_line.
' as d';
1965 $sql .=
' LEFT JOIN '.MAIN_DB_PREFIX.
'product as p ON (d.fk_product = p.rowid)';
1966 $sql .=
' LEFT JOIN '.MAIN_DB_PREFIX.
'c_country as c ON c.rowid = p.fk_country';
1967 $sql .=
' WHERE d.fk_propal = '.((int) $this->
id);
1968 if ($only_product) {
1969 $sql .=
' AND p.fk_product_type = 0';
1971 if ($sqlforgedfilters) {
1972 $sql .= $sqlforgedfilters;
1974 $sql .=
' ORDER BY d.rang, d.rowid';
1976 dol_syslog(get_class($this).
"::fetch_lines", LOG_DEBUG);
1977 $result = $this->db->query($sql);
1979 require_once DOL_DOCUMENT_ROOT.
'/core/class/extrafields.class.php';
1981 $num = $this->db->num_rows($result);
1985 $objp = $this->db->fetch_object($result);
1989 $line->rowid = $objp->rowid;
1990 $line->id = $objp->rowid;
1991 $line->fk_propal = $objp->fk_propal;
1992 $line->fk_parent_line = $objp->fk_parent_line;
1993 $line->label = $objp->custom_label;
1994 $line->desc = $objp->description;
1995 $line->description = $objp->description;
1996 $line->qty = $objp->qty;
1997 $line->vat_src_code = $objp->vat_src_code;
1998 $line->tva_tx = $objp->tva_tx;
1999 $line->localtax1_tx = $objp->localtax1_tx;
2000 $line->localtax2_tx = $objp->localtax2_tx;
2001 $line->localtax1_type = $objp->localtax1_type;
2002 $line->localtax2_type = $objp->localtax2_type;
2003 $line->subprice = $objp->subprice;
2004 $line->subprice_ttc = $objp->subprice_ttc;
2005 $line->fk_remise_except = $objp->fk_remise_except;
2006 $line->remise_percent = $objp->remise_percent;
2008 $line->info_bits = $objp->info_bits;
2009 $line->total_ht = $objp->total_ht;
2010 $line->total_tva = $objp->total_tva;
2011 $line->total_localtax1 = $objp->total_localtax1;
2012 $line->total_localtax2 = $objp->total_localtax2;
2013 $line->total_ttc = $objp->total_ttc;
2014 $line->fk_fournprice = $objp->fk_fournprice;
2015 $marginInfos =
getMarginInfos($objp->subprice, $objp->remise_percent, $objp->tva_tx, $objp->localtax1_tx, $objp->localtax2_tx, $line->fk_fournprice, $objp->pa_ht);
2016 $line->pa_ht = $marginInfos[0];
2017 $line->marge_tx = $marginInfos[1];
2018 $line->marque_tx = $marginInfos[2];
2019 $line->special_code = $objp->special_code;
2020 $line->rang = $objp->rang;
2022 $line->fk_product = $objp->fk_product;
2024 $line->ref = $objp->product_ref;
2025 $line->libelle = $objp->product_label;
2027 $line->product_ref = $objp->product_ref;
2028 $line->product_label = $objp->product_label;
2029 $line->product_desc = $objp->product_desc;
2030 $line->product_tobatch = $objp->product_tobatch;
2031 $line->product_barcode = $objp->product_barcode;
2032 $line->product_custom_code = $objp->customcode;
2033 $line->product_custom_country_id = $objp->country_id;
2034 $line->product_custom_country_code = $objp->country_code;
2035 $line->product_type = $objp->product_type;
2036 $line->fk_product_type = $objp->fk_product_type;
2038 $line->fk_unit = $objp->fk_unit;
2039 $line->weight = $objp->weight;
2040 $line->weight_units = $objp->weight_units;
2041 $line->volume = $objp->volume;
2042 $line->volume_units = $objp->volume_units;
2044 $line->date_start = $this->db->jdate($objp->date_start);
2045 $line->date_end = $this->db->jdate($objp->date_end);
2047 $line->extraparams = !empty($objp->extraparams) ? (array) json_decode($objp->extraparams,
true) : array();
2050 $line->fk_multicurrency = $objp->fk_multicurrency;
2051 $line->multicurrency_code = $objp->multicurrency_code;
2052 $line->multicurrency_subprice = $objp->multicurrency_subprice;
2053 $line->multicurrency_total_ht = $objp->multicurrency_total_ht;
2054 $line->multicurrency_total_tva = $objp->multicurrency_total_tva;
2055 $line->multicurrency_total_ttc = $objp->multicurrency_total_ttc;
2057 $line->fetch_optionals();
2060 if (
getDolGlobalInt(
'MAIN_MULTILANGS') && !empty($objp->fk_product) && !empty($loadalsotranslation)) {
2061 $tmpproduct =
new Product($this->db);
2062 $tmpproduct->fetch($objp->fk_product);
2063 $tmpproduct->getMultiLangs();
2065 $line->multilangs = $tmpproduct->multilangs;
2068 $this->lines[$i] = $line;
2073 $this->db->free($result);
2077 $this->error = $this->db->lasterror();
2089 public function valid($user, $notrigger = 0)
2093 require_once DOL_DOCUMENT_ROOT.
'/core/lib/files.lib.php';
2098 if ($this->
status == self::STATUS_VALIDATED) {
2099 dol_syslog(get_class($this).
"::valid action abandoned: already validated", LOG_WARNING);
2103 if (!((!
getDolGlobalString(
'MAIN_USE_ADVANCED_PERMS') && $user->hasRight(
'propal',
'creer'))
2104 || (
getDolGlobalString(
'MAIN_USE_ADVANCED_PERMS') && $user->hasRight(
'propal',
'propal_advance',
'validate')))) {
2105 $this->error =
'ErrorPermissionDenied';
2106 dol_syslog(get_class($this).
"::valid ".$this->error, LOG_ERR);
2111 dol_syslog(get_class($this).
"::valid checkActiveProductInLines ".$this->error, LOG_INFO);
2120 $soc =
new Societe($this->db);
2121 $soc->fetch($this->socid);
2124 if (preg_match(
'/^[\(]?PROV/i', $this->
ref) || empty($this->
ref)) {
2125 $num = $this->getNextNumRef($soc);
2131 $sql =
"UPDATE ".MAIN_DB_PREFIX.$this->table_element;
2132 $sql .=
" SET ref = '".$this->db->escape($num).
"',";
2133 $sql .=
" fk_statut = ".self::STATUS_VALIDATED.
", date_valid='".$this->db->idate($now).
"', fk_user_valid=".((int) $user->id);
2136 dol_syslog(get_class($this).
"::valid", LOG_DEBUG);
2137 $resql = $this->db->query($sql);
2144 if (!$error && !$notrigger) {
2146 $result = $this->call_trigger(
'PROPAL_VALIDATE', $user);
2154 $this->oldref = $this->ref;
2157 if (preg_match(
'/^[\(]?PROV/i', $this->
ref)) {
2159 $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).
"'";
2160 $sql .=
" WHERE filename LIKE '".$this->db->escape($this->
ref).
"%' AND filepath = 'propale/".$this->db->escape($this->
ref).
"' and entity = ".((int)
$conf->entity);
2161 $resql = $this->db->query($sql);
2164 $this->error = $this->db->lasterror();
2166 $sql =
'UPDATE '.MAIN_DB_PREFIX.
"ecm_files set filepath = 'propale/".$this->db->escape($this->newref).
"'";
2167 $sql .=
" WHERE filepath = 'propale/".$this->db->escape($this->
ref).
"' and entity = ".((int)
$conf->entity);
2168 $resql = $this->db->query($sql);
2171 $this->error = $this->db->lasterror();
2177 $dirsource =
$conf->propal->multidir_output[$this->entity].
'/'.$oldref;
2178 $dirdest =
$conf->propal->multidir_output[$this->entity].
'/'.$newref;
2179 if (!$error && file_exists($dirsource)) {
2180 dol_syslog(get_class($this).
"::validate rename dir ".$dirsource.
" into ".$dirdest);
2181 if (@rename($dirsource, $dirdest)) {
2184 $listoffiles =
dol_dir_list($dirdest,
'files', 1,
'^'.preg_quote($oldref,
'/'));
2185 foreach ($listoffiles as $fileentry) {
2186 $dirsource = $fileentry[
'name'];
2187 $dirdest = preg_replace(
'/^'.preg_quote($oldref,
'/').
'/', $newref, $dirsource);
2188 $dirsource = $fileentry[
'path'].
'/'.$dirsource;
2189 $dirdest = $fileentry[
'path'].
'/'.$dirdest;
2190 @rename($dirsource, $dirdest);
2199 $this->user_validation_id = $user->id;
2200 $this->datev = $now;
2201 $this->date_validation = $now;
2203 $this->db->commit();
2206 $this->db->rollback();
2225 $this->error =
'ErrorBadParameter';
2226 dol_syslog(get_class($this).
"::set_date ".$this->error, LOG_ERR);
2230 if ($user->hasRight(
'propal',
'creer')) {
2235 $sql =
"UPDATE ".MAIN_DB_PREFIX.$this->table_element;
2236 $sql .=
" SET datep = '".$this->db->idate($date).
"'";
2237 $sql .=
" WHERE rowid = ".((int) $this->
id);
2240 $resql = $this->db->query($sql);
2242 $this->errors[] = $this->db->error();
2247 $this->oldcopy = clone $this;
2248 $this->
date = $date;
2249 $this->datep = $date;
2252 if (!$notrigger && empty($error)) {
2254 $result = $this->call_trigger(
'PROPAL_MODIFY', $user);
2262 $this->db->commit();
2265 foreach ($this->errors as $errmsg) {
2266 dol_syslog(__METHOD__.
' Error: '.$errmsg, LOG_ERR);
2267 $this->error .= ($this->error ?
', '.$errmsg : $errmsg);
2269 $this->db->rollback();
2289 if ($user->hasRight(
'propal',
'creer')) {
2294 $sql =
"UPDATE ".MAIN_DB_PREFIX.$this->table_element;
2295 $sql .=
" SET fin_validite = ".($date_end_validity !=
'' ?
"'".$this->db->idate($date_end_validity).
"'" :
'null');
2296 $sql .=
" WHERE rowid = ".((int) $this->
id);
2300 $resql = $this->db->query($sql);
2302 $this->errors[] = $this->db->error();
2308 $this->oldcopy = clone $this;
2309 $this->fin_validite = $date_end_validity;
2312 if (!$notrigger && empty($error)) {
2314 $result = $this->call_trigger(
'PROPAL_MODIFY', $user);
2322 $this->db->commit();
2325 foreach ($this->errors as $errmsg) {
2326 dol_syslog(__METHOD__.
' Error: '.$errmsg, LOG_ERR);
2327 $this->error .= ($this->error ?
', '.$errmsg : $errmsg);
2329 $this->db->rollback();
2363 if ($user->hasRight(
'propal',
'creer')) {
2368 $sql =
"UPDATE ".MAIN_DB_PREFIX.$this->table_element;
2369 $sql .=
" SET date_livraison = ".(isDolTms($delivery_date) ?
"'".$this->db->idate($delivery_date).
"'" :
'null');
2370 $sql .=
" WHERE rowid = ".((int) $this->
id);
2373 $resql = $this->db->query($sql);
2375 $this->errors[] = $this->db->error();
2380 $this->oldcopy = clone $this;
2381 $this->delivery_date = $delivery_date;
2384 if (!$notrigger && empty($error)) {
2386 $result = $this->call_trigger(
'PROPAL_MODIFY', $user);
2394 $this->db->commit();
2397 foreach ($this->errors as $errmsg) {
2398 dol_syslog(__METHOD__.
' Error: '.$errmsg, LOG_ERR);
2399 $this->error .= ($this->error ?
', '.$errmsg : $errmsg);
2401 $this->db->rollback();
2421 if ($this->
status >= self::STATUS_DRAFT) {
2426 $sql =
"UPDATE ".MAIN_DB_PREFIX.$this->table_element;
2427 $sql .=
" SET fk_availability = ".((int) ($id > 0 ? ((
int) $id) : 0));
2428 $sql .=
" WHERE rowid = ".((int) $this->
id);
2431 $resql = $this->db->query($sql);
2433 $this->errors[] = $this->db->error();
2438 $this->oldcopy = clone $this;
2439 $this->fk_availability =
$id;
2440 $this->availability_id =
$id;
2443 if (!$notrigger && empty($error)) {
2445 $result = $this->call_trigger(
'PROPAL_MODIFY', $user);
2453 $this->db->commit();
2456 foreach ($this->errors as $errmsg) {
2457 dol_syslog(__METHOD__.
' Error: '.$errmsg, LOG_ERR);
2458 $this->error .= ($this->error ?
', '.$errmsg : $errmsg);
2460 $this->db->rollback();
2464 $error_str =
'Propal status do not meet requirement '.$this->status;
2466 $this->error = $error_str;
2467 $this->errors[] = $this->error;
2484 if ($user->hasRight(
'propal',
'creer') && $this->status >= self::STATUS_DRAFT) {
2489 $sql =
"UPDATE ".MAIN_DB_PREFIX.$this->table_element;
2490 $sql .=
" SET fk_input_reason = ".((int) $id);
2491 $sql .=
" WHERE rowid = ".((int) $this->
id);
2494 $resql = $this->db->query($sql);
2496 $this->errors[] = $this->db->error();
2502 $this->oldcopy = clone $this;
2504 $this->demand_reason_id = $id;
2508 if (!$notrigger && empty($error)) {
2510 $result = $this->call_trigger(
'PROPAL_MODIFY', $user);
2518 $this->db->commit();
2521 foreach ($this->errors as $errmsg) {
2522 dol_syslog(__METHOD__.
' Error: '.$errmsg, LOG_ERR);
2523 $this->error .= ($this->error ?
', '.$errmsg : $errmsg);
2525 $this->db->rollback();
2529 $error_str =
'Propal status do not meet requirement '.$this->status;
2531 $this->error = $error_str;
2532 $this->errors[] = $this->error;
2549 if ($user->hasRight(
'propal',
'creer')) {
2554 $sql =
"UPDATE ".MAIN_DB_PREFIX.$this->table_element;
2555 $sql .=
" SET ref_client = ".(empty($ref_client) ?
'NULL' :
"'".$this->db->escape($ref_client).
"'");
2556 $sql .=
" WHERE rowid = ".((int) $this->
id);
2558 dol_syslog(__METHOD__.
' $this->id='.$this->id.
', ref_client='.$ref_client, LOG_DEBUG);
2559 $resql = $this->db->query($sql);
2561 $this->errors[] = $this->db->error();
2566 $this->oldcopy = clone $this;
2567 $this->ref_customer = $ref_client;
2568 $this->ref_client = $ref_client;
2571 if (!$notrigger && empty($error)) {
2573 $result = $this->call_trigger(
'PROPAL_MODIFY', $user);
2581 $this->db->commit();
2584 foreach ($this->errors as $errmsg) {
2585 dol_syslog(__METHOD__.
' Error: '.$errmsg, LOG_ERR);
2586 $this->error .= ($this->error ?
', '.$errmsg : $errmsg);
2588 $this->db->rollback();
2606 public function reopen($user, $status, $note =
'', $notrigger = 0)
2610 $sql =
"UPDATE ".MAIN_DB_PREFIX.$this->table_element;
2611 $sql .=
" SET fk_statut = ".((int) $status).
",";
2612 if (!empty($note)) {
2613 $sql .=
" note_private = '".$this->db->escape($note).
"',";
2615 $sql .=
" date_cloture=NULL, fk_user_cloture=NULL";
2616 $sql .=
" WHERE rowid = ".((int) $this->
id);
2620 dol_syslog(get_class($this).
"::reopen", LOG_DEBUG);
2621 $resql = $this->db->query($sql);
2624 $this->errors[] =
"Error ".$this->db->lasterror();
2629 $result = $this->call_trigger(
'PROPAL_REOPEN', $user);
2639 if (!empty($this->errors)) {
2640 foreach ($this->errors as $errmsg) {
2641 dol_syslog(get_class($this).
"::update ".$errmsg, LOG_ERR);
2642 $this->error .= ($this->error ?
', '.$errmsg : $errmsg);
2645 $this->db->rollback();
2648 $this->statut = $status;
2651 $this->db->commit();
2666 public function closeProposal($user, $status, $note_private =
'', $notrigger = 0, $note_public =
'')
2668 global $langs,
$conf;
2675 $newprivatenote =
dol_concatdesc($this->note_private, $note_private);
2676 $newpublicnote =
dol_concatdesc($this->note_public, $note_public);
2679 $date_signature = $now;
2680 $fk_user_signature = $user->id;
2682 $this->
info($this->
id);
2683 if (!isset($this->date_signature) || $this->date_signature ==
'') {
2684 $date_signature = $now;
2685 $fk_user_signature = $user->id;
2687 $date_signature = $this->date_signature;
2688 $fk_user_signature = $this->user_signature->id;
2692 $sql =
"UPDATE ".MAIN_DB_PREFIX.$this->table_element;
2693 $sql .=
" SET fk_statut = ".((int) $status).
", note_private = '".$this->db->escape($newprivatenote).
"', note_public = '".$this->db->escape($newpublicnote).
"'";
2694 if ($status == self::STATUS_SIGNED) {
2695 $sql .=
", date_signature='".$this->db->idate($now).
"', fk_user_signature = ".((int) $fk_user_signature);
2697 $sql .=
" WHERE rowid = ".((int) $this->
id);
2699 $resql = $this->db->query($sql);
2703 $triggerName =
'PROPAL_CLOSE_REFUSED';
2705 if ($status == self::STATUS_SIGNED) {
2706 $triggerName =
'PROPAL_CLOSE_SIGNED';
2710 $soc =
new Societe($this->db);
2711 $soc->id = $this->socid;
2712 $result = $soc->setAsCustomer();
2715 $this->error = $this->db->lasterror();
2716 $this->db->rollback();
2723 $outputlangs = $langs;
2726 $newlang = (
GETPOST(
'lang_id',
'aZ09') ?
GETPOST(
'lang_id',
'aZ09') : $this->thirdparty->default_lang);
2727 $outputlangs->setDefaultLang($newlang);
2736 $this->
generateDocument($modelpdf, $outputlangs, $hidedetails, $hidedesc, $hideref);
2739 $this->oldcopy = clone $this;
2740 $this->statut = $status;
2742 $this->date_signature = $date_signature;
2743 $this->note_private = $newprivatenote;
2745 if (!$notrigger && empty($error)) {
2747 $result = $this->call_trigger($triggerName, $user);
2755 $this->db->commit();
2758 foreach ($this->errors as $errmsg) {
2759 dol_syslog(__METHOD__.
' Error: '.$errmsg, LOG_ERR);
2760 $this->error .= ($this->error ?
', '.$errmsg : $errmsg);
2762 if (!empty($this->oldcopy)) {
2763 $this->statut = $this->oldcopy->status;
2764 $this->
status = $this->oldcopy->status;
2765 $this->date_signature = $this->oldcopy->date_signature;
2766 $this->note_private = $this->oldcopy->note_private;
2769 $this->db->rollback();
2773 $this->error = $this->db->lasterror();
2774 $this->db->rollback();
2789 global
$conf, $langs;
2796 $triggerName =
'PROPAL_CLASSIFY_BILLED';
2802 $sql =
'UPDATE '.MAIN_DB_PREFIX.$this->table_element;
2803 $sql .=
" SET fk_statut = ".self::STATUS_BILLED.
", ";
2804 $sql .=
" note_private = '".$this->db->escape($newprivatenote).
"', date_cloture='".$this->db->idate($now).
"', fk_user_cloture=".((int) $user->id);
2805 $sql .=
' WHERE rowid = '.((int) $this->
id).
' AND fk_statut = '.((int) self::STATUS_SIGNED);
2808 $resql = $this->db->query($sql);
2810 $this->errors[] = $this->db->error();
2813 $num = $this->db->affected_rows($resql);
2821 $outputlangs = $langs;
2824 $newlang = (
GETPOST(
'lang_id',
'aZ09') ?
GETPOST(
'lang_id',
'aZ09') : $this->thirdparty->default_lang);
2825 $outputlangs->setDefaultLang($newlang);
2834 $this->
generateDocument($modelpdf, $outputlangs, $hidedetails, $hidedesc, $hideref);
2837 $this->oldcopy = clone $this;
2840 $this->date_cloture = $now;
2841 $this->note_private = $newprivatenote;
2844 if (!$notrigger && empty($error)) {
2846 $result = $this->call_trigger($triggerName, $user);
2854 $this->db->commit();
2857 foreach ($this->errors as $errmsg) {
2858 dol_syslog(__METHOD__.
' Error: '.$errmsg, LOG_ERR);
2859 $this->error .= ($this->error ?
', '.$errmsg : $errmsg);
2861 $this->db->rollback();
2878 $sql =
"UPDATE ". MAIN_DB_PREFIX . $this->table_element;
2879 $sql .=
" SET fk_statut = " . self::STATUS_CANCELED .
",";
2880 $sql .=
" fk_user_modif = " . ((int) $user->id);
2881 $sql .=
" WHERE rowid = " . ((int) $this->
id);
2883 dol_syslog(get_class($this).
"::cancel", LOG_DEBUG);
2884 if ($this->db->query($sql)) {
2886 $result = $this->call_trigger(
'PROPAL_CANCEL', $user);
2895 $this->db->commit();
2898 foreach ($this->errors as $errmsg) {
2899 dol_syslog(get_class($this).
"::cancel ".$errmsg, LOG_ERR);
2900 $this->error .= ($this->error ?
', '.$errmsg : $errmsg);
2902 $this->db->rollback();
2906 $this->error = $this->db->error();
2907 $this->db->rollback();
2926 if ($this->
status <= self::STATUS_DRAFT) {
2930 dol_syslog(get_class($this).
"::setDraft", LOG_DEBUG);
2934 $sql =
"UPDATE ".MAIN_DB_PREFIX.$this->table_element;
2935 $sql .=
" SET fk_statut = ".self::STATUS_DRAFT;
2936 $sql .=
", online_sign_ip = NULL , online_sign_name = NULL";
2937 $sql .=
" WHERE rowid = ".((int) $this->
id);
2939 $resql = $this->db->query($sql);
2941 $this->errors[] = $this->db->error();
2946 $this->oldcopy = clone $this;
2949 if (!$notrigger && empty($error)) {
2951 $result = $this->call_trigger(
'PROPAL_MODIFY', $user);
2962 $this->db->commit();
2965 foreach ($this->errors as $errmsg) {
2966 dol_syslog(__METHOD__.
' Error: '.$errmsg, LOG_ERR);
2967 $this->error .= ($this->error ?
', '.$errmsg : $errmsg);
2969 $this->db->rollback();
2989 public function liste_array($shortlist = 0, $draft = 0, $notcurrentuser = 0, $socid = 0, $limit = 0, $offset = 0, $sortfield =
'p.datep', $sortorder =
'DESC')
2996 $sql =
"SELECT s.rowid, s.nom as name, s.client,";
2997 $sql .=
" p.rowid as propalid, p.fk_statut, p.total_ht, p.ref, p.remise, ";
2998 $sql .=
" p.datep as dp, p.fin_validite as datelimite";
2999 $sql .=
" FROM ".MAIN_DB_PREFIX.
"societe as s, ".MAIN_DB_PREFIX.$this->table_element.
" as p, ".MAIN_DB_PREFIX.
"c_propalst as c";
3000 $sql .=
" WHERE p.entity IN (".getEntity(
'propal').
")";
3001 $sql .=
" AND p.fk_soc = s.rowid";
3002 $sql .=
" AND p.fk_statut = c.id";
3006 if (empty($user->socid) && !$user->hasRight(
'societe',
'client',
'voir')) {
3007 $search_sale = $user->id;
3010 if ($search_sale && $search_sale !=
'-1') {
3011 if ($search_sale == -2) {
3012 $sql .=
" AND NOT EXISTS (SELECT sc.fk_soc FROM ".MAIN_DB_PREFIX.
"societe_commerciaux as sc WHERE sc.fk_soc = p.fk_soc)";
3013 } elseif ($search_sale > 0) {
3014 $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).
")";
3019 $sql .=
" AND p.fk_soc = ".((int) $socid);
3022 $sql .=
" AND p.fk_statut = ".((int) self::STATUS_DRAFT);
3024 if ($notcurrentuser > 0) {
3025 $sql .=
" AND p.fk_user_author <> ".((int) $user->id);
3027 $sql .= $this->db->order($sortfield, $sortorder);
3028 $sql .= $this->db->plimit($limit, $offset);
3030 $result = $this->db->query($sql);
3032 $num = $this->db->num_rows($result);
3036 $obj = $this->db->fetch_object($result);
3038 if ($shortlist == 1) {
3039 $ga[$obj->propalid] = $obj->ref;
3040 } elseif ($shortlist == 2) {
3041 $ga[$obj->propalid] = $obj->ref.
' ('.$obj->name.
')';
3043 $ga[$i][
'id'] = $obj->propalid;
3044 $ga[$i][
'ref'] = $obj->ref;
3045 $ga[$i][
'name'] = $obj->name;
3079 $linkedInvoices = array();
3082 foreach ($this->linkedObjectsIds as $objecttype => $objectid) {
3085 foreach ($objectid as $key =>
$object) {
3087 if ($objecttype ==
'facture') {
3092 foreach ($this->linkedObjectsIds as $subobjecttype => $subobjectid) {
3093 foreach ($subobjectid as $subkey => $subobject) {
3094 if ($subobjecttype ==
'facture') {
3095 $linkedInvoices[] = $subobject;
3103 if (count($linkedInvoices) > 0) {
3104 $sql =
"SELECT rowid as facid, ref, total_ht as total, datef as df, fk_user_author, fk_statut, paye";
3105 $sql .=
" FROM ".MAIN_DB_PREFIX.
"facture";
3106 $sql .=
" WHERE rowid IN (".$this->db->sanitize(implode(
',', $linkedInvoices)).
")";
3108 dol_syslog(get_class($this).
"::InvoiceArrayList", LOG_DEBUG);
3109 $resql = $this->db->query($sql);
3112 $tab_sqlobj = array();
3113 $nump = $this->db->num_rows($resql);
3114 for ($i = 0; $i < $nump; $i++) {
3115 $obj = $this->db->fetch_object($resql);
3116 $tab_sqlobj[] = $obj;
3118 $this->db->free($resql);
3120 $nump = count($tab_sqlobj);
3124 while ($i < $nump) {
3125 $obj = array_shift($tab_sqlobj);
3148 public function delete($user, $notrigger = 0)
3151 require_once DOL_DOCUMENT_ROOT.
'/core/lib/files.lib.php';
3159 $result = $this->call_trigger(
'PROPAL_DELETE', $user);
3168 $sql =
"DELETE FROM ".MAIN_DB_PREFIX.
"categorie_propal";
3169 $sql .=
" WHERE fk_propal = ".((int) $this->
id);
3171 $result = $this->db->query($sql);
3174 $this->error = $this->db->lasterror();
3175 $this->errors[] = $this->error;
3180 if (!$error && !empty($this->table_element_line)) {
3181 $tabletodelete = $this->table_element_line;
3182 $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).
")";
3183 $sql =
"DELETE FROM ".MAIN_DB_PREFIX.$tabletodelete.
" WHERE ".$this->fk_element.
" = ".((int) $this->
id);
3184 if (!$this->db->query($sqlef) || !$this->db->query($sql)) {
3186 $this->error = $this->db->lasterror();
3187 $this->errors[] = $this->error;
3188 dol_syslog(get_class($this).
"::delete error ".$this->error, LOG_ERR);
3213 dol_syslog(get_class($this).
"::delete error ".$this->error, LOG_ERR);
3219 $sql =
"DELETE FROM ".MAIN_DB_PREFIX.$this->table_element.
" WHERE rowid = ".((int) $this->
id);
3220 $res = $this->db->query($sql);
3223 $this->error = $this->db->lasterror();
3224 $this->errors[] = $this->error;
3225 dol_syslog(get_class($this).
"::delete error ".$this->error, LOG_ERR);
3241 if ($conf->propal->multidir_output[$this->entity] && !empty($this->
ref)) {
3242 $dir =
$conf->propal->multidir_output[$this->entity].
"/".$ref;
3243 $file = $dir.
"/".$ref.
".pdf";
3244 if (file_exists($file)) {
3248 $this->error =
'ErrorFailToDeleteFile';
3249 $this->errors[] = $this->error;
3250 $this->db->rollback();
3254 if (file_exists($dir)) {
3257 $this->error =
'ErrorFailToDeleteDir';
3258 $this->errors[] = $this->error;
3259 $this->db->rollback();
3267 dol_syslog(get_class($this).
"::delete ".$this->
id.
" by ".$user->id, LOG_DEBUG);
3268 $this->db->commit();
3271 $this->db->rollback();
3288 if ($this->
status >= self::STATUS_DRAFT) {
3293 $sql =
'UPDATE '.MAIN_DB_PREFIX.$this->table_element;
3294 $sql .=
' SET fk_availability = '.((int) $availability_id);
3295 $sql .=
' WHERE rowid='.((int) $this->
id);
3297 dol_syslog(__METHOD__.
' availability('.$availability_id.
')', LOG_DEBUG);
3298 $resql = $this->db->query($sql);
3300 $this->errors[] = $this->db->error();
3305 $this->oldcopy = clone $this;
3306 $this->availability_id = $availability_id;
3309 if (!$notrigger && empty($error)) {
3311 $result = $this->call_trigger(
'PROPAL_MODIFY', $user);
3319 $this->db->commit();
3322 foreach ($this->errors as $errmsg) {
3323 dol_syslog(__METHOD__.
' Error: '.$errmsg, LOG_ERR);
3324 $this->error .= ($this->error ?
', '.$errmsg : $errmsg);
3326 $this->db->rollback();
3330 $error_str =
'Propal status do not meet requirement '.$this->status;
3332 $this->error = $error_str;
3333 $this->errors[] = $this->error;
3352 if ($this->
status >= self::STATUS_DRAFT) {
3357 $sql =
'UPDATE '.MAIN_DB_PREFIX.$this->table_element;
3358 $sql .=
' SET fk_input_reason = '.((int) $demand_reason_id);
3359 $sql .=
' WHERE rowid='.((int) $this->
id);
3361 dol_syslog(__METHOD__.
' demand_reason('.$demand_reason_id.
')', LOG_DEBUG);
3362 $resql = $this->db->query($sql);
3364 $this->errors[] = $this->db->error();
3369 $this->oldcopy = clone $this;
3370 $this->demand_reason_id = $demand_reason_id;
3373 if (!$notrigger && empty($error)) {
3375 $result = $this->call_trigger(
'PROPAL_MODIFY', $user);
3383 $this->db->commit();
3386 foreach ($this->errors as $errmsg) {
3387 dol_syslog(__METHOD__.
' Error: '.$errmsg, LOG_ERR);
3388 $this->error .= ($this->error ?
', '.$errmsg : $errmsg);
3390 $this->db->rollback();
3394 $error_str =
'Propal status do not meet requirement '.$this->status;
3396 $this->error = $error_str;
3397 $this->errors[] = $this->error;
3411 $sql =
"SELECT c.rowid, ";
3412 $sql .=
" c.datec, c.date_valid as datev, c.date_signature, c.date_cloture,";
3413 $sql .=
" c.fk_user_author, c.fk_user_valid, c.fk_user_signature, c.fk_user_cloture";
3414 $sql .=
" FROM ".MAIN_DB_PREFIX.$this->table_element.
" as c";
3415 $sql .=
" WHERE c.rowid = ".((int) $id);
3417 $result = $this->db->query($sql);
3420 if ($this->db->num_rows($result)) {
3421 $obj = $this->db->fetch_object($result);
3423 $this->
id = $obj->rowid;
3425 $this->date_creation = $this->db->jdate($obj->datec);
3426 $this->date_validation = $this->db->jdate($obj->datev);
3427 $this->date_signature = $this->db->jdate($obj->date_signature);
3428 $this->date_cloture = $this->db->jdate($obj->date_cloture);
3430 $this->user_creation_id = $obj->fk_user_author;
3431 $this->user_validation_id = $obj->fk_user_valid;
3433 if ($obj->fk_user_signature) {
3434 $user_signature =
new User($this->db);
3435 $user_signature->fetch($obj->fk_user_signature);
3436 $this->user_signature = $user_signature;
3439 $this->user_closing_id = $obj->fk_user_cloture;
3441 $this->db->free($result);
3470 global $hookmanager;
3473 if (empty($this->labelStatus) || empty($this->labelStatusShort)) {
3475 $langs->load(
"propal");
3476 $this->labelStatus[-1] = $langs->transnoentitiesnoconv(
"PropalStatusCanceled");
3477 $this->labelStatus[0] = $langs->transnoentitiesnoconv(
"PropalStatusDraft");
3478 $this->labelStatus[1] = $langs->transnoentitiesnoconv(
"PropalStatusValidated");
3479 $this->labelStatus[2] = $langs->transnoentitiesnoconv(
"PropalStatusSigned");
3480 $this->labelStatus[3] = $langs->transnoentitiesnoconv(
"PropalStatusNotSigned");
3481 $this->labelStatus[4] = $langs->transnoentitiesnoconv(
"PropalStatusBilled");
3482 $this->labelStatusShort[-1] = $langs->transnoentitiesnoconv(
"PropalStatusCanceledShort");
3483 $this->labelStatusShort[0] = $langs->transnoentitiesnoconv(
"PropalStatusDraftShort");
3484 $this->labelStatusShort[1] = $langs->transnoentitiesnoconv(
"PropalStatusValidatedShort");
3485 $this->labelStatusShort[2] = $langs->transnoentitiesnoconv(
"PropalStatusSignedShort");
3486 $this->labelStatusShort[3] = $langs->transnoentitiesnoconv(
"PropalStatusNotSignedShort");
3487 $this->labelStatusShort[4] = $langs->transnoentitiesnoconv(
"PropalStatusBilledShort");
3491 if ($status == self::STATUS_CANCELED) {
3492 $statusType =
'status9';
3493 } elseif ($status == self::STATUS_DRAFT) {
3494 $statusType =
'status0';
3495 } elseif ($status == self::STATUS_VALIDATED) {
3496 $statusType =
'status1';
3497 } elseif ($status == self::STATUS_SIGNED) {
3498 $statusType =
'status4';
3499 } elseif ($status == self::STATUS_NOTSIGNED) {
3500 $statusType =
'status9';
3501 } elseif ($status == self::STATUS_BILLED) {
3502 $statusType =
'status6';
3505 $parameters = array(
'status' => $status,
'mode' => $mode);
3506 $reshook = $hookmanager->executeHooks(
'LibStatut', $parameters, $this);
3509 return $hookmanager->resPrint;
3512 return dolGetStatus($this->labelStatus[$status], $this->labelStatusShort[$status],
'', $statusType, $mode);
3527 global $langs, $hookmanager;
3529 $sql =
"SELECT p.rowid, p.ref, p.datec as datec, p.fin_validite as datefin, p.total_ht";
3530 if (empty($user->socid) && !$user->hasRight(
'societe',
'client',
'voir')) {
3531 $sql .=
" FROM ".MAIN_DB_PREFIX.$this->table_element.
" as p";
3532 $sql .=
" LEFT JOIN ".MAIN_DB_PREFIX.
"societe_commerciaux as sc ON p.fk_soc = sc.fk_soc";
3534 $sql .=
" FROM ".MAIN_DB_PREFIX.
"propal as p";
3536 $sql .=
" WHERE p.entity IN (".getEntity(
'propal').
")";
3537 if ($mode ==
'opened') {
3538 $sql .=
" AND p.fk_statut = ".self::STATUS_VALIDATED;
3540 if ($mode ==
'signed') {
3541 $sql .=
" AND p.fk_statut = ".self::STATUS_SIGNED;
3544 if (empty($user->socid) && !$user->hasRight(
'societe',
'client',
'voir')) {
3545 $sql .=
" AND sc.fk_user = ".((int) $user->id);
3548 $sql .=
" AND p.fk_soc = ".((int) $user->socid);
3553 if (empty($user->socid) && !$user->hasRight(
'societe',
'client',
'voir')) {
3554 $search_sale = $user->id;
3557 if ($search_sale && $search_sale !=
'-1') {
3558 if ($search_sale == -2) {
3559 $sql .=
" AND NOT EXISTS (SELECT sc.fk_soc FROM ".MAIN_DB_PREFIX.
"societe_commerciaux as sc WHERE sc.fk_soc = p.fk_soc)";
3560 } elseif ($search_sale > 0) {
3561 $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).
")";
3565 $sql .=
" AND p.fk_soc = ".((int) $user->socid);
3568 $parameters = array(
'socid' => $user->socid);
3569 $reshook = $hookmanager->executeHooks(
'printFieldListWhere', $parameters, $this);
3570 $sql .= $hookmanager->resPrint;
3572 $resql = $this->db->query($sql);
3574 $langs->load(
"propal");
3579 $label = $labelShort =
'';
3580 if ($mode ==
'opened') {
3583 $label = $langs->transnoentitiesnoconv(
"PropalsToClose");
3584 $labelShort = $langs->transnoentitiesnoconv(
"ToAcceptRefuse");
3586 if ($mode ==
'signed') {
3589 $label = $langs->trans(
"PropalsToBill");
3590 $labelShort = $langs->trans(
"ToBill");
3594 $response->warning_delay = $delay_warning / 60 / 60 / 24;
3595 $response->label = $label;
3596 $response->labelShort = $labelShort;
3597 $response->url =
dolBuildUrl(DOL_URL_ROOT.
'/comm/propal/list.php', [
'search_status' => $status,
'mainmenu' =>
'commercial',
'leftmenu' =>
'propals']);
3598 $response->url_late =
dolBuildUrl(DOL_URL_ROOT.
'/comm/propal/list.php', [
'search_option' =>
'late',
'mainmenu' =>
'commercial',
'leftmenu' =>
'propals',
'sortfield' =>
'p.datep',
'sortorder' =>
'asc']);
3602 while ($obj = $this->db->fetch_object($resql)) {
3603 $response->nbtodo++;
3604 $response->total += $obj->total_ht;
3606 if ($mode ==
'opened') {
3607 $datelimit = $this->db->jdate($obj->datefin);
3608 if ($datelimit < ($now - $delay_warning)) {
3609 $response->nbtodolate++;
3618 $this->error = $this->db->error();
3634 global
$conf, $langs;
3639 $sql =
"SELECT rowid";
3640 $sql .=
" FROM ".MAIN_DB_PREFIX.
"product";
3641 $sql .=
" WHERE entity IN (".getEntity(
'product').
")";
3642 if (array_key_exists(
'tosell', $param)) {
3643 $sql .=
" AND tosell = ".((int) $param[
'tosell']);
3645 $sql .= $this->db->plimit(100);
3647 $resql = $this->db->query($sql);
3649 $num_prods = $this->db->num_rows($resql);
3651 while ($i < $num_prods) {
3653 $row = $this->db->fetch_row($resql);
3654 $prodids[$i] = $row[0];
3660 $this->
ref =
'SPECIMEN';
3661 $this->ref_customer =
'NEMICEPS';
3662 $this->ref_client =
'NEMICEPS';
3663 $this->specimen = 1;
3665 $this->
date = time();
3666 $this->fin_validite = $this->
date + 3600 * 24 * 30;
3667 $this->cond_reglement_id = 1;
3668 $this->cond_reglement_code =
'RECEP';
3669 $this->mode_reglement_id = 7;
3670 $this->mode_reglement_code =
'CHQ';
3671 $this->availability_id = 1;
3672 $this->availability_code =
'AV_NOW';
3673 $this->demand_reason_id = 1;
3674 $this->demand_reason_code =
'SRC_00';
3675 $this->note_public =
'This is a comment (public)';
3676 $this->note_private =
'This is a comment (private)';
3678 $this->multicurrency_tx = 1;
3684 while ($xnbp < $nbp) {
3686 $line->desc = $langs->trans(
"Description").
" ".$xnbp;
3688 $line->subprice = 100;
3690 $line->localtax1_tx = 0;
3691 $line->localtax2_tx = 0;
3693 $line->total_ht = 50;
3694 $line->total_ttc = 60;
3695 $line->total_tva = 10;
3696 $line->remise_percent = 50;
3698 $line->total_ht = 100;
3699 $line->total_ttc = 120;
3700 $line->total_tva = 20;
3701 $line->remise_percent = 00;
3704 if ($num_prods > 0) {
3705 $prodid = mt_rand(1, $num_prods);
3706 $line->fk_product = $prodids[$prodid];
3707 $line->product_ref =
'SPECIMEN';
3710 $this->lines[$xnbp] = $line;
3712 $this->total_ht += $line->total_ht;
3713 $this->total_tva += $line->total_tva;
3714 $this->total_ttc += $line->total_ttc;
3729 global $user, $hookmanager;
3731 $this->nb = array();
3733 $sql =
"SELECT count(p.rowid) as nb";
3734 $sql .=
" FROM ".MAIN_DB_PREFIX.$this->table_element.
" as p";
3735 $sql .=
" LEFT JOIN ".MAIN_DB_PREFIX.
"societe as s ON p.fk_soc = s.rowid";
3736 $sql .=
" WHERE p.entity IN (".getEntity(
'propal').
")";
3740 if (empty($user->socid) && !$user->hasRight(
'societe',
'client',
'voir')) {
3741 $search_sale = $user->id;
3744 if ($search_sale && $search_sale !=
'-1') {
3745 if ($search_sale == -2) {
3746 $sql .=
" AND NOT EXISTS (SELECT sc.fk_soc FROM ".MAIN_DB_PREFIX.
"societe_commerciaux as sc WHERE sc.fk_soc = p.fk_soc)";
3747 } elseif ($search_sale > 0) {
3748 $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).
")";
3753 $parameters = array();
3754 $hookmanager->executeHooks(
'printFieldListWhere', $parameters, $this);
3755 $sql .= $hookmanager->resPrint;
3756 $resql = $this->db->query($sql);
3759 while ($obj = $this->db->fetch_object($resql)) {
3760 $this->nb[
"proposals"] = $obj->nb;
3762 $this->db->free($resql);
3766 $this->error = $this->db->error();
3779 public function getNextNumRef($soc)
3781 global
$conf, $langs;
3782 $langs->load(
"propal");
3786 if (!empty($classname)) {
3789 $file = $classname.
".php";
3792 $dirmodels = array_merge(array(
'/'), (array)
$conf->modules_parts[
'models']);
3793 foreach ($dirmodels as $reldir) {
3797 $mybool = ((bool) @include_once $dir.$file) || $mybool;
3805 $obj =
new $classname();
3806 '@phan-var-force ModeleNumRefPropales $obj';
3809 $numref = $obj->getNextValue($soc, $this);
3811 if ($numref !=
"") {
3814 $this->error = $obj->error;
3819 $langs->load(
"errors");
3820 print $langs->trans(
"Error").
" ".$langs->trans(
"ErrorModuleSetupNotComplete", $langs->transnoentitiesnoconv(
"Proposal"));
3833 global
$conf, $langs, $user;
3835 $langs->load(
'propal');
3837 $nofetch = !empty($params[
'nofetch']);
3840 return [
'optimize' => $langs->trans(
"Proposal")];
3842 if ($user->hasRight(
'propal',
'lire')) {
3843 $datas[
'picto'] =
img_picto(
'', $this->picto,
'', 0, 0, 0,
'',
'paddingrightonly').
'<u>'.$langs->trans(
"Proposal").
'</u>';
3844 if (isset($this->
status)) {
3845 $datas[
'status'] =
' '.$this->getLibStatut(5);
3847 if (!empty($this->
ref)) {
3848 $datas[
'ref'] =
'<br><b>'.$langs->trans(
'Ref').
':</b> '.$this->ref;
3851 $langs->load(
'companies');
3852 if (empty($this->thirdparty)) {
3855 $datas[
'customer'] =
'<br><b>'.$langs->trans(
'Customer').
':</b> '.$this->thirdparty->getNomUrl(1,
'', 0, 1);
3857 if (!empty($this->ref_customer)) {
3858 $datas[
'refcustomer'] =
'<br><b>'.$langs->trans(
'RefCustomer').
':</b> '.$this->ref_customer;
3861 $langs->load(
'project');
3862 if (is_null($this->project) || (is_object($this->project) && $this->project->isEmpty())) {
3864 if ($res > 0 && $this->project instanceof
Project) {
3865 $datas[
'project'] =
'<br><b>'.$langs->trans(
'Project').
':</b> '.$this->project->getNomUrl(1,
'', 0,
'1');
3869 if (!empty($this->total_ht)) {
3870 $datas[
'amountht'] =
'<br><b>'.$langs->trans(
'AmountHT').
':</b> '.
price($this->total_ht, 0, $langs, 0, -1, -1,
$conf->currency);
3872 if (!empty($this->total_tva)) {
3873 $datas[
'vat'] =
'<br><b>'.$langs->trans(
'VAT').
':</b> '.
price($this->total_tva, 0, $langs, 0, -1, -1,
$conf->currency);
3875 if (!empty($this->total_ttc)) {
3876 $datas[
'amountttc'] =
'<br><b>'.$langs->trans(
'AmountTTC').
':</b> '.
price($this->total_ttc, 0, $langs, 0, -1, -1,
$conf->currency);
3878 if (!empty($this->
date)) {
3879 $datas[
'date'] =
'<br><b>'.$langs->trans(
'Date').
':</b> '.
dol_print_date($this->
date,
'day');
3881 if (!empty($this->date_signature)) {
3882 $datas[
'datesignature'] =
'<br><b>'.$langs->trans(
'DateSigning').
':</b> '.
dol_print_date($this->date_signature,
'day');
3884 if (!empty($this->delivery_date)) {
3885 $datas[
'deliverydate'] =
'<br><b>'.$langs->trans(
'DeliveryDate').
':</b> '.
dol_print_date($this->delivery_date,
'dayhour');
3903 public function getNomUrl($withpicto = 0, $option =
'', $get_params =
'', $notooltip = 0, $save_lastsearch_value = -1, $addlinktonotes = -1)
3905 global $langs,
$conf, $user, $hookmanager;
3907 if (!empty(
$conf->dol_no_mouse_hover)) {
3914 'objecttype' => $this->element,
3915 'option' => $option,
3918 $classfortooltip =
'classfortooltip';
3921 $classfortooltip =
'classforajaxtooltip';
3922 $dataparams =
' data-params="'.dol_escape_htmltag(json_encode($params)).
'"';
3930 if ($user->hasRight(
'propal',
'lire')) {
3931 parse_str($get_params, $query);
3932 $query = array_merge($query, [
'id' => $this->
id]);
3933 if ($option ==
'') {
3934 $baseurl = DOL_URL_ROOT .
'/comm/propal/card.php';
3935 } elseif ($option ==
'compta') {
3936 $baseurl = DOL_URL_ROOT .
'/comm/propal/card.php';
3937 } elseif ($option ==
'expedition') {
3938 $baseurl = DOL_URL_ROOT .
'/expedition/propal.php';
3939 } elseif ($option ==
'document') {
3940 $baseurl = DOL_URL_ROOT .
'/comm/propal/document.php';
3943 if ($option !=
'nolink') {
3945 $add_save_lastsearch_values = ($save_lastsearch_value == 1 ? 1 : 0);
3946 if ($save_lastsearch_value == -1 && isset($_SERVER[
"PHP_SELF"]) && preg_match(
'/list\.php/', $_SERVER[
"PHP_SELF"])) {
3947 $add_save_lastsearch_values = 1;
3949 if ($add_save_lastsearch_values) {
3950 $query = array_merge($query, [
'save_lastsearch_values' => 1]);
3957 if (empty($notooltip) && $user->hasRight(
'propal',
'lire')) {
3959 $label = $langs->trans(
"Proposal");
3960 $linkclose .=
' alt="'.dolPrintHTMLForAttribute($label).
'"';
3962 $linkclose .= ($label ?
' title="'.dolPrintHTMLForAttribute($label).
'"' :
' title="tocomplete"');
3963 $linkclose .= $dataparams.
' class="'.$classfortooltip.
'"';
3966 $linkstart =
'<a href="'.$url.
'"';
3967 $linkstart .= $linkclose.
'>';
3970 $result .= $linkstart;
3972 $result .=
img_object(($notooltip ?
'' : $label), ($this->picto ? $this->picto :
'generic'), (($withpicto != 2) ?
'class="paddingright"' :
''), 0, 0, $notooltip ? 0 : 1);
3974 if ($withpicto != 2) {
3975 $result .= $this->ref;
3977 $result .= $linkend;
3979 if ($addlinktonotes >= 0) {
3982 if ($addlinktonotes == 0) {
3983 if (!empty($this->note_private) || !empty($this->note_public)) {
3984 $txttoshow = $langs->trans(
'ViewPrivateNote');
3986 } elseif ($addlinktonotes == 1) {
3987 if (!empty($this->note_private)) {
3990 } elseif ($addlinktonotes == 2) {
3991 if (!empty($this->note_public)) {
3994 } elseif ($addlinktonotes == 3) {
3995 if ($user->socid > 0) {
3996 if (!empty($this->note_public)) {
4000 if (!empty($this->note_public)) {
4003 if (!empty($this->note_private)) {
4004 if (!empty($txttoshow)) {
4005 $txttoshow .=
'<br><br>';
4013 $result .=
' <span class="note inline-block">';
4014 $result .=
'<a href="'.dolBuildUrl(DOL_URL_ROOT.
'/comm/propal/note.php', [
'id' => $this->id]).
'" class="classfortooltip" title="'.
dol_escape_htmltag($txttoshow).
'">';
4017 $result .=
'</span>';
4022 $hookmanager->initHooks(array($this->element .
'dao'));
4023 $parameters = array(
'id' => $this->
id,
'getnomurl' => &$result);
4024 $reshook = $hookmanager->executeHooks(
'getNomUrl', $parameters, $this, $action);
4026 $result = $hookmanager->resPrint;
4028 $result .= $hookmanager->resPrint;
4041 return $this->
fetch_lines(0, 0, $sqlforgedfilters);
4055 public function generateDocument($modele, $outputlangs, $hidedetails = 0, $hidedesc = 0, $hideref = 0, $moreparams =
null)
4057 $outputlangs->loadLangs(array(
"propale",
"products"));
4062 if ($this->model_pdf) {
4063 $modele = $this->model_pdf;
4067 $modelpath =
"core/modules/propale/doc/";
4069 return $this->
commonGenerateDocument($modelpath, $modele, $outputlangs, $hidedetails, $hidedesc, $hideref, $moreparams);
4117 $selected = (empty($arraydata[
'selected']) ? 0 : $arraydata[
'selected']);
4119 $return =
'<div class="box-flex-item box-flex-grow-zero">';
4120 $return .=
'<div class="info-box info-box-sm">';
4121 $return .=
'<div class="info-box-icon bg-infobox-action">';
4123 $return .=
'</div>';
4124 $return .=
'<div class="info-box-content">';
4125 $return .=
'<span class="info-box-ref inline-block tdoverflowmax150 valignmiddle">' . $this->
getNomUrl() .
'</span>';
4126 if ($selected >= 0) {
4127 $return .=
'<input id="cb'.$this->id.
'" class="flat checkforselect fright" type="checkbox" name="toselect[]" value="'.$this->
id.
'"'.($selected ?
' checked="checked"' :
'').
'>';
4129 if (!empty($arraydata[
'projectlink'])) {
4130 $return .=
'<span class="info-box-ref"> | '.$arraydata[
'projectlink'].
'</span>';
4133 if (is_object($this->thirdparty)) {
4134 $return .=
'<div class="info-box-ref tdoverflowmax150">'.$this->thirdparty->getNomUrl(1).
'</div>';
4136 $return .=
'<span class="info-box-label amount" title="'.$langs->trans(
"AmountHT").
'">'.
price($this->total_ht).
'</span>';
4137 if (!empty($arraydata[
'authorlink'])) {
4138 $return .=
' <span class="info-box-label">'.$arraydata[
'authorlink'].
'</span>';
4140 $return .=
'<br><div class="info-box-status">'.$this->getLibStatut(3).
'</div>';
4141 $return .=
'</div>';
4142 $return .=
'</div>';
4143 $return .=
'</div>';
4159 require_once DOL_DOCUMENT_ROOT.
'/categories/class/categorie.class.php';
4160 return parent::setCategoriesCommon($categories, Categorie::TYPE_PROPOSAL);
$id
Support class for third parties, contacts, members, users or resources.
if(! $sortfield) if(! $sortorder) $object
fetch_optionals($rowid=null, $optionsArray=null)
Function to get extra fields of an object into $this->array_options This method is in most cases call...
line_order($renum=false, $rowidorder='ASC', $fk_parent_line=true)
Save a new position (field rang) for details lines.
deleteEcmFiles($mode=0)
Delete related files of object in database.
update_price($exclspec=0, $roundingadjust='auto', $nodatabaseupdate=0, $seller=null)
Update total_ht, total_ttc, total_vat, total_localtax1, total_localtax2 for an object (sum of lines).
add_object_linked($origin=null, $origin_id=null, $f_user=null, $notrigger=0)
Add an object link into llx_element_element.
commonGenerateDocument($modelspath, $modele, $outputlangs, $hidedetails, $hidedesc, $hideref, $moreparams=null)
Common function for all objects extending CommonObject for generating documents.
fetchProject()
Load the project with id $this->fk_project into this->project.
fetch_thirdparty($force_thirdparty_id=0)
Load the third party of object, from id $this->socid or $this->fk_soc, into this->thirdparty.
deleteObjectLinked($sourceid=null, $sourcetype='', $targetid=null, $targettype='', $rowid=0, $f_user=null, $notrigger=0)
Delete all links between an object $this.
setErrorsFromObject($object)
setErrorsFromObject
static isExistingObject($element, $id, $ref='', $ref_ext='')
Check if an object id or ref exists If you don't need or want to instantiate the object and just need...
updateRangOfLine($rowid, $rang)
Update position of line (rang)
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 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.
setEntity($currentobject)
Set entity id to use when to create an object.
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.
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', ...)
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_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.
setEventMessages($mesg, $mesgs, $style='mesgs', $messagekey='', $noduplicate=0, $attop=0)
Set event messages in dol_events session 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)
img_object($titlealt, $picto, $moreatt='', $pictoisfullpath=0, $srconly=0, $notitle=0, $allowothertags=array())
Show a picto called object_picto (generic function)
setEventMessage($mesgs, $style='mesgs', $noduplicate=0, $attop=0)
Set event message in dol_events session object.
dolGetStatus($statusLabel='', $statusLabelShort='', $html='', $statusType='status0', $displayMode=0, $url='', $params=array())
Output the badge of a status.
dol_print_error($db=null, $error='', $errors=null)
Displays error message system with all the information to facilitate the diagnosis and the escalation...
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
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