Files
tms/extensions/ki_invoice/print.php
TMS eb299c9131 Initial commit: Kimai TMS
Kimai time management system (PHP 5.6 / MySQL) with custom extensions:
- Budget tracking (ki_budget)
- Change request form (ki_changerequest)
- Invoice generation (ki_invoice)
- Expense tracking (ki_expenses)
- Flexi time (ki_flexitime)
- Export, admin panel, timesheets, tasks, summary

Database: ~900K time entries, 2,000+ users, 439 projects.
Config: includes/autoconf.php — localhost/kimai/kimai
2026-06-18 21:20:26 +00:00

206 lines
6.2 KiB
PHP

<?php
/**
* This file is part of
* Kimai - Open Source Time Tracking // http://www.kimai.org
* (c) 2006-2009 Kimai-Development-Team
*
* Kimai is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; Version 3, 29 June 2007
*
* Kimai is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Kimai; If not, see <http://www.gnu.org/licenses/>.
*/
include_once('../../includes/basics.php');
// libs TinyButStrong
include_once('TinyButStrong/tinyButStrong.class.php');
include_once('TinyButStrong/tinyDoc.class.php');
include_once('private_db_layer_'.$kga['server_conn'].'.php');
/**
* returns true if event is in the arrays
*
* @param $arrays
* @return true if $event is in the array
* @author AA
*/
function array_event_exists($arrays, $event) {
$index = 0;
foreach ($arrays as $array) {
if ( in_array($event,$array) ) {
return $index;
}
$index++;
}
return -1;
}
function RoundValue( $value, $prec ) {
$precision = $prec;
// suppress division by zero errror
if ($precision == 0.0) {
$precision = 1.0;
}
return floor($value / $precision + 0.5)*$precision;
}
// insert KSPI
$isCoreProcessor = 0;
$dir_templates = "templates/";
$usr = checkUser();
$timespace = get_timespace();
$in = $timespace[0];
$out = $timespace[1];
$timeArray = get_arr_zef($in, $out, null, null, array($_REQUEST['pct_ID']), 1);
/* $timeArray now contains: zef_ID, zef_in, zef_out, zef_time, zef_rate, zef_pctID,
zef_evtID, zef_usrID, pct_ID, knd_name, pct_kndID, evt_name, pct_comment,
pct_name, zef_location, zef_trackingnr, zef_comment, zef_comment_type,
usr_name, usr_alias, zef_cleared
*/
$date = date("m-d-Y");
$month = $kga['lang']['months'][date("n", $out)-1];
$year = date("Y", $out );
if (count($timeArray) > 0) {
// customer data
$kndArray = get_entry_knd($timeArray[0]['knd_name']);
$project = html_entity_decode($timeArray[0]['pct_name']);
$customerName = html_entity_decode($timeArray[0]['knd_name']);
$companyName = $kndArray['knd_company'];
$customerStreet = $kndArray['knd_street'];
$customerCity = $kndArray['knd_city'];
$customerZip = $kndArray['knd_zipcode'];
$customerComment = $kndArray['knd_comment'];
$customerPhone = $kndArray['knd_tel'];
$customerFax = $kndArray['knd_fax'];
$customerMobile = $kndArray['knd_mobile'];
$customerEmail = $kndArray['knd_mail'];
$customerContact = $kndArray['knd_homepage']; //I'm using the "homepage" field to store client contact name
$beginDate = date("F j, Y", $in);
$endDate = date("F j, Y", $out);
$invoiceID = $customerName. "-" . date("y", $in). "-" . date("m", $in);
$today = date("F j, Y");
$dueDate = date("F j, Y", mktime(0, 0, 0, date("m") + 1, date("d"), date("Y")));
} else {
echo '<script language="javascript">alert("'.$kga['lang']['ext_invoice']['noData'].'")</script>';
return;
}
// MERGE SORT
$time_index = 0;
$invoiceArray = array();
while ($time_index < count($timeArray)) {
$wage = $timeArray[$time_index]['wage'];
$time = $timeArray[$time_index]['zef_time']/3600;
$event = html_entity_decode($timeArray[$time_index]['evt_name']);
$comment = $timeArray[$time_index]['zef_comment'];
$evtdt = date("m/d/Y", $timeArray[$time_index]['zef_in']);
// do we have to create a short form?
if ( isset($_REQUEST['short']) ) {
$index = array_event_exists($invoiceArray,$event);
if ( $index >= 0 ) {
$totalTime = $invoiceArray[$index]['hour'];
$totalAmount = $invoiceArray[$index]['amount'];
$invoiceArray[$index] = array(
'desc' => $event,
'hour' => $totalTime+$time,
"amount" => $totalAmount+$wage,
'date' => $evtdt,
'comment' => $comment
);
}
else {
$invoiceArray[] = array('desc'=>$event, 'hour'=>$time, 'amount'=>$wage, 'date'=>$evtdt, 'comment'=>$comment);
}
}
else {
$invoiceArray[] = array('desc'=>$event, 'hour'=>$time, 'amount'=>$wage, 'date'=>$evtdt, 'comment'=>$comment);
}
$time_index++;
}
$round = 0;
// do we have to round the time ?
if (isset($_REQUEST['round'])) {
$round = $_REQUEST['pct_round'];
$time_index = 0;
$amount = count($invoiceArray);
while ($time_index < $amount) {
$rounded = RoundValue( $invoiceArray[$time_index]['hour'], $round/10);
// Write a logfile entry for each value that is rounded.
logfile("Round ". $invoiceArray[$time_index]['hour'] . " to " . $rounded . " with ". $round);
$rate = RoundValue($invoiceArray[$time_index]['amount']/$invoiceArray[$time_index]['hour'],0.05);
$invoiceArray[$time_index]['hour'] = $rounded;
$invoiceArray[$time_index]['amount'] = $invoiceArray[$time_index]['hour']*$rate;
$time_index++;
}
}
// calculate invoice sums
$ttltime = 0;
$gtotal = 0;
while (list($id, $fd) = each($invoiceArray)) {
$gtotal += $invoiceArray[$id]['amount'];
$ttltime += $invoiceArray[$id]['hour'];
}
$vat_rate = $kndArray['knd_vat'];
if (!is_numeric($vat_rate)) {
$vat_rate = $kga['conf']['defaultVat'];
}
$vat = $vat_rate*$gtotal/100;
$total = $gtotal-$vat;
$doc = new tinyDoc();
// use zip extension if available
if (class_exists('ZipArchive')) {
$doc->setZipMethod('ziparchive');
}
else {
$doc->setZipMethod('shell');
try {
$doc->setZipBinary('zip');
$doc->setUnzipBinary('unzip');
}
catch (tinyDocException $e) {
$doc->setZipMethod('pclzip');
}
}
$doc->setProcessDir('../../temporary');
//This is where the template is selected
$templateform = "templates/" . $_REQUEST['ivform_file'];
$doc->createFrom($templateform);
$doc->loadXml('content.xml');
$doc->mergeXmlBlock('row', $invoiceArray);
$doc->saveXml();
$doc->close();
// send and remove the document
$doc->sendResponse();
$doc->remove();