dolibarr 22.0.5
fournisseur.facture-rec.class.php
1<?php
2/* Copyright (C) 2003-2005 Rodolphe Quiedeville <rodolphe@quiedeville.org>
3 * Copyright (C) 2004-2019 Laurent Destailleur <eldy@users.sourceforge.net>
4 * Copyright (C) 2009-2012 Regis Houssin <regis.houssin@inodbox.com>
5 * Copyright (C) 2010-2011 Juanjo Menent <jmenent@2byte.es>
6 * Copyright (C) 2012 Cedric Salvador <csalvador@gpcsolutions.fr>
7 * Copyright (C) 2013 Florian Henry <florian.henry@open-concept.pro>
8 * Copyright (C) 2015 Marcos García <marcosgdf@gmail.com>
9 * Copyright (C) 2017-2024 Frédéric France <frederic.france@free.fr>
10 * Copyright (C) 2024-2025 MDW <mdeweerd@users.noreply.github.com>
11 * Copyright (C) 2023-2024 Nick Fragoulis
12 *
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; either version 3 of the License, or
16 * (at your option) any later version.
17 *
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
22 *
23 * You should have received a copy of the GNU General Public License
24 * along with this program. If not, see <https://www.gnu.org/licenses/>.
25 */
26
33require_once DOL_DOCUMENT_ROOT.'/core/class/notify.class.php';
34require_once DOL_DOCUMENT_ROOT.'/product/class/product.class.php';
35require_once DOL_DOCUMENT_ROOT.'/fourn/class/fournisseur.facture.class.php';
36require_once DOL_DOCUMENT_ROOT.'/fourn/class/fournisseur.facture-rec.ligne.class.php';
37require_once DOL_DOCUMENT_ROOT.'/core/lib/date.lib.php';
38
39
44{
45 const TRIGGER_PREFIX = 'SUPPLIERBILLREC';
49 public $element = 'invoice_supplier_rec';
50
54 public $table_element = 'facture_fourn_rec';
55
59 public $table_element_line = 'facture_fourn_det_rec';
60
64 public $fk_element = 'fk_facture_fourn';
65
69 public $picto = 'bill';
70
74 protected $table_ref_field = 'titre';
75
80 public $titre;
84 public $title;
85
89 public $ref_supplier;
93 public $socid;
94
99 public $fk_soc;
100
104 public $suspended; // status
105
110 public $libelle;
114 public $label;
115
120 public $amount;
125 public $remise;
126
130 public $vat_src_code;
134 public $localtax1;
138 public $localtax2;
139
143 public $user_author;
147 public $user_modif;
151 public $fk_project;
152
156 public $mode_reglement_id;
160 public $mode_reglement_code;
164 public $cond_reglement_code;
168 public $cond_reglement_doc;
172 public $cond_reglement_id;
173
177 public $date_lim_reglement;
178
182 public $usenewprice = 0;
186 public $frequency;
190 public $unit_frequency;
194 public $date_when;
198 public $date_last_gen;
199
203 public $nb_gen_done;
204
208 public $nb_gen_max;
209
213 public $auto_validate; //
217 public $generate_pdf; // 1 to generate PDF on invoice generation (default)
218
223 public $lines = array();
224
225
226 /* Override fields in CommonObject
227 public $entity;
228 public $total_ht;
229 public $total_tva;
230 public $total_ttc;
231 public $fk_account;
232 public $mode_reglement;
233 public $cond_reglement;
234 public $note_public;
235 public $note_private;
236 */
237
262 // BEGIN MODULEBUILDER PROPERTIES
266 public $fields = array(
267 'rowid' => array('type' => 'integer', 'label' => 'TechnicalID', 'enabled' => 1, 'visible' => -1, 'notnull' => 1, 'position' => 10),
268 'titre' => array('type' => 'varchar(100)', 'label' => 'Titre', 'enabled' => 1, 'showoncombobox' => 1, 'visible' => -1, 'position' => 15),
269 'ref_supplier' => array('type' => 'varchar(180)', 'label' => 'RefSupplier', 'enabled' => 1, 'showoncombobox' => 1, 'visible' => -1, 'position' => 20),
270 'entity' => array('type' => 'integer', 'label' => 'Entity', 'default' => '1', 'enabled' => 1, 'visible' => -2, 'notnull' => 1, 'position' => 25, 'index' => 1),
271 'fk_soc' => array('type' => 'integer:Societe:societe/class/societe.class.php', 'label' => 'ThirdParty', 'enabled' => 'isModEnabled("societe")', 'visible' => -1, 'notnull' => 1, 'position' => 30),
272 'datec' => array('type' => 'datetime', 'label' => 'DateCreation', 'enabled' => 1, 'visible' => -1, 'position' => 35),
273 'tms' => array('type' => 'timestamp', 'label' => 'DateModification', 'enabled' => 1, 'visible' => -1, 'notnull' => 1, 'position' => 40),
274 'suspended' => array('type' => 'integer', 'label' => 'Suspended', 'enabled' => 1, 'visible' => -1, 'position' => 225),
275 'libelle' => array('type' => 'varchar(100)', 'label' => 'Libelle', 'enabled' => 1, 'showoncombobox' => 0, 'visible' => -1, 'position' => 15),
276
277 'localtax1' => array('type' => 'double(24,8)', 'label' => 'Localtax1', 'enabled' => 1, 'visible' => -1, 'position' => 60, 'isameasure' => 1),
278 'localtax2' => array('type' => 'double(24,8)', 'label' => 'Localtax2', 'enabled' => 1, 'visible' => -1, 'position' => 65, 'isameasure' => 1),
279 'total_ht' => array('type' => 'double(24,8)', 'label' => 'Total', 'enabled' => 1, 'visible' => -1, 'position' => 70, 'isameasure' => 1),
280 'total_tva' => array('type' => 'double(24,8)', 'label' => 'Tva', 'enabled' => 1, 'visible' => -1, 'position' => 55, 'isameasure' => 1),
281 'total_ttc' => array('type' => 'double(24,8)', 'label' => 'Total ttc', 'enabled' => 1, 'visible' => -1, 'position' => 75, 'isameasure' => 1),
282
283 'fk_user_author' => array('type' => 'integer:User:user/class/user.class.php', 'label' => 'Fk user author', 'enabled' => 1, 'visible' => -1, 'position' => 80),
284 'fk_user_modif' => array('type' => 'integer:User:user/class/user.class.php', 'label' => 'UserModif', 'enabled' => 1, 'visible' => -2, 'notnull' => -1, 'position' => 210),
285 'fk_projet' => array('type' => 'integer:Project:projet/class/project.class.php:1:fk_statut=1', 'label' => 'Fk projet', 'enabled' => "isModEnabled('project')", 'visible' => -1, 'position' => 85),
286 'fk_account' => array('type' => 'integer', 'label' => 'Fk account', 'enabled' => 'isModEnabled("bank")', 'visible' => -1, 'position' => 175),
287 'fk_cond_reglement' => array('type' => 'integer', 'label' => 'Fk cond reglement', 'enabled' => 1, 'visible' => -1, 'position' => 90),
288 'fk_mode_reglement' => array('type' => 'integer', 'label' => 'Fk mode reglement', 'enabled' => 1, 'visible' => -1, 'position' => 95),
289 'date_lim_reglement' => array('type' => 'date', 'label' => 'Date lim reglement', 'enabled' => 1, 'visible' => -1, 'position' => 100),
290
291 'note_private' => array('type' => 'html', 'label' => 'NotePublic', 'enabled' => 1, 'visible' => 0, 'position' => 105),
292 'note_public' => array('type' => 'html', 'label' => 'NotePrivate', 'enabled' => 1, 'visible' => 0, 'position' => 110),
293 'modelpdf' => array('type' => 'varchar(255)', 'label' => 'Modelpdf', 'enabled' => 1, 'visible' => -1, 'position' => 115),
294
295 'fk_multicurrency' => array('type' => 'integer', 'label' => 'Fk multicurrency', 'enabled' => 1, 'visible' => -1, 'position' => 180),
296 'multicurrency_code' => array('type' => 'varchar(255)', 'label' => 'Multicurrency code', 'enabled' => 1, 'visible' => -1, 'position' => 185),
297 'multicurrency_tx' => array('type' => 'double(24,8)', 'label' => 'Multicurrency tx', 'enabled' => 1, 'visible' => -1, 'position' => 190, 'isameasure' => 1),
298 'multicurrency_total_ht' => array('type' => 'double(24,8)', 'label' => 'Multicurrency total ht', 'enabled' => 1, 'visible' => -1, 'position' => 195, 'isameasure' => 1),
299 'multicurrency_total_tva' => array('type' => 'double(24,8)', 'label' => 'Multicurrency total tva', 'enabled' => 1, 'visible' => -1, 'position' => 200, 'isameasure' => 1),
300 'multicurrency_total_ttc' => array('type' => 'double(24,8)', 'label' => 'Multicurrency total ttc', 'enabled' => 1, 'visible' => -1, 'position' => 205, 'isameasure' => 1),
301
302 'usenewprice' => array('type' => 'integer', 'label' => 'UseNewPrice', 'enabled' => 1, 'visible' => 0, 'position' => 155),
303 'frequency' => array('type' => 'integer', 'label' => 'Frequency', 'enabled' => 1, 'visible' => -1, 'position' => 150),
304 'unit_frequency' => array('type' => 'varchar(2)', 'label' => 'Unit frequency', 'enabled' => 1, 'visible' => -1, 'position' => 125),
305
306 'date_when' => array('type' => 'datetime', 'label' => 'Date when', 'enabled' => 1, 'visible' => -1, 'position' => 130),
307 'date_last_gen' => array('type' => 'datetime', 'label' => 'Date last gen', 'enabled' => 1, 'visible' => -1, 'position' => 135),
308 'nb_gen_done' => array('type' => 'integer', 'label' => 'Nb gen done', 'enabled' => 1, 'visible' => -1, 'position' => 140),
309 'nb_gen_max' => array('type' => 'integer', 'label' => 'Nb gen max', 'enabled' => 1, 'visible' => -1, 'position' => 145),
310 'revenuestamp' => array('type' => 'double(24,8)', 'label' => 'RevenueStamp', 'enabled' => 1, 'visible' => -1, 'position' => 160, 'isameasure' => 1),
311 'auto_validate' => array('type' => 'integer', 'label' => 'Auto validate', 'enabled' => 1, 'visible' => -1, 'position' => 165),
312 'generate_pdf' => array('type' => 'integer', 'label' => 'Generate pdf', 'enabled' => 1, 'visible' => -1, 'position' => 170),
313 );
314 // END MODULEBUILDER PROPERTIES
315
316 const STATUS_NOTSUSPENDED = 0;
317 const STATUS_SUSPENDED = 1;
318
319
320
326 public function __construct($db)
327 {
328 $this->db = $db;
329 }
330
340 public function create($user, $facFournId, $notrigger = 0, $onlylines = array())
341 {
342 global $conf;
343
344 $error = 0;
345 $now = dol_now();
346
347 // Clean parameters
348 $this->titre = empty($this->titre) ? '' : $this->titre; // deprecated
349 $this->title = empty($this->title) ? '' : $this->title;
350 $keyforref = $this->table_ref_field;
351 $this->ref = $this->$keyforref;
352
353 $this->ref_supplier = empty($this->ref_supplier) ? '' : $this->ref_supplier;
354
355 $this->usenewprice = empty($this->usenewprice) ? 0 : $this->usenewprice;
356 $this->suspended = empty($this->suspended) ? 0 : $this->suspended;
357 // No frequency defined then no next date to execution
358 if (empty($this->frequency)) {
359 $this->frequency = 0;
360 $this->date_when = null;
361 }
362 $this->frequency = abs($this->frequency);
363 $this->nb_gen_done = 0;
364 $this->nb_gen_max = empty($this->nb_gen_max) ? 0 : $this->nb_gen_max;
365 $this->auto_validate = empty($this->auto_validate) ? 0 : $this->auto_validate;
366 $this->generate_pdf = empty($this->generate_pdf) ? 0 : $this->generate_pdf;
367
368 $this->db->begin();
369
370 // On charge la facture fournisseur depuis laquelle on crée la facture fournisseur modèle
371 $facfourn_src = new FactureFournisseur($this->db);
372 $result = $facfourn_src->fetch($facFournId);
373 if ($result > 0) {
374 $sql = 'INSERT INTO '.MAIN_DB_PREFIX.'facture_fourn_rec (';
375 $sql .= 'titre';
376 $sql .= ", subtype";
377 $sql .= ', ref_supplier';
378 $sql .= ', entity';
379 $sql .= ', fk_soc';
380 $sql .= ', datec';
381 $sql .= ', suspended';
382 $sql .= ', libelle';
383 $sql .= ', total_ttc';
384 $sql .= ', fk_user_author';
385 $sql .= ', fk_projet';
386 $sql .= ', fk_account';
387 $sql .= ', fk_cond_reglement';
388 $sql .= ', fk_mode_reglement';
389 $sql .= ', date_lim_reglement';
390 $sql .= ', note_private';
391 $sql .= ', note_public';
392 $sql .= ', modelpdf';
393 $sql .= ', fk_multicurrency';
394 $sql .= ', multicurrency_code';
395 $sql .= ', multicurrency_tx';
396 $sql .= ', usenewprice';
397 $sql .= ', frequency';
398 $sql .= ', unit_frequency';
399 $sql .= ', date_when';
400 $sql .= ', date_last_gen';
401 $sql .= ', nb_gen_done';
402 $sql .= ', nb_gen_max';
403 $sql .= ', auto_validate';
404 $sql .= ', generate_pdf';
405 $sql .= ') VALUES (';
406 $sql .= "'".$this->db->escape($this->title)."'";
407 $sql .= ", ".($this->subtype ? "'".$this->db->escape((string) $this->subtype)."'" : "null");
408 $sql .= ", '".$this->db->escape($this->ref_supplier)."'";
409 $sql .= ", ".((int) $conf->entity);
410 $sql .= ", ".((int) $facfourn_src->socid);
411 $sql .= ", '".$this->db->idate($now)."'";
412 $sql .= ", ".((int) $this->suspended);
413 $sql .= ", '".$this->db->escape($this->libelle)."'";
414 $sql .= ", " .(!empty($facfourn_src->total_ttc) ? (float) $facfourn_src->total_ttc : '0'); // amount
415 $sql .= ", " .((int) $user->id);
416 $sql .= ", " .(!empty($this->fk_project) ? ((int) $this->fk_project) : 'NULL');
417 $sql .= ", " .(!empty($facfourn_src->fk_account) ? ((int) $facfourn_src->fk_account) : 'NULL');
418 $sql .= ", " .($this->cond_reglement_id > 0 ? (int) $this->cond_reglement_id : 'NULL');
419 $sql .= ", " .($this->mode_reglement_id > 0 ? (int) $this->mode_reglement_id : 'NULL');
420 $sql .= ", ".($facfourn_src->date_echeance > 0 ? "'".$this->db->idate($facfourn_src->date_echeance)."'" : 'NULL'); // date_lim_reglement
421 $sql .= ", " .(!empty($this->note_private) ? "'".$this->db->escape($this->note_private)."'" : 'NULL');
422 $sql .= ", " .(!empty($this->note_public) ? "'".$this->db->escape($this->note_public)."'" : 'NULL');
423 $sql .= ", " .(!empty($this->model_pdf) ? "'".$this->db->escape($this->model_pdf)."'" : 'NULL');
424 $sql .= ", " . (int) $facfourn_src->fk_multicurrency;
425 $sql .= ", '".$this->db->escape($facfourn_src->multicurrency_code)."'";
426 $sql .= ", " . (float) $facfourn_src->multicurrency_tx;
427 $sql .= ", " . (int) $this->usenewprice;
428 $sql .= ", " . (int) $this->frequency;
429 $sql .= ", '".$this->db->escape($this->unit_frequency)."'";
430 $sql .= ", " .(!empty($this->date_when) ? "'".$this->db->idate($this->date_when)."'" : 'NULL');
431 $sql .= ", " .(!empty($this->date_last_gen) ? "'".$this->db->idate($this->date_last_gen)."'" : 'NULL');
432 $sql .= ", " . (int) $this->nb_gen_done;
433 $sql .= ", " . (int) $this->nb_gen_max;
434 $sql .= ", " . (int) $this->auto_validate;
435 $sql .= ", " . (int) $this->generate_pdf;
436 $sql .= ')';
437
438 if ($this->db->query($sql)) {
439 $this->id = $this->db->last_insert_id(MAIN_DB_PREFIX. 'facture_fourn_rec');
440
441 // Fields used into addline later
442 $this->fk_multicurrency = $facfourn_src->fk_multicurrency;
443
444 $this->multicurrency_code = $facfourn_src->multicurrency_code;
445 $this->multicurrency_tx = $facfourn_src->multicurrency_tx;
446
447 // Add lines
448 $num = count($facfourn_src->lines);
449 for ($i = 0; $i < $num; $i++) {
450 $facfourn_line = $facfourn_src->lines[$i];
451 '@phan-var-force SupplierInvoiceLine $facfourn_line';
452 if (!empty($onlylines) && !in_array($facfourn_line->id, $onlylines)) {
453 continue; // Skip unselected lines
454 }
455
456 $tva_tx = $facfourn_line->tva_tx;
457 if (!empty($facfourn_line->vat_src_code) && !preg_match('/\‍(/', (string) $tva_tx)) {
458 $tva_tx .= ' ('.$facfourn_line->vat_src_code.')';
459 }
460
461 $result_insert = $this->addline(
462 $facfourn_line->fk_product,
463 $facfourn_line->ref_supplier,
464 $facfourn_line->product_label,
465 $facfourn_line->desc ? $facfourn_line->desc : $facfourn_line->description,
466 $facfourn_line->pu_ht,
467 $facfourn_line->pu_ttc,
468 $facfourn_line->qty,
469 $facfourn_line->remise_percent,
470 $tva_tx,
471 $facfourn_line->localtax1_tx,
472 $facfourn_line->localtax2_tx,
473 'HT',
474 $facfourn_line->product_type,
475 $facfourn_line->date_start,
476 $facfourn_line->date_end,
477 $facfourn_line->info_bits,
478 $facfourn_line->special_code,
479 $facfourn_line->rang,
480 $facfourn_line->fk_unit
481 );
482
483 if ($result_insert < 0) {
484 $error++;
485 } else {
486 $objectline = new FactureFournisseurLigneRec($this->db);
487
488 $result2 = $objectline->fetch($result_insert);
489 if ($result2 > 0) {
490 // Extrafields
491 if (method_exists($facfourn_line, 'fetch_optionals')) {
492 $facfourn_line->fetch_optionals($facfourn_line->id);
493 $objectline->array_options = $facfourn_line->array_options;
494 }
495
496 $result = $objectline->insertExtraFields();
497 if ($result < 0) {
498 $error++;
499 }
500 } elseif ($result2 < 0) {
501 $this->errors[] = $objectline->error;
502 $error++;
503 }
504 }
505 }
506
507 if (!empty($this->linkedObjectsIds) && empty($this->linked_objects)) { // To use new linkedObjectsIds instead of old linked_objects
508 $this->linked_objects = $this->linkedObjectsIds; // TODO Replace linked_objects with linkedObjectsIds
509 }
510
511 // Add object linked
512 if (!$error && $this->id && !empty($this->linked_objects) && is_array($this->linked_objects)) {
513 foreach ($this->linked_objects as $origin => $tmp_origin_id) {
514 if (is_array($tmp_origin_id)) { // New behaviour, if linked_object can have several links per type, so is something like array('contract'=>array(id1, id2, ...))
515 foreach ($tmp_origin_id as $origin_id) {
516 $ret = $this->add_object_linked($origin, $origin_id);
517 if (!$ret) {
518 $this->error = $this->db->lasterror();
519 $error++;
520 }
521 }
522 } else { // Old behaviour, if linked_object has only one link per type, so is something like array('contract'=>id1))
523 $origin_id = $tmp_origin_id;
524 $ret = $this->add_object_linked($origin, $origin_id);
525 if (!$ret) {
526 $this->error = $this->db->lasterror();
527 $error++;
528 }
529 }
530 }
531 }
532
533 if (!$error) {
534 $result = $this->insertExtraFields();
535 if ($result < 0) {
536 $error++;
537 }
538 }
539
540 if (!$error && !$notrigger) {
541 // Call trigger
542 $result = $this->call_trigger('SUPPLIERBILLREC_CREATE', $user);
543 if ($result < 0) {
544 $this->db->rollback();
545 return -2;
546 }
547 // End call triggers
548 }
549
550 if ($error) {
551 $this->db->rollback();
552 return -3;
553 } else {
554 $this->db->commit();
555 return $this->id;
556 }
557 } else {
558 $this->error = $this->db->lasterror();
559 $this->db->rollback();
560 return -2;
561 }
562 } else {
563 $this->db->rollback();
564 return -1;
565 }
566 }
567
568
576 public function update(User $user, $notrigger = 0)
577 {
578 $error = 0;
579
580 $sql = "UPDATE ".MAIN_DB_PREFIX."facture_fourn_rec SET";
581 $sql .= " titre = '" . (!empty($this->title) ? $this->db->escape($this->title) : "")."'," ;
582 $sql .= " subtype=".(isset($this->subtype) ? $this->db->escape((string) $this->subtype) : "null").",";
583 $sql .= " ref_supplier = '". (!empty($this->ref_supplier) ? $this->db->escape($this->ref_supplier) : "")."',";
584 $sql .= " entity = ". (!empty($this->entity) ? ((int) $this->entity) : 1) . ',';
585 if (!empty($this->socid) && $this->socid > 0) {
586 $sql .= " fk_soc = ". ((int) $this->socid). ',';
587 } elseif (!empty($this->fk_soc) && $this->fk_soc > 0) { // For backward compatibility
588 $sql .= " fk_soc = ". ((int) $this->fk_soc). ',';
589 }
590 $sql .= " suspended = ". (!empty($this->suspended) ? ((int) $this->suspended) : 0) . ',';
591 $sql .= " libelle = ". (!empty($this->libelle) ? "'".$this->db->escape($this->libelle)."'" : 'NULL') . ",";
592 $sql .= " vat_src_code = ". (!empty($this->vat_src_code) ? "'".$this->db->escape($this->vat_src_code)."'" : 'NULL') . ',';
593 $sql .= " localtax1 = ". (!empty($this->localtax1) ? ((float) $this->localtax1) : 0.00) . ',';
594 $sql .= " localtax2 = ". (!empty($this->localtax2) ? ((float) $this->localtax2) : 0.00) . ',';
595 $sql .= " total_ht = ". (!empty($this->total_ht) ? ((float) $this->total_ht) : 0.00) . ',';
596 $sql .= " total_tva = ". (!empty($this->total_tva) ? ((float) $this->total_tva) : 0.00) . ',';
597 $sql .= " total_ttc = ". (!empty($this->total_ttc) ? ((float) $this->total_ttc) : 0.00) . ',';
598 $sql .= " fk_user_modif = ". ((int) $user->id) . ',';
599 $sql .= " fk_projet = ". (!empty($this->fk_project) ? ((int) $this->fk_project) : 'NULL') . ',';
600 $sql .= " fk_account = ". (!empty($this->fk_account) ? ((int) $this->fk_account) : 'NULL') . ',';
601 $sql .= " fk_mode_reglement = ". (!empty($this->mode_reglement_id) ? ((int) $this->mode_reglement_id) : 'NULL') . ',';
602 $sql .= " fk_cond_reglement = ". (!empty($this->cond_reglement_id) ? ((int) $this->cond_reglement_id) : 'NULL') . ',';
603 $sql .= " date_lim_reglement = ". (!empty($this->date_lim_reglement) ? "'".$this->db->idate($this->date_lim_reglement)."'" : 'NULL') . ',';
604 $sql .= " note_private = '". (!empty($this->note_private) ? $this->db->escape($this->note_private) : '') . "',";
605 $sql .= " note_public = '". (!empty($this->note_public) ? $this->db->escape($this->note_public) : '') . "',";
606 $sql .= " modelpdf = ". (!empty($this->model_pdf) ? "'".$this->db->escape($this->model_pdf)."'" : 'NULL') . ",";
607 $sql .= " fk_multicurrency = ". (!empty($this->fk_multicurrency) ? ((int) $this->fk_multicurrency) : 'NULL') . ',';
608 $sql .= " multicurrency_code = ". (!empty($this->multicurrency_code) ? "'".$this->db->escape($this->multicurrency_code)."'" : 'NULL') . ",";
609 $sql .= " multicurrency_tx = ". (!empty($this->multicurrency_tx) ? ((float) $this->multicurrency_tx) : 1) . ',';
610 $sql .= " multicurrency_total_ht = ". (!empty($this->multicurrency_total_ht) ? ((float) $this->multicurrency_total_ht) : 0.00) . ',';
611 $sql .= " multicurrency_total_tva = ". (!empty($this->multicurrency_total_tva) ? ((float) $this->multicurrency_total_tva) : 0.00) . ',';
612 $sql .= " multicurrency_total_ttc = ". (!empty($this->multicurrency_total_ttc) ? ((float) $this->multicurrency_total_ttc) : 0.00) . ',';
613 $sql .= " usenewprice = ". (!empty($this->usenewprice) ? ((int) $this->usenewprice) : 0) . ',';
614 $sql .= " frequency = ". (!empty($this->frequency) ? ((int) $this->frequency) : 0). ',';
615 $sql .= " unit_frequency = '". (!empty($this->unit_frequency) ? $this->db->escape($this->unit_frequency) : ''). "',";
616 $sql .= " date_when = ". (!empty($this->date_when) ? "'".$this->db->idate($this->date_when)."'" : 'NULL') . ',';
617 $sql .= " date_last_gen = ". (!empty($this->date_last_gen) ? "'".$this->db->idate($this->date_last_gen)."'" : 'NULL') . ',';
618 $sql .= " nb_gen_done = ". (!empty($this->nb_gen_done) ? ((int) $this->nb_gen_done) : 0) . ',';
619 $sql .= " nb_gen_max = ". (!empty($this->nb_gen_max) ? ((int) $this->nb_gen_max) : 0) . ',';
620 $sql .= " auto_validate = ". (!empty($this->auto_validate) ? ((int) $this->auto_validate) : 0);
621 $sql .= " WHERE rowid = ". (int) $this->id;
622
623 $this->db->begin();
624
625 dol_syslog(get_class($this)."::update", LOG_DEBUG);
626 $resql = $this->db->query($sql);
627 if ($resql) {
628 if (!$error) {
629 $result = $this->insertExtraFields();
630 if ($result < 0) {
631 $error++;
632 }
633 }
634
635 if (!$error && !$notrigger) {
636 // Call trigger
637 $result = $this->call_trigger('SUPPLIERBILLREC_MODIFY', $user);
638 if ($result < 0) {
639 $this->db->rollback();
640 return -2;
641 }
642 // End call triggers
643 }
644 $this->db->commit();
645 return 1;
646 } else {
647 $this->error = $this->db->lasterror();
648 $this->db->rollback();
649 return -2;
650 }
651 }
652
661 public function fetch($rowid, $ref = '', $ref_ext = '')
662 {
663 $sql = 'SELECT f.rowid, f.titre as title, f.subtype, f.ref_supplier, f.entity, f.fk_soc';
664 $sql .= ', f.datec, f.tms, f.suspended';
665 $sql .= ', f.libelle as label';
666 $sql .= ', f.vat_src_code, f.localtax1, f.localtax2';
667 $sql .= ', f.total_tva, f.total_ht, f.total_ttc';
668 $sql .= ', f.fk_user_author, f.fk_user_modif';
669 $sql .= ', f.fk_projet as fk_project, f.fk_account';
670 $sql .= ', f.fk_mode_reglement, p.code as mode_reglement_code, p.libelle as mode_reglement_libelle';
671 $sql .= ', f.fk_cond_reglement, c.code as cond_reglement_code, c.libelle as cond_reglement_libelle, c.libelle_facture as cond_reglement_libelle_doc';
672 $sql .= ', f.date_lim_reglement';
673 $sql .= ', f.note_private, f.note_public, f.modelpdf as model_pdf';
674 $sql .= ', f.fk_multicurrency, f.multicurrency_code, f.multicurrency_tx, f.multicurrency_total_ht, f.multicurrency_total_tva, f.multicurrency_total_ttc';
675 $sql .= ', f.usenewprice, f.frequency, f.unit_frequency, f.date_when, f.date_last_gen, f.nb_gen_done, f.nb_gen_max, f.auto_validate';
676 $sql .= ', f.generate_pdf';
677 $sql .= ' FROM '.MAIN_DB_PREFIX.'facture_fourn_rec as f';
678 $sql .= ' LEFT JOIN '.MAIN_DB_PREFIX.'c_payment_term as c ON f.fk_cond_reglement = c.rowid';
679 $sql .= ' LEFT JOIN '.MAIN_DB_PREFIX.'c_paiement as p ON f.fk_mode_reglement = p.id';
680 $sql .= ' WHERE f.entity IN ('.getEntity('invoice').')';
681 if ($rowid) {
682 $sql .= ' AND f.rowid='. (int) $rowid;
683 } elseif ($ref) {
684 $sql .= " AND f.titre='".$this->db->escape($ref)."'";
685 } else {
686 $sql .= ' AND f.rowid = 0';
687 }
688
689 $result = $this->db->query($sql);
690 if ($result) {
691 if ($this->db->num_rows($result)) {
692 $obj = $this->db->fetch_object($result);
693
694 $keyforref = $this->table_ref_field;
695
696 $this->id = $obj->rowid;
697 $this->titre = $obj->title;
698 $this->title = $obj->title;
699 $this->subtype = $obj->subtype;
700 $this->ref = $obj->title;
701 $this->ref_supplier = $obj->ref_supplier;
702 $this->entity = $obj->entity;
703 $this->socid = $obj->fk_soc;
704 $this->date_creation = $obj->datec;
705 $this->date_modification = $obj->tms;
706 $this->suspended = $obj->suspended;
707 $this->libelle = $obj->label;
708 $this->label = $obj->label;
709 $this->vat_src_code = $obj->vat_src_code;
710 $this->total_localtax1 = $obj->localtax1;
711 $this->total_localtax2 = $obj->localtax2;
712 $this->total_ht = $obj->total_ht;
713 $this->total_tva = $obj->total_tva;
714 $this->total_ttc = $obj->total_ttc;
715 $this->user_author = $obj->fk_user_author;
716 $this->user_modif = $obj->fk_user_modif;
717 $this->fk_project = $obj->fk_project;
718 $this->fk_account = $obj->fk_account;
719 $this->mode_reglement_id = $obj->fk_mode_reglement;
720 $this->mode_reglement_code = $obj->mode_reglement_code;
721 $this->mode_reglement = $obj->mode_reglement_libelle;
722 $this->cond_reglement_id = $obj->fk_cond_reglement;
723 $this->cond_reglement_code = $obj->cond_reglement_code;
724 $this->cond_reglement = $obj->cond_reglement_libelle;
725 $this->cond_reglement_doc = $obj->cond_reglement_libelle_doc;
726 $this->date_lim_reglement = $this->db->jdate($obj->date_lim_reglement);
727 $this->note_private = $obj->note_private;
728 $this->note_public = $obj->note_public;
729 $this->model_pdf = $obj->model_pdf;
730
731 // Multicurrency
732 $this->fk_multicurrency = $obj->fk_multicurrency;
733 $this->multicurrency_code = $obj->multicurrency_code;
734 $this->multicurrency_tx = $obj->multicurrency_tx;
735 $this->multicurrency_total_ht = $obj->multicurrency_total_ht;
736 $this->multicurrency_total_tva = $obj->multicurrency_total_tva;
737 $this->multicurrency_total_ttc = $obj->multicurrency_total_ttc;
738
739 $this->usenewprice = $obj->usenewprice;
740 $this->frequency = $obj->frequency;
741 $this->unit_frequency = $obj->unit_frequency;
742 $this->date_when = $this->db->jdate($obj->date_when);
743 $this->date_last_gen = $this->db->jdate($obj->date_last_gen);
744 $this->nb_gen_done = $obj->nb_gen_done;
745 $this->nb_gen_max = $obj->nb_gen_max;
746 $this->auto_validate = $obj->auto_validate;
747 $this->generate_pdf = $obj->generate_pdf;
748
749 // Retrieve all extrafield
750 // fetch optionals attributes and labels
751 $this->fetch_optionals();
752
753 /*
754 * Lines
755 */
756 $result = $this->fetch_lines();
757 if ($result < 0) {
758 $this->error = $this->db->lasterror();
759 return -3;
760 }
761 return 1;
762 } else {
763 $this->error = 'Bill with id '.$rowid.' or ref '.$ref.' not found';
764 dol_syslog('Facture::Fetch Error '.$this->error, LOG_ERR);
765 return -2;
766 }
767 } else {
768 $this->error = $this->db->error();
769 return -1;
770 }
771 }
772
773
779 public function getLinesArray()
780 {
781 return $this->fetch_lines();
782 }
783
784 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
790 public function fetch_lines()
791 {
792 // phpcs:enable
793 $this->lines = array();
794
795 // Retrieve all extrafield for line
796 // fetch optionals attributes and labels
797 /*if (!is_object($extrafields)) {
798 require_once DOL_DOCUMENT_ROOT.'/core/class/extrafields.class.php';
799 $extrafields = new ExtraFields($this->db);
800 }
801 $extrafields->fetch_name_optionals_label($this->table_element_line, true);
802 */
803
804 $sql = 'SELECT l.rowid,';
805 $sql .= ' l.fk_facture_fourn, l.fk_parent_line, l.fk_product, l.ref as ref_supplier, l.label, l.description as line_desc,';
806 $sql .= ' l.pu_ht, l.pu_ttc, l.qty, l.remise_percent, l.fk_remise_except, l.vat_src_code, l.tva_tx,';
807 $sql .= ' l.localtax1_tx, l.localtax2_tx, l.localtax1_type, l.localtax2_type,';
808 $sql .= ' l.total_ht, l.total_tva, l.total_ttc, total_localtax1, total_localtax2,';
809 $sql .= ' l.product_type, l.date_start, l.date_end,';
810 $sql .= ' l.info_bits, l.special_code, l.rang,';
811 $sql .= ' l.fk_unit, l.import_key, l.fk_user_author, l.fk_user_modif, l.extraparams,';
812 $sql .= ' l.fk_multicurrency, l.multicurrency_code, l.multicurrency_subprice, l.multicurrency_total_ht, l.multicurrency_total_tva, l.multicurrency_total_ttc,';
813 $sql .= ' p.ref as product_ref, p.fk_product_type as fk_product_type, p.label as product_label, p.description as product_desc';
814 $sql .= ' FROM '.MAIN_DB_PREFIX.'facture_fourn_det_rec as l';
815 $sql .= ' LEFT JOIN '.MAIN_DB_PREFIX.'product as p ON l.fk_product = p.rowid';
816 $sql .= ' WHERE l.fk_facture_fourn = '. (int) $this->id;
817 $sql .= ' ORDER BY l.rang';
818
819 dol_syslog('FactureFournisseurRec::fetch_lines', LOG_DEBUG);
820
821 $result = $this->db->query($sql);
822 if ($result) {
823 $num = $this->db->num_rows($result);
824 $i = 0;
825 while ($i < $num) {
826 $objp = $this->db->fetch_object($result);
827
828 $line = new FactureFournisseurLigneRec($this->db);
829
830 $line->id = $objp->rowid;
831 $line->fk_facture_fourn = $objp->fk_facture_fourn;
832 $line->fk_parent = $objp->fk_parent_line;
833 $line->fk_product = $objp->fk_product;
834 $line->ref = $objp->product_ref; // Ref of product
835 $line->product_ref = $objp->product_ref; // Ref of product
836 $line->product_label = $objp->product_label;
837 $line->product_desc = $objp->product_desc;
838 $line->ref_supplier = $objp->ref_supplier;
839 $line->label = $objp->label;
840 $line->description = $objp->line_desc;
841 $line->desc = $objp->line_desc;
842 $line->pu_ht = $objp->pu_ht;
843 $line->subprice = $objp->pu_ht;
844 $line->pu_ttc = $objp->pu_ttc;
845 $line->qty = $objp->qty;
846 $line->remise_percent = $objp->remise_percent;
847 $line->fk_remise_except = $objp->fk_remise_except;
848 $line->vat_src_code = $objp->vat_src_code;
849 $line->tva_tx = $objp->tva_tx;
850 $line->localtax1_tx = $objp->localtax1_tx;
851 $line->localtax1_type = $objp->localtax1_type;
852 $line->localtax2_tx = $objp->localtax2_tx;
853 $line->localtax2_type = $objp->localtax2_type;
854 $line->total_ht = $objp->total_ht;
855 $line->total_tva = $objp->total_tva;
856 $line->total_localtax1 = $objp->total_localtax1;
857 $line->total_localtax2 = $objp->total_localtax2;
858 $line->total_ttc = $objp->total_ttc;
859 $line->product_type = $objp->product_type;
860 $line->date_start = $this->db->jdate($objp->date_start);
861 $line->date_end = $this->db->jdate($objp->date_end);
862 $line->info_bits = $objp->info_bits ;
863 $line->special_code = $objp->special_code;
864 $line->rang = $objp->rang;
865 $line->fk_unit = $objp->fk_unit;
866 $line->import_key = $objp->import_key;
867 $line->fk_user_author = $objp->fk_user_author;
868 $line->fk_user_modif = $objp->fk_user_modif;
869 $this->extraparams = !empty($objp->extraparams) ? (array) json_decode($objp->extraparams, true) : array();
870 $line->fk_multicurrency = $objp->fk_multicurrency;
871 $line->multicurrency_code = $objp->multicurrency_code;
872 $line->multicurrency_subprice = $objp->multicurrency_subprice;
873 $line->multicurrency_total_ht = $objp->multicurrency_total_ht;
874 $line->multicurrency_total_tva = $objp->multicurrency_total_tva;
875 $line->multicurrency_total_ttc = $objp->multicurrency_total_ttc;
876
877 $line->fetch_optionals();
878
879 $this->lines[$i] = $line;
880
881 $i++;
882 }
883
884 $this->db->free($result);
885 return 1;
886 } else {
887 $this->error = $this->db->lasterror();
888 return -3;
889 }
890 }
891
892
901 public function delete(User $user, $notrigger = 0, $idwarehouse = -1)
902 {
903 $rowid = $this->id;
904
905 dol_syslog(get_class($this)."::delete rowid=".((int) $rowid), LOG_DEBUG);
906
907 $error = 0;
908 $this->db->begin();
909
910 $main = MAIN_DB_PREFIX.'facture_fourn_det_rec';
911 $ef = $main."_extrafields";
912
913 $sqlef = "DELETE FROM ".$ef." WHERE fk_object IN (SELECT rowid FROM ".$main." WHERE fk_facture_fourn = ". (int) $rowid .")";
914 $sql = "DELETE FROM ".MAIN_DB_PREFIX."facture_fourn_det_rec WHERE fk_facture_fourn = ". (int) $rowid;
915
916 if ($this->db->query($sqlef) && $this->db->query($sql)) {
917 $sql = "DELETE FROM ".MAIN_DB_PREFIX."facture_fourn_rec WHERE rowid = ". (int) $rowid;
918 dol_syslog($sql);
919 if ($this->db->query($sql)) {
920 // Delete linked object
921 $res = $this->deleteObjectLinked();
922 if ($res < 0) {
923 $error = -3;
924 }
925 // Delete extrafields
926 $res = $this->deleteExtraFields();
927 if ($res < 0) {
928 $error = -4;
929 }
930 } else {
931 $this->error = $this->db->lasterror();
932 $error = -1;
933 }
934 } else {
935 $this->error = $this->db->lasterror();
936 $error = -2;
937 }
938 if (!$error && !$notrigger) {
939 // Call trigger
940 $result = $this->call_trigger('SUPPLIERBILLREC_DELETE', $user);
941 if ($result < 0) {
942 $error++;
943 }
944 // End call triggers
945 }
946 if (! $error) {
947 $this->db->commit();
948 return 1;
949 } else {
950 $this->db->rollback();
951 return $error;
952 }
953 }
954
981 public function addline($fk_product, $ref, $label, $desc, $pu_ht, $pu_ttc, $qty, $remise_percent, $txtva, $txlocaltax1 = 0, $txlocaltax2 = 0, $price_base_type = 'HT', $type = 0, $date_start = 0, $date_end = 0, $info_bits = 0, $special_code = 0, $rang = -1, $fk_unit = null, $pu_ht_devise = 0)
982 {
983 global $mysoc, $user;
984
985 include_once DOL_DOCUMENT_ROOT.'/core/lib/price.lib.php';
986
987 $facid = $this->id; //Supplier invoice template ID linked to
988
989 dol_syslog(get_class($this)."::addline facid=$facid,desc=$desc,pu_ht=$pu_ht,qty=$qty,txtva=$txtva,txlocaltax1=$txlocaltax1,txlocaltax2=$txlocaltax2,fk_product=$fk_product,remise_percent=$remise_percent,info_bits=$info_bits,price_base_type=$price_base_type,pu_ttc=$pu_ttc,type=$type,fk_unit=$fk_unit,pu_ht_devise=$pu_ht_devise,date_start_fill=$date_start,date_end_fill=$date_end", LOG_DEBUG);
990
991 // Check if object of the line is product or service
992 if ($type < 0) {
993 return -1;
994 }
995
996 $localtaxes_type = getLocalTaxesFromRate($txtva, 0, $this->thirdparty, $mysoc);
997
998 // Clean vat code
999 $reg = array();
1000 $vat_src_code = '';
1001 if (preg_match('/\‍((.*)\‍)/', (string) $txtva, $reg)) {
1002 $vat_src_code = $reg[1];
1003 $txtva = preg_replace('/\s*\‍(.*\‍)/', '', (string) $txtva); // Remove code into vatrate.
1004 }
1005
1006 // Clean parameters
1007 $fk_product = empty($fk_product) ? 0 : $fk_product;
1008 $label = empty($label) ? '' : $label;
1009 $remise_percent = empty($remise_percent) ? 0 : price2num($remise_percent);
1010 $qty = price2num($qty);
1011 $pu_ht = price2num($pu_ht);
1012 $pu_ttc = price2num($pu_ttc);
1013 if (!preg_match('/\‍((.*)\‍)/', $txtva)) {
1014 $txtva = price2num($txtva); // $txtva can have format '5.0(XXX)' or '5'
1015 }
1016 $txlocaltax1 = price2num($txlocaltax1);
1017 $txlocaltax2 = price2num($txlocaltax2);
1018 $txtva = !empty($txtva) ? $txtva : 0;
1019 $txlocaltax1 = !empty($txlocaltax1) ? $txlocaltax1 : 0;
1020 $txlocaltax2 = !empty($txlocaltax2) ? $txlocaltax2 : 0;
1021 $info_bits = !empty($info_bits) ? $info_bits : 0;
1022 $info_bits = !empty($info_bits) ? $info_bits : 0;
1023 $pu = $price_base_type == 'HT' ? $pu_ht : $pu_ttc;
1024
1025 // Calcul du total TTC et de la TVA pour la ligne a partir de qty, pu, remise_percent et txtva
1026 // TRES IMPORTANT: C'est au moment de l'insertion ligne qu'on doit stocker
1027 // la part ht, tva et ttc, et ce au niveau de la ligne qui a son propre taux tva.
1028
1029 $tabprice = calcul_price_total((float) $qty, (float) $pu, $remise_percent, $txtva, $txlocaltax1, $txlocaltax2, 0, $price_base_type, $info_bits, $type, $mysoc, $localtaxes_type, 100, $this->multicurrency_tx, $pu_ht_devise);
1030 $total_ht = $tabprice[0];
1031 $total_tva = $tabprice[1];
1032 $total_ttc = $tabprice[2];
1033 $total_localtax1 = $tabprice[9];
1034 $total_localtax2 = $tabprice[10];
1035 $pu_ht = $tabprice[3];
1036
1037 // MultiCurrency
1038 $multicurrency_total_ht = $tabprice[16];
1039 $multicurrency_total_tva = $tabprice[17];
1040 $multicurrency_total_ttc = $tabprice[18];
1041 $pu_ht_devise = $tabprice[19];
1042
1043 $this->db->begin();
1044 $product_type = $type;
1045 if ($fk_product) {
1046 $product = new Product($this->db);
1047 $result = $product->fetch($fk_product);
1048 if ($result < 0) {
1049 return -1;
1050 }
1051 $product_type = $product->type;
1052 if (empty($label)) {
1053 $label = $product->label;
1054 }
1055 }
1056
1057 $sql = 'INSERT INTO ' . MAIN_DB_PREFIX . 'facture_fourn_det_rec (';
1058 $sql .= 'fk_facture_fourn';
1059 $sql .= ', fk_product';
1060 $sql .= ', ref';
1061 $sql .= ', label';
1062 $sql .= ', description';
1063 $sql .= ', pu_ht';
1064 $sql .= ', pu_ttc';
1065 $sql .= ', qty';
1066 $sql .= ', remise_percent';
1067 $sql .= ', fk_remise_except';
1068 $sql .= ', vat_src_code';
1069 $sql .= ', tva_tx';
1070 $sql .= ', localtax1_tx';
1071 $sql .= ', localtax1_type';
1072 $sql .= ', localtax2_tx';
1073 $sql .= ', localtax2_type';
1074 $sql .= ', total_ht';
1075 $sql .= ', total_tva';
1076 $sql .= ', total_localtax1';
1077 $sql .= ', total_localtax2';
1078 $sql .= ', total_ttc';
1079 $sql .= ', product_type';
1080 $sql .= ', date_start';
1081 $sql .= ', date_end';
1082 $sql .= ', info_bits';
1083 $sql .= ', special_code';
1084 $sql .= ', rang';
1085 $sql .= ', fk_unit';
1086 $sql .= ', fk_user_author';
1087 $sql .= ', fk_multicurrency, multicurrency_code, multicurrency_subprice, multicurrency_total_ht, multicurrency_total_tva, multicurrency_total_ttc';
1088 $sql .= ') VALUES (';
1089 $sql .= ' ' . (int) $facid; // source supplier invoice id
1090 $sql .= ', ' . (!empty($fk_product) ? ((int) $fk_product) : 'null');
1091 $sql .= ', ' . (!empty($ref) ? "'" . $this->db->escape($ref) . "'" : 'null');
1092 $sql .= ', ' . (!empty($label) ? "'" . $this->db->escape($label) . "'" : 'null');
1093 $sql .= ", '" . $this->db->escape($desc) . "'";
1094 $sql .= ', ' . price2num($pu_ht);
1095 $sql .= ', ' . price2num($pu_ttc);
1096 $sql .= ', ' . price2num($qty);
1097 $sql .= ', ' . price2num($remise_percent);
1098 $sql .= ', null';
1099 $sql .= ", '" . $this->db->escape($vat_src_code) . "'";
1100 $sql .= ', ' . price2num($txtva);
1101 $sql .= ', ' . price2num($txlocaltax1);
1102 $sql .= ", '" . $this->db->escape(isset($localtaxes_type[0]) ? $localtaxes_type[0] : '') . "'";
1103 $sql .= ', ' . price2num($txlocaltax2);
1104 $sql .= ", '" . $this->db->escape(isset($localtaxes_type[2]) ? $localtaxes_type[2] : '') . "'";
1105 $sql .= ', ' . price2num($total_ht);
1106 $sql .= ', ' . price2num($total_tva);
1107 $sql .= ', ' . price2num($total_localtax1);
1108 $sql .= ', ' . price2num($total_localtax2);
1109 $sql .= ', ' . price2num($total_ttc);
1110 $sql .= ', ' . (int) $product_type;
1111 $sql .= ', ' . ($date_start > 0 ? (int) $date_start : 'NULL');
1112 $sql .= ', ' . ($date_end > 0 ? (int) $date_end : 'NULL');
1113 $sql .= ', ' . (int) $info_bits;
1114 $sql .= ', ' . (int) $special_code;
1115 $sql .= ', ' . (int) $rang;
1116 $sql .= ', ' . ($fk_unit ? (int) $fk_unit : 'NULL');
1117 $sql .= ', ' . (int) $user->id;
1118 $sql .= ', ' . (int) $this->fk_multicurrency;
1119 $sql .= ", '" . $this->db->escape($this->multicurrency_code) . "'";
1120 $sql .= ', ' . price2num($pu_ht_devise, 'CU');
1121 $sql .= ', ' . price2num($multicurrency_total_ht, 'CT');
1122 $sql .= ', ' . price2num($multicurrency_total_tva, 'CT');
1123 $sql .= ', ' . price2num($multicurrency_total_ttc, 'CT');
1124 $sql .= ')';
1125
1126 dol_syslog(get_class($this). '::addline', LOG_DEBUG);
1127 if ($this->db->query($sql)) {
1128 $lineId = $this->db->last_insert_id(MAIN_DB_PREFIX. 'facture_fourn_det_rec');
1129 $this->update_price();
1130 $this->id = $facid;
1131 $this->db->commit();
1132 return $lineId;
1133 } else {
1134 $this->db->rollback();
1135 $this->error = $this->db->lasterror();
1136
1137 return -1;
1138 }
1139 }
1140
1168 public function updateline($rowid, $fk_product, $ref, $label, $desc, $pu_ht, $qty, $remise_percent, $txtva, $txlocaltax1 = 0, $txlocaltax2 = 0, $price_base_type = 'HT', $type = 0, $date_start = 0, $date_end = 0, $info_bits = 0, $special_code = 0, $rang = -1, $fk_unit = null, $pu_ht_devise = 0, $pu_ttc = 0)
1169 {
1170 global $mysoc, $user;
1171
1172 $facid = $this->id;
1173
1174 dol_syslog(get_class($this). '::updateline facid=' .$facid." rowid=$rowid, desc=$desc, pu_ht=$pu_ht, qty=$qty, txtva=$txtva, txlocaltax1=$txlocaltax1, txlocaltax2=$txlocaltax2, fk_product=$fk_product, remise_percent=$remise_percent, info_bits=$info_bits, price_base_type=$price_base_type, pu_ttc=$pu_ttc, type=$type, fk_unit=$fk_unit, pu_ht_devise=$pu_ht_devise", LOG_DEBUG);
1175 include_once DOL_DOCUMENT_ROOT.'/core/lib/price.lib.php';
1176
1177 // Check parameters
1178 if ($type < 0) {
1179 return -1;
1180 }
1181
1182 // Clean parameters
1183 $fk_product = empty($fk_product) ? 0 : $fk_product;
1184 $label = empty($label) ? '' : $label;
1185 $remise_percent = empty($remise_percent) ? 0 : price2num($remise_percent);
1186 $qty = price2num($qty);
1187 $info_bits = empty($info_bits) ? 0 : $info_bits;
1188 $pu_ht = price2num($pu_ht);
1189 $pu_ttc = price2num($pu_ttc);
1190 $pu_ht_devise = price2num($pu_ht_devise);
1191
1192 if (!preg_match('/\‍((.*)\‍)/', (string) $txtva)) {
1193 $txtva = price2num($txtva); // $txtva can have format '5.0(XXX)' or '5'
1194 }
1195
1196 $txlocaltax1 = empty($txlocaltax1) ? 0 : price2num($txlocaltax1);
1197 $txlocaltax2 = empty($txlocaltax2) ? 0 : price2num($txlocaltax2);
1198 $this->multicurrency_total_ht = empty($this->multicurrency_total_ht) ? 0 : $this->multicurrency_total_ht;
1199 $this->multicurrency_total_tva = empty($this->multicurrency_total_tva) ? 0 : $this->multicurrency_total_tva;
1200 $this->multicurrency_total_ttc = empty($this->multicurrency_total_ttc) ? 0 : $this->multicurrency_total_ttc;
1201
1202 $pu = ($price_base_type == 'HT' ? $pu_ht : $pu_ttc);
1203
1204
1205 // Calculate total with, without tax and tax from qty, pu, remise_percent and txtva
1206 // TRES IMPORTANT: C'est au moment de l'insertion ligne qu'on doit stocker
1207 // la part ht, tva et ttc, et ce au niveau de la ligne qui a son propre taux tva.
1208
1209 $localtaxes_type = getLocalTaxesFromRate($txtva, 0, $this->thirdparty, $mysoc);
1210
1211 // Clean vat code
1212 $vat_src_code = '';
1213 $reg = array();
1214 if (preg_match('/\‍((.*)\‍)/', $txtva, $reg)) {
1215 $vat_src_code = $reg[1];
1216 $txtva = preg_replace('/\s*\‍(.*\‍)/', '', $txtva); // Remove code into vatrate.
1217 }
1218
1219 $tabprice = calcul_price_total((float) $qty, (float) $pu, $remise_percent, $txtva, $txlocaltax1, $txlocaltax2, 0, $price_base_type, $info_bits, $type, $mysoc, $localtaxes_type, 100, $this->multicurrency_tx, (float) $pu_ht_devise);
1220
1221 $total_ht = $tabprice[0];
1222 $total_tva = $tabprice[1];
1223 $total_ttc = $tabprice[2];
1224 $total_localtax1 = $tabprice[9];
1225 $total_localtax2 = $tabprice[10];
1226 $pu_ht = $tabprice[3];
1227 $pu_tva = $tabprice[4];
1228 $pu_ttc = $tabprice[5];
1229
1230 // MultiCurrency
1231 $multicurrency_total_ht = $tabprice[16];
1232 $multicurrency_total_tva = $tabprice[17];
1233 $multicurrency_total_ttc = $tabprice[18];
1234 $pu_ht_devise = $tabprice[19];
1235
1236 $product_type = $type;
1237 if ($fk_product) {
1238 $product = new Product($this->db);
1239 $result = $product->fetch($fk_product);
1240 $product_type = $product->type;
1241 }
1242
1243 $sql = 'UPDATE ' . MAIN_DB_PREFIX . 'facture_fourn_det_rec SET';
1244 $sql .= ' fk_facture_fourn = ' . ((int) $facid);
1245 $sql .= ', fk_product = ' . ($fk_product > 0 ? ((int) $fk_product) : 'null');
1246 $sql .= ", ref = '" . $this->db->escape($ref) . "'";
1247 $sql .= ", label = '" . $this->db->escape($label) . "'";
1248 $sql .= ", description = '" . $this->db->escape($desc) . "'";
1249 $sql .= ', pu_ht = ' . price2num($pu_ht);
1250 $sql .= ', qty = ' . price2num($qty);
1251 $sql .= ", remise_percent = '" . price2num($remise_percent) . "'";
1252 $sql .= ", vat_src_code = '" . $this->db->escape($vat_src_code) . "'";
1253 $sql .= ', tva_tx = ' . price2num($txtva);
1254 $sql .= ', localtax1_tx = ' . (float) $txlocaltax1;
1255 $sql .= ", localtax1_type = '" . $this->db->escape($localtaxes_type[0]) . "'";
1256 $sql .= ', localtax2_tx = ' . (float) $txlocaltax2;
1257 $sql .= ", localtax2_type = '" . $this->db->escape($localtaxes_type[2]) . "'";
1258 $sql .= ", total_ht = '" . price2num($total_ht) . "'";
1259 $sql .= ", total_tva = '" . price2num($total_tva) . "'";
1260 $sql .= ", total_localtax1 = '" . price2num($total_localtax1) . "'";
1261 $sql .= ", total_localtax2 = '" . price2num($total_localtax2) . "'";
1262 $sql .= ", total_ttc = '" . price2num($total_ttc) . "'";
1263 $sql .= ', product_type = ' . (int) $product_type;
1264 $sql .= ', date_start = ' . (empty($date_start) ? 'NULL' : (int) $date_start);
1265 $sql .= ', date_end = ' . (empty($date_end) ? 'NULL' : (int) $date_end);
1266 $sql .= ', info_bits = ' . (int) $info_bits;
1267 $sql .= ', special_code = ' . (int) $special_code;
1268 $sql .= ', rang = ' . (int) $rang;
1269 $sql .= ', fk_unit = ' . ($fk_unit ? "'" . $this->db->escape($fk_unit) . "'" : 'null');
1270 $sql .= ', fk_user_modif = ' . (int) $user;
1271 $sql .= ', multicurrency_subprice = '.price2num($pu_ht_devise);
1272 $sql .= ', multicurrency_total_ht = '.price2num($multicurrency_total_ht);
1273 $sql .= ', multicurrency_total_tva = '.price2num($multicurrency_total_tva);
1274 $sql .= ', multicurrency_total_ttc = '.price2num($multicurrency_total_ttc);
1275 $sql .= ' WHERE rowid = ' . (int) $rowid;
1276
1277 dol_syslog(get_class($this). '::updateline', LOG_DEBUG);
1278 if ($this->db->query($sql)) {
1279 $this->id = $facid;
1280 $this->update_price();
1281 return 1;
1282 } else {
1283 $this->error = $this->db->lasterror();
1284 return -1;
1285 }
1286 }
1287
1288
1296 public function getNextNumRef($soc, $mode = 'next')
1297 {
1298 // Not used for recurring invoices
1299 return '';
1300 }
1301
1307 public function getNextDate()
1308 {
1309 if (empty($this->date_when)) {
1310 return false;
1311 }
1312 return dol_time_plus_duree((int) $this->date_when, $this->frequency, $this->unit_frequency, 1);
1313 }
1314
1320 public function isMaxNbGenReached()
1321 {
1322 $ret = false;
1323 if ($this->nb_gen_max > 0 && ($this->nb_gen_done >= $this->nb_gen_max)) {
1324 $ret = true;
1325 }
1326 return $ret;
1327 }
1328
1335 public function strikeIfMaxNbGenReached($ret)
1336 {
1337 // Special case to strike the date
1338 return ($this->isMaxNbGenReached() ? '<strike>' : '').$ret.($this->isMaxNbGenReached() ? '</strike>' : '');
1339 }
1340
1351 public function createRecurringInvoices($restrictioninvoiceid = 0, $forcevalidation = 0)
1352 {
1353 global $conf, $langs, $db, $user, $hookmanager;
1354
1355 $error = 0;
1356 $nb_create = 0;
1357
1358 // Load translation files required by the page
1359 $langs->loadLangs(array('main', 'bills'));
1360
1361 $now = dol_now();
1362 $tmparray = dol_getdate($now);
1363 $today = dol_mktime(23, 59, 59, $tmparray['mon'], $tmparray['mday'], $tmparray['year']); // Today is last second of current day
1364
1365 dol_syslog('createRecurringInvoices restrictioninvoiceid=' .$restrictioninvoiceid. ' forcevalidation=' .$forcevalidation);
1366
1367 $sql = 'SELECT rowid FROM '.MAIN_DB_PREFIX.'facture_fourn_rec';
1368 $sql .= ' WHERE frequency > 0'; // A recurring supplier invoice is an invoice with a frequency
1369 $sql .= " AND (date_when IS NULL OR date_when <= '".$this->db->idate($today)."')";
1370 $sql .= ' AND (nb_gen_done < nb_gen_max OR nb_gen_max = 0)';
1371 $sql .= ' AND suspended = 0';
1372 $sql .= ' AND entity = '. (int) $conf->entity; // MUST STAY = $conf->entity here
1373 if ($restrictioninvoiceid > 0) {
1374 $sql .= ' AND rowid = '. (int) $restrictioninvoiceid;
1375 }
1376 $sql .= $this->db->order('entity', 'ASC');
1377 if (getDolGlobalInt('NB_REC_FACT_GEN_BY_CALL')) {
1378 $sql .= $this->db->plimit(getDolGlobalInt('NB_REC_FACT_GEN_BY_CALL'));
1379 }
1380 //print $sql;exit;
1381 $parameters = array(
1382 'restrictioninvoiceid' => $restrictioninvoiceid,
1383 'forcevalidation' => $forcevalidation,
1384 );
1385 $reshook = $hookmanager->executeHooks('beforeCreationOfRecurringInvoices', $parameters, $sql); // note that $sql might be modified by hooks
1386
1387 $resql = $this->db->query($sql);
1388 if ($resql) {
1389 $i = 0;
1390 $num = $this->db->num_rows($resql);
1391
1392 if ($num) {
1393 $this->output .= $langs->trans('FoundXQualifiedRecurringInvoiceTemplate', $num)."\n";
1394 } else {
1395 $this->output .= $langs->trans('NoQualifiedRecurringInvoiceTemplateFound');
1396 }
1397
1398 $saventity = $conf->entity;
1399 $laststep = "None";
1400
1401 while ($i < $num) { // Loop on each template invoice. If $num = 0, test is false at first pass.
1402 $line = $this->db->fetch_object($resql);
1403
1404 $this->db->begin();
1405
1406 $invoiceidgenerated = 0;
1407
1408 $new_fac_fourn = null;
1409 $facturerec = new FactureFournisseurRec($this->db);
1410 $laststep = "Fetch {$line->rowid}";
1411 $facturerec->fetch($line->rowid);
1412
1413 if ($facturerec->id > 0) {
1414 // Set entity context
1415 $conf->entity = $facturerec->entity;
1416
1417 dol_syslog('createRecurringInvoices Process invoice template id=' .$facturerec->id. ', ref=' .$facturerec->ref. ', entity=' .$facturerec->entity);
1418
1419 $new_fac_fourn = new FactureFournisseur($this->db);
1420 $new_fac_fourn->fac_rec = $facturerec->id; // We will create $facture from this recurring invoice
1421 $new_fac_fourn->fk_fac_rec_source = $facturerec->id; // We will create $facture from this recurring invoice
1422
1423 $new_fac_fourn->type = self::TYPE_STANDARD;
1424 $new_fac_fourn->subtype = $facturerec->subtype;
1425 $new_fac_fourn->statut = self::STATUS_DRAFT; // deprecated
1426 $new_fac_fourn->status = self::STATUS_DRAFT;
1427 $new_fac_fourn->date = empty($facturerec->date_when) ? $now : $facturerec->date_when; // We could also use dol_now here but we prefer date_when so invoice has real date when we would like even if we generate later.
1428 $new_fac_fourn->socid = $facturerec->socid;
1429 $new_fac_fourn->lines = $facturerec->lines;
1430 $new_fac_fourn->ref_supplier = $facturerec->ref_supplier;
1431 $new_fac_fourn->model_pdf = $facturerec->model_pdf;
1432 $new_fac_fourn->fk_project = $facturerec->fk_project;
1433 $new_fac_fourn->label = $facturerec->label;
1434 $new_fac_fourn->libelle = $facturerec->label; // deprecated
1435
1436 $invoiceidgenerated = $new_fac_fourn->create($user);
1437 $laststep = "Create invoiceidgenerated $invoiceidgenerated";
1438 if ($invoiceidgenerated <= 0) {
1439 $this->errors = $new_fac_fourn->errors;
1440 $this->error = $new_fac_fourn->error;
1441 $error++;
1442 }
1443 if (!$error && ($facturerec->auto_validate || $forcevalidation)) {
1444 $result = $new_fac_fourn->validate($user);
1445 $laststep = "Validate by user {$user->login}";
1446 if ($result <= 0) {
1447 $this->errors = $new_fac_fourn->errors;
1448 $this->error = $new_fac_fourn->error;
1449 $error++;
1450 }
1451 }
1452
1453 if (!$error && $facturerec->generate_pdf) {
1454 // We refresh the object in order to have all necessary data (like date_lim_reglement)
1455 $laststep = "Refresh ".$new_fac_fourn->id;
1456 $new_fac_fourn->fetch($new_fac_fourn->id);
1457 $laststep = "GenerateDocument ".$new_fac_fourn->id;
1458 $result = $new_fac_fourn->generateDocument($facturerec->model_pdf, $langs);
1459 if ($result < 0) {
1460 $this->errors = $new_fac_fourn->errors;
1461 $this->error = $new_fac_fourn->error;
1462 $error++;
1463 }
1464 }
1465 } else {
1466 $error++;
1467 $this->error = 'Failed to load invoice template with id=' .$line->rowid. ', entity=' .$conf->entity."\n";
1468 $this->errors[] = 'Failed to load invoice template with id=' .$line->rowid. ', entity=' .$conf->entity;
1469 dol_syslog('createRecurringInvoices Failed to load invoice template with id=' .$line->rowid. ', entity=' .$conf->entity);
1470 }
1471
1472 if (!$error && $invoiceidgenerated >= 0) {
1473 $facturerec->nb_gen_done++;
1474 $facturerec->date_last_gen = dol_now();
1475 $nextDate = $facturerec->getNextDate();
1476 $facturerec->date_when = (($nextDate === false) ? null : $nextDate);
1477 $facturerec->update($user);
1478 $this->db->commit('createRecurringInvoices Process invoice template id=' .$facturerec->id. ', title=' .$facturerec->title);
1479 dol_syslog('createRecurringInvoices Process invoice template ' .$facturerec->title. ' is finished with a success generation');
1480 $nb_create++;
1481 $this->output .= $langs->trans('InvoiceGeneratedFromTemplate', $new_fac_fourn->ref, $facturerec->title)."\n";
1482 } else {
1483 $this->db->rollback('createRecurringInvoices Process invoice template error='.$error.' invoiceidgenerated='.$invoiceidgenerated.' LastStep='.$laststep.' id=' .$facturerec->id. ', title=' .$facturerec->title);
1484 }
1485
1486 $parameters = array(
1487 'cpt' => $i,
1488 'total' => $num,
1489 'errorCount' => $error,
1490 'invoiceidgenerated' => $invoiceidgenerated,
1491 'facturerec' => $facturerec, // it's an object which PHP passes by "reference", so modifiable by hooks.
1492 'this' => $this, // it's an object which PHP passes by "reference", so modifiable by hooks.
1493 );
1494 // @phan-suppress-next-line PhanTypeMismatchArgumentNullable
1495 $reshook = $hookmanager->executeHooks('afterCreationOfRecurringInvoice', $parameters, $new_fac_fourn); // note: $facture can be modified by hooks (warning: $facture can be null)
1496
1497 $i++;
1498 }
1499
1500 $conf->entity = $saventity; // Restore entity context
1501 } else {
1502 dol_print_error($this->db);
1503 }
1504
1505 $this->output = trim($this->output);
1506
1507 return $error ? $error : 0;
1508 }
1509
1522 public function getNomUrl($withpicto = 0, $option = '', $max = 0, $short = 0, $moretitle = '', $notooltip = 0, $save_lastsearch_value = -1)
1523 {
1524 global $langs, $hookmanager;
1525
1526 $result = '';
1527
1528 $label = '<u>'.$langs->trans('RepeatableInvoice').'</u>';
1529 if (!empty($this->ref)) {
1530 $label .= '<br><b>'.$langs->trans('Ref').':</b> '.$this->ref;
1531 }
1532 if ($this->frequency > 0) {
1533 $label .= '<br><b>'.$langs->trans('Frequency').':</b> '.$langs->trans('FrequencyPer_'.$this->unit_frequency, $this->frequency);
1534 }
1535 if (!empty($this->date_last_gen)) {
1536 $label .= '<br><b>'.$langs->trans('DateLastGeneration').':</b> '.dol_print_date($this->date_last_gen, 'dayhour');
1537 }
1538 if ($this->frequency > 0) {
1539 if (!empty($this->date_when)) {
1540 $label .= '<br><b>'.$langs->trans('NextDateToExecution').':</b> ';
1541 $label .= (empty($this->suspended) ? '' : '<strike>').dol_print_date($this->date_when, 'day').(empty($this->suspended) ? '' : '</strike>'); // No hour for this property
1542 if (!empty($this->suspended)) {
1543 $label .= ' ('.$langs->trans('Disabled').')';
1544 }
1545 }
1546 }
1547
1548 $url = DOL_URL_ROOT.'/fourn/facture/card-rec.php?facid='.$this->id;
1549
1550 if ($short) {
1551 return $url;
1552 }
1553
1554 if ($option != 'nolink') {
1555 // Add param to save lastsearch_values or not
1556 $add_save_lastsearch_values = ($save_lastsearch_value == 1 ? 1 : 0);
1557 if ($save_lastsearch_value == -1 && preg_match('/list\.php/', $_SERVER['PHP_SELF'])) {
1558 $add_save_lastsearch_values = 1;
1559 }
1560 if ($add_save_lastsearch_values) {
1561 $url .= '&save_lastsearch_values=1';
1562 }
1563 }
1564
1565 $linkstart = '<a href="'.$url.'" title="'.dol_escape_htmltag($label, 1).'" class="classfortooltip">';
1566 $linkend = '</a>';
1567
1568 $result .= $linkstart;
1569 if ($withpicto) {
1570 $result .= img_object(($notooltip ? '' : $label), ($this->picto ? $this->picto : 'generic'), ($notooltip ? (($withpicto != 2) ? 'class="paddingright"' : '') : 'class="'.(($withpicto != 2) ? 'paddingright ' : '').'classfortooltip"'), 0, 0, $notooltip ? 0 : 1);
1571 }
1572 if ($withpicto != 2) {
1573 $result .= $this->ref;
1574 }
1575 $result .= $linkend;
1576 global $action;
1577 $hookmanager->initHooks(array($this->element . 'dao'));
1578 $parameters = array('id' => $this->id, 'getnomurl' => &$result);
1579 $reshook = $hookmanager->executeHooks('getNomUrl', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks
1580 if ($reshook > 0) {
1581 $result = $hookmanager->resPrint;
1582 } else {
1583 $result .= $hookmanager->resPrint;
1584 }
1585 return $result;
1586 }
1587
1595 public function getLibStatut($mode = 0, $alreadypaid = -1)
1596 {
1597 return $this->LibStatut($this->frequency ? 1 : 0, $this->suspended, $mode, $alreadypaid, empty($this->type) ? 0 : $this->type);
1598 }
1599
1600 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1612 public function LibStatut($recur, $status, $mode = 0, $alreadypaid = -1, $type = 0, $nbofopendirectdebitorcredittransfer = 0)
1613 {
1614 // phpcs:enable
1615 global $langs;
1616 $langs->load('bills');
1617
1618 $labelStatus = $langs->transnoentitiesnoconv('Active');
1619 $statusType = 'status0';
1620
1621 //print "$recur,$status,$mode,$alreadypaid,$type";
1622 if ($mode == 0) {
1623 if ($recur) {
1624 if ($status == self::STATUS_SUSPENDED) {
1625 $labelStatus = $langs->transnoentitiesnoconv('Disabled');
1626 } else {
1627 $labelStatus = $langs->transnoentitiesnoconv('Active');
1628 }
1629 } else {
1630 if ($status == self::STATUS_SUSPENDED) {
1631 $labelStatus = $langs->transnoentitiesnoconv('Disabled');
1632 } else {
1633 $labelStatus = $langs->transnoentitiesnoconv('Draft');
1634 }
1635 }
1636 } elseif ($mode == 1) {
1637 $prefix = 'Short';
1638 if ($recur) {
1639 if ($status == self::STATUS_SUSPENDED) {
1640 $labelStatus = $langs->transnoentitiesnoconv('Disabled');
1641 } else {
1642 $labelStatus = $langs->transnoentitiesnoconv('Active');
1643 }
1644 } else {
1645 if ($status == self::STATUS_SUSPENDED) {
1646 $labelStatus = $langs->transnoentitiesnoconv('Disabled');
1647 } else {
1648 $labelStatus = $langs->transnoentitiesnoconv('Draft');
1649 }
1650 }
1651 } elseif ($mode == 2) {
1652 if ($recur) {
1653 if ($status == self::STATUS_SUSPENDED) {
1654 $statusType = 'status6';
1655 $labelStatus = $langs->transnoentitiesnoconv('Disabled');
1656 } else {
1657 $statusType = 'status4';
1658 $labelStatus = $langs->transnoentitiesnoconv('Active');
1659 }
1660 } else {
1661 if ($status == self::STATUS_SUSPENDED) {
1662 $statusType = 'status6';
1663 $labelStatus = $langs->transnoentitiesnoconv('Disabled');
1664 } else {
1665 $statusType = 'status0';
1666 $labelStatus = $langs->transnoentitiesnoconv('Draft');
1667 }
1668 }
1669 } elseif ($mode == 3) {
1670 if ($recur) {
1671 $prefix = 'Short';
1672 if ($status == self::STATUS_SUSPENDED) {
1673 $statusType = 'status6';
1674 $labelStatus = $langs->transnoentitiesnoconv('Disabled');
1675 } else {
1676 $statusType = 'status4';
1677 $labelStatus = $langs->transnoentitiesnoconv('Active');
1678 }
1679 } else {
1680 if ($status == self::STATUS_SUSPENDED) {
1681 $statusType = 'status6';
1682 $labelStatus = $langs->transnoentitiesnoconv('Disabled');
1683 } else {
1684 $statusType = 'status0';
1685 $labelStatus = $langs->transnoentitiesnoconv('Draft');
1686 }
1687 }
1688 } elseif ($mode == 4) {
1689 $prefix = '';
1690 if ($recur) {
1691 if ($status == self::STATUS_SUSPENDED) {
1692 $statusType = 'status6';
1693 $labelStatus = $langs->transnoentitiesnoconv('Disabled');
1694 } else {
1695 $statusType = 'status4';
1696 $labelStatus = $langs->transnoentitiesnoconv('Active');
1697 }
1698 } else {
1699 if ($status == self::STATUS_SUSPENDED) {
1700 $statusType = 'status6';
1701 $labelStatus = $langs->transnoentitiesnoconv('Disabled');
1702 } else {
1703 $statusType = 'status0';
1704 $labelStatus = $langs->transnoentitiesnoconv('Draft');
1705 }
1706 }
1707 } elseif ($mode == 5 || $mode == 6) {
1708 $prefix = '';
1709 if ($mode == 5) {
1710 $prefix = 'Short';
1711 }
1712 if ($recur) {
1713 if ($status == self::STATUS_SUSPENDED) {
1714 $statusType = 'status6';
1715 $labelStatus = $langs->transnoentitiesnoconv('Disabled');
1716 } else {
1717 $statusType = 'status4';
1718 $labelStatus = $langs->transnoentitiesnoconv('Active');
1719 }
1720 } else {
1721 if ($status == self::STATUS_SUSPENDED) {
1722 $statusType = 'status6';
1723 $labelStatus = $langs->transnoentitiesnoconv('Disabled');
1724 } else {
1725 $statusType = 'status0';
1726 $labelStatus = $langs->transnoentitiesnoconv('Draft');
1727 }
1728 }
1729 }
1730
1731 $labelStatusShort = $labelStatus;
1732
1733 return dolGetStatus($labelStatus, $labelStatusShort, '', $statusType, $mode);
1734 }
1735
1744 public function initAsSpecimen($option = '')
1745 {
1746 global $user, $langs, $conf;
1747
1748 $now = dol_now();
1749 $arraynow = dol_getdate($now);
1750 $nownotime = dol_mktime(0, 0, 0, $arraynow['mon'], $arraynow['mday'], $arraynow['year']);
1751
1752 // Load array of products prodids
1753 $num_prods = 0;
1754 $prodids = array();
1755
1756 $sql = 'SELECT rowid';
1757 $sql .= ' FROM ' .MAIN_DB_PREFIX. 'product';
1758 $sql .= ' WHERE entity IN (' .getEntity('product'). ')';
1759 $sql .= $this->db->plimit(100);
1760
1761 $resql = $this->db->query($sql);
1762 if ($resql) {
1763 $num_prods = $this->db->num_rows($resql);
1764 $i = 0;
1765 while ($i < $num_prods) {
1766 $i++;
1767 $row = $this->db->fetch_row($resql);
1768 $prodids[$i] = $row[0];
1769 }
1770 }
1771
1772 // Initialize parameters
1773 $this->id = 0;
1774 $this->ref = 'SPECIMEN';
1775 $this->title = 'SPECIMEN';
1776 $this->specimen = 1;
1777 $this->socid = 1;
1778 $this->date = $nownotime;
1779 $this->date_lim_reglement = $nownotime + 3600 * 24 * 30;
1780 $this->cond_reglement_id = 1;
1781 $this->cond_reglement_code = 'RECEP';
1782 $this->date_lim_reglement = $this->calculate_date_lim_reglement();
1783 $this->mode_reglement_id = 0; // Not forced to show payment mode CHQ + VIR
1784 $this->mode_reglement_code = ''; // Not forced to show payment mode CHQ + VIR
1785 $this->note_public = 'This is a comment (public)';
1786 $this->note_private = 'This is a comment (private)';
1787 $this->note = 'This is a comment (private)';
1788 $this->fk_incoterms = 0;
1789 $this->location_incoterms = '';
1790
1791 if (empty($option) || $option != 'nolines') {
1792 // Lines
1793 $nbp = min(1000, GETPOSTINT('nblines') ? GETPOSTINT('nblines') : 5); // We can force the nb of lines to test from command line (but not more than 1000)
1794 $xnbp = 0;
1795 while ($xnbp < $nbp) {
1796 $line = new FactureLigne($this->db);
1797 $line->desc = $langs->trans('Description'). ' ' .$xnbp;
1798 $line->qty = 1;
1799 $line->subprice = 100;
1800 $line->tva_tx = 19.6;
1801 $line->localtax1_tx = 0;
1802 $line->localtax2_tx = 0;
1803 $line->remise_percent = 0;
1804 if ($xnbp == 1) { // Qty is negative (product line)
1805 $prodid = mt_rand(1, $num_prods);
1806 $line->fk_product = $prodids[$prodid];
1807 $line->qty = -1;
1808 $line->total_ht = -100;
1809 $line->total_ttc = -119.6;
1810 $line->total_tva = -19.6;
1811 } elseif ($xnbp == 2) { // UP is negative (free line)
1812 $line->subprice = -100;
1813 $line->total_ht = -100;
1814 $line->total_ttc = -119.6;
1815 $line->total_tva = -19.6;
1816 $line->remise_percent = 0;
1817 } elseif ($xnbp == 3) { // Discount is 50% (product line)
1818 $prodid = mt_rand(1, $num_prods);
1819 $line->fk_product = $prodids[$prodid];
1820 $line->total_ht = 50;
1821 $line->total_ttc = 59.8;
1822 $line->total_tva = 9.8;
1823 $line->remise_percent = 50;
1824 } else { // (product line)
1825 $prodid = mt_rand(1, $num_prods);
1826 $line->fk_product = $prodids[$prodid];
1827 $line->total_ht = 100;
1828 $line->total_ttc = 119.6;
1829 $line->total_tva = 19.6;
1830 $line->remise_percent = 00;
1831 }
1832
1833 $this->lines[$xnbp] = $line;
1834 $xnbp++;
1835
1836 $this->total_ht += $line->total_ht;
1837 $this->total_tva += $line->total_tva;
1838 $this->total_ttc += $line->total_ttc;
1839 }
1840 $this->revenuestamp = 0;
1841
1842 // Add a line "offered"
1843 $line = new FactureLigne($this->db);
1844 $line->desc = $langs->trans('Description'). ' (offered line)';
1845 $line->qty = 1;
1846 $line->subprice = 100;
1847 $line->tva_tx = 19.6;
1848 $line->localtax1_tx = 0;
1849 $line->localtax2_tx = 0;
1850 $line->remise_percent = 100;
1851 $line->total_ht = 0;
1852 $line->total_ttc = 0; // 90 * 1.196
1853 $line->total_tva = 0;
1854 $prodid = mt_rand(1, $num_prods);
1855 $line->fk_product = $prodids[$prodid];
1856
1857 $this->lines[$xnbp] = $line;
1858 $xnbp++;
1859 }
1860
1861 $this->usenewprice = 0;
1862
1863 return 1;
1864 }
1865
1874 public static function replaceThirdparty(DoliDB $dbs, $origin_id, $dest_id)
1875 {
1876 $tables = array(
1877 'facture_fourn_rec'
1878 );
1879
1880 return CommonObject::commonReplaceThirdparty($dbs, $origin_id, $dest_id, $tables);
1881 }
1882
1890 public function setFrequencyAndUnit($frequency, $unit)
1891 {
1892 if (!$this->table_element) {
1893 dol_syslog(get_class($this). '::setFrequencyAndUnit was called on object with property table_element not defined', LOG_ERR);
1894 return -1;
1895 }
1896
1897 if (!empty($frequency) && empty($unit)) {
1898 dol_syslog(get_class($this). '::setFrequencyAndUnit was called on object with params frequency defined but unit not defined', LOG_ERR);
1899 return -2;
1900 }
1901
1902 $sql = "UPDATE ".MAIN_DB_PREFIX.$this->table_element;
1903 $sql .= " SET frequency = ".($frequency ? ((int) $frequency) : "NULL");
1904 if (!empty($unit)) {
1905 $sql .= ", unit_frequency = '".$this->db->escape($unit)."'";
1906 }
1907 $sql .= " WHERE rowid = ".((int) $this->id);
1908
1909 dol_syslog(get_class($this).'::setFrequencyAndUnit', LOG_DEBUG);
1910
1911 if ($this->db->query($sql)) {
1912 $this->frequency = $frequency;
1913 if (!empty($unit)) {
1914 $this->unit_frequency = $unit;
1915 }
1916 return 1;
1917 } else {
1918 $this->error = $this->db->lasterror();
1919 return -1;
1920 }
1921 }
1922
1930 public function setNextDate($date, $increment_nb_gen_done = 0)
1931 {
1932 if (!$this->table_element) {
1933 dol_syslog(get_class($this).'::setNextDate was called on object with property table_element not defined', LOG_ERR);
1934 return -1;
1935 }
1936 $sql = "UPDATE ".MAIN_DB_PREFIX.$this->table_element;
1937 $sql .= " SET date_when = " .($date ? "'".$this->db->idate($date)."'" : "NULL");
1938 if ($increment_nb_gen_done > 0) {
1939 $sql .= ", nb_gen_done = nb_gen_done + 1";
1940 }
1941 $sql .= " WHERE rowid = " . (int) $this->id;
1942
1943 dol_syslog(get_class($this).'::setNextDate', LOG_DEBUG);
1944
1945 if ($this->db->query($sql)) {
1946 $this->date_when = $date;
1947 if ($increment_nb_gen_done > 0) {
1948 $this->nb_gen_done++;
1949 }
1950 return 1;
1951 } else {
1952 $this->error = $this->db->lasterror();
1953 return -1;
1954 }
1955 }
1956
1963 public function setMaxPeriod($nb)
1964 {
1965 if (!$this->table_element) {
1966 dol_syslog(get_class($this).'::setMaxPeriod was called on object with property table_element not defined', LOG_ERR);
1967 return -1;
1968 }
1969
1970 if (empty($nb)) {
1971 $nb = 0;
1972 }
1973
1974 $sql = "UPDATE ".MAIN_DB_PREFIX.$this->table_element;
1975 $sql .= " SET nb_gen_max = ". (int) $nb;
1976 $sql .= " WHERE rowid = " . (int) $this->id;
1977
1978 dol_syslog(get_class($this).'::setMaxPeriod', LOG_DEBUG);
1979
1980 if ($this->db->query($sql)) {
1981 $this->nb_gen_max = $nb;
1982 return 1;
1983 } else {
1984 dol_print_error($this->db);
1985 return -1;
1986 }
1987 }
1988
1995 public function setAutoValidate($validate)
1996 {
1997 if (!$this->table_element) {
1998 dol_syslog(get_class($this).'::setAutoValidate was called on object with property table_element not defined', LOG_ERR);
1999 return -1;
2000 }
2001
2002 $sql = "UPDATE ".MAIN_DB_PREFIX.$this->table_element;
2003 $sql .= " SET auto_validate = ".((int) $validate);
2004 $sql .= " WHERE rowid = " . (int) $this->id;
2005
2006 dol_syslog(get_class($this).'::setAutoValidate', LOG_DEBUG);
2007
2008 if ($this->db->query($sql)) {
2009 $this->auto_validate = $validate;
2010 return 1;
2011 } else {
2012 dol_print_error($this->db);
2013 return -1;
2014 }
2015 }
2016
2023 public function setGeneratePdf($validate)
2024 {
2025 if (!$this->table_element) {
2026 dol_syslog(get_class($this).'::setGeneratePdf was called on object with property table_element not defined', LOG_ERR);
2027 return -1;
2028 }
2029
2030 $sql = "UPDATE ".MAIN_DB_PREFIX.$this->table_element;
2031 $sql .= " SET generate_pdf = ". (int) $validate;
2032 $sql .= " WHERE rowid = " . (int) $this->id;
2033
2034 dol_syslog(get_class($this).'::setGeneratePdf', LOG_DEBUG);
2035
2036 if ($this->db->query($sql)) {
2037 $this->generate_pdf = $validate;
2038 return 1;
2039 } else {
2040 dol_print_error($this->db);
2041 return -1;
2042 }
2043 }
2044
2051 public function setModelPdf($model)
2052 {
2053 if (!$this->table_element) {
2054 dol_syslog(get_class($this).'::setModelPdf was called on object with property table_element not defined', LOG_ERR);
2055 return -1;
2056 }
2057
2058 $sql = "UPDATE ".MAIN_DB_PREFIX.$this->table_element;
2059 $sql .= " SET modelpdf = '".$this->db->escape($model)."'";
2060 $sql .= " WHERE rowid = " . (int) $this->id;
2061
2062 dol_syslog(get_class($this).'::setModelPdf', LOG_DEBUG);
2063
2064 if ($this->db->query($sql)) {
2065 $this->model_pdf = $model;
2066 return 1;
2067 } else {
2068 dol_print_error($this->db);
2069 return -1;
2070 }
2071 }
2072}
$object ref
Definition info.php:90
Superclass for invoice classes.
const TYPE_STANDARD
Standard invoice.
calculate_date_lim_reglement($cond_reglement=0)
Returns an invoice payment deadline based on the invoice settlement conditions and billing date.
const STATUS_DRAFT
Draft status.
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...
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.
deleteObjectLinked($sourceid=null, $sourcetype='', $targetid=null, $targettype='', $rowid=0, $f_user=null, $notrigger=0)
Delete all links between an object $this.
deleteExtraFields()
Delete all extra fields values for the current object.
static commonReplaceThirdparty(DoliDB $dbs, $origin_id, $dest_id, array $tables, $ignoreerrors=0)
Function used to replace a thirdparty id with another one.
insertExtraFields($trigger='', $userused=null)
Add/Update all extra fields values for the current object.
call_trigger($triggerName, $user)
Call trigger based on this instance.
Class to manage Dolibarr database access.
Class to manage suppliers invoices.
Class to manage supplier invoice lines of templates.
Class to manage invoice templates.
setModelPdf($model)
Update the model for documents.
fetch($rowid, $ref='', $ref_ext='')
Load object and lines.
strikeIfMaxNbGenReached($ret)
Format string to output with by striking the string if max number of generation was reached.
setFrequencyAndUnit($frequency, $unit)
Update frequency and unit.
getNextNumRef($soc, $mode='next')
Return next reference of invoice not already used (or last reference)
setGeneratePdf($validate)
Update the auto generate documents.
getLinesArray()
Create an array of invoice lines.
initAsSpecimen($option='')
Initialise an instance with random values.
updateline($rowid, $fk_product, $ref, $label, $desc, $pu_ht, $qty, $remise_percent, $txtva, $txlocaltax1=0, $txlocaltax2=0, $price_base_type='HT', $type=0, $date_start=0, $date_end=0, $info_bits=0, $special_code=0, $rang=-1, $fk_unit=null, $pu_ht_devise=0, $pu_ttc=0)
Update a line to supplier invoice template.
isMaxNbGenReached()
Return if maximum number of generation is reached.
LibStatut($recur, $status, $mode=0, $alreadypaid=-1, $type=0, $nbofopendirectdebitorcredittransfer=0)
Return label of a status.
setAutoValidate($validate)
Update the auto validate flag of invoice.
static replaceThirdparty(DoliDB $dbs, $origin_id, $dest_id)
Function used to replace a thirdparty id with another one.
getNextDate()
Return the next date of.
fetch_lines()
Get lines of template invoices into this->lines.
getLibStatut($mode=0, $alreadypaid=-1)
Return label of object status.
setNextDate($date, $increment_nb_gen_done=0)
Update the next date of execution.
setMaxPeriod($nb)
Update the maximum period.
createRecurringInvoices($restrictioninvoiceid=0, $forcevalidation=0)
Create all recurrents supplier invoices (for all entities if multicompany is used).
update(User $user, $notrigger=0)
Update fourn_invoice_rec.
addline($fk_product, $ref, $label, $desc, $pu_ht, $pu_ttc, $qty, $remise_percent, $txtva, $txlocaltax1=0, $txlocaltax2=0, $price_base_type='HT', $type=0, $date_start=0, $date_end=0, $info_bits=0, $special_code=0, $rang=-1, $fk_unit=null, $pu_ht_devise=0)
Add a line to recursive supplier invoice.
getNomUrl($withpicto=0, $option='', $max=0, $short=0, $moretitle='', $notooltip=0, $save_lastsearch_value=-1)
Return clickable name (with picto eventually)
create($user, $facFournId, $notrigger=0, $onlylines=array())
Create a predefined supplier invoice.
Class to manage invoice lines.
Class to manage products or services.
Class to manage Dolibarr users.
dol_time_plus_duree($time, $duration_value, $duration_unit, $ruleforendofmonth=0)
Add a delay to a date.
Definition date.lib.php:125
dol_mktime($hour, $minute, $second, $month, $day, $year, $gm='auto', $check=1)
Return a timestamp date built from detailed information (by default a local PHP server timestamp) Rep...
GETPOSTINT($paramname, $method=0)
Return the value of a $_GET or $_POST supervariable, converted into integer.
price2num($amount, $rounding='', $option=0)
Function that return a number with universal decimal format (decimal separator is '.
img_object($titlealt, $picto, $moreatt='', $pictoisfullpath=0, $srconly=0, $notitle=0, $allowothertags=array())
Show a picto called object_picto (generic function)
dol_now($mode='auto')
Return date for now.
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.
dol_print_date($time, $format='', $tzoutput='auto', $outputlangs=null, $encodetooutput=false)
Output date in a string format according to outputlangs (or langs if not defined).
dolGetStatus($statusLabel='', $statusLabelShort='', $html='', $statusType='status0', $displayMode=0, $url='', $params=array())
Output the badge of a status.
dol_print_error($db=null, $error='', $errors=null)
Displays error message system with all the information to facilitate the diagnosis and the escalation...
dol_syslog($message, $level=LOG_INFO, $ident=0, $suffixinfilename='', $restricttologhandler='', $logcontext=null)
Write log message into outputs.
dol_getdate($timestamp, $fast=false, $forcetimezone='')
Return an array with locale date info.
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...
global $conf
The following vars must be defined: $type2label $form $conf, $lang, The following vars may also be de...
Definition member.php:79
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.
Definition price.lib.php:90
if(preg_match('/(crypted|dolcrypt):/i', $dolibarr_main_db_pass)||!empty($dolibarr_main_db_encrypted_pass)) $conf db type
Definition repair.php:158