46require_once DOL_DOCUMENT_ROOT.
'/core/class/commonobject.class.php';
47require_once DOL_DOCUMENT_ROOT.
'/comm/propal/class/propaleligne.class.php';
48require_once DOL_DOCUMENT_ROOT.
'/product/class/product.class.php';
49require_once DOL_DOCUMENT_ROOT.
'/margin/lib/margins.lib.php';
50require_once DOL_DOCUMENT_ROOT.
'/multicurrency/class/multicurrency.class.php';
51require_once DOL_DOCUMENT_ROOT.
'/core/class/commonincoterm.class.php';
52require_once DOL_DOCUMENT_ROOT.
'/subtotals/class/commonsubtotal.class.php';
70 public $element =
'propal';
75 public $table_element =
'propal';
80 public $table_element_line =
'propaldet';
85 public $fk_element =
'fk_propal';
90 public $picto =
'propal';
96 public $TRIGGER_PREFIX =
'PROPAL';
102 public $restrictiononfksoc = 1;
133 public $ref_customer;
167 public $date_validation;
172 public $date_signature;
177 public $user_signature;
194 public $delivery_date;
200 public $fin_validite;
205 public $user_author_id;
236 public $cond_reglement_code;
241 public $cond_reglement;
246 public $cond_reglement_doc;
251 public $mode_reglement_code;
256 public $mode_reglement;
263 public $deposit_percent;
275 public $address_type;
286 public $availability_id;
293 public $fk_availability;
298 public $availability_code;
303 public $availability;
308 public $duree_validite;
313 public $demand_reason_id;
318 public $demand_reason_code;
323 public $demand_reason;
328 public $warehouse_id;
333 public $lines = array();
340 public $labelStatus = array();
341 public $labelStatusShort = array();
372 public $fields = array(
373 'rowid' => array(
'type' =>
'integer',
'label' =>
'TechnicalID',
'enabled' => 1,
'visible' => -1,
'notnull' => 1,
'position' => 10),
374 'entity' => array(
'type' =>
'integer',
'label' =>
'Entity',
'default' =>
'1',
'enabled' => 1,
'visible' => -2,
'notnull' => 1,
'position' => 15,
'index' => 1),
375 'ref' => array(
'type' =>
'varchar(30)',
'label' =>
'Ref',
'enabled' => 1,
'visible' => -1,
'notnull' => 1,
'showoncombobox' => 1,
'position' => 20),
376 'ref_client' => array(
'type' =>
'varchar(255)',
'label' =>
'RefCustomer',
'enabled' => 1,
'visible' => -1,
'position' => 22),
377 'ref_ext' => array(
'type' =>
'varchar(255)',
'label' =>
'RefExt',
'enabled' => 1,
'visible' => 0,
'position' => 40),
378 'fk_soc' => array(
'type' =>
'integer:Societe:societe/class/societe.class.php',
'label' =>
'ThirdParty',
'enabled' =>
'isModEnabled("societe")',
'visible' => -1,
'position' => 23),
379 'fk_projet' => array(
'type' =>
'integer:Project:projet/class/project.class.php:1:(fk_statut:=:1)',
'label' =>
'Project',
'enabled' =>
"isModEnabled('project')",
'visible' => -1,
'position' => 24),
380 'tms' => array(
'type' =>
'timestamp',
'label' =>
'DateModification',
'enabled' => 1,
'visible' => -1,
'notnull' => 1,
'position' => 25),
381 'datec' => array(
'type' =>
'datetime',
'label' =>
'DateCreation',
'enabled' => 1,
'visible' => -1,
'position' => 55),
382 'datep' => array(
'type' =>
'date',
'label' =>
'Date',
'enabled' => 1,
'visible' => -1,
'position' => 60),
383 'fin_validite' => array(
'type' =>
'datetime',
'label' =>
'DateEnd',
'enabled' => 1,
'visible' => -1,
'position' => 65),
384 'date_valid' => array(
'type' =>
'datetime',
'label' =>
'DateValidation',
'enabled' => 1,
'visible' => -1,
'position' => 70),
385 'date_cloture' => array(
'type' =>
'datetime',
'label' =>
'DateClosing',
'enabled' => 1,
'visible' => -1,
'position' => 75),
386 'fk_user_author' => array(
'type' =>
'integer:User:user/class/user.class.php',
'label' =>
'UserAuthor',
'enabled' => 1,
'visible' => -1,
'position' => 80),
387 'fk_user_modif' => array(
'type' =>
'integer:User:user/class/user.class.php',
'label' =>
'UserModif',
'enabled' => 1,
'visible' => -2,
'notnull' => -1,
'position' => 85),
388 'fk_user_valid' => array(
'type' =>
'integer:User:user/class/user.class.php',
'label' =>
'UserValidation',
'enabled' => 1,
'visible' => -1,
'position' => 90),
389 'fk_user_cloture' => array(
'type' =>
'integer:User:user/class/user.class.php',
'label' =>
'UserClosing',
'enabled' => 1,
'visible' => -1,
'position' => 95),
390 'price' => array(
'type' =>
'double',
'label' =>
'Price',
'enabled' => 1,
'visible' => -1,
'position' => 105),
391 'total_ht' => array(
'type' =>
'double(24,8)',
'label' =>
'TotalHT',
'enabled' => 1,
'visible' => -1,
'position' => 125,
'isameasure' => 1),
392 'total_tva' => array(
'type' =>
'double(24,8)',
'label' =>
'VAT',
'enabled' => 1,
'visible' => -1,
'position' => 130,
'isameasure' => 1),
393 'localtax1' => array(
'type' =>
'double(24,8)',
'label' =>
'LocalTax1',
'enabled' => 1,
'visible' => -1,
'position' => 135,
'isameasure' => 1),
394 'localtax2' => array(
'type' =>
'double(24,8)',
'label' =>
'LocalTax2',
'enabled' => 1,
'visible' => -1,
'position' => 140,
'isameasure' => 1),
395 'total_ttc' => array(
'type' =>
'double(24,8)',
'label' =>
'TotalTTC',
'enabled' => 1,
'visible' => -1,
'position' => 145,
'isameasure' => 1),
396 'fk_account' => array(
'type' =>
'integer',
'label' =>
'BankAccount',
'enabled' =>
'isModEnabled("bank")',
'visible' => -1,
'position' => 150),
397 'fk_currency' => array(
'type' =>
'varchar(3)',
'label' =>
'Currency',
'enabled' => 1,
'visible' => -1,
'position' => 155),
398 'fk_cond_reglement' => array(
'type' =>
'integer',
'label' =>
'PaymentTerm',
'enabled' => 1,
'visible' => -1,
'position' => 160),
399 'deposit_percent' => array(
'type' =>
'varchar(63)',
'label' =>
'DepositPercent',
'enabled' => 1,
'visible' => -1,
'position' => 161),
400 'fk_mode_reglement' => array(
'type' =>
'integer',
'label' =>
'PaymentMode',
'enabled' => 1,
'visible' => -1,
'position' => 165),
401 'note_private' => array(
'type' =>
'html',
'label' =>
'NotePrivate',
'enabled' => 1,
'visible' => 0,
'position' => 170),
402 'note_public' => array(
'type' =>
'html',
'label' =>
'NotePublic',
'enabled' => 1,
'visible' => 0,
'position' => 175),
403 'model_pdf' => array(
'type' =>
'varchar(255)',
'label' =>
'PDFTemplate',
'enabled' => 1,
'visible' => 0,
'position' => 180),
404 'date_livraison' => array(
'type' =>
'date',
'label' =>
'DateDeliveryPlanned',
'enabled' => 1,
'visible' => -1,
'position' => 185),
405 'fk_shipping_method' => array(
'type' =>
'integer',
'label' =>
'ShippingMethod',
'enabled' => 1,
'visible' => -1,
'position' => 190),
406 'fk_warehouse' => array(
'type' =>
'integer:Entrepot:product/stock/class/entrepot.class.php',
'label' =>
'DefaultWarehouse',
'enabled' =>
'isModEnabled("stock")',
'visible' => -1,
'position' => 191),
407 'fk_availability' => array(
'type' =>
'integer',
'label' =>
'Availability',
'enabled' => 1,
'visible' => -1,
'position' => 195),
408 'fk_delivery_address' => array(
'type' =>
'integer',
'label' =>
'DeliveryAddress',
'enabled' => 1,
'visible' => 0,
'position' => 200),
409 'fk_input_reason' => array(
'type' =>
'integer',
'label' =>
'InputReason',
'enabled' => 1,
'visible' => -1,
'position' => 205),
410 'extraparams' => array(
'type' =>
'varchar(255)',
'label' =>
'Extraparams',
'enabled' => 1,
'visible' => -1,
'position' => 215),
411 'fk_incoterms' => array(
'type' =>
'integer',
'label' =>
'IncotermCode',
'enabled' =>
'isModEnabled("incoterm")',
'visible' => -1,
'position' => 220),
412 'location_incoterms' => array(
'type' =>
'varchar(255)',
'label' =>
'IncotermLabel',
'enabled' =>
'isModEnabled("incoterm")',
'visible' => -1,
'position' => 225),
413 'fk_multicurrency' => array(
'type' =>
'integer',
'label' =>
'MulticurrencyID',
'enabled' => 1,
'visible' => -1,
'position' => 230),
414 'multicurrency_code' => array(
'type' =>
'varchar(255)',
'label' =>
'MulticurrencyCurrency',
'enabled' =>
'isModEnabled("multicurrency")',
'visible' => -1,
'position' => 235),
415 'multicurrency_tx' => array(
'type' =>
'double(24,8)',
'label' =>
'MulticurrencyRate',
'enabled' =>
'isModEnabled("multicurrency")',
'visible' => -1,
'position' => 240,
'isameasure' => 1),
416 'multicurrency_total_ht' => array(
'type' =>
'double(24,8)',
'label' =>
'MulticurrencyAmountHT',
'enabled' =>
'isModEnabled("multicurrency")',
'visible' => -1,
'position' => 245,
'isameasure' => 1),
417 'multicurrency_total_tva' => array(
'type' =>
'double(24,8)',
'label' =>
'MulticurrencyAmountVAT',
'enabled' =>
'isModEnabled("multicurrency")',
'visible' => -1,
'position' => 250,
'isameasure' => 1),
418 'multicurrency_total_ttc' => array(
'type' =>
'double(24,8)',
'label' =>
'MulticurrencyAmountTTC',
'enabled' =>
'isModEnabled("multicurrency")',
'visible' => -1,
'position' => 255,
'isameasure' => 1),
419 'last_main_doc' => array(
'type' =>
'varchar(255)',
'label' =>
'LastMainDoc',
'enabled' => 1,
'visible' => -1,
'position' => 260),
420 'fk_statut' => array(
'type' =>
'smallint(6)',
'label' =>
'Status',
'enabled' => 1,
'visible' => -1,
'notnull' => 1,
'position' => 500),
421 'import_key' => array(
'type' =>
'varchar(14)',
'label' =>
'ImportId',
'enabled' => 1,
'visible' => -2,
'position' => 900),
462 $this->ismultientitymanaged = 1;
463 $this->socid = $socid;
464 $this->
id = $propalid;
468 $this->fields[
'ref_ext'][
'visible'] =
getDolGlobalInt(
'MAIN_LIST_SHOW_REF_EXT');
484 public function add_product($idproduct, $qty, $remise_percent = 0)
493 dol_syslog(get_class($this).
"::add_product $idproduct, $qty, $remise_percent");
494 if ($idproduct > 0) {
496 $prod->fetch($idproduct);
498 $productdesc =
$prod->description;
502 if (empty($tva_tx)) {
512 $price =
$prod->multiprices[$this->thirdparty->price_level];
514 $price =
$prod->price;
519 $line->fk_product = $idproduct;
520 $line->desc = $productdesc;
522 $line->subprice = $price;
523 $line->remise_percent = $remise_percent;
524 $line->vat_src_code = $vat_src_code;
525 $line->tva_tx = $tva_tx;
526 $line->fk_unit =
$prod->fk_unit;
528 $line->info_bits = 1;
531 $this->lines[] = $line;
549 include_once DOL_DOCUMENT_ROOT.
'/core/lib/price.lib.php';
550 include_once DOL_DOCUMENT_ROOT.
'/core/class/discount.class.php';
555 $result = $remise->fetch($idremise);
558 if ($remise->fk_facture) {
559 $this->error = $langs->trans(
"ErrorDiscountAlreadyUsed");
560 $this->db->rollback();
566 $line->context = $this->context;
568 $line->fk_propal = $this->id;
569 $line->fk_remise_except = $remise->id;
570 $line->desc = $remise->description;
571 $line->vat_src_code = $remise->vat_src_code;
572 $line->tva_tx = $remise->tva_tx;
573 $line->localtax1_tx = $remise->localtax1_tx;
574 $line->localtax1_type = $remise->localtax1_type;
575 $line->localtax2_tx = $remise->localtax1_tx;
576 $line->localtax2_type = $remise->localtax1_type;
577 $line->subprice = -(float) $remise->amount_ht;
578 $line->fk_product = 0;
580 $line->remise_percent = 0;
582 $line->info_bits = 2;
584 $line->total_ht = -(float) $remise->amount_ht;
585 $line->total_tva = -(float) $remise->amount_tva;
586 $line->total_ttc = -(float) $remise->amount_ttc;
587 $line->total_localtax1 = -(float) $remise->total_localtax1;
588 $line->total_localtax2 = -(float) $remise->total_localtax2;
590 $result = $line->insert();
597 $this->db->rollback();
602 $this->db->rollback();
606 $this->db->rollback();
656 $remise_percent = 0.0,
657 $price_base_type =
'HT',
669 $array_options = array(),
674 $fk_remise_except = 0,
675 $noupdateafterinsertline = 0
679 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);
681 if ($this->
status == self::STATUS_DRAFT) {
682 include_once DOL_DOCUMENT_ROOT.
'/core/lib/price.lib.php';
685 if (empty($remise_percent)) {
691 if (empty($info_bits)) {
697 if (empty($fk_parent_line) || $fk_parent_line < 0) {
701 $remise_percent =
price2num($remise_percent);
704 $pu_ht_devise =
price2num($pu_ht_devise);
706 if (!preg_match(
'/\((.*)\)/', (
string) $txtva)) {
712 if ($price_base_type ==
'HT') {
724 $langs->load(
"errors");
725 $this->error = $langs->trans(
'ErrorStartDateGreaterEnd');
731 $product_type = $type;
732 if (!empty($fk_product) && $fk_product > 0) {
733 $product =
new Product($this->db);
734 $result = $product->fetch($fk_product);
735 $product_type = $product->type;
737 if ($product->isStockManaged() && $product->stock_reel < $qty &&
getDolGlobalString(
'STOCK_MUST_BE_ENOUGH_FOR_PROPOSAL')) {
738 $langs->load(
"errors");
739 $this->error = $langs->trans(
'ErrorStockIsNotEnoughToAddProductOnProposal', $product->ref);
740 $this->db->rollback();
752 $tmpproduct =
new Product($this->db);
753 $result = $tmpproduct->fetch($fk_product);
755 if ($newqty != $qty) {
757 setEventMessages($langs->trans(
'QtyRecalculatedWithPackaging'),
null,
'warnings');
764 if (preg_match(
'/\((.*)\)/', $txtva, $reg)) {
765 $vat_src_code = $reg[1];
766 $txtva = preg_replace(
'/\s*\(.*\)/',
'', $txtva);
769 $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);
771 $total_ht = $tabprice[0];
772 $total_tva = $tabprice[1];
773 $total_ttc = $tabprice[2];
774 $total_localtax1 = $tabprice[9];
775 $total_localtax2 = $tabprice[10];
776 $pu_ht = $tabprice[3];
777 $pu_tva = $tabprice[4];
778 $pu_ttc = $tabprice[5];
781 $multicurrency_total_ht = $tabprice[16];
782 $multicurrency_total_tva = $tabprice[17];
783 $multicurrency_total_ttc = $tabprice[18];
784 $pu_ht_devise = $tabprice[19];
788 if (empty($ranktouse) || $ranktouse == -1) {
789 $rangmax = $this->
line_max($fk_parent_line);
790 $ranktouse = $rangmax + 1;
796 $this->line->context = $this->context;
798 $this->line->fk_propal = $this->id;
799 $this->line->label = $label;
800 $this->line->desc = $desc;
801 $this->line->qty = (float) $qty;
803 $this->line->vat_src_code = $vat_src_code;
804 $this->line->tva_tx = $txtva;
805 $this->line->localtax1_tx = ($total_localtax1 ? $localtaxes_type[1] : 0);
806 $this->line->localtax2_tx = ($total_localtax2 ? $localtaxes_type[3] : 0);
807 $this->line->localtax1_type = empty($localtaxes_type[0]) ?
'' : $localtaxes_type[0];
808 $this->line->localtax2_type = empty($localtaxes_type[2]) ?
'' : $localtaxes_type[2];
809 $this->line->fk_product = $fk_product;
810 $this->line->product_type = $type;
811 $this->line->fk_remise_except = $fk_remise_except;
812 $this->line->remise_percent = $remise_percent;
813 $this->line->subprice = (float) $pu_ht;
815 $this->line->subprice_ttc = ($price_base_type ===
'TTC') ? (
float) $pu_ttc : 0;
816 $this->line->rang = $ranktouse;
817 $this->line->info_bits = $info_bits;
818 $this->line->total_ht = (float) $total_ht;
819 $this->line->total_tva = (float) $total_tva;
820 $this->line->total_localtax1 = (float) $total_localtax1;
821 $this->line->total_localtax2 = (float) $total_localtax2;
822 $this->line->total_ttc = (float) $total_ttc;
823 $this->line->special_code = $special_code;
824 $this->line->fk_parent_line = $fk_parent_line;
825 $this->line->fk_unit = $fk_unit;
828 $this->line->date_end = $date_end;
830 $this->line->fk_fournprice = $fk_fournprice;
831 $this->line->pa_ht = $pa_ht;
833 $this->line->origin_id = $origin_id;
834 $this->line->origin = $origin;
837 $this->line->fk_multicurrency = $this->fk_multicurrency;
838 $this->line->multicurrency_code = $this->multicurrency_code;
839 $this->line->multicurrency_subprice = (float) $pu_ht_devise;
840 $this->line->multicurrency_total_ht = (float) $multicurrency_total_ht;
841 $this->line->multicurrency_total_tva = (float) $multicurrency_total_tva;
842 $this->line->multicurrency_total_ttc = (float) $multicurrency_total_ttc;
845 if (empty($qty) && empty($special_code)) {
846 $this->line->special_code = 3;
849 if (is_array($array_options) && count($array_options) > 0) {
850 $this->line->array_options = $array_options;
853 $result = $this->line->insert();
855 if (!isset($this->context[
'createfromclone'])) {
856 if (!empty($fk_parent_line)) {
859 } elseif ($ranktouse > 0 && $ranktouse <= count($this->lines)) {
861 $linecount = count($this->lines);
862 for ($ii = $ranktouse; $ii <= $linecount; $ii++) {
867 $this->lines[] = $this->line;
870 foreach ($this->lines as $tmpline) {
871 if ($tmpline->id == $origin_id && $tmpline->element == $origin) {
872 $this->line->extraparams = $tmpline->extraparams;
873 $this->line->setExtraParameters();
879 if (empty($noupdateafterinsertline)) {
885 return $this->line->id;
887 $this->error = $this->db->error();
888 $this->db->rollback();
893 $this->db->rollback();
897 dol_syslog(get_class($this).
"::addline status of proposal must be Draft to allow use of ->addline()", LOG_ERR);
932 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)
937 $this->error =
'ErrorLineIDDoesNotMatchWithObjectID';
941 dol_syslog(get_class($this).
"::updateLine rowid=$rowid, pu=$pu, qty=$qty, remise_percent=$remise_percent,
942 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");
943 include_once DOL_DOCUMENT_ROOT.
'/core/lib/price.lib.php';
946 $remise_percent =
price2num($remise_percent);
949 $pu_ht_devise =
price2num($pu_ht_devise);
950 if (!preg_match(
'/\((.*)\)/', (
string) $txtva)) {
956 if (empty($qty) && empty($special_code)) {
959 if (!empty($qty) && $special_code == 3) {
967 $langs->load(
"errors");
968 $this->error = $langs->trans(
'ErrorStartDateGreaterEnd');
972 if ($this->
status == self::STATUS_DRAFT) {
984 if (preg_match(
'/\((.*)\)/', $txtva, $reg)) {
985 $vat_src_code = $reg[1];
986 $txtva = preg_replace(
'/\s*\(.*\)/',
'', $txtva);
995 if ($tmpline->fetch($rowid) > 0) {
997 if ($newqty != $qty) {
999 setEventMessages($langs->trans(
'QtyRecalculatedWithPackaging'),
null,
'warnings');
1004 $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);
1005 $total_ht = $tabprice[0];
1006 $total_tva = $tabprice[1];
1007 $total_ttc = $tabprice[2];
1008 $total_localtax1 = $tabprice[9];
1009 $total_localtax2 = $tabprice[10];
1010 $pu_ht = $tabprice[3];
1011 $pu_tva = $tabprice[4];
1012 $pu_ttc = $tabprice[5];
1015 $multicurrency_total_ht = $tabprice[16];
1016 $multicurrency_total_tva = $tabprice[17];
1017 $multicurrency_total_ttc = $tabprice[18];
1018 $pu_ht_devise = $tabprice[19];
1022 $line->fetch($rowid);
1024 $staticline = clone $line;
1026 $line->oldline = $staticline;
1027 $this->line = $line;
1028 $this->line->context = $this->context;
1029 $this->line->rang = $rang;
1032 if (!empty($fk_parent_line) && !empty($staticline->fk_parent_line) && $fk_parent_line != $staticline->fk_parent_line) {
1033 $rangmax = $this->
line_max($fk_parent_line);
1034 $this->line->rang = $rangmax + 1;
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);
1135 if ($id > 0 && (
int) $line->fk_propal !== (
int) $id) {
1136 $this->db->rollback();
1137 $this->error =
'ErrorLineIDDoesNotMatchWithObjectID';
1142 $staticline = clone $line;
1143 $line->oldline = $staticline;
1145 if ($line->delete($user) > 0) {
1148 $this->db->commit();
1152 $this->db->rollback();
1156 $this->error =
'ErrorDeleteLineNotAllowedByObjectStatus';
1170 public function create($user, $notrigger = 0)
1179 if (empty($this->
date)) {
1180 $this->
date = $this->datep;
1182 $this->fin_validite = $this->
date + ($this->duree_validite * 24 * 3600);
1183 if (empty($this->availability_id)) {
1184 $this->availability_id = 0;
1186 if (empty($this->demand_reason_id)) {
1187 $this->demand_reason_id = 0;
1191 if (!empty($this->multicurrency_code) && empty($this->multicurrency_tx)) {
1196 if (empty($this->fk_multicurrency)) {
1198 $this->fk_multicurrency = 0;
1199 $this->multicurrency_tx = 1;
1205 $delivery_date = $this->delivery_date;
1212 $this->error =
"Failed to fetch company";
1213 dol_syslog(get_class($this).
"::create ".$this->error, LOG_ERR);
1218 if (!empty($this->
ref)) {
1221 $this->error =
'ErrorRefAlreadyExists';
1222 dol_syslog(get_class($this).
"::create ".$this->error, LOG_WARNING);
1223 $this->db->rollback();
1228 if (empty($this->
date)) {
1229 $this->error =
"Date of proposal is required";
1230 dol_syslog(get_class($this).
"::create ".$this->error, LOG_ERR);
1238 $sql =
"INSERT INTO ".MAIN_DB_PREFIX.$this->table_element.
" (";
1241 $sql .=
", total_tva";
1242 $sql .=
", total_ttc";
1246 $sql .=
", fk_user_author";
1247 $sql .=
", note_private";
1248 $sql .=
", note_public";
1249 $sql .=
", model_pdf";
1250 $sql .=
", fin_validite";
1251 $sql .=
", fk_cond_reglement";
1252 $sql .=
", deposit_percent";
1253 $sql .=
", fk_mode_reglement";
1254 $sql .=
", fk_account";
1255 $sql .=
", ref_client";
1256 $sql .=
", ref_ext";
1257 $sql .=
", date_livraison";
1258 $sql .=
", fk_shipping_method";
1259 $sql .=
", fk_warehouse";
1260 $sql .=
", fk_availability";
1261 $sql .=
", fk_input_reason";
1262 $sql .=
", fk_projet";
1263 $sql .=
", fk_incoterms";
1264 $sql .=
", location_incoterms";
1266 $sql .=
", fk_multicurrency";
1267 $sql .=
", multicurrency_code";
1268 $sql .=
", multicurrency_tx";
1270 $sql .=
" VALUES (";
1271 $sql .= ((int) $this->socid);
1275 $sql .=
", '".$this->db->idate($this->
date).
"'";
1276 $sql .=
", '".$this->db->idate($now).
"'";
1277 $sql .=
", '(PROV)'";
1278 $sql .=
", ".($user->id > 0 ? ((int) $user->id) :
"NULL");
1279 $sql .=
", '".$this->db->escape($this->note_private).
"'";
1280 $sql .=
", '".$this->db->escape($this->note_public).
"'";
1281 $sql .=
", '".$this->db->escape($this->model_pdf).
"'";
1282 $sql .=
", ".($this->fin_validite !=
'' ?
"'".$this->db->idate($this->fin_validite).
"'" :
"NULL");
1283 $sql .=
", ".($this->cond_reglement_id > 0 ? ((int) $this->cond_reglement_id) :
'NULL');
1284 $sql .=
", ".(!empty($this->deposit_percent) ?
"'".$this->db->escape($this->deposit_percent).
"'" :
'NULL');
1285 $sql .=
", ".($this->mode_reglement_id > 0 ? ((int) $this->mode_reglement_id) :
'NULL');
1286 $sql .=
", ".($this->fk_account > 0 ? ((int) $this->fk_account) :
'NULL');
1287 $sql .=
", '".$this->db->escape((
string) $this->ref_client).
"'";
1288 $sql .=
", '".$this->db->escape((
string) $this->ref_ext).
"'";
1289 $sql .=
", ".(!
isDolTms($delivery_date) ?
"NULL" :
"'".$this->db->idate($delivery_date).
"'");
1290 $sql .=
", ".($this->shipping_method_id > 0 ? ((int) $this->shipping_method_id) :
'NULL');
1291 $sql .=
", ".($this->warehouse_id > 0 ? ((int) $this->warehouse_id) :
'NULL');
1292 $sql .=
", ".((int) $this->availability_id);
1293 $sql .=
", ".((int) $this->demand_reason_id);
1294 $sql .=
", ".($this->fk_project ? ((int) $this->fk_project) :
"null");
1295 $sql .=
", ".(int) $this->fk_incoterms;
1296 $sql .=
", '".$this->db->escape($this->location_incoterms).
"'";
1297 $sql .=
", ".(int) $this->entity;
1298 $sql .=
", ".(int) $this->fk_multicurrency;
1299 $sql .=
", '".$this->db->escape($this->multicurrency_code).
"'";
1300 $sql .=
", ".(float) $this->multicurrency_tx;
1303 dol_syslog(get_class($this).
"::create", LOG_DEBUG);
1304 $resql = $this->db->query($sql);
1306 $this->
id = $this->db->last_insert_id(MAIN_DB_PREFIX.$this->table_element);
1309 $this->
ref =
'(PROV'.$this->id.
')';
1310 $sql =
'UPDATE '.MAIN_DB_PREFIX.$this->table_element.
" SET ref='".$this->db->escape($this->
ref).
"' WHERE rowid=".((int) $this->
id);
1312 dol_syslog(get_class($this).
"::create", LOG_DEBUG);
1313 $resql = $this->db->query($sql);
1318 if (!empty($this->linkedObjectsIds) && empty($this->linked_objects)) {
1319 $this->linked_objects = $this->linkedObjectsIds;
1323 if (!$error && !empty($this->linked_objects) && is_array($this->linked_objects)) {
1324 foreach ($this->linked_objects as $origin => $tmp_origin_id) {
1325 if (is_array($tmp_origin_id)) {
1326 foreach ($tmp_origin_id as $origin_id) {
1329 $this->error = $this->db->lasterror();
1334 $origin_id = $tmp_origin_id;
1337 $this->error = $this->db->lasterror();
1348 $fk_parent_line = 0;
1349 $num = count($this->lines);
1351 for ($i = 0; $i < $num; $i++) {
1352 if (!is_object($this->lines[$i])) {
1356 foreach ($this->lines[$i] as $key => $val) {
1357 $lineobj->$key = $val;
1360 $this->lines[$i] = $line;
1362 $line = $this->lines[$i];
1365 if (($line->product_type != 9 && empty($line->fk_parent_line)) || $line->product_type == 9) {
1366 $fk_parent_line = 0;
1369 $vatrate = $line->tva_tx;
1370 if ($line->vat_src_code && !preg_match(
'/\(.*\)/', $vatrate)) {
1371 $vatrate .=
' ('.$line->vat_src_code.
')';
1375 $originid = $line->origin_id;
1376 $origintype = empty($line->origin_type) ? $line->origin : $line->origin_type;
1378 $originid = $line->id;
1379 $origintype = $this->element;
1383 $line_price_base_type = $line->getPriceBaseType();
1386 (
float) $line->subprice,
1389 $line->localtax1_tx,
1390 $line->localtax2_tx,
1392 $line->remise_percent,
1393 $line_price_base_type,
1394 (
float) $line->subprice_ttc,
1396 $line->product_type,
1398 $line->special_code,
1400 $line->fk_fournprice,
1405 $line->array_options,
1407 (
string) $origintype,
1416 $this->error = $this->db->error;
1417 dol_print_error($this->db);
1422 $line->id = $result;
1425 if ($result > 0 && $line->product_type == 9) {
1426 $fk_parent_line = $result;
1441 if (!$error && !$notrigger) {
1443 $result = $this->call_trigger(
'PROPAL_CREATE', $user);
1450 $this->error = $this->db->lasterror();
1455 $this->error = $this->db->lasterror();
1460 $this->db->commit();
1461 dol_syslog(get_class($this).
"::create done id=".$this->
id);
1464 $this->db->rollback();
1468 $this->error = $this->db->lasterror();
1469 $this->db->rollback();
1484 public function createFromClone(
User $user, $socid = 0, $forceentity =
null, $update_prices =
false, $update_desc =
false)
1495 $object =
new self($this->db);
1502 $objsoc =
new Societe($this->db);
1505 if (!empty($socid) && $socid !=
$object->socid) {
1506 if ($objsoc->fetch($socid) > 0) {
1508 $object->cond_reglement_id = (!empty($objsoc->cond_reglement_id) ? $objsoc->cond_reglement_id : 0);
1509 $object->deposit_percent = (!empty($objsoc->deposit_percent) ? $objsoc->deposit_percent :
null);
1510 $object->mode_reglement_id = (!empty($objsoc->mode_reglement_id) ? $objsoc->mode_reglement_id : 0);
1511 $object->fk_delivery_address = 0;
1534 $objsoc->fetch(
$object->socid);
1538 if ($update_prices ===
true || $update_desc ===
true) {
1539 if ($objsoc->id > 0 && !empty(
$object->lines)) {
1542 require_once DOL_DOCUMENT_ROOT .
'/product/class/productcustomerprice.class.php';
1545 foreach (
$object->lines as $line) {
1548 if ($line->fk_product > 0) {
1550 $res =
$prod->fetch($line->fk_product);
1552 if ($update_prices ===
true) {
1553 $pu_ht =
$prod->price;
1555 $remise_percent = $objsoc->remise_percent;
1558 $pu_ht =
$prod->multiprices[$objsoc->price_level];
1560 if (isset(
$prod->multiprices_tva_tx[$objsoc->price_level])) {
1561 $tva_tx = (string)
$prod->multiprices_tva_tx[$objsoc->price_level];
1566 $filter = array(
't.fk_product' => (
string)
$prod->id,
't.fk_soc' => (
string) $objsoc->id);
1567 $result = $prodcustprice->fetchAll(
'',
'', 0, 0, $filter);
1570 if (count($prodcustprice->lines) > 0) {
1571 $date_now = (int) floor(
dol_now() / 86400) * 86400;
1572 foreach ($prodcustprice->lines as $k => $custprice_line) {
1573 if ($custprice_line->date_begin <= $date_now && (empty($custprice_line->date_end) || $date_now <= $custprice_line->date_end)) {
1574 $pu_ht =
price($custprice_line->price);
1575 $tva_tx = ($custprice_line->default_vat_code ? $custprice_line->tva_tx .
' (' . $custprice_line->default_vat_code .
' )' : $custprice_line->tva_tx);
1576 if ($custprice_line->default_vat_code && !preg_match(
'/\(.*\)/', $tva_tx)) {
1577 $tva_tx .=
' (' . $custprice_line->default_vat_code .
')';
1579 $remise_percent = $custprice_line->discount_percent;
1587 $line->subprice = $pu_ht;
1588 $line->tva_tx = $tva_tx;
1589 $line->remise_percent = $remise_percent;
1594 if ($buyPrice > 0) {
1595 $line->pa_ht = $buyPrice;
1598 if ($update_desc ===
true) {
1599 $line->desc =
$prod->description;
1609 $object->entity = (!empty($forceentity) ? $forceentity :
$object->entity);
1614 $object->user_creation_id = $user->id;
1615 $object->user_validation_id = 0;
1628 $object->context[
'createfromclone'] =
'createfromclone';
1629 $result =
$object->create($user);
1637 if (
$object->copy_linked_contact($this,
'internal') < 0) {
1644 if ($this->socid ==
$object->socid) {
1645 if (
$object->copy_linked_contact($this,
'external') < 0) {
1653 if (is_object($hookmanager)) {
1654 $parameters = array(
'objFrom' => $this,
'clonedObj' =>
$object);
1656 $reshook = $hookmanager->executeHooks(
'createFrom', $parameters,
$object, $action);
1664 unset(
$object->context[
'createfromclone']);
1668 $this->db->commit();
1671 $this->db->rollback();
1685 public function fetch($rowid, $ref =
'', $ref_ext =
'', $forceentity = 0)
1687 $sql =
"SELECT p.rowid, p.ref, p.entity, p.fk_soc";
1688 $sql .=
", p.total_ttc, p.total_tva, p.localtax1, p.localtax2, p.total_ht";
1689 $sql .=
", p.datec";
1690 $sql .=
", p.date_signature as dates";
1691 $sql .=
", p.date_valid as datev";
1692 $sql .=
", p.date_cloture";
1693 $sql .=
", p.datep as dp";
1694 $sql .=
", p.fin_validite as dfv";
1695 $sql .=
", p.date_livraison as delivery_date";
1696 $sql .=
", p.model_pdf, p.last_main_doc, p.ref_client, ref_ext, p.extraparams";
1697 $sql .=
", p.note_private, p.note_public";
1698 $sql .=
", p.fk_projet as fk_project, p.fk_statut";
1699 $sql .=
", p.fk_user_author, p.fk_user_valid, p.fk_user_cloture";
1700 $sql .=
", p.fk_delivery_address";
1701 $sql .=
", p.fk_availability";
1702 $sql .=
", p.fk_input_reason";
1703 $sql .=
", p.fk_cond_reglement";
1704 $sql .=
", p.fk_mode_reglement";
1705 $sql .=
', p.fk_account';
1706 $sql .=
", p.fk_shipping_method";
1707 $sql .=
", p.fk_warehouse";
1708 $sql .=
", p.fk_incoterms, p.location_incoterms";
1709 $sql .=
", p.fk_multicurrency, p.multicurrency_code, p.multicurrency_tx, p.multicurrency_total_ht, p.multicurrency_total_tva, p.multicurrency_total_ttc";
1710 $sql .=
", p.tms as date_modification";
1711 $sql .=
", i.libelle as label_incoterms";
1712 $sql .=
", c.label as statut_label";
1713 $sql .=
", ca.code as availability_code, ca.label as availability";
1714 $sql .=
", dr.code as demand_reason_code, dr.label as demand_reason";
1715 $sql .=
", cr.code as cond_reglement_code, cr.libelle as cond_reglement, cr.libelle_facture as cond_reglement_libelle_doc, p.deposit_percent";
1716 $sql .=
", cp.code as mode_reglement_code, cp.libelle as mode_reglement";
1717 $sql .=
" FROM ".MAIN_DB_PREFIX.$this->table_element.
" as p";
1718 $sql .=
' LEFT JOIN '.MAIN_DB_PREFIX.
'c_propalst as c ON p.fk_statut = c.id';
1719 $sql .=
' LEFT JOIN '.MAIN_DB_PREFIX.
'c_paiement as cp ON p.fk_mode_reglement = cp.id AND cp.entity IN ('.
getEntity(
'c_paiement').
')';
1720 $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').
')';
1721 $sql .=
' LEFT JOIN '.MAIN_DB_PREFIX.
'c_availability as ca ON p.fk_availability = ca.rowid';
1722 $sql .=
' LEFT JOIN '.MAIN_DB_PREFIX.
'c_input_reason as dr ON p.fk_input_reason = dr.rowid';
1723 $sql .=
' LEFT JOIN '.MAIN_DB_PREFIX.
'c_incoterms as i ON p.fk_incoterms = i.rowid';
1726 if (!empty($forceentity)) {
1727 $sql .=
" WHERE p.entity = ".(int) $forceentity;
1729 $sql .=
" WHERE p.entity IN (".getEntity(
'propal').
")";
1731 $sql .=
" AND p.ref='".$this->db->escape($ref).
"'";
1734 $sql .=
" WHERE p.rowid = ".((int) $rowid);
1737 dol_syslog(get_class($this).
"::fetch", LOG_DEBUG);
1738 $resql = $this->db->query($sql);
1740 if ($this->db->num_rows($resql)) {
1741 $obj = $this->db->fetch_object($resql);
1743 $this->
id = $obj->rowid;
1744 $this->entity = $obj->entity;
1746 $this->
ref = $obj->ref;
1747 $this->ref_client = $obj->ref_client;
1748 $this->ref_customer = $obj->ref_client;
1749 $this->ref_ext = $obj->ref_ext;
1751 $this->total = $obj->total_ttc;
1752 $this->total_ttc = $obj->total_ttc;
1753 $this->total_ht = $obj->total_ht;
1754 $this->total_tva = $obj->total_tva;
1755 $this->total_localtax1 = $obj->localtax1;
1756 $this->total_localtax2 = $obj->localtax2;
1758 $this->socid = $obj->fk_soc;
1759 $this->thirdparty =
null;
1761 $this->fk_project = $obj->fk_project;
1762 $this->project =
null;
1764 $this->model_pdf = $obj->model_pdf;
1765 $this->last_main_doc = $obj->last_main_doc;
1766 $this->note = $obj->note_private;
1767 $this->note_private = $obj->note_private;
1768 $this->note_public = $obj->note_public;
1770 $this->
status = (int) $obj->fk_statut;
1771 $this->statut = $this->status;
1773 $this->datec = $this->db->jdate($obj->datec);
1774 $this->datev = $this->db->jdate($obj->datev);
1775 $this->date_creation = $this->db->jdate($obj->datec);
1776 $this->date_validation = $this->db->jdate($obj->datev);
1777 $this->date_modification = $this->db->jdate($obj->date_modification);
1778 $this->date_signature = $this->db->jdate($obj->dates);
1779 $this->date_cloture = $this->db->jdate($obj->date_cloture);
1780 $this->
date = $this->db->jdate($obj->dp);
1781 $this->datep = $this->db->jdate($obj->dp);
1782 $this->fin_validite = $this->db->jdate($obj->dfv);
1783 $this->delivery_date = $this->db->jdate($obj->delivery_date);
1784 $this->shipping_method_id = ($obj->fk_shipping_method > 0) ? $obj->fk_shipping_method :
null;
1785 $this->warehouse_id = ($obj->fk_warehouse > 0) ? $obj->fk_warehouse :
null;
1786 $this->availability_id = $obj->fk_availability;
1787 $this->availability_code = $obj->availability_code;
1789 $this->demand_reason_id = $obj->fk_input_reason;
1790 $this->demand_reason_code = $obj->demand_reason_code;
1792 $this->fk_address = $obj->fk_delivery_address;
1794 $this->mode_reglement_id = $obj->fk_mode_reglement;
1795 $this->mode_reglement_code = $obj->mode_reglement_code;
1796 $this->mode_reglement = $obj->mode_reglement;
1797 $this->fk_account = ($obj->fk_account > 0) ? $obj->fk_account :
null;
1798 $this->cond_reglement_id = $obj->fk_cond_reglement;
1799 $this->cond_reglement_code = $obj->cond_reglement_code;
1800 $this->cond_reglement = $obj->cond_reglement;
1801 $this->cond_reglement_doc = $obj->cond_reglement_libelle_doc;
1802 $this->deposit_percent = $obj->deposit_percent;
1804 $this->extraparams = !empty($obj->extraparams) ? (array) json_decode($obj->extraparams,
true) : array();
1806 $this->user_author_id = $obj->fk_user_author;
1807 $this->user_validation_id = $obj->fk_user_valid;
1808 $this->user_closing_id = $obj->fk_user_cloture;
1811 $this->fk_incoterms = $obj->fk_incoterms;
1812 $this->location_incoterms = $obj->location_incoterms;
1813 $this->label_incoterms = $obj->label_incoterms;
1816 $this->fk_multicurrency = $obj->fk_multicurrency;
1817 $this->multicurrency_code = $obj->multicurrency_code;
1818 $this->multicurrency_tx = $obj->multicurrency_tx;
1819 $this->multicurrency_total_ht = $obj->multicurrency_total_ht;
1820 $this->multicurrency_total_tva = $obj->multicurrency_total_tva;
1821 $this->multicurrency_total_ttc = $obj->multicurrency_total_ttc;
1827 $this->db->free($resql);
1829 $this->lines = array();
1840 $this->error =
"Record Not Found";
1843 $this->error = $this->db->lasterror();
1860 if (isset($this->
ref)) {
1861 $this->
ref = trim($this->
ref);
1863 if (isset($this->ref_client)) {
1864 $this->ref_client = trim($this->ref_client);
1866 if (isset($this->note) || isset($this->note_private)) {
1867 $this->note_private = (isset($this->note_private) ? trim($this->note_private) : trim($this->note));
1869 if (isset($this->note_public)) {
1870 $this->note_public = trim($this->note_public);
1872 if (isset($this->model_pdf)) {
1873 $this->model_pdf = trim($this->model_pdf);
1875 if (isset($this->import_key)) {
1876 $this->import_key = trim($this->import_key);
1878 if (!empty($this->duree_validite) && is_numeric($this->duree_validite)) {
1879 $this->fin_validite = $this->
date + ($this->duree_validite * 24 * 3600);
1886 $sql =
"UPDATE ".MAIN_DB_PREFIX.$this->table_element.
" SET";
1887 $sql =
"UPDATE ".MAIN_DB_PREFIX.
"propal SET";
1888 $sql .=
" ref = ".(isset($this->
ref) ?
"'".$this->db->escape($this->
ref).
"'" :
"null").
",";
1889 $sql .=
" ref_client = ".(isset($this->ref_client) ?
"'".$this->db->escape($this->ref_client).
"'" :
"null").
",";
1890 $sql .=
" ref_ext = ".(isset($this->ref_ext) ?
"'".$this->db->escape($this->ref_ext).
"'" :
"null").
",";
1891 $sql .=
" fk_soc = ".(!empty($this->socid) ? (int) $this->socid :
"null").
",";
1892 $sql .=
" datep = ".(strval($this->
date) !=
'' ?
"'".$this->db->idate($this->
date).
"'" :
'null').
",";
1893 if (!empty($this->fin_validite)) {
1894 $sql .=
" fin_validite = ".(strval($this->fin_validite) !=
'' ?
"'".$this->db->idate($this->fin_validite).
"'" :
'null').
",";
1896 $sql .=
" date_valid = ".(strval($this->date_validation) !=
'' ?
"'".$this->db->idate($this->date_validation).
"'" :
'null').
",";
1897 $sql .=
" total_tva = ".(isset($this->total_tva) ? (float) $this->total_tva :
"null").
",";
1898 $sql .=
" localtax1 = ".(isset($this->total_localtax1) ? (float) $this->total_localtax1 :
"null").
",";
1899 $sql .=
" localtax2 = ".(isset($this->total_localtax2) ? (float) $this->total_localtax2 :
"null").
",";
1900 $sql .=
" total_ht = ".(isset($this->total_ht) ? (float) $this->total_ht :
"null").
",";
1901 $sql .=
" total_ttc = ".(isset($this->total_ttc) ? (float) $this->total_ttc :
"null").
",";
1902 $sql .=
" fk_statut = ".(isset($this->
status) ? (int) $this->
status :
"null").
",";
1903 $sql .=
" fk_user_author = ".(!empty($this->user_author_id) ? (int) $this->user_author_id :
"null").
",";
1904 $sql .=
" fk_user_valid = ".(!empty($this->user_validation_id) ? (int) $this->user_validation_id :
"null").
",";
1906 $sql .=
" fk_projet = ".(!empty($this->fk_project) ? (int) $this->fk_project :
"null").
",";
1907 $sql .=
" fk_cond_reglement = ".(!empty($this->cond_reglement_id) ? (int) $this->cond_reglement_id :
"null").
",";
1908 $sql .=
" deposit_percent = ".(!empty($this->deposit_percent) ?
"'".$this->db->escape($this->deposit_percent).
"'" :
"null").
",";
1909 $sql .=
" fk_mode_reglement = ".(!empty($this->mode_reglement_id) ? (int) $this->mode_reglement_id :
"null").
",";
1910 $sql .=
" fk_input_reason = ".(!empty($this->demand_reason_id) ? (int) $this->demand_reason_id :
"null").
",";
1911 $sql .=
" fk_shipping_method = ".(isset($this->shipping_method_id) ? (int) $this->shipping_method_id :
"null").
",";
1912 $sql .=
" fk_availability = ".(!empty($this->availability_id) ? (int) $this->availability_id :
"null").
",";
1913 $sql .=
" note_private = ".(isset($this->note_private) ?
"'".$this->db->escape($this->note_private).
"'" :
"null").
",";
1914 $sql .=
" note_public = ".(isset($this->note_public) ?
"'".$this->db->escape($this->note_public).
"'" :
"null").
",";
1915 $sql .=
" model_pdf = ".(isset($this->model_pdf) ?
"'".$this->db->escape($this->model_pdf).
"'" :
"null").
",";
1916 $sql .=
" import_key = ".(isset($this->import_key) ?
"'".$this->db->escape($this->import_key).
"'" :
"null");
1917 $sql .=
" WHERE rowid = ".((int) $this->
id);
1921 dol_syslog(get_class($this).
"::update", LOG_DEBUG);
1922 $resql = $this->db->query($sql);
1925 $this->errors[] =
"Error ".$this->db->lasterror();
1935 if (!$error && !$notrigger) {
1937 $result = $this->call_trigger(
'PROPAL_MODIFY', $user);
1946 foreach ($this->errors as $errmsg) {
1947 dol_syslog(get_class($this).
"::update ".$errmsg, LOG_ERR);
1948 $this->error .= ($this->error ?
', '.$errmsg : $errmsg);
1950 $this->db->rollback();
1953 $this->db->commit();
1968 public function fetch_lines($only_product = 0, $loadalsotranslation = 0, $sqlforgedfilters =
'')
1971 $this->lines = array();
1973 $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,';
1974 $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,';
1975 $sql .=
' d.fk_unit,';
1976 $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,';
1977 $sql .=
' p.weight, p.weight_units, p.volume, p.volume_units,';
1978 $sql .=
' p.customcode, p.fk_country as country_id, c.code as country_code,';
1979 $sql .=
' d.date_start, d.date_end, d.extraparams,';
1980 $sql .=
' d.fk_multicurrency, d.multicurrency_code, d.multicurrency_subprice, d.multicurrency_total_ht, d.multicurrency_total_tva, d.multicurrency_total_ttc';
1981 $sql .=
' FROM '.MAIN_DB_PREFIX.$this->table_element_line.
' as d';
1982 $sql .=
' LEFT JOIN '.MAIN_DB_PREFIX.
'product as p ON (d.fk_product = p.rowid)';
1983 $sql .=
' LEFT JOIN '.MAIN_DB_PREFIX.
'c_country as c ON c.rowid = p.fk_country';
1984 $sql .=
' WHERE d.fk_propal = '.((int) $this->
id);
1985 if ($only_product) {
1986 $sql .=
' AND p.fk_product_type = 0';
1988 if ($sqlforgedfilters) {
1989 $sql .= $sqlforgedfilters;
1991 $sql .=
' ORDER BY d.rang, d.rowid';
1993 dol_syslog(get_class($this).
"::fetch_lines", LOG_DEBUG);
1994 $result = $this->db->query($sql);
1996 require_once DOL_DOCUMENT_ROOT.
'/core/class/extrafields.class.php';
1998 $num = $this->db->num_rows($result);
2002 $objp = $this->db->fetch_object($result);
2006 $line->rowid = $objp->rowid;
2007 $line->id = $objp->rowid;
2008 $line->fk_propal = $objp->fk_propal;
2009 $line->fk_parent_line = $objp->fk_parent_line;
2010 $line->label = $objp->custom_label;
2011 $line->desc = $objp->description;
2012 $line->description = $objp->description;
2013 $line->qty = $objp->qty;
2014 $line->vat_src_code = $objp->vat_src_code;
2015 $line->tva_tx = $objp->tva_tx;
2016 $line->localtax1_tx = $objp->localtax1_tx;
2017 $line->localtax2_tx = $objp->localtax2_tx;
2018 $line->localtax1_type = $objp->localtax1_type;
2019 $line->localtax2_type = $objp->localtax2_type;
2020 $line->subprice = $objp->subprice;
2021 $line->subprice_ttc = $objp->subprice_ttc;
2022 $line->fk_remise_except = $objp->fk_remise_except;
2023 $line->remise_percent = $objp->remise_percent;
2025 $line->info_bits = $objp->info_bits;
2026 $line->total_ht = $objp->total_ht;
2027 $line->total_tva = $objp->total_tva;
2028 $line->total_localtax1 = $objp->total_localtax1;
2029 $line->total_localtax2 = $objp->total_localtax2;
2030 $line->total_ttc = $objp->total_ttc;
2031 $line->fk_fournprice = $objp->fk_fournprice;
2032 $marginInfos =
getMarginInfos($objp->subprice, $objp->remise_percent, $objp->tva_tx, $objp->localtax1_tx, $objp->localtax2_tx, $line->fk_fournprice, $objp->pa_ht);
2033 $line->pa_ht = $marginInfos[0];
2034 $line->marge_tx = $marginInfos[1];
2035 $line->marque_tx = $marginInfos[2];
2036 $line->special_code = $objp->special_code;
2037 $line->rang = $objp->rang;
2039 $line->fk_product = $objp->fk_product;
2041 $line->ref = $objp->product_ref;
2042 $line->libelle = $objp->product_label;
2044 $line->product_ref = $objp->product_ref;
2045 $line->product_label = $objp->product_label;
2046 $line->product_desc = $objp->product_desc;
2047 $line->product_tobatch = $objp->product_tobatch;
2048 $line->product_barcode = $objp->product_barcode;
2049 $line->product_custom_code = $objp->customcode;
2050 $line->product_custom_country_id = $objp->country_id;
2051 $line->product_custom_country_code = $objp->country_code;
2052 $line->product_type = $objp->product_type;
2053 $line->fk_product_type = $objp->fk_product_type;
2055 $line->fk_unit = $objp->fk_unit;
2056 $line->weight = $objp->weight;
2057 $line->weight_units = $objp->weight_units;
2058 $line->volume = $objp->volume;
2059 $line->volume_units = $objp->volume_units;
2061 $line->date_start = $this->db->jdate($objp->date_start);
2062 $line->date_end = $this->db->jdate($objp->date_end);
2064 $line->extraparams = !empty($objp->extraparams) ? (array) json_decode($objp->extraparams,
true) : array();
2067 $line->fk_multicurrency = $objp->fk_multicurrency;
2068 $line->multicurrency_code = $objp->multicurrency_code;
2069 $line->multicurrency_subprice = $objp->multicurrency_subprice;
2070 $line->multicurrency_total_ht = $objp->multicurrency_total_ht;
2071 $line->multicurrency_total_tva = $objp->multicurrency_total_tva;
2072 $line->multicurrency_total_ttc = $objp->multicurrency_total_ttc;
2074 $line->fetch_optionals();
2077 if (
getDolGlobalInt(
'MAIN_MULTILANGS') && !empty($objp->fk_product) && !empty($loadalsotranslation)) {
2078 $tmpproduct =
new Product($this->db);
2079 $tmpproduct->fetch($objp->fk_product);
2080 $tmpproduct->getMultiLangs();
2082 $line->multilangs = $tmpproduct->multilangs;
2085 $this->lines[$i] = $line;
2090 $this->db->free($result);
2094 $this->error = $this->db->lasterror();
2106 public function valid($user, $notrigger = 0)
2110 require_once DOL_DOCUMENT_ROOT.
'/core/lib/files.lib.php';
2115 if ($this->
status == self::STATUS_VALIDATED) {
2116 dol_syslog(get_class($this).
"::valid action abandoned: already validated", LOG_WARNING);
2120 if (!((!
getDolGlobalString(
'MAIN_USE_ADVANCED_PERMS') && $user->hasRight(
'propal',
'creer'))
2121 || (
getDolGlobalString(
'MAIN_USE_ADVANCED_PERMS') && $user->hasRight(
'propal',
'propal_advance',
'validate')))) {
2122 $this->error =
'ErrorPermissionDenied';
2123 dol_syslog(get_class($this).
"::valid ".$this->error, LOG_ERR);
2128 dol_syslog(get_class($this).
"::valid checkActiveProductInLines ".$this->error, LOG_INFO);
2137 $soc =
new Societe($this->db);
2138 $soc->fetch($this->socid);
2141 if (preg_match(
'/^[\(]?PROV/i', $this->
ref) || empty($this->
ref)) {
2142 $num = $this->getNextNumRef($soc);
2144 $num = (string) $this->
ref;
2148 $sql =
"UPDATE ".MAIN_DB_PREFIX.$this->table_element;
2149 $sql .=
" SET ref = '".$this->db->escape($num).
"',";
2150 $sql .=
" fk_statut = ".self::STATUS_VALIDATED.
", date_valid='".$this->db->idate($now).
"', fk_user_valid=".((int) $user->id);
2153 dol_syslog(get_class($this).
"::valid", LOG_DEBUG);
2154 $resql = $this->db->query($sql);
2156 dol_print_error($this->db);
2161 if (!$error && !$notrigger) {
2163 $result = $this->call_trigger(
'PROPAL_VALIDATE', $user);
2171 $this->oldref = $this->ref;
2174 if (preg_match(
'/^[\(]?PROV/i', $this->
ref)) {
2176 $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).
"'";
2177 $sql .=
" WHERE filename LIKE '".$this->db->escape($this->
ref).
"%' AND filepath = 'propale/".$this->db->escape($this->
ref).
"' and entity = ".((int)
$conf->entity);
2178 $resql = $this->db->query($sql);
2181 $this->error = $this->db->lasterror();
2183 $sql =
'UPDATE '.MAIN_DB_PREFIX.
"ecm_files set filepath = 'propale/".$this->db->escape($this->newref).
"'";
2184 $sql .=
" WHERE filepath = 'propale/".$this->db->escape($this->
ref).
"' and entity = ".((int)
$conf->entity);
2185 $resql = $this->db->query($sql);
2188 $this->error = $this->db->lasterror();
2194 $dirsource =
$conf->propal->multidir_output[$this->entity].
'/'.$oldref;
2195 $dirdest =
$conf->propal->multidir_output[$this->entity].
'/'.$newref;
2196 if (!$error && file_exists($dirsource)) {
2197 dol_syslog(get_class($this).
"::validate rename dir ".$dirsource.
" into ".$dirdest);
2198 if (@rename($dirsource, $dirdest)) {
2201 $listoffiles =
dol_dir_list($dirdest,
'files', 1,
'^'.preg_quote($oldref,
'/'));
2202 foreach ($listoffiles as $fileentry) {
2203 $dirsource = $fileentry[
'name'];
2204 $dirdest = preg_replace(
'/^'.preg_quote($oldref,
'/').
'/', $newref, $dirsource);
2205 $dirsource = $fileentry[
'path'].
'/'.$dirsource;
2206 $dirdest = $fileentry[
'path'].
'/'.$dirdest;
2207 @rename($dirsource, $dirdest);
2216 $this->user_validation_id = $user->id;
2217 $this->datev = $now;
2218 $this->date_validation = $now;
2220 $this->db->commit();
2223 $this->db->rollback();
2242 $this->error =
'ErrorBadParameter';
2243 dol_syslog(get_class($this).
"::set_date ".$this->error, LOG_ERR);
2247 if ($user->hasRight(
'propal',
'creer')) {
2252 $sql =
"UPDATE ".MAIN_DB_PREFIX.$this->table_element;
2253 $sql .=
" SET datep = '".$this->db->idate($date).
"'";
2254 $sql .=
" WHERE rowid = ".((int) $this->
id);
2257 $resql = $this->db->query($sql);
2259 $this->errors[] = $this->db->error();
2264 $this->oldcopy = clone $this;
2265 $this->
date = $date;
2266 $this->datep = $date;
2269 if (!$notrigger && empty($error)) {
2271 $result = $this->call_trigger(
'PROPAL_MODIFY', $user);
2279 $this->db->commit();
2282 foreach ($this->errors as $errmsg) {
2283 dol_syslog(__METHOD__.
' Error: '.$errmsg, LOG_ERR);
2284 $this->error .= ($this->error ?
', '.$errmsg : $errmsg);
2286 $this->db->rollback();
2306 if ($user->hasRight(
'propal',
'creer')) {
2311 $sql =
"UPDATE ".MAIN_DB_PREFIX.$this->table_element;
2312 $sql .=
" SET fin_validite = ".($date_end_validity !=
'' ?
"'".$this->db->idate($date_end_validity).
"'" :
'null');
2313 $sql .=
" WHERE rowid = ".((int) $this->
id);
2317 $resql = $this->db->query($sql);
2319 $this->errors[] = $this->db->error();
2325 $this->oldcopy = clone $this;
2326 $this->fin_validite = $date_end_validity;
2329 if (!$notrigger && empty($error)) {
2331 $result = $this->call_trigger(
'PROPAL_MODIFY', $user);
2339 $this->db->commit();
2342 foreach ($this->errors as $errmsg) {
2343 dol_syslog(__METHOD__.
' Error: '.$errmsg, LOG_ERR);
2344 $this->error .= ($this->error ?
', '.$errmsg : $errmsg);
2346 $this->db->rollback();
2380 if ($user->hasRight(
'propal',
'creer')) {
2385 $sql =
"UPDATE ".MAIN_DB_PREFIX.$this->table_element;
2386 $sql .=
" SET date_livraison = ".(isDolTms($delivery_date) ?
"'".$this->db->idate($delivery_date).
"'" :
'null');
2387 $sql .=
" WHERE rowid = ".((int) $this->
id);
2390 $resql = $this->db->query($sql);
2392 $this->errors[] = $this->db->error();
2397 $this->oldcopy = clone $this;
2398 $this->delivery_date = $delivery_date;
2401 if (!$notrigger && empty($error)) {
2403 $result = $this->call_trigger(
'PROPAL_MODIFY', $user);
2411 $this->db->commit();
2414 foreach ($this->errors as $errmsg) {
2415 dol_syslog(__METHOD__.
' Error: '.$errmsg, LOG_ERR);
2416 $this->error .= ($this->error ?
', '.$errmsg : $errmsg);
2418 $this->db->rollback();
2438 if ($this->
status >= self::STATUS_DRAFT) {
2443 $sql =
"UPDATE ".MAIN_DB_PREFIX.$this->table_element;
2444 $sql .=
" SET fk_availability = ".((int) ($id > 0 ? ((
int) $id) : 0));
2445 $sql .=
" WHERE rowid = ".((int) $this->
id);
2448 $resql = $this->db->query($sql);
2450 $this->errors[] = $this->db->error();
2455 $this->oldcopy = clone $this;
2456 $this->fk_availability =
$id;
2457 $this->availability_id =
$id;
2460 if (!$notrigger && empty($error)) {
2462 $result = $this->call_trigger(
'PROPAL_MODIFY', $user);
2470 $this->db->commit();
2473 foreach ($this->errors as $errmsg) {
2474 dol_syslog(__METHOD__.
' Error: '.$errmsg, LOG_ERR);
2475 $this->error .= ($this->error ?
', '.$errmsg : $errmsg);
2477 $this->db->rollback();
2481 $error_str =
'Propal status do not meet requirement '.$this->status;
2483 $this->error = $error_str;
2484 $this->errors[] = $this->error;
2501 if ($user->hasRight(
'propal',
'creer') && $this->status >= self::STATUS_DRAFT) {
2506 $sql =
"UPDATE ".MAIN_DB_PREFIX.$this->table_element;
2507 $sql .=
" SET fk_input_reason = ".((int) $id);
2508 $sql .=
" WHERE rowid = ".((int) $this->
id);
2511 $resql = $this->db->query($sql);
2513 $this->errors[] = $this->db->error();
2519 $this->oldcopy = clone $this;
2521 $this->demand_reason_id = $id;
2525 if (!$notrigger && empty($error)) {
2527 $result = $this->call_trigger(
'PROPAL_MODIFY', $user);
2535 $this->db->commit();
2538 foreach ($this->errors as $errmsg) {
2539 dol_syslog(__METHOD__.
' Error: '.$errmsg, LOG_ERR);
2540 $this->error .= ($this->error ?
', '.$errmsg : $errmsg);
2542 $this->db->rollback();
2546 $error_str =
'Propal status do not meet requirement '.$this->status;
2548 $this->error = $error_str;
2549 $this->errors[] = $this->error;
2566 if ($user->hasRight(
'propal',
'creer')) {
2571 $sql =
"UPDATE ".MAIN_DB_PREFIX.$this->table_element;
2572 $sql .=
" SET ref_client = ".(empty($ref_client) ?
'NULL' :
"'".$this->db->escape($ref_client).
"'");
2573 $sql .=
" WHERE rowid = ".((int) $this->
id);
2575 dol_syslog(__METHOD__.
' $this->id='.$this->id.
', ref_client='.$ref_client, LOG_DEBUG);
2576 $resql = $this->db->query($sql);
2578 $this->errors[] = $this->db->error();
2583 $this->oldcopy = clone $this;
2584 $this->ref_customer = $ref_client;
2585 $this->ref_client = $ref_client;
2588 if (!$notrigger && empty($error)) {
2590 $result = $this->call_trigger(
'PROPAL_MODIFY', $user);
2598 $this->db->commit();
2601 foreach ($this->errors as $errmsg) {
2602 dol_syslog(__METHOD__.
' Error: '.$errmsg, LOG_ERR);
2603 $this->error .= ($this->error ?
', '.$errmsg : $errmsg);
2605 $this->db->rollback();
2623 public function reopen($user, $status, $note =
'', $notrigger = 0)
2627 $sql =
"UPDATE ".MAIN_DB_PREFIX.$this->table_element;
2628 $sql .=
" SET fk_statut = ".((int) $status).
",";
2629 if (!empty($note)) {
2630 $sql .=
" note_private = '".$this->db->escape($note).
"',";
2632 $sql .=
" date_cloture=NULL, fk_user_cloture=NULL";
2633 $sql .=
" WHERE rowid = ".((int) $this->
id);
2637 dol_syslog(get_class($this).
"::reopen", LOG_DEBUG);
2638 $resql = $this->db->query($sql);
2641 $this->errors[] =
"Error ".$this->db->lasterror();
2646 $result = $this->call_trigger(
'PROPAL_REOPEN', $user);
2656 if (!empty($this->errors)) {
2657 foreach ($this->errors as $errmsg) {
2658 dol_syslog(get_class($this).
"::update ".$errmsg, LOG_ERR);
2659 $this->error .= ($this->error ?
', '.$errmsg : $errmsg);
2662 $this->db->rollback();
2665 $this->statut = $status;
2668 $this->db->commit();
2683 public function closeProposal($user, $status, $note_private =
'', $notrigger = 0, $note_public =
'')
2685 global $langs,
$conf;
2692 $newprivatenote =
dol_concatdesc($this->note_private, $note_private);
2693 $newpublicnote =
dol_concatdesc($this->note_public, $note_public);
2696 $date_signature = $now;
2697 $fk_user_signature = $user->id;
2699 $this->
info($this->
id);
2700 if (!isset($this->date_signature) || $this->date_signature ==
'') {
2701 $date_signature = $now;
2702 $fk_user_signature = $user->id;
2704 $date_signature = $this->date_signature;
2705 $fk_user_signature = $this->user_signature->id;
2709 $sql =
"UPDATE ".MAIN_DB_PREFIX.$this->table_element;
2710 $sql .=
" SET fk_statut = ".((int) $status).
", note_private = '".$this->db->escape($newprivatenote).
"', note_public = '".$this->db->escape($newpublicnote).
"'";
2711 if ($status == self::STATUS_SIGNED) {
2712 $sql .=
", date_signature='".$this->db->idate($now).
"', fk_user_signature = ".((int) $fk_user_signature);
2714 $sql .=
" WHERE rowid = ".((int) $this->
id);
2716 $resql = $this->db->query($sql);
2720 $triggerName =
'PROPAL_CLOSE_REFUSED';
2722 if ($status == self::STATUS_SIGNED) {
2723 $triggerName =
'PROPAL_CLOSE_SIGNED';
2727 $soc =
new Societe($this->db);
2728 $soc->id = $this->socid;
2729 $result = $soc->setAsCustomer();
2732 $this->error = $this->db->lasterror();
2733 $this->db->rollback();
2740 $outputlangs = $langs;
2743 $newlang = (
GETPOST(
'lang_id',
'aZ09') ?
GETPOST(
'lang_id',
'aZ09') : $this->thirdparty->default_lang);
2744 $outputlangs->setDefaultLang($newlang);
2753 $this->
generateDocument($modelpdf, $outputlangs, $hidedetails, $hidedesc, $hideref);
2756 $this->oldcopy = clone $this;
2757 $this->statut = $status;
2759 $this->date_signature = $date_signature;
2760 $this->note_private = $newprivatenote;
2762 if (!$notrigger && empty($error)) {
2764 $result = $this->call_trigger($triggerName, $user);
2772 $this->db->commit();
2775 foreach ($this->errors as $errmsg) {
2776 dol_syslog(__METHOD__.
' Error: '.$errmsg, LOG_ERR);
2777 $this->error .= ($this->error ?
', '.$errmsg : $errmsg);
2779 if (!empty($this->oldcopy)) {
2780 $this->statut = $this->oldcopy->status;
2781 $this->
status = $this->oldcopy->status;
2782 $this->date_signature = $this->oldcopy->date_signature;
2783 $this->note_private = $this->oldcopy->note_private;
2786 $this->db->rollback();
2790 $this->error = $this->db->lasterror();
2791 $this->db->rollback();
2806 global
$conf, $langs;
2813 $triggerName =
'PROPAL_CLASSIFY_BILLED';
2819 $sql =
'UPDATE '.MAIN_DB_PREFIX.$this->table_element;
2820 $sql .=
" SET fk_statut = ".self::STATUS_BILLED.
", ";
2821 $sql .=
" note_private = '".$this->db->escape($newprivatenote).
"', date_cloture='".$this->db->idate($now).
"', fk_user_cloture=".((int) $user->id);
2822 $sql .=
' WHERE rowid = '.((int) $this->
id).
' AND fk_statut = '.((int) self::STATUS_SIGNED);
2825 $resql = $this->db->query($sql);
2827 $this->errors[] = $this->db->error();
2830 $num = $this->db->affected_rows($resql);
2838 $outputlangs = $langs;
2841 $newlang = (
GETPOST(
'lang_id',
'aZ09') ?
GETPOST(
'lang_id',
'aZ09') : $this->thirdparty->default_lang);
2842 $outputlangs->setDefaultLang($newlang);
2851 $this->
generateDocument($modelpdf, $outputlangs, $hidedetails, $hidedesc, $hideref);
2854 $this->oldcopy = clone $this;
2857 $this->date_cloture = $now;
2858 $this->note_private = $newprivatenote;
2861 if (!$notrigger && empty($error)) {
2863 $result = $this->call_trigger($triggerName, $user);
2871 $this->db->commit();
2874 foreach ($this->errors as $errmsg) {
2875 dol_syslog(__METHOD__.
' Error: '.$errmsg, LOG_ERR);
2876 $this->error .= ($this->error ?
', '.$errmsg : $errmsg);
2878 $this->db->rollback();
2895 $sql =
"UPDATE ". MAIN_DB_PREFIX . $this->table_element;
2896 $sql .=
" SET fk_statut = " . self::STATUS_CANCELED .
",";
2897 $sql .=
" fk_user_modif = " . ((int) $user->id);
2898 $sql .=
" WHERE rowid = " . ((int) $this->
id);
2900 dol_syslog(get_class($this).
"::cancel", LOG_DEBUG);
2901 if ($this->db->query($sql)) {
2903 $result = $this->call_trigger(
'PROPAL_CANCEL', $user);
2912 $this->db->commit();
2915 foreach ($this->errors as $errmsg) {
2916 dol_syslog(get_class($this).
"::cancel ".$errmsg, LOG_ERR);
2917 $this->error .= ($this->error ?
', '.$errmsg : $errmsg);
2919 $this->db->rollback();
2923 $this->error = $this->db->error();
2924 $this->db->rollback();
2943 if ($this->
status <= self::STATUS_DRAFT) {
2947 dol_syslog(get_class($this).
"::setDraft", LOG_DEBUG);
2951 $sql =
"UPDATE ".MAIN_DB_PREFIX.$this->table_element;
2952 $sql .=
" SET fk_statut = ".self::STATUS_DRAFT;
2953 $sql .=
", online_sign_ip = NULL , online_sign_name = NULL";
2954 $sql .=
" WHERE rowid = ".((int) $this->
id);
2956 $resql = $this->db->query($sql);
2958 $this->errors[] = $this->db->error();
2963 $this->oldcopy = clone $this;
2966 if (!$notrigger && empty($error)) {
2968 $result = $this->call_trigger(
'PROPAL_MODIFY', $user);
2979 $this->db->commit();
2982 foreach ($this->errors as $errmsg) {
2983 dol_syslog(__METHOD__.
' Error: '.$errmsg, LOG_ERR);
2984 $this->error .= ($this->error ?
', '.$errmsg : $errmsg);
2986 $this->db->rollback();
3006 public function liste_array($shortlist = 0, $draft = 0, $notcurrentuser = 0, $socid = 0, $limit = 0, $offset = 0, $sortfield =
'p.datep', $sortorder =
'DESC')
3013 $sql =
"SELECT s.rowid, s.nom as name, s.client,";
3014 $sql .=
" p.rowid as propalid, p.fk_statut, p.total_ht, p.ref, p.remise, ";
3015 $sql .=
" p.datep as dp, p.fin_validite as datelimite";
3016 $sql .=
" FROM ".MAIN_DB_PREFIX.
"societe as s, ".MAIN_DB_PREFIX.$this->table_element.
" as p, ".MAIN_DB_PREFIX.
"c_propalst as c";
3017 $sql .=
" WHERE p.entity IN (".getEntity(
'propal').
")";
3018 $sql .=
" AND p.fk_soc = s.rowid";
3019 $sql .=
" AND p.fk_statut = c.id";
3023 if (empty($user->socid) && !$user->hasRight(
'societe',
'client',
'voir')) {
3024 $search_sale = $user->id;
3027 if ($search_sale && $search_sale !=
'-1') {
3028 if ($search_sale == -2) {
3029 $sql .=
" AND NOT EXISTS (SELECT sc.fk_soc FROM ".MAIN_DB_PREFIX.
"societe_commerciaux as sc WHERE sc.fk_soc = p.fk_soc)";
3030 } elseif ($search_sale > 0) {
3031 $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).
")";
3036 $sql .=
" AND p.fk_soc = ".((int) $socid);
3039 $sql .=
" AND p.fk_statut = ".((int) self::STATUS_DRAFT);
3041 if ($notcurrentuser > 0) {
3042 $sql .=
" AND p.fk_user_author <> ".((int) $user->id);
3044 $sql .= $this->db->order($sortfield, $sortorder);
3045 $sql .= $this->db->plimit($limit, $offset);
3047 $result = $this->db->query($sql);
3049 $num = $this->db->num_rows($result);
3053 $obj = $this->db->fetch_object($result);
3055 if ($shortlist == 1) {
3056 $ga[$obj->propalid] = $obj->ref;
3057 } elseif ($shortlist == 2) {
3058 $ga[$obj->propalid] = $obj->ref.
' ('.$obj->name.
')';
3060 $ga[$i][
'id'] = $obj->propalid;
3061 $ga[$i][
'ref'] = $obj->ref;
3062 $ga[$i][
'name'] = $obj->name;
3070 dol_print_error($this->db);
3096 $linkedInvoices = array();
3099 foreach ($this->linkedObjectsIds as $objecttype => $objectid) {
3102 foreach ($objectid as $key =>
$object) {
3104 if ($objecttype ==
'facture') {
3109 foreach ($this->linkedObjectsIds as $subobjecttype => $subobjectid) {
3110 foreach ($subobjectid as $subkey => $subobject) {
3111 if ($subobjecttype ==
'facture') {
3112 $linkedInvoices[] = $subobject;
3120 if (count($linkedInvoices) > 0) {
3121 $sql =
"SELECT rowid as facid, ref, total_ht as total, datef as df, fk_user_author, fk_statut, paye";
3122 $sql .=
" FROM ".MAIN_DB_PREFIX.
"facture";
3123 $sql .=
" WHERE rowid IN (".$this->db->sanitize(implode(
',', $linkedInvoices)).
")";
3125 dol_syslog(get_class($this).
"::InvoiceArrayList", LOG_DEBUG);
3126 $resql = $this->db->query($sql);
3129 $tab_sqlobj = array();
3130 $nump = $this->db->num_rows($resql);
3131 for ($i = 0; $i < $nump; $i++) {
3132 $obj = $this->db->fetch_object($resql);
3133 $tab_sqlobj[] = $obj;
3135 $this->db->free($resql);
3137 $nump = count($tab_sqlobj);
3141 while ($i < $nump) {
3142 $obj = array_shift($tab_sqlobj);
3165 public function delete($user, $notrigger = 0)
3168 require_once DOL_DOCUMENT_ROOT.
'/core/lib/files.lib.php';
3176 $result = $this->call_trigger(
'PROPAL_DELETE', $user);
3185 $sql =
"DELETE FROM ".MAIN_DB_PREFIX.
"categorie_propal";
3186 $sql .=
" WHERE fk_propal = ".((int) $this->
id);
3188 $result = $this->db->query($sql);
3191 $this->error = $this->db->lasterror();
3192 $this->errors[] = $this->error;
3197 if (!$error && !empty($this->table_element_line)) {
3198 $tabletodelete = $this->table_element_line;
3199 $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).
")";
3200 $sql =
"DELETE FROM ".MAIN_DB_PREFIX.$tabletodelete.
" WHERE ".$this->fk_element.
" = ".((int) $this->
id);
3201 if (!$this->db->query($sqlef) || !$this->db->query($sql)) {
3203 $this->error = $this->db->lasterror();
3204 $this->errors[] = $this->error;
3205 dol_syslog(get_class($this).
"::delete error ".$this->error, LOG_ERR);
3230 dol_syslog(get_class($this).
"::delete error ".$this->error, LOG_ERR);
3236 $sql =
"DELETE FROM ".MAIN_DB_PREFIX.$this->table_element.
" WHERE rowid = ".((int) $this->
id);
3237 $res = $this->db->query($sql);
3240 $this->error = $this->db->lasterror();
3241 $this->errors[] = $this->error;
3242 dol_syslog(get_class($this).
"::delete error ".$this->error, LOG_ERR);
3258 if ($conf->propal->multidir_output[$this->entity] && !empty($this->
ref)) {
3259 $dir =
$conf->propal->multidir_output[$this->entity].
"/".$ref;
3260 $file = $dir.
"/".$ref.
".pdf";
3261 if (file_exists($file)) {
3265 $this->error =
'ErrorFailToDeleteFile';
3266 $this->errors[] = $this->error;
3267 $this->db->rollback();
3271 if (file_exists($dir)) {
3274 $this->error =
'ErrorFailToDeleteDir';
3275 $this->errors[] = $this->error;
3276 $this->db->rollback();
3284 dol_syslog(get_class($this).
"::delete ".$this->
id.
" by ".$user->id, LOG_DEBUG);
3285 $this->db->commit();
3288 $this->db->rollback();
3305 if ($this->
status >= self::STATUS_DRAFT) {
3310 $sql =
'UPDATE '.MAIN_DB_PREFIX.$this->table_element;
3311 $sql .=
' SET fk_availability = '.((int) $availability_id);
3312 $sql .=
' WHERE rowid='.((int) $this->
id);
3314 dol_syslog(__METHOD__.
' availability('.$availability_id.
')', LOG_DEBUG);
3315 $resql = $this->db->query($sql);
3317 $this->errors[] = $this->db->error();
3322 $this->oldcopy = clone $this;
3323 $this->availability_id = $availability_id;
3326 if (!$notrigger && empty($error)) {
3328 $result = $this->call_trigger(
'PROPAL_MODIFY', $user);
3336 $this->db->commit();
3339 foreach ($this->errors as $errmsg) {
3340 dol_syslog(__METHOD__.
' Error: '.$errmsg, LOG_ERR);
3341 $this->error .= ($this->error ?
', '.$errmsg : $errmsg);
3343 $this->db->rollback();
3347 $error_str =
'Propal status do not meet requirement '.$this->status;
3349 $this->error = $error_str;
3350 $this->errors[] = $this->error;
3369 if ($this->
status >= self::STATUS_DRAFT) {
3374 $sql =
'UPDATE '.MAIN_DB_PREFIX.$this->table_element;
3375 $sql .=
' SET fk_input_reason = '.((int) $demand_reason_id);
3376 $sql .=
' WHERE rowid='.((int) $this->
id);
3378 dol_syslog(__METHOD__.
' demand_reason('.$demand_reason_id.
')', LOG_DEBUG);
3379 $resql = $this->db->query($sql);
3381 $this->errors[] = $this->db->error();
3386 $this->oldcopy = clone $this;
3387 $this->demand_reason_id = $demand_reason_id;
3390 if (!$notrigger && empty($error)) {
3392 $result = $this->call_trigger(
'PROPAL_MODIFY', $user);
3400 $this->db->commit();
3403 foreach ($this->errors as $errmsg) {
3404 dol_syslog(__METHOD__.
' Error: '.$errmsg, LOG_ERR);
3405 $this->error .= ($this->error ?
', '.$errmsg : $errmsg);
3407 $this->db->rollback();
3411 $error_str =
'Propal status do not meet requirement '.$this->status;
3413 $this->error = $error_str;
3414 $this->errors[] = $this->error;
3428 $sql =
"SELECT c.rowid, ";
3429 $sql .=
" c.datec, c.date_valid as datev, c.date_signature, c.date_cloture,";
3430 $sql .=
" c.fk_user_author, c.fk_user_valid, c.fk_user_signature, c.fk_user_cloture";
3431 $sql .=
" FROM ".MAIN_DB_PREFIX.$this->table_element.
" as c";
3432 $sql .=
" WHERE c.rowid = ".((int) $id);
3434 $result = $this->db->query($sql);
3437 if ($this->db->num_rows($result)) {
3438 $obj = $this->db->fetch_object($result);
3440 $this->
id = $obj->rowid;
3442 $this->date_creation = $this->db->jdate($obj->datec);
3443 $this->date_validation = $this->db->jdate($obj->datev);
3444 $this->date_signature = $this->db->jdate($obj->date_signature);
3445 $this->date_cloture = $this->db->jdate($obj->date_cloture);
3447 $this->user_creation_id = $obj->fk_user_author;
3448 $this->user_validation_id = $obj->fk_user_valid;
3450 if ($obj->fk_user_signature) {
3451 $user_signature =
new User($this->db);
3452 $user_signature->fetch($obj->fk_user_signature);
3453 $this->user_signature = $user_signature;
3456 $this->user_closing_id = $obj->fk_user_cloture;
3458 $this->db->free($result);
3460 dol_print_error($this->db);
3487 global $hookmanager;
3490 if (empty($this->labelStatus) || empty($this->labelStatusShort)) {
3492 $langs->load(
"propal");
3493 $this->labelStatus[-1] = $langs->transnoentitiesnoconv(
"PropalStatusCanceled");
3494 $this->labelStatus[0] = $langs->transnoentitiesnoconv(
"PropalStatusDraft");
3495 $this->labelStatus[1] = $langs->transnoentitiesnoconv(
"PropalStatusValidated");
3496 $this->labelStatus[2] = $langs->transnoentitiesnoconv(
"PropalStatusSigned");
3497 $this->labelStatus[3] = $langs->transnoentitiesnoconv(
"PropalStatusNotSigned");
3498 $this->labelStatus[4] = $langs->transnoentitiesnoconv(
"PropalStatusBilled");
3499 $this->labelStatusShort[-1] = $langs->transnoentitiesnoconv(
"PropalStatusCanceledShort");
3500 $this->labelStatusShort[0] = $langs->transnoentitiesnoconv(
"PropalStatusDraftShort");
3501 $this->labelStatusShort[1] = $langs->transnoentitiesnoconv(
"PropalStatusValidatedShort");
3502 $this->labelStatusShort[2] = $langs->transnoentitiesnoconv(
"PropalStatusSignedShort");
3503 $this->labelStatusShort[3] = $langs->transnoentitiesnoconv(
"PropalStatusNotSignedShort");
3504 $this->labelStatusShort[4] = $langs->transnoentitiesnoconv(
"PropalStatusBilledShort");
3508 if ($status == self::STATUS_CANCELED) {
3509 $statusType =
'status9';
3510 } elseif ($status == self::STATUS_DRAFT) {
3511 $statusType =
'status0';
3512 } elseif ($status == self::STATUS_VALIDATED) {
3513 $statusType =
'status1';
3514 } elseif ($status == self::STATUS_SIGNED) {
3515 $statusType =
'status4';
3516 } elseif ($status == self::STATUS_NOTSIGNED) {
3517 $statusType =
'status9';
3518 } elseif ($status == self::STATUS_BILLED) {
3519 $statusType =
'status6';
3522 $parameters = array(
'status' => $status,
'mode' => $mode);
3523 $reshook = $hookmanager->executeHooks(
'LibStatut', $parameters, $this);
3526 return $hookmanager->resPrint;
3529 return dolGetStatus($this->labelStatus[$status], $this->labelStatusShort[$status],
'', $statusType, $mode);
3544 global $langs, $hookmanager;
3548 if ($mode ==
'opened') {
3551 if ($mode ==
'signed') {
3558 $sql =
"SELECT COUNT(p.rowid) as nb, SUM(p.total_ht) as total,";
3559 if ($mode ==
'opened') {
3560 $sql .=
" SUM(CASE WHEN p.fin_validite IS NULL OR p.fin_validite < '".$this->db->idate($now - $delay_warning).
"' THEN 1 ELSE 0 END) as nblate";
3562 $sql .=
" 0 as nblate";
3564 if (empty($user->socid) && !$user->hasRight(
'societe',
'client',
'voir')) {
3565 $sql .=
" FROM ".MAIN_DB_PREFIX.$this->table_element.
" as p";
3566 $sql .=
" LEFT JOIN ".MAIN_DB_PREFIX.
"societe_commerciaux as sc ON p.fk_soc = sc.fk_soc";
3568 $sql .=
" FROM ".MAIN_DB_PREFIX.
"propal as p";
3570 $sql .=
" WHERE p.entity IN (".getEntity(
'propal').
")";
3571 if ($mode ==
'opened') {
3572 $sql .=
" AND p.fk_statut = ".self::STATUS_VALIDATED;
3574 if ($mode ==
'signed') {
3575 $sql .=
" AND p.fk_statut = ".self::STATUS_SIGNED;
3578 if (empty($user->socid) && !$user->hasRight(
'societe',
'client',
'voir')) {
3579 $sql .=
" AND sc.fk_user = ".((int) $user->id);
3582 $sql .=
" AND p.fk_soc = ".((int) $user->socid);
3587 if (empty($user->socid) && !$user->hasRight(
'societe',
'client',
'voir')) {
3588 $search_sale = $user->id;
3591 if ($search_sale && $search_sale !=
'-1') {
3592 if ($search_sale == -2) {
3593 $sql .=
" AND NOT EXISTS (SELECT sc.fk_soc FROM ".MAIN_DB_PREFIX.
"societe_commerciaux as sc WHERE sc.fk_soc = p.fk_soc)";
3594 } elseif ($search_sale > 0) {
3595 $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).
")";
3599 $sql .=
" AND p.fk_soc = ".((int) $user->socid);
3602 $parameters = array(
'socid' => $user->socid);
3603 $reshook = $hookmanager->executeHooks(
'printFieldListWhere', $parameters, $this);
3604 $sql .= $hookmanager->resPrint;
3606 $resql = $this->db->query($sql);
3608 $langs->load(
"propal");
3611 $label = $labelShort =
'';
3612 if ($mode ==
'opened') {
3614 $label = $langs->transnoentitiesnoconv(
"PropalsToClose");
3615 $labelShort = $langs->transnoentitiesnoconv(
"ToAcceptRefuse");
3617 if ($mode ==
'signed') {
3619 $label = $langs->trans(
"PropalsToBill");
3620 $labelShort = $langs->trans(
"ToBill");
3624 $response->warning_delay = $delay_warning / 60 / 60 / 24;
3625 $response->label = $label;
3626 $response->labelShort = $labelShort;
3627 $response->url =
dolBuildUrl(DOL_URL_ROOT.
'/comm/propal/list.php', [
'search_status' => $status,
'mainmenu' =>
'commercial',
'leftmenu' =>
'propals']);
3628 $response->url_late =
dolBuildUrl(DOL_URL_ROOT.
'/comm/propal/list.php', [
'search_option' =>
'late',
'mainmenu' =>
'commercial',
'leftmenu' =>
'propals',
'sortfield' =>
'p.datep',
'sortorder' =>
'asc']);
3629 $response->img = img_object(
'',
"propal");
3633 $obj = $this->db->fetch_object($resql);
3635 $response->nbtodo = (int) $obj->nb;
3636 $response->total = (float) $obj->total;
3637 $response->nbtodolate = (int) $obj->nblate;
3642 $this->error = $this->db->error();
3658 global
$conf, $langs;
3663 $sql =
"SELECT rowid";
3664 $sql .=
" FROM ".MAIN_DB_PREFIX.
"product";
3665 $sql .=
" WHERE entity IN (".getEntity(
'product').
")";
3666 if (array_key_exists(
'tosell', $param)) {
3667 $sql .=
" AND tosell = ".((int) $param[
'tosell']);
3669 $sql .= $this->db->plimit(100);
3671 $resql = $this->db->query($sql);
3673 $num_prods = $this->db->num_rows($resql);
3675 while ($i < $num_prods) {
3677 $row = $this->db->fetch_row($resql);
3678 $prodids[$i] = $row[0];
3684 $this->
ref =
'SPECIMEN';
3685 $this->ref_customer =
'NEMICEPS';
3686 $this->ref_client =
'NEMICEPS';
3687 $this->specimen = 1;
3690 $this->fin_validite = $this->
date + 3600 * 24 * 30;
3691 $this->cond_reglement_id = 1;
3692 $this->cond_reglement_code =
'RECEP';
3693 $this->mode_reglement_id = 7;
3694 $this->mode_reglement_code =
'CHQ';
3695 $this->availability_id = 1;
3696 $this->availability_code =
'AV_NOW';
3697 $this->demand_reason_id = 1;
3698 $this->demand_reason_code =
'SRC_00';
3699 $this->note_public =
'This is a comment (public)';
3700 $this->note_private =
'This is a comment (private)';
3702 $this->multicurrency_tx = 1;
3708 while ($xnbp < $nbp) {
3710 $line->desc = $langs->trans(
"Description").
" ".$xnbp;
3712 $line->subprice = 100;
3714 $line->localtax1_tx = 0;
3715 $line->localtax2_tx = 0;
3717 $line->total_ht = 50;
3718 $line->total_ttc = 60;
3719 $line->total_tva = 10;
3720 $line->remise_percent = 50;
3722 $line->total_ht = 100;
3723 $line->total_ttc = 120;
3724 $line->total_tva = 20;
3725 $line->remise_percent = 00;
3728 if ($num_prods > 0) {
3729 $prodid = mt_rand(1, $num_prods);
3730 $line->fk_product = $prodids[$prodid];
3731 $line->product_ref =
'SPECIMEN';
3734 $this->lines[$xnbp] = $line;
3736 $this->total_ht += $line->total_ht;
3737 $this->total_tva += $line->total_tva;
3738 $this->total_ttc += $line->total_ttc;
3753 global $user, $hookmanager;
3755 $this->nb = array();
3757 $sql =
"SELECT count(p.rowid) as nb";
3758 $sql .=
" FROM ".MAIN_DB_PREFIX.$this->table_element.
" as p";
3759 $sql .=
" LEFT JOIN ".MAIN_DB_PREFIX.
"societe as s ON p.fk_soc = s.rowid";
3760 $sql .=
" WHERE p.entity IN (".getEntity(
'propal').
")";
3764 if (empty($user->socid) && !$user->hasRight(
'societe',
'client',
'voir')) {
3765 $search_sale = $user->id;
3768 if ($search_sale && $search_sale !=
'-1') {
3769 if ($search_sale == -2) {
3770 $sql .=
" AND NOT EXISTS (SELECT sc.fk_soc FROM ".MAIN_DB_PREFIX.
"societe_commerciaux as sc WHERE sc.fk_soc = p.fk_soc)";
3771 } elseif ($search_sale > 0) {
3772 $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).
")";
3777 $parameters = array();
3778 $hookmanager->executeHooks(
'printFieldListWhere', $parameters, $this);
3779 $sql .= $hookmanager->resPrint;
3780 $resql = $this->db->query($sql);
3783 while ($obj = $this->db->fetch_object($resql)) {
3784 $this->nb[
"proposals"] = $obj->nb;
3786 $this->db->free($resql);
3789 dol_print_error($this->db);
3790 $this->error = $this->db->error();
3803 public function getNextNumRef($soc)
3805 global
$conf, $langs;
3806 $langs->load(
"propal");
3810 if (!empty($classname)) {
3813 $file = $classname.
".php";
3816 $dirmodels = array_merge(array(
'/'), (array)
$conf->modules_parts[
'models']);
3817 foreach ($dirmodels as $reldir) {
3821 $mybool = ((bool) @include_once $dir.$file) || $mybool;
3825 dol_print_error(
null,
"Failed to include file ".$file);
3829 $obj =
new $classname();
3830 '@phan-var-force ModeleNumRefPropales $obj';
3833 $numref = $obj->getNextValue($soc, $this);
3835 if ($numref !=
"") {
3838 $this->error = $obj->error;
3843 $langs->load(
"errors");
3844 print $langs->trans(
"Error").
" ".$langs->trans(
"ErrorModuleSetupNotComplete", $langs->transnoentitiesnoconv(
"Proposal"));
3857 global
$conf, $langs, $user;
3859 $langs->load(
'propal');
3861 $nofetch = !empty($params[
'nofetch']);
3864 return [
'optimize' => $langs->trans(
"Proposal")];
3866 if ($user->hasRight(
'propal',
'lire')) {
3867 $datas[
'picto'] = img_picto(
'', $this->picto,
'', 0, 0, 0,
'',
'paddingrightonly').
'<u>'.$langs->trans(
"Proposal").
'</u>';
3868 if (isset($this->
status)) {
3869 $datas[
'status'] =
' '.$this->getLibStatut(5);
3871 if (!empty($this->
ref)) {
3872 $datas[
'ref'] =
'<br><b>'.$langs->trans(
'Ref').
':</b> '.$this->ref;
3875 $langs->load(
'companies');
3876 if (empty($this->thirdparty)) {
3879 $datas[
'customer'] =
'<br><b>'.$langs->trans(
'Customer').
':</b> '.$this->thirdparty->getNomUrl(1,
'', 0, 1);
3881 if (!empty($this->ref_customer)) {
3882 $datas[
'refcustomer'] =
'<br><b>'.$langs->trans(
'RefCustomer').
':</b> '.$this->ref_customer;
3885 $langs->load(
'project');
3886 if (is_null($this->project) || (is_object($this->project) && empty($this->project->id))) {
3888 if ($res > 0 && $this->project instanceof
Project) {
3889 $datas[
'project'] =
'<br><b>'.$langs->trans(
'Project').
':</b> '.$this->project->getNomUrl(1,
'', 0,
'1');
3893 if (!empty($this->total_ht)) {
3894 $datas[
'amountht'] =
'<br><b>'.$langs->trans(
'AmountHT').
':</b> '.
price($this->total_ht, 0, $langs, 0, -1, -1,
$conf->currency);
3896 if (!empty($this->total_tva)) {
3897 $datas[
'vat'] =
'<br><b>'.$langs->trans(
'VAT').
':</b> '.
price($this->total_tva, 0, $langs, 0, -1, -1,
$conf->currency);
3899 if (!empty($this->total_ttc)) {
3900 $datas[
'amountttc'] =
'<br><b>'.$langs->trans(
'AmountTTC').
':</b> '.
price($this->total_ttc, 0, $langs, 0, -1, -1,
$conf->currency);
3902 if (!empty($this->
date)) {
3903 $datas[
'date'] =
'<br><b>'.$langs->trans(
'Date').
':</b> '.
dol_print_date($this->
date,
'day');
3905 if (!empty($this->date_signature)) {
3906 $datas[
'datesignature'] =
'<br><b>'.$langs->trans(
'DateSigning').
':</b> '.
dol_print_date($this->date_signature,
'day');
3908 if (!empty($this->delivery_date)) {
3909 $datas[
'deliverydate'] =
'<br><b>'.$langs->trans(
'DeliveryDate').
':</b> '.
dol_print_date($this->delivery_date,
'dayhour');
3927 public function getNomUrl($withpicto = 0, $option =
'', $get_params =
'', $notooltip = 0, $save_lastsearch_value = -1, $addlinktonotes = -1)
3929 global $langs,
$conf, $user, $hookmanager;
3931 if (!empty(
$conf->dol_no_mouse_hover)) {
3938 'objecttype' => $this->element,
3939 'option' => $option,
3942 $classfortooltip =
'classfortooltip';
3945 $classfortooltip =
'classforajaxtooltip';
3946 $dataparams =
' data-params="'.dol_escape_htmltag(json_encode($params)).
'"';
3954 if ($user->hasRight(
'propal',
'lire')) {
3955 parse_str($get_params, $query);
3956 $query = array_merge($query, [
'id' => $this->
id]);
3957 if ($option ==
'') {
3958 $baseurl = DOL_URL_ROOT .
'/comm/propal/card.php';
3959 } elseif ($option ==
'compta') {
3960 $baseurl = DOL_URL_ROOT .
'/comm/propal/card.php';
3961 } elseif ($option ==
'expedition') {
3962 $baseurl = DOL_URL_ROOT .
'/expedition/propal.php';
3963 } elseif ($option ==
'document') {
3964 $baseurl = DOL_URL_ROOT .
'/comm/propal/document.php';
3967 if ($option !=
'nolink') {
3969 $add_save_lastsearch_values = ($save_lastsearch_value == 1 ? 1 : 0);
3970 if ($save_lastsearch_value == -1 && isset($_SERVER[
"PHP_SELF"]) && preg_match(
'/list\.php/', $_SERVER[
"PHP_SELF"])) {
3971 $add_save_lastsearch_values = 1;
3973 if ($add_save_lastsearch_values) {
3974 $query = array_merge($query, [
'save_lastsearch_values' => 1]);
3981 if (empty($notooltip) && $user->hasRight(
'propal',
'lire')) {
3983 $label = $langs->trans(
"Proposal");
3984 $linkclose .=
' alt="'.dolPrintHTMLForAttribute($label).
'"';
3986 $linkclose .= ($label ?
' title="'.dolPrintHTMLForAttribute($label).
'"' :
' title="tocomplete"');
3987 $linkclose .= $dataparams.
' class="'.$classfortooltip.
'"';
3990 $linkstart =
'<a href="'.$url.
'"';
3991 $linkstart .= $linkclose.
'>';
3994 $result .= $linkstart;
3996 $result .= img_object(($notooltip ?
'' : $label), ($this->picto ? $this->picto :
'generic'), (($withpicto != 2) ?
'class="paddingright"' :
''), 0, 0, $notooltip ? 0 : 1);
3998 if ($withpicto != 2) {
3999 $result .= $this->ref;
4001 $result .= $linkend;
4003 if ($addlinktonotes >= 0) {
4006 if ($addlinktonotes == 0) {
4007 if (!empty($this->note_private) || !empty($this->note_public)) {
4008 $txttoshow = $langs->trans(
'ViewPrivateNote');
4010 } elseif ($addlinktonotes == 1) {
4011 if (!empty($this->note_private)) {
4014 } elseif ($addlinktonotes == 2) {
4015 if (!empty($this->note_public)) {
4018 } elseif ($addlinktonotes == 3) {
4019 if ($user->socid > 0) {
4020 if (!empty($this->note_public)) {
4024 if (!empty($this->note_public)) {
4027 if (!empty($this->note_private)) {
4028 if (!empty($txttoshow)) {
4029 $txttoshow .=
'<br><br>';
4037 $result .=
' <span class="note inline-block">';
4038 $result .=
'<a href="'.dolBuildUrl(DOL_URL_ROOT.
'/comm/propal/note.php', [
'id' => $this->id]).
'" class="classfortooltip" title="'.
dol_escape_htmltag($txttoshow).
'">';
4039 $result .= img_picto(
'',
'note');
4041 $result .=
'</span>';
4046 $hookmanager->initHooks(array($this->element .
'dao'));
4047 $parameters = array(
'id' => $this->
id,
'getnomurl' => &$result);
4048 $reshook = $hookmanager->executeHooks(
'getNomUrl', $parameters, $this, $action);
4050 $result = $hookmanager->resPrint;
4052 $result .= $hookmanager->resPrint;
4065 return $this->
fetch_lines(0, 0, $sqlforgedfilters);
4079 public function generateDocument($modele, $outputlangs, $hidedetails = 0, $hidedesc = 0, $hideref = 0, $moreparams =
null)
4081 $outputlangs->loadLangs(array(
"propale",
"products"));
4086 if ($this->model_pdf) {
4087 $modele = $this->model_pdf;
4091 $modelpath =
"core/modules/propale/doc/";
4093 return $this->
commonGenerateDocument($modelpath, $modele, $outputlangs, $hidedetails, $hidedesc, $hideref, $moreparams);
4141 $selected = (empty($arraydata[
'selected']) ? 0 : $arraydata[
'selected']);
4143 $return =
'<div class="box-flex-item box-flex-grow-zero">';
4144 $return .=
'<div class="info-box info-box-sm">';
4145 $return .=
'<div class="info-box-icon bg-infobox-action">';
4146 $return .= img_picto(
'', $this->picto);
4147 $return .=
'</div>';
4148 $return .=
'<div class="info-box-content">';
4149 $return .=
'<span class="info-box-ref inline-block tdoverflowmax150 valignmiddle">' . $this->
getNomUrl() .
'</span>';
4150 if ($selected >= 0) {
4151 $return .=
'<input id="cb'.$this->id.
'" class="flat checkforselect fright" type="checkbox" name="toselect[]" value="'.$this->
id.
'"'.($selected ?
' checked="checked"' :
'').
'>';
4153 if (!empty($arraydata[
'projectlink'])) {
4154 $return .=
'<span class="info-box-ref"> | '.$arraydata[
'projectlink'].
'</span>';
4157 if (is_object($this->thirdparty)) {
4158 $return .=
'<div class="info-box-ref tdoverflowmax150">'.$this->thirdparty->getNomUrl(1).
'</div>';
4160 $return .=
'<span class="info-box-label amount" title="'.$langs->trans(
"AmountHT").
'">'.
price($this->total_ht).
'</span>';
4161 if (!empty($arraydata[
'authorlink'])) {
4162 $return .=
' <span class="info-box-label">'.$arraydata[
'authorlink'].
'</span>';
4164 $return .=
'<br><div class="info-box-status">'.$this->getLibStatut(3).
'</div>';
4165 $return .=
'</div>';
4166 $return .=
'</div>';
4167 $return .=
'</div>';
4183 require_once DOL_DOCUMENT_ROOT.
'/categories/class/categorie.class.php';
4184 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.
roundQtyToPackaging($qty, $packaging)
Round a quantity up to the next multiple of a packaging quantity (options PRODUCT_USE_CUSTOMER_PACKAG...
commonGenerateDocument($modelspath, $modele, $outputlangs, $hidedetails, $hidedesc, $hideref, $moreparams=null)
Common function for all objects extending CommonObject for generating documents.
fetchProject()
Load the project with id $this->fk_project into this->project.
fetch_thirdparty($force_thirdparty_id=0)
Load the third party of object, from id $this->socid or $this->fk_soc, into this->thirdparty.
deleteObjectLinked($sourceid=null, $sourcetype='', $targetid=null, $targettype='', $rowid=0, $f_user=null, $notrigger=0)
Delete all links between an object $this.
setErrorsFromObject($object)
setErrorsFromObject
isLineOfObject($lineid)
Check that a line belongs to this object, using $this->table_element_line and $this->fk_element.
static isExistingObject($element, $id, $ref='', $ref_ext='')
Check if an object id or ref exists If you don't need or want to instantiate the object and just need...
updateRangOfLine($rowid, $rang)
Update position of line (rang)
checkActiveProductInLines($status='onsale')
Check if all products have the right status (on sale, on buy) called during validation of propal,...
deleteExtraFields()
Delete all extra fields values for the current object.
fetchObjectLinked($sourceid=null, $sourcetype='', $targetid=null, $targettype='', $clause='OR', $alsosametype=1, $orderby='sourcetype', $loadalsoobjects=1)
Fetch array of objects linked to current object (object of enabled modules only).
static commonReplaceThirdparty(DoliDB $dbs, $origin_id, $dest_id, array $tables, $ignoreerrors=0)
Function used to replace a thirdparty id with another one.
static commonReplaceProduct(DoliDB $dbs, $origin_id, $dest_id, array $tables, $ignoreerrors=0)
Function used to replace a product id with another one.
line_max($fk_parent_line=0)
Get max value used for position of line (rang)
insertExtraFields($trigger='', $userused=null)
Add/Update all extra fields values for the current object.
delete_linked_contact($source='', $code='')
Delete all links between an object $this and all its contacts in llx_element_contact.
defineBuyPrice($unitPrice=0.0, $discountPercent=0.0, $fk_product=0, $qty=0)
Get buy price to use for margin calculation.
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.
dol_escape_htmltag($stringtoescape, $keepb=0, $keepn=0, $noescapetags='', $escapeonlyhtmltags=0, $cleanalsojavascript=0)
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