dbutils = new DbUtils(); require_once 'translations.php'; } function handleCommand($command) { // all commands require closing,manager or admin rights if (!($this->hasCurrentUserManagerOrAdminRights()) && ($command != 'createClosing') && ($command != 'getClosings') && ($command != 'remotecreateclosing')) { if ($command != 'exportCsv') { echo json_encode(array("status" => "ERROR", "code" => ERROR_MANAGER_NOT_AUTHOTRIZED, "msg" => ERROR_MANAGER_NOT_AUTHOTRIZED_MSG)); } else { // exception - result is not handled on HTML/JS side echo json_encode(array("status" => "ERROR","msg" => "Fehlende Benutzerrechte")); } return; } // user has manager rights if($command == 'createClosing') { $this->createClosing($_POST['remark'],$_POST['print']); } else if ($command == 'remotecreateclosing') { if (isset($_POST['remoteaccesscode'])) { if (isset($_POST['remark'])) { $this->remotecreateclosing($_POST['remoteaccesscode'],$_POST['remark']); } else { $this->remotecreateclosing($_POST['remoteaccesscode'],''); } } else { echo json_encode("Remote access code not given"); } return; } else if ($command == 'getClosings') { $this->getClosings($_GET['month'], $_GET['year']); } else if ($command == 'exportCsv') { $this->exportCsv($_GET['closingid']); } else if ($command == 'exportGuestCsv') { $this->exportGuestCsv($_GET['closingid']); } else if ($command == 'emailCsv') { $this->emailCsv($_GET['closingid'],$_GET['emailaddress'],$_GET['topic']); } else if ($command == 'getClosing') { $this->getClosing($_GET['closingid']); } else if ($command == 'getClosingSummary') { $this->getClosingSummary($_GET['closingid'],null,true); } else if ($command == 'htmlreport') { $this->htmlreport($_GET["closid"]); } else if ($command == 'getClosingsListOfMonthYear') { $this->getClosingsListOfMonthYear($_GET["month"],$_GET["year"]); } else if ($command == 'getFirstAndLastClosing') { self::getFirstAndLastClosing(); } else { echo "Command not supported."; } } private function hasCurrentUserManagerOrAdminRights() { session_start(); if (!isset($_SESSION['angemeldet']) || !$_SESSION['angemeldet']) { // no user logged in return false; } else { return ($_SESSION['right_manager'] || $_SESSION['is_admin']); } } private function getDecPoint() { $sql = "SELECT name,setting FROM %config% WHERE name=?"; $pdo = $this->dbutils->openDbAndReturnPdo(); $stmt = $pdo->prepare($this->dbutils->resolveTablenamesInSqlString($sql)); $stmt->execute(array("decpoint")); $row = $stmt->fetchObject(); return($row->setting); } private function saveLastClosingCreation($pdo) { date_default_timezone_set(DbUtils::getTimeZone()); $date = new DateTime(); $unixTimeStamp = $date->getTimestamp(); $sql = "SELECT count(id) as countid FROM %work% WHERE item=?"; $row = CommonUtils::getRowSqlObject($pdo, $sql, array('lastclosing')); if ($row->countid == 0) { $sql = "INSERT INTO %work% (item,value,signature) VALUES(?,?,?)"; CommonUtils::execSql($pdo, $sql, array('lastclosing', $unixTimeStamp, null)); } else { $sql = "UPDATE %work% SET value=? WHERE item=?"; CommonUtils::execSql($pdo, $sql, array($unixTimeStamp, 'lastclosing')); } } private function isClosingAllowed($pdo) { $TIMEOUT = 120; $sql = "SELECT count(id) as countid FROM %work% WHERE item=?"; $row = CommonUtils::getRowSqlObject($pdo, $sql, array('lastclosing')); if ($row->countid == 0) { return true; } else { $sql = "SELECT value FROM %work% WHERE item=?"; $row = CommonUtils::getRowSqlObject($pdo, $sql, array('lastclosing')); $lastaccess = $row->value; date_default_timezone_set(DbUtils::getTimeZone()); $date = new DateTime(); $currentTimeStamp = $date->getTimestamp(); if (($currentTimeStamp - $lastaccess) > $TIMEOUT) { return true; } else { return false; } } } private function remotecreateclosing($remoteaccesscode,$remark) { $pdo = DbUtils::openDbAndReturnPdoStatic(); $code = CommonUtils::getConfigValue($pdo, 'remoteaccesscode', null); if (is_null($code) || ($code == '')) { echo json_encode("Remote access code was not configured!"); } else { if (md5($remoteaccesscode) == $code) { echo json_encode($this->createClosing($remark,0)); } else { echo json_encode("Remote access code not correct!"); } } } private function createClosing ($remark,$doPrint = 1) { $pdo = DbUtils::openDbAndReturnPdoStatic(); date_default_timezone_set(DbUtils::getTimeZone()); if (!$this->isClosingAllowed($pdo)) { echo json_encode(array("status" => "ERROR", "msg" => "Time between closings too short", "code" => ERROR_CLOSING_TIME_LIMIT)); return; } $closingTime = date('Y-m-d H:i:s'); $result = $this->createClosingCore($pdo,$remark,$doPrint,$closingTime,true); echo json_encode($result); } public function createClosingCore ($pdo,$remark,$doPrint, $closingTime,$checkForNewVersionAvailable) { set_time_limit(60*60); if (is_null($remark)) { $remark = ""; } $decpoint = $this->getDecPoint(); // first create a closing entry date_default_timezone_set(DbUtils::getTimeZone()); $pdo->beginTransaction(); $this->saveLastClosingCreation($pdo); if (CommonUtils::callPlugin($pdo, "createClosing", "replace")) { return; } CommonUtils::callPlugin($pdo, "createClosing", "before"); CommonUtils::execSql($pdo, 'DELETE FROM %recordsqueue%', null); CommonUtils::execSql($pdo, 'DELETE FROM %records%', null); $sql = "SELECT MAX(id) as maxid FROM %closing%"; $maxIdRes = CommonUtils::fetchSqlAll($pdo, $sql); $maxId = 0; if (!is_null($maxIdRes)) { $maxIdVal = $maxIdRes[0]["maxid"]; if (!is_null($maxIdVal)) { $maxId = intval($maxIdVal); } } $newClosingId = $maxIdVal + 1; $closingEntrySql = "INSERT INTO `%closing%` (`id`,`closingdate`,`remark`,`billcount`,`billsum`,`signature`) VALUES (?,?,?,?,?,?)"; CommonUtils::execSql($pdo, $closingEntrySql, array($newClosingId,$closingTime,$remark,0,0.0,null)); set_time_limit(60*60); $sql = "SELECT id FROM %bill% WHERE closingid is null AND (tableid >= '0' OR status='c') "; $stmt = $pdo->prepare($this->dbutils->resolveTablenamesInSqlString($sql)); $stmt->execute(); $result = $stmt->fetchAll(); $utils = new CommonUtils(); $ok = true; foreach($result as $row) { $aBillId = $row['id']; if (!$utils->verifyBill($pdo, $aBillId)) { $ok=false; break; } } if (!$ok) { return(array("status" => "ERROR", "code" => ERROR_INCONSISTENT_DB, "msg" => ERROR_INCONSISTENT_DB_MSG)); } set_time_limit(60*60); $sql = "UPDATE %bill% SET closingid='$newClosingId' WHERE closingid is null AND (tableid >= '0' OR status='c') AND (paymentid <> ?)"; CommonUtils::execSql($pdo, $sql, array(8)); set_time_limit(60*60); $sql = "SELECT count(id) as billstotake FROM %bill% WHERE closingid=? AND (tableid >= '0' OR status='c')"; $stmt = $pdo->prepare($this->dbutils->resolveTablenamesInSqlString($sql)); $stmt->execute(array($newClosingId)); $row = $stmt->fetchObject(); $billsToTake = $row->billstotake; $pricesum = null; // now calculate the sum of the prices of this closing if ($billsToTake > 0) { $sql = "SELECT sum(brutto) as pricesum FROM %bill% WHERE closingid=? AND (tableid >= '0' OR status='c')"; $stmt = $pdo->prepare($this->dbutils->resolveTablenamesInSqlString($sql)); $stmt->execute(array($newClosingId)); $row = $stmt->fetchObject(); $pricesum = $row->pricesum; } if (is_null($pricesum)) { $pricesum = 0; } $prevClosingDate = self::getDateOfPreviousClosing($pdo,$newClosingId); if (is_null($prevClosingDate)) { $prevClosingDate = ""; } $pricesumstr = number_format($pricesum, 2, ".", ''); $data = "I($newClosingId)-S($prevClosingDate)-E($closingTime)-D($billsToTake)-S($pricesumstr)"; $signature = md5($data); set_time_limit(60*60); $sql = "UPDATE %closing% SET billcount=?, billsum=?,signature=? WHERE id=?"; CommonUtils::execSql($pdo, $sql, array($billsToTake,$pricesum,$signature,$newClosingId)); set_time_limit(60*60); $sql = "SELECT value as val FROM %work% WHERE item=?"; $indexunclosedqueue = 0; $r = CommonUtils::fetchSqlAll($pdo, $sql, array('indexunclosedqueue')); if (count($r) > 0) { $rval = $r[0]["val"]; if (!is_null($rval)) { $indexunclosedqueue = intval($rval); } } set_time_limit(60*60); $sql = "UPDATE %queue% Q SET Q.clsid=? WHERE Q.id > ? AND Q.clsid is null"; CommonUtils::execSql($pdo, $sql, array($newClosingId,$indexunclosedqueue)); set_time_limit(60*60); $sql = "UPDATE %queue% SET toremove='1' WHERE billid is null AND clsid=?"; CommonUtils::execSql($pdo, $sql, array($newClosingId)); set_time_limit(60*60); $sql = "UPDATE %queue% set paidtime=?,delivertime=? WHERE billid is not null AND paidtime is null"; CommonUtils::execSql($pdo, $sql, array($closingTime,$closingTime)); $sql = "UPDATE %queue% set delivertime=?,workprinted=? WHERE billid is not null AND delivertime IS NULL"; CommonUtils::execSql($pdo, $sql, array($closingTime,1)); $sql = "DELETE FROM %printjobs%"; CommonUtils::execSql($pdo, $sql, null); CommonUtils::execSql($pdo, "OPTIMIZE TABLE %printjobs%", null); $sql = "DELETE FROM %work% WHERE item=?"; CommonUtils::execSql($pdo, $sql, array("sumuphash")); set_time_limit(60*60); $sql = "UPDATE %queue% SET isclosed=?"; CommonUtils::execSql($pdo, $sql, array(1)); $dblogging = CommonUtils::getConfigValue($pdo, 'dblog', 1); if ($dblogging == 0) { $sql = "DELETE FROM %log%"; CommonUtils::execSql($pdo, $sql, null); CommonUtils::execSql($pdo, "OPTIMIZE TABLE %log%", null); } workreceipts::resetWorkReceiptId($pdo); $sql = "UPDATE %customerlog% SET clsid=? WHERE clsid is null"; CommonUtils::execSql($pdo, $sql, array($newClosingId)); $sql = "UPDATE %hist% SET clsid=? WHERE clsid IS NULL"; CommonUtils::execSql($pdo, $sql, array($newClosingId)); // commit must before email, because there direct access to db happens $pdo->commit(); // now send the email $toEmail = $this->getGeneralItemFromDbWithPdo($pdo,"receiveremail"); if (($toEmail != '') && (strpos($toEmail,'@') !== false)) { $theSum = number_format($pricesum, 2, $decpoint, ''); $this->emailCsvCore($pdo,$newClosingId, $toEmail, "Tagesabschluss",$prevClosingDate,$closingTime,$theSum,$billsToTake); } $admin = new Admin(); $versionInfo = $admin->getEnv($pdo); $content = array("env" => $versionInfo,"result" => $pricesum, "closingid" => $newClosingId); if ($checkForNewVersionAvailable) { // check if new version is evailable // (do not inform user if last install or update is right before new version - let new version mature a bit..) $url = "http://www.ordersprinter.de/version/checkversion.php?"; $url .= "v=" .$versionInfo["version"] . "&i=" . $versionInfo["installdate"] . "l=" . $versionInfo["lastupdate"]; $ctx = stream_context_create(array('http'=> array( 'timeout' => 5, // 5 seconds ) )); $newversionavailable = @file_get_contents($url, false, $ctx); // TODO: has to be forwarded to user to inform him } CommonUtils::keepOnlyLastLog($pdo); // call plugin after completion of closing CommonUtils::callPlugin($pdo, "createClosing", "after"); return(array("status" => "OK", "msg" => $content, "print" => $doPrint)); } private function getSumOfBillsWithClosingId($pdo,$closingid,$onlyBar) { $sql = "SELECT count(id) as countid FROM %bill% WHERE closingid=?"; $stmt = $pdo->prepare(DbUtils::substTableAlias($sql)); $stmt->execute(array($closingid)); $row = $stmt->fetchObject(); if ($row->countid == 0) { return 0.0; } $sql = "SELECT sum(brutto) as billsum FROM %bill% WHERE closingid=?"; if ($onlyBar) { $sql .= " AND paymentid='1'"; } $stmt = $pdo->prepare(DbUtils::substTableAlias($sql)); $stmt->execute(array($closingid)); $row = $stmt->fetchObject(); $sum = floatval($row->billsum); return $sum; } private function getUserGroupedSumOfClosing($pdo,$closingid) { $sql = "SELECT userid,username,"; $sql .= "ROUND(sum(brutto),2) as billsumall,"; $sql .= "ROUND(sum(if(paymentid='1',brutto,'0.00')),2) as sumonlybar,"; $sql .= "ROUND(sum(if(status = 'c',brutto,'0.00')),2) as sumcash "; $sql .= "FROM %bill%,%user% WHERE userid=%user%.id AND closingid=? GROUP BY userid,username"; $stmt = $pdo->prepare(DbUtils::substTableAlias($sql)); $stmt->execute(array($closingid)); $result = $stmt->fetchAll(); return $result; } private function getTaxesGroupedOfClosing($pdo,$closingid) { $sql = "SELECT %queue%.tax as tax,SUM(price) as brutto,ROUND(SUM(price)/(1 + %queue%.tax/100.0),2) as netto FROM %queue%,%bill%,%closing% "; $sql .= " WHERE billid=%bill%.id AND %bill%.closingid=%closing%.id AND closingid=? GROUP BY tax"; $stmt = $pdo->prepare(DbUtils::substTableAlias($sql)); $stmt->execute(array($closingid)); return ($stmt->fetchAll(PDO::FETCH_OBJ)); } private function getCashOpsOfClosing($pdo,$closingid) { $sql = "SELECT SUM(brutto) as cashsum FROM %bill%,%closing% WHERE status=? AND closingid=%closing%.id AND closingid=?"; $stmt = $pdo->prepare(DbUtils::substTableAlias($sql)); $stmt->execute(array('c',$closingid)); $row = $stmt->fetchObject(); return ($row->cashsum); } private function getCategoriasBruttoOfClosing($pdo,$closingid) { $sql = "SELECT SUM(price) as brutto,kind FROM %queue% Q,%bill%,%closing%,%prodtype% T,%products% P "; $sql .= " WHERE billid=%bill%.id AND %bill%.closingid=%closing%.id AND closingid=? "; $sql .= " AND Q.productid=P.id AND P.category=T.id "; $sql .= " GROUP BY kind"; $stmt = $pdo->prepare(DbUtils::substTableAlias($sql)); $stmt->execute(array($closingid)); return ($stmt->fetchAll(PDO::FETCH_OBJ)); } private static function getFirstAndLastClosing() { $pdo = DbUtils::openDbAndReturnPdoStatic(); $sql = "select id,closingdate from %closing% ORDER BY closingdate LIMIT 1"; $firstClosing = CommonUtils::fetchSqlAll($pdo, $sql); $sql = "select id,closingdate from %closing% ORDER BY closingdate DESC LIMIT 1"; $lastClosing = CommonUtils::fetchSqlAll($pdo, $sql); echo json_encode(array("status" => "OK", "firstclosing" => self::closingSqlDateToText($firstClosing),"lastclosing" => self::closingSqlDateToText($lastClosing))); } private static function closingSqlDateToText($closdate) { if (count($closdate) > 0) { return $closdate[0]["closingdate"]; } else { return ""; } } private function getClosingsListOfMonthYear($month,$year) { $pdo = DbUtils::openDbAndReturnPdoStatic(); date_default_timezone_set(DbUtils::getTimeZone()); $monthText=$month; if ($month < 10) { $monthText = "0" . $month; } $lastDayInMonth = date("t", mktime(0, 0, 0, $month, 1, $year)); $dateStart = $year . $monthText . "01"; $dateEnd = $year . $monthText . $lastDayInMonth; $sql = "SELECT id,IFNULL(remark,'') as remark,DATE_FORMAT(closingdate,'%w') as dayofweek,DATE_FORMAT(closingdate, '%d.%m.%Y %k:%i') as closdate from %closing% WHERE DATE(closingdate) BETWEEN ? AND ? ORDER BY id"; $result = CommonUtils::fetchSqlAll($pdo, $sql, array($dateStart,$dateEnd)); echo json_encode(array("status" => "OK", "msg" => $result)); } /* * Get all closings that are requested: * if month and year is null or empty ==> last 30 closings * otherwise query by date */ private function getClosings($month, $year) { $pdo = DbUtils::openDbAndReturnPdoStatic(); date_default_timezone_set(DbUtils::getTimeZone()); $monthText=$month; if ($month < 10) { $monthText = "0" . $month; } $lastDayInMonth = date("t", mktime(0, 0, 0, $month, 1, $year)); $dateStart = $year . $monthText . "01"; $dateEnd = $year . $monthText . $lastDayInMonth; $sql = "SELECT id,closingdate,remark FROM %closing% WHERE DATE(closingdate) BETWEEN ? AND ? ORDER BY closingdate DESC"; $result = CommonUtils::fetchSqlAll($pdo, $sql, array($dateStart,$dateEnd)); $resultarray = array(); foreach($result as $zeile) { $theId = $zeile['id']; $closingDate = $zeile['closingdate']; $remark = $zeile['remark']; $totalSum = $this->getSumOfBillsWithClosingId($pdo,$theId, false); $cashSum = $this->getSumOfBillsWithClosingId($pdo,$theId, true); $userSums = $this->getUserGroupedSumOfClosing($pdo, $theId); $taxessums = $this->getTaxesGroupedOfClosing($pdo,$theId); $categorysums = $this->getCategoriasBruttoOfClosing($pdo,$theId); $cashops = $this->getCashOpsOfClosing($pdo,$theId); $daynameno = date('N', strtotime($closingDate)); $closingEntry = array("id" => $theId, "closingDate" => $closingDate, "daynameno" => $daynameno, "remark" => $remark, "totalsum" => $totalSum, "cashsum" => $cashSum, "usersums" => $userSums, "taxessums" => $taxessums, "categorysums" => $categorysums, "cashops" => $cashops); $resultarray[] = $closingEntry; } echo json_encode(array("status" => "OK", "msg" => $resultarray)); } private function getPaymentArray($pdo) { $sql = "SELECT id,name FROM %payment%"; $stmt = $pdo->prepare(DbUtils::substTableAlias($sql)); $stmt->execute(); $result = $stmt->fetchAll(); $retArray = array(); foreach($result as $zeile) { $retArray[$zeile['id']] = $zeile['name']; } return $retArray; } private function getClosing($closingid) { $pdo = DbUtils::openDbAndReturnPdoStatic(); $this->retrieveClosingFromDb($pdo,$closingid, false, false); } private function exportCsv($closingid) { $pdo = DbUtils::openDbAndReturnPdoStatic(); $this->retrieveClosingFromDb($pdo,$closingid, true, false); } private function exportGuestCsv($closingid) { $pdo = DbUtils::openDbAndReturnPdoStatic(); Customers::exportLogOfOneClosing($pdo, $closingid); } private function emailCsvCore($pdo,$closingid,$toEmail,$topic,$startdate,$enddate,$billsum,$billcount) { $msg = $this->getClosingByTaxAndUser($pdo,$closingid); $msg .= $this->retrieveClosingFromDb($pdo,$closingid, false, true); $msg = "Zeitraum: $startdate - $enddate\nBrutto-Summe: $billsum\nEnthaltene Bons: $billcount\n\n" . $msg; $msg = str_replace("\n", "\r\n", $msg); $topictxt = $topic . " " . $closingid . "\r\n"; if (Emailer::sendEmail($pdo, $msg, $toEmail, $topictxt)) { return true; } else { return false; } } private function emailCsv($closingid,$toEmail,$topic) { // additional info to insert into email $decpoint = $this->getDecPoint(); $pdo = $this->dbutils->openDbAndReturnPdo(); $prevClosingDate = self::getDateOfPreviousClosing($pdo,$closingid); if (is_null($prevClosingDate)) { $prevClosingDate = ""; } $sql = "SELECT closingdate, billcount, billsum FROM %closing% WHERE id=?"; $stmt = $pdo->prepare($this->dbutils->resolveTablenamesInSqlString($sql)); $stmt->execute(array($closingid)); $row = $stmt->fetchObject(); $billsum = number_format($row->billsum, 2, $decpoint, ''); $billcount = $row->billcount; $closdate = $row->closingdate; if ($this->emailCsvCore($pdo,$closingid, $toEmail, $topic, $prevClosingDate,$closdate,$billsum,$billcount)) { echo json_encode(array("status" => "OK")); } else { echo json_encode(array("status" => "ERROR", "code" => ERROR_EMAIL_FAILURE, "msg" => ERROR_EMAIL_FAILURE_MSG)); } } private function getGeneralItemFromDb($field) { $pdo = $this->dbutils->openDbAndReturnPdo(); $this->getGeneralItemFromDbWithPdo($pdo, $field); } private function getGeneralItemFromDbWithPdo($pdo,$field) { if (is_null($pdo)) { $pdo = $this->dbutils->openDbAndReturnPdo(); } $aValue=""; $sql = "SELECT setting FROM %config% where name='$field'"; $stmt = $pdo->prepare($this->dbutils->resolveTablenamesInSqlString($sql)); $stmt->execute(); $row =$stmt->fetchObject(); if ($row != null) { $aValue = $row->setting; } return $aValue; } public static function getDateOfPreviousClosing($pdoval,$closingid) { if (is_null($pdoval)) { $pdo = DbUtils::openDbAndReturnPdoStatic(); } else { $pdo = $pdoval; } // ids can be generated but not used in case of rollback $sql = "SELECT MAX(id) as previousid FROM %closing% WHERE id"; $stmt = $pdo->prepare(DbUtils::substTableAlias($sql)); $stmt->execute(array($closingid)); $row =$stmt->fetchObject(); if ($row != null) { $previousId = intval($row->previousid); $sql = "SELECT closingdate FROM %closing% WHERE id=?"; $stmt = $pdo->prepare(DbUtils::substTableAlias($sql)); $stmt->execute(array($previousId)); $row =$stmt->fetchObject(); if ($row != null) { return $row->closingdate; } else { return null; } } else { return null; } } private function returnErrorInconsDB($doCsvExport,$onlyresultreturn) { if ($doCsvExport) { echo "ERROR - signatures do not fit"; } else if ($onlyresultreturn) { return "Tagesabschluss-Datum: $closingdate\nBemerkung: $remark\nStatus: Inkonsistente Datenbank\n\ncsv-Daten:\n" . $csv; } else { echo json_encode(array("status" => "ERROR", "code" => ERROR_INCONSISTENT_DB, "msg" => ERROR_INCONSISTENT_DB_MSG)); } } private function getClosingByTaxAndUser($pdo,$closingid) { $sql = "SELECT sum(price) as sumprice,%queue%.tax as thetax,username "; $sql .= "FROM %bill%,%billproducts%,%queue%,%user% "; $sql .= "WHERE %billproducts%.billid=%bill%.id AND %bill%.closingid=? AND %bill%.userid=%user%.id AND %billproducts%.queueid=%queue%.id "; $sql .= "AND (%bill%.status is null OR %bill%.status != (? OR ? OR ?)) "; $sql .= "GROUP BY username,thetax "; $decpoint = CommonUtils::getConfigValue($pdo, "decpoint", ","); $result = CommonUtils::fetchSqlAll($pdo, $sql, array($closingid,'c','x','s')); $count = count($result); if ($count == 0) { return ""; } else { $msg = "Umsätze aufgeschlüsselt nach Benutzer und Steuersatz (ohne Ein-/Auslagen):\n\n"; $msg .= "Benutzer;Steuersatz;Umsatz (Brutto)\n"; foreach($result as $res) { // sumprice | thetax | username $tax = str_replace('.', $decpoint, $res['thetax']); $sumprice = str_replace('.', $decpoint, $res['sumprice']); $msg .= $res['username'] . ";$tax;$sumprice\n"; } return $msg . "\n"; } } private function retrieveClosingFromDb($pdo,$closingid,$doCsvExport,$onlyresultreturn) { if(session_id() == '') { session_start(); } $l = $_SESSION['language']; $commonUtils = new CommonUtils(); $currency = $commonUtils->getCurrency(); $decpoint = $this->getDecPoint(); $paymentArray = $this->getPaymentArray($pdo); $previousClosingDate = self::getDateOfPreviousClosing(null,$closingid); $csv = ""; if ($doCsvExport || $onlyresultreturn) { $file_name = "tagesabschluss.csv"; header("Content-type: text/x-csv"); header("Content-Disposition: attachment; filename=$file_name"); header("Cache-Control: must-revalidate, post-check=0, pre-check=0"); header("Pragma: no-cache"); header("Expires: 0"); $csv .= $this->t['ID'][$l] . ";" . $this->t['Date'][$l] . ";" . $this->t['Tablename'][$l] . ";" . $this->t['Prod'][$l] . ";" . $this->t['Category'][$l] . ";" . $this->t['Option'][$l] . ";" . $this->t['Brutto'][$l] . "($currency);"; $csv .= $this->t['Netto'][$l] . "($currency);"; $csv .= $this->t['Tax'][$l] . ";"; $csv .= $this->t['PayWay'][$l] . ";"; $csv .= $this->t['Userid'][$l] . ";"; $csv .= $this->t['User'][$l] . ";"; $csv .= $this->t['State'][$l] . ";"; $csv .= $this->t['Ref'][$l] . "\n"; } $sql = "SELECT closingdate,remark,signature,billsum,billcount FROM %closing% WHERE id=?"; $stmt = $pdo->prepare(DbUtils::substTableAlias($sql)); $stmt->execute(array($closingid)); $row = $stmt->fetchObject(); $closingdate = $row->closingdate; $remark = $row->remark; $billsum = $row->billsum; $billcount = $row->billcount; $signature = $row->signature; $sql = "SELECT %bill%.id as id,IF(tableid > '0',(SELECT tableno FROM %resttables% WHERE id=tableid),'') as tablename,paymentid,billdate,userid,ref,username,status,brutto,netto,IF(tax is not null, tax, '0.00') as tax FROM %bill%,%user% WHERE closingid=? AND %bill%.userid = %user%.id ORDER BY billdate"; $stmt = $pdo->prepare(DbUtils::substTableAlias($sql)); $stmt->execute(array($closingid)); $billIdsAndPaymentsForThatClosing = $stmt->fetchAll(); $foundBillCount = count($billIdsAndPaymentsForThatClosing); if (is_null($previousClosingDate)) { $startDate = ""; } else { $startDate = $previousClosingDate; } $billsumstr = number_format($billsum, 2, ".", ''); $data = "I($closingid)-S($startDate)-E($closingdate)-D($billcount)-S($billsumstr)"; $md5ofData = md5($data); $ok = 1; if ($signature != $md5ofData) { $ok = 0; } if (($ok == 0) || ($billcount <> $foundBillCount)) { // something went wrong! $this->returnErrorInconsDB($doCsvExport, $onlyresultreturn); return; } $retValues = array(); for ($index=0;$index < count($billIdsAndPaymentsForThatClosing);$index++) { $aBillId = $billIdsAndPaymentsForThatClosing[$index]['id']; if (!$commonUtils->verifyBill($pdo, $aBillId)) { $this->returnErrorInconsDB($doCsvExport, $onlyresultreturn); return; } $tablename = $billIdsAndPaymentsForThatClosing[$index]['tablename']; $billdate = $billIdsAndPaymentsForThatClosing[$index]['billdate']; $paymentid = $billIdsAndPaymentsForThatClosing[$index]['paymentid']; $userid = $billIdsAndPaymentsForThatClosing[$index]['userid']; $username = $billIdsAndPaymentsForThatClosing[$index]['username']; $status = $billIdsAndPaymentsForThatClosing[$index]['status']; $brutto = $billIdsAndPaymentsForThatClosing[$index]['brutto']; $netto = $billIdsAndPaymentsForThatClosing[$index]['netto']; $tax = $billIdsAndPaymentsForThatClosing[$index]['tax']; $ref = $billIdsAndPaymentsForThatClosing[$index]['ref']; $ref = ($ref == null ? "" : $ref); if ($status == 'c') { $statusTxt = $this->t['cashact'][$l]; // "Bareinlage/-entnahme"; $brutto = number_format($brutto, 2, $decpoint, ''); $netto = number_format($netto, 2, $decpoint, ''); $tax = number_format($tax, 2, $decpoint, ''); $retValues[] = array ( "billid" => $aBillId, "tablename" => '', "paidtime" => $billdate, "productname" => $this->t['cashaction'][$l], // Kassenaktion "kind" => "-", "option" => '', "price" => $brutto, "netto" => $netto, "tax" => number_format(0.00, 2, $decpoint, ''), "payment" => $paymentArray[$paymentid], "userid" => $userid, "username" => $username, "status" => $statusTxt, "ref" => $ref); if ($doCsvExport || $onlyresultreturn) { $csv .= "$aBillId; \"$billdate\" ; \"$tablename\" ; \"" . $this->t['cashaction'][$l] . "\" ; - ; \"\" ; \"$brutto\" ; \"$netto\" ; \"$tax\" ; \"$paymentArray[$paymentid]\";$userid; \"$username\"; \"$statusTxt\"; $ref\n"; } } else { $unit = CommonUtils::caseOfSqlUnitSelection($pdo); $sql = "SELECT DISTINCT CONCAT($unit,productname) as productname,price,Q.tax as tax,anoption,kind FROM %queue% Q,%billproducts%,%prodtype%,%products% P WHERE %billproducts%.billid=? AND %billproducts%.queueid=Q.id AND Q.productid=P.id AND P.category=%prodtype%.id"; if ($status == 'x') { $statusTxt = $this->t["laterCancelled"][$l]; } else if ($status == 's') { $statusTxt = $this->t["storno"][$l]; } else { $statusTxt = ""; $sql = "SELECT CONCAT($unit,productname) as productname,anoption,paidtime,price,Q.tax as tax,kind FROM %queue% Q,%prodtype%,%products% P WHERE billid=? AND Q.productid=P.id AND P.category=%prodtype%.id"; } $stmt = $pdo->prepare(DbUtils::substTableAlias($sql)); $stmt->execute(array($aBillId)); $result = $stmt->fetchAll(); foreach ($result as $zeile) { $productname = $zeile['productname']; $option = $zeile['anoption']; $tax = $zeile['tax']; $kind = "Speise"; if ($zeile['kind'] == 1) { $kind = "Getraenk"; } $paidtime = ($billdate == null ? "" : $billdate) ; $price = ($status == 's' ? 0.0-floatval($zeile['price']) : $zeile['price']); $netto = $price/(1 + $tax/100.0); $netto = number_format($netto, 2, $decpoint, ''); $price = number_format($price, 2, $decpoint, ''); $formattedtax = number_format($tax, 2, $decpoint, ''); $retValues[] = array ( "billid" => $aBillId, "tablename" => $tablename, "paidtime" => $paidtime, "productname" => $productname, "kind" => $kind, "option" => $option, "price" => $price, "netto" => $netto, "tax" => $formattedtax, "payment" => $paymentArray[$paymentid], "userid" => $userid, "username" => $username, "status" => $statusTxt, "ref" => $ref); $productname = str_replace('"','""',$productname); $option = str_replace('"','""',$option); if ($doCsvExport || $onlyresultreturn) { $csv .= "$aBillId; \"$paidtime\" ; \"$tablename\" ; \"$productname\" ; \"$kind\" ; \"$option\" ; \"$price\" ; \"$netto\" ; \"$formattedtax\" ; \"$paymentArray[$paymentid]\"; $userid; \"$username\"; \"$statusTxt\"; $ref\n"; } } } } if ($doCsvExport) { echo $csv; } else if ($onlyresultreturn) { return "Tagesabschluss-Datum: $closingdate\nBemerkung: $remark\n\ncsv-Daten:\n" . $csv; } else { echo json_encode(array("status" => "OK", "msg" => $retValues, "closingid" => $closingid, "closingdate" => $closingdate, "previousClosingDate" => $previousClosingDate)); } } public function getClosingSummaryWoSign($closingid,$pdo,$fromWeb,$fl=0) { return $this->getClosingSummaryCore($closingid, $pdo, $fromWeb, false,$fl); } public function getClosingSummary($closingid,$pdo,$fromWeb,$fl=0) { return $this->getClosingSummaryCore($closingid, $pdo, $fromWeb, true,$fl); } public static function signAllClosings($pdo) { $sql = "select id,closingdate,billcount,billsum,remark,signature from %closing%"; $r = CommonUtils::fetchSqlAll($pdo, $sql); $sql = "UPDATE %closing% SET signature=? WHERE id=?"; foreach ($r as $c) { $closingid = $c["id"]; $previousClosingDate = self::getDateOfPreviousClosing($pdo,$closingid); if (is_null($previousClosingDate)) { $startDate = ""; } else { $startDate = $previousClosingDate; } $billsumstr = number_format($c["billsum"], 2, ".", ''); $billcount = $c["billcount"]; $closingdate = $c["closingdate"]; $data = "I($closingid)-S($startDate)-E($closingdate)-D($billcount)-S($billsumstr)"; $md5ofdata = md5($data); CommonUtils::execSql($pdo, $sql, array($md5ofdata,$closingid)); } } public static function checkForClosingConsistency($pdo,$closingid) { $sql = "select id,closingdate,billcount,billsum,remark,signature from %closing% where id=?"; $stmt = $pdo->prepare(DbUtils::substTableAlias($sql)); $stmt->execute(array($closingid)); $closingpart = $stmt->fetchObject(); $previousClosingDate = self::getDateOfPreviousClosing($pdo,$closingid); if (is_null($previousClosingDate)) { $startDate = ""; } else { $startDate = $previousClosingDate; } $billsumstr = number_format($closingpart->billsum, 2, ".", ''); $billcount = $closingpart->billcount; $closingdate = $closingpart->closingdate; $data = "I($closingid)-S($startDate)-E($closingdate)-D($billcount)-S($billsumstr)"; $md5ofdata = md5($data); $ok = 1; if (($closingpart->signature) != $md5ofdata) { $ok = 0; } return $ok; } public function getClosingSummaryCore($closingid,$pdo,$fromWeb,$exportSignature,$fl=0) { if(is_null($pdo)) { $pdo = $this->dbutils->openDbAndReturnPdo(); }; $sql = "select id,closingdate,billcount,billsum,remark,signature from %closing% where id=?"; $stmt = $pdo->prepare(DbUtils::substTableAlias($sql)); $stmt->execute(array($closingid)); $closingpart = $stmt->fetchObject(); $ok = self::checkForClosingConsistency($pdo, $closingid); if (($ok == 0)) { if ($fromWeb) { echo json_encode(array("status" => "ERROR", "code" => ERROR_INCONSISTENT_DB, "msg" => ERROR_INCONSISTENT_DB_MSG)); return; } else { return null; } } if ($fl < 14) { $sql = "select sum(%bill%.brutto) as sum,round(sum(%bill%.netto),2) as netto,%payment%.name,%bill%.status from %bill%,%payment% where "; $sql .= "%bill%.closingid=? and "; $sql .= "%bill%.paymentid=%payment%.id "; $sql .= "group by %bill%.tax,%payment%.name,%bill%.status"; $overview = CommonUtils::fetchSqlAll($pdo, $sql, array($closingid)); } else { $sql = "SELECT SUM(B.brutto) as sum,round(sum(B.netto),2) as netto,P.name,IF(B.status='x',null,B.status) as status from %bill% B,%payment% P WHERE "; $sql .= "B.closingid=? AND B.paymentid=P.id AND "; $sql .= "(B.status <> 's' OR B.status is null) "; $sql .= "GROUP BY B.tax,P.name,B.status "; $sql .= "HAVING SUM(B.brutto) is not null "; $sql .= " UNION ALL "; $sql .= "SELECT sum(B.brutto) as sum,round(sum(B.netto),2) as netto,'',B.status from %bill% B WHERE "; $sql .= "B.closingid=? AND B.status='s' "; $sql .= "HAVING sum(B.brutto) is not null "; $sql .= " UNION ALL "; $sql .= "SELECT sum(Q.price) as sum,TRUNCATE(sum(Q.price / (1 + Q.tax * 0.01)),2) as netto,'','d' from %queue% Q WHERE Q.toremove='1' AND Q.clsid=? "; $sql .= "HAVING sum(Q.price) is not null "; $overview = CommonUtils::fetchSqlAll($pdo, $sql, array($closingid,$closingid,$closingid)); } $sql = "select %queue%.tax as t,SUM(%queue%.price) as bruttosum,ROUND(SUM(%queue%.price)/(1 + %queue%.tax/100.0),2) as nettosum "; $sql .= " FROM %bill%,%queue% "; $sql .= " WHERE %bill%.closingid=? AND %queue%.billid=%bill%.id GROUP BY t"; $stmt = $pdo->prepare($this->dbutils->resolveTablenamesInSqlString($sql)); $stmt->execute(array($closingid)); $taxessum = $stmt->fetchAll(PDO::FETCH_ASSOC); $sql = "SELECT DISTINCT paymentid,name FROM %bill%,%payment% WHERE %bill%.closingid=? AND %bill%.paymentid=%payment%.id"; $payments = CommonUtils::fetchSqlAll($pdo, $sql, array($closingid)); $paymenttaxes = array(); foreach($payments as $aPayment) { $sql = "select %queue%.tax as t,SUM(%queue%.price) as bruttosum,ROUND(SUM(%queue%.price)/(1 + %queue%.tax/100.0),2) as nettosum "; $sql .= " FROM %bill%,%queue% "; $sql .= " WHERE %bill%.closingid=? AND %queue%.billid=%bill%.id AND %bill%.paymentid=? GROUP BY t"; $paymenttaxessum = CommonUtils::fetchSqlAll($pdo, $sql, array($closingid,$aPayment["paymentid"])); if (count($paymenttaxessum) > 0) { $paymenttaxes[] = array("payment" => $aPayment["name"],"paymenttaxessum" => $paymenttaxessum); } } $sql = "select count(%queue%.productname) as count,%queue%.productname,%queue%.price,%queue%.tax as tax,sum(%queue%.price) as sumprice "; $sql .= " from %queue%,%bill% where "; $sql .= "%queue%.billid=%bill%.id AND %bill%.closingid=? AND "; $sql .= "%bill%.status is null "; $sql .= "group by %queue%.productname,%queue%.tax,%queue%.price"; $stmt = $pdo->prepare($this->dbutils->resolveTablenamesInSqlString($sql)); $stmt->execute(array($closingid)); $details = $stmt->fetchAll(PDO::FETCH_ASSOC); // -> returns something like this: if (!$exportSignature || $fromWeb) { unset($closingpart->signature); } if ($fl >= 8) { $closshowci = CommonUtils::getConfigValue($pdo, 'closshowci', 1); $closshowpaytaxes = CommonUtils::getConfigValue($pdo, 'closshowpaytaxes', 1); $closshowprods = CommonUtils::getConfigValue($pdo, 'closshowprods', 1); $companyinfo = CommonUtils::getConfigValueAtClosingTime($pdo, 'companyinfo', '', $closingid); $retVal = array("closing" => $closingpart, "overview" => $overview, "details" => $details, "taxessum" => $taxessum, "companyinfo" => $companyinfo, "paymenttaxessum" => $paymenttaxes, "closshowci" => $closshowci, "closshowpaytaxes" => $closshowpaytaxes, "closshowprods" => $closshowprods, ); if ($fl >= 15) { $retVal["sn"] = CommonUtils::getConfigValueAtClosingTime($pdo, 'sn', "?", $closingid); $retVal["uid"] = CommonUtils::getConfigValueAtClosingTime($pdo, 'uid', "?", $closingid); $retVal["version"] = CommonUtils::getConfigValueAtClosingTime($pdo, 'version', "?", $closingid); $retVal["systemid"] = CommonUtils::getConfigValueAtClosingTime($pdo, 'systemid', "?", $closingid); } } else if ($fl >= 3) { $retVal = array("closing" => $closingpart, "overview" => $overview, "details" => $details, "taxessum" => $taxessum); } else { $retVal = array("closing" => $closingpart, "overview" => $overview, "details" => $details); } if ($fromWeb) { echo json_encode(array("status" => "OK", "msg" => $retVal)); } else { return $retVal; } } private function htmlreport($closingid) { $pdo = DbUtils::openDbAndReturnPdoStatic(); $ok = self::checkForClosingConsistency($pdo, $closingid); if (($ok == 0)) { echo "Datenbank inkonsistent"; return; } $closing = $this->getClosingSummaryCore($closingid,$pdo,false,false,8); $clostemplate = CommonUtils::getConfigValue($pdo, "clostemplate", "Kein Template festgelegt"); $templatelines = Templateutils::getTemplateAsLineArray($clostemplate); $reporter = new ClosTemplater($templatelines,$closingid,$closing); $txt = $reporter->createWithTemplate($pdo); $html = ""; $html = "
"; $html .= ""; $html .= $txt; $version = CommonUtils::getConfigValue($pdo, "version", ""); $html .= "