dolibarr 21.0.4
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 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
90 public $ref_supplier;
94 public $socid;
95
100 public $fk_soc;
101
105 public $suspended; // status
106
111 public $libelle;
115 public $label;
116
121 public $amount;
126 public $remise;
127
131 public $vat_src_code;
135 public $localtax1;
139 public $localtax2;
140
144 public $user_author;
148 public $user_modif;
152 public $fk_project;
153
157 public $mode_reglement_id;
161 public $mode_reglement_code;
165 public $cond_reglement_code;
169 public $cond_reglement_doc;
173 public $cond_reglement_id;
174
178 public $date_lim_reglement;
179
183 public $usenewprice = 0;
187 public $frequency;
191 public $unit_frequency;
195 public $date_when;
199 public $date_last_gen;
200
204 public $nb_gen_done;
205
209 public $nb_gen_max;
210
214 public $auto_validate; //
218 public $generate_pdf; // 1 to generate PDF on invoice generation (default)
219
224 public $lines = array();
225
226
227 /* Override fields in CommonObject
228 public $entity;
229 public $total_ht;
230 public $total_tva;
231 public $total_ttc;
232 public $fk_account;
233 public $mode_reglement;
234 public $cond_reglement;
235 public $note_public;
236 public $note_private;
237 */
238
263 // BEGIN MODULEBUILDER PROPERTIES
267 public $fields = array(
268 'rowid' => array('type' => 'integer', 'label' => 'TechnicalID', 'enabled' => 1, 'visible' => -1, 'notnull' => 1, 'position' => 10),
269 'titre' => array('type' => 'varchar(100)', 'label' => 'Titre', 'enabled' => 1, 'showoncombobox' => 1, 'visible' => -1, 'position' => 15),
270 'ref_supplier' => array('type' => 'varchar(180)', 'label' => 'RefSupplier', 'enabled' => 1, 'showoncombobox' => 1, 'visible' => -1, 'position' => 20),
271 'entity' => array('type' => 'integer', 'label' => 'Entity', 'default' => '1', 'enabled' => 1, 'visible' => -2, 'notnull' => 1, 'position' => 25, 'index' => 1),
272 'fk_soc' => array('type' => 'integer:Societe:societe/class/societe.class.php', 'label' => 'ThirdParty', 'enabled' => 'isModEnabled("societe")', 'visible' => -1, 'notnull' => 1, 'position' => 30),
273 'datec' => array('type' => 'datetime', 'label' => 'DateCreation', 'enabled' => 1, 'visible' => -1, 'position' => 35),
274 'tms' => array('type' => 'timestamp', 'label' => 'DateModification', 'enabled' => 1, 'visible' => -1, 'notnull' => 1, 'position' => 40),
275 'suspended' => array('type' => 'integer', 'label' => 'Suspended', 'enabled' => 1, 'visible' => -1, 'position' => 225),
276 'libelle' => array('type' => 'varchar(100)', 'label' => 'Libelle', 'enabled' => 1, 'showoncombobox' => 0, 'visible' => -1, 'position' => 15),
277
278 'localtax1' => array('type' => 'double(24,8)', 'label' => 'Localtax1', 'enabled' => 1, 'visible' => -1, 'position' => 60, 'isameasure' => 1),
279 'localtax2' => array('type' => 'double(24,8)', 'label' => 'Localtax2', 'enabled' => 1, 'visible' => -1, 'position' => 65, 'isameasure' => 1),
280 'total_ht' => array('type' => 'double(24,8)', 'label' => 'Total', 'enabled' => 1, 'visible' => -1, 'position' => 70, 'isameasure' => 1),
281 'total_tva' => array('type' => 'double(24,8)', 'label' => 'Tva', 'enabled' => 1, 'visible' => -1, 'position' => 55, 'isameasure' => 1),
282 'total_ttc' => array('type' => 'double(24,8)', 'label' => 'Total ttc', 'enabled' => 1, 'visible' => -1, 'position' => 75, 'isameasure' => 1),
283
284 'fk_user_author' => array('type' => 'integer:User:user/class/user.class.php', 'label' => 'Fk user author', 'enabled' => 1, 'visible' => -1, 'position' => 80),
285 'fk_user_modif' => array('type' => 'integer:User:user/class/user.class.php', 'label' => 'UserModif', 'enabled' => 1, 'visible' => -2, 'notnull' => -1, 'position' => 210),
286 '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),
287 'fk_account' => array('type' => 'integer', 'label' => 'Fk account', 'enabled' => 'isModEnabled("bank")', 'visible' => -1, 'position' => 175),
288 'fk_cond_reglement' => array('type' => 'integer', 'label' => 'Fk cond reglement', 'enabled' => 1, 'visible' => -1, 'position' => 90),
289 'fk_mode_reglement' => array('type' => 'integer', 'label' => 'Fk mode reglement', 'enabled' => 1, 'visible' => -1, 'position' => 95),
290 'date_lim_reglement' => array('type' => 'date', 'label' => 'Date lim reglement', 'enabled' => 1, 'visible' => -1, 'position' => 100),
291
292 'note_private' => array('type' => 'html', 'label' => 'NotePublic', 'enabled' => 1, 'visible' => 0, 'position' => 105),
293 'note_public' => array('type' => 'html', 'label' => 'NotePrivate', 'enabled' => 1, 'visible' => 0, 'position' => 110),
294 'modelpdf' => array('type' => 'varchar(255)', 'label' => 'Modelpdf', 'enabled' => 1, 'visible' => -1, 'position' => 115),
295
296 'fk_multicurrency' => array('type' => 'integer', 'label' => 'Fk multicurrency', 'enabled' => 1, 'visible' => -1, 'position' => 180),
297 'multicurrency_code' => array('type' => 'varchar(255)', 'label' => 'Multicurrency code', 'enabled' => 1, 'visible' => -1, 'position' => 185),
298 'multicurrency_tx' => array('type' => 'double(24,8)', 'label' => 'Multicurrency tx', 'enabled' => 1, 'visible' => -1, 'position' => 190, 'isameasure' => 1),
299 'multicurrency_total_ht' => array('type' => 'double(24,8)', 'label' => 'Multicurrency total ht', 'enabled' => 1, 'visible' => -1, 'position' => 195, 'isameasure' => 1),
300 'multicurrency_total_tva' => array('type' => 'double(24,8)', 'label' => 'Multicurrency total tva', 'enabled' => 1, 'visible' => -1, 'position' => 200, 'isameasure' => 1),
301 'multicurrency_total_ttc' => array('type' => 'double(24,8)', 'label' => 'Multicurrency total ttc', 'enabled' => 1, 'visible' => -1, 'position' => 205, 'isameasure' => 1),
302
303 'usenewprice' => array('type' => 'integer', 'label' => 'UseNewPrice', 'enabled' => 1, 'visible' => 0, 'position' => 155),
304 'frequency' => array('type' => 'integer', 'label' => 'Frequency', 'enabled' => 1, 'visible' => -1, 'position' => 150),
305 'unit_frequency' => array('type' => 'varchar(2)', 'label' => 'Unit frequency', 'enabled' => 1, 'visible' => -1, 'position' => 125),
306
307 'date_when' => array('type' => 'datetime', 'label' => 'Date when', 'enabled' => 1, 'visible' => -1, 'position' => 130),
308 'date_last_gen' => array('type' => 'datetime', 'label' => 'Date last gen', 'enabled' => 1, 'visible' => -1, 'position' => 135),
309 'nb_gen_done' => array('type' => 'integer', 'label' => 'Nb gen done', 'enabled' => 1, 'visible' => -1, 'position' => 140),
310 'nb_gen_max' => array('type' => 'integer', 'label' => 'Nb gen max', 'enabled' => 1, 'visible' => -1, 'position' => 145),
311 'revenuestamp' => array('type' => 'double(24,8)', 'label' => 'RevenueStamp', 'enabled' => 1, 'visible' => -1, 'position' => 160, 'isameasure' => 1),
312 'auto_validate' => array('type' => 'integer', 'label' => 'Auto validate', 'enabled' => 1, 'visible' => -1, 'position' => 165),
313 'generate_pdf' => array('type' => 'integer', 'label' => 'Generate pdf', 'enabled' => 1, 'visible' => -1, 'position' => 170),
314 );
315 // END MODULEBUILDER PROPERTIES
316
317 const STATUS_NOTSUSPENDED = 0;
318 const STATUS_SUSPENDED = 1;
319
320
321
327 public function __construct($db)
328 {
329 $this->db = $db;
330 }
331
340 public function create($user, $facFournId, $notrigger = 0)
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 $this->ref_supplier = empty($this->ref_supplier) ? '' : $this->ref_supplier;
353 $this->usenewprice = empty($this->usenewprice) ? 0 : $this->usenewprice;
354 $this->suspended = empty($this->suspended) ? 0 : $this->suspended;
355 // No frequency defined then no next date to execution
356 if (empty($this->frequency)) {
357 $this->frequency = 0;
358 $this->date_when = null;
359 }
360 $this->frequency = abs($this->frequency);
361 $this->nb_gen_done = 0;
362 $this->nb_gen_max = empty($this->nb_gen_max) ? 0 : $this->nb_gen_max;
363 $this->auto_validate = empty($this->auto_validate) ? 0 : $this->auto_validate;
364 $this->generate_pdf = empty($this->generate_pdf) ? 0 : $this->generate_pdf;
365
366 $this->db->begin();
367
368 // On charge la facture fournisseur depuis laquelle on crée la facture fournisseur modèle
369 $facfourn_src = new FactureFournisseur($this->db);
370 $result = $facfourn_src->fetch($facFournId);
371 if ($result > 0) {
372 $sql = 'INSERT INTO '.MAIN_DB_PREFIX.'facture_fourn_rec (';
373 $sql .= 'titre';
374 $sql .= ", subtype";
375 $sql .= ', ref_supplier';
376 $sql .= ', entity';
377 $sql .= ', fk_soc';
378 $sql .= ', datec';
379 $sql .= ', suspended';
380 $sql .= ', libelle';
381 $sql .= ', total_ttc';
382 $sql .= ', fk_user_author';
383 $sql .= ', fk_projet';
384 $sql .= ', fk_account';
385 $sql .= ', fk_cond_reglement';
386 $sql .= ', fk_mode_reglement';
387 $sql .= ', date_lim_reglement';
388 $sql .= ', note_private';
389 $sql .= ', note_public';
390 $sql .= ', modelpdf';
391 $sql .= ', fk_multicurrency';
392 $sql .= ', multicurrency_code';
393 $sql .= ', multicurrency_tx';
394 $sql .= ', usenewprice';
395 $sql .= ', frequency';
396 $sql .= ', unit_frequency';
397 $sql .= ', date_when';
398 $sql .= ', date_last_gen';
399 $sql .= ', nb_gen_done';
400 $sql .= ', nb_gen_max';
401 $sql .= ', auto_validate';
402 $sql .= ', generate_pdf';
403 $sql .= ') VALUES (';
404 $sql .= "'".$this->db->escape($this->title)."'";
405 $sql .= ", ".($this->subtype ? "'".$this->db->escape($this->subtype)."'" : "null");
406 $sql .= ", '".$this->db->escape($this->ref_supplier)."'";
407 $sql .= ", ".((int) $conf->entity);
408 $sql .= ", ".((int) $facfourn_src->socid);
409 $sql .= ", '".$this->db->idate($now)."'";
410 $sql .= ", ".((int) $this->suspended);
411 $sql .= ", '".$this->db->escape($this->libelle)."'";
412 $sql .= ", " .(!empty($facfourn_src->total_ttc) ? (float) $facfourn_src->total_ttc : '0'); // amount
413 $sql .= ", " .((int) $user->id);
414 $sql .= ", " .(!empty($this->fk_project) ? ((int) $this->fk_project) : 'NULL');
415 $sql .= ", " .(!empty($facfourn_src->fk_account) ? ((int) $facfourn_src->fk_account) : 'NULL');
416 $sql .= ", " .($this->cond_reglement_id > 0 ? (int) $this->cond_reglement_id : 'NULL');
417 $sql .= ", " .($this->mode_reglement_id > 0 ? (int) $this->mode_reglement_id : 'NULL');
418 $sql .= ", ".($facfourn_src->date_echeance > 0 ? "'".$this->db->idate($facfourn_src->date_echeance)."'" : 'NULL'); // date_lim_reglement
419 $sql .= ", " .(!empty($this->note_private) ? "'".$this->db->escape($this->note_private)."'" : 'NULL');
420 $sql .= ", " .(!empty($this->note_public) ? "'".$this->db->escape($this->note_public)."'" : 'NULL');
421 $sql .= ", " .(!empty($this->model_pdf) ? "'".$this->db->escape($this->model_pdf)."'" : 'NULL');
422 $sql .= ", " . (int) $facfourn_src->fk_multicurrency;
423 $sql .= ", '".$this->db->escape($facfourn_src->multicurrency_code)."'";
424 $sql .= ", " . (float) $facfourn_src->multicurrency_tx;
425 $sql .= ", " . (int) $this->usenewprice;
426 $sql .= ", " . (int) $this->frequency;
427 $sql .= ", '".$this->db->escape($this->unit_frequency)."'";
428 $sql .= ", " .(!empty($this->date_when) ? "'".$this->db->idate($this->date_when)."'" : 'NULL');
429 $sql .= ", " .(!empty($this->date_last_gen) ? "'".$this->db->idate($this->date_last_gen)."'" : 'NULL');
430 $sql .= ", " . (int) $this->nb_gen_done;
431 $sql .= ", " . (int) $this->nb_gen_max;
432 $sql .= ", " . (int) $this->auto_validate;
433 $sql .= ", " . (int) $this->generate_pdf;
434 $sql .= ')';
435
436 if ($this->db->query($sql)) {
437 $this->id = $this->db->last_insert_id(MAIN_DB_PREFIX. 'facture_fourn_rec');
438
439 // Fields used into addline later
440 $this->fk_multicurrency = $facfourn_src->fk_multicurrency;
441
442 $this->multicurrency_code = $facfourn_src->multicurrency_code;
443 $this->multicurrency_tx = $facfourn_src->multicurrency_tx;
444
445 // Add lines
446 $num = count($facfourn_src->lines);
447 for ($i = 0; $i < $num; $i++) {
448 $facfourn_line = $facfourn_src->lines[$i];
449 '@phan-var-force SupplierInvoiceLine $facfourn_line';
450
451 $tva_tx = $facfourn_line->tva_tx;
452 if (!empty($facfourn_line->vat_src_code) && !preg_match('/\‍(/', (string) $tva_tx)) {
453 $tva_tx .= ' ('.$facfourn_line->vat_src_code.')';
454 }
455
456 $result_insert = $this->addline(
457 $facfourn_line->fk_product,
458 $facfourn_line->ref_supplier,
459 $facfourn_line->product_label,
460 $facfourn_line->desc ? $facfourn_line->desc : $facfourn_line->description,
461 $facfourn_line->pu_ht,
462 $facfourn_line->pu_ttc,
463 $facfourn_line->qty,
464 $facfourn_line->remise_percent,
465 $tva_tx,
466 $facfourn_line->localtax1_tx,
467 $facfourn_line->localtax2_tx,
468 'HT',
469 $facfourn_line->product_type,
470 $facfourn_line->date_start,
471 $facfourn_line->date_end,
472 $facfourn_line->info_bits,
473 $facfourn_line->special_code,
474 $facfourn_line->rang,
475 $facfourn_line->fk_unit
476 );
477
478 if ($result_insert < 0) {
479 $error++;
480 } else {
481 $objectline = new FactureFournisseurLigneRec($this->db);
482
483 $result2 = $objectline->fetch($result_insert);
484 if ($result2 > 0) {
485 // Extrafields
486 if (method_exists($facfourn_line, 'fetch_optionals')) {
487 $facfourn_line->fetch_optionals($facfourn_line->id);
488 $objectline->array_options = $facfourn_line->array_options;
489 }
490
491 $result = $objectline->insertExtraFields();
492 if ($result < 0) {
493 $error++;
494 }
495 } elseif ($result2 < 0) {
496 $this->errors[] = $objectline->error;
497 $error++;
498 }
499 }
500 }
501
502 if (!empty($this->linkedObjectsIds) && empty($this->linked_objects)) { // To use new linkedObjectsIds instead of old linked_objects
503 $this->linked_objects = $this->linkedObjectsIds; // TODO Replace linked_objects with linkedObjectsIds
504 }
505
506 // Add object linked
507 if (!$error && $this->id && !empty($this->linked_objects) && is_array($this->linked_objects)) {
508 foreach ($this->linked_objects as $origin => $tmp_origin_id) {
509 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, ...))
510 foreach ($tmp_origin_id as $origin_id) {
511 $ret = $this->add_object_linked($origin, $origin_id);
512 if (!$ret) {
513 $this->error = $this->db->lasterror();
514 $error++;
515 }
516 }
517 } else { // Old behaviour, if linked_object has only one link per type, so is something like array('contract'=>id1))
518 $origin_id = $tmp_origin_id;
519 $ret = $this->add_object_linked($origin, $origin_id);
520 if (!$ret) {
521 $this->error = $this->db->lasterror();
522 $error++;
523 }
524 }
525 }
526 }
527
528 if (!$error) {
529 $result = $this->insertExtraFields();
530 if ($result < 0) {
531 $error++;
532 }
533 }
534
535 if (!$error && !$notrigger) {
536 // Call trigger
537 $result = $this->call_trigger('SUPPLIERBILLREC_CREATE', $user);
538 if ($result < 0) {
539 $this->db->rollback();
540 return -2;
541 }
542 // End call triggers
543 }
544
545 if ($error) {
546 $this->db->rollback();
547 return -3;
548 } else {
549 $this->db->commit();
550 return $this->id;
551 }
552 } else {
553 $this->error = $this->db->lasterror();
554 $this->db->rollback();
555 return -2;
556 }
557 } else {
558 $this->db->rollback();
559 return -1;
560 }
561 }
562
563
571 public function update(User $user, $notrigger = 0)
572 {
573 $error = 0;
574
575 $sql = "UPDATE ".MAIN_DB_PREFIX."facture_fourn_rec SET";
576 $sql .= " titre = '" . (!empty($this->title) ? $this->db->escape($this->title) : "")."'," ;
577 $sql .= " subtype=".(isset($this->subtype) ? $this->db->escape($this->subtype) : "null").",";
578 $sql .= " ref_supplier = '". (!empty($this->ref_supplier) ? $this->db->escape($this->ref_supplier) : "")."',";
579 $sql .= " entity = ". (!empty($this->entity) ? ((int) $this->entity) : 1) . ',';
580 if (!empty($this->socid) && $this->socid > 0) {
581 $sql .= " fk_soc = ". ((int) $this->socid). ',';
582 } elseif (!empty($this->fk_soc) && $this->fk_soc > 0) { // For backward compatibility
583 $sql .= " fk_soc = ". ((int) $this->fk_soc). ',';
584 }
585 $sql .= " suspended = ". (!empty($this->suspended) ? ((int) $this->suspended) : 0) . ',';
586 $sql .= " libelle = ". (!empty($this->libelle) ? "'".$this->db->escape($this->libelle)."'" : 'NULL') . ",";
587 $sql .= " vat_src_code = ". (!empty($this->vat_src_code) ? "'".$this->db->escape($this->vat_src_code)."'" : 'NULL') . ',';
588 $sql .= " localtax1 = ". (!empty($this->localtax1) ? ((float) $this->localtax1) : 0.00) . ',';
589 $sql .= " localtax2 = ". (!empty($this->localtax2) ? ((float) $this->localtax2) : 0.00) . ',';
590 $sql .= " total_ht = ". (!empty($this->total_ht) ? ((float) $this->total_ht) : 0.00) . ',';
591 $sql .= " total_tva = ". (!empty($this->total_tva) ? ((float) $this->total_tva) : 0.00) . ',';
592 $sql .= " total_ttc = ". (!empty($this->total_ttc) ? ((float) $this->total_ttc) : 0.00) . ',';
593 $sql .= " fk_user_modif = ". ((int) $user->id) . ',';
594 $sql .= " fk_projet = ". (!empty($this->fk_project) ? ((int) $this->fk_project) : 'NULL') . ',';
595 $sql .= " fk_account = ". (!empty($this->fk_account) ? ((int) $this->fk_account) : 'NULL') . ',';
596 $sql .= " fk_mode_reglement = ". (!empty($this->mode_reglement_id) ? ((int) $this->mode_reglement_id) : 'NULL') . ',';
597 $sql .= " fk_cond_reglement = ". (!empty($this->cond_reglement_id) ? ((int) $this->cond_reglement_id) : 'NULL') . ',';
598 $sql .= " date_lim_reglement = ". (!empty($this->date_lim_reglement) ? "'".$this->db->idate($this->date_lim_reglement)."'" : 'NULL') . ',';
599 $sql .= " note_private = '". (!empty($this->note_private) ? $this->db->escape($this->note_private) : '') . "',";
600 $sql .= " note_public = '". (!empty($this->note_public) ? $this->db->escape($this->note_public) : '') . "',";
601 $sql .= " modelpdf = ". (!empty($this->model_pdf) ? "'".$this->db->escape($this->model_pdf)."'" : 'NULL') . ",";
602 $sql .= " fk_multicurrency = ". (!empty($this->fk_multicurrency) ? ((int) $this->fk_multicurrency) : 'NULL') . ',';
603 $sql .= " multicurrency_code = ". (!empty($this->multicurrency_code) ? "'".$this->db->escape($this->multicurrency_code)."'" : 'NULL') . ",";
604 $sql .= " multicurrency_tx = ". (!empty($this->multicurrency_tx) ? ((float) $this->multicurrency_tx) : 1) . ',';
605 $sql .= " multicurrency_total_ht = ". (!empty($this->multicurrency_total_ht) ? ((float) $this->multicurrency_total_ht) : 0.00) . ',';
606 $sql .= " multicurrency_total_tva = ". (!empty($this->multicurrency_total_tva) ? ((float) $this->multicurrency_total_tva) : 0.00) . ',';
607 $sql .= " multicurrency_total_ttc = ". (!empty($this->multicurrency_total_ttc) ? ((float) $this->multicurrency_total_ttc) : 0.00) . ',';
608 $sql .= " usenewprice = ". (!empty($this->usenewprice) ? ((int) $this->usenewprice) : 0) . ',';
609 $sql .= " frequency = ". (!empty($this->frequency) ? ((int) $this->frequency) : 0). ',';
610 $sql .= " unit_frequency = '". (!empty($this->unit_frequency) ? $this->db->escape($this->unit_frequency) : ''). "',";
611 $sql .= " date_when = ". (!empty($this->date_when) ? "'".$this->db->idate($this->date_when)."'" : 'NULL') . ',';
612 $sql .= " date_last_gen = ". (!empty($this->date_last_gen) ? "'".$this->db->idate($this->date_last_gen)."'" : 'NULL') . ',';
613 $sql .= " nb_gen_done = ". (!empty($this->nb_gen_done) ? ((int) $this->nb_gen_done) : 0) . ',';
614 $sql .= " nb_gen_max = ". (!empty($this->nb_gen_max) ? ((int) $this->nb_gen_max) : 0) . ',';
615 $sql .= " auto_validate = ". (!empty($this->auto_validate) ? ((int) $this->auto_validate) : 0);
616 $sql .= " WHERE rowid = ". (int) $this->id;
617
618 $this->db->begin();
619
620 dol_syslog(get_class($this)."::update", LOG_DEBUG);
621 $resql = $this->db->query($sql);
622 if ($resql) {
623 if (!$error) {
624 $result = $this->insertExtraFields();
625 if ($result < 0) {
626 $error++;
627 }
628 }
629
630 if (!$error && !$notrigger) {
631 // Call trigger
632 $result = $this->call_trigger('SUPPLIERBILLREC_MODIFY', $user);
633 if ($result < 0) {
634 $this->db->rollback();
635 return -2;
636 }
637 // End call triggers
638 }
639 $this->db->commit();
640 return 1;
641 } else {
642 $this->error = $this->db->lasterror();
643 $this->db->rollback();
644 return -2;
645 }
646 }
647
656 public function fetch($rowid, $ref = '', $ref_ext = '')
657 {
658 $sql = 'SELECT f.rowid, f.titre as title, f.subtype, f.ref_supplier, f.entity, f.fk_soc';
659 $sql .= ', f.datec, f.tms, f.suspended';
660 $sql .= ', f.libelle as label';
661 $sql .= ', f.vat_src_code, f.localtax1, f.localtax2';
662 $sql .= ', f.total_tva, f.total_ht, f.total_ttc';
663 $sql .= ', f.fk_user_author, f.fk_user_modif';
664 $sql .= ', f.fk_projet as fk_project, f.fk_account';
665 $sql .= ', f.fk_mode_reglement, p.code as mode_reglement_code, p.libelle as mode_reglement_libelle';
666 $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';
667 $sql .= ', f.date_lim_reglement';
668 $sql .= ', f.note_private, f.note_public, f.modelpdf as model_pdf';
669 $sql .= ', f.fk_multicurrency, f.multicurrency_code, f.multicurrency_tx, f.multicurrency_total_ht, f.multicurrency_total_tva, f.multicurrency_total_ttc';
670 $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';
671 $sql .= ', f.generate_pdf';
672 $sql .= ' FROM '.MAIN_DB_PREFIX.'facture_fourn_rec as f';
673 $sql .= ' LEFT JOIN '.MAIN_DB_PREFIX.'c_payment_term as c ON f.fk_cond_reglement = c.rowid';
674 $sql .= ' LEFT JOIN '.MAIN_DB_PREFIX.'c_paiement as p ON f.fk_mode_reglement = p.id';
675 $sql .= ' WHERE f.entity IN ('.getEntity('invoice').')';
676 if ($rowid) {
677 $sql .= ' AND f.rowid='. (int) $rowid;
678 } elseif ($ref) {
679 $sql .= " AND f.titre='".$this->db->escape($ref)."'";
680 } else {
681 $sql .= ' AND f.rowid = 0';
682 }
683
684 $result = $this->db->query($sql);
685 if ($result) {
686 if ($this->db->num_rows($result)) {
687 $obj = $this->db->fetch_object($result);
688
689 $keyforref = $this->table_ref_field;
690
691 $this->id = $obj->rowid;
692 $this->titre = $obj->title;
693 $this->title = $obj->title;
694 $this->subtype = $obj->subtype;
695 $this->ref = $obj->title;
696 $this->ref_supplier = $obj->ref_supplier;
697 $this->entity = $obj->entity;
698 $this->socid = $obj->fk_soc;
699 $this->date_creation = $obj->datec;
700 $this->date_modification = $obj->tms;
701 $this->suspended = $obj->suspended;
702 $this->libelle = $obj->label;
703 $this->label = $obj->label;
704 $this->vat_src_code = $obj->vat_src_code;
705 $this->total_localtax1 = $obj->localtax1;
706 $this->total_localtax2 = $obj->localtax2;
707 $this->total_ht = $obj->total_ht;
708 $this->total_tva = $obj->total_tva;
709 $this->total_ttc = $obj->total_ttc;
710 $this->user_author = $obj->fk_user_author;
711 $this->user_modif = $obj->fk_user_modif;
712 $this->fk_project = $obj->fk_project;
713 $this->fk_account = $obj->fk_account;
714 $this->mode_reglement_id = $obj->fk_mode_reglement;
715 $this->mode_reglement_code = $obj->mode_reglement_code;
716 $this->mode_reglement = $obj->mode_reglement_libelle;
717 $this->cond_reglement_id = $obj->fk_cond_reglement;
718 $this->cond_reglement_code = $obj->cond_reglement_code;
719 $this->cond_reglement = $obj->cond_reglement_libelle;
720 $this->cond_reglement_doc = $obj->cond_reglement_libelle_doc;
721 $this->date_lim_reglement = $this->db->jdate($obj->date_lim_reglement);
722 $this->note_private = $obj->note_private;
723 $this->note_public = $obj->note_public;
724 $this->model_pdf = $obj->model_pdf;
725
726 // Multicurrency
727 $this->fk_multicurrency = $obj->fk_multicurrency;
728 $this->multicurrency_code = $obj->multicurrency_code;
729 $this->multicurrency_tx = $obj->multicurrency_tx;
730 $this->multicurrency_total_ht = $obj->multicurrency_total_ht;
731 $this->multicurrency_total_tva = $obj->multicurrency_total_tva;
732 $this->multicurrency_total_ttc = $obj->multicurrency_total_ttc;
733
734 $this->usenewprice = $obj->usenewprice;
735 $this->frequency = $obj->frequency;
736 $this->unit_frequency = $obj->unit_frequency;
737 $this->date_when = $this->db->jdate($obj->date_when);
738 $this->date_last_gen = $this->db->jdate($obj->date_last_gen);
739 $this->nb_gen_done = $obj->nb_gen_done;
740 $this->nb_gen_max = $obj->nb_gen_max;
741 $this->auto_validate = $obj->auto_validate;
742 $this->generate_pdf = $obj->generate_pdf;
743
744 // Retrieve all extrafield
745 // fetch optionals attributes and labels
746 $this->fetch_optionals();
747
748 /*
749 * Lines
750 */
751 $result = $this->fetch_lines();
752 if ($result < 0) {
753 $this->error = $this->db->lasterror();
754 return -3;
755 }
756 return 1;
757 } else {
758 $this->error = 'Bill with id '.$rowid.' or ref '.$ref.' not found';
759 dol_syslog('Facture::Fetch Error '.$this->error, LOG_ERR);
760 return -2;
761 }
762 } else {
763 $this->error = $this->db->error();
764 return -1;
765 }
766 }
767
768
774 public function getLinesArray()
775 {
776 return $this->fetch_lines();
777 }
778
779 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
785 public function fetch_lines()
786 {
787 // phpcs:enable
788 $this->lines = array();
789
790 // Retrieve all extrafield for line
791 // fetch optionals attributes and labels
792 /*if (!is_object($extrafields)) {
793 require_once DOL_DOCUMENT_ROOT.'/core/class/extrafields.class.php';
794 $extrafields = new ExtraFields($this->db);
795 }
796 $extrafields->fetch_name_optionals_label($this->table_element_line, true);
797 */
798
799 $sql = 'SELECT l.rowid,';
800 $sql .= ' l.fk_facture_fourn, l.fk_parent_line, l.fk_product, l.ref as ref_supplier, l.label, l.description as line_desc,';
801 $sql .= ' l.pu_ht, l.pu_ttc, l.qty, l.remise_percent, l.fk_remise_except, l.vat_src_code, l.tva_tx,';
802 $sql .= ' l.localtax1_tx, l.localtax2_tx, l.localtax1_type, l.localtax2_type,';
803 $sql .= ' l.total_ht, l.total_tva, l.total_ttc, total_localtax1, total_localtax2,';
804 $sql .= ' l.product_type, l.date_start, l.date_end,';
805 $sql .= ' l.info_bits, l.special_code, l.rang,';
806 $sql .= ' l.fk_unit, l.import_key, l.fk_user_author, l.fk_user_modif,';
807 $sql .= ' l.fk_multicurrency, l.multicurrency_code, l.multicurrency_subprice, l.multicurrency_total_ht, l.multicurrency_total_tva, l.multicurrency_total_ttc,';
808 $sql .= ' p.ref as product_ref, p.fk_product_type as fk_product_type, p.label as product_label, p.description as product_desc';
809 $sql .= ' FROM '.MAIN_DB_PREFIX.'facture_fourn_det_rec as l';
810 $sql .= ' LEFT JOIN '.MAIN_DB_PREFIX.'product as p ON l.fk_product = p.rowid';
811 $sql .= ' WHERE l.fk_facture_fourn = '. (int) $this->id;
812 $sql .= ' ORDER BY l.rang';
813
814 dol_syslog('FactureFournisseurRec::fetch_lines', LOG_DEBUG);
815
816 $result = $this->db->query($sql);
817 if ($result) {
818 $num = $this->db->num_rows($result);
819 $i = 0;
820 while ($i < $num) {
821 $objp = $this->db->fetch_object($result);
822
823 $line = new FactureFournisseurLigneRec($this->db);
824
825 $line->id = $objp->rowid;
826 $line->fk_facture_fourn = $objp->fk_facture_fourn;
827 $line->fk_parent = $objp->fk_parent_line;
828 $line->fk_product = $objp->fk_product;
829 $line->ref = $objp->product_ref; // Ref of product
830 $line->product_ref = $objp->product_ref; // Ref of product
831 $line->product_label = $objp->product_label;
832 $line->product_desc = $objp->product_desc;
833 $line->ref_supplier = $objp->ref_supplier;
834 $line->label = $objp->label;
835 $line->description = $objp->line_desc;
836 $line->desc = $objp->line_desc;
837 $line->pu_ht = $objp->pu_ht;
838 $line->subprice = $objp->pu_ht;
839 $line->pu_ttc = $objp->pu_ttc;
840 $line->qty = $objp->qty;
841 $line->remise_percent = $objp->remise_percent;
842 $line->fk_remise_except = $objp->fk_remise_except;
843 $line->vat_src_code = $objp->vat_src_code;
844 $line->tva_tx = $objp->tva_tx;
845 $line->localtax1_tx = $objp->localtax1_tx;
846 $line->localtax1_type = $objp->localtax1_type;
847 $line->localtax2_tx = $objp->localtax2_tx;
848 $line->localtax2_type = $objp->localtax2_type;
849 $line->total_ht = $objp->total_ht;
850 $line->total_tva = $objp->total_tva;
851 $line->total_localtax1 = $objp->total_localtax1;
852 $line->total_localtax2 = $objp->total_localtax2;
853 $line->total_ttc = $objp->total_ttc;
854 $line->product_type = $objp->product_type;
855 $line->date_start = $this->db->jdate($objp->date_start);
856 $line->date_end = $this->db->jdate($objp->date_end);
857 $line->info_bits = $objp->info_bits ;
858 $line->special_code = $objp->special_code;
859 $line->rang = $objp->rang;
860 $line->fk_unit = $objp->fk_unit;
861 $line->import_key = $objp->import_key;
862 $line->fk_user_author = $objp->fk_user_author;
863 $line->fk_user_modif = $objp->fk_user_modif;
864 $line->fk_multicurrency = $objp->fk_multicurrency;
865 $line->multicurrency_code = $objp->multicurrency_code;
866 $line->multicurrency_subprice = $objp->multicurrency_subprice;
867 $line->multicurrency_total_ht = $objp->multicurrency_total_ht;
868 $line->multicurrency_total_tva = $objp->multicurrency_total_tva;
869 $line->multicurrency_total_ttc = $objp->multicurrency_total_ttc;
870
871 $line->fetch_optionals();
872
873 $this->lines[$i] = $line;
874
875 $i++;
876 }
877
878 $this->db->free($result);
879 return 1;
880 } else {
881 $this->error = $this->db->lasterror();
882 return -3;
883 }
884 }
885
886
895 public function delete(User $user, $notrigger = 0, $idwarehouse = -1)
896 {
897 $rowid = $this->id;
898
899 dol_syslog(get_class($this)."::delete rowid=".((int) $rowid), LOG_DEBUG);
900
901 $error = 0;
902 $this->db->begin();
903
904 $main = MAIN_DB_PREFIX.'facture_fourn_det_rec';
905 $ef = $main."_extrafields";
906
907 $sqlef = "DELETE FROM ".$ef." WHERE fk_object IN (SELECT rowid FROM ".$main." WHERE fk_facture_fourn = ". (int) $rowid .")";
908 $sql = "DELETE FROM ".MAIN_DB_PREFIX."facture_fourn_det_rec WHERE fk_facture_fourn = ". (int) $rowid;
909
910 if ($this->db->query($sqlef) && $this->db->query($sql)) {
911 $sql = "DELETE FROM ".MAIN_DB_PREFIX."facture_fourn_rec WHERE rowid = ". (int) $rowid;
912 dol_syslog($sql);
913 if ($this->db->query($sql)) {
914 // Delete linked object
915 $res = $this->deleteObjectLinked();
916 if ($res < 0) {
917 $error = -3;
918 }
919 // Delete extrafields
920 $res = $this->deleteExtraFields();
921 if ($res < 0) {
922 $error = -4;
923 }
924 } else {
925 $this->error = $this->db->lasterror();
926 $error = -1;
927 }
928 } else {
929 $this->error = $this->db->lasterror();
930 $error = -2;
931 }
932 if (!$error && !$notrigger) {
933 // Call trigger
934 $result = $this->call_trigger('SUPPLIERBILLREC_DELETE', $user);
935 if ($result < 0) {
936 $error++;
937 }
938 // End call triggers
939 }
940 if (! $error) {
941 $this->db->commit();
942 return 1;
943 } else {
944 $this->db->rollback();
945 return $error;
946 }
947 }
948
975 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)
976 {
977 global $mysoc, $user;
978
979 include_once DOL_DOCUMENT_ROOT.'/core/lib/price.lib.php';
980
981 $facid = $this->id; //Supplier invoice template ID linked to
982
983 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);
984
985 // Check if object of the line is product or service
986 if ($type < 0) {
987 return -1;
988 }
989
990 $localtaxes_type = getLocalTaxesFromRate($txtva, 0, $this->thirdparty, $mysoc);
991
992 // Clean vat code
993 $reg = array();
994 $vat_src_code = '';
995 if (preg_match('/\‍((.*)\‍)/', (string) $txtva, $reg)) {
996 $vat_src_code = $reg[1];
997 $txtva = preg_replace('/\s*\‍(.*\‍)/', '', (string) $txtva); // Remove code into vatrate.
998 }
999
1000 // Clean parameters
1001 $fk_product = empty($fk_product) ? 0 : $fk_product;
1002 $label = empty($label) ? '' : $label;
1003 $remise_percent = empty($remise_percent) ? 0 : price2num($remise_percent);
1004 $qty = price2num($qty);
1005 $pu_ht = price2num($pu_ht);
1006 $pu_ttc = price2num($pu_ttc);
1007 if (!preg_match('/\‍((.*)\‍)/', $txtva)) {
1008 $txtva = price2num($txtva); // $txtva can have format '5.0(XXX)' or '5'
1009 }
1010 $txlocaltax1 = price2num($txlocaltax1);
1011 $txlocaltax2 = price2num($txlocaltax2);
1012 $txtva = !empty($txtva) ? $txtva : 0;
1013 $txlocaltax1 = !empty($txlocaltax1) ? $txlocaltax1 : 0;
1014 $txlocaltax2 = !empty($txlocaltax2) ? $txlocaltax2 : 0;
1015 $info_bits = !empty($info_bits) ? $info_bits : 0;
1016 $info_bits = !empty($info_bits) ? $info_bits : 0;
1017 $pu = $price_base_type == 'HT' ? $pu_ht : $pu_ttc;
1018
1019 // Calcul du total TTC et de la TVA pour la ligne a partir de qty, pu, remise_percent et txtva
1020 // TRES IMPORTANT: C'est au moment de l'insertion ligne qu'on doit stocker
1021 // la part ht, tva et ttc, et ce au niveau de la ligne qui a son propre taux tva.
1022
1023 $tabprice = calcul_price_total($qty, $pu, $remise_percent, $txtva, $txlocaltax1, $txlocaltax2, 0, $price_base_type, $info_bits, $type, $mysoc, $localtaxes_type, 100, $this->multicurrency_tx, $pu_ht_devise);
1024 $total_ht = $tabprice[0];
1025 $total_tva = $tabprice[1];
1026 $total_ttc = $tabprice[2];
1027 $total_localtax1 = $tabprice[9];
1028 $total_localtax2 = $tabprice[10];
1029 $pu_ht = $tabprice[3];
1030
1031 // MultiCurrency
1032 $multicurrency_total_ht = $tabprice[16];
1033 $multicurrency_total_tva = $tabprice[17];
1034 $multicurrency_total_ttc = $tabprice[18];
1035 $pu_ht_devise = $tabprice[19];
1036
1037 $this->db->begin();
1038 $product_type = $type;
1039 if ($fk_product) {
1040 $product = new Product($this->db);
1041 $result = $product->fetch($fk_product);
1042 if ($result < 0) {
1043 return -1;
1044 }
1045 $product_type = $product->type;
1046 if (empty($label)) {
1047 $label = $product->label;
1048 }
1049 }
1050
1051 $sql = 'INSERT INTO ' . MAIN_DB_PREFIX . 'facture_fourn_det_rec (';
1052 $sql .= 'fk_facture_fourn';
1053 $sql .= ', fk_product';
1054 $sql .= ', ref';
1055 $sql .= ', label';
1056 $sql .= ', description';
1057 $sql .= ', pu_ht';
1058 $sql .= ', pu_ttc';
1059 $sql .= ', qty';
1060 $sql .= ', remise_percent';
1061 $sql .= ', fk_remise_except';
1062 $sql .= ', vat_src_code';
1063 $sql .= ', tva_tx';
1064 $sql .= ', localtax1_tx';
1065 $sql .= ', localtax1_type';
1066 $sql .= ', localtax2_tx';
1067 $sql .= ', localtax2_type';
1068 $sql .= ', total_ht';
1069 $sql .= ', total_tva';
1070 $sql .= ', total_localtax1';
1071 $sql .= ', total_localtax2';
1072 $sql .= ', total_ttc';
1073 $sql .= ', product_type';
1074 $sql .= ', date_start';
1075 $sql .= ', date_end';
1076 $sql .= ', info_bits';
1077 $sql .= ', special_code';
1078 $sql .= ', rang';
1079 $sql .= ', fk_unit';
1080 $sql .= ', fk_user_author';
1081 $sql .= ', fk_multicurrency, multicurrency_code, multicurrency_subprice, multicurrency_total_ht, multicurrency_total_tva, multicurrency_total_ttc';
1082 $sql .= ') VALUES (';
1083 $sql .= ' ' . (int) $facid; // source supplier invoice id
1084 $sql .= ', ' . (!empty($fk_product) ? "'" . $this->db->escape($fk_product) . "'" : 'null');
1085 $sql .= ', ' . (!empty($ref) ? "'" . $this->db->escape($ref) . "'" : 'null');
1086 $sql .= ', ' . (!empty($label) ? "'" . $this->db->escape($label) . "'" : 'null');
1087 $sql .= ", '" . $this->db->escape($desc) . "'";
1088 $sql .= ', ' . price2num($pu_ht);
1089 $sql .= ', ' . price2num($pu_ttc);
1090 $sql .= ', ' . price2num($qty);
1091 $sql .= ', ' . price2num($remise_percent);
1092 $sql .= ', null';
1093 $sql .= ", '" . $this->db->escape($vat_src_code) . "'";
1094 $sql .= ', ' . price2num($txtva);
1095 $sql .= ', ' . price2num($txlocaltax1);
1096 $sql .= ", '" . $this->db->escape(isset($localtaxes_type[0]) ? $localtaxes_type[0] : '') . "'";
1097 $sql .= ', ' . price2num($txlocaltax2);
1098 $sql .= ", '" . $this->db->escape(isset($localtaxes_type[2]) ? $localtaxes_type[2] : '') . "'";
1099 $sql .= ', ' . price2num($total_ht);
1100 $sql .= ', ' . price2num($total_tva);
1101 $sql .= ', ' . price2num($total_localtax1);
1102 $sql .= ', ' . price2num($total_localtax2);
1103 $sql .= ', ' . price2num($total_ttc);
1104 $sql .= ', ' . (int) $product_type;
1105 $sql .= ', ' . ($date_start > 0 ? (int) $date_start : 'NULL');
1106 $sql .= ', ' . ($date_end > 0 ? (int) $date_end : 'NULL');
1107 $sql .= ', ' . (int) $info_bits;
1108 $sql .= ', ' . (int) $special_code;
1109 $sql .= ', ' . (int) $rang;
1110 $sql .= ', ' . ($fk_unit ? (int) $fk_unit : 'NULL');
1111 $sql .= ', ' . (int) $user->id;
1112 $sql .= ', ' . (int) $this->fk_multicurrency;
1113 $sql .= ", '" . $this->db->escape($this->multicurrency_code) . "'";
1114 $sql .= ', ' . price2num($pu_ht_devise, 'CU');
1115 $sql .= ', ' . price2num($multicurrency_total_ht, 'CT');
1116 $sql .= ', ' . price2num($multicurrency_total_tva, 'CT');
1117 $sql .= ', ' . price2num($multicurrency_total_ttc, 'CT');
1118 $sql .= ')';
1119
1120 dol_syslog(get_class($this). '::addline', LOG_DEBUG);
1121 if ($this->db->query($sql)) {
1122 $lineId = $this->db->last_insert_id(MAIN_DB_PREFIX. 'facture_fourn_det_rec');
1123 $this->update_price();
1124 $this->id = $facid;
1125 $this->db->commit();
1126 return $lineId;
1127 } else {
1128 $this->db->rollback();
1129 $this->error = $this->db->lasterror();
1130
1131 return -1;
1132 }
1133 }
1134
1162 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)
1163 {
1164 global $mysoc, $user;
1165
1166 $facid = $this->id;
1167
1168 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);
1169 include_once DOL_DOCUMENT_ROOT.'/core/lib/price.lib.php';
1170
1171 // Check parameters
1172 if ($type < 0) {
1173 return -1;
1174 }
1175
1176 // Clean parameters
1177 $fk_product = empty($fk_product) ? 0 : $fk_product;
1178 $label = empty($label) ? '' : $label;
1179 $remise_percent = empty($remise_percent) ? 0 : price2num($remise_percent);
1180 $qty = price2num($qty);
1181 $info_bits = empty($info_bits) ? 0 : $info_bits;
1182 $pu_ht = price2num($pu_ht);
1183 $pu_ttc = price2num($pu_ttc);
1184 $pu_ht_devise = price2num($pu_ht_devise);
1185
1186 if (!preg_match('/\‍((.*)\‍)/', (string) $txtva)) {
1187 $txtva = price2num($txtva); // $txtva can have format '5.0(XXX)' or '5'
1188 }
1189
1190 $txlocaltax1 = empty($txlocaltax1) ? 0 : price2num($txlocaltax1);
1191 $txlocaltax2 = empty($txlocaltax2) ? 0 : price2num($txlocaltax2);
1192 $this->multicurrency_total_ht = empty($this->multicurrency_total_ht) ? 0 : $this->multicurrency_total_ht;
1193 $this->multicurrency_total_tva = empty($this->multicurrency_total_tva) ? 0 : $this->multicurrency_total_tva;
1194 $this->multicurrency_total_ttc = empty($this->multicurrency_total_ttc) ? 0 : $this->multicurrency_total_ttc;
1195
1196 $pu = $price_base_type == 'HT' ? $pu_ht : $pu_ttc;
1197
1198
1199 // Calculate total with, without tax and tax from qty, pu, remise_percent and txtva
1200 // TRES IMPORTANT: C'est au moment de l'insertion ligne qu'on doit stocker
1201 // la part ht, tva et ttc, et ce au niveau de la ligne qui a son propre taux tva.
1202
1203 $localtaxes_type = getLocalTaxesFromRate($txtva, 0, $this->thirdparty, $mysoc);
1204
1205 // Clean vat code
1206 $vat_src_code = '';
1207 $reg = array();
1208 if (preg_match('/\‍((.*)\‍)/', $txtva, $reg)) {
1209 $vat_src_code = $reg[1];
1210 $txtva = preg_replace('/\s*\‍(.*\‍)/', '', $txtva); // Remove code into vatrate.
1211 }
1212
1213 $tabprice = calcul_price_total($qty, $pu, $remise_percent, $txtva, $txlocaltax1, $txlocaltax2, 0, $price_base_type, $info_bits, $type, $mysoc, $localtaxes_type, 100, $this->multicurrency_tx, $pu_ht_devise);
1214
1215 $total_ht = $tabprice[0];
1216 $total_tva = $tabprice[1];
1217 $total_ttc = $tabprice[2];
1218 $total_localtax1 = $tabprice[9];
1219 $total_localtax2 = $tabprice[10];
1220 $pu_ht = $tabprice[3];
1221 $pu_tva = $tabprice[4];
1222 $pu_ttc = $tabprice[5];
1223
1224 // MultiCurrency
1225 $multicurrency_total_ht = $tabprice[16];
1226 $multicurrency_total_tva = $tabprice[17];
1227 $multicurrency_total_ttc = $tabprice[18];
1228 $pu_ht_devise = $tabprice[19];
1229
1230 $product_type = $type;
1231 if ($fk_product) {
1232 $product = new Product($this->db);
1233 $result = $product->fetch($fk_product);
1234 $product_type = $product->type;
1235 }
1236
1237 $sql = 'UPDATE ' . MAIN_DB_PREFIX . 'facture_fourn_det_rec SET';
1238 $sql .= ' fk_facture_fourn = ' . ((int) $facid);
1239 $sql .= ', fk_product = ' . ($fk_product > 0 ? ((int) $fk_product) : 'null');
1240 $sql .= ", ref = '" . $this->db->escape($ref) . "'";
1241 $sql .= ", label = '" . $this->db->escape($label) . "'";
1242 $sql .= ", description = '" . $this->db->escape($desc) . "'";
1243 $sql .= ', pu_ht = ' . price2num($pu_ht);
1244 $sql .= ', qty = ' . price2num($qty);
1245 $sql .= ", remise_percent = '" . price2num($remise_percent) . "'";
1246 $sql .= ", vat_src_code = '" . $this->db->escape($vat_src_code) . "'";
1247 $sql .= ', tva_tx = ' . price2num($txtva);
1248 $sql .= ', localtax1_tx = ' . (float) $txlocaltax1;
1249 $sql .= ", localtax1_type = '" . $this->db->escape($localtaxes_type[0]) . "'";
1250 $sql .= ', localtax2_tx = ' . (float) $txlocaltax2;
1251 $sql .= ", localtax2_type = '" . $this->db->escape($localtaxes_type[2]) . "'";
1252 $sql .= ", total_ht = '" . price2num($total_ht) . "'";
1253 $sql .= ", total_tva = '" . price2num($total_tva) . "'";
1254 $sql .= ", total_localtax1 = '" . price2num($total_localtax1) . "'";
1255 $sql .= ", total_localtax2 = '" . price2num($total_localtax2) . "'";
1256 $sql .= ", total_ttc = '" . price2num($total_ttc) . "'";
1257 $sql .= ', product_type = ' . (int) $product_type;
1258 $sql .= ', date_start = ' . (empty($date_start) ? 'NULL' : (int) $date_start);
1259 $sql .= ', date_end = ' . (empty($date_end) ? 'NULL' : (int) $date_end);
1260 $sql .= ', info_bits = ' . (int) $info_bits;
1261 $sql .= ', special_code = ' . (int) $special_code;
1262 $sql .= ', rang = ' . (int) $rang;
1263 $sql .= ', fk_unit = ' . ($fk_unit ? "'" . $this->db->escape($fk_unit) . "'" : 'null');
1264 $sql .= ', fk_user_modif = ' . (int) $user;
1265 $sql .= ', multicurrency_subprice = '.price2num($pu_ht_devise);
1266 $sql .= ', multicurrency_total_ht = '.price2num($multicurrency_total_ht);
1267 $sql .= ', multicurrency_total_tva = '.price2num($multicurrency_total_tva);
1268 $sql .= ', multicurrency_total_ttc = '.price2num($multicurrency_total_ttc);
1269 $sql .= ' WHERE rowid = ' . (int) $rowid;
1270
1271 dol_syslog(get_class($this). '::updateline', LOG_DEBUG);
1272 if ($this->db->query($sql)) {
1273 $this->id = $facid;
1274 $this->update_price();
1275 return 1;
1276 } else {
1277 $this->error = $this->db->lasterror();
1278 return -1;
1279 }
1280 }
1281
1282
1290 public function getNextNumRef($soc, $mode = 'next')
1291 {
1292 // Not used for recurring invoices
1293 return '';
1294 }
1295
1301 public function getNextDate()
1302 {
1303 if (empty($this->date_when)) {
1304 return false;
1305 }
1306 return dol_time_plus_duree((int) $this->date_when, $this->frequency, $this->unit_frequency, 1);
1307 }
1308
1314 public function isMaxNbGenReached()
1315 {
1316 $ret = false;
1317 if ($this->nb_gen_max > 0 && ($this->nb_gen_done >= $this->nb_gen_max)) {
1318 $ret = true;
1319 }
1320 return $ret;
1321 }
1322
1329 public function strikeIfMaxNbGenReached($ret)
1330 {
1331 // Special case to strike the date
1332 return ($this->isMaxNbGenReached() ? '<strike>' : '').$ret.($this->isMaxNbGenReached() ? '</strike>' : '');
1333 }
1334
1345 public function createRecurringInvoices($restrictioninvoiceid = 0, $forcevalidation = 0)
1346 {
1347 global $conf, $langs, $db, $user, $hookmanager;
1348
1349 $error = 0;
1350 $nb_create = 0;
1351
1352 // Load translation files required by the page
1353 $langs->loadLangs(array('main', 'bills'));
1354
1355 $now = dol_now();
1356 $tmparray = dol_getdate($now);
1357 $today = dol_mktime(23, 59, 59, $tmparray['mon'], $tmparray['mday'], $tmparray['year']); // Today is last second of current day
1358
1359 dol_syslog('createRecurringInvoices restrictioninvoiceid=' .$restrictioninvoiceid. ' forcevalidation=' .$forcevalidation);
1360
1361 $sql = 'SELECT rowid FROM '.MAIN_DB_PREFIX.'facture_fourn_rec';
1362 $sql .= ' WHERE frequency > 0'; // A recurring supplier invoice is an invoice with a frequency
1363 $sql .= " AND (date_when IS NULL OR date_when <= '".$this->db->idate($today)."')";
1364 $sql .= ' AND (nb_gen_done < nb_gen_max OR nb_gen_max = 0)';
1365 $sql .= ' AND suspended = 0';
1366 $sql .= ' AND entity = '. (int) $conf->entity; // MUST STAY = $conf->entity here
1367 if ($restrictioninvoiceid > 0) {
1368 $sql .= ' AND rowid = '. (int) $restrictioninvoiceid;
1369 }
1370 $sql .= $this->db->order('entity', 'ASC');
1371 //print $sql;exit;
1372 $parameters = array(
1373 'restrictioninvoiceid' => $restrictioninvoiceid,
1374 'forcevalidation' => $forcevalidation,
1375 );
1376 $reshook = $hookmanager->executeHooks('beforeCreationOfRecurringInvoices', $parameters, $sql); // note that $sql might be modified by hooks
1377
1378 $resql = $this->db->query($sql);
1379 if ($resql) {
1380 $i = 0;
1381 $num = $this->db->num_rows($resql);
1382
1383 if ($num) {
1384 $this->output .= $langs->trans('FoundXQualifiedRecurringInvoiceTemplate', $num)."\n";
1385 } else {
1386 $this->output .= $langs->trans('NoQualifiedRecurringInvoiceTemplateFound');
1387 }
1388
1389 $saventity = $conf->entity;
1390 $laststep = "None";
1391
1392 while ($i < $num) { // Loop on each template invoice. If $num = 0, test is false at first pass.
1393 $line = $this->db->fetch_object($resql);
1394
1395 $this->db->begin();
1396
1397 $invoiceidgenerated = 0;
1398
1399 $new_fac_fourn = null;
1400 $facturerec = new FactureFournisseurRec($this->db);
1401 $laststep = "Fetch {$line->rowid}";
1402 $facturerec->fetch($line->rowid);
1403
1404 if ($facturerec->id > 0) {
1405 // Set entity context
1406 $conf->entity = $facturerec->entity;
1407
1408 dol_syslog('createRecurringInvoices Process invoice template id=' .$facturerec->id. ', ref=' .$facturerec->ref. ', entity=' .$facturerec->entity);
1409
1410 $new_fac_fourn = new FactureFournisseur($this->db);
1411 $new_fac_fourn->fac_rec = $facturerec->id; // We will create $facture from this recurring invoice
1412 $new_fac_fourn->fk_fac_rec_source = $facturerec->id; // We will create $facture from this recurring invoice
1413
1414 $new_fac_fourn->type = self::TYPE_STANDARD;
1415 $new_fac_fourn->subtype = $facturerec->subtype;
1416 $new_fac_fourn->statut = self::STATUS_DRAFT; // deprecated
1417 $new_fac_fourn->status = self::STATUS_DRAFT;
1418 $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.
1419 $new_fac_fourn->socid = $facturerec->socid;
1420 $new_fac_fourn->lines = $facturerec->lines;
1421 $new_fac_fourn->ref_supplier = $facturerec->ref_supplier;
1422 $new_fac_fourn->model_pdf = $facturerec->model_pdf;
1423 $new_fac_fourn->fk_project = $facturerec->fk_project;
1424 $new_fac_fourn->label = $facturerec->label;
1425 $new_fac_fourn->libelle = $facturerec->label; // deprecated
1426
1427 $invoiceidgenerated = $new_fac_fourn->create($user);
1428 $laststep = "Create invoiceidgenerated $invoiceidgenerated";
1429 if ($invoiceidgenerated <= 0) {
1430 $this->errors = $new_fac_fourn->errors;
1431 $this->error = $new_fac_fourn->error;
1432 $error++;
1433 }
1434 if (!$error && ($facturerec->auto_validate || $forcevalidation)) {
1435 $result = $new_fac_fourn->validate($user);
1436 $laststep = "Validate by user {$user->login}";
1437 if ($result <= 0) {
1438 $this->errors = $new_fac_fourn->errors;
1439 $this->error = $new_fac_fourn->error;
1440 $error++;
1441 }
1442 }
1443
1444 if (!$error && $facturerec->generate_pdf) {
1445 // We refresh the object in order to have all necessary data (like date_lim_reglement)
1446 $laststep = "Refresh ".$new_fac_fourn->id;
1447 $new_fac_fourn->fetch($new_fac_fourn->id);
1448 $laststep = "GenerateDocument ".$new_fac_fourn->id;
1449 $result = $new_fac_fourn->generateDocument($facturerec->model_pdf, $langs);
1450 if ($result < 0) {
1451 $this->errors = $new_fac_fourn->errors;
1452 $this->error = $new_fac_fourn->error;
1453 $error++;
1454 }
1455 }
1456 } else {
1457 $error++;
1458 $this->error = 'Failed to load invoice template with id=' .$line->rowid. ', entity=' .$conf->entity."\n";
1459 $this->errors[] = 'Failed to load invoice template with id=' .$line->rowid. ', entity=' .$conf->entity;
1460 dol_syslog('createRecurringInvoices Failed to load invoice template with id=' .$line->rowid. ', entity=' .$conf->entity);
1461 }
1462
1463 if (!$error && $invoiceidgenerated >= 0) {
1464 $facturerec->nb_gen_done++;
1465 $facturerec->date_last_gen = dol_now();
1466 $nextDate = $facturerec->getNextDate();
1467 $facturerec->date_when = (($nextDate === false) ? null : $nextDate);
1468 $facturerec->update($user);
1469 $this->db->commit('createRecurringInvoices Process invoice template id=' .$facturerec->id. ', title=' .$facturerec->title);
1470 dol_syslog('createRecurringInvoices Process invoice template ' .$facturerec->title. ' is finished with a success generation');
1471 $nb_create++;
1472 $this->output .= $langs->trans('InvoiceGeneratedFromTemplate', $new_fac_fourn->ref, $facturerec->title)."\n";
1473 } else {
1474 $this->db->rollback('createRecurringInvoices Process invoice template error='.$error.' invoiceidgenerated='.$invoiceidgenerated.' LastStep='.$laststep.' id=' .$facturerec->id. ', title=' .$facturerec->title);
1475 }
1476
1477 $parameters = array(
1478 'cpt' => $i,
1479 'total' => $num,
1480 'errorCount' => $error,
1481 'invoiceidgenerated' => $invoiceidgenerated,
1482 'facturerec' => $facturerec, // it's an object which PHP passes by "reference", so modifiable by hooks.
1483 'this' => $this, // it's an object which PHP passes by "reference", so modifiable by hooks.
1484 );
1485 $reshook = $hookmanager->executeHooks('afterCreationOfRecurringInvoice', $parameters, $new_fac_fourn); // note: $facture can be modified by hooks (warning: $facture can be null)
1486
1487 $i++;
1488 }
1489
1490 $conf->entity = $saventity; // Restore entity context
1491 } else {
1492 dol_print_error($this->db);
1493 }
1494
1495 $this->output = trim($this->output);
1496
1497 return $error ? $error : 0;
1498 }
1499
1512 public function getNomUrl($withpicto = 0, $option = '', $max = 0, $short = 0, $moretitle = '', $notooltip = 0, $save_lastsearch_value = -1)
1513 {
1514 global $langs, $hookmanager;
1515
1516 $result = '';
1517
1518 $label = '<u>'.$langs->trans('RepeatableInvoice').'</u>';
1519 if (!empty($this->ref)) {
1520 $label .= '<br><b>'.$langs->trans('Ref').':</b> '.$this->ref;
1521 }
1522 if ($this->frequency > 0) {
1523 $label .= '<br><b>'.$langs->trans('Frequency').':</b> '.$langs->trans('FrequencyPer_'.$this->unit_frequency, $this->frequency);
1524 }
1525 if (!empty($this->date_last_gen)) {
1526 $label .= '<br><b>'.$langs->trans('DateLastGeneration').':</b> '.dol_print_date($this->date_last_gen, 'dayhour');
1527 }
1528 if ($this->frequency > 0) {
1529 if (!empty($this->date_when)) {
1530 $label .= '<br><b>'.$langs->trans('NextDateToExecution').':</b> ';
1531 $label .= (empty($this->suspended) ? '' : '<strike>').dol_print_date($this->date_when, 'day').(empty($this->suspended) ? '' : '</strike>'); // No hour for this property
1532 if (!empty($this->suspended)) {
1533 $label .= ' ('.$langs->trans('Disabled').')';
1534 }
1535 }
1536 }
1537
1538 $url = DOL_URL_ROOT.'/fourn/facture/card-rec.php?facid='.$this->id;
1539
1540 if ($short) {
1541 return $url;
1542 }
1543
1544 if ($option != 'nolink') {
1545 // Add param to save lastsearch_values or not
1546 $add_save_lastsearch_values = ($save_lastsearch_value == 1 ? 1 : 0);
1547 if ($save_lastsearch_value == -1 && preg_match('/list\.php/', $_SERVER['PHP_SELF'])) {
1548 $add_save_lastsearch_values = 1;
1549 }
1550 if ($add_save_lastsearch_values) {
1551 $url .= '&save_lastsearch_values=1';
1552 }
1553 }
1554
1555 $linkstart = '<a href="'.$url.'" title="'.dol_escape_htmltag($label, 1).'" class="classfortooltip">';
1556 $linkend = '</a>';
1557
1558 $result .= $linkstart;
1559 if ($withpicto) {
1560 $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);
1561 }
1562 if ($withpicto != 2) {
1563 $result .= $this->ref;
1564 }
1565 $result .= $linkend;
1566 global $action;
1567 $hookmanager->initHooks(array($this->element . 'dao'));
1568 $parameters = array('id' => $this->id, 'getnomurl' => &$result);
1569 $reshook = $hookmanager->executeHooks('getNomUrl', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks
1570 if ($reshook > 0) {
1571 $result = $hookmanager->resPrint;
1572 } else {
1573 $result .= $hookmanager->resPrint;
1574 }
1575 return $result;
1576 }
1577
1585 public function getLibStatut($mode = 0, $alreadypaid = -1)
1586 {
1587 return $this->LibStatut($this->frequency ? 1 : 0, $this->suspended, $mode, $alreadypaid, empty($this->type) ? 0 : $this->type);
1588 }
1589
1590 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1602 public function LibStatut($recur, $status, $mode = 0, $alreadypaid = -1, $type = 0, $nbofopendirectdebitorcredittransfer = 0)
1603 {
1604 // phpcs:enable
1605 global $langs;
1606 $langs->load('bills');
1607
1608 $labelStatus = $langs->transnoentitiesnoconv('Active');
1609 $statusType = 'status0';
1610
1611 //print "$recur,$status,$mode,$alreadypaid,$type";
1612 if ($mode == 0) {
1613 if ($recur) {
1614 if ($status == self::STATUS_SUSPENDED) {
1615 $labelStatus = $langs->transnoentitiesnoconv('Disabled');
1616 } else {
1617 $labelStatus = $langs->transnoentitiesnoconv('Active');
1618 }
1619 } else {
1620 if ($status == self::STATUS_SUSPENDED) {
1621 $labelStatus = $langs->transnoentitiesnoconv('Disabled');
1622 } else {
1623 $labelStatus = $langs->transnoentitiesnoconv('Draft');
1624 }
1625 }
1626 } elseif ($mode == 1) {
1627 $prefix = 'Short';
1628 if ($recur) {
1629 if ($status == self::STATUS_SUSPENDED) {
1630 $labelStatus = $langs->transnoentitiesnoconv('Disabled');
1631 } else {
1632 $labelStatus = $langs->transnoentitiesnoconv('Active');
1633 }
1634 } else {
1635 if ($status == self::STATUS_SUSPENDED) {
1636 $labelStatus = $langs->transnoentitiesnoconv('Disabled');
1637 } else {
1638 $labelStatus = $langs->transnoentitiesnoconv('Draft');
1639 }
1640 }
1641 } elseif ($mode == 2) {
1642 if ($recur) {
1643 if ($status == self::STATUS_SUSPENDED) {
1644 $statusType = 'status6';
1645 $labelStatus = $langs->transnoentitiesnoconv('Disabled');
1646 } else {
1647 $statusType = 'status4';
1648 $labelStatus = $langs->transnoentitiesnoconv('Active');
1649 }
1650 } else {
1651 if ($status == self::STATUS_SUSPENDED) {
1652 $statusType = 'status6';
1653 $labelStatus = $langs->transnoentitiesnoconv('Disabled');
1654 } else {
1655 $statusType = 'status0';
1656 $labelStatus = $langs->transnoentitiesnoconv('Draft');
1657 }
1658 }
1659 } elseif ($mode == 3) {
1660 if ($recur) {
1661 $prefix = 'Short';
1662 if ($status == self::STATUS_SUSPENDED) {
1663 $statusType = 'status6';
1664 $labelStatus = $langs->transnoentitiesnoconv('Disabled');
1665 } else {
1666 $statusType = 'status4';
1667 $labelStatus = $langs->transnoentitiesnoconv('Active');
1668 }
1669 } else {
1670 if ($status == self::STATUS_SUSPENDED) {
1671 $statusType = 'status6';
1672 $labelStatus = $langs->transnoentitiesnoconv('Disabled');
1673 } else {
1674 $statusType = 'status0';
1675 $labelStatus = $langs->transnoentitiesnoconv('Draft');
1676 }
1677 }
1678 } elseif ($mode == 4) {
1679 $prefix = '';
1680 if ($recur) {
1681 if ($status == self::STATUS_SUSPENDED) {
1682 $statusType = 'status6';
1683 $labelStatus = $langs->transnoentitiesnoconv('Disabled');
1684 } else {
1685 $statusType = 'status4';
1686 $labelStatus = $langs->transnoentitiesnoconv('Active');
1687 }
1688 } else {
1689 if ($status == self::STATUS_SUSPENDED) {
1690 $statusType = 'status6';
1691 $labelStatus = $langs->transnoentitiesnoconv('Disabled');
1692 } else {
1693 $statusType = 'status0';
1694 $labelStatus = $langs->transnoentitiesnoconv('Draft');
1695 }
1696 }
1697 } elseif ($mode == 5 || $mode == 6) {
1698 $prefix = '';
1699 if ($mode == 5) {
1700 $prefix = 'Short';
1701 }
1702 if ($recur) {
1703 if ($status == self::STATUS_SUSPENDED) {
1704 $statusType = 'status6';
1705 $labelStatus = $langs->transnoentitiesnoconv('Disabled');
1706 } else {
1707 $statusType = 'status4';
1708 $labelStatus = $langs->transnoentitiesnoconv('Active');
1709 }
1710 } else {
1711 if ($status == self::STATUS_SUSPENDED) {
1712 $statusType = 'status6';
1713 $labelStatus = $langs->transnoentitiesnoconv('Disabled');
1714 } else {
1715 $statusType = 'status0';
1716 $labelStatus = $langs->transnoentitiesnoconv('Draft');
1717 }
1718 }
1719 }
1720
1721 $labelStatusShort = $labelStatus;
1722
1723 return dolGetStatus($labelStatus, $labelStatusShort, '', $statusType, $mode);
1724 }
1725
1734 public function initAsSpecimen($option = '')
1735 {
1736 global $user, $langs, $conf;
1737
1738 $now = dol_now();
1739 $arraynow = dol_getdate($now);
1740 $nownotime = dol_mktime(0, 0, 0, $arraynow['mon'], $arraynow['mday'], $arraynow['year']);
1741
1742 // Load array of products prodids
1743 $num_prods = 0;
1744 $prodids = array();
1745
1746 $sql = 'SELECT rowid';
1747 $sql .= ' FROM ' .MAIN_DB_PREFIX. 'product';
1748 $sql .= ' WHERE entity IN (' .getEntity('product'). ')';
1749 $sql .= $this->db->plimit(100);
1750
1751 $resql = $this->db->query($sql);
1752 if ($resql) {
1753 $num_prods = $this->db->num_rows($resql);
1754 $i = 0;
1755 while ($i < $num_prods) {
1756 $i++;
1757 $row = $this->db->fetch_row($resql);
1758 $prodids[$i] = $row[0];
1759 }
1760 }
1761
1762 // Initialize parameters
1763 $this->id = 0;
1764 $this->ref = 'SPECIMEN';
1765 $this->title = 'SPECIMEN';
1766 $this->specimen = 1;
1767 $this->socid = 1;
1768 $this->date = $nownotime;
1769 $this->date_lim_reglement = $nownotime + 3600 * 24 * 30;
1770 $this->cond_reglement_id = 1;
1771 $this->cond_reglement_code = 'RECEP';
1772 $this->date_lim_reglement = $this->calculate_date_lim_reglement();
1773 $this->mode_reglement_id = 0; // Not forced to show payment mode CHQ + VIR
1774 $this->mode_reglement_code = ''; // Not forced to show payment mode CHQ + VIR
1775 $this->note_public = 'This is a comment (public)';
1776 $this->note_private = 'This is a comment (private)';
1777 $this->note = 'This is a comment (private)';
1778 $this->fk_incoterms = 0;
1779 $this->location_incoterms = '';
1780
1781 if (empty($option) || $option != 'nolines') {
1782 // Lines
1783 $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)
1784 $xnbp = 0;
1785 while ($xnbp < $nbp) {
1786 $line = new FactureLigne($this->db);
1787 $line->desc = $langs->trans('Description'). ' ' .$xnbp;
1788 $line->qty = 1;
1789 $line->subprice = 100;
1790 $line->tva_tx = 19.6;
1791 $line->localtax1_tx = 0;
1792 $line->localtax2_tx = 0;
1793 $line->remise_percent = 0;
1794 if ($xnbp == 1) { // Qty is negative (product line)
1795 $prodid = mt_rand(1, $num_prods);
1796 $line->fk_product = $prodids[$prodid];
1797 $line->qty = -1;
1798 $line->total_ht = -100;
1799 $line->total_ttc = -119.6;
1800 $line->total_tva = -19.6;
1801 } elseif ($xnbp == 2) { // UP is negative (free line)
1802 $line->subprice = -100;
1803 $line->total_ht = -100;
1804 $line->total_ttc = -119.6;
1805 $line->total_tva = -19.6;
1806 $line->remise_percent = 0;
1807 } elseif ($xnbp == 3) { // Discount is 50% (product line)
1808 $prodid = mt_rand(1, $num_prods);
1809 $line->fk_product = $prodids[$prodid];
1810 $line->total_ht = 50;
1811 $line->total_ttc = 59.8;
1812 $line->total_tva = 9.8;
1813 $line->remise_percent = 50;
1814 } else { // (product line)
1815 $prodid = mt_rand(1, $num_prods);
1816 $line->fk_product = $prodids[$prodid];
1817 $line->total_ht = 100;
1818 $line->total_ttc = 119.6;
1819 $line->total_tva = 19.6;
1820 $line->remise_percent = 00;
1821 }
1822
1823 $this->lines[$xnbp] = $line;
1824 $xnbp++;
1825
1826 $this->total_ht += $line->total_ht;
1827 $this->total_tva += $line->total_tva;
1828 $this->total_ttc += $line->total_ttc;
1829 }
1830 $this->revenuestamp = 0;
1831
1832 // Add a line "offered"
1833 $line = new FactureLigne($this->db);
1834 $line->desc = $langs->trans('Description'). ' (offered line)';
1835 $line->qty = 1;
1836 $line->subprice = 100;
1837 $line->tva_tx = 19.6;
1838 $line->localtax1_tx = 0;
1839 $line->localtax2_tx = 0;
1840 $line->remise_percent = 100;
1841 $line->total_ht = 0;
1842 $line->total_ttc = 0; // 90 * 1.196
1843 $line->total_tva = 0;
1844 $prodid = mt_rand(1, $num_prods);
1845 $line->fk_product = $prodids[$prodid];
1846
1847 $this->lines[$xnbp] = $line;
1848 $xnbp++;
1849 }
1850
1851 $this->usenewprice = 0;
1852
1853 return 1;
1854 }
1855
1864 public static function replaceThirdparty(DoliDB $dbs, $origin_id, $dest_id)
1865 {
1866 $tables = array(
1867 'facture_fourn_rec'
1868 );
1869
1870 return CommonObject::commonReplaceThirdparty($dbs, $origin_id, $dest_id, $tables);
1871 }
1872
1880 public function setFrequencyAndUnit($frequency, $unit)
1881 {
1882 if (!$this->table_element) {
1883 dol_syslog(get_class($this). '::setFrequencyAndUnit was called on object with property table_element not defined', LOG_ERR);
1884 return -1;
1885 }
1886
1887 if (!empty($frequency) && empty($unit)) {
1888 dol_syslog(get_class($this). '::setFrequencyAndUnit was called on object with params frequency defined but unit not defined', LOG_ERR);
1889 return -2;
1890 }
1891
1892 $sql = "UPDATE ".MAIN_DB_PREFIX.$this->table_element;
1893 $sql .= " SET frequency = ".($frequency ? ((int) $frequency) : "NULL");
1894 if (!empty($unit)) {
1895 $sql .= ", unit_frequency = '".$this->db->escape($unit)."'";
1896 }
1897 $sql .= " WHERE rowid = ".((int) $this->id);
1898
1899 dol_syslog(get_class($this).'::setFrequencyAndUnit', LOG_DEBUG);
1900
1901 if ($this->db->query($sql)) {
1902 $this->frequency = $frequency;
1903 if (!empty($unit)) {
1904 $this->unit_frequency = $unit;
1905 }
1906 return 1;
1907 } else {
1908 $this->error = $this->db->lasterror();
1909 return -1;
1910 }
1911 }
1912
1920 public function setNextDate($date, $increment_nb_gen_done = 0)
1921 {
1922 if (!$this->table_element) {
1923 dol_syslog(get_class($this).'::setNextDate was called on object with property table_element not defined', LOG_ERR);
1924 return -1;
1925 }
1926 $sql = "UPDATE ".MAIN_DB_PREFIX.$this->table_element;
1927 $sql .= " SET date_when = " .($date ? "'".$this->db->idate($date)."'" : "NULL");
1928 if ($increment_nb_gen_done > 0) {
1929 $sql .= ", nb_gen_done = nb_gen_done + 1";
1930 }
1931 $sql .= " WHERE rowid = " . (int) $this->id;
1932
1933 dol_syslog(get_class($this).'::setNextDate', LOG_DEBUG);
1934
1935 if ($this->db->query($sql)) {
1936 $this->date_when = $date;
1937 if ($increment_nb_gen_done > 0) {
1938 $this->nb_gen_done++;
1939 }
1940 return 1;
1941 } else {
1942 $this->error = $this->db->lasterror();
1943 return -1;
1944 }
1945 }
1946
1953 public function setMaxPeriod($nb)
1954 {
1955 if (!$this->table_element) {
1956 dol_syslog(get_class($this).'::setMaxPeriod was called on object with property table_element not defined', LOG_ERR);
1957 return -1;
1958 }
1959
1960 if (empty($nb)) {
1961 $nb = 0;
1962 }
1963
1964 $sql = "UPDATE ".MAIN_DB_PREFIX.$this->table_element;
1965 $sql .= " SET nb_gen_max = ". (int) $nb;
1966 $sql .= " WHERE rowid = " . (int) $this->id;
1967
1968 dol_syslog(get_class($this).'::setMaxPeriod', LOG_DEBUG);
1969
1970 if ($this->db->query($sql)) {
1971 $this->nb_gen_max = $nb;
1972 return 1;
1973 } else {
1974 dol_print_error($this->db);
1975 return -1;
1976 }
1977 }
1978
1985 public function setAutoValidate($validate)
1986 {
1987 if (!$this->table_element) {
1988 dol_syslog(get_class($this).'::setAutoValidate was called on object with property table_element not defined', LOG_ERR);
1989 return -1;
1990 }
1991
1992 $sql = "UPDATE ".MAIN_DB_PREFIX.$this->table_element;
1993 $sql .= " SET auto_validate = ".((int) $validate);
1994 $sql .= " WHERE rowid = " . (int) $this->id;
1995
1996 dol_syslog(get_class($this).'::setAutoValidate', LOG_DEBUG);
1997
1998 if ($this->db->query($sql)) {
1999 $this->auto_validate = $validate;
2000 return 1;
2001 } else {
2002 dol_print_error($this->db);
2003 return -1;
2004 }
2005 }
2006
2013 public function setGeneratePdf($validate)
2014 {
2015 if (!$this->table_element) {
2016 dol_syslog(get_class($this).'::setGeneratePdf was called on object with property table_element not defined', LOG_ERR);
2017 return -1;
2018 }
2019
2020 $sql = "UPDATE ".MAIN_DB_PREFIX.$this->table_element;
2021 $sql .= " SET generate_pdf = ". (int) $validate;
2022 $sql .= " WHERE rowid = " . (int) $this->id;
2023
2024 dol_syslog(get_class($this).'::setGeneratePdf', LOG_DEBUG);
2025
2026 if ($this->db->query($sql)) {
2027 $this->generate_pdf = $validate;
2028 return 1;
2029 } else {
2030 dol_print_error($this->db);
2031 return -1;
2032 }
2033 }
2034
2041 public function setModelPdf($model)
2042 {
2043 if (!$this->table_element) {
2044 dol_syslog(get_class($this).'::setModelPdf was called on object with property table_element not defined', LOG_ERR);
2045 return -1;
2046 }
2047
2048 $sql = "UPDATE ".MAIN_DB_PREFIX.$this->table_element;
2049 $sql .= " SET modelpdf = '".$this->db->escape($model)."'";
2050 $sql .= " WHERE rowid = " . (int) $this->id;
2051
2052 dol_syslog(get_class($this).'::setModelPdf', LOG_DEBUG);
2053
2054 if ($this->db->query($sql)) {
2055 $this->model_pdf = $model;
2056 return 1;
2057 } else {
2058 dol_print_error($this->db);
2059 return -1;
2060 }
2061 }
2062}
$object ref
Definition info.php:89
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)
create($user, $facFournId, $notrigger=0)
Create a predefined supplier invoice.
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)
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.
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='', $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:/i', $dolibarr_main_db_pass)||!empty($dolibarr_main_db_encrypted_pass)) $conf db type
Definition repair.php:150