TUTOS PHP Cross Reference Groupware Applications

Source: /php/invoice/invoice.pinc - 1464 lines - 48702 bytes - Summary - Text - Print

Description: Copyright 2003 - 2013 by Gero Kohnert

   1  <?php
   2  /**
   3   *  Copyright 2003 - 2013 by Gero Kohnert
   4   *
   5   *  This program is free software; you can redistribute it and/or modify it
   6   *  under the terms of the GNU General Public License as published by the
   7   *  Free Software Foundation; version 2 of the License.
   8   *
   9   *  SVN Info  $Id: invoice.pinc 1202 2013-12-14 19:54:29Z gokohnert $
  10   *  $Author: gokohnert $
  11   */
  12  $tutos['files'][__FILE__] = '$Rev: 1202 $';
  13  
  14  define ('INV_STATE_NEW',1);
  15  define ('INV_STATE_READY',2);
  16  define ('INV_STATE_PAYNOW',3);
  17  define ('INV_STATE_REMINDED',4);
  18  define ('INV_STATE_PAYED',7);
  19  define ('INV_STATE_CANCELLED',8);
  20  
  21  loadmodule('stc');
  22  
  23  /** ---------------------------------------------------------------------------
  24   */
  25  function InvoiceAskState ($default,$any = 0) {
  26      global $lang,$tutos,$current_user;
  27  
  28      $stc = getObject($current_user->dbconn,$tutos['invoice_state_stc']);
  29      if (!is_object($stc)) {
  30          $stc = new stc(null);
  31          $stc->initByArray('InvoiceStates',null);
  32      }
  33  
  34      $r = '<select id="state" name="state">';
  35      foreach ($stc->states as $f) {
  36          if($f->stc_state == STC_NOT_EXISTANT) continue;
  37          $r .= '  <option value="'. $f->stc_state .'" style="background:'.$f->color.'"';
  38          if ( $f->stc_state == $default ) {
  39              $r .= ' selected="selected"';
  40          }
  41          $r .= '>'. myentities($f->getFullName()) ."</option>\n";
  42      }
  43      if ( $any > 0 ) {
  44          $r .= '<option value="-1"';
  45          if ( -1 == $default ) {
  46              $r .= ' selected="selected"';
  47          }
  48          $r .= '>'. $lang['any'] .'</option>';
  49      }
  50      // Any but not closed
  51      if ( $any == 2 ) {
  52          $r .= '<option value="-2"';
  53          if ( -2 == $default ) {
  54              $r .= ' selected="selected"';
  55          }
  56          $r .= '>'. $lang['InvAnyUnpaid'] .'</option>';
  57      }
  58      $r .= "\n</select>";
  59      return $r;
  60  }
  61  /**
  62   * List all invoices
  63   * cols > 0  make sperate rows with cols columns for each note
  64   */
  65  function showInvoice(tutos_user $user,tutos_base $obj,$rows = 0) {
  66      global $tutos,$lang;
  67  
  68      $r   = '';
  69      $pre = '';
  70  
  71      $n = 1;
  72      $x = count($obj->list[useinvoice][1]);
  73  
  74      if (($obj->getType() == 'company') ||
  75          ($obj->getType() == 'department') ||
  76          ($obj->getType() == 'address')
  77          ) {
  78          $link = 'invoice/invoice_overview.php?customerid='.$obj->id;
  79      } else {
  80          $link = 'invoice/invoice_overview.php?link_id='.$obj->id;
  81      }
  82      if ( $rows == 0 ) {
  83          $rows = $tutos['maxshort'];
  84      }
  85      if ( $rows == -1 ) {
  86          $rows = $x;
  87      }
  88      if ($x > 0) {
  89          foreach ( $obj->list[useinvoice][1] as $i => $f) {
  90              if ( ($n >= $rows) && ( $x != $rows ) ) {
  91                  $r .=  $pre . $user->layout->theme->getImage(folder,'list') ." ". makelink($link,sprintf($lang['AllEntries'], $x));
  92                  break;
  93              }
  94              $r .= $pre . $user->layout->theme->getImage(paper,'list') .' '. $f->creation->getDate() .' : '. $f->getLink() .' : '.$f->creator->getLink($f->creator->getShortname())." : ". $f->getState() ;
  95              $pre = "<br />\n";
  96              $n++;
  97          }
  98          if (($n < $rows) || ($x == $rows)) {
  99              $linktitle = $lang['InvOverview'];
 100              $r .= $pre.$user->layout->theme->getImage(folder,'list') ." ". makelink($link,$linktitle);
 101          }
 102      }
 103  
 104  
 105      $n = 1;
 106      $x = count($obj->list[useinvoice][2]);
 107      $link = 'invoice/invoice_overview.php?pos_id='.$obj->id;
 108      if ( $rows == 0 ) {
 109          $rows = $tutos['maxshort'];
 110      }
 111      if ( $rows == -1 ) {
 112          $rows = $x;
 113      }
 114      if ($x > 0) {
 115          foreach ( $obj->list[useinvoice][2] as $i => $f) {
 116              $r .= $pre .$user->layout->theme->getImage(paper,'list') .' '.$lang['InvPosPos'].' '. $f->creation->getDate() .' : '. $f->getLink() .' : '.$f->creator->getLink($f->creator->getShortname()).' : '. $f->getState() ;
 117              $pre = "<br />\n";
 118              $n++;
 119          }
 120          if ( $x > 1 ) {
 121              $linktitle = $lang['InvOverview'];
 122              $r .= $pre.$user->layout->theme->getImage(folder,'list') ." ". makelink($link,$linktitle);
 123          }
 124      }
 125      return $r;
 126  }
 127  
 128  /**
 129   * A invoice position
 130   *
 131   * @package invoice
 132   */
 133  class Invpos extends tutos_base {
 134      /**
 135       *
 136       */
 137      function invpos(tutos_db $dbconn) {
 138          global $tutos,$table;
 139  
 140          $this->init($dbconn);
 141          $this->tablename   = $this->dbconn->prefix .$table['invpos'][name];
 142          $this->description = '??';
 143          $this->currency    = $tutos[currencies][0];
 144          $this->items       = 0;
 145          $this->sum_single  = 0.0;
 146          $this->itype       = '*';
 147          $this->inv_id      = -1;
 148          $this->ref_id      = -1;
 149          $this->ref         = -1;
 150          $this->tax         = 0;
 151          $this->ADD         = false;
 152          $this->DELETE      = false;
 153          $this->run_postinit_hook();
 154      }
 155  
 156      function read_result (result $r, $pos ) {
 157          $this->id          = $r->get($pos, 'id');
 158          $this->ref_id      = $r->get($pos, 'ref_id');
 159          $this->inv_id      = $r->get($pos, 'inv_id');
 160          $this->items       = $r->get($pos, 'items');
 161          $this->itype       = $r->get($pos, 'ityp');
 162          $this->pos         = $r->get($pos, 'pos');
 163          $this->description = $r->get($pos, 'description');
 164          $this->sum_single  = $r->get($pos, 'sum_single');
 165          $this->currency  = $r->get($pos, 'currency');
 166          if ($this->currency == '' ) {
 167              $this->currency  = '?';
 168          }
 169          $this->tax  = $r->get($pos, 'tax');
 170          $this->ref  = -1;
 171          $this->inv  = -1;
 172      }
 173  
 174      /**
 175       *
 176       */
 177      static function gettypeid () {
 178          return useinvoice;
 179      }
 180  
 181      function exportXML_body () {
 182          $r = parent::exportXML_body();
 183          $r .= '<pos>'.$this->pos.'</pos>';
 184          $r .= '<description>'. htmlspecialchars($this->description).'</description>';
 185          $r .= '<currency>'. htmlspecialchars($this->currency).'</currency>';
 186          $r .= '<items>'.$this->items.'</items>';
 187          $r .= '<itype>'. htmlspecialchars($this->itype).'</itype>';
 188          $r .= '<ref_id>'.$this->ref_id.'</ref_id>';
 189          $r .= '<tax>'.$this->tax.'</tax>';
 190          return $r;
 191      }
 192  
 193  
 194      /**
 195       * preset the object with data from $obj
 196       */
 197      function read_ref() {
 198          if ( !is_object($this->ref) && ($this->ref_id > -1) ) {
 199              $this->ref = getObject($this->dbconn,$this->ref_id);
 200          }
 201          if ( !is_object($this->inv) && ($this->inv_id > -1) ) {
 202              $this->inv = new invoice($this->dbconn);
 203              $this->inv = $this->inv->read($this->inv_id,$this->inv);
 204          }
 205      }
 206  
 207      /**
 208       * preset the object with data from $obj
 209       */
 210      function set(Invoice $inv,tutos_base $obj) {
 211          global $lang;
 212  
 213          $this->inv_id = $inv->id;
 214          $this->inv = $inv;
 215          $this->ref_id = $obj->id;
 216          $this->ref = $obj;
 217  
 218          if ( !is_object($obj) ) {
 219          } else
 220              if ( $obj->gettype() == 'product' ) {
 221                  $this->items = 1;
 222                  $this->itype = $lang['pcs'];
 223                  $this->sum_single = $obj->price;
 224                  $this->description = $lang[$obj->getType()] ."\n". $obj->getFullName();
 225                  $this->currency = $obj->currency;
 226                  $this->itype = $lang['pcs'];
 227              } else if ( $obj->gettype() == 'installation' ) {
 228                  $this->items = 1;
 229                  $this->itype = $lang['pcs'];
 230                  $this->sum_single = $obj->money;
 231                  $this->currency = $obj->currency;
 232                  $this->description = $lang[$obj->getType()] ."\n". $obj->getFullName();
 233                  $this->itype = $lang['pcs'];
 234              } else if ( $obj->gettype() == 'timetrack' ) {
 235                  $this->items = $obj->volume;
 236                  $this->itype = $lang['hours'];
 237                  $this->sum_single = $obj->cph;
 238                  $this->description = '';
 239                  if (is_object($obj->ref)) {
 240                      $this->description .=  $lang[$obj->ref->getType()] .' '. $obj->ref->getFullName() ."\n";
 241                  }
 242                  $this->description .= $lang[$obj->getType()] ."\n". $obj->desc;
 243                  $this->currency = $obj->currency;
 244              } else if ( $obj->gettype() == 'bugtracking' ) {
 245                  $this->items = 1;
 246                  $this->itype = $lang['pcs'];
 247                  $this->sum_single = 0;
 248                  $this->description = $lang[$obj->getType()] ."\n". $obj->short;
 249              } else if ( $obj->gettype() == 'task' ) {
 250                  $this->items = 1;
 251                  $this->itype = $lang['pcs'];
 252                  $this->description = $lang[$obj->getType()] ."\n". $obj->name;
 253                  $this->sum_single = 0;
 254                  $obj->readtimetrack();
 255                  @reset($obj->ttlist) ;
 256                  foreach($obj->ttlist as $i2 => $f2) {
 257                      if ( $f2->state != TT_STATE_CHECKED ) {
 258                          // Show only checked entries
 259                          continue;
 260                      }
 261                      if ( $f2->inv_id != -1 ) {
 262                          // Show only entries without a invoice
 263                          continue;
 264                      }
 265                      $this->sum_single += $f2->volume * $f2->cph;
 266                      $this->currency = $f2->currency;
 267                      $this->description .= "\n". $f2->wday->getDate() .' '. $f2->volume .' '. $lang['hours'] .' '. $lang['InvPosSingle'] .' '. $f2->cph .' '. $f2->currency;
 268                  }
 269  
 270              } else if ( $obj->gettype() == 'expense' ) {
 271                  $this->items = 1;
 272                  $this->itype = $lang['pcs'];
 273                  $this->description = $lang[$obj->getType()] ."\n". $obj->getCategory() ."\n". $obj->getFullName();
 274                  $this->currency = $obj->currency;
 275                  $this->tax = $obj->itax;
 276                  $this->sum_single = $obj->getNetAmount();
 277              } else  {
 278                  $this->items = 1;
 279                  $this->description = $lang[$obj->getType()] ."\n". $obj->getFullName();
 280              }
 281      }
 282  
 283      /**
 284       *
 285       */
 286      function getTotal() {
 287          if ( $this->tax != 0 ) {
 288              return $this->sum_single * $this->items * (1 + ($this->tax/100.0));
 289          } else {
 290              return $this->sum_single * $this->items;
 291          }
 292      }
 293  
 294      /**
 295       * save a invoice position
 296       */
 297      function save() {
 298          global $table,$tutos;
 299  
 300          $msg = $this->run_presave_hook();
 301  
 302          $q = new query($this->dbconn);
 303          $q->setTable($this->tablename);
 304          $q->addFV('pos',$this->pos,'INT');
 305          $q->addFV('ref_id',$this->ref_id,'INT');
 306          $q->addFV('inv_id',$this->inv_id,'INT');
 307          $q->addFV('items',$this->items,'FLOAT');
 308          $q->addFV('ityp',$this->itype,'STRING',$table['invpos']['ityp'][size]);
 309          $q->addFV('description',$this->description,'STRING',$table['invpos']['description'][size]);
 310          $q->addFV('sum_single',$this->sum_single,'FLOAT');
 311          $q->addFV('tax',$this->tax,'FLOAT');
 312          $q->addFV('currency',$this->currency,'STRING');
 313  
 314          if ( $this->id < 0 ) {
 315              if ( isset($this->newid) ) {
 316                  $this->id = $this->newid;
 317                  $q->addFV('id',$this->id,'');
 318              } else {
 319                  $this->id = $q->addFV('id',-1,'NEXTID');
 320              }
 321              $query = $q->getInsert();
 322          } else {
 323              $q->addWC('id',$this->id,'');
 324              $query = $q->getUpdate();
 325          }
 326  
 327          $r = $this->dbconn->Exec($query);
 328          $r->free();
 329  
 330          if ( is_object($this->ref) && ($this->ref->getType() == 'expense') ) {
 331              //$this->ref->SetInvoice($this->inv_id);
 332              $msg = addLine($msg,$this->ref->save());
 333          }
 334          if ( is_object($this->ref) && ($this->ref->getType() == 'timetrack') ) {
 335              $this->ref->SetInvoice($this->inv_id);
 336              if ($this->inv->state == INV_STATE_PAYED) {
 337                  $this->ref->SetState($tutos['timetrack_payed_state']);
 338              } else {
 339                  $this->ref->SetState($tutos['timetrack_cleared_state']);
 340              }
 341              $msg = addLine($msg,$this->ref->save());
 342          }
 343          if ( $this->ADD && is_object($this->ref) && ($this->ref->getType() == 'task') ) {
 344              $this->ref->readtimetrack();
 345              foreach ($this->ref->ttlist as $i2 => $f2) {
 346                  if ( $f2->state != TT_STATE_CHECKED ) {
 347                      // change only checked entries
 348                      continue;
 349                  }
 350                  if ( ($f2->inv_id != -1) && ($f2->inv_id != $this->inv_id) ) {
 351                      continue;
 352                  }
 353                  $f2->SetInvoice($this->inv_id);
 354                  // if the state is paided then mark the timetracks as paid
 355                  if ($this->inv->state == INV_STATE_PAYED) {
 356                      $f2->SetState($tutos['timetrack_payed_state']);
 357                  } else {
 358                      $f2->SetState($tutos['timetrack_cleared_state']);
 359                  }
 360                  $msg = addLine($msg,$f2->save());
 361              }
 362          }
 363          return $msg;
 364      }
 365  
 366      /**
 367       * delete a position in an invoice
 368       */
 369      function delete() {
 370          global $table;
 371  
 372          $msg = '';
 373  
 374          $this->read_ref();
 375          if ( is_object($this->ref) ) {
 376              if ( $this->ref->getType() == 'task' ) {
 377                  $this->ref->readtimetrack();
 378                  foreach ($this->ref->ttlist as $i2 => $f2) {
 379                      if ( $f2->inv_id != $this->inv_id ) {
 380                          // change our entries
 381                          continue;
 382                      }
 383                      $f2->SetInvoice(-1);
 384                      $f2->SetState(TT_STATE_CHECKED);
 385                      $msg = addLine($msg,$f2->save());
 386                  }
 387              } else if ( $this->ref->getType() == 'timetrack' ) {
 388                  $this->ref->SetState(TT_STATE_CHECKED);
 389                  $this->ref->SetInvoice(-1);
 390                  $msg = addLine($msg,$this->ref->save());
 391              } else if ( $this->ref->getType() == 'expense' ) {
 392                  //$this->ref->SetInvoice(-1);
 393                  $msg = addLine($msg,$this->ref->save());
 394              }
 395          }
 396          $msg = addLine($msg,parent::delete());
 397          return $msg;
 398      }
 399  
 400      /**
 401       * Transfer reference ids according to given table
 402       */
 403      function transfer_ids (&$trans) {
 404          parent::transfer_ids ($trans);
 405          if (isset($trans[$this->ref_id])) {
 406              $this->ref_id = $trans[$this->ref_id];
 407          }
 408          if (isset($trans[$this->inv_id])) {
 409              $this->inv_id = $trans[$this->inv_id];
 410          }
 411          return;
 412      }
 413  
 414      /**
 415       * get the type of object
 416       */
 417      static function gettype () {
 418          return 'invpos';
 419      }
 420  }
 421  
 422  /**
 423   * A invoice
 424   *
 425   * @package invoice
 426   */
 427  class Invoice extends Tutos_module {
 428      /**
 429       * URL to use for modify this object
 430       */
 431      protected $modurl  = 'invoice/invoice_new.php';
 432      /**
 433       * URL to use for display this object
 434       */
 435      protected $showurl = 'invoice/invoice_show.php';
 436      /**
 437       * revision of file
 438       */
 439      static public $revision = '$Rev: 1202 $';
 440  
 441  
 442      /**
 443       *
 444       */
 445      function invoice(tutos_db $dbconn) {
 446          global $current_user,$tutos;
 447  
 448          $this->init($dbconn);
 449  
 450          $this->name        = 'auto';
 451          $this->state       = 1;
 452          $this->pos         = array();
 453          $this->link_id     = -1;
 454          $this->ref         = null;
 455          $this->customer_id = -1;
 456          $this->customer    = null;
 457          $this->accountant  = $current_user->id;
 458          $this->datesent[0] = new TUTOS_Date_Time(0);
 459          $this->datedue[0]  = new TUTOS_Date_Time(0);
 460  
 461          $this->datesent[1] = new TUTOS_Date_Time(0);
 462          $this->datedue[1]  = new TUTOS_Date_Time(0);
 463  
 464          $this->datesent[2] = new TUTOS_Date_Time(0);
 465          $this->datedue[2]  = new TUTOS_Date_Time(0);
 466  
 467          $this->d_sent0 = &$this->datesent[0];
 468          $this->d_sent1 = &$this->datesent[1];
 469          $this->d_sent2 = &$this->datesent[2];
 470          $this->d_due0 = &$this->datedue[0];
 471          $this->d_due1 = &$this->datedue[1];
 472          $this->d_due2 = &$this->datedue[2];
 473  
 474          $this->datefinish  = new TUTOS_Date_Time(0);
 475  
 476          $this->tablename   = $this->dbconn->prefix .'invoice';
 477          $this->tablename2  = $this->dbconn->prefix .'invoice_pos';
 478          $this->run_postinit_hook();
 479      }
 480  
 481      /**
 482       *
 483       */
 484      function read_result (result $r, $pos ) {
 485          $this->name        = $r->get($pos, 'name');
 486          $this->state       = $r->get($pos, 'state');
 487          $this->link_id     = $r->get($pos, 'link_id');
 488          $this->accountant  = $r->get($pos, 'accountant');
 489          $this->customer_id = $r->get($pos, 'customer');
 490          $this->customer    = $r->getObject($pos,'customer');
 491  
 492          $this->datesent[0] = $r->getDateTime($pos, 'd_sent0');
 493          $this->datesent[1] = $r->getDateTime($pos, 'd_sent1');
 494          $this->datesent[2] = $r->getDateTime($pos, 'd_sent2');
 495          $this->datedue[0] = $r->getDateTime($pos, 'd_due0');
 496          $this->datedue[1] = $r->getDateTime($pos, 'd_due1');
 497          $this->datedue[2] = $r->getDateTime($pos, 'd_due2');
 498          $this->datefinish = $r->getDateTime($pos, 'd_finish');
 499  
 500          $this->creator     = getObject($this->dbconn,$r->get($pos, 'creator'));
 501  
 502          $this->pos = array();
 503          parent::read_result($r,$pos);
 504          return;
 505      }
 506  
 507      /**
 508       * read the positions of this invoice
 509       */
 510      function read_pos () {
 511          if ( empty($this->id) ) return;
 512          if ( -1 == $this->id ) return;
 513  
 514          $q = 'SELECT * FROM '. $this->tablename2 .' WHERE inv_id ='. $this->id .' ORDER BY pos';
 515          $r = $this->dbconn->Exec($q);
 516          $n = $r->numrows();
 517  
 518          if ( 0 == $n) {
 519              return;
 520          }
 521          $a = 0;
 522          while ($a < $n) {
 523              $i = new invpos($this->dbconn);
 524              $i->read_result($r,$a);
 525              $i->invoice = &$this;
 526              $this->pos[$i->id] = &$i;
 527              unset ($i);
 528              $a++;
 529          }
 530          $r->free();
 531      }
 532  
 533      /**
 534       * read the positions of this invoice
 535       */
 536      function add_pos ($x) {
 537          $obj = getObject($this->dbconn,$x);
 538  
 539          $p = new invpos($this->dbconn);
 540          $p->set($this,$obj);
 541          $p->pos = count($this->pos) + 1;
 542  
 543          // this is a new one
 544          $p->ADD = true;
 545  
 546          $this->pos[] = &$p;
 547          unset($p);
 548      }
 549  
 550      /**
 551       * save the positions of this invoice
 552       */
 553      function save_pos () {
 554  
 555          $r = '';
 556          if ( empty($this->id) ) return;
 557          if ( -1 == $this->id ) return;
 558  
 559          foreach ($this->pos as $f) {
 560              if ( isset($f->DELETE) && ($f->DELETE == true) ) {
 561                  $f->read_ref();
 562                  // change the positions state back to something
 563                  if (is_object($f->ref) && $f->ref->getType() == 'timetrack') {
 564                  }
 565                  $r .= $f->delete();
 566                  $f->id = -1;
 567                  unset($f);
 568              }
 569          }
 570  
 571          $pos = 1;
 572          foreach ($this->pos as $f) {
 573              if ( isset($f->DELETE) && ($f->DELETE == true) ) {
 574                  continue;
 575              }
 576              $f->pos = $pos++;
 577              $f->inv_id = $this->id;
 578              $f->inv = $this;
 579              $f->read_ref();
 580              $r .= $f->save();
 581              unset($f);
 582          }
 583          return $r;
 584      }
 585  
 586      /**
 587       *
 588       */
 589      function read_ref () {
 590          $this->ref = getObject($this->dbconn,$this->link_id,0);
 591          $this->acc = getObject($this->dbconn,$this->accountant,0);
 592      }
 593  
 594      /**
 595       * is the invoice in a state where chenges are possible
 596       */
 597      function change_ok() {
 598          if ( ! is_object($this->ref)) {
 599              return 0;
 600          }
 601          if ( ($this->state == 3) || ( $this->state == INV_STATE_PAYED) ) {
 602              // to be payed
 603              return 0;
 604          }
 605          // default yes we can change
 606          return 1;
 607      }
 608  
 609      function exportXML_body () {
 610          $r = parent::exportXML_body();
 611          $r .= '<name>'. htmlspecialchars($this->name).'</name>';
 612          $r .= '<state>'.$this->state.'</state>';
 613          $r .= '<customer_id>'.$this->customer_id.'</customer_id>';
 614          $r .= '<accountant>'.$this->accountant.'</accountant>';
 615          $r .= '<datesent>'.$this->datesent[0]->exportXML_body().'</datesent>';
 616          $r .= '<datedue>'.$this->datedue[0]->exportXML_body().'</datedue>';
 617          $r .= '<datefinish>'.$this->datefinish->exportXML_body().'</datefinish>';
 618          $this->read_pos();
 619          if ( isset($this->pos) && (count($this->pos) > 0) ) {
 620              foreach($this->pos as $i => $f) {
 621                  $r .= $f->exportXML_start();
 622                  $r .= $f->exportXML_body();
 623                  $r .= $f->exportXML_end();
 624              }
 625          }
 626          return $r;
 627      }
 628  
 629      /**
 630       * the url where we go after deleting this object
 631       */
 632      function get_after_del_url () {
 633          return 'invoice/invoice_select.php';
 634      }
 635  
 636      /**
 637       * Return a fullname i.e name
 638       */
 639      function getFullname() {
 640          return sprintf('%s',$this->name);
 641      }
 642  
 643      /**
 644       * Return the sum of all positions
 645       */
 646      function getSum() {
 647          $sum[0] = 0;
 648          $sum[1] = 0;
 649          @reset($this->pos) ;
 650          while ( list ($i,$f) = @each ($this->pos) ) {
 651          }
 652          return $sum;
 653      }
 654  
 655      /**
 656       * Return a link to this appointment
 657       */
 658      function getLink($text = '',$arg = '') {
 659          global $lang;
 660  
 661          if ( empty($text) ) {
 662              $text = myentities($this->getFullname());
 663          }
 664  
 665          if ( $this->see_ok() ) {
 666              return makelink($this->getURL($arg),$text,sprintf($lang['InvLinkInfo'],$this->getFullName()) );
 667          } else {
 668              return $text;
 669          }
 670      }
 671  
 672      /**
 673       * get current state of this invoice
 674       */
 675      function getState ($s = "") {
 676          global $tutos,$lang;
 677  
 678          $r = '';
 679          if ( empty($s) ) {
 680              $s = $this->state;
 681          }
 682          $r .= '<span class="invstate'. $s .'">';
 683  
 684          $stc = getObject($this->dbconn,$tutos['invoice_state_stc']);
 685          if (!is_object($stc)) {
 686              $stc = new stc(null);
 687              $stc->initByArray('InvoiceStates',null);
 688          }
 689          $r .= $stc->getState($s);
 690          $r .= '</span>';
 691          return $r;
 692      }
 693  
 694      /**
 695       * create a select list with possible states
 696       */
 697      function askState () {
 698          global $tutos;
 699  
 700          $r = '';
 701          $stc = getObject($this->dbconn,$tutos['invoice_state_stc']);
 702          if (!is_object($stc)) {
 703              $stc = new stc(null);
 704              $stc->initByArray('InvoiceStates',null);
 705          }
 706          $r .= $stc->getStateSelection($this->state,'state');
 707          return $r;
 708      }
 709  
 710      /**
 711       * Set the state
 712       */
 713      function setState($value) {
 714          global $tutos;
 715  
 716          if ( $this->setIntField("state",$value,"InvoiceState") ){
 717              if ( ($value == INV_STATE_PAYED) || ($value == INV_STATE_CANCELLED) ) {
 718                  $this->setDateFinish(new TUTOS_Date_Time());
 719              }
 720              // set the state of positions
 721              foreach ($this->pos as $f) {
 722                  $f->read_ref();
 723                  if (is_object($f->ref) && $f->ref->getType() == 'timetrack') {
 724                      if ($value == INV_STATE_PAYED) {
 725                          $f->ref->setState($tutos['timetrack_payed_state']);
 726                      } else {
 727                          $f->ref->setState($tutos['timetrack_cleared_state']);
 728                      }
 729                  }
 730                  if (is_object($f->ref) && $f->ref->getType() == 'task') {
 731                      $f->ref->readtimetrack();
 732                      foreach ($f->ref->ttlist as $i2 => $f2) {
 733                          if ($value == INV_STATE_PAYED) {
 734                              $f2->setState($tutos['timetrack_payed_state']);
 735                          } else {
 736                              $f2->setState($tutos['timetrack_cleared_state']);
 737                          }
 738                      }
 739                  }
 740              }
 741  
 742          }
 743      }
 744  
 745      /**
 746       * Set the Accountant
 747       */
 748      function setAccountant($value) {
 749          $this->setIntField("accountant",$value,"Accountant");
 750      }
 751  
 752      /**
 753       * Set the name
 754       */
 755      function setName($value) {
 756          global $tutos,$sequence;
 757  
 758          if ( $value == "auto" ) {
 759              $value = strftime($tutos['inv_autoname']);
 760              $value = preg_replace('/&X/',''.$this->dbconn->nextid($sequence["invname"][name]),$value);
 761              if (is_object($this->ref)) {
 762                  $value = preg_replace('/&Y/',$this->ref->id,$value);
 763                  $value = preg_replace('/&Z/',$this->ref->getFullName(),$value);
 764              }
 765          }
 766  
 767          $value = preg_replace('/&Y/','',$value);
 768          $value = preg_replace('/&Z/','',$value);
 769          $this->setStrField("name",$value,"InvoiceName");
 770      }
 771  
 772      /**
 773       * set the Customer
 774       */
 775      function setCustomer(&$obj) {
 776          if (!is_object($obj)) return;
 777          if ( ($this->customer_id != $obj->id) ) {
 778              $this->modified[] = array ( "field" => "Customer", "old" => $this->customer_id , "new" => $obj->id );
 779              $this->customer = $obj;
 780              $this->customer_id = $obj->id;
 781          }
 782          unset($c);
 783          return;
 784      }
 785  
 786      /**
 787       * set the Due Date
 788       */
 789      function setDateDue($idx,&$name) {
 790          $a = $this->datedue[$idx]->getYYYYMMDD();
 791          $b = $name->getYYYYMMDD();
 792  
 793          if ( $a != $b ) {
 794              $this->modified[] = array ( "field" => "InvDateDue_".$idx, "old" => $a , "new" => $b );
 795              $this->datedue[$idx] = $name;
 796          }
 797          return;
 798      }
 799  
 800      /**
 801       * set the Due Date
 802       */
 803      function setDateSent($idx,&$name) {
 804          $a = $this->datesent[$idx]->getYYYYMMDD();
 805          $b = $name->getYYYYMMDD();
 806  
 807          if ( $a != $b ) {
 808              $this->modified[] = array ( "field" => "InvDateSent_".$idx, "old" => $a , "new" => $b );
 809              $this->datesent[$idx] = $name;
 810          }
 811          return;
 812      }
 813  
 814      /**
 815       * set the Finish Date
 816       */
 817      function setDateFinish(&$name) {
 818          $a = $this->datefinish->getYYYYMMDD();
 819          $b = $name->getYYYYMMDD();
 820  
 821          if ( $a != $b ) {
 822              if ($this->state == INV_STATE_PAYED ) {
 823                  $this->modified[] = array ( "field" => "InvDatePayed", "old" => $a , "new" => $b );
 824              } else {
 825                  $this->modified[] = array ( "field" => "InvDateCancel", "old" => $a , "new" => $b );
 826              }
 827              $this->datefinish = $name;
 828          }
 829          return;
 830      }
 831  
 832      /**
 833       * get the total sum
 834       */
 835      function getTotal() {
 836          $sum = array();
 837          foreach ($this->pos as $f) {
 838              if (isset($sum[$f->currency])) {
 839                  $sum[$f->currency] += $f->getTotal();
 840              } else {
 841                  $sum[$f->currency] = $f->getTotal();
 842              }
 843          }
 844          return $sum;
 845      }
 846  
 847      /**
 848       * Save Invoice to DB
 849       */
 850      function save() {
 851          global $tutos,$current_user,$table;
 852  
 853          $msg = '';
 854          $this->run_presave_hook();
 855  
 856          $q = new query($this->dbconn);
 857          $q->setTable($this->tablename);
 858          $q->addFV("name",$this->name,"STRING",$table['invoice']['name'][size]);
 859          $q->addFV("state",$this->state,"INT");
 860          $q->addFV("link_id",$this->link_id,"INT");
 861          $q->addFV("accountant",$this->accountant,"INT");
 862          $q->addFV("customer",$this->customer,"OBJ");
 863          $q->addFV("d_sent0",$this->datesent[0],"DATETIME");
 864          $q->addFV("d_sent1",$this->datesent[1],"DATETIME");
 865          $q->addFV("d_sent2",$this->datesent[2],"DATETIME");
 866          $q->addFV("d_due0",$this->datedue[0],"DATETIME");
 867          $q->addFV("d_due1",$this->datedue[1],"DATETIME");
 868          $q->addFV("d_due2",$this->datedue[2],"DATETIME");
 869          $q->addFV("d_finish",$this->datefinish,"DATETIME");
 870          $this->save_custom_fields($q);
 871  
 872          if ( $this->id < 0 ) {
 873              unset ($this->modified);
 874              if ( isset($this->newid) ) {
 875                  $this->id = $this->newid;
 876                  $q->addFV("id",$this->id,"");
 877              } else {
 878                  $this->id = $q->addFV("id",-1,"NEXTID");
 879                  $this->acl_default();
 880                  unset ($this->modified);
 881                  $this->modified[] = array ( "field" => "created" ,
 882                                              "old" => $this->getType() ,
 883                                              "new" => $this->id,
 884                                              "obj_id" => $this->id
 885                      );
 886              }
 887              $q->addFV("creator",$this->creator,"OBJ");
 888              $q->addFV("creation",$this->creation,"DATETIME");
 889  
 890              $query = $q->getInsert();
 891  
 892          } else {
 893              $q->addWC("id",$this->id,"");
 894              $query = $q->getUpdate();
 895          }
 896  
 897  
 898          $r = $this->dbconn->Exec($query);
 899          $r->free();
 900          $msg = addLine($msg,$this->save_pos());
 901          $msg = addLine($msg,parent::save());
 902  
 903          return $msg;
 904      }
 905  
 906      /**
 907       * delete this invoice an set the positions references to unaccounted
 908       */
 909      function delete() {
 910          $msg = '';
 911  
 912          $this->read_Pos();
 913          foreach( $this->pos as $i => $f) {
 914              $msg = addLine($msg,$f->delete());
 915          }
 916  
 917          $q = 'DELETE FROM '. $this->tablename .' WHERE id = '. $this->id;
 918          $r = $this->dbconn->Exec($q);
 919          $r->free();
 920  
 921          $msg = addLine($msg,parent::delete());
 922          return $msg;
 923      }
 924  
 925      /**
 926       * get the invoice as a PDF file using the fpdf package
 927       */
 928      function getPDF () {
 929          global $tutos,$lang;
 930  
 931          require_once  'invoice_pdf.pinc';
 932          $w = 40;
 933          $h = 10;
 934          $pdf=new invoice_pdf($this);
 935          $pdf->Open();
 936          $pdf->setAuthor($this->creator->getFullName());
 937          $pdf->setCreator("TUTOS Version ".$tutos[version]);
 938          $pdf->setTitle($this->getFullName());
 939          $pdf->setSubject($this->getFullName());
 940          $pdf->setDisplayMode('fullpage','continuous');
 941          $pdf->SetCompression(true);
 942          $pdf->AddPage();
 943  
 944          $pdf->SetFont('Arial','',12);
 945          // Customer
 946          if (is_object($this->customer) ) {
 947              $pdf->Cell(0,20,$this->customer->getFullName(),0,1);
 948          }
 949  
 950          // Accountant
 951          if ( $this->acc->getType() == "location" ) {
 952              $pdf->Cell(0,20,$this->acc->company->getFullName(),0,1);
 953          } else {
 954              $pdf->Cell(0,20,$this->acc->getFullName(),0,1);
 955          }
 956  
 957          // Product
 958          if (is_object($this->ref)) {
 959              $pdf->Cell(40,20,$lang[$this->ref->getType()],0,0);
 960              $pdf->Cell(0,20,$this->ref->getFullName(),0,1);
 961          }
 962  
 963  
 964          // add textblock
 965          $pdf->addFileBlock($tutos['base']."/php/invoice/invoice_head.txt");
 966  
 967  
 968          // Positions
 969          $w  = array(14,20,20,45,25,30,17);
 970          $fs = array(9,10,10,8,10,10,10);
 971          $al = array('R','R','L','L','R','R','L');
 972  
 973  
 974          // Header
 975          $h = 8;
 976          $pdf->SetFont('Arial','B',$fs[0]);
 977          $pdf->Cell($w[0],$h, myiconv($lang['InvPosPos']),1,0,$al[0]);
 978          $pdf->SetFont('Arial','B',$fs[1]);
 979          $pdf->Cell($w[1],$h, myiconv($lang['InvPosItems']),1,0,$al[1]);
 980          $pdf->SetFont('Arial','B',$fs[2]);
 981          $pdf->Cell($w[2],$h, myiconv($lang['InvPosIType']),1,0,$al[2]);
 982          $pdf->SetFont('Arial','B',$fs[3]);
 983          $pdf->Cell($w[3],$h, myiconv($lang['InvPosDesc']),1,0,$al[3]);
 984          $pdf->SetFont('Arial','B',$fs[4]);
 985          $pdf->Cell($w[4],$h, myiconv($lang['InvPosSingle']),1,0,$al[4]);
 986          $pdf->SetFont('Arial','B',$fs[5]);
 987          $pdf->Cell($w[5],$h, myiconv($lang['InvPosSum']),1,0,$al[5]);
 988          $pdf->SetFont('Arial','B',$fs[6]);
 989          $pdf->Cell($w[6],$h, myiconv($lang['Currency']),1,0,$al[6]);
 990  
 991          $pdf->Ln();
 992  
 993          foreach($this->pos as $i => $f) {
 994              // Default line height
 995              $l = explode("\n",$f->description);
 996              $subline = 1;
 997              $h = 8;
 998  
 999              if (!isset($sum[$f->currency])) {
1000                  $sum[$f->currency] = 0.0;
1001              }
1002              $sum[$f->currency] += $f->getTotal();
1003  
1004              $pdf->SetFont('Arial','',$fs[0]);
1005              $pdf->Cell($w[0],$h, sprintf("%04d",$f->pos),'LRT',0,$al[0]);
1006  
1007              $pdf->SetFont('Arial','',$fs[1]);
1008              $pdf->Cell($w[1],$h, my_number_format($f->items,2),'LRT',0,$al[1]);
1009  
1010              $pdf->SetFont('Arial','',$fs[2]);
1011              $pdf->Cell($w[2],$h, myiconv($f->itype), 'LRT',0,$al[2]);
1012  
1013              $pdf->SetFont('Arial','',$fs[3]);
1014              $pdf->Cell($w[3],$h, myiconv($l[0]),'LRT',0,$al[3]);
1015  
1016              $pdf->SetFont('Arial','',$fs[4]);
1017              $pdf->Cell($w[4],$h, my_number_format($f->sum_single ,2), 'LRT',0,$al[4]);
1018  
1019              $pdf->SetFont('Arial','',$fs[5]);
1020              $pdf->Cell($w[5],$h, my_number_format($f->getTotal(),2), 'LRT',0,$al[5]);
1021  
1022              $pdf->SetFont('Arial','',$fs[6]);
1023              $pdf->Cell($w[6],$h, myiconv($f->currency) ,'LRT',0,$al[6]);
1024              $pdf->Ln();
1025  
1026              while ($subline < (count($l))) {
1027                  $h = 4;
1028                  $pdf->SetFont('Arial','',8);
1029                  $subline++;
1030                  if ($subline == count($l)) {
1031                      $f = 'LRB';
1032                  } else {
1033                      $f = 'LR';
1034                  }
1035                  $pdf->SetFont('Arial','',$fs[0]);
1036                  $pdf->Cell($w[0],$h,'',$f,0);
1037                  $pdf->SetFont('Arial','',$fs[1]);
1038                  $pdf->Cell($w[1],$h,'',$f,0);
1039                  $pdf->SetFont('Arial','',$fs[2]);
1040                  $pdf->Cell($w[2],$h,'',$f,0);
1041                  $pdf->SetFont('Arial','',$fs[3]);
1042                  $pdf->Cell($w[3],$h,$l[$subline-1],$f,0,$al[3]);
1043                  $pdf->SetFont('Arial','',$fs[4]);
1044                  $pdf->Cell($w[4],$h,'',$f,0);
1045                  $pdf->SetFont('Arial','',$fs[5]);
1046                  $pdf->Cell($w[5],$h,'',$f,0);
1047                  $pdf->SetFont('Arial','',$fs[6]);
1048                  $pdf->Cell($w[6],$h,'',$f,0);
1049                  $pdf->Ln();
1050              }
1051          }
1052  
1053          // Summary
1054          foreach($tutos[currencies] as $i => $c) {
1055              if ( !isset($sum[$c]) || ($sum[$c] == 0) ) {
1056                  continue;
1057              }
1058              $h = 8;
1059              $pdf->SetFont('Arial','B',$fs[0]);
1060              $pdf->Cell($w[0],$h, "",'LB',0,$al[0]);
1061              $pdf->SetFont('Arial','B',$fs[1]);
1062              $pdf->Cell($w[1],$h, "",'B',0,$al[1]);
1063              $pdf->SetFont('Arial','B',$fs[2]);
1064              $pdf->Cell($w[2],$h, "",'B',0,$al[2]);
1065              $pdf->SetFont('Arial','B',$fs[3]);
1066              $pdf->Cell($w[3],$h, "",'B',0,$al[3]);
1067              $pdf->SetFont('Arial','B',$fs[4]);
1068              $pdf->Cell($w[4],$h, "",'BR',0,$al[4]);
1069  
1070              $pdf->SetFont('Arial','B',$fs[5]);
1071              $pdf->Cell($w[5],$h,my_number_format($sum[$c],2) ,'B',0,$al[5]);
1072              $pdf->SetFont('Arial','B',$fs[6]);
1073              $pdf->Cell($w[6],$h, $c ,'BR',0,$al[6]);
1074  
1075              $pdf->Ln();
1076          }
1077  
1078          // add textblock
1079          $pdf->SetFont('Arial','',12);
1080          $pdf->addFileBlock($tutos['base']."/php/invoice/invoice_end.txt");
1081  
1082          $pdf->Close();
1083          return $pdf->buffer;
1084      }
1085  
1086      /**
1087       * Transfer reference ids according to given table
1088       */
1089      function transfer_ids (&$trans) {
1090          parent::transfer_ids ($trans);
1091          if (isset($trans[$this->link_id])) {
1092              $this->link_id = $trans[$this->link_id];
1093          }
1094          if (isset($trans[$this->lcustomer_id])) {
1095              $this->customer_id = $trans[$this->customer_id];
1096          }
1097          return;
1098      }
1099  
1100      /**
1101       * get the type of object
1102       */
1103      static function gettype () {
1104          return "invoice";
1105      }
1106  
1107      /**
1108       * get the type id of object
1109       */
1110      static function gettypeid () {
1111          return useinvoice;
1112      }
1113  
1114      /**
1115       * get name of icons
1116       */
1117      static function getHtmlIcon () {
1118          return 'money_dollar';
1119      }
1120  
1121      /**
1122       * return a list of possible date fields (for reminder)
1123       */
1124      function get_date_fields() {
1125          global $lang;
1126  
1127          $x = parent::get_date_fields();
1128          $x[0][10] = array('d_sent0',$lang['InvDateSent'][0]);
1129          $x[0][11] = array('d_due0' ,$lang['InvDateDue'][0]);
1130          $x[0][12] = array('d_sent1',$lang['InvDateSent'][1]);
1131          $x[0][13] = array('d_due1' ,$lang['InvDateDue'][1]);
1132          $x[0][14] = array('d_sent2',$lang['InvDateSent'][2]);
1133          $x[0][15] = array('d_due2' ,$lang['InvDateDue'][2]);
1134          $x[0][16] = array('datefinish' ,$lang['InvDatePayed']);
1135          // possible Offsets
1136          $x[1] = array_unique($x[1] + array(-86400*7*1,-86400*2,-86400*1,-3600*2,-3600*1,0,
1137                                             3600*1,3600*2,86400*1,86400*2,86400*7*1,86400*7*4,86400*7*52));
1138  
1139          return $x;
1140      }
1141  
1142      /**
1143       * resolve a history Tag (to be called from history_show)
1144       */
1145      function resolveHistoryTag ($f) {
1146          global $lang;
1147  
1148          $x = null;
1149          switch ($f['field']) {
1150          case 'InvDateSent_0':
1151          case 'InvDateDue_0':
1152          case 'InvDateSent_1':
1153          case 'InvDateDue_1':
1154          case 'InvDateSent_2':
1155          case 'InvDateDue_2':
1156          case 'InstDateTime':
1157              $x = resolve_history_datetime($f,$this->dbconn);
1158              return $x;
1159              break;
1160          case 'InvoiceState':
1161              $x = $f;
1162              $x['field'] = isset( $lang[$f['field']]) ? $lang[$f['field']] : $f['field'];
1163              $x['old'] = $lang['InvoiceStates'][$f['old']];
1164              $x['new'] = $lang['InvoiceStates'][$f['new']];
1165              break;
1166  
1167          }
1168          return $x;
1169      }
1170      /* ---------------------------------------------------------------------------
1171       * The following methods are abstract factory functions for groups
1172       * which handle the membership list of an object
1173       * --------------------------------------------------------------------------- */
1174      /**
1175       * Read a list of all invoices related to an object
1176       */
1177      static function obj_read (tutos_base $obj) {
1178          global $table;
1179  
1180          if (! is_object($obj) ) return;
1181          if ( $obj->id == -1 ) return;
1182  
1183          $q2 = '';
1184          $obj->list[useinvoice][1] = array(); // direct ref
1185          $obj->list[useinvoice][2] = array(); // postion
1186          if ( ($obj->getType() == "product") || ($obj->getType() == "installation") || ($obj->getType() == "expense")  ) {
1187              $q = "SELECT * from ". $obj->dbconn->prefix.$table['invoice'][name] ." where link_id = ". $obj->id ." order by creation desc";
1188              // the given object is referenced somewhere
1189              $q2 = "SELECT inv_id from ". $obj->dbconn->prefix.$table['invpos'][name]." where ref_id = ". $obj->id;
1190          } else if ( ($obj->getType() == "company") || ($obj->getType() == "department") ) {
1191              $q = "SELECT * from ". $obj->dbconn->prefix.$table['invoice'][name]." where customer = ". $obj->id ." order by creation desc";
1192          } else {
1193              $q = "SELECT * from ". $obj->dbconn->prefix.$table['invoice'][name]." where (creator = ". $obj->id .") OR ( link_id = ". $obj->id .") OR ( customer = ". $obj->id .") order by creation desc";
1194          }
1195  
1196          $r = $obj->dbconn->Exec($q);
1197          $n = $r->numrows();
1198          $a = 0;
1199          while ($a < $n) {
1200              $i = new invoice($obj->dbconn);
1201              $i->read_result($r,$a);
1202              if ( $i->see_ok() ) {
1203                  $obj->list[useinvoice][1][$i->id] = &$i;
1204              }
1205              $a++;
1206              unset($i);
1207          }
1208          $r->free();
1209  
1210          if ( $q2 != "" ) {
1211              // Position in invoice
1212              $r = $obj->dbconn->Exec($q2);
1213              $n = $r->numrows();
1214              $a = 0;
1215              while ($a < $n) {
1216                  $i = new invoice($obj->dbconn);
1217                  $i = $i->read($r->get($a,"inv_id"),$i);
1218                  if ( $i->see_ok() ) {
1219                      $obj->list[useinvoice][2][$i->id] = &$i;
1220                  }
1221                  $a++;
1222                  unset($i);
1223              }
1224              $r->free();
1225          }
1226          return;
1227      }
1228      /**
1229       * create a list of invoices for the given object
1230       */
1231      static function infolist (tutos_user $user,tutos_base $obj,$cols,$format = "html") {
1232          global $lang;
1233  
1234          $r = '';
1235          if (! is_object($obj) ) return $r;
1236  
1237          if ( ! $user->feature_ok(useinvoice,PERM_SEE) ) return $r;
1238          if ( ! $obj->obj_feature_ok($user,useinvoice,PERM_SEE) ) return $r;
1239  
1240          invoice::obj_read($obj);
1241          if ( !isset($obj->list[useinvoice][1]) || count($obj->list[useinvoice][1])+count($obj->list[useinvoice][2]) == 0 ) {
1242              return $r;
1243          }
1244          $r .= $user->layout->ContentRowStart();
1245          $r .= $user->layout->show_info_field($lang['Invoices'],$obj,get_class());
1246          if ( $format == "paper" ) {
1247              $d = showInvoice($user,$obj,-1);
1248          } else {
1249              $d = showInvoice($user,$obj);
1250          }
1251          $r .= $user->layout->showdata($d,$cols-1);
1252          $r .= $user->layout->ContentRowEnd();
1253          return $r;
1254      }
1255  
1256      /**
1257       * create a link where a invoice for the given object could be added
1258       */
1259      static function getaddlink (tutos_user $user,tutos_base $obj,$text = "") {
1260          global $lang;
1261  
1262          if (! is_object($obj) ) return '';
1263          if ( $obj->id == -1 ) return '';
1264          if (! $user->feature_ok(useinvoice,PERM_NEW) ) return '';
1265          if (! $obj->obj_feature_ok($user,useinvoice,PERM_NEW) ) return '';
1266          if (! $obj->use_ok() ) return ''; // wee need the use permission
1267  
1268          if ($obj->getType() == 'company') return '';
1269          if ($obj->getType() == 'department') return '';
1270          if ($obj->getType() == 'stc') return '';
1271  
1272          $x = array( url => 'invoice/invoice_new.php?link_id='. $obj->id,
1273                      confirm => false,
1274                      text => ($text == "" ? $lang['InvoiceCreate']:$text),
1275                      info => sprintf($lang['InvoiceCreateI'], $obj->getFullName()),
1276                      category => array('invoice','new','module',useinvoice)
1277              );
1278          return $x;
1279      }
1280  
1281      /**
1282       * get an header for overview tables that shows objects of type objtype
1283       */
1284      function get_overview_header (layout_base $layout,$objtype) {
1285          global $lang;
1286  
1287          $r = '';
1288          if ( ! $layout->user->feature_ok(useinvoice,PERM_SEE) ) {
1289              return $r;
1290          }
1291          if ($objtype == "timetrack") {
1292              $r .= $layout->orderHeader("",$lang['Invoice'],"");
1293              $layout->flds++;
1294          } else if ($objtype == "installation") {
1295              $r .= $layout->orderHeader("",$lang['Invoice'],"");
1296              $layout->flds++;
1297          } else if ($objtype == "expense") {
1298              $r .= $layout->orderHeader("",$lang['Invoice'],"");
1299              $layout->flds++;
1300          }
1301          return $r;
1302      }
1303  
1304      /**
1305       * get an data for overview tables that shows a line with obj info
1306       */
1307      function get_overview_data (layout_base $layout,tutos_base $obj) {
1308          global $tutos,$lang;
1309  
1310          $r = '';
1311          if ( ! $layout->user->feature_ok(useinvoice,PERM_SEE) ) {
1312              return $r;
1313          }
1314          if ( ($obj->gettype() == "timetrack") ) {
1315              $xx = '';
1316              if ( $obj->inv_id != -1 ) {
1317                  $obj->invoice = new invoice($obj->dbconn);
1318                  $obj->invoice = $obj->invoice->read($obj->inv_id,$obj->invoice);
1319                  if ( $obj->inv_id == $obj->invoice->id ) {
1320                      $xx .= $obj->invoice->getLink().' : '. $obj->invoice->getState();
1321                  }
1322              }
1323              $r .= $layout->OverviewRowBlock(($xx != '' ? $xx:'&#160;'),'over_l');
1324          } else if ( ($obj->gettype() == "installation") || ($obj->gettype() == "expense") ) {
1325              $xx = '';
1326              invoice::obj_read($obj);
1327              $pre = '';
1328              if ( count($obj->list[useinvoice][1]) > 0 ) {
1329                  foreach ($obj->list[useinvoice][1] as $i => $f) {
1330                      $xx .= $pre . $f->getLink() ." : ". $f->getState() ;
1331                      $pre = "\n<br />";
1332                  }
1333              }
1334              if ( count($obj->list[useinvoice][2]) > 0 ) {
1335                  foreach ($obj->list[useinvoice][2] as $i => $f) {
1336                      $xx .= $pre .'+'.$f->getLink() ." : ". $f->getState() ;
1337                      $pre = "\n<br />";
1338                  }
1339              }
1340              $r .= $layout->OverviewRowBlock(($xx != '' ? $xx:'&#160;'),'over_l');
1341          }
1342          return $r;
1343      }
1344  
1345      /**
1346       * create a link to a overview page
1347       */
1348      static function getOverviewLink (tutos_user $user,$text = "") {
1349          global $lang;
1350          if ( ! $user->feature_ok(useinvoice,PERM_SEE) ) {
1351              return;
1352          }
1353          return array( url => 'invoice/invoice_overview.php',
1354                        image => $user->layout->theme->getImage(invoice::getHtmlIcon(),'menu'),
1355                        text => ($text == "" ?  $lang['InvOverview']: $text),
1356                        info => $lang['InvOverview'],
1357                        category => array('overview','invoice','module',useinvoice)
1358              );
1359      }
1360  
1361      /**
1362       * create a link for an overview filtered by $obj
1363       */
1364      function getOverviewLinkObj (tutos_user $user,tutos_base $obj,$text = "") {
1365          global $lang;
1366  
1367          if (! is_object($obj) ) return '';
1368          if ( $obj->id == -1 ) return '';
1369          if (! $user->feature_ok(useinvoice,PERM_SEE) ) return '';
1370          if (! $obj->obj_feature_ok($user,useinvoice,PERM_SEE) ) return '';
1371          if (! $obj->see_ok() ) return '';
1372  
1373          return array( url => 'invoice/invoice_overview.php?link_id='.$obj->id,
1374                        confirm => false,
1375                        text => ($text == '' ? $lang['InvOverview']:$text),
1376                        info => $lang['InvOverview'],
1377                        category => array('overview','module',useinvoice)
1378              );
1379      }
1380  
1381      /**
1382       * create a link to a select page
1383       */
1384      static function getSelectLink (tutos_user $user,$text = "") {
1385          global $lang;
1386          if ( ! $user->feature_ok(useinvoice,PERM_SEL) ) {
1387              return;
1388          }
1389          return array( url => 'invoice/invoice_select.php',
1390                        image => $user->layout->theme->getImage(invoice::getHtmlIcon(),'menu'),
1391                        text => ($text == "" ?  $lang['Invoices']: $text),
1392                        info => $lang['InvoiceSearch'],
1393                        category => array('search','invoice','module',useinvoice)
1394              );
1395      }
1396  
1397      /**
1398       * show the mytutos info about invoices
1399       */
1400      static function mytutos (tutos_user $user) {
1401          global $tutos,$lang,$current_user;
1402  
1403          if ( ! $current_user->feature_ok(useinvoice,PERM_SEE) ) {
1404              return '';
1405          }
1406          if ( ! $current_user->feature_ok(useinvoice,PERM_MYTUTOS) ) {
1407              return '';
1408          }
1409  
1410          invoice::obj_read($user);
1411          if ( count($user->list[useinvoice][1]) == 0 ) {
1412              return '';
1413          }
1414          $r = info_table_start();
1415          $r .= " <tr>\n";
1416          $m = invoice::getSelectLink($user);
1417          if ($m) {
1418              $ml = menulink($m[url],$m[text],$m[info]);
1419          } else {
1420              $ml = $lang['Invoices'];
1421          }
1422          $r .= ' <th colspan="3">'.  $user->layout->theme->getImage(invoice::getHtmlIcon(),'list') .' '. $ml ."</th>\n";
1423          $r .= " </tr>\n";
1424          $r .= " <tr>\n";
1425          $r .= '  <th>'. $lang['InvoiceName'] ."</th>\n";
1426          $r .= '  <th>'. $lang['InvoiceCustomer'] ."</th>\n";
1427          $r .= '  <th>'. $lang['InvoiceState'] ."</th>\n";
1428          $r .= " </tr>\n";
1429          $a = 0;
1430          foreach ($user->list[useinvoice][1] as $f) {
1431              if (!($a++ < 2 * $tutos['maxshort'])) break;
1432              $r .= " <tr>\n";
1433              $r .= '  <td>' . $f->getLink() ."</td>\n";
1434              $r .= "  <td>\n";
1435              if ( isset($f->customer->id) ) {
1436                  $r .= $f->customer->getLink();
1437              } else {
1438                  $r .= '<i>'. $lang['HistoryDeleted'] ."</i>";
1439              }
1440              $r .= "  </td>\n";
1441              $r .= "  <td>" . $f->getState() ."</td>\n";
1442              $r .= " </tr>\n";
1443              unset($f);
1444          }
1445          $r .= info_table_end();
1446          return $r;
1447      }
1448  
1449      /**
1450       * get the help index
1451       */
1452      static function getHelpIndex () {
1453          global $lang;
1454  
1455          $r = '';
1456          $r .= '<h3>'. makelink("help.php?p=glossary#invoice",$lang['Invoices'],$lang['Invoices']) ."</h3><ul>\n";
1457          $r .= ' <li>'. makelink('help.php?p=invoice_new',$lang['NewEntry'].'/'. $lang['Modify'],$lang['NewEntry'].'/'. $lang["Modify"]) ."</li>\n";
1458          $r .= ' <li>'. makelink('help.php?p=invoice_show',$lang['show'],$lang['show']) ."</li>\n";
1459          $r .= ' <li>'. makelink('help.php?p=invoice_overview',$lang['InvOverview'],$lang['InvOverview'])."</li>\n";
1460          $r .= "</ul>\n";
1461          return $r;
1462      }
1463  }
1464  ?>

title

Description

title

Description

title

Description

title

title

Body