1258 lines
46 KiB
PHP
1258 lines
46 KiB
PHP
<?php
|
|
// Datenbank-Verbindungsparameter
|
|
require_once ('dbutils.php');
|
|
require_once ('commonutils.php');
|
|
require_once ('globals.php');
|
|
require_once ('admin.php');
|
|
require_once ('customers.php');
|
|
require_once ('utilities/Emailer.php');
|
|
|
|
class Closing {
|
|
var $dbutils;
|
|
var $t;
|
|
|
|
function __construct() {
|
|
$this->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'],$_POST['counting'],$_POST['coinscount'],$_POST['notescount'],$_POST['counted']);
|
|
} 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 if ($command == 'getCashSumsForNextClosing') {
|
|
$pdo = DbUtils::openDbAndReturnPdoStatic();
|
|
self::getCashSumsForNextClosing($pdo);
|
|
} 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,0,0,0,0.0));
|
|
} else {
|
|
echo json_encode("Remote access code not correct!");
|
|
}
|
|
}
|
|
}
|
|
|
|
private function createClosing ($remark,$doPrint,$counting,$coinscount,$notescount,$counted) {
|
|
$pdo = DbUtils::openDbAndReturnPdoStatic();
|
|
date_default_timezone_set(DbUtils::getTimeZone());
|
|
if (!$this->isClosingAllowed($pdo)) {
|
|
if (!CommonUtils::startsWith($remark, "Test")) {
|
|
// for auto-tests do not require that time in between
|
|
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,$counting,$coinscount,$notescount,$counted);
|
|
echo json_encode($result);
|
|
}
|
|
|
|
private static function insertCounting($pdo,$clsid,$coinscount,$notescount) {
|
|
self::insertCountingOfType($pdo, $clsid, $coinscount, 1);
|
|
self::insertCountingOfType($pdo, $clsid, $notescount, 0);
|
|
}
|
|
private static function insertCountingOfType($pdo,$clsid,$counts,$type) {
|
|
$sql = "INSERT INTO %counting% (clsid,value,count,iscoin) VALUES(?,?,?,?)";
|
|
foreach($counts as $c) {
|
|
$value = $c["value"];
|
|
$count = $c["count"];
|
|
CommonUtils::execSql($pdo, $sql, array($clsid,$value,$count,$type));
|
|
}
|
|
}
|
|
|
|
public function createClosingCore ($pdo,$remark,$doPrint, $closingTime,$checkForNewVersionAvailable,$counting,$coinscount,$notescount,$counted) {
|
|
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)) {
|
|
$prevClsId = $maxIdRes[0]["maxid"];
|
|
if (!is_null($prevClsId)) {
|
|
$maxId = intval($prevClsId);
|
|
}
|
|
|
|
}
|
|
$newClosingId = $prevClsId + 1;
|
|
|
|
$dsfinvkversion = CommonUtils::getConfigValue($pdo, 'dsfinvkversion', null);
|
|
$dsfinvk_name = CommonUtils::getConfigValue($pdo, 'dsfinvk_name', null);
|
|
$dsfinvk_street = CommonUtils::getConfigValue($pdo, 'dsfinvk_street', null);
|
|
$dsfinvk_postalcode = CommonUtils::getConfigValue($pdo, 'dsfinvk_postalcode', null);
|
|
$dsfinvk_city = CommonUtils::getConfigValue($pdo, 'dsfinvk_city', null);
|
|
$dsfinvk_country = CommonUtils::getConfigValue($pdo, 'dsfinvk_country', null);
|
|
$dsfinvk_stnr = CommonUtils::getConfigValue($pdo, 'dsfinvk_stnr', null);
|
|
$dsfinvk_ustid = CommonUtils::getConfigValue($pdo, 'dsfinvk_ustid', null);
|
|
$version = CommonUtils::getConfigValue($pdo, 'version', '');
|
|
$taxset1 = CommonUtils::getConfigValue($pdo, 'tax', 19.00);
|
|
$taxset2 = CommonUtils::getConfigValue($pdo, 'togotax', 7.00);
|
|
|
|
$terminalInfo = Terminals::getTerminalInfo();
|
|
$terminalEntryId = Terminals::createOrReferenceTerminalDbEntry($pdo, $terminalInfo);
|
|
|
|
$dsfinvkCols = "`dsfinvkversion`,`dsfinvk_name`,`dsfinvk_street`,`dsfinvk_postalcode`,`dsfinvk_city`,`dsfinvk_country`,`dsfinvk_stnr`,`dsfinvk_ustid`,`terminalid`";
|
|
$dsfinvkQuests = "?,?,?,?,?,?,?,?,?";
|
|
$closingEntrySql = "INSERT INTO `%closing%` (`id`,`closingdate`,`remark`,`billcount`,`billsum`,`signature`,`counting`,`counted`,$dsfinvkCols,`version`,`taxset1`,`taxset2`) VALUES (?,?,?,?,?,?,?,?,$dsfinvkQuests,?,?,?)";
|
|
CommonUtils::execSql($pdo, $closingEntrySql, array($newClosingId,$closingTime,$remark,0,0.0,null,$counting,$counted,
|
|
$dsfinvkversion,$dsfinvk_name,$dsfinvk_street,$dsfinvk_postalcode,$dsfinvk_city,$dsfinvk_country,$dsfinvk_stnr,$dsfinvk_ustid,$terminalEntryId,$version,$taxset1,$taxset2));
|
|
|
|
if ($counting == 1) {
|
|
self::insertCounting($pdo,$newClosingId,$coinscount,$notescount);
|
|
}
|
|
|
|
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));
|
|
|
|
|
|
if ($counting == 0) {
|
|
$sql = "SELECT counted FROM %closing% WHERE id=?";
|
|
$previousCounted = CommonUtils::fetchSqlAll($pdo, $sql, array($prevClsId));
|
|
$prevCountedVal = doubleVal($previousCounted[0]["counted"]);
|
|
|
|
$sql = "SELECT COALESCE(SUM(B.brutto),'0.00') as sumbrutto FROM %bill% B,%closing% C WHERE B.paymentid='1' AND C.id=? AND C.id=B.closingid AND B.intguestid is null";
|
|
$result = CommonUtils::fetchSqlAll($pdo, $sql,array($newClosingId));
|
|
$salesAndCashOps = doubleVal($result[0]['sumbrutto']);
|
|
|
|
$sql = "UPDATE %closing% SET counted=? WHERE id=?";
|
|
CommonUtils::execSql($pdo, $sql, array($prevCountedVal + $salesAndCashOps,$newClosingId));
|
|
}
|
|
$sql = "SELECT FORMAT(COALESCE(SUM(brutto),'0.00'),2) as cashsum FROM %closing% C ";
|
|
$sql .= " INNER JOIN %bill% B ON B.closingid=C.id ";
|
|
$sql .= " WHERE C.id=? and B.paymentid=?";
|
|
$cashsumresult = CommonUtils::fetchSqlAll($pdo, $sql, array($newClosingId,1));
|
|
$sql = "UPDATE %closing% SET cashsum=? WHERE id=?";
|
|
CommonUtils::execSql($pdo, $sql, array($cashsumresult[0]['cashsum'],$newClosingId));
|
|
|
|
$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));
|
|
|
|
self::signValueByTseAndUpdateClosing($pdo, $newClosingId, "Kassenabschluss $newClosingId - $closingTime");
|
|
|
|
// 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
|
|
)
|
|
));
|
|
|
|
if (!CommonUtils::startsWith($remark, "Test")) {
|
|
// for auto-tests do not check for new available versions
|
|
$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,COALESCE(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,counting,counted 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'];
|
|
$counting = $zeile['counting'];
|
|
$counted = $zeile['counted'];
|
|
$masterData = CommonUtils::getMasterDataAtCertainDateTime($pdo, $closingDate, "clstemplate");
|
|
$coinname = $masterData['coinvalname'];
|
|
$notename = $masterData['notevalname'];
|
|
$barTotalBeforeTE = self::getBarTotalBeforeTE($pdo,$theId,'.');
|
|
$barTotalAfterTE = self::getBarTotalAfterTE($pdo,$theId,'.');
|
|
|
|
$diffSollIst = 0.0;
|
|
if ($counting == 1) {
|
|
$sql = "SELECT id,value,count,iscoin,IF(iscoin='1','Münzen','Banknoten') as coinsornotes,FORMAT((count*value*IF(iscoin='1',1,100))/100.0,2) as sum,IF(iscoin='1',1,100) as factor FROM %counting% WHERE clsid=? ORDER BY iscoin DESC,value";
|
|
$countingprotocol = CommonUtils::fetchSqlAll($pdo, $sql, array($theId));
|
|
$diffSollIst = $barTotalAfterTE - $counted;
|
|
} else {
|
|
$countingprotocol = array();
|
|
}
|
|
|
|
$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,
|
|
"counted" => $counted,
|
|
"coinname" => $coinname,
|
|
"notename" => $notename,
|
|
"countingprotocol" => $countingprotocol,
|
|
"barTotalBeforeTE" => $barTotalBeforeTE,
|
|
"barTotalAfterTE" => $barTotalAfterTE,
|
|
"diffsollist" => $diffSollIst);
|
|
$resultarray[] = $closingEntry;
|
|
}
|
|
|
|
echo json_encode(array("status" => "OK", "msg" => $resultarray));
|
|
}
|
|
|
|
private static function getBarTotalBeforeTE($pdo,$clsid,$decpoint) {
|
|
// TODO: include guest payments!
|
|
|
|
if ($clsid == 1) {
|
|
return "0.00";
|
|
}
|
|
|
|
$sqlPrevClsId = "SELECT IFNULL(MAX(id),'0') FROM %closing% C where id<?";
|
|
$sql = "SELECT REPLACE(COALESCE(counted,'0.00'),'.','$decpoint') as counted FROM %closing% WHERE id=($sqlPrevClsId)";
|
|
$countedSql = CommonUtils::fetchSqlAll($pdo, $sql, array($clsid));
|
|
return $countedSql[0]['counted'];
|
|
}
|
|
|
|
private static function getBarTotalAfterTE($pdo,$clsid,$decpoint) {
|
|
// TODO: include guest payments!
|
|
|
|
$previousCash = doubleVal(self::getBarTotalBeforeTE($pdo, $clsid, '.'));
|
|
|
|
$sql = "SELECT COALESCE(SUM(B.brutto),'0.00') as sumbrutto FROM %bill% B,%closing% C WHERE B.paymentid='1' AND C.id=? AND C.id=B.closingid AND B.intguestid is null";
|
|
$result = CommonUtils::fetchSqlAll($pdo, $sql,array($clsid));
|
|
$salesAndCashOps = doubleval($result[0]['sumbrutto']);
|
|
|
|
return number_format($salesAndCashOps + $previousCash,2,$decpoint,'');
|
|
}
|
|
|
|
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;
|
|
|
|
$cashSqlReadable = Bill::getTranslateSqlCashTypeToReadable();
|
|
$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,$cashSqlReadable 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] . $billIdsAndPaymentsForThatClosing[$index]['cashtype']; // "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,$replacedecpoint,$fl=0) {
|
|
return $this->getClosingSummaryCore($closingid, $pdo, $fromWeb, false,$replacedecpoint,$fl);
|
|
}
|
|
|
|
public function getClosingSummary($closingid,$pdo,$fromWeb,$fl=0) {
|
|
return $this->getClosingSummaryCore($closingid, $pdo, $fromWeb, true,false,$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;
|
|
}
|
|
|
|
private static function getClosingMasterDataAtClsTime($pdo,$closid) {
|
|
$sql = "SELECT closingdate FROM %closing% WHERE id=?";
|
|
$res = CommonUtils::fetchSqlAll($pdo, $sql, array($closid));
|
|
$clsdate = $res[0]["closingdate"];
|
|
return CommonUtils::getMasterDataAtCertainDateTime($pdo, $clsdate, "clstemplate");
|
|
}
|
|
|
|
public static function getCashSumsForNextClosing($pdo) {
|
|
$decpoint = CommonUtils::getConfigValue($pdo, "decpoint", ".");
|
|
|
|
$sql = "SELECT MAX(id) as maxid FROM %closing%";
|
|
$result = CommonUtils::fetchSqlAll($pdo, $sql);
|
|
$maxid = $result[0]["maxid"];
|
|
if (is_null($maxid)) {
|
|
$origCashInDeskFloat = 0.00;
|
|
} else {
|
|
$sql = "SELECT counted FROM %closing% WHERE id=?";
|
|
$result = CommonUtils::fetchSqlAll($pdo, $sql, array($maxid));
|
|
$origCashInDeskFloat = doubleval($result[0]["counted"]);
|
|
}
|
|
|
|
$sql = "SELECT ROUND(COALESCE(SUM(brutto),0.00),2) as sumbrutto FROM %bill% WHERE (status is null OR (status='x' OR status='s' OR status='c')) AND paymentid=? AND closingid is null";
|
|
$result = CommonUtils::fetchSqlAll($pdo, $sql, array(1));
|
|
$cashedNotInClosing = doubleval($result[0]["sumbrutto"]);
|
|
|
|
$cashInDeskFloat = $origCashInDeskFloat + $cashedNotInClosing;
|
|
|
|
$cashInDesk = number_format($cashInDeskFloat,2,$decpoint,'');
|
|
$cashedNotInClosing = number_format($cashedNotInClosing,2,$decpoint,'');
|
|
echo json_encode (array("status" => "OK","msg" => array("cashindesk" => $cashInDesk,"unclosedsalesincash" => $cashedNotInClosing)));
|
|
}
|
|
|
|
public function getClosingSummaryCore($closingid,$pdo,$fromWeb,$exportSignature,$replacedecpoint,$fl=0) {
|
|
if(is_null($pdo)) {
|
|
$pdo = DbUtils::openDbAndReturnPdoStatic();
|
|
};
|
|
|
|
$currency = CommonUtils::getConfigValue($pdo, 'currency', "Euro");
|
|
if ($replacedecpoint) {
|
|
$decpoint = CommonUtils::getConfigValue($pdo, 'decpoint', ".");
|
|
} else {
|
|
$decpoint = ".";
|
|
}
|
|
|
|
$masterData = self::getClosingMasterDataAtClsTime($pdo, $closingid);
|
|
|
|
$sql = "select id,closingdate,billcount,REPLACE(billsum,'.','$decpoint') as billsum,remark,signature,counting,REPLACE(counted,'.','$decpoint') as counted 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;
|
|
}
|
|
}
|
|
|
|
$barTotalBeforeTE = self::getBarTotalBeforeTE($pdo,$closingid,$decpoint);
|
|
$barTotalAfterTE = self::getBarTotalAfterTE($pdo,$closingid,$decpoint);
|
|
$diffSollIst = 0.0;
|
|
$counting = $closingpart->counting;
|
|
$counted = $closingpart->counted;
|
|
if ($counting == 1) {
|
|
$sql = "SELECT id,value,count,iscoin,IF(iscoin='1','Münzen','Banknoten') as coinsornotes,";
|
|
$sql .= "REPLACE(FORMAT((count*value*IF(iscoin='1',1,100))/100.0,2),'.','$decpoint') as sum,IF(iscoin='1',1,100) as factor ";
|
|
$sql .= "FROM %counting% WHERE clsid=? ORDER BY iscoin DESC,value";
|
|
$countingprotocol = CommonUtils::fetchSqlAll($pdo, $sql, array($closingid));
|
|
$diffSollIst = number_format($barTotalAfterTE - $counted,2,$decpoint,'');
|
|
} else {
|
|
$countingprotocol = array();
|
|
}
|
|
|
|
|
|
$statusOfPaymentSql = "CASE WHEN B.status='x' THEN 'VERK' WHEN B.status is null THEN 'VERK' WHEN B.status='s' THEN 'BSTR' WHEN B.status='c' THEN 'EINL' END";
|
|
|
|
$sql = "SELECT REPLACE(SUM(B.brutto),'.','$decpoint') as sum,REPLACE(round(sum(B.netto),2),'.','$decpoint') as netto,P.name,IF(B.status='x',null,B.status) as status, ";
|
|
$sql .= "($statusOfPaymentSql) as process ";
|
|
$sql .= " 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,IF(B.status='x',null,B.status) ";
|
|
$sql .= "HAVING SUM(B.brutto) is not null ";
|
|
$sql .= " UNION ALL ";
|
|
$sql .= "SELECT REPLACE(sum(B.brutto),'.','$decpoint') as sum,REPLACE(round(sum(B.netto),2),'.','$decpoint') as netto,'',B.status, ";
|
|
$sql .= "($statusOfPaymentSql) as process ";
|
|
$sql .= " FROM %bill% B WHERE ";
|
|
$sql .= "B.closingid=? AND B.status='s' ";
|
|
$sql .= "HAVING sum(B.brutto) is not null ";
|
|
$sql .= " UNION ALL ";
|
|
$sql .= "SELECT REPLACE(sum(Q.price),'.','$decpoint') as sum,REPLACE(TRUNCATE(sum(Q.price / (1 + Q.tax * 0.01)),2),'.','$decpoint') as netto,'','d' as status,'PSTR' as process 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 REPLACE(%queue%.tax,'.','$decpoint') as t,REPLACE(SUM(%queue%.price),'.','$decpoint') as bruttosum,REPLACE(ROUND(SUM(%queue%.price)/(1 + %queue%.tax/100.0),2),'.','$decpoint') 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 REPLACE(%queue%.tax,'.','$decpoint') as t,REPLACE(SUM(%queue%.price),'.','$decpoint') as bruttosum,REPLACE(ROUND(SUM(%queue%.price)/(1 + %queue%.tax/100.0),2),'.','$decpoint') 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,REPLACE(%queue%.price,'.','$decpoint') as price,REPLACE(%queue%.tax,'.','$decpoint') as tax,REPLACE(sum(%queue%.price),'.','$decpoint') 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);
|
|
}
|
|
|
|
$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,
|
|
"countingprotocol" => $countingprotocol,
|
|
"barTotalBeforeTE" => $barTotalBeforeTE,
|
|
"barTotalAfterTE" => $barTotalAfterTE,
|
|
"diffsollist" => $diffSollIst
|
|
);
|
|
|
|
$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);
|
|
$retVal["version"] = $masterData["version"];
|
|
$retVal["template"] = $masterData["template"];
|
|
$retVal["companyinfo"] = $masterData["companyinfo"];
|
|
|
|
$retVal["dsfinvk_name"] = $masterData["dsfinvk_name"];
|
|
$retVal["dsfinvk_street"] = $masterData["dsfinvk_street"];
|
|
$retVal["dsfinvk_postalcode"] = $masterData["dsfinvk_postalcode"];
|
|
$retVal["dsfinvk_city"] = $masterData["dsfinvk_city"];
|
|
$retVal["dsfinvk_country"] = $masterData["dsfinvk_country"];
|
|
$retVal["dsfinvk_stnr"] = $masterData["dsfinvk_stnr"];
|
|
$retVal["dsfinvk_ustid"] = $masterData["dsfinvk_ustid"];
|
|
|
|
$retVal["closingid"] = $closingid;
|
|
$retVal["billcount"] = $closingpart->billcount;
|
|
$retVal["billsum"] = str_replace('.',$decpoint,$closingpart->billsum) . " " . $currency;
|
|
$retVal["closingdate"] = $closingpart->closingdate;
|
|
$retVal["remark"] = $closingpart->remark;
|
|
$retVal["counting"] = $counting;
|
|
$retVal["counted"] = $counted;
|
|
|
|
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,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 = "<head><meta charset='UTF-8'></head>";
|
|
$html .= "<body><style>";
|
|
$html .= "</style>";
|
|
$html .= $txt;
|
|
$version = CommonUtils::getConfigValue($pdo, "version", "");
|
|
$html .= "<br><br><hr><div style='text-align:right;font-style:italic;'>OrderSprinter $version</div>";
|
|
$html .= "</body></html>";
|
|
|
|
echo $html;
|
|
}
|
|
|
|
public static function createdCountedValuesForClosing($pdo) {
|
|
$sql = "SELECT id from %closing% ORDER BY id";
|
|
$result = CommonUtils::fetchSqlAll($pdo, $sql);
|
|
foreach($result as $r) {
|
|
$clsid = $r['id'];
|
|
$sqlNoCounting = "SELECT COALESCE(SUM(B.brutto),'0.00') as sumbrutto FROM %bill% B,%closing% C WHERE B.paymentid='1' AND C.id<=? AND C.id=B.closingid AND B.intguestid is null";
|
|
$sumbruttores = CommonUtils::fetchSqlAll($pdo, $sqlNoCounting, array($clsid));
|
|
CommonUtils::execSql($pdo, "UPDATE %closing% SET counted=? WHERE id=?", array($sumbruttores[0]["sumbrutto"],$clsid));
|
|
}
|
|
}
|
|
|
|
private static function signValueByTseAndUpdateClosing($pdo,$closingid,$valueToSign) {
|
|
$status = TSE::sendFreeContentToTSE($pdo, $valueToSign);
|
|
if ($status["status"] != "OK") {
|
|
return(array("status" => "ERROR","msg" => "TSE-Signierung fehlgeschlagen. Vorgang konnte nicht ausgeführt werden."));
|
|
} else {
|
|
$logtime = 0;
|
|
$trans = 0;
|
|
$tseSignature = '';
|
|
$pubkeyRef = null;
|
|
$sigalgRef = null;
|
|
$sigcounter = 0;
|
|
|
|
if ($status["usetse"] == DbUtils::$TSE_OK) {
|
|
$msgAsString = $status["msg"];
|
|
$tseLog = json_decode($msgAsString, true);
|
|
$logtime = $tseLog["logtime"];
|
|
$trans = $tseLog["trans"];
|
|
$sigcounter = $tseLog["sigcounter"];
|
|
$tseSignature = $tseLog["signature"];
|
|
$publicKey = $tseLog["publickey"];
|
|
$tseCertificate = $tseLog["certificate"];
|
|
$serialNo = $tseLog["serialno"];
|
|
$sigalgRef = CommonUtils::referenceValueInTseValuesTable($pdo, $tseLog["sigalg"]);
|
|
$pubkeyRef = CommonUtils::referenceValueInTseValuesTable($pdo, $tseLog["publickey"]);
|
|
$serialNoRef = CommonUtils::referenceValueInTseValuesTable($pdo, $tseLog["serialno"]);
|
|
$certificateRef = CommonUtils::referenceValueInTseValuesTable($pdo, $tseLog["certificate"]);
|
|
}
|
|
|
|
$opid = Operations::createOperation(
|
|
$pdo,
|
|
DbUtils::$PROCESSTYPE_SONSTIGER_VORGANG,
|
|
DbUtils::$OPERATION_IN_CLOSING_TABLE,
|
|
$logtime,
|
|
$trans,
|
|
$valueToSign,
|
|
$tseSignature,
|
|
$pubkeyRef,
|
|
$sigalgRef,
|
|
$serialNoRef,
|
|
$certificateRef,
|
|
$sigcounter,
|
|
$status["usetse"]);
|
|
|
|
$sql = "UPDATE %closing% SET opid=? WHERE id=?";
|
|
CommonUtils::execSql($pdo, $sql, array($opid, $closingid));
|
|
|
|
return array("status" => "OK");
|
|
}
|
|
}
|
|
}
|