44require_once DOL_DOCUMENT_ROOT.
'/core/class/commonobject.class.php';
45require_once DOL_DOCUMENT_ROOT.
'/comm/propal/class/propaleligne.class.php';
46require_once DOL_DOCUMENT_ROOT.
'/product/class/product.class.php';
47require_once DOL_DOCUMENT_ROOT.
'/margin/lib/margins.lib.php';
48require_once DOL_DOCUMENT_ROOT.
'/multicurrency/class/multicurrency.class.php';
49require_once DOL_DOCUMENT_ROOT.
'/core/class/commonincoterm.class.php';
50require_once DOL_DOCUMENT_ROOT.
'/subtotals/class/commonsubtotal.class.php';
68 public $element =
'propal';
73 public $table_element =
'propal';
78 public $table_element_line =
'propaldet';
83 public $fk_element =
'fk_propal';
88 public $picto =
'propal';
94 public $TRIGGER_PREFIX =
'PROPAL';
100 public $restrictiononfksoc = 1;
131 public $ref_customer;
165 public $date_validation;
170 public $date_signature;
175 public $user_signature;
192 public $delivery_date;
198 public $fin_validite;
203 public $user_author_id;
234 public $cond_reglement_code;
239 public $cond_reglement;
244 public $cond_reglement_doc;
249 public $mode_reglement_code;
254 public $mode_reglement;
261 public $deposit_percent;
273 public $address_type;
284 public $availability_id;
291 public $fk_availability;
296 public $availability_code;
301 public $availability;
306 public $duree_validite;
311 public $demand_reason_id;
316 public $demand_reason_code;
321 public $demand_reason;
326 public $warehouse_id;
331 public $lines = array();
338 public $labelStatus = array();
339 public $labelStatusShort = array();
370 public $fields = array(
371 'rowid' => array(
'type' =>
'integer',
'label' =>
'TechnicalID',
'enabled' => 1,
'visible' => -1,
'notnull' => 1,
'position' => 10),
372 'entity' => array(
'type' =>
'integer',
'label' =>
'Entity',
'default' =>
'1',
'enabled' => 1,
'visible' => -2,
'notnull' => 1,
'position' => 15,
'index' => 1),
373 'ref' => array(
'type' =>
'varchar(30)',
'label' =>
'Ref',
'enabled' => 1,
'visible' => -1,
'notnull' => 1,
'showoncombobox' => 1,
'position' => 20),
374 'ref_client' => array(
'type' =>
'varchar(255)',
'label' =>
'RefCustomer',
'enabled' => 1,
'visible' => -1,
'position' => 22),
375 'ref_ext' => array(
'type' =>
'varchar(255)',
'label' =>
'RefExt',
'enabled' => 1,
'visible' => 0,
'position' => 40),
376 'fk_soc' => array(
'type' =>
'integer:Societe:societe/class/societe.class.php',
'label' =>
'ThirdParty',
'enabled' =>
'isModEnabled("societe")',
'visible' => -1,
'position' => 23),
377 'fk_projet' => array(
'type' =>
'integer:Project:projet/class/project.class.php:1:(fk_statut:=:1)',
'label' =>
'Fk projet',
'enabled' =>
"isModEnabled('project')",
'visible' => -1,
'position' => 24),
378 'tms' => array(
'type' =>
'timestamp',
'label' =>
'DateModification',
'enabled' => 1,
'visible' => -1,
'notnull' => 1,
'position' => 25),
379 'datec' => array(
'type' =>
'datetime',
'label' =>
'DateCreation',
'enabled' => 1,
'visible' => -1,
'position' => 55),
380 'datep' => array(
'type' =>
'date',
'label' =>
'Date',
'enabled' => 1,
'visible' => -1,
'position' => 60),
381 'fin_validite' => array(
'type' =>
'datetime',
'label' =>
'DateEnd',
'enabled' => 1,
'visible' => -1,
'position' => 65),
382 'date_valid' => array(
'type' =>
'datetime',
'label' =>
'DateValidation',
'enabled' => 1,
'visible' => -1,
'position' => 70),
383 'date_cloture' => array(
'type' =>
'datetime',
'label' =>
'DateClosing',
'enabled' => 1,
'visible' => -1,
'position' => 75),
384 'fk_user_author' => array(
'type' =>
'integer:User:user/class/user.class.php',
'label' =>
'UserAuthor',
'enabled' => 1,
'visible' => -1,
'position' => 80),
385 'fk_user_modif' => array(
'type' =>
'integer:User:user/class/user.class.php',
'label' =>
'UserModif',
'enabled' => 1,
'visible' => -2,
'notnull' => -1,
'position' => 85),
386 'fk_user_valid' => array(
'type' =>
'integer:User:user/class/user.class.php',
'label' =>
'UserValidation',
'enabled' => 1,
'visible' => -1,
'position' => 90),
387 'fk_user_cloture' => array(
'type' =>
'integer:User:user/class/user.class.php',
'label' =>
'UserClosing',
'enabled' => 1,
'visible' => -1,
'position' => 95),
388 'price' => array(
'type' =>
'double',
'label' =>
'Price',
'enabled' => 1,
'visible' => -1,
'position' => 105),
389 'total_ht' => array(
'type' =>
'double(24,8)',
'label' =>
'TotalHT',
'enabled' => 1,
'visible' => -1,
'position' => 125,
'isameasure' => 1),
390 'total_tva' => array(
'type' =>
'double(24,8)',
'label' =>
'VAT',
'enabled' => 1,
'visible' => -1,
'position' => 130,
'isameasure' => 1),
391 'localtax1' => array(
'type' =>
'double(24,8)',
'label' =>
'LocalTax1',
'enabled' => 1,
'visible' => -1,
'position' => 135,
'isameasure' => 1),
392 'localtax2' => array(
'type' =>
'double(24,8)',
'label' =>
'LocalTax2',
'enabled' => 1,
'visible' => -1,
'position' => 140,
'isameasure' => 1),
393 'total_ttc' => array(
'type' =>
'double(24,8)',
'label' =>
'TotalTTC',
'enabled' => 1,
'visible' => -1,
'position' => 145,
'isameasure' => 1),
394 'fk_account' => array(
'type' =>
'integer',
'label' =>
'BankAccount',
'enabled' =>
'isModEnabled("bank")',
'visible' => -1,
'position' => 150),
395 'fk_currency' => array(
'type' =>
'varchar(3)',
'label' =>
'Currency',
'enabled' => 1,
'visible' => -1,
'position' => 155),
396 'fk_cond_reglement' => array(
'type' =>
'integer',
'label' =>
'PaymentTerm',
'enabled' => 1,
'visible' => -1,
'position' => 160),
397 'deposit_percent' => array(
'type' =>
'varchar(63)',
'label' =>
'DepositPercent',
'enabled' => 1,
'visible' => -1,
'position' => 161),
398 'fk_mode_reglement' => array(
'type' =>
'integer',
'label' =>
'PaymentMode',
'enabled' => 1,
'visible' => -1,
'position' => 165),
399 'note_private' => array(
'type' =>
'html',
'label' =>
'NotePrivate',
'enabled' => 1,
'visible' => 0,
'position' => 170),
400 'note_public' => array(
'type' =>
'html',
'label' =>
'NotePublic',
'enabled' => 1,
'visible' => 0,
'position' => 175),
401 'model_pdf' => array(
'type' =>
'varchar(255)',
'label' =>
'PDFTemplate',
'enabled' => 1,
'visible' => 0,
'position' => 180),
402 'date_livraison' => array(
'type' =>
'date',
'label' =>
'DateDeliveryPlanned',
'enabled' => 1,
'visible' => -1,
'position' => 185),
403 'fk_shipping_method' => array(
'type' =>
'integer',
'label' =>
'ShippingMethod',
'enabled' => 1,
'visible' => -1,
'position' => 190),
404 'fk_warehouse' => array(
'type' =>
'integer:Entrepot:product/stock/class/entrepot.class.php',
'label' =>
'Fk warehouse',
'enabled' =>
'isModEnabled("stock")',
'visible' => -1,
'position' => 191),
405 'fk_availability' => array(
'type' =>
'integer',
'label' =>
'Availability',
'enabled' => 1,
'visible' => -1,
'position' => 195),
406 'fk_delivery_address' => array(
'type' =>
'integer',
'label' =>
'DeliveryAddress',
'enabled' => 1,
'visible' => 0,
'position' => 200),
407 'fk_input_reason' => array(
'type' =>
'integer',
'label' =>
'InputReason',
'enabled' => 1,
'visible' => -1,
'position' => 205),
408 'extraparams' => array(
'type' =>
'varchar(255)',
'label' =>
'Extraparams',
'enabled' => 1,
'visible' => -1,
'position' => 215),
409 'fk_incoterms' => array(
'type' =>
'integer',
'label' =>
'IncotermCode',
'enabled' =>
'isModEnabled("incoterm")',
'visible' => -1,
'position' => 220),
410 'location_incoterms' => array(
'type' =>
'varchar(255)',
'label' =>
'IncotermLabel',
'enabled' =>
'isModEnabled("incoterm")',
'visible' => -1,
'position' => 225),
411 'fk_multicurrency' => array(
'type' =>
'integer',
'label' =>
'MulticurrencyID',
'enabled' => 1,
'visible' => -1,
'position' => 230),
412 'multicurrency_code' => array(
'type' =>
'varchar(255)',
'label' =>
'MulticurrencyCurrency',
'enabled' =>
'isModEnabled("multicurrency")',
'visible' => -1,
'position' => 235),
413 'multicurrency_tx' => array(
'type' =>
'double(24,8)',
'label' =>
'MulticurrencyRate',
'enabled' =>
'isModEnabled("multicurrency")',
'visible' => -1,
'position' => 240,
'isameasure' => 1),
414 'multicurrency_total_ht' => array(
'type' =>
'double(24,8)',
'label' =>
'MulticurrencyAmountHT',
'enabled' =>
'isModEnabled("multicurrency")',
'visible' => -1,
'position' => 245,
'isameasure' => 1),
415 'multicurrency_total_tva' => array(
'type' =>
'double(24,8)',
'label' =>
'MulticurrencyAmountVAT',
'enabled' =>
'isModEnabled("multicurrency")',
'visible' => -1,
'position' => 250,
'isameasure' => 1),
416 'multicurrency_total_ttc' => array(
'type' =>
'double(24,8)',
'label' =>
'MulticurrencyAmountTTC',
'enabled' =>
'isModEnabled("multicurrency")',
'visible' => -1,
'position' => 255,
'isameasure' => 1),
417 'last_main_doc' => array(
'type' =>
'varchar(255)',
'label' =>
'LastMainDoc',
'enabled' => 1,
'visible' => -1,
'position' => 260),
418 'fk_statut' => array(
'type' =>
'smallint(6)',
'label' =>
'Status',
'enabled' => 1,
'visible' => -1,
'notnull' => 1,
'position' => 500),
419 'import_key' => array(
'type' =>
'varchar(14)',
'label' =>
'ImportId',
'enabled' => 1,
'visible' => -2,
'position' => 900),
460 $this->ismultientitymanaged = 1;
461 $this->socid = $socid;
462 $this->
id = $propalid;
466 $this->fields[
'ref_ext'][
'visible'] =
getDolGlobalInt(
'MAIN_LIST_SHOW_REF_EXT');
482 public function add_product($idproduct, $qty, $remise_percent = 0)
491 dol_syslog(get_class($this).
"::add_product $idproduct, $qty, $remise_percent");
492 if ($idproduct > 0) {
493 $prod =
new Product($this->db);
494 $prod->fetch($idproduct);
496 $productdesc = $prod->description;
500 if (empty($tva_tx)) {
510 $price = $prod->multiprices[$this->thirdparty->price_level];
512 $price = $prod->price;
517 $line->fk_product = $idproduct;
518 $line->desc = $productdesc;
520 $line->subprice = $price;
521 $line->remise_percent = $remise_percent;
522 $line->vat_src_code = $vat_src_code;
523 $line->tva_tx = $tva_tx;
524 $line->fk_unit = $prod->fk_unit;
526 $line->info_bits = 1;
529 $this->lines[] = $line;
547 include_once DOL_DOCUMENT_ROOT.
'/core/lib/price.lib.php';
548 include_once DOL_DOCUMENT_ROOT.
'/core/class/discount.class.php';
553 $result = $remise->fetch($idremise);
556 if ($remise->fk_facture) {
557 $this->error = $langs->trans(
"ErrorDiscountAlreadyUsed");
558 $this->db->rollback();
564 $line->context = $this->context;
566 $line->fk_propal = $this->id;
567 $line->fk_remise_except = $remise->id;
568 $line->desc = $remise->description;
569 $line->vat_src_code = $remise->vat_src_code;
570 $line->tva_tx = $remise->tva_tx;
571 $line->subprice = -(float) $remise->amount_ht;
572 $line->fk_product = 0;
574 $line->remise_percent = 0;
576 $line->info_bits = 2;
578 $line->total_ht = -(float) $remise->amount_ht;
579 $line->total_tva = -(float) $remise->amount_tva;
580 $line->total_ttc = -(float) $remise->amount_ttc;
582 $result = $line->insert();
589 $this->db->rollback();
594 $this->db->rollback();
598 $this->db->rollback();
648 $remise_percent = 0.0,
649 $price_base_type =
'HT',
661 $array_options = array(),
666 $fk_remise_except = 0,
667 $noupdateafterinsertline = 0
671 dol_syslog(get_class($this).
"::addline propalid=$this->id, desc=$desc, pu_ht=$pu_ht, qty=$qty, txtva=$txtva, fk_product=$fk_product, remise_except=$remise_percent, price_base_type=$price_base_type, pu_ttc=$pu_ttc, info_bits=$info_bits, type=$type, fk_remise_except=".$fk_remise_except);
673 if ($this->
status == self::STATUS_DRAFT) {
674 include_once DOL_DOCUMENT_ROOT.
'/core/lib/price.lib.php';
677 if (empty($remise_percent)) {
683 if (empty($info_bits)) {
689 if (empty($fk_parent_line) || $fk_parent_line < 0) {
693 $remise_percent =
price2num($remise_percent);
696 $pu_ht_devise =
price2num($pu_ht_devise);
698 if (!preg_match(
'/\((.*)\)/', (
string) $txtva)) {
704 if ($price_base_type ==
'HT') {
715 if ($date_start && $date_end && $date_start > $date_end) {
716 $langs->load(
"errors");
717 $this->error = $langs->trans(
'ErrorStartDateGreaterEnd');
723 $product_type = $type;
724 if (!empty($fk_product) && $fk_product > 0) {
725 $product =
new Product($this->db);
726 $result = $product->fetch($fk_product);
727 $product_type = $product->type;
729 if ($product->isStockManaged() && $product->stock_reel < $qty &&
getDolGlobalString(
'STOCK_MUST_BE_ENOUGH_FOR_PROPOSAL')) {
730 $langs->load(
"errors");
731 $this->error = $langs->trans(
'ErrorStockIsNotEnoughToAddProductOnProposal', $product->ref);
732 $this->db->rollback();
745 $tmpproduct =
new Product($this->db);
746 $result = $tmpproduct->fetch($fk_product);
747 if (abs((
float) $qty) < $tmpproduct->packaging) {
748 $qty = (float) $tmpproduct->packaging;
749 setEventMessages($langs->trans(
'QtyRecalculatedWithPackaging'),
null,
'warnings');
751 if (!empty($tmpproduct->packaging) && (
float)
price2num(fmod((
float) $qty, (
float) $tmpproduct->packaging),
'MS')) {
752 $coeff = intval(abs((
float) $qty) / $tmpproduct->packaging) + 1;
753 $qty =
price2num((
float) $tmpproduct->packaging * $coeff,
'MS');
754 setEventMessages($langs->trans(
'QtyRecalculatedWithPackaging'),
null,
'warnings');
762 if (preg_match(
'/\((.*)\)/', $txtva, $reg)) {
763 $vat_src_code = $reg[1];
764 $txtva = preg_replace(
'/\s*\(.*\)/',
'', $txtva);
767 $tabprice =
calcul_price_total($qty, (
float) $pu, (
float) $remise_percent, $txtva, (
float) $txlocaltax1, (
float) $txlocaltax2, 0, $price_base_type, $info_bits, $product_type,
$mysoc, $localtaxes_type, 100, $this->multicurrency_tx, (
float) $pu_ht_devise);
769 $total_ht = $tabprice[0];
770 $total_tva = $tabprice[1];
771 $total_ttc = $tabprice[2];
772 $total_localtax1 = $tabprice[9];
773 $total_localtax2 = $tabprice[10];
774 $pu_ht = $tabprice[3];
775 $pu_tva = $tabprice[4];
776 $pu_ttc = $tabprice[5];
779 $multicurrency_total_ht = $tabprice[16];
780 $multicurrency_total_tva = $tabprice[17];
781 $multicurrency_total_ttc = $tabprice[18];
782 $pu_ht_devise = $tabprice[19];
786 if (empty($ranktouse) || $ranktouse == -1) {
787 $rangmax = $this->
line_max($fk_parent_line);
788 $ranktouse = $rangmax + 1;
794 $this->line->context = $this->context;
796 $this->line->fk_propal = $this->id;
797 $this->line->label = $label;
798 $this->line->desc = $desc;
799 $this->line->qty = (float) $qty;
801 $this->line->vat_src_code = $vat_src_code;
802 $this->line->tva_tx = $txtva;
803 $this->line->localtax1_tx = ($total_localtax1 ? $localtaxes_type[1] : 0);
804 $this->line->localtax2_tx = ($total_localtax2 ? $localtaxes_type[3] : 0);
805 $this->line->localtax1_type = empty($localtaxes_type[0]) ?
'' : $localtaxes_type[0];
806 $this->line->localtax2_type = empty($localtaxes_type[2]) ?
'' : $localtaxes_type[2];
807 $this->line->fk_product = $fk_product;
808 $this->line->product_type = $type;
809 $this->line->fk_remise_except = $fk_remise_except;
810 $this->line->remise_percent = $remise_percent;
811 $this->line->subprice = (float) $pu_ht;
812 $this->line->rang = $ranktouse;
813 $this->line->info_bits = $info_bits;
814 $this->line->total_ht = (float) $total_ht;
815 $this->line->total_tva = (float) $total_tva;
816 $this->line->total_localtax1 = (float) $total_localtax1;
817 $this->line->total_localtax2 = (float) $total_localtax2;
818 $this->line->total_ttc = (float) $total_ttc;
819 $this->line->special_code = $special_code;
820 $this->line->fk_parent_line = $fk_parent_line;
821 $this->line->fk_unit = $fk_unit;
823 $this->line->date_start = $date_start;
824 $this->line->date_end = $date_end;
826 $this->line->fk_fournprice = $fk_fournprice;
827 $this->line->pa_ht = $pa_ht;
829 $this->line->origin_id = $origin_id;
830 $this->line->origin = $origin;
833 $this->line->fk_multicurrency = $this->fk_multicurrency;
834 $this->line->multicurrency_code = $this->multicurrency_code;
835 $this->line->multicurrency_subprice = (float) $pu_ht_devise;
836 $this->line->multicurrency_total_ht = (float) $multicurrency_total_ht;
837 $this->line->multicurrency_total_tva = (float) $multicurrency_total_tva;
838 $this->line->multicurrency_total_ttc = (float) $multicurrency_total_ttc;
841 if (empty($qty) && empty($special_code)) {
842 $this->line->special_code = 3;
845 if (is_array($array_options) && count($array_options) > 0) {
846 $this->line->array_options = $array_options;
849 $result = $this->line->insert();
851 if (!isset($this->context[
'createfromclone'])) {
852 if (!empty($fk_parent_line)) {
855 } elseif ($ranktouse > 0 && $ranktouse <= count($this->lines)) {
857 $linecount = count($this->lines);
858 for ($ii = $ranktouse; $ii <= $linecount; $ii++) {
863 $this->lines[] = $this->line;
865 foreach ($this->lines as $line) {
866 if ($line->id == $origin_id) {
867 $this->line->extraparams = $line->extraparams;
868 $this->line->setExtraParameters();
874 if (empty($noupdateafterinsertline)) {
880 return $this->line->id;
882 $this->error = $this->db->error();
883 $this->db->rollback();
888 $this->db->rollback();
892 dol_syslog(get_class($this).
"::addline status of proposal must be Draft to allow use of ->addline()", LOG_ERR);
927 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)
931 dol_syslog(get_class($this).
"::updateLine rowid=$rowid, pu=$pu, qty=$qty, remise_percent=$remise_percent,
932 txtva=$txtva, desc=$desc, price_base_type=$price_base_type, info_bits=$info_bits, special_code=$special_code, fk_parent_line=$fk_parent_line, pa_ht=$pa_ht, type=$type, date_start=$date_start, date_end=$date_end");
933 include_once DOL_DOCUMENT_ROOT.
'/core/lib/price.lib.php';
936 $remise_percent =
price2num($remise_percent);
939 $pu_ht_devise =
price2num($pu_ht_devise);
940 if (!preg_match(
'/\((.*)\)/', (
string) $txtva)) {
946 if (empty($qty) && empty($special_code)) {
949 if (!empty($qty) && $special_code == 3) {
956 if ($date_start && $date_end && $date_start > $date_end) {
957 $langs->load(
"errors");
958 $this->error = $langs->trans(
'ErrorStartDateGreaterEnd');
962 if ($this->
status == self::STATUS_DRAFT) {
975 if (preg_match(
'/\((.*)\)/', $txtva, $reg)) {
976 $vat_src_code = $reg[1];
977 $txtva = preg_replace(
'/\s*\(.*\)/',
'', $txtva);
982 $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);
983 $total_ht = $tabprice[0];
984 $total_tva = $tabprice[1];
985 $total_ttc = $tabprice[2];
986 $total_localtax1 = $tabprice[9];
987 $total_localtax2 = $tabprice[10];
988 $pu_ht = $tabprice[3];
989 $pu_tva = $tabprice[4];
990 $pu_ttc = $tabprice[5];
993 $multicurrency_total_ht = $tabprice[16];
994 $multicurrency_total_tva = $tabprice[17];
995 $multicurrency_total_ttc = $tabprice[18];
996 $pu_ht_devise = $tabprice[19];
1000 $line->fetch($rowid);
1002 $staticline = clone $line;
1004 $line->oldline = $staticline;
1005 $this->line = $line;
1006 $this->line->context = $this->context;
1007 $this->line->rang = $rang;
1010 if (!empty($fk_parent_line) && !empty($staticline->fk_parent_line) && $fk_parent_line != $staticline->fk_parent_line) {
1011 $rangmax = $this->
line_max($fk_parent_line);
1012 $this->line->rang = $rangmax + 1;
1016 if (abs((
float) $qty) < $this->line->packaging) {
1017 $qty = $this->line->packaging;
1018 setEventMessage($langs->trans(
'QtyRecalculatedWithPackaging'),
'warnings');
1020 if (!empty($this->line->packaging)
1021 && is_numeric($this->line->packaging)
1022 && (
float) $this->line->packaging > 0
1023 && (
float)
price2num(fmod((
float) $qty, (
float) $this->line->packaging),
'MS')) {
1024 $coeff = intval(abs((
float) $qty) / $this->line->packaging) + 1;
1025 $qty = $this->line->packaging * $coeff;
1026 setEventMessage($langs->trans(
'QtyRecalculatedWithPackaging'),
'warnings');
1031 $this->line->id = $rowid;
1032 $this->line->label = $label;
1033 $this->line->desc = $desc;
1034 $this->line->qty = $qty;
1035 $this->line->product_type = $type;
1036 $this->line->vat_src_code = $vat_src_code;
1037 $this->line->tva_tx = $txtva;
1038 $this->line->localtax1_tx = $txlocaltax1;
1039 $this->line->localtax2_tx = $txlocaltax2;
1040 $this->line->localtax1_type = empty($localtaxes_type[0]) ?
'' : $localtaxes_type[0];
1041 $this->line->localtax2_type = empty($localtaxes_type[2]) ?
'' : $localtaxes_type[2];
1042 $this->line->remise_percent = $remise_percent;
1043 $this->line->subprice = (float) $pu_ht;
1044 $this->line->info_bits = $info_bits;
1046 $this->line->total_ht = (float) $total_ht;
1047 $this->line->total_tva = (float) $total_tva;
1048 $this->line->total_localtax1 = (float) $total_localtax1;
1049 $this->line->total_localtax2 = (float) $total_localtax2;
1050 $this->line->total_ttc = (float) $total_ttc;
1051 $this->line->special_code = $special_code;
1052 $this->line->fk_parent_line = $fk_parent_line;
1053 $this->line->skip_update_total = $skip_update_total;
1054 $this->line->fk_unit = $fk_unit;
1056 $this->line->fk_fournprice = $fk_fournprice;
1057 $this->line->pa_ht = $pa_ht;
1059 $this->line->date_start = $date_start;
1060 $this->line->date_end = $date_end;
1062 if (is_array($array_options) && count($array_options) > 0) {
1064 foreach ($array_options as $key => $value) {
1065 $this->line->array_options[$key] = $array_options[$key];
1070 $this->line->multicurrency_subprice = (float) $pu_ht_devise;
1071 $this->line->multicurrency_total_ht = (float) $multicurrency_total_ht;
1072 $this->line->multicurrency_total_tva = (float) $multicurrency_total_tva;
1073 $this->line->multicurrency_total_ttc = (float) $multicurrency_total_ttc;
1075 $result = $this->line->update($notrigger);
1078 if (!empty($fk_parent_line)) {
1088 $this->db->commit();
1092 $this->db->rollback();
1096 dol_syslog(get_class($this).
"::updateline Erreur -2 Propal en mode incompatible pour cette action");
1113 if ($this->
status == self::STATUS_DRAFT) {
1118 $line->context = $this->context;
1121 $line->fetch($lineid);
1123 if ($id > 0 && $line->fk_propal != $id) {
1124 $this->error =
'ErrorLineIDDoesNotMatchWithObjectID';
1129 $staticline = clone $line;
1130 $line->oldline = $staticline;
1132 if ($line->delete($user) > 0) {
1135 $this->db->commit();
1139 $this->db->rollback();
1143 $this->error =
'ErrorDeleteLineNotAllowedByObjectStatus';
1157 public function create($user, $notrigger = 0)
1166 if (empty($this->
date)) {
1167 $this->
date = $this->datep;
1169 $this->fin_validite = $this->
date + ($this->duree_validite * 24 * 3600);
1170 if (empty($this->availability_id)) {
1171 $this->availability_id = 0;
1173 if (empty($this->demand_reason_id)) {
1174 $this->demand_reason_id = 0;
1178 if (!empty($this->multicurrency_code) && empty($this->multicurrency_tx)) {
1183 if (empty($this->fk_multicurrency)) {
1185 $this->fk_multicurrency = 0;
1186 $this->multicurrency_tx = 1;
1192 $delivery_date = $this->delivery_date;
1199 $this->error =
"Failed to fetch company";
1200 dol_syslog(get_class($this).
"::create ".$this->error, LOG_ERR);
1205 if (!empty($this->
ref)) {
1208 $this->error =
'ErrorRefAlreadyExists';
1209 dol_syslog(get_class($this).
"::create ".$this->error, LOG_WARNING);
1210 $this->db->rollback();
1215 if (empty($this->
date)) {
1216 $this->error =
"Date of proposal is required";
1217 dol_syslog(get_class($this).
"::create ".$this->error, LOG_ERR);
1225 $sql =
"INSERT INTO ".MAIN_DB_PREFIX.$this->table_element.
" (";
1228 $sql .=
", total_tva";
1229 $sql .=
", total_ttc";
1233 $sql .=
", fk_user_author";
1234 $sql .=
", note_private";
1235 $sql .=
", note_public";
1236 $sql .=
", model_pdf";
1237 $sql .=
", fin_validite";
1238 $sql .=
", fk_cond_reglement";
1239 $sql .=
", deposit_percent";
1240 $sql .=
", fk_mode_reglement";
1241 $sql .=
", fk_account";
1242 $sql .=
", ref_client";
1243 $sql .=
", ref_ext";
1244 $sql .=
", date_livraison";
1245 $sql .=
", fk_shipping_method";
1246 $sql .=
", fk_warehouse";
1247 $sql .=
", fk_availability";
1248 $sql .=
", fk_input_reason";
1249 $sql .=
", fk_projet";
1250 $sql .=
", fk_incoterms";
1251 $sql .=
", location_incoterms";
1253 $sql .=
", fk_multicurrency";
1254 $sql .=
", multicurrency_code";
1255 $sql .=
", multicurrency_tx";
1257 $sql .=
" VALUES (";
1258 $sql .= $this->socid;
1262 $sql .=
", '".$this->db->idate($this->
date).
"'";
1263 $sql .=
", '".$this->db->idate($now).
"'";
1264 $sql .=
", '(PROV)'";
1265 $sql .=
", ".($user->id > 0 ? ((int) $user->id) :
"NULL");
1266 $sql .=
", '".$this->db->escape($this->note_private).
"'";
1267 $sql .=
", '".$this->db->escape($this->note_public).
"'";
1268 $sql .=
", '".$this->db->escape($this->model_pdf).
"'";
1269 $sql .=
", ".($this->fin_validite !=
'' ?
"'".$this->db->idate($this->fin_validite).
"'" :
"NULL");
1270 $sql .=
", ".($this->cond_reglement_id > 0 ? ((int) $this->cond_reglement_id) :
'NULL');
1271 $sql .=
", ".(!empty($this->deposit_percent) ?
"'".$this->db->escape($this->deposit_percent).
"'" :
'NULL');
1272 $sql .=
", ".($this->mode_reglement_id > 0 ? ((int) $this->mode_reglement_id) :
'NULL');
1273 $sql .=
", ".($this->fk_account > 0 ? ((int) $this->fk_account) :
'NULL');
1274 $sql .=
", '".$this->db->escape((
string) $this->ref_client).
"'";
1275 $sql .=
", '".$this->db->escape((
string) $this->ref_ext).
"'";
1276 $sql .=
", ".(!
isDolTms($delivery_date) ?
"NULL" :
"'".$this->db->idate($delivery_date).
"'");
1277 $sql .=
", ".($this->shipping_method_id > 0 ? $this->shipping_method_id :
'NULL');
1278 $sql .=
", ".($this->warehouse_id > 0 ? $this->warehouse_id :
'NULL');
1279 $sql .=
", ".((int) $this->availability_id);
1280 $sql .=
", ".((int) $this->demand_reason_id);
1281 $sql .=
", ".($this->fk_project ? $this->fk_project :
"null");
1282 $sql .=
", ".(int) $this->fk_incoterms;
1283 $sql .=
", '".$this->db->escape($this->location_incoterms).
"'";
1284 $sql .=
", ".(int) $this->entity;
1285 $sql .=
", ".(int) $this->fk_multicurrency;
1286 $sql .=
", '".$this->db->escape($this->multicurrency_code).
"'";
1287 $sql .=
", ".(float) $this->multicurrency_tx;
1290 dol_syslog(get_class($this).
"::create", LOG_DEBUG);
1291 $resql = $this->db->query($sql);
1293 $this->
id = $this->db->last_insert_id(MAIN_DB_PREFIX.$this->table_element);
1296 $this->
ref =
'(PROV'.$this->id.
')';
1297 $sql =
'UPDATE '.MAIN_DB_PREFIX.$this->table_element.
" SET ref='".$this->db->escape($this->
ref).
"' WHERE rowid=".((int) $this->
id);
1299 dol_syslog(get_class($this).
"::create", LOG_DEBUG);
1300 $resql = $this->db->query($sql);
1305 if (!empty($this->linkedObjectsIds) && empty($this->linked_objects)) {
1306 $this->linked_objects = $this->linkedObjectsIds;
1310 if (!$error && !empty($this->linked_objects) && is_array($this->linked_objects)) {
1311 foreach ($this->linked_objects as $origin => $tmp_origin_id) {
1312 if (is_array($tmp_origin_id)) {
1313 foreach ($tmp_origin_id as $origin_id) {
1316 $this->error = $this->db->lasterror();
1321 $origin_id = $tmp_origin_id;
1324 $this->error = $this->db->lasterror();
1336 $fk_parent_line = 0;
1337 $num = count($this->lines);
1339 for ($i = 0; $i < $num; $i++) {
1340 if (!is_object($this->lines[$i])) {
1342 $line = (object) $this->lines[$i];
1344 $line = $this->lines[$i];
1347 if (($line->product_type != 9 && empty($line->fk_parent_line)) || $line->product_type == 9) {
1348 $fk_parent_line = 0;
1351 $vatrate = $line->tva_tx;
1352 if ($line->vat_src_code && !preg_match(
'/\(.*\)/', $vatrate)) {
1353 $vatrate .=
' ('.$line->vat_src_code.
')';
1357 $originid = $line->origin_id;
1358 $origintype = $line->origin;
1360 $originid = $line->id;
1361 $origintype = $this->element;
1369 $line->localtax1_tx,
1370 $line->localtax2_tx,
1372 $line->remise_percent,
1376 $line->product_type,
1378 $line->special_code,
1380 $line->fk_fournprice,
1385 $line->array_options,
1387 (
string) $origintype,
1396 $this->error = $this->db->error;
1402 $line->id = $result;
1405 if ($result > 0 && $line->product_type == 9) {
1406 $fk_parent_line = $result;
1421 if (!$error && !$notrigger) {
1423 $result = $this->call_trigger(
'PROPAL_CREATE', $user);
1430 $this->error = $this->db->lasterror();
1435 $this->error = $this->db->lasterror();
1440 $this->db->commit();
1441 dol_syslog(get_class($this).
"::create done id=".$this->
id);
1444 $this->db->rollback();
1448 $this->error = $this->db->lasterror();
1449 $this->db->rollback();
1464 public function createFromClone(
User $user, $socid = 0, $forceentity =
null, $update_prices =
false, $update_desc =
false)
1466 global $conf, $hookmanager,
$mysoc;
1475 $object =
new self($this->db);
1482 $objsoc =
new Societe($this->db);
1485 if (!empty($socid) && $socid !=
$object->socid) {
1486 if ($objsoc->fetch($socid) > 0) {
1488 $object->cond_reglement_id = (!empty($objsoc->cond_reglement_id) ? $objsoc->cond_reglement_id : 0);
1489 $object->deposit_percent = (!empty($objsoc->deposit_percent) ? $objsoc->deposit_percent :
null);
1490 $object->mode_reglement_id = (!empty($objsoc->mode_reglement_id) ? $objsoc->mode_reglement_id : 0);
1491 $object->fk_delivery_address = 0;
1514 $objsoc->fetch(
$object->socid);
1518 if ($update_prices ===
true || $update_desc ===
true) {
1519 if ($objsoc->id > 0 && !empty(
$object->lines)) {
1522 require_once DOL_DOCUMENT_ROOT .
'/product/class/productcustomerprice.class.php';
1525 foreach (
$object->lines as $line) {
1528 if ($line->fk_product > 0) {
1529 $prod =
new Product($this->db);
1530 $res = $prod->fetch($line->fk_product);
1532 if ($update_prices ===
true) {
1533 $pu_ht = $prod->price;
1535 $remise_percent = $objsoc->remise_percent;
1538 $pu_ht = $prod->multiprices[$objsoc->price_level];
1540 if (isset($prod->multiprices_tva_tx[$objsoc->price_level])) {
1541 $tva_tx = (string) $prod->multiprices_tva_tx[$objsoc->price_level];
1546 $filter = array(
't.fk_product' => (
string) $prod->id,
't.fk_soc' => (
string) $objsoc->id);
1547 $result = $prodcustprice->fetchAll(
'',
'', 0, 0, $filter);
1550 if (count($prodcustprice->lines) > 0) {
1551 $date_now = (int) floor(
dol_now() / 86400) * 86400;
1552 foreach ($prodcustprice->lines as $k => $custprice_line) {
1553 if ($custprice_line->date_begin <= $date_now && (empty($custprice_line->date_end) || $date_now <= $custprice_line->date_end)) {
1554 $pu_ht =
price($custprice_line->price);
1555 $tva_tx = ($custprice_line->default_vat_code ? $custprice_line->tva_tx .
' (' . $custprice_line->default_vat_code .
' )' : $custprice_line->tva_tx);
1556 if ($custprice_line->default_vat_code && !preg_match(
'/\(.*\)/', $tva_tx)) {
1557 $tva_tx .=
' (' . $custprice_line->default_vat_code .
')';
1559 $remise_percent = $custprice_line->discount_percent;
1567 $line->subprice = $pu_ht;
1568 $line->tva_tx = $tva_tx;
1569 $line->remise_percent = $remise_percent;
1571 if ($update_desc ===
true) {
1572 $line->desc = $prod->description;
1582 $object->entity = (!empty($forceentity) ? $forceentity :
$object->entity);
1587 $object->user_creation_id = $user->id;
1588 $object->user_validation_id = 0;
1601 $object->context[
'createfromclone'] =
'createfromclone';
1602 $result =
$object->create($user);
1610 if (
$object->copy_linked_contact($this,
'internal') < 0) {
1617 if ($this->socid ==
$object->socid) {
1618 if (
$object->copy_linked_contact($this,
'external') < 0) {
1626 if (is_object($hookmanager)) {
1627 $parameters = array(
'objFrom' => $this,
'clonedObj' =>
$object);
1629 $reshook = $hookmanager->executeHooks(
'createFrom', $parameters,
$object, $action);
1637 unset(
$object->context[
'createfromclone']);
1641 $this->db->commit();
1644 $this->db->rollback();
1658 public function fetch($rowid, $ref =
'', $ref_ext =
'', $forceentity = 0)
1660 $sql =
"SELECT p.rowid, p.ref, p.entity, p.fk_soc";
1661 $sql .=
", p.total_ttc, p.total_tva, p.localtax1, p.localtax2, p.total_ht";
1662 $sql .=
", p.datec";
1663 $sql .=
", p.date_signature as dates";
1664 $sql .=
", p.date_valid as datev";
1665 $sql .=
", p.datep as dp";
1666 $sql .=
", p.fin_validite as dfv";
1667 $sql .=
", p.date_livraison as delivery_date";
1668 $sql .=
", p.model_pdf, p.last_main_doc, p.ref_client, ref_ext, p.extraparams";
1669 $sql .=
", p.note_private, p.note_public";
1670 $sql .=
", p.fk_projet as fk_project, p.fk_statut";
1671 $sql .=
", p.fk_user_author, p.fk_user_valid, p.fk_user_cloture";
1672 $sql .=
", p.fk_delivery_address";
1673 $sql .=
", p.fk_availability";
1674 $sql .=
", p.fk_input_reason";
1675 $sql .=
", p.fk_cond_reglement";
1676 $sql .=
", p.fk_mode_reglement";
1677 $sql .=
', p.fk_account';
1678 $sql .=
", p.fk_shipping_method";
1679 $sql .=
", p.fk_warehouse";
1680 $sql .=
", p.fk_incoterms, p.location_incoterms";
1681 $sql .=
", p.fk_multicurrency, p.multicurrency_code, p.multicurrency_tx, p.multicurrency_total_ht, p.multicurrency_total_tva, p.multicurrency_total_ttc";
1682 $sql .=
", p.tms as date_modification";
1683 $sql .=
", i.libelle as label_incoterms";
1684 $sql .=
", c.label as statut_label";
1685 $sql .=
", ca.code as availability_code, ca.label as availability";
1686 $sql .=
", dr.code as demand_reason_code, dr.label as demand_reason";
1687 $sql .=
", cr.code as cond_reglement_code, cr.libelle as cond_reglement, cr.libelle_facture as cond_reglement_libelle_doc, p.deposit_percent";
1688 $sql .=
", cp.code as mode_reglement_code, cp.libelle as mode_reglement";
1689 $sql .=
" FROM ".MAIN_DB_PREFIX.$this->table_element.
" as p";
1690 $sql .=
' LEFT JOIN '.MAIN_DB_PREFIX.
'c_propalst as c ON p.fk_statut = c.id';
1691 $sql .=
' LEFT JOIN '.MAIN_DB_PREFIX.
'c_paiement as cp ON p.fk_mode_reglement = cp.id AND cp.entity IN ('.
getEntity(
'c_paiement').
')';
1692 $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').
')';
1693 $sql .=
' LEFT JOIN '.MAIN_DB_PREFIX.
'c_availability as ca ON p.fk_availability = ca.rowid';
1694 $sql .=
' LEFT JOIN '.MAIN_DB_PREFIX.
'c_input_reason as dr ON p.fk_input_reason = dr.rowid';
1695 $sql .=
' LEFT JOIN '.MAIN_DB_PREFIX.
'c_incoterms as i ON p.fk_incoterms = i.rowid';
1698 if (!empty($forceentity)) {
1699 $sql .=
" WHERE p.entity = ".(int) $forceentity;
1701 $sql .=
" WHERE p.entity IN (".getEntity(
'propal').
")";
1703 $sql .=
" AND p.ref='".$this->db->escape($ref).
"'";
1706 $sql .=
" WHERE p.rowid = ".((int) $rowid);
1709 dol_syslog(get_class($this).
"::fetch", LOG_DEBUG);
1710 $resql = $this->db->query($sql);
1712 if ($this->db->num_rows($resql)) {
1713 $obj = $this->db->fetch_object($resql);
1715 $this->
id = $obj->rowid;
1716 $this->entity = $obj->entity;
1718 $this->
ref = $obj->ref;
1719 $this->ref_client = $obj->ref_client;
1720 $this->ref_customer = $obj->ref_client;
1721 $this->ref_ext = $obj->ref_ext;
1723 $this->total = $obj->total_ttc;
1724 $this->total_ttc = $obj->total_ttc;
1725 $this->total_ht = $obj->total_ht;
1726 $this->total_tva = $obj->total_tva;
1727 $this->total_localtax1 = $obj->localtax1;
1728 $this->total_localtax2 = $obj->localtax2;
1730 $this->socid = $obj->fk_soc;
1731 $this->thirdparty =
null;
1733 $this->fk_project = $obj->fk_project;
1734 $this->project =
null;
1736 $this->model_pdf = $obj->model_pdf;
1737 $this->last_main_doc = $obj->last_main_doc;
1738 $this->note = $obj->note_private;
1739 $this->note_private = $obj->note_private;
1740 $this->note_public = $obj->note_public;
1742 $this->
status = (int) $obj->fk_statut;
1743 $this->statut = $this->status;
1745 $this->datec = $this->db->jdate($obj->datec);
1746 $this->datev = $this->db->jdate($obj->datev);
1747 $this->date_creation = $this->db->jdate($obj->datec);
1748 $this->date_validation = $this->db->jdate($obj->datev);
1749 $this->date_modification = $this->db->jdate($obj->date_modification);
1750 $this->date_signature = $this->db->jdate($obj->dates);
1751 $this->
date = $this->db->jdate($obj->dp);
1752 $this->datep = $this->db->jdate($obj->dp);
1753 $this->fin_validite = $this->db->jdate($obj->dfv);
1754 $this->delivery_date = $this->db->jdate($obj->delivery_date);
1755 $this->shipping_method_id = ($obj->fk_shipping_method > 0) ? $obj->fk_shipping_method :
null;
1756 $this->warehouse_id = ($obj->fk_warehouse > 0) ? $obj->fk_warehouse :
null;
1757 $this->availability_id = $obj->fk_availability;
1758 $this->availability_code = $obj->availability_code;
1760 $this->demand_reason_id = $obj->fk_input_reason;
1761 $this->demand_reason_code = $obj->demand_reason_code;
1763 $this->fk_address = $obj->fk_delivery_address;
1765 $this->mode_reglement_id = $obj->fk_mode_reglement;
1766 $this->mode_reglement_code = $obj->mode_reglement_code;
1767 $this->mode_reglement = $obj->mode_reglement;
1768 $this->fk_account = ($obj->fk_account > 0) ? $obj->fk_account :
null;
1769 $this->cond_reglement_id = $obj->fk_cond_reglement;
1770 $this->cond_reglement_code = $obj->cond_reglement_code;
1771 $this->cond_reglement = $obj->cond_reglement;
1772 $this->cond_reglement_doc = $obj->cond_reglement_libelle_doc;
1773 $this->deposit_percent = $obj->deposit_percent;
1775 $this->extraparams = !empty($obj->extraparams) ? (array) json_decode($obj->extraparams,
true) : array();
1777 $this->user_author_id = $obj->fk_user_author;
1778 $this->user_validation_id = $obj->fk_user_valid;
1779 $this->user_closing_id = $obj->fk_user_cloture;
1782 $this->fk_incoterms = $obj->fk_incoterms;
1783 $this->location_incoterms = $obj->location_incoterms;
1784 $this->label_incoterms = $obj->label_incoterms;
1787 $this->fk_multicurrency = $obj->fk_multicurrency;
1788 $this->multicurrency_code = $obj->multicurrency_code;
1789 $this->multicurrency_tx = $obj->multicurrency_tx;
1790 $this->multicurrency_total_ht = $obj->multicurrency_total_ht;
1791 $this->multicurrency_total_tva = $obj->multicurrency_total_tva;
1792 $this->multicurrency_total_ttc = $obj->multicurrency_total_ttc;
1798 $this->db->free($resql);
1800 $this->lines = array();
1811 $this->error =
"Record Not Found";
1814 $this->error = $this->db->lasterror();
1833 if (isset($this->
ref)) {
1834 $this->
ref = trim($this->
ref);
1836 if (isset($this->ref_client)) {
1837 $this->ref_client = trim($this->ref_client);
1839 if (isset($this->note) || isset($this->note_private)) {
1840 $this->note_private = (isset($this->note_private) ? trim($this->note_private) : trim($this->note));
1842 if (isset($this->note_public)) {
1843 $this->note_public = trim($this->note_public);
1845 if (isset($this->model_pdf)) {
1846 $this->model_pdf = trim($this->model_pdf);
1848 if (isset($this->import_key)) {
1849 $this->import_key = trim($this->import_key);
1851 if (!empty($this->duree_validite) && is_numeric($this->duree_validite)) {
1852 $this->fin_validite = $this->
date + ($this->duree_validite * 24 * 3600);
1859 $sql =
"UPDATE ".MAIN_DB_PREFIX.$this->table_element.
" SET";
1860 $sql =
"UPDATE ".MAIN_DB_PREFIX.
"propal SET";
1861 $sql .=
" ref = ".(isset($this->
ref) ?
"'".$this->db->escape($this->
ref).
"'" :
"null").
",";
1862 $sql .=
" ref_client = ".(isset($this->ref_client) ?
"'".$this->db->escape($this->ref_client).
"'" :
"null").
",";
1863 $sql .=
" ref_ext = ".(isset($this->ref_ext) ?
"'".$this->db->escape($this->ref_ext).
"'" :
"null").
",";
1864 $sql .=
" fk_soc = ".(!empty($this->socid) ? (int) $this->socid :
"null").
",";
1865 $sql .=
" datep = ".(strval($this->
date) !=
'' ?
"'".$this->db->idate($this->
date).
"'" :
'null').
",";
1866 if (!empty($this->fin_validite)) {
1867 $sql .=
" fin_validite = ".(strval($this->fin_validite) !=
'' ?
"'".$this->db->idate($this->fin_validite).
"'" :
'null').
",";
1869 $sql .=
" date_valid = ".(strval($this->date_validation) !=
'' ?
"'".$this->db->idate($this->date_validation).
"'" :
'null').
",";
1870 $sql .=
" total_tva = ".(isset($this->total_tva) ? (float) $this->total_tva :
"null").
",";
1871 $sql .=
" localtax1 = ".(isset($this->total_localtax1) ? (float) $this->total_localtax1 :
"null").
",";
1872 $sql .=
" localtax2 = ".(isset($this->total_localtax2) ? (float) $this->total_localtax2 :
"null").
",";
1873 $sql .=
" total_ht = ".(isset($this->total_ht) ? (float) $this->total_ht :
"null").
",";
1874 $sql .=
" total_ttc = ".(isset($this->total_ttc) ? (float) $this->total_ttc :
"null").
",";
1875 $sql .=
" fk_statut = ".(isset($this->
status) ? (int) $this->
status :
"null").
",";
1876 $sql .=
" fk_user_author = ".(!empty($this->user_author_id) ? (int) $this->user_author_id :
"null").
",";
1877 $sql .=
" fk_user_valid = ".(!empty($this->user_validation_id) ? (int) $this->user_validation_id :
"null").
",";
1879 $sql .=
" fk_projet = ".(!empty($this->fk_project) ? (int) $this->fk_project :
"null").
",";
1880 $sql .=
" fk_cond_reglement = ".(!empty($this->cond_reglement_id) ? (int) $this->cond_reglement_id :
"null").
",";
1881 $sql .=
" deposit_percent = ".(!empty($this->deposit_percent) ?
"'".$this->db->escape($this->deposit_percent).
"'" :
"null").
",";
1882 $sql .=
" fk_mode_reglement = ".(!empty($this->mode_reglement_id) ? (int) $this->mode_reglement_id :
"null").
",";
1883 $sql .=
" fk_input_reason = ".(!empty($this->demand_reason_id) ? (int) $this->demand_reason_id :
"null").
",";
1884 $sql .=
" fk_shipping_method = ".(isset($this->shipping_method_id) ? (int) $this->shipping_method_id :
"null").
",";
1885 $sql .=
" fk_availability = ".(!empty($this->availability_id) ? (int) $this->availability_id :
"null").
",";
1886 $sql .=
" note_private = ".(isset($this->note_private) ?
"'".$this->db->escape($this->note_private).
"'" :
"null").
",";
1887 $sql .=
" note_public = ".(isset($this->note_public) ?
"'".$this->db->escape($this->note_public).
"'" :
"null").
",";
1888 $sql .=
" model_pdf = ".(isset($this->model_pdf) ?
"'".$this->db->escape($this->model_pdf).
"'" :
"null").
",";
1889 $sql .=
" import_key = ".(isset($this->import_key) ?
"'".$this->db->escape($this->import_key).
"'" :
"null");
1890 $sql .=
" WHERE rowid = ".((int) $this->
id);
1894 dol_syslog(get_class($this).
"::update", LOG_DEBUG);
1895 $resql = $this->db->query($sql);
1898 $this->errors[] =
"Error ".$this->db->lasterror();
1908 if (!$error && !$notrigger) {
1910 $result = $this->call_trigger(
'PROPAL_MODIFY', $user);
1919 foreach ($this->errors as $errmsg) {
1920 dol_syslog(get_class($this).
"::update ".$errmsg, LOG_ERR);
1921 $this->error .= ($this->error ?
', '.$errmsg : $errmsg);
1923 $this->db->rollback();
1926 $this->db->commit();
1941 public function fetch_lines($only_product = 0, $loadalsotranslation = 0, $sqlforgedfilters =
'')
1944 $this->lines = array();
1946 $sql =
'SELECT d.rowid, d.fk_propal, d.fk_parent_line, d.label as custom_label, d.description, d.price, d.vat_src_code, d.tva_tx, d.localtax1_tx, d.localtax2_tx, d.localtax1_type, d.localtax2_type, d.qty, d.fk_remise_except, d.remise_percent, d.subprice, d.fk_product,';
1947 $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,';
1948 $sql .=
' d.fk_unit,';
1949 $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,';
1950 $sql .=
' p.weight, p.weight_units, p.volume, p.volume_units,';
1951 $sql .=
' p.customcode, p.fk_country as country_id, c.code as country_code,';
1952 $sql .=
' d.date_start, d.date_end, d.extraparams,';
1953 $sql .=
' d.fk_multicurrency, d.multicurrency_code, d.multicurrency_subprice, d.multicurrency_total_ht, d.multicurrency_total_tva, d.multicurrency_total_ttc';
1954 $sql .=
' FROM '.MAIN_DB_PREFIX.$this->table_element_line.
' as d';
1955 $sql .=
' LEFT JOIN '.MAIN_DB_PREFIX.
'product as p ON (d.fk_product = p.rowid)';
1956 $sql .=
' LEFT JOIN '.MAIN_DB_PREFIX.
'c_country as c ON c.rowid = p.fk_country';
1957 $sql .=
' WHERE d.fk_propal = '.((int) $this->
id);
1958 if ($only_product) {
1959 $sql .=
' AND p.fk_product_type = 0';
1961 if ($sqlforgedfilters) {
1962 $sql .= $sqlforgedfilters;
1964 $sql .=
' ORDER BY d.rang, d.rowid';
1966 dol_syslog(get_class($this).
"::fetch_lines", LOG_DEBUG);
1967 $result = $this->db->query($sql);
1969 require_once DOL_DOCUMENT_ROOT.
'/core/class/extrafields.class.php';
1971 $num = $this->db->num_rows($result);
1975 $objp = $this->db->fetch_object($result);
1979 $line->rowid = $objp->rowid;
1980 $line->id = $objp->rowid;
1981 $line->fk_propal = $objp->fk_propal;
1982 $line->fk_parent_line = $objp->fk_parent_line;
1983 $line->label = $objp->custom_label;
1984 $line->desc = $objp->description;
1985 $line->description = $objp->description;
1986 $line->qty = $objp->qty;
1987 $line->vat_src_code = $objp->vat_src_code;
1988 $line->tva_tx = $objp->tva_tx;
1989 $line->localtax1_tx = $objp->localtax1_tx;
1990 $line->localtax2_tx = $objp->localtax2_tx;
1991 $line->localtax1_type = $objp->localtax1_type;
1992 $line->localtax2_type = $objp->localtax2_type;
1993 $line->subprice = $objp->subprice;
1994 $line->fk_remise_except = $objp->fk_remise_except;
1995 $line->remise_percent = $objp->remise_percent;
1997 $line->info_bits = $objp->info_bits;
1998 $line->total_ht = $objp->total_ht;
1999 $line->total_tva = $objp->total_tva;
2000 $line->total_localtax1 = $objp->total_localtax1;
2001 $line->total_localtax2 = $objp->total_localtax2;
2002 $line->total_ttc = $objp->total_ttc;
2003 $line->fk_fournprice = $objp->fk_fournprice;
2004 $marginInfos =
getMarginInfos($objp->subprice, $objp->remise_percent, $objp->tva_tx, $objp->localtax1_tx, $objp->localtax2_tx, $line->fk_fournprice, $objp->pa_ht);
2005 $line->pa_ht = $marginInfos[0];
2006 $line->marge_tx = $marginInfos[1];
2007 $line->marque_tx = $marginInfos[2];
2008 $line->special_code = $objp->special_code;
2009 $line->rang = $objp->rang;
2011 $line->fk_product = $objp->fk_product;
2013 $line->ref = $objp->product_ref;
2014 $line->libelle = $objp->product_label;
2016 $line->product_ref = $objp->product_ref;
2017 $line->product_label = $objp->product_label;
2018 $line->product_desc = $objp->product_desc;
2019 $line->product_tobatch = $objp->product_tobatch;
2020 $line->product_barcode = $objp->product_barcode;
2021 $line->product_custom_code = $objp->customcode;
2022 $line->product_custom_country_id = $objp->country_id;
2023 $line->product_custom_country_code = $objp->country_code;
2024 $line->product_type = $objp->product_type;
2025 $line->fk_product_type = $objp->fk_product_type;
2027 $line->fk_unit = $objp->fk_unit;
2028 $line->weight = $objp->weight;
2029 $line->weight_units = $objp->weight_units;
2030 $line->volume = $objp->volume;
2031 $line->volume_units = $objp->volume_units;
2033 $line->date_start = $this->db->jdate($objp->date_start);
2034 $line->date_end = $this->db->jdate($objp->date_end);
2036 $line->extraparams = !empty($objp->extraparams) ? (array) json_decode($objp->extraparams,
true) : array();
2039 $line->fk_multicurrency = $objp->fk_multicurrency;
2040 $line->multicurrency_code = $objp->multicurrency_code;
2041 $line->multicurrency_subprice = $objp->multicurrency_subprice;
2042 $line->multicurrency_total_ht = $objp->multicurrency_total_ht;
2043 $line->multicurrency_total_tva = $objp->multicurrency_total_tva;
2044 $line->multicurrency_total_ttc = $objp->multicurrency_total_ttc;
2046 $line->fetch_optionals();
2049 if (
getDolGlobalInt(
'MAIN_MULTILANGS') && !empty($objp->fk_product) && !empty($loadalsotranslation)) {
2050 $tmpproduct =
new Product($this->db);
2051 $tmpproduct->fetch($objp->fk_product);
2052 $tmpproduct->getMultiLangs();
2054 $line->multilangs = $tmpproduct->multilangs;
2057 $this->lines[$i] = $line;
2062 $this->db->free($result);
2066 $this->error = $this->db->lasterror();
2078 public function valid($user, $notrigger = 0)
2082 require_once DOL_DOCUMENT_ROOT.
'/core/lib/files.lib.php';
2087 if ($this->
status == self::STATUS_VALIDATED) {
2088 dol_syslog(get_class($this).
"::valid action abandoned: already validated", LOG_WARNING);
2092 if (!((!
getDolGlobalString(
'MAIN_USE_ADVANCED_PERMS') && $user->hasRight(
'propal',
'creer'))
2093 || (
getDolGlobalString(
'MAIN_USE_ADVANCED_PERMS') && $user->hasRight(
'propal',
'propal_advance',
'validate')))) {
2094 $this->error =
'ErrorPermissionDenied';
2095 dol_syslog(get_class($this).
"::valid ".$this->error, LOG_ERR);
2100 dol_syslog(get_class($this).
"::valid checkActiveProductInLines ".$this->error, LOG_INFO);
2109 $soc =
new Societe($this->db);
2110 $soc->fetch($this->socid);
2113 if (preg_match(
'/^[\(]?PROV/i', $this->
ref) || empty($this->
ref)) {
2114 $num = $this->getNextNumRef($soc);
2116 $num = (string) $this->
ref;
2120 $sql =
"UPDATE ".MAIN_DB_PREFIX.$this->table_element;
2121 $sql .=
" SET ref = '".$this->db->escape($num).
"',";
2122 $sql .=
" fk_statut = ".self::STATUS_VALIDATED.
", date_valid='".$this->db->idate($now).
"', fk_user_valid=".((int) $user->id);
2125 dol_syslog(get_class($this).
"::valid", LOG_DEBUG);
2126 $resql = $this->db->query($sql);
2133 if (!$error && !$notrigger) {
2135 $result = $this->call_trigger(
'PROPAL_VALIDATE', $user);
2143 $this->oldref = $this->ref;
2146 if (preg_match(
'/^[\(]?PROV/i', $this->
ref)) {
2148 $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).
"'";
2149 $sql .=
" WHERE filename LIKE '".$this->db->escape($this->
ref).
"%' AND filepath = 'propale/".$this->db->escape($this->
ref).
"' and entity = ".((int) $conf->entity);
2150 $resql = $this->db->query($sql);
2153 $this->error = $this->db->lasterror();
2155 $sql =
'UPDATE '.MAIN_DB_PREFIX.
"ecm_files set filepath = 'propale/".$this->db->escape($this->newref).
"'";
2156 $sql .=
" WHERE filepath = 'propale/".$this->db->escape($this->
ref).
"' and entity = ".$conf->entity;
2157 $resql = $this->db->query($sql);
2160 $this->error = $this->db->lasterror();
2166 $dirsource = $conf->propal->multidir_output[$this->entity].
'/'.$oldref;
2167 $dirdest = $conf->propal->multidir_output[$this->entity].
'/'.$newref;
2168 if (!$error && file_exists($dirsource)) {
2169 dol_syslog(get_class($this).
"::validate rename dir ".$dirsource.
" into ".$dirdest);
2170 if (@rename($dirsource, $dirdest)) {
2173 $listoffiles =
dol_dir_list($dirdest,
'files', 1,
'^'.preg_quote($oldref,
'/'));
2174 foreach ($listoffiles as $fileentry) {
2175 $dirsource = $fileentry[
'name'];
2176 $dirdest = preg_replace(
'/^'.preg_quote($oldref,
'/').
'/', $newref, $dirsource);
2177 $dirsource = $fileentry[
'path'].
'/'.$dirsource;
2178 $dirdest = $fileentry[
'path'].
'/'.$dirdest;
2179 @rename($dirsource, $dirdest);
2187 $this->user_validation_id = $user->id;
2188 $this->datev = $now;
2189 $this->date_validation = $now;
2191 $this->db->commit();
2194 $this->db->rollback();
2213 $this->error =
'ErrorBadParameter';
2214 dol_syslog(get_class($this).
"::set_date ".$this->error, LOG_ERR);
2218 if ($user->hasRight(
'propal',
'creer')) {
2223 $sql =
"UPDATE ".MAIN_DB_PREFIX.$this->table_element;
2224 $sql .=
" SET datep = '".$this->db->idate($date).
"'";
2225 $sql .=
" WHERE rowid = ".((int) $this->
id);
2228 $resql = $this->db->query($sql);
2230 $this->errors[] = $this->db->error();
2235 $this->oldcopy = clone $this;
2236 $this->
date = $date;
2237 $this->datep = $date;
2240 if (!$notrigger && empty($error)) {
2242 $result = $this->call_trigger(
'PROPAL_MODIFY', $user);
2250 $this->db->commit();
2253 foreach ($this->errors as $errmsg) {
2254 dol_syslog(__METHOD__.
' Error: '.$errmsg, LOG_ERR);
2255 $this->error .= ($this->error ?
', '.$errmsg : $errmsg);
2257 $this->db->rollback();
2277 if ($user->hasRight(
'propal',
'creer')) {
2282 $sql =
"UPDATE ".MAIN_DB_PREFIX.$this->table_element;
2283 $sql .=
" SET fin_validite = ".($date_end_validity !=
'' ?
"'".$this->db->idate($date_end_validity).
"'" :
'null');
2284 $sql .=
" WHERE rowid = ".((int) $this->
id);
2288 $resql = $this->db->query($sql);
2290 $this->errors[] = $this->db->error();
2296 $this->oldcopy = clone $this;
2297 $this->fin_validite = $date_end_validity;
2300 if (!$notrigger && empty($error)) {
2302 $result = $this->call_trigger(
'PROPAL_MODIFY', $user);
2310 $this->db->commit();
2313 foreach ($this->errors as $errmsg) {
2314 dol_syslog(__METHOD__.
' Error: '.$errmsg, LOG_ERR);
2315 $this->error .= ($this->error ?
', '.$errmsg : $errmsg);
2317 $this->db->rollback();
2351 if ($user->hasRight(
'propal',
'creer')) {
2356 $sql =
"UPDATE ".MAIN_DB_PREFIX.$this->table_element;
2357 $sql .=
" SET date_livraison = ".(isDolTms($delivery_date) ?
"'".$this->db->idate($delivery_date).
"'" :
'null');
2358 $sql .=
" WHERE rowid = ".((int) $this->
id);
2361 $resql = $this->db->query($sql);
2363 $this->errors[] = $this->db->error();
2368 $this->oldcopy = clone $this;
2369 $this->delivery_date = $delivery_date;
2372 if (!$notrigger && empty($error)) {
2374 $result = $this->call_trigger(
'PROPAL_MODIFY', $user);
2382 $this->db->commit();
2385 foreach ($this->errors as $errmsg) {
2386 dol_syslog(__METHOD__.
' Error: '.$errmsg, LOG_ERR);
2387 $this->error .= ($this->error ?
', '.$errmsg : $errmsg);
2389 $this->db->rollback();
2409 if ($user->hasRight(
'propal',
'creer') && $this->status >= self::STATUS_DRAFT) {
2414 $sql =
"UPDATE ".MAIN_DB_PREFIX.$this->table_element;
2415 $sql .=
" SET fk_availability = ".((int) $id);
2416 $sql .=
" WHERE rowid = ".((int) $this->
id);
2418 dol_syslog(__METHOD__.
' availability('.$id.
')', LOG_DEBUG);
2419 $resql = $this->db->query($sql);
2421 $this->errors[] = $this->db->error();
2426 $this->oldcopy = clone $this;
2427 $this->fk_availability = $id;
2428 $this->availability_id = $id;
2431 if (!$notrigger && empty($error)) {
2433 $result = $this->call_trigger(
'PROPAL_MODIFY', $user);
2441 $this->db->commit();
2444 foreach ($this->errors as $errmsg) {
2445 dol_syslog(__METHOD__.
' Error: '.$errmsg, LOG_ERR);
2446 $this->error .= ($this->error ?
', '.$errmsg : $errmsg);
2448 $this->db->rollback();
2452 $error_str =
'Propal status do not meet requirement '.$this->status;
2454 $this->error = $error_str;
2455 $this->errors[] = $this->error;
2472 if ($user->hasRight(
'propal',
'creer') && $this->status >= self::STATUS_DRAFT) {
2477 $sql =
"UPDATE ".MAIN_DB_PREFIX.$this->table_element;
2478 $sql .=
" SET fk_input_reason = ".((int) $id);
2479 $sql .=
" WHERE rowid = ".((int) $this->
id);
2482 $resql = $this->db->query($sql);
2484 $this->errors[] = $this->db->error();
2490 $this->oldcopy = clone $this;
2492 $this->demand_reason_id = $id;
2496 if (!$notrigger && empty($error)) {
2498 $result = $this->call_trigger(
'PROPAL_MODIFY', $user);
2506 $this->db->commit();
2509 foreach ($this->errors as $errmsg) {
2510 dol_syslog(__METHOD__.
' Error: '.$errmsg, LOG_ERR);
2511 $this->error .= ($this->error ?
', '.$errmsg : $errmsg);
2513 $this->db->rollback();
2517 $error_str =
'Propal status do not meet requirement '.$this->status;
2519 $this->error = $error_str;
2520 $this->errors[] = $this->error;
2537 if ($user->hasRight(
'propal',
'creer')) {
2542 $sql =
"UPDATE ".MAIN_DB_PREFIX.$this->table_element;
2543 $sql .=
" SET ref_client = ".(empty($ref_client) ?
'NULL' :
"'".$this->db->escape($ref_client).
"'");
2544 $sql .=
" WHERE rowid = ".((int) $this->
id);
2546 dol_syslog(__METHOD__.
' $this->id='.$this->id.
', ref_client='.$ref_client, LOG_DEBUG);
2547 $resql = $this->db->query($sql);
2549 $this->errors[] = $this->db->error();
2554 $this->oldcopy = clone $this;
2555 $this->ref_customer = $ref_client;
2556 $this->ref_client = $ref_client;
2559 if (!$notrigger && empty($error)) {
2561 $result = $this->call_trigger(
'PROPAL_MODIFY', $user);
2569 $this->db->commit();
2572 foreach ($this->errors as $errmsg) {
2573 dol_syslog(__METHOD__.
' Error: '.$errmsg, LOG_ERR);
2574 $this->error .= ($this->error ?
', '.$errmsg : $errmsg);
2576 $this->db->rollback();
2594 public function reopen($user, $status, $note =
'', $notrigger = 0)
2598 $sql =
"UPDATE ".MAIN_DB_PREFIX.$this->table_element;
2599 $sql .=
" SET fk_statut = ".((int) $status).
",";
2600 if (!empty($note)) {
2601 $sql .=
" note_private = '".$this->db->escape($note).
"',";
2603 $sql .=
" date_cloture=NULL, fk_user_cloture=NULL";
2604 $sql .=
" WHERE rowid = ".((int) $this->
id);
2608 dol_syslog(get_class($this).
"::reopen", LOG_DEBUG);
2609 $resql = $this->db->query($sql);
2612 $this->errors[] =
"Error ".$this->db->lasterror();
2617 $result = $this->call_trigger(
'PROPAL_REOPEN', $user);
2627 if (!empty($this->errors)) {
2628 foreach ($this->errors as $errmsg) {
2629 dol_syslog(get_class($this).
"::update ".$errmsg, LOG_ERR);
2630 $this->error .= ($this->error ?
', '.$errmsg : $errmsg);
2633 $this->db->rollback();
2636 $this->statut = $status;
2639 $this->db->commit();
2654 public function closeProposal($user, $status, $note_private =
'', $notrigger = 0, $note_public =
'')
2656 global $langs,$conf;
2663 $newprivatenote =
dol_concatdesc($this->note_private, $note_private);
2664 $newpublicnote =
dol_concatdesc($this->note_public, $note_public);
2667 $date_signature = $now;
2668 $fk_user_signature = $user->id;
2670 $this->
info($this->
id);
2671 if (!isset($this->date_signature) || $this->date_signature ==
'') {
2672 $date_signature = $now;
2673 $fk_user_signature = $user->id;
2675 $date_signature = $this->date_signature;
2676 $fk_user_signature = $this->user_signature->id;
2680 $sql =
"UPDATE ".MAIN_DB_PREFIX.$this->table_element;
2681 $sql .=
" SET fk_statut = ".((int) $status).
", note_private = '".$this->db->escape($newprivatenote).
"', note_public = '".$this->db->escape($newpublicnote).
"'";
2682 if ($status == self::STATUS_SIGNED) {
2683 $sql .=
", date_signature='".$this->db->idate($now).
"', fk_user_signature = ".($fk_user_signature);
2685 $sql .=
" WHERE rowid = ".((int) $this->
id);
2687 $resql = $this->db->query($sql);
2691 $triggerName =
'PROPAL_CLOSE_REFUSED';
2693 if ($status == self::STATUS_SIGNED) {
2694 $triggerName =
'PROPAL_CLOSE_SIGNED';
2698 $soc =
new Societe($this->db);
2699 $soc->id = $this->socid;
2700 $result = $soc->setAsCustomer();
2703 $this->error = $this->db->lasterror();
2704 $this->db->rollback();
2711 $outputlangs = $langs;
2713 $outputlangs =
new Translate(
"", $conf);
2714 $newlang = (
GETPOST(
'lang_id',
'aZ09') ?
GETPOST(
'lang_id',
'aZ09') : $this->thirdparty->default_lang);
2715 $outputlangs->setDefaultLang($newlang);
2724 $this->
generateDocument($modelpdf, $outputlangs, $hidedetails, $hidedesc, $hideref);
2727 $this->oldcopy = clone $this;
2728 $this->statut = $status;
2730 $this->date_signature = $date_signature;
2731 $this->note_private = $newprivatenote;
2733 if (!$notrigger && empty($error)) {
2735 $result = $this->call_trigger($triggerName, $user);
2743 $this->db->commit();
2746 foreach ($this->errors as $errmsg) {
2747 dol_syslog(__METHOD__.
' Error: '.$errmsg, LOG_ERR);
2748 $this->error .= ($this->error ?
', '.$errmsg : $errmsg);
2750 if (!empty($this->oldcopy)) {
2751 $this->statut = $this->oldcopy->status;
2752 $this->
status = $this->oldcopy->status;
2753 $this->date_signature = $this->oldcopy->date_signature;
2754 $this->note_private = $this->oldcopy->note_private;
2757 $this->db->rollback();
2761 $this->error = $this->db->lasterror();
2762 $this->db->rollback();
2777 global $conf, $langs;
2784 $triggerName =
'PROPAL_CLASSIFY_BILLED';
2790 $sql =
'UPDATE '.MAIN_DB_PREFIX.$this->table_element;
2791 $sql .=
" SET fk_statut = ".self::STATUS_BILLED.
", ";
2792 $sql .=
" note_private = '".$this->db->escape($newprivatenote).
"', date_cloture='".$this->db->idate($now).
"', fk_user_cloture=".((int) $user->id);
2793 $sql .=
' WHERE rowid = '.((int) $this->
id).
' AND fk_statut = '.((int) self::STATUS_SIGNED);
2796 $resql = $this->db->query($sql);
2798 $this->errors[] = $this->db->error();
2801 $num = $this->db->affected_rows($resql);
2809 $outputlangs = $langs;
2811 $outputlangs =
new Translate(
"", $conf);
2812 $newlang = (
GETPOST(
'lang_id',
'aZ09') ?
GETPOST(
'lang_id',
'aZ09') : $this->thirdparty->default_lang);
2813 $outputlangs->setDefaultLang($newlang);
2822 $this->
generateDocument($modelpdf, $outputlangs, $hidedetails, $hidedesc, $hideref);
2825 $this->oldcopy = clone $this;
2828 $this->date_cloture = $now;
2829 $this->note_private = $newprivatenote;
2832 if (!$notrigger && empty($error)) {
2834 $result = $this->call_trigger($triggerName, $user);
2842 $this->db->commit();
2845 foreach ($this->errors as $errmsg) {
2846 dol_syslog(__METHOD__.
' Error: '.$errmsg, LOG_ERR);
2847 $this->error .= ($this->error ?
', '.$errmsg : $errmsg);
2849 $this->db->rollback();
2866 $sql =
"UPDATE ". MAIN_DB_PREFIX . $this->table_element;
2867 $sql .=
" SET fk_statut = " . self::STATUS_CANCELED .
",";
2868 $sql .=
" fk_user_modif = " . ((int) $user->id);
2869 $sql .=
" WHERE rowid = " . ((int) $this->
id);
2871 dol_syslog(get_class($this).
"::cancel", LOG_DEBUG);
2872 if ($this->db->query($sql)) {
2874 $result = $this->call_trigger(
'PROPAL_CANCEL', $user);
2883 $this->db->commit();
2886 foreach ($this->errors as $errmsg) {
2887 dol_syslog(get_class($this).
"::cancel ".$errmsg, LOG_ERR);
2888 $this->error .= ($this->error ?
', '.$errmsg : $errmsg);
2890 $this->db->rollback();
2894 $this->error = $this->db->error();
2895 $this->db->rollback();
2914 if ($this->
status <= self::STATUS_DRAFT) {
2918 dol_syslog(get_class($this).
"::setDraft", LOG_DEBUG);
2922 $sql =
"UPDATE ".MAIN_DB_PREFIX.$this->table_element;
2923 $sql .=
" SET fk_statut = ".self::STATUS_DRAFT;
2924 $sql .=
", online_sign_ip = NULL , online_sign_name = NULL";
2925 $sql .=
" WHERE rowid = ".((int) $this->
id);
2927 $resql = $this->db->query($sql);
2929 $this->errors[] = $this->db->error();
2934 $this->oldcopy = clone $this;
2937 if (!$notrigger && empty($error)) {
2939 $result = $this->call_trigger(
'PROPAL_MODIFY', $user);
2950 $this->db->commit();
2953 foreach ($this->errors as $errmsg) {
2954 dol_syslog(__METHOD__.
' Error: '.$errmsg, LOG_ERR);
2955 $this->error .= ($this->error ?
', '.$errmsg : $errmsg);
2957 $this->db->rollback();
2977 public function liste_array($shortlist = 0, $draft = 0, $notcurrentuser = 0, $socid = 0, $limit = 0, $offset = 0, $sortfield =
'p.datep', $sortorder =
'DESC')
2984 $sql =
"SELECT s.rowid, s.nom as name, s.client,";
2985 $sql .=
" p.rowid as propalid, p.fk_statut, p.total_ht, p.ref, p.remise, ";
2986 $sql .=
" p.datep as dp, p.fin_validite as datelimite";
2987 $sql .=
" FROM ".MAIN_DB_PREFIX.
"societe as s, ".MAIN_DB_PREFIX.$this->table_element.
" as p, ".MAIN_DB_PREFIX.
"c_propalst as c";
2988 $sql .=
" WHERE p.entity IN (".getEntity(
'propal').
")";
2989 $sql .=
" AND p.fk_soc = s.rowid";
2990 $sql .=
" AND p.fk_statut = c.id";
2994 if (empty($user->socid) && !$user->hasRight(
'societe',
'client',
'voir')) {
2995 $search_sale = $user->id;
2998 if ($search_sale && $search_sale !=
'-1') {
2999 if ($search_sale == -2) {
3000 $sql .=
" AND NOT EXISTS (SELECT sc.fk_soc FROM ".MAIN_DB_PREFIX.
"societe_commerciaux as sc WHERE sc.fk_soc = p.fk_soc)";
3001 } elseif ($search_sale > 0) {
3002 $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).
")";
3007 $sql .=
" AND p.fk_soc = ".((int) $socid);
3010 $sql .=
" AND p.fk_statut = ".((int) self::STATUS_DRAFT);
3012 if ($notcurrentuser > 0) {
3013 $sql .=
" AND p.fk_user_author <> ".((int) $user->id);
3015 $sql .= $this->db->order($sortfield, $sortorder);
3016 $sql .= $this->db->plimit($limit, $offset);
3018 $result = $this->db->query($sql);
3020 $num = $this->db->num_rows($result);
3024 $obj = $this->db->fetch_object($result);
3026 if ($shortlist == 1) {
3027 $ga[$obj->propalid] = $obj->ref;
3028 } elseif ($shortlist == 2) {
3029 $ga[$obj->propalid] = $obj->ref.
' ('.$obj->name.
')';
3031 $ga[$i][
'id'] = $obj->propalid;
3032 $ga[$i][
'ref'] = $obj->ref;
3033 $ga[$i][
'name'] = $obj->name;
3067 $linkedInvoices = array();
3070 foreach ($this->linkedObjectsIds as $objecttype => $objectid) {
3073 foreach ($objectid as $key =>
$object) {
3075 if ($objecttype ==
'facture') {
3080 foreach ($this->linkedObjectsIds as $subobjecttype => $subobjectid) {
3081 foreach ($subobjectid as $subkey => $subobject) {
3082 if ($subobjecttype ==
'facture') {
3083 $linkedInvoices[] = $subobject;
3091 if (count($linkedInvoices) > 0) {
3092 $sql =
"SELECT rowid as facid, ref, total_ht as total, datef as df, fk_user_author, fk_statut, paye";
3093 $sql .=
" FROM ".MAIN_DB_PREFIX.
"facture";
3094 $sql .=
" WHERE rowid IN (".$this->db->sanitize(implode(
',', $linkedInvoices)).
")";
3096 dol_syslog(get_class($this).
"::InvoiceArrayList", LOG_DEBUG);
3097 $resql = $this->db->query($sql);
3100 $tab_sqlobj = array();
3101 $nump = $this->db->num_rows($resql);
3102 for ($i = 0; $i < $nump; $i++) {
3103 $sqlobj = $this->db->fetch_object($resql);
3104 $tab_sqlobj[] = $sqlobj;
3106 $this->db->free($resql);
3108 $nump = count($tab_sqlobj);
3112 while ($i < $nump) {
3113 $obj = array_shift($tab_sqlobj);
3136 public function delete($user, $notrigger = 0)
3139 require_once DOL_DOCUMENT_ROOT.
'/core/lib/files.lib.php';
3147 $result = $this->call_trigger(
'PROPAL_DELETE', $user);
3155 if (!$error && !empty($this->table_element_line)) {
3156 $tabletodelete = $this->table_element_line;
3157 $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).
")";
3158 $sql =
"DELETE FROM ".MAIN_DB_PREFIX.$tabletodelete.
" WHERE ".$this->fk_element.
" = ".((int) $this->
id);
3159 if (!$this->db->query($sqlef) || !$this->db->query($sql)) {
3161 $this->error = $this->db->lasterror();
3162 $this->errors[] = $this->error;
3163 dol_syslog(get_class($this).
"::delete error ".$this->error, LOG_ERR);
3188 dol_syslog(get_class($this).
"::delete error ".$this->error, LOG_ERR);
3194 $sql =
"DELETE FROM ".MAIN_DB_PREFIX.$this->table_element.
" WHERE rowid = ".((int) $this->
id);
3195 $res = $this->db->query($sql);
3198 $this->error = $this->db->lasterror();
3199 $this->errors[] = $this->error;
3200 dol_syslog(get_class($this).
"::delete error ".$this->error, LOG_ERR);
3216 if ($conf->propal->multidir_output[$this->entity] && !empty($this->
ref)) {
3217 $dir = $conf->propal->multidir_output[$this->entity].
"/".$ref;
3218 $file = $dir.
"/".$ref.
".pdf";
3219 if (file_exists($file)) {
3223 $this->error =
'ErrorFailToDeleteFile';
3224 $this->errors[] = $this->error;
3225 $this->db->rollback();
3229 if (file_exists($dir)) {
3232 $this->error =
'ErrorFailToDeleteDir';
3233 $this->errors[] = $this->error;
3234 $this->db->rollback();
3242 dol_syslog(get_class($this).
"::delete ".$this->
id.
" by ".$user->id, LOG_DEBUG);
3243 $this->db->commit();
3246 $this->db->rollback();
3263 if ($this->
status >= self::STATUS_DRAFT) {
3268 $sql =
'UPDATE '.MAIN_DB_PREFIX.$this->table_element;
3269 $sql .=
' SET fk_availability = '.((int) $availability_id);
3270 $sql .=
' WHERE rowid='.((int) $this->
id);
3272 dol_syslog(__METHOD__.
' availability('.$availability_id.
')', LOG_DEBUG);
3273 $resql = $this->db->query($sql);
3275 $this->errors[] = $this->db->error();
3280 $this->oldcopy = clone $this;
3281 $this->availability_id = $availability_id;
3284 if (!$notrigger && empty($error)) {
3286 $result = $this->call_trigger(
'PROPAL_MODIFY', $user);
3294 $this->db->commit();
3297 foreach ($this->errors as $errmsg) {
3298 dol_syslog(__METHOD__.
' Error: '.$errmsg, LOG_ERR);
3299 $this->error .= ($this->error ?
', '.$errmsg : $errmsg);
3301 $this->db->rollback();
3305 $error_str =
'Propal status do not meet requirement '.$this->status;
3307 $this->error = $error_str;
3308 $this->errors[] = $this->error;
3327 if ($this->
status >= self::STATUS_DRAFT) {
3332 $sql =
'UPDATE '.MAIN_DB_PREFIX.$this->table_element;
3333 $sql .=
' SET fk_input_reason = '.((int) $demand_reason_id);
3334 $sql .=
' WHERE rowid='.((int) $this->
id);
3336 dol_syslog(__METHOD__.
' demand_reason('.$demand_reason_id.
')', LOG_DEBUG);
3337 $resql = $this->db->query($sql);
3339 $this->errors[] = $this->db->error();
3344 $this->oldcopy = clone $this;
3345 $this->demand_reason_id = $demand_reason_id;
3348 if (!$notrigger && empty($error)) {
3350 $result = $this->call_trigger(
'PROPAL_MODIFY', $user);
3358 $this->db->commit();
3361 foreach ($this->errors as $errmsg) {
3362 dol_syslog(__METHOD__.
' Error: '.$errmsg, LOG_ERR);
3363 $this->error .= ($this->error ?
', '.$errmsg : $errmsg);
3365 $this->db->rollback();
3369 $error_str =
'Propal status do not meet requirement '.$this->status;
3371 $this->error = $error_str;
3372 $this->errors[] = $this->error;
3386 $sql =
"SELECT c.rowid, ";
3387 $sql .=
" c.datec, c.date_valid as datev, c.date_signature, c.date_cloture,";
3388 $sql .=
" c.fk_user_author, c.fk_user_valid, c.fk_user_signature, c.fk_user_cloture";
3389 $sql .=
" FROM ".MAIN_DB_PREFIX.$this->table_element.
" as c";
3390 $sql .=
" WHERE c.rowid = ".((int) $id);
3392 $result = $this->db->query($sql);
3395 if ($this->db->num_rows($result)) {
3396 $obj = $this->db->fetch_object($result);
3398 $this->
id = $obj->rowid;
3400 $this->date_creation = $this->db->jdate($obj->datec);
3401 $this->date_validation = $this->db->jdate($obj->datev);
3402 $this->date_signature = $this->db->jdate($obj->date_signature);
3403 $this->date_cloture = $this->db->jdate($obj->date_cloture);
3405 $this->user_creation_id = $obj->fk_user_author;
3406 $this->user_validation_id = $obj->fk_user_valid;
3408 if ($obj->fk_user_signature) {
3409 $user_signature =
new User($this->db);
3410 $user_signature->fetch($obj->fk_user_signature);
3411 $this->user_signature = $user_signature;
3414 $this->user_closing_id = $obj->fk_user_cloture;
3416 $this->db->free($result);
3445 global $hookmanager;
3448 if (empty($this->labelStatus) || empty($this->labelStatusShort)) {
3450 $langs->load(
"propal");
3451 $this->labelStatus[-1] = $langs->transnoentitiesnoconv(
"PropalStatusCanceled");
3452 $this->labelStatus[0] = $langs->transnoentitiesnoconv(
"PropalStatusDraft");
3453 $this->labelStatus[1] = $langs->transnoentitiesnoconv(
"PropalStatusValidated");
3454 $this->labelStatus[2] = $langs->transnoentitiesnoconv(
"PropalStatusSigned");
3455 $this->labelStatus[3] = $langs->transnoentitiesnoconv(
"PropalStatusNotSigned");
3456 $this->labelStatus[4] = $langs->transnoentitiesnoconv(
"PropalStatusBilled");
3457 $this->labelStatusShort[-1] = $langs->transnoentitiesnoconv(
"PropalStatusCanceledShort");
3458 $this->labelStatusShort[0] = $langs->transnoentitiesnoconv(
"PropalStatusDraftShort");
3459 $this->labelStatusShort[1] = $langs->transnoentitiesnoconv(
"PropalStatusValidatedShort");
3460 $this->labelStatusShort[2] = $langs->transnoentitiesnoconv(
"PropalStatusSignedShort");
3461 $this->labelStatusShort[3] = $langs->transnoentitiesnoconv(
"PropalStatusNotSignedShort");
3462 $this->labelStatusShort[4] = $langs->transnoentitiesnoconv(
"PropalStatusBilledShort");
3466 if ($status == self::STATUS_CANCELED) {
3467 $statusType =
'status9';
3468 } elseif ($status == self::STATUS_DRAFT) {
3469 $statusType =
'status0';
3470 } elseif ($status == self::STATUS_VALIDATED) {
3471 $statusType =
'status1';
3472 } elseif ($status == self::STATUS_SIGNED) {
3473 $statusType =
'status4';
3474 } elseif ($status == self::STATUS_NOTSIGNED) {
3475 $statusType =
'status9';
3476 } elseif ($status == self::STATUS_BILLED) {
3477 $statusType =
'status6';
3480 $parameters = array(
'status' => $status,
'mode' => $mode);
3481 $reshook = $hookmanager->executeHooks(
'LibStatut', $parameters, $this);
3484 return $hookmanager->resPrint;
3487 return dolGetStatus($this->labelStatus[$status], $this->labelStatusShort[$status],
'', $statusType, $mode);
3502 global $conf, $langs, $hookmanager;
3504 $sql =
"SELECT p.rowid, p.ref, p.datec as datec, p.fin_validite as datefin, p.total_ht";
3505 $sql .=
" FROM ".MAIN_DB_PREFIX.$this->table_element.
" as p";
3506 $sql .=
" WHERE p.entity IN (".getEntity(
'propal').
")";
3507 if ($mode ==
'opened') {
3508 $sql .=
" AND p.fk_statut = ".self::STATUS_VALIDATED;
3510 if ($mode ==
'signed') {
3511 $sql .=
" AND p.fk_statut = ".self::STATUS_SIGNED;
3515 if (empty($user->socid) && !$user->hasRight(
'societe',
'client',
'voir')) {
3516 $search_sale = $user->id;
3519 if ($search_sale && $search_sale !=
'-1') {
3520 if ($search_sale == -2) {
3521 $sql .=
" AND NOT EXISTS (SELECT sc.fk_soc FROM ".MAIN_DB_PREFIX.
"societe_commerciaux as sc WHERE sc.fk_soc = p.fk_soc)";
3522 } elseif ($search_sale > 0) {
3523 $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).
")";
3527 $sql .=
" AND p.fk_soc = ".((int) $user->socid);
3530 $parameters = array(
'socid' => $user->socid);
3531 $reshook = $hookmanager->executeHooks(
'printFieldListWhere', $parameters, $this);
3532 $sql .= $hookmanager->resPrint;
3534 $resql = $this->db->query($sql);
3536 $langs->load(
"propal");
3541 $label = $labelShort =
'';
3542 if ($mode ==
'opened') {
3545 $label = $langs->transnoentitiesnoconv(
"PropalsToClose");
3546 $labelShort = $langs->transnoentitiesnoconv(
"ToAcceptRefuse");
3548 if ($mode ==
'signed') {
3551 $label = $langs->trans(
"PropalsToBill");
3552 $labelShort = $langs->trans(
"ToBill");
3556 $response->warning_delay = $delay_warning / 60 / 60 / 24;
3557 $response->label = $label;
3558 $response->labelShort = $labelShort;
3559 $response->url = DOL_URL_ROOT.
'/comm/propal/list.php?search_status='.$status.
'&mainmenu=commercial&leftmenu=propals';
3560 $response->url_late = DOL_URL_ROOT.
'/comm/propal/list.php?search_option=late&mainmenu=commercial&leftmenu=propals&sortfield=p.datep&sortorder=asc';
3564 while ($obj = $this->db->fetch_object($resql)) {
3565 $response->nbtodo++;
3566 $response->total += $obj->total_ht;
3568 if ($mode ==
'opened') {
3569 $datelimit = $this->db->jdate($obj->datefin);
3570 if ($datelimit < ($now - $delay_warning)) {
3571 $response->nbtodolate++;
3580 $this->error = $this->db->error();
3596 global $conf, $langs;
3601 $sql =
"SELECT rowid";
3602 $sql .=
" FROM ".MAIN_DB_PREFIX.
"product";
3603 $sql .=
" WHERE entity IN (".getEntity(
'product').
")";
3604 if (array_key_exists(
'tosell', $param)) {
3605 $sql .=
" AND tosell = ".((int) $param[
'tosell']);
3607 $sql .= $this->db->plimit(100);
3609 $resql = $this->db->query($sql);
3611 $num_prods = $this->db->num_rows($resql);
3613 while ($i < $num_prods) {
3615 $row = $this->db->fetch_row($resql);
3616 $prodids[$i] = $row[0];
3622 $this->
ref =
'SPECIMEN';
3623 $this->ref_customer =
'NEMICEPS';
3624 $this->ref_client =
'NEMICEPS';
3625 $this->specimen = 1;
3627 $this->
date = time();
3628 $this->fin_validite = $this->
date + 3600 * 24 * 30;
3629 $this->cond_reglement_id = 1;
3630 $this->cond_reglement_code =
'RECEP';
3631 $this->mode_reglement_id = 7;
3632 $this->mode_reglement_code =
'CHQ';
3633 $this->availability_id = 1;
3634 $this->availability_code =
'AV_NOW';
3635 $this->demand_reason_id = 1;
3636 $this->demand_reason_code =
'SRC_00';
3637 $this->note_public =
'This is a comment (public)';
3638 $this->note_private =
'This is a comment (private)';
3640 $this->multicurrency_tx = 1;
3646 while ($xnbp < $nbp) {
3648 $line->desc = $langs->trans(
"Description").
" ".$xnbp;
3650 $line->subprice = 100;
3652 $line->localtax1_tx = 0;
3653 $line->localtax2_tx = 0;
3655 $line->total_ht = 50;
3656 $line->total_ttc = 60;
3657 $line->total_tva = 10;
3658 $line->remise_percent = 50;
3660 $line->total_ht = 100;
3661 $line->total_ttc = 120;
3662 $line->total_tva = 20;
3663 $line->remise_percent = 00;
3666 if ($num_prods > 0) {
3667 $prodid = mt_rand(1, $num_prods);
3668 $line->fk_product = $prodids[$prodid];
3669 $line->product_ref =
'SPECIMEN';
3672 $this->lines[$xnbp] = $line;
3674 $this->total_ht += $line->total_ht;
3675 $this->total_tva += $line->total_tva;
3676 $this->total_ttc += $line->total_ttc;
3691 global $user, $hookmanager;
3693 $this->nb = array();
3695 $sql =
"SELECT count(p.rowid) as nb";
3696 $sql .=
" FROM ".MAIN_DB_PREFIX.$this->table_element.
" as p";
3697 $sql .=
" LEFT JOIN ".MAIN_DB_PREFIX.
"societe as s ON p.fk_soc = s.rowid";
3698 $sql .=
" WHERE p.entity IN (".getEntity(
'propal').
")";
3702 if (empty($user->socid) && !$user->hasRight(
'societe',
'client',
'voir')) {
3703 $search_sale = $user->id;
3706 if ($search_sale && $search_sale !=
'-1') {
3707 if ($search_sale == -2) {
3708 $sql .=
" AND NOT EXISTS (SELECT sc.fk_soc FROM ".MAIN_DB_PREFIX.
"societe_commerciaux as sc WHERE sc.fk_soc = p.fk_soc)";
3709 } elseif ($search_sale > 0) {
3710 $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).
")";
3715 $parameters = array();
3716 $hookmanager->executeHooks(
'printFieldListWhere', $parameters, $this);
3717 $sql .= $hookmanager->resPrint;
3718 $resql = $this->db->query($sql);
3721 while ($obj = $this->db->fetch_object($resql)) {
3722 $this->nb[
"proposals"] = $obj->nb;
3724 $this->db->free($resql);
3728 $this->error = $this->db->error();
3741 public function getNextNumRef($soc)
3743 global $conf, $langs;
3744 $langs->load(
"propal");
3748 if (!empty($classname)) {
3751 $file = $classname.
".php";
3754 $dirmodels = array_merge(array(
'/'), (array) $conf->modules_parts[
'models']);
3755 foreach ($dirmodels as $reldir) {
3759 $mybool = ((bool) @include_once $dir.$file) || $mybool;
3767 $obj =
new $classname();
3768 '@phan-var-force ModeleNumRefPropales $obj';
3771 $numref = $obj->getNextValue($soc, $this);
3773 if ($numref !=
"") {
3776 $this->error = $obj->error;
3781 $langs->load(
"errors");
3782 print $langs->trans(
"Error").
" ".$langs->trans(
"ErrorModuleSetupNotComplete", $langs->transnoentitiesnoconv(
"Proposal"));
3795 global $conf, $langs, $user;
3797 $langs->load(
'propal');
3799 $nofetch = !empty($params[
'nofetch']);
3802 return [
'optimize' => $langs->trans(
"Proposal")];
3804 if ($user->hasRight(
'propal',
'lire')) {
3805 $datas[
'picto'] =
img_picto(
'', $this->picto,
'', 0, 0, 0,
'',
'paddingrightonly').
'<u>'.$langs->trans(
"Proposal").
'</u>';
3806 if (isset($this->
status)) {
3807 $datas[
'status'] =
' '.$this->getLibStatut(5);
3809 if (!empty($this->
ref)) {
3810 $datas[
'ref'] =
'<br><b>'.$langs->trans(
'Ref').
':</b> '.$this->ref;
3813 $langs->load(
'companies');
3814 if (empty($this->thirdparty)) {
3817 $datas[
'customer'] =
'<br><b>'.$langs->trans(
'Customer').
':</b> '.$this->thirdparty->getNomUrl(1,
'', 0, 1);
3819 if (!empty($this->ref_customer)) {
3820 $datas[
'refcustomer'] =
'<br><b>'.$langs->trans(
'RefCustomer').
':</b> '.$this->ref_customer;
3823 $langs->load(
'project');
3824 if (is_null($this->project) || (is_object($this->project) && $this->project->isEmpty())) {
3826 if ($res > 0 && $this->project instanceof
Project) {
3827 $datas[
'project'] =
'<br><b>'.$langs->trans(
'Project').
':</b> '.$this->project->getNomUrl(1,
'', 0,
'1');
3831 if (!empty($this->total_ht)) {
3832 $datas[
'amountht'] =
'<br><b>'.$langs->trans(
'AmountHT').
':</b> '.
price($this->total_ht, 0, $langs, 0, -1, -1, $conf->currency);
3834 if (!empty($this->total_tva)) {
3835 $datas[
'vat'] =
'<br><b>'.$langs->trans(
'VAT').
':</b> '.
price($this->total_tva, 0, $langs, 0, -1, -1, $conf->currency);
3837 if (!empty($this->total_ttc)) {
3838 $datas[
'amountttc'] =
'<br><b>'.$langs->trans(
'AmountTTC').
':</b> '.
price($this->total_ttc, 0, $langs, 0, -1, -1, $conf->currency);
3840 if (!empty($this->
date)) {
3841 $datas[
'date'] =
'<br><b>'.$langs->trans(
'Date').
':</b> '.
dol_print_date($this->
date,
'day');
3843 if (!empty($this->date_signature)) {
3844 $datas[
'datesignature'] =
'<br><b>'.$langs->trans(
'DateSigning').
':</b> '.
dol_print_date($this->date_signature,
'day');
3846 if (!empty($this->delivery_date)) {
3847 $datas[
'deliverydate'] =
'<br><b>'.$langs->trans(
'DeliveryDate').
':</b> '.
dol_print_date($this->delivery_date,
'dayhour');
3865 public function getNomUrl($withpicto = 0, $option =
'', $get_params =
'', $notooltip = 0, $save_lastsearch_value = -1, $addlinktonotes = -1)
3867 global $langs, $conf, $user, $hookmanager;
3869 if (!empty($conf->dol_no_mouse_hover)) {
3876 'objecttype' => $this->element,
3877 'option' => $option,
3880 $classfortooltip =
'classfortooltip';
3883 $classfortooltip =
'classforajaxtooltip';
3884 $dataparams =
' data-params="'.dol_escape_htmltag(json_encode($params)).
'"';
3892 if ($user->hasRight(
'propal',
'lire')) {
3893 parse_str($get_params, $query);
3894 $query = array_merge($query, [
'id' => $this->
id]);
3895 if ($option ==
'') {
3896 $baseurl = DOL_URL_ROOT .
'/comm/propal/card.php';
3897 } elseif ($option ==
'compta') {
3898 $baseurl = DOL_URL_ROOT .
'/comm/propal/card.php';
3899 } elseif ($option ==
'expedition') {
3900 $baseurl = DOL_URL_ROOT .
'/expedition/propal.php';
3901 } elseif ($option ==
'document') {
3902 $baseurl = DOL_URL_ROOT .
'/comm/propal/document.php';
3905 if ($option !=
'nolink') {
3907 $add_save_lastsearch_values = ($save_lastsearch_value == 1 ? 1 : 0);
3908 if ($save_lastsearch_value == -1 && isset($_SERVER[
"PHP_SELF"]) && preg_match(
'/list\.php/', $_SERVER[
"PHP_SELF"])) {
3909 $add_save_lastsearch_values = 1;
3911 if ($add_save_lastsearch_values) {
3912 $query = array_merge($query, [
'save_lastsearch_values' => 1]);
3919 if (empty($notooltip) && $user->hasRight(
'propal',
'lire')) {
3921 $label = $langs->trans(
"Proposal");
3922 $linkclose .=
' alt="'.dolPrintHTMLForAttribute($label).
'"';
3924 $linkclose .= ($label ?
' title="'.dolPrintHTMLForAttribute($label).
'"' :
' title="tocomplete"');
3925 $linkclose .= $dataparams.
' class="'.$classfortooltip.
'"';
3928 $linkstart =
'<a href="'.$url.
'"';
3929 $linkstart .= $linkclose.
'>';
3932 $result .= $linkstart;
3934 $result .=
img_object(($notooltip ?
'' : $label), ($this->picto ? $this->picto :
'generic'), (($withpicto != 2) ?
'class="paddingright"' :
''), 0, 0, $notooltip ? 0 : 1);
3936 if ($withpicto != 2) {
3937 $result .= $this->ref;
3939 $result .= $linkend;
3941 if ($addlinktonotes >= 0) {
3944 if ($addlinktonotes == 0) {
3945 if (!empty($this->note_private) || !empty($this->note_public)) {
3946 $txttoshow = $langs->trans(
'ViewPrivateNote');
3948 } elseif ($addlinktonotes == 1) {
3949 if (!empty($this->note_private)) {
3952 } elseif ($addlinktonotes == 2) {
3953 if (!empty($this->note_public)) {
3956 } elseif ($addlinktonotes == 3) {
3957 if ($user->socid > 0) {
3958 if (!empty($this->note_public)) {
3962 if (!empty($this->note_public)) {
3965 if (!empty($this->note_private)) {
3966 if (!empty($txttoshow)) {
3967 $txttoshow .=
'<br><br>';
3975 $result .=
' <span class="note inline-block">';
3976 $result .=
'<a href="'.DOL_URL_ROOT.
'/comm/propal/note.php?id='.$this->
id.
'" class="classfortooltip" title="'.
dol_escape_htmltag($txttoshow).
'">';
3979 $result .=
'</span>';
3984 $hookmanager->initHooks(array($this->element .
'dao'));
3985 $parameters = array(
'id' => $this->
id,
'getnomurl' => &$result);
3986 $reshook = $hookmanager->executeHooks(
'getNomUrl', $parameters, $this, $action);
3988 $result = $hookmanager->resPrint;
3990 $result .= $hookmanager->resPrint;
4003 return $this->
fetch_lines(0, 0, $sqlforgedfilters);
4017 public function generateDocument($modele, $outputlangs, $hidedetails = 0, $hidedesc = 0, $hideref = 0, $moreparams =
null)
4019 $outputlangs->loadLangs(array(
"propale",
"products"));
4024 if ($this->model_pdf) {
4025 $modele = $this->model_pdf;
4031 $modelpath =
"core/modules/propale/doc/";
4033 return $this->
commonGenerateDocument($modelpath, $modele, $outputlangs, $hidedetails, $hidedesc, $hideref, $moreparams);
4081 $selected = (empty($arraydata[
'selected']) ? 0 : $arraydata[
'selected']);
4083 $return =
'<div class="box-flex-item box-flex-grow-zero">';
4084 $return .=
'<div class="info-box info-box-sm">';
4085 $return .=
'<div class="info-box-icon bg-infobox-action">';
4087 $return .=
'</div>';
4088 $return .=
'<div class="info-box-content">';
4089 $return .=
'<span class="info-box-ref inline-block tdoverflowmax150 valignmiddle">' . $this->
getNomUrl() .
'</span>';
4090 if ($selected >= 0) {
4091 $return .=
'<input id="cb'.$this->id.
'" class="flat checkforselect fright" type="checkbox" name="toselect[]" value="'.$this->
id.
'"'.($selected ?
' checked="checked"' :
'').
'>';
4093 if (!empty($arraydata[
'projectlink'])) {
4094 $return .=
'<span class="info-box-ref"> | '.$arraydata[
'projectlink'].
'</span>';
4097 if (is_object($this->thirdparty)) {
4098 $return .=
'<div class="info-box-ref tdoverflowmax150">'.$this->thirdparty->getNomUrl(1).
'</div>';
4100 $return .=
'<span class="info-box-label amount" title="'.$langs->trans(
"AmountHT").
'">'.
price($this->total_ht).
'</span>';
4101 if (!empty($arraydata[
'authorlink'])) {
4102 $return .=
' <span class="info-box-label">'.$arraydata[
'authorlink'].
'</span>';
4104 $return .=
'<br><div class="info-box-status">'.$this->getLibStatut(3).
'</div>';
4105 $return .=
'</div>';
4106 $return .=
'</div>';
4107 $return .=
'</div>';
4123 require_once DOL_DOCUMENT_ROOT.
'/categories/class/categorie.class.php';
4124 return parent::setCategoriesCommon($categories, Categorie::TYPE_PROPOSAL);
if(! $sortfield) if(! $sortorder) $object
Parent class of all other business classes (invoices, contracts, proposals, orders,...
fetch_optionals($rowid=null, $optionsArray=null)
Function to get extra fields of an object into $this->array_options This method is in most cases call...
line_order($renum=false, $rowidorder='ASC', $fk_parent_line=true)
Save a new position (field rang) for details lines.
deleteEcmFiles($mode=0)
Delete related files of object in database.
update_price($exclspec=0, $roundingadjust='auto', $nodatabaseupdate=0, $seller=null)
Update total_ht, total_ttc, total_vat, total_localtax1, total_localtax2 for an object (sum of lines).
add_object_linked($origin=null, $origin_id=null, $f_user=null, $notrigger=0)
Add an object link into llx_element_element.
commonGenerateDocument($modelspath, $modele, $outputlangs, $hidedetails, $hidedesc, $hideref, $moreparams=null)
Common function for all objects extending CommonObject for generating documents.
fetchProject()
Load the project with id $this->fk_project into this->project.
fetch_thirdparty($force_thirdparty_id=0)
Load the third party of object, from id $this->socid or $this->fk_soc, into this->thirdparty.
deleteObjectLinked($sourceid=null, $sourcetype='', $targetid=null, $targettype='', $rowid=0, $f_user=null, $notrigger=0)
Delete all links between an object $this.
setErrorsFromObject($object)
setErrorsFromObject
static isExistingObject($element, $id, $ref='', $ref_ext='')
Check if an object id or ref exists If you don't need or want to instantiate the object and just need...
updateRangOfLine($rowid, $rang)
Update position of line (rang)
checkActiveProductInLines($status='onsale')
Check if all products have the right status (on sale, on buy) called during validation of propal,...
deleteExtraFields()
Delete all extra fields values for the current object.
fetchObjectLinked($sourceid=null, $sourcetype='', $targetid=null, $targettype='', $clause='OR', $alsosametype=1, $orderby='sourcetype', $loadalsoobjects=1)
Fetch array of objects linked to current object (object of enabled modules only).
static commonReplaceThirdparty(DoliDB $dbs, $origin_id, $dest_id, array $tables, $ignoreerrors=0)
Function used to replace a thirdparty id with another one.
static commonReplaceProduct(DoliDB $dbs, $origin_id, $dest_id, array $tables, $ignoreerrors=0)
Function used to replace a product id with another one.
line_max($fk_parent_line=0)
Get max value used for position of line (rang)
insertExtraFields($trigger='', $userused=null)
Add/Update all extra fields values for the current object.
delete_linked_contact($source='', $code='')
Delete all links between an object $this and all its contacts in llx_element_contact.
Class to manage absolute discounts.
Class to manage Dolibarr database access.
static getIdAndTxFromCode($dbs, $code, $date_document=0)
Get id and rate of currency from code.
static getIdFromCode($dbs, $code)
Get id of currency from code.
File of class to manage predefined price products or services by customer.
Class to manage products or services.
Class to manage projects.
Class to manage proposals.
getTooltipContentArray($params)
getTooltipContentArray
const STATUS_DRAFT
Draft status.
set_date($user, $date, $notrigger=0)
Define proposal date.
const STATUS_SIGNED
Signed quote.
getNomUrl($withpicto=0, $option='', $get_params='', $notooltip=0, $save_lastsearch_value=-1, $addlinktonotes=-1)
Return clickable link of object (with eventually picto)
getKanbanView($option='', $arraydata=null)
Return clickable link of object (with eventually picto)
InvoiceArrayList($id)
Returns an array with id and ref of related invoices.
availability($availability_id, $notrigger=0)
Change the delivery time.
const STATUS_NOTSIGNED
Not signed quote.
setDeliveryDate($user, $delivery_date, $notrigger=0)
Set delivery date.
classifyBilled(User $user, $notrigger=0, $note='')
Classify the proposal to status Billed.
getLinesArray($sqlforgedfilters='')
Retrieve an array of proposal lines.
fetch($rowid, $ref='', $ref_ext='', $forceentity=0)
Load a proposal from database.
set_availability($user, $id, $notrigger=0)
Set delivery.
fetch_lines($only_product=0, $loadalsotranslation=0, $sqlforgedfilters='')
Load array lines.
updateline($rowid, $pu, $qty, $remise_percent, $txtva, $txlocaltax1=0.0, $txlocaltax2=0.0, $desc='', $price_base_type='HT', $info_bits=0, $special_code=0, $fk_parent_line=0, $skip_update_total=0, $fk_fournprice=0, $pa_ht=0, $label='', $type=0, $date_start='', $date_end='', $array_options=array(), $fk_unit=null, $pu_ht_devise=0, $notrigger=0, $rang=0)
Update a proposal line.
update(User $user, $notrigger=0)
Update database.
addline( $desc, $pu_ht, $qty, $txtva, $txlocaltax1=0.0, $txlocaltax2=0.0, $fk_product=0, $remise_percent=0.0, $price_base_type='HT', $pu_ttc=0.0, $info_bits=0, $type=0, $rang=-1, $special_code=0, $fk_parent_line=0, $fk_fournprice=0, $pa_ht=0, $label='', $date_start='', $date_end='', $array_options=array(), $fk_unit=null, $origin='', $origin_id=0, $pu_ht_devise=0, $fk_remise_except=0, $noupdateafterinsertline=0)
Add a proposal line into database (linked to product/service or not) The parameters are already suppo...
closeProposal($user, $status, $note_private='', $notrigger=0, $note_public='')
Close/set the commercial proposal to status signed or refused (fill also date signature)
demand_reason($demand_reason_id, $notrigger=0)
Change source demand.
info($id)
Object Proposal Information.
const STATUS_BILLED
Billed or processed quote.
initAsSpecimen($param=array())
Initialise an instance with random values.
static replaceThirdparty(DoliDB $dbs, $origin_id, $dest_id)
Function used to replace a thirdparty id with another one.
getLibStatut($mode=0)
Return label of status of proposal (draft, validated, ...)
const STATUS_CANCELED
Canceled status.
insert_discount($idremise)
Add a discount line into an proposal (as a proposal line) using an existing absolute discount (Consum...
LibStatut($status, $mode=1)
Return label of a status (draft, validated, ...)
valid($user, $notrigger=0)
Set status to validated.
static replaceProduct(DoliDB $db, $origin_id, $dest_id)
Function used to replace a product id with another one.
set_ref_client($user, $ref_client, $notrigger=0)
Set customer reference number.
setDraft($user, $notrigger=0)
Set draft status.
set_echeance($user, $date_end_validity, $notrigger=0)
Define end validity date.
set_demand_reason($user, $id, $notrigger=0)
Set source of demand.
setCategories($categories)
Sets object to supplied categories.
generateDocument($modele, $outputlangs, $hidedetails=0, $hidedesc=0, $hideref=0, $moreparams=null)
Create a document onto disk according to template module.
create($user, $notrigger=0)
Create commercial proposal into database this->ref can be set or empty.
liste_array($shortlist=0, $draft=0, $notcurrentuser=0, $socid=0, $limit=0, $offset=0, $sortfield='p.datep', $sortorder='DESC')
Return list of proposal (eventually filtered on user) into an array.
add_product($idproduct, $qty, $remise_percent=0)
Add line into array ->lines $this->thirdparty should be loaded.
reopen($user, $status, $note='', $notrigger=0)
Reopen the commercial proposal.
deleteLine($lineid, $id=0)
Delete detail line.
__construct($db, $socid=0, $propalid=0)
Constructor.
load_board($user, $mode)
Load indicators for dashboard (this->nbtodo and this->nbtodolate)
setCancel(User $user)
Cancel the proposal.
getInvoiceArrayList()
Returns an array with the numbers of related invoices.
set_date_livraison($user, $delivery_date, $notrigger=0)
Set delivery date.
const STATUS_VALIDATED
Validated status.
loadStateBoard()
Load the indicators this->nb for the state board.
createFromClone(User $user, $socid=0, $forceentity=null, $update_prices=false, $update_desc=false)
Load an object from its id and create a new one in database.
Class to manage commercial proposal lines.
Class to manage third parties objects (customers, suppliers, prospects...)
Class to manage translations.
Class to manage Dolibarr users.
print $langs trans("Ref").' m titre as m m statut as status
Or an array listing all the potential status of the object: array: int of the status => translated la...
dol_delete_file($file, $disableglob=0, $nophperrors=0, $nohook=0, $object=null, $allowdotdot=false, $indexdatabase=1, $nolog=0)
Remove a file or several files with a mask.
dol_delete_dir_recursive($dir, $count=0, $nophperrors=0, $onlysub=0, &$countdeleted=0, $indexdatabase=1, $nolog=0, $level=0)
Remove a directory $dir and its subdirectories (or only files and subdirectories)
dol_dir_list($utf8_path, $types="all", $recursive=0, $filter="", $excludefilter=null, $sortcriteria="name", $sortorder=SORT_ASC, $mode=0, $nohook=0, $relativename="", $donotfollowsymlinks=0, $nbsecondsold=0)
Scan a directory and return a list of files/directories.
dol_delete_preview($object)
Delete all preview files linked to object instance.
dol_now($mode='gmt')
Return date for now.
setEventMessages($mesg, $mesgs, $style='mesgs', $messagekey='', $noduplicate=0, $attop=0)
Set event messages in dol_events session object.
setEntity($currentobject)
Set entity id to use when to create an object.
img_picto($titlealt, $picto, $moreatt='', $pictoisfullpath=0, $srconly=0, $notitle=0, $alt='', $morecss='', $marginleftonlyshort=2, $allowothertags=array())
Show picto whatever it's its name (generic function)
GETPOSTINT($paramname, $method=0)
Return the value of a $_GET or $_POST supervariable, converted into integer.
dolBuildUrl($url, $params=[], $addtoken=false)
Return path of url.
dol_string_nohtmltag($stringtoclean, $removelinefeed=1, $pagecodeto='UTF-8', $strip_tags=0, $removedoublespaces=1)
Clean a string from all HTML tags and entities.
price2num($amount, $rounding='', $option=0)
Function that return a number with universal decimal format (decimal separator is '.
isDolTms($timestamp)
isDolTms check if a timestamp is valid.
img_object($titlealt, $picto, $moreatt='', $pictoisfullpath=0, $srconly=0, $notitle=0, $allowothertags=array())
Show a picto called object_picto (generic function)
setEventMessage($mesgs, $style='mesgs', $noduplicate=0, $attop=0)
Set event message in dol_events session object.
dol_sanitizeFileName($str, $newstr='_', $unaccent=1, $includequotes=0, $allowdash=0)
Clean a string to use it as a file name.
dol_strlen($string, $stringencoding='UTF-8')
Make a strlen call.
price($amount, $form=0, $outlangs='', $trunc=1, $rounding=-1, $forcerounding=-1, $currency_code='')
Function to format a value into an amount for visual output Function used into PDF and HTML pages.
getDolGlobalInt($key, $default=0)
Return a Dolibarr global constant int value.
getLocalTaxesFromRate($vatrate, $local, $buyer, $seller, $firstparamisid=0)
Get type and rate of localtaxes for a particular vat rate/country of a thirdparty.
if(!function_exists( 'dol_getprefix')) dol_include_once($relpath, $classname='')
Make an include_once using default root and alternate root if it fails.
get_default_npr(Societe $thirdparty_seller, Societe $thirdparty_buyer, $idprod=0, $idprodfournprice=0)
Function that returns whether VAT must be recoverable collected VAT (e.g.: VAT NPR in France)
dol_concatdesc($text1, $text2, $forxml=false, $invert=false)
Concat 2 descriptions with a new line between them (second operand after first one with appropriate n...
getDolCurrency()
Return the main currency ('EUR', 'USD', ...)
dolGetStatus($statusLabel='', $statusLabelShort='', $html='', $statusType='status0', $displayMode=0, $url='', $params=array())
Output the badge of a status.
GETPOST($paramname, $check='alphanohtml', $method=0, $filter=null, $options=null, $noreplace=0)
Return value of a param into GET or POST supervariable.
dol_buildpath($path, $type=0, $returnemptyifnotfound=0)
Return path of url or filesystem.
dol_print_date($time, $format='', $tzoutput='auto', $outputlangs=null, $encodetooutput=false, $decorate=0)
Output date in a string format according to outputlangs (or langs if not defined).
getDolGlobalBool($key, $default=false)
Return a Dolibarr global constant boolean value.
dol_print_error($db=null, $error='', $errors=null)
Displays error message system with all the information to facilitate the diagnosis and the escalation...
getDolGlobalString($key, $default='')
Return a Dolibarr global constant string value.
getWarningDelay($module, $parmlevel1, $parmlevel2='')
Return a warning delay You can use it like this: if (getWarningDelay('module', 'paramlevel1')) It rep...
get_default_tva(Societe $thirdparty_seller, Societe $thirdparty_buyer, $idprod=0, $idprodfournprice=0)
Function that return vat rate of a product line (according to seller, buyer and product vat rate) VAT...
get_localtax($vatrate, $local, $thirdparty_buyer=null, $thirdparty_seller=null, $vatnpr=0)
Return localtax rate for a particular VAT rate, when selling a product with vat $vatrate,...
dol_syslog($message, $level=LOG_INFO, $ident=0, $suffixinfilename='', $restricttologhandler='', $logcontext=null)
Write log message into outputs.
getEntity($element, $shared=1, $currentobject=null)
Get list of entity id to use.
dol_escape_htmltag($stringtoescape, $keepb=0, $keepn=0, $noescapetags='', $escapeonlyhtmltags=0, $cleanalsojavascript=0)
Returns text escaped for inclusion in HTML alt or title or value tags, or into values of HTML input f...
getMarginInfos($pv_ht, $remise_percent, $tva_tx, $localtax1_tx, $localtax2_tx, $fk_pa, $pa_ht)
Return an array with margins information of a line.
calcul_price_total($qty, $pu, $remise_percent_ligne, $txtva, $uselocaltax1_rate, $uselocaltax2_rate, $remise_percent_global, $price_base_type, $info_bits, $type, $seller=null, $localtaxes_array=[], $progress=100, $multicurrency_tx=1, $pu_devise=0, $multicurrency_code='')
Calculate totals (net, vat, ...) of a line.
if(getDolGlobalString( 'TAKEPOS_SHOW_CUSTOMER')) print $langs trans('Date')." left Label right Qty right Price right TotalHT right TotalTTC right right right right right right right right right centpercent right TotalHT right n right VAT right n right TotalVAT right n No sujeto a RE IRPF right TotalLT1 right n right TotalLT2 right n right TotalTTC right n takeposcustomercurrency takeposcustomercurrency takeposcustomercurrency takeposcustomercurrency right TotalTTC takeposcustomercurrency right takeposcustomercurrency n right PaymentTypeShortLIQ right SELECT p pos_change as p datep as date