Initial xentral_oss_20.3.c9ffacf

This commit is contained in:
Alex
2021-05-21 08:49:41 +02:00
parent 5406e4a551
commit 34e5ac43d9
18884 changed files with 2109867 additions and 0 deletions
@@ -0,0 +1,74 @@
<?php
namespace Xentral\Modules\Api\Controller\Legacy;
use Xentral\Components\Http\Request;
use Xentral\Modules\Api\Exception\BadRequestException;
class DefaultController
{
/** @var Request $request */
protected $request;
/** @var \Api $legacyApi */
protected $legacyApi;
/** @var int $apiId */
protected $apiId;
/**
* @param \Api $legacyApi
* @param Request $request
* @param int $apiId
*/
public function __construct($legacyApi, $request, $apiId)
{
$this->request = $request;
$this->legacyApi = $legacyApi;
$this->apiId = $apiId;
}
public function postAction()
{
$action = $this->request->attributes->get('action');
$contentType = $this->request->getContentType();
$content = $this->request->getContent();
if ($contentType === 'xml') {
$this->legacyApi->app->Secure->POST['xml'] = '<xml>' . $content . '</xml>';
}
if ($contentType === 'json') {
$requestData = json_decode($content, true);
$contentPrepared = isset($requestData['data']) ? json_encode($requestData['data']) : $content;
$this->legacyApi->app->Secure->GET['json'] = true;
$this->legacyApi->app->Secure->POST['json'] = $contentPrepared;
}
// API-Methode aufrufen
$this->legacyApi->setApiId($this->apiId);
$this->legacyApi->app->Secure->GET['action'] = $action;
$apiMethod = 'Api' . $action;
$actionMapping = [
'AccountCreate' => 'ApiAdresseAccountCreate',
'AccountEdit' => 'ApiAdresseAccountEdit',
];
if (isset($actionMapping[$action])) {
$apiMethod = $actionMapping[$action];
}
$this->legacyApi->$apiMethod();
// API-Methode liefert normalerweise selbst das Ergebnis aus und beendet die Script-Ausführung.
// Falls aber eine nicht existierende API-Methode aufgerufen wird, läuft das Script in die Exception.
throw new BadRequestException();
}
public function readAction()
{
$this->legacyApi->setApiId($this->apiId);
$action = $this->request->attributes->get('action');
}
}
@@ -0,0 +1,42 @@
<?php
namespace Xentral\Modules\Api\Controller\Legacy;
use Xentral\Components\Http\Request;
use Xentral\Modules\Api\LegacyBridge\LegacyApplication;
class GobNavConnectController
{
/** @var Request $request */
protected $request;
/** @var LegacyApplication */
protected $app;
/**
* @param LegacyApplication $app
* @param Request $request
*/
public function __construct(LegacyApplication $app, Request $request)
{
$this->request = $request;
$this->app = $app;
}
public function exampleAction()
{
$post = $this->request->getContent();
$id = (int)$this->app->DB->Select(
"SELECT id FROM uebertragungen_account WHERE aktiv = 1 AND xml_pdf = 'TransferGobNav' LIMIT 1"
);
if ($id > 0) {
/** @var \Uebertragungen $transferObject */
$transferObject = $this->app->loadModule('uebertragungen');
if (!empty($transferObject)) {
/** @var \TransferGobNav $transferGobnav */
$transferGobnav = $transferObject->LoadTransferModul('TransferGobNav', $id);
$transferGobnav->ParseRequest($post);
}
}
exit;
}
}
@@ -0,0 +1,746 @@
<?php
namespace Xentral\Modules\Api\Controller\Legacy;
use DateInterval;
use DateTime;
use DateTimeInterface;
use Exception;
use Xentral\Components\Database\Database;
use Xentral\Components\Http\Request;
use Xentral\Modules\Api\Controller\Version1\AbstractController;
use Xentral\Modules\Api\Converter\Converter;
use Xentral\Modules\Api\Dashboard\WidgetData;
use Xentral\Modules\Api\Dashboard\WidgetResult;
use Xentral\Modules\Api\Exception\BadRequestException;
use Xentral\Modules\Api\Exception\InvalidArgumentException;
use Xentral\Modules\Api\LegacyBridge\LegacyApplication;
class MobileApiController extends AbstractController
{
/** @var LegacyApplication $app */
private $app;
/**
* @param LegacyApplication $app
* @param Converter $converter
* @param Database $database
* @param Request $request
*/
public function __construct(LegacyApplication $app, Converter $converter, Database $database, Request $request)
{
parent::__construct(null, $database, $converter, $request, null);
$this->app = $app;
}
/**
* controller for dashboard api call
*
* uses optional GET request parameter 'date'
*
* @throws Exception
*/
public function dashboardAction()
{
$today = new DateTime('now');
$interval = (int)$this->request->get->get('interval');
$mode = $this->request->get->get('mode');
if (!in_array($mode, ['month', 'week', 'year'])) {
$mode = 'day';
}
if ($interval <= 0) {
switch ($mode) {
case 'year':
$interval = 10;
break;
case 'month':
$interval = 12;
break;
case 'week':
default:
$interval = 14;
break;
}
}
$requestDate = $this->request->get->get('date');
if ($requestDate !== null && !$this->isDate($requestDate)) {
throw new BadRequestException('Bad request: parameter \'date\' expected format YYYY-mm-dd');
}
if ($this->isDate($requestDate)) {
$today = new DateTime($requestDate);
}
$yesterday = new DateTime($today->format('Y-m-d'));
$yesterday = $yesterday->sub(new DateInterval('P1D'));
$lastYear = new DateTime($today->format('Y'));
$lastYear = $lastYear->sub(new DateInterval('P1Y'));
$result = new WidgetResult([]);
//Dashboard mainpage
$result->addData($this->getOrdersCountWidget($today, $yesterday));
$result->addData($this->getTurnoverWidget($today, $yesterday));
$result->addData($this->getDispatchWidget($today, $yesterday));
$result->addData($this->getOrderValueWidget($today, $yesterday));
$result->addData($this->getTwoWeeksTurnoverWidget($today, $interval, $mode));
$result->addData($this->getNewCustomerWidget($today, $yesterday));
$result->addData($this->getOpenTicketsWidget());
//financial data page
$result->addData(
new WidgetData(
'turnover_current',
WidgetData::WIDGET_TYPE_CONTRAST_BIG,
'Umsatz aktueller Monat (netto)',
['current' => $this->getTurnoverThisMonth(), 'previous' => $this->getTurnoverLastMonth()],
'cashflow',
'€',
WidgetData::FORMAT_CURRENCY
)
);
$result->addData(
new WidgetData(
'turnover_lastmonth',
WidgetData::WIDGET_TYPE_CONTRAST_BIG,
'Umsatz letzter Monat (netto)',
['current' => $this->getTurnoverLastMonth(), 'previous' => $this->getTurnoverBeforeLastMonth()],
'cashflow',
'€',
WidgetData::FORMAT_CURRENCY
)
);
$result->addData(
new WidgetData(
'turnover_beforelastmonth',
WidgetData::WIDGET_TYPE_SIMPLE_BIG,
'Umsatz vorletzter Monat (netto)',
['value' => $this->getTurnoverBeforeLastMonth()],
'cashflow',
'€',
WidgetData::FORMAT_CURRENCY
)
);
$result->addData(
new WidgetData(
'liability_open',
WidgetData::WIDGET_TYPE_SIMPLE_BIG,
'Offene Verbindlichkeiten (brutto)',
['value' => $this->getOpenLiabilies()],
'cashflow',
'€',
WidgetData::FORMAT_CURRENCY
)
);
$result->addData(
new WidgetData(
'orders_open',
WidgetData::WIDGET_TYPE_SIMPLE_BIG,
'Offene Aufträge (netto)',
['value' => $this->getOpenOrders()],
'cashflow',
'€',
WidgetData::FORMAT_CURRENCY
)
);
$result->addData(
new WidgetData(
'dunning_current',
WidgetData::WIDGET_TYPE_SIMPLE_BIG,
'Mahnwesen (brutto)',
['value' => $this->getDunning()],
'cashflow',
'€',
WidgetData::FORMAT_CURRENCY
)
);
$result->addData(
new WidgetData(
'timetrack_current',
WidgetData::WIDGET_TYPE_SIMPLE_BIG,
'Zeit Gebucht',
['value' => $this->getTimeTracking()],
'customer',
'',
WidgetData::FORMAT_HOURS
)
);
$result->addData(
new WidgetData(
'subscription_nextmonth',
WidgetData::WIDGET_TYPE_SIMPLE_BIG,
'Abolauf nächsten Monat (brutto)',
['value' => $this->getSubscriptionRun()],
'cashflow',
'€',
WidgetData::FORMAT_CURRENCY
)
);
$result->addData(
new WidgetData(
'accounts_total_current',
WidgetData::WIDGET_TYPE_SIMPLE_BIG,
'Bankkonten Gesamt',
['value' => $this->getAccountsTotal()],
'cashflow',
'€',
WidgetData::FORMAT_CURRENCY
)
);
$result->addData(
new WidgetData(
'turnover_year_current',
WidgetData::WIDGET_TYPE_CONTRAST_BIG,
'Gesamtumsatz laufendes Jahr (netto)',
['current' => $this->getTurnoverByYear($today), 'previous' => $this->getTurnoverByYear($lastYear)],
'cashflow',
'€',
WidgetData::FORMAT_CURRENCY
)
);
return $this->sendResult($result);
}
/**
* returns chart data for number of orders
*
* @param DateTimeInterface $currentDay today
* @param DateTimeInterface $previousDay yesterday
*
* @return WidgetData chart data
*/
protected function getOrdersCountWidget(DateTimeInterface $currentDay, DateTimeInterface $previousDay)
{
$currentNumber = (int)$this->getOrdersCountByDay($currentDay);
$previousNumber = (int)$this->getOrdersCountByDay($previousDay);
$widget = new WidgetData(
'order_count',
WidgetData::WIDGET_TYPE_CONTRAST,
'Aufträge',
['current' => $currentNumber, 'previous' => $previousNumber],
'basket'
);
return $widget;
}
protected function getTurnoverWidget(DateTimeInterface $currentDay, DateTimeInterface $previousDay)
{
return new WidgetData(
'turnover_day',
WidgetData::WIDGET_TYPE_CONTRAST,
'Umsatz (heute)',
['current' => $this->getTurnoverByDay($currentDay), 'previous' => $this->getTurnoverByDay($previousDay)],
'euro',
'€',
WidgetData::FORMAT_CURRENCY
);
}
/**
* returns chart data for new customers
*
* @param DateTimeInterface $currentDay today
* @param DateTimeInterface $previousDay yesterday
*
* @return WidgetData chart data
*/
protected function getNewCustomerWidget(DateTimeInterface $currentDay, DateTimeInterface $previousDay)
{
$currentNumber = (int)$this->getNewCustomersByDay($currentDay);
$previousNumber = (int)$this->getNewCustomersByDay($previousDay);
$widget = new WidgetData(
'customer_new',
WidgetData::WIDGET_TYPE_CONTRAST,
'Neukunden',
['current' => $currentNumber, 'previous' => $previousNumber],
'customer'
);
return $widget;
}
protected function getOpenTicketsWidget()
{
return new WidgetData(
'tickets',
WidgetData::WIDGET_TYPE_SIMPLE,
'Offene Tickets',
['value' => $this->getOpenTicketCount()],
'ticket'
);
}
/**
* returns chart data for dispatched packages
*
* @param DateTimeInterface $currentDay today
* @param DateTimeInterface $previousDay yesterday
*
* @return WidgetData chart data
*/
protected function getDispatchWidget(DateTimeInterface $currentDay, DateTimeInterface $previousDay)
{
$currentNumber = (int)$this->getDispatchCountByDay($currentDay);
$previousNumber = (int)$this->getDispatchCountByDay($previousDay);
$widget = new WidgetData(
'dispatch_package',
WidgetData::WIDGET_TYPE_CONTRAST,
'Pakete',
['current' => $currentNumber, 'previous' => $previousNumber],
'packages'
);
return $widget;
}
protected function getOrderValueWidget(DateTimeInterface $today, DateTimeInterface $yesterday)
{
return new WidgetData(
'order_value',
WidgetData::WIDGET_TYPE_CONTRAST,
'Aufträge Heute',
['current' => $this->getOrderValueByDay($today), 'previous' => $this->getOrderValueByDay($yesterday)],
'euro',
'€',
WidgetData::FORMAT_CURRENCY
);
}
/**
* returns chart data for 14 days turnover
*
* @param DateTimeInterface $currentDay
* @param int $interval
* @param string $mode
*
* @throws Exception
* @return WidgetData chart data
*/
protected function getTwoWeeksTurnoverWidget(DateTimeInterface $currentDay, $interval = 0, $mode = 'day')
{
$dateString = $currentDay->format('Y-m-d');
switch ($mode) {
case 'year':
$modeName = 'Jahre';
if ($interval <= 0) {
$interval = 10;
}
$dayTo = new DateTime((new DateTime($dateString))->format('Y-12-31'));
$dayFrom = new DateTime((new DateTime($dateString))->format('Y-01-01'));
$dayFrom = $dayFrom->sub(new DateInterval(sprintf('P%dY', $interval - 1)));
break;
case 'month':
$modeName = 'Monate';
if ($interval <= 0) {
$interval = 12;
}
$dayTo = (new DateTime((new DateTime($dateString))
->format('Y-m-01')))
->add(new DateInterval('P1M'))
->sub(new DateInterval('P1D'));
$dayFrom = new DateTime((new DateTime($dateString))->format('Y-m-01'));
$dayFrom = $dayFrom->sub(new DateInterval(sprintf('P%dM', $interval - 1)));
break;
case 'week':
$modeName = 'Wochen';
if ($interval <= 0) {
$interval = 14;
}
$dayTo = new DateTime($dateString);
$weekDay = $dayTo->format('N');
if ($weekDay < 7) {
$dayTo->add(new DateInterval((sprintf('P%dD', 7 - $weekDay))));
}
$dayFrom = new DateTime($dayTo->format('Y-m-d'));
$dayFrom = $dayFrom->sub(new DateInterval(sprintf('P%dD', $interval * 7 - 1)));
break;
default:
$modeName = 'Tage';
if ($interval <= 0) {
$interval = 14;
}
$dayTo = new DateTime($dateString);
$dayFrom = new DateTime($dateString);
$dayFrom = $dayFrom->sub(new DateInterval(sprintf('P%dD', $interval - 1)));
break;
}
$data = $this->getTrunoverByDays($dayFrom, $dayTo, $mode);
$widget = new WidgetData(
'turnover_period',
WidgetData::WIDGET_TYPE_BARCHART,
sprintf('Umsatz (%d %s)', $interval, $modeName),
$data,
'euro',
'€',
WidgetData::FORMAT_CURRENCY
);
return $widget;
}
/**
* Returns number of orders created on specific date
*
* @param DateTimeInterface $date
*
* @return integer
*/
protected function getOrdersCountByDay(DateTimeInterface $date)
{
$dateFormatted = $date->format('Y-m-d');
if (!$this->isDate($dateFormatted)) {
throw new InvalidArgumentException('Invalid date format.');
}
$sql = 'SELECT COUNT(a.id) AS anzahl FROM auftrag AS a WHERE a.datum = :dateFormatted';
$values = ['dateFormatted' => $dateFormatted];
$result = $this->db->fetchRow($sql, $values);
return (int)$result['anzahl'];
}
/**
* Returns total revenue of specific day
*
* @param DateTimeInterface $date
*
* @return double
*/
protected function getOrderValueByDay(DateTimeInterface $date)
{
$dateFormatted = $date->format('Y-m-d');
$sql = "SELECT SUM(a.gesamtsumme) AS `ordervalue`
FROM auftrag AS a
WHERE a.datum = :dateFormatted AND a.status!='angelegt'";
$values = ['dateFormatted' => $dateFormatted];
$result = $this->db->fetchRow($sql, $values);
return (float)$result['ordervalue'];
}
/**
* Returns number of customers who placed their first order on specific date
*
* @param DateTimeInterface $date
*
* @return integer
*/
protected function getNewCustomersByDay(DateTimeInterface $date)
{
$dateFormatted = $date->format('Y-m-d');
if (!$this->isDate($dateFormatted)) {
throw new InvalidArgumentException('Invalid date format.');
}
$sql = "SELECT Count(DISTINCT adr.name) AS neukunden
FROM adresse AS adr JOIN auftrag AS auf
ON adr.id = auf.adresse
WHERE adr.id NOT IN
(SELECT DISTINCT a.id
FROM adresse AS a RIGHT JOIN auftrag AS au
ON a.id = au.adresse
WHERE au.status<>'angelegt' AND au.datum <> :dateFormatted AND au.id IS NOT NULL
);";
$values = ['dateFormatted' => $dateFormatted];
$result = $this->db->fetchRow($sql, $values);
return (int)$result['neukunden'];
}
/**
* Returns number of packeges dispatched on specific date
*
* @param DateTimeInterface $date
*
* @return integer
*/
protected function getDispatchCountByDay(DateTimeInterface $date)
{
$dateFormatted = $date->format('Y-m-d');
if (!$this->isDate($dateFormatted)) {
throw new InvalidArgumentException('Invalid date format.');
}
$sql = 'SELECT COUNT(v.id) AS anzahlpakete FROM versand AS v WHERE v.versendet_am = :dateFormatted';
$values = ['dateFormatted' => $dateFormatted];
$result = $this->db->fetchRow($sql, $values);
return (int)$result['anzahlpakete'];
}
protected function getOpenTicketCount()
{
return (float)$this->app->erp->AnzahlOffeneTickets(false);
}
/**
* Returns true if specific string represents a date.
*
* Accepted date format 'Y-m-d'
*
* @example isDate('2019-08-23') -> true
*
* @param string $dateString
*
* @return bool true=string represents a date
*/
protected function isDate($dateString)
{
$date = (string)$dateString;
if (preg_match('/^[1-9]\d{3}-\d{2}-\d{2}$/', $date)) {
return true;
}
return false;
}
/**
* @return float
*/
protected function getCashValues($key)
{
$obj = $this->app->loadModule('managementboard');
if (empty($obj)) {
return null;
}
$value = $obj->getCashValues($key);
return $value;
}
/**
* @param DateTimeInterface $dateFrom
* @param DateTimeInterface $dateTo
* @param string $mode
*
* @throws Exception
* @return array
*/
private function getTrunoverByDays(DateTimeInterface $dateFrom, DateTimeInterface $dateTo, $mode = 'day')
{
if ($dateFrom > $dateTo) {
throw new BadRequestException('Bad request: parameter \'dateFrom\' is later than parameter \'dateTo\'');
}
switch ($mode) {
case 'year':
$formatDb = '%Y';
$formatPhp = 'Y';
break;
case 'month':
$formatDb = '%m/%Y';
$formatPhp = 'm/Y';
break;
case 'week':
$formatDb = '%v/%x';
$formatPhp = 'W/o';
break;
default:
$formatDb = '%Y-%m-%d';
$formatPhp = 'Y-m-d';
break;
}
$dateFormattedFrom = $dateFrom->format('Y-m-d');
$dateFormattedTo = $dateTo->format('Y-m-d');
$values = [
'dateFormattedFrom' => $dateFormattedFrom,
'dateFormattedTo' => $dateFormattedTo,
];
$sqlInvoices = sprintf(
"SELECT DATE_FORMAT(r.datum,'%s') AS `date`, sum(r.umsatz_netto) AS `commitment`
FROM rechnung AS r
WHERE DATE_FORMAT(r.datum,'%%Y-%%m-%%d') >= :dateFormattedFrom
AND DATE_FORMAT(r.datum,'%%Y-%%m-%%d') <= :dateFormattedTo
AND r.status!='angelegt'
GROUP BY DATE_FORMAT(r.datum,'%s')",
$formatDb, $formatDb
);
$resultInvoices = $this->db->fetchPairs($sqlInvoices, $values);
$sqlReturnOrders = sprintf(
"SELECT DATE_FORMAT(g.datum,'%s') AS `date`, sum(g.umsatz_netto) AS `credit`
FROM gutschrift AS g
WHERE DATE_FORMAT(g.datum,'%%Y-%%m-%%d') >= :dateFormattedFrom
AND DATE_FORMAT(g.datum,'%%Y-%%m-%%d') <= :dateFormattedTo
AND g.status!='angelegt'
GROUP BY DATE_FORMAT(g.datum,'%s')",
$formatDb, $formatDb
);
$resultReturnOrders = $this->db->fetchPairs($sqlReturnOrders, $values);
$day = new DateTime($dateFormattedFrom);
$return = [];
while ($day <= $dateTo) {
$dayFormated = $day->format($formatPhp);
$return[$dayFormated] =
(empty($resultInvoices[$dayFormated]) ? 0.0 : $resultInvoices[$dayFormated])
- (empty($resultReturnOrders[$dayFormated]) ? 0.0 : $resultReturnOrders[$dayFormated]);
switch ($mode) {
case 'year':
$day = $day->add(new DateInterval('P1Y'));
break;
case 'month':
$day = $day->add(new DateInterval('P1M'));
break;
case 'week':
$day = $day->add(new DateInterval('P7D'));
break;
default:
$day = $day->add(new DateInterval('P1D'));
break;
}
}
return $return;
}
/**
* @param DateTimeInterface $date
*
* @return float
*/
private function getTurnoverByDay(DateTimeInterface $date)
{
$dateFormatted = $date->format('Y-m-d');
$values = ['dateFormatted' => $dateFormatted];
$sql = "SELECT sum(r.umsatz_netto) AS `commitment`
FROM rechnung AS r
WHERE DATE_FORMAT(r.datum,'%Y-%m-%d')=:dateFormatted AND r.status!='angelegt'";
$result = $this->db->fetchRow($sql, $values);
if (empty($result)) {
return 0.0;
}
$commitment = (float)$result['commitment'];
$sql = "SELECT sum(g.umsatz_netto) AS `credit`
FROM gutschrift AS g
WHERE DATE_FORMAT(g.datum,'%Y-%m-%d')=:dateFormatted AND g.status!='angelegt'";
$result = $this->db->fetchRow($sql, $values);
if (empty($result)) {
return 0.0;
}
$credit = (float)$result['credit'];
return $commitment - $credit;
}
/**
* @param DateTimeInterface $date
*
* @return float
*/
private function getTurnoverByYear(DateTimeInterface $date)
{
$dateFormatted = $date->format('Y');
$values = ['dateFormatted' => $dateFormatted];
$sql = "SELECT sum(r.umsatz_netto) AS `commitment`
FROM rechnung AS r
WHERE DATE_FORMAT(r.datum,'%Y')=:dateFormatted AND r.status!='angelegt'";
$result = $this->db->fetchRow($sql, $values);
if (empty($result)) {
return 0.0;
}
$commitment = (float)$result['commitment'];
$sql = "SELECT sum(g.umsatz_netto) AS `credit`
FROM gutschrift AS g
WHERE DATE_FORMAT(g.datum,'%Y')=:dateFormatted AND g.status!='angelegt'";
$result = $this->db->fetchRow($sql, $values);
if (empty($result)) {
return 0.0;
}
$credit = (float)$result['credit'];
return $commitment - $credit;
}
/**
* @return float
*/
private function getTurnoverThisMonth()
{
return (float)$this->getCashValues('13.1') - (float)$this->getCashValues('13.2');
}
/**
* @return float
*/
private function getTurnoverLastMonth()
{
return (float)$this->getCashValues('17.1') - (float)$this->getCashValues('17.2');
}
/**
* @return float
*/
private function getTurnoverBeforeLastMonth()
{
return (float)$this->getCashValues('21.1') - (float)$this->getCashValues('21.2');
}
/**
* @return float
*/
private function getOpenLiabilies()
{
return (float)$this->getCashValues(9);
}
/**
* @return float
*/
private function getOpenOrders()
{
return (float)$this->getCashValues(10);
}
/**
* @return float
*/
private function getDunning()
{
return (float)$this->getCashValues(11);
}
/**
* @return float
*/
private function getTimeTracking()
{
return (float)$this->app->DB->Select(
"SELECT sum(TIMESTAMPDIFF(HOUR,von,bis))
FROM zeiterfassung
WHERE DATE_FORMAT(von,'%m-%Y') = DATE_FORMAT(NOW(),'%m-%Y')"
);
}
/**
* @return float
*/
private function getSubscriptionRun()
{
$obj = $this->app->erp->LoadModul('rechnungslauf');
$value = 0.0;
if ($obj) {
$value = (float)$obj->RechnungslaufRechnungslauf(true);
}
return $value;
}
/**
* @return float
*/
private function getAccountsTotal()
{
return (float)$this->getCashValues(25);
}
}
@@ -0,0 +1,411 @@
<?php
namespace Xentral\Modules\Api\Controller\Legacy;
use TransferOpentrans;
use Xentral\Components\Http\Request;
use Xentral\Components\Http\Response;
use Xentral\Modules\Api\Converter\OpenTransConverter;
use Xentral\Modules\Api\Exception\ResourceNotFoundException;
use Xentral\Modules\Api\LegacyBridge\LegacyApplication;
class OpenTransConnectController
{
/** @var Request $request */
protected $request;
/** @var LegacyApplication $app */
protected $app;
/** @var int $accountId */
protected $accountId;
/**
* @param LegacyApplication $app
* @param Request $request
*/
public function __construct(LegacyApplication $app, OpenTransConverter $converter, Request $request, $accountId)
{
$this->request = $request;
$this->converter = $converter;
$this->app = $app;
$this->accountId = $accountId;
}
/**
* @return Response
*/
public function deleteOrder()
{
$orderId = $this->getDoctypeIdByRequestAttributes('order');
$transferOpenTrans = $this->getTransferObject();
list($result, $statusCode, $rootNode) = $transferOpenTrans->deleteOrder($orderId);
if(is_array($result)) {
$result = $this->converter->arrayToXml($result, $rootNode);
}
if(empty($result)) {
throw new ResourceNotFoundException('Auftrag konnte nicht gelöscht werden');
}
return $this->sendResponse($result,$statusCode);
}
/**
* @param string $doctype
*
* @return int
*/
protected function getDoctypeIdByRequestAttributes($doctype = 'deliverynote')
{
$id = (int)$this->request->attributes->get('id');
$orderId = $this->request->attributes->get('orderid');
$ordernumber = $orderId > 0?'':$this->request->attributes->get('ordernumber');
$extOrder = $orderId > 0 || !empty($ordernumber)?'':$this->request->attributes->get('extorder');
if($id > 0) {
return $id;
}
if(!empty($ordernumber)) {
$orderId = $this->app->DB->Select(
sprintf(
"SELECT id FROM auftrag WHERE belegnr = '%s' AND belegnr <> '' LIMIT 1",
$this->app->DB->real_escape_string($ordernumber)
)
);
if(empty($orderId)) {
throw new ResourceNotFoundException(sprintf('Auftrag mit Belegnr \'%s\' nicht gefunden', $ordernumber));
}
}
if(!empty($extOrder)) {
$orderId = $this->app->DB->Select(
sprintf(
"SELECT id FROM auftrag WHERE internet = '%s' AND internet <> '' LIMIT 1",
$this->app->DB->real_escape_string($extOrder)
)
);
if(empty($orderId)) {
throw new ResourceNotFoundException(sprintf('Auftrag mit Externer Belegnr \'%s\' nicht gefunden', $extOrder));
}
}
if(!empty($orderId)) {
switch($doctype) {
case 'order':
return $orderId;
break;
case 'invoice':
$id = $this->app->DB->Select(
sprintf(
"SELECT id FROM rechnung WHERE auftragid = %d ORDER BY status = 'storniert' LIMIT 1",
$orderId
)
);
if(!empty($id)) {
return $id;
}
throw new ResourceNotFoundException(
sprintf('Rechnung mit Order-ID \'%s\' nicht gefunden',
$orderId
)
);
break;
case 'deliverynote':
default:
$id = $this->app->DB->Select(
sprintf(
"SELECT id FROM lieferschein WHERE auftragid = %d ORDER BY status = 'storniert' LIMIT 1",
$orderId
)
);
if(!empty($id)) {
return $id;
}
throw new ResourceNotFoundException(
sprintf('Lieferschein mit Order-ID \'%s\' nicht gefunden',
$orderId
)
);
break;
}
}
return $id;
}
/**
* @return Response
*/
public function readDispatchnotification()
{
$deliveryNoteId = $this->getDoctypeIdByRequestAttributes('deliverynote');
$transferOpenTrans = $this->getTransferObject();
list($result, $statusCode, $rootNode) = $transferOpenTrans->getDispatchnotification($deliveryNoteId);
if(is_array($result)) {
$result = $this->converter->arrayToXml($result, $rootNode);
}
if(empty($result)) {
throw new ResourceNotFoundException(
sprintf('Lieferschein mit ID \'%s\' nicht gefunden',
$deliveryNoteId
)
);
}
return $this->sendResponse($result,$statusCode);
}
/**
* @param int $apiId
* @param string $request
* @param string $type
* @param bool $isIncoming
* @param string $doctype
* @param string $status
* @param int $doctypeId
*
* @return int
*/
protected function insertApiRequestLog(
$apiId, $request, $type, $isIncoming, $doctype, $status = '', $doctypeId = 0
)
{
$this->app->DB->Insert(
sprintf(
"INSERT INTO `api_request_response_log`
(api_id, raw_request, raw_response, type, status, doctype, doctype_id, is_incomming, created_at)
VALUES (%d, '%s', '%s', '%s', '%s','%s',%d,%d,NOW()) ",
$apiId,
($isIncoming?$this->app->DB->real_escape_string($request):''),
(!$isIncoming?$this->app->DB->real_escape_string($request):''),
$this->app->DB->real_escape_string($type),
$this->app->DB->real_escape_string($status),
$this->app->DB->real_escape_string($doctype),
$doctypeId,
$isIncoming
)
);
return (int)$this->app->DB->GetInsertID();
}
/**
* @param int $logId
* @param string $status
*/
protected function setLogStatus($logId, $status)
{
$this->app->DB->Update(
sprintf(
"UPDATE `api_request_response_log` SET `status` = '%s' WHERE `id` = %d",
$this->app->DB->real_escape_string($status),
$logId
)
);
}
/**
* @param int $logId
* @param int $doctypeId
*/
protected function setLogDoctypeId($logId, $doctypeId)
{
$this->app->DB->Update(
sprintf(
'UPDATE `api_request_response_log` SET `doctype_id` = %d WHERE `id` = %d',
$doctypeId,
$logId
)
);
}
/**
* @return Response
*/
public function createOrder()
{
$transferOpenTrans = $this->getTransferObject();
if(!empty($this->accountId)) {
$transferOpenTrans->setApiId($this->accountId);
}
$post = $this->request->getContent();
if(empty($post)) {
throw new ResourceNotFoundException('Data is empty');
}
$logId = $this->insertApiRequestLog($this->accountId, $post, 'create_order',true,'auftrag');
$xml = $this->converter->getXmlFromString($post);
if(empty($xml)) {
$this->setLogStatus($logId, 'error');
throw new ResourceNotFoundException('Data is no valid Xml');
}
list($result, $statusCode, $rootNode, $orderId) = $transferOpenTrans->createOrder($xml);
if(!empty($orderId)) {
$this->setLogDoctypeId($logId, $orderId);
}
if(is_array($result)) {
$result = $this->converter->arrayToXml($result, $rootNode);
}
if(empty($result)) {
$this->setLogStatus($logId, 'error');
throw new ResourceNotFoundException('Auftrag konnte nicht erstellt werden');
}
if($statusCode === Response::HTTP_CREATED) {
$this->setLogStatus($logId, 'ok');
}
else {
$this->setLogStatus($logId, 'error');
}
return $this->sendResponse($result,$statusCode);
}
/**
* @return Response
*/
public function updateDispatchnotification()
{
$deliveryNoteId = $this->getDoctypeIdByRequestAttributes('deliverynote');
$post = $this->request->getContent();
if(empty($post)) {
throw new ResourceNotFoundException('Data is empty');
}
$logId = $this->insertApiRequestLog(
$this->accountId, $post, 'update_dispatchnotification',true,'lieferschein','', $deliveryNoteId
);
$xml = $this->converter->getXmlFromString($post);
if(empty($xml)) {
$this->setLogStatus($logId, 'error');
throw new ResourceNotFoundException('Data is no valid Xml');
}
$transferOpenTrans = $this->getTransferObject();
list($result, $statusCode, $rootNode) = $transferOpenTrans->updateDispatchnotification($deliveryNoteId, $xml);
if(is_array($result)) {
$result = $this->converter->arrayToXml(
$result,
$rootNode
);
}
if($statusCode === Response::HTTP_OK) {
$this->setLogStatus($logId, 'ok');
}
return $this->sendResponse($result,$statusCode);
}
/**
* @return Response
*/
public function readInvoice()
{
$invoiceId = $this->getDoctypeIdByRequestAttributes('invoice');
$transferOpenTrans = $this->getTransferObject();
list($result, $statusCode, $rootNode) = $transferOpenTrans->getInvoice($invoiceId);
if(is_array($result)) {
$result = $this->converter->arrayToXml(
$result,
$rootNode
);
}
if(empty($result)) {
throw new ResourceNotFoundException(sprintf('Rechnung mit ID \'%s\' nicht gefunden', $invoiceId));
}
return $this->sendResponse($result,$statusCode);
}
/**
* @return Response
*/
public function readOrder()
{
$orderId = $this->getDoctypeIdByRequestAttributes('order');
$transferOpenTrans = $this->getTransferObject();
list($result,$statusCode, $rootNode) = $transferOpenTrans->getOrder($orderId);
if(is_array($result)) {
$result = $this->converter->arrayToXml
(
$result,
$rootNode
);
}
if(empty($result)) {
throw new ResourceNotFoundException(sprintf('Auftrag mit ID \'%s\' nicht gefunden', $orderId));
}
return $this->sendResponse($result,$statusCode);
}
public function updateOrder()
{
$orderId = $this->getDoctypeIdByRequestAttributes('order');
$transferOpenTrans = $this->getTransferObject();
$order = $transferOpenTrans->getOrderArr($orderId);
if(empty($order)) {
throw new ResourceNotFoundException(sprintf('Auftrag mit ID \'%s\' nicht gefunden', $orderId));
}
$post = $this->request->getContent();
$logId = $this->insertApiRequestLog(
$this->accountId, $post, 'update_order',true,'auftrag','', $orderId
);
$arr = $this->converter->toArray($post);
if(empty($arr)) {
$this->setLogStatus($logId, 'error');
throw new ResourceNotFoundException('XML konnte nicht geparsed werden');
}
}
/**
* @param string $data
* @param string $contentType [xml|json]
* @param int $statusCode HTTP-Statuscode
*
* @return Response
*/
protected function sendResponse($data, $contentType, $statusCode = Response::HTTP_OK)
{
return new Response(
$data,
$statusCode,
['Content-Type' => 'application/xml; charset=UTF-8']
);
}
/**
* @return TransferOpentrans
*/
private function getTransferObject()
{
$id = (int)$this->app->DB->Select(
"SELECT id FROM uebertragungen_account WHERE aktiv = 1 AND xml_pdf = 'TransferOpenTrans' AND id = %d LIMIT 1",
$this->accountId
);
if($id < 0) {
throw new ResourceNotFoundException('TransferOpenTrans Module not found');
}
/** @var \Uebertragungen $transferObject */
$transferObject = $this->app->loadModule('uebertragungen');
if(empty($transferObject)) {
throw new ResourceNotFoundException('TransferOpenTrans Module not found');
}
return $transferObject->LoadTransferModul('TransferOpentrans', $id);
}
}
@@ -0,0 +1,483 @@
<?php
namespace Xentral\Modules\Api\Controller\Legacy;
use Xentral\Components\Http\Request;
use Xentral\Components\Http\Response;
use Xentral\Modules\Api\Exception\ResourceNotFoundException;
use Xentral\Modules\Api\LegacyBridge\LegacyApplication;
class ShopimportController
{
/** @var Request $request */
protected $request;
/** @var LegacyApplication $app */
protected $app;
/** @var int $accountId */
protected $accountId;
/**
* @param LegacyApplication $app
* @param Request $request
*/
public function __construct(LegacyApplication $app, Request $request, $accountId)
{
$this->request = $request;
$this->app = $app;
$this->accountId = $accountId;
}
/**
* @param bool $onlyActive
*
* @return array
*/
private function getShopFromApi($onlyActive = true)
{
$shop = $this->app->DB->SelectRow(
sprintf(
'SELECT * FROM `shopexport` WHERE `api_account_id` = %d LIMIT 1',
$this->accountId
)
);
if (empty($shop)) {
throw new ResourceNotFoundException('Shop not found');
}
if($onlyActive && empty($shop['aktiv'])) {
throw new ResourceNotFoundException('Shop not connected');
}
return $shop;
}
/**
* @return Response
*/
public function auth()
{
$shop = $this->getShopFromApi();
$pageContents = $this->app->remote->RemoteConnection($shop['id'], true);
if (strpos($pageContents, 'success') !== 0) {
throw new ResourceNotFoundException('Auth Error ' . $pageContents);
}
/*$this->app->DB->Update(
sprintf(
"UPDATE `shopexport` SET `api_account_token` = '' WHERE `id` = %d",
$shop['id']
)
);*/
return $this->sendResponse(json_encode(['success' => true]), Response::HTTP_OK);
}
/**
* @return string
*/
public function getOrderByRequest()
{
$orderNumber = $this->request->attributes->get('ordernumber');
$orderNumber = base64_decode($orderNumber);
if (empty($orderNumber)) {
throw new ResourceNotFoundException(
'Ordernumber is empty'
);
}
return $orderNumber;
}
/**
* @param int $shopId
* @param bool $withDbCheck
*/
public function getArticleByRequest($shopId, $withDbCheck = true)
{
$articlenumber = $this->request->attributes->get('articlenumber');
$articlenumber = base64_decode($articlenumber);
if (empty($articlenumber)) {
throw new ResourceNotFoundException(
'Articlenumber is empty'
);
}
$article = $this->app->DB->SelectRow(
sprintf(
"SELECT art.id, art.projekt FROM `artikel` AS art
LEFT JOIN `artikelnummer_fremdnummern` AS af on art.id = af.artikel AND af.aktiv = 1 AND af.shopid = %d
WHERE (art.nummer = '%s' OR af.nummer = '%s') AND (art.geloescht = 0 OR art.geloescht IS NULL)
ORDER BY af.id DESC
LIMIT 1",
$shopId,
$this->app->DB->real_escape_string($articlenumber),
$this->app->DB->real_escape_string($articlenumber)
)
);
if (empty($article)) {
if($withDbCheck) {
throw new ResourceNotFoundException(
sprintf('Articlenumber %s not found', $articlenumber)
);
}
$article = [];
}
$article['number'] = $articlenumber;
return $article;
}
/**
* @return Response
*/
public function putArticleToShop()
{
$this->auth();
$shop = $this->getShopFromApi();
$article = $this->getArticleByRequest($shop['id']);
$ret = $this->app->remote->RemoteSendArticleList($shop['id'],[$article['id']], $article['number'], false);
if (empty($ret) || !is_array($ret) || isset($ret['error'])) {
return $this->sendResponse(
json_encode(['success' => false]),
Response::HTTP_BAD_REQUEST
);
}
return $this->sendResponse(json_encode(['success' => true]), Response::HTTP_OK);
}
/**
* @return Response
*/
public function getStatus()
{
$shop = $this->getShopFromApi(false);
$status = !empty($shop['aktiv']);
if($status) {
$this->auth();
}
return $this->sendResponse(json_encode(['success' => true, 'connected' => $status]), Response::HTTP_OK);
}
/**
* @return Response
*/
public function postDisconnect()
{
$shop = $this->getShopFromApi(false);
$status = !empty($shop['aktiv']);
if(!$status) {
return $this->sendResponse(
json_encode(
['success' => false,'error'=>'shop allready disconnected']
),
Response::HTTP_BAD_REQUEST
);
}
$this->app->DB->Update(sprintf("UPDATE `shopexport` SET `aktiv` = 0 WHERE `id` = %d", $shop['id']));
return $this->sendResponse(
json_encode(
['success' => true,'message'=>'shop disconnected']
),
Response::HTTP_OK
);
}
/**
* @return Response
*/
public function postReconnect()
{
$shop = $this->getShopFromApi(false);
$status = !empty($shop['aktiv']);
if($status) {
return $this->sendResponse(
json_encode(
['success' => false,'error'=>'shop allready connected']
),
Response::HTTP_BAD_REQUEST
);
}
$this->app->DB->Update(sprintf("UPDATE `shopexport` SET `aktiv` = 1 WHERE `id` = %d", $shop['id']));
return $this->sendResponse(
json_encode(
['success' => true,'message'=>'shop reconnected']
),
Response::HTTP_OK
);
}
/**
* @return Response
*/
public function putOrderToXentral()
{
$this->auth();
$shop = $this->getShopFromApi();
$orderNumber = $this->getOrderByRequest();
/** @var \Shopimport $shopimport */
$shopimport = $this->app->loadModule('shopimport');
$res = $shopimport->importSingleOrder(
$shop['id'], $orderNumber, empty($shop['demomodus']), $shop['projekt'], true
);
if(empty($res['status'])) {
return $this->sendResponse(
json_encode(
['success' => false,'error'=>$res['error']]
),
Response::HTTP_BAD_REQUEST
);
}
if($shop['auftraegeaufspaeter']) {
return $this->sendResponse(
json_encode(
[
'success' => true,
'message'=>$res['info'],
]
),
Response::HTTP_OK
);
}
$cart = $this->app->DB->SelectRow(
sprintf('SELECT * FROM `shopimport_auftraege` WHERE `id` = %d', $res['id'])
);
[$customerNumber, $customerNumberImported] = $shopimport->getCustomerNumberFromShopCart($cart);
$res = $shopimport->importShopOrder(
$res['id'], $shop['utf8codierung'],
$customerNumber, $customerNumberImported,
$unknownPaymentTypes
);
return $this->sendResponse(
json_encode(
[
'success' => true,
'message'=>$res['info'],
]
),
Response::HTTP_OK
);
}
/**
* @return Response
*/
public function putArticleToXentral()
{
$this->auth();
$shop = $this->getShopFromApi();
$article = $this->getArticleByRequest($shop['id'], false);
$ret = $this->app->remote->RemoteGetArticle($shop['id'], $article['number'], true);
if (empty($ret) || !is_array($ret) || isset($ret['error'])) {
return $this->sendResponse(
json_encode(['success' => false]),
Response::HTTP_BAD_REQUEST
);
}
if(empty($article['id'])) {
$article = $this->getArticleByRequest($shop['id'], false);
}
if(!empty($article['id'])) {
/** @var \Artikel $articleObj */
$articleObj = $this->app->loadModule('artikel');
$articleObj->updateShopArticle($article['id'], $ret);
}
return $this->sendResponse(json_encode(['success' => true]), Response::HTTP_OK);
}
/**
* @return Response
*/
public function syncStorage()
{
//$this->auth();
$shop = $this->getShopFromApi();
$article = $this->getArticleByRequest($shop['id']);
$ret = $this->app->remote->RemoteSendArticleList($shop['id'], [$article['id']],$article['number'], true);
if (empty($ret) || (!is_array($ret) && $ret !== 1) || isset($ret['error'])) {
return $this->sendResponse(
json_encode(['success' => false]),
Response::HTTP_BAD_REQUEST
);
}
return $this->sendResponse(json_encode(['success' => true]), Response::HTTP_OK);
}
/**
* @return Response
*/
public function getArticleSyncState()
{
$shop = $this->getShopFromApi();
$count = $this->app->DB->Select(
sprintf(
'SELECT COUNT(`ao`.`id`)
FROM `artikel_onlineshops` AS `ao`
INNER JOIN `artikel` AS `art` ON `ao`.artikel = `art`.`id` AND `art`.geloescht = 0
WHERE `ao`.shop = %d AND `ao`.`aktiv` = 1',
$shop['id']
)
);
return $this->sendResponse(json_encode(['success' => true, 'count' => $count]), Response::HTTP_OK);
}
public function postDistconnect()
{
//postReconnect
}
/**
* @return Response
*/
public function getModulelinks()
{
$shop = $this->getShopFromApi();
$shopId = $shop['id'];
/** @var \Onlineshops $onlineShop */
$onlineShop = $this->app->loadModule('onlineshops');
$moduleList = $onlineShop->getModulelinks($shopId);
return $this->sendResponse(
json_encode(
['success' => true, 'modulelist' => $moduleList]
),
Response::HTTP_OK
);
}
/**
* @return Response
*/
public function getStatistics()
{
$shop = $this->getShopFromApi();
$shopId = $shop['id'];
$stats = [];
/** @var \Verkaufszahlen $verkaufszahlen */
$verkaufszahlen = $this->app->loadModule('verkaufszahlen');
[$stats['orders_in_shipment'], $stats['orders_open']] = $verkaufszahlen->getVersandStats(
sprintf(' AND a.shop = %d ', $shopId)
);
$stats['packages_yesterday'] = $verkaufszahlen->getPackages(
" v.versendet_am=DATE_FORMAT(DATE_SUB(NOW(),INTERVAL 1 day),'%Y-%m-%d') '",
sprintf('INNER JOIN `auftrag` AS `a` ON l.auftragid = a.id AND a.shop = %d', $shopId)
);
$stats['packages_today'] = $verkaufszahlen->getPackages(
" v.versendet_am=DATE_FORMAT(NOW(),'%Y-%m-%d') '",
sprintf('INNER JOIN `auftrag` AS `a` ON l.auftragid = a.id AND a.shop = %d', $shopId)
);
[
$stats['order_income_yesterday'],
$stats['contribution_margin_yesterday'],
$stats['contribution_margin_perc_yesterday']
] =
$verkaufszahlen->getOrderStats(
sprintf(
" AND `datum` = DATE_FORMAT(DATE_SUB(NOW(),INTERVAL 1 day),'%%Y-%%m-%%d') AND `shop` = %d ",
$shopId
)
);
[
$stats['order_income_today'],
$stats['contribution_margin_today'],
$stats['contribution_margin_perc_today']
] =
$verkaufszahlen->getOrderStats(
sprintf(
" AND `datum` = DATE_FORMAT(NOW(),'%%Y-%%m-%%d') AND `shop` = %d ",
$shopId
)
);
return $this->sendResponse(json_encode(['success' => true, 'stats' => $stats]), Response::HTTP_OK);
}
/**
* @return Response
*/
public function postRefund()
{
$shop = $this->getShopFromApi();
$shopId = $shop['id'];
$post = $this->request->getContent();
if(empty($post)) {
throw new ResourceNotFoundException('Data is empty');
}
$contentType = $this->request->getContentType();
$data = null;
if ($contentType === 'json' || $contentType === null) {
$data = json_decode($post);
}
if ($data === null && ($contentType === 'xml' || $contentType === null)) {
$data = simplexml_load_string($post);
}
if(empty($post)) {
throw new ResourceNotFoundException('could not parse Data');
}
/** @var \Shopimport $shopimport */
$shopimport = $this->app->loadModule('shopimport');
if($shopimport === null || !method_exists($shopimport, 'Refund')) {
return $this->sendResponse(
json_encode(
[
'success' => false,
'error'=>'not implemented'
]
),
Response::HTTP_BAD_REQUEST
);
}
try {
$ret = $shopimport->Refund($shopId, $data);
}
catch(\Exception $e) {
return $this->sendResponse(
json_encode(
[
'success' => false,
'error' => $e->getMessage(),
]
),
Response::HTTP_BAD_REQUEST
);
}
return $this->sendResponse(json_encode(['success' => true,'creditnote_id' => $ret]), Response::HTTP_OK);
}
/**
* @param string $data
* @param string $contentType [xml|json]
* @param int $statusCode HTTP-Statuscode
*
* @return Response
*/
protected function sendResponse($data, $contentType, $statusCode = Response::HTTP_OK)
{
return new Response(
$data,
$statusCode,
['Content-Type' => 'application/json; charset=UTF-8']
);
}
}