increase speed

This commit is contained in:
Marko 2024-03-20 17:32:52 +01:00
parent 060b481319
commit df4d62bfdf
No known key found for this signature in database
15 changed files with 1907 additions and 777 deletions

3
.env
View File

@ -36,3 +36,6 @@ CORS_ALLOW_ORIGIN='^https?://(localhost|127\.0\.0\.1)(:[0-9]+)?$'
###> symfony/slack-notifier ### ###> symfony/slack-notifier ###
# SLACK_DSN=slack://TOKEN@default?channel=CHANNEL # SLACK_DSN=slack://TOKEN@default?channel=CHANNEL
###< symfony/slack-notifier ### ###< symfony/slack-notifier ###
###> sentry/sentry-symfony ###
SENTRY_DSN="https://0cf1306e7e61ee881cffc3ccfa6f3750@o4506943704727552.ingest.us.sentry.io/4506943709315072"
###< sentry/sentry-symfony ###

View File

@ -3,6 +3,7 @@
<component name="NewModuleRootManager"> <component name="NewModuleRootManager">
<content url="file://$MODULE_DIR$"> <content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" packagePrefix="App\" /> <sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" packagePrefix="App\" />
<sourceFolder url="file://$MODULE_DIR$/tests" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/tests" isTestSource="true" packagePrefix="App\Tests\" /> <sourceFolder url="file://$MODULE_DIR$/tests" isTestSource="true" packagePrefix="App\Tests\" />
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/serializer" /> <excludeFolder url="file://$MODULE_DIR$/vendor/symfony/serializer" />
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/form" /> <excludeFolder url="file://$MODULE_DIR$/vendor/symfony/form" />

View File

@ -14,7 +14,7 @@
<configured-by-url>true</configured-by-url> <configured-by-url>true</configured-by-url>
<remarks>DDEV generated data source</remarks> <remarks>DDEV generated data source</remarks>
<jdbc-driver>org.mariadb.jdbc.Driver</jdbc-driver> <jdbc-driver>org.mariadb.jdbc.Driver</jdbc-driver>
<jdbc-url>jdbc:mariadb://127.0.0.1:55009/db?user=db&amp;password=db</jdbc-url> <jdbc-url>jdbc:mariadb://127.0.0.1:32768/db?user=db&amp;password=db</jdbc-url>
<working-dir>$ProjectFileDir$</working-dir> <working-dir>$ProjectFileDir$</working-dir>
</data-source> </data-source>
</component> </component>

View File

@ -152,6 +152,20 @@
<path value="$PROJECT_DIR$/vendor/symfony/polyfill-intl-idn" /> <path value="$PROJECT_DIR$/vendor/symfony/polyfill-intl-idn" />
<path value="$PROJECT_DIR$/vendor/psr/http-message" /> <path value="$PROJECT_DIR$/vendor/psr/http-message" />
<path value="$PROJECT_DIR$/vendor/ralouphie/getallheaders" /> <path value="$PROJECT_DIR$/vendor/ralouphie/getallheaders" />
<path value="$PROJECT_DIR$/vendor/jean85/pretty-package-versions" />
<path value="$PROJECT_DIR$/vendor/php-http/message" />
<path value="$PROJECT_DIR$/vendor/php-http/discovery" />
<path value="$PROJECT_DIR$/vendor/php-http/client-common" />
<path value="$PROJECT_DIR$/vendor/symfony/psr-http-message-bridge" />
<path value="$PROJECT_DIR$/vendor/php-http/promise" />
<path value="$PROJECT_DIR$/vendor/php-http/message-factory" />
<path value="$PROJECT_DIR$/vendor/php-http/httplug" />
<path value="$PROJECT_DIR$/vendor/clue/stream-filter" />
<path value="$PROJECT_DIR$/vendor/sentry/sentry" />
<path value="$PROJECT_DIR$/vendor/sentry/sentry-symfony" />
<path value="$PROJECT_DIR$/vendor/psr/http-client" />
<path value="$PROJECT_DIR$/vendor/psr/http-factory" />
<path value="$PROJECT_DIR$/vendor/http-interop/http-factory-guzzle" />
</include_path> </include_path>
</component> </component>
<component name="PhpInterpreters"> <component name="PhpInterpreters">
@ -262,7 +276,16 @@
</interpreter> </interpreter>
</phpInfoCache> </phpInfoCache>
</component> </component>
<component name="PhpProjectSharedConfiguration" php_language_level="8.1" /> <component name="PhpProjectServersManager">
<servers>
<server host="cdsconnector.ddev.site" id="05df7051-cd1e-44c5-9383-2d86219fa880" name="cdsconnector.ddev.site" use_path_mappings="true">
<path_mappings>
<mapping local-root="$PROJECT_DIR$" remote-root="/var/www/html" />
</path_mappings>
</server>
</servers>
</component>
<component name="PhpProjectSharedConfiguration" php_language_level="8.2" />
<component name="PhpStanOptionsConfiguration"> <component name="PhpStanOptionsConfiguration">
<option name="transferred" value="true" /> <option name="transferred" value="true" />
</component> </component>

View File

@ -4,7 +4,7 @@
"minimum-stability": "stable", "minimum-stability": "stable",
"prefer-stable": true, "prefer-stable": true,
"require": { "require": {
"php": ">=8.1", "php": ">=8.2",
"ext-ctype": "*", "ext-ctype": "*",
"ext-curl": "*", "ext-curl": "*",
"ext-ftp": "*", "ext-ftp": "*",
@ -19,6 +19,7 @@
"nelmio/cors-bundle": "^2.2", "nelmio/cors-bundle": "^2.2",
"phpdocumentor/reflection-docblock": "^5.3", "phpdocumentor/reflection-docblock": "^5.3",
"phpstan/phpdoc-parser": "^1.6", "phpstan/phpdoc-parser": "^1.6",
"sentry/sentry-symfony": "^4.14",
"symfony/apache-pack": "^1.0", "symfony/apache-pack": "^1.0",
"symfony/asset": "6.3.*", "symfony/asset": "6.3.*",
"symfony/console": "6.3.*", "symfony/console": "6.3.*",

2093
composer.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -12,4 +12,5 @@ return [
Symfony\Bundle\SecurityBundle\SecurityBundle::class => ['all' => true], Symfony\Bundle\SecurityBundle\SecurityBundle::class => ['all' => true],
Nelmio\CorsBundle\NelmioCorsBundle::class => ['all' => true], Nelmio\CorsBundle\NelmioCorsBundle::class => ['all' => true],
ApiPlatform\Symfony\Bundle\ApiPlatformBundle::class => ['all' => true], ApiPlatform\Symfony\Bundle\ApiPlatformBundle::class => ['all' => true],
Sentry\SentryBundle\SentryBundle::class => ['prod' => true],
]; ];

View File

@ -0,0 +1,10 @@
services:
Psr\Http\Message\RequestFactoryInterface: '@http_discovery.psr17_factory'
Psr\Http\Message\ResponseFactoryInterface: '@http_discovery.psr17_factory'
Psr\Http\Message\ServerRequestFactoryInterface: '@http_discovery.psr17_factory'
Psr\Http\Message\StreamFactoryInterface: '@http_discovery.psr17_factory'
Psr\Http\Message\UploadedFileFactoryInterface: '@http_discovery.psr17_factory'
Psr\Http\Message\UriFactoryInterface: '@http_discovery.psr17_factory'
http_discovery.psr17_factory:
class: Http\Discovery\Psr17Factory

View File

@ -0,0 +1,26 @@
when@prod:
sentry:
dsn: '%env(SENTRY_DSN)%'
# this hooks into critical paths of the framework (and vendors) to perform
# automatic instrumentation (there might be some performance penalty)
# https://docs.sentry.io/platforms/php/guides/symfony/performance/instrumentation/automatic-instrumentation/
tracing:
enabled: false
# If you are using Monolog, you also need this additional configuration to log the errors correctly:
# https://docs.sentry.io/platforms/php/guides/symfony/#monolog-integration
register_error_listener: false
register_error_handler: false
monolog:
handlers:
sentry:
type: sentry
level: !php/const Monolog\Logger::ERROR
hub_id: Sentry\State\HubInterface
# Uncomment these lines to register a log message processor that resolves PSR-3 placeholders
# https://docs.sentry.io/platforms/php/guides/symfony/#monolog-integration
services:
Monolog\Processor\PsrLogMessageProcessor:
tags: { name: monolog.processor, handler: sentry }

View File

@ -8,6 +8,8 @@ use App\Repository\ProductRepository;
use App\Repository\StockRepository; use App\Repository\StockRepository;
use App\Repository\WarehouseRepository; use App\Repository\WarehouseRepository;
use Psr\Log\LoggerInterface; use Psr\Log\LoggerInterface;
use Sentry\CheckIn;
use Sentry\CheckInStatus;
use Symfony\Component\Console\Attribute\AsCommand; use Symfony\Component\Console\Attribute\AsCommand;
use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputInterface;
@ -15,6 +17,7 @@ use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Style\SymfonyStyle; use Symfony\Component\Console\Style\SymfonyStyle;
use Symfony\Component\HttpKernel\KernelInterface; use Symfony\Component\HttpKernel\KernelInterface;
use function Sentry\captureCheckIn;
#[AsCommand( #[AsCommand(
name: 'hiltes:import', name: 'hiltes:import',
@ -49,6 +52,18 @@ class HiltesImportCommand extends Command
protected function execute(InputInterface $input, OutputInterface $output): int protected function execute(InputInterface $input, OutputInterface $output): int
{ {
$time_start = microtime(true); $time_start = microtime(true);
// 🟡 Notify Sentry your job is running:
$checkInId = captureCheckIn(
slug: 'bestandsabgleich-delta',
status: CheckInStatus::inProgress()
);
$this->logger->error('Start Hiltes Import');
dump($checkInId);
$io = new SymfonyStyle($input, $output); $io = new SymfonyStyle($input, $output);
$io->success('Start Hiltes Import'); $io->success('Start Hiltes Import');
@ -65,6 +80,14 @@ class HiltesImportCommand extends Command
if (isset($r['error'])) { if (isset($r['error'])) {
$io->error($r['text']); $io->error($r['text']);
$this->logger->error($r['text']); $this->logger->error($r['text']);
// 🔴 Notify Sentry your job has failed:
captureCheckIn(
slug: 'bestandsabgleich-delta',
status: CheckInStatus::error(),
checkInId: $checkInId,
);
return Command::FAILURE; return Command::FAILURE;
} else { } else {
$io->info('Start Hiltes Push JTL'); $io->info('Start Hiltes Push JTL');
@ -81,6 +104,14 @@ class HiltesImportCommand extends Command
$execution_time = ($time_end - $time_start) / 60; $execution_time = ($time_end - $time_start) / 60;
// 🟢 Notify Sentry your job has completed successfully:
captureCheckIn(
slug: 'bestandsabgleich-delta',
status: CheckInStatus::ok(),
duration: $execution_time,
checkInId: $checkInId
);
$io->success('Done.' . PHP_EOL . 'Execution time: ' . $execution_time . ' minutes'); $io->success('Done.' . PHP_EOL . 'Execution time: ' . $execution_time . ' minutes');
return Command::SUCCESS; return Command::SUCCESS;
} }

View File

@ -30,7 +30,6 @@ class Order
#[ORM\Column(length: 255, unique: true)] #[ORM\Column(length: 255, unique: true)]
#[ApiProperty(identifier: true)] #[ApiProperty(identifier: true)]
private ?string $orderId = null; private ?string $orderId = null;
#[ORM\Column] #[ORM\Column]
@ -42,12 +41,6 @@ class Order
#[ORM\Column(name: 'change_date', type: Types::DATETIME_MUTABLE, nullable: true, options: ['default' => 'CURRENT_TIMESTAMP'])] #[ORM\Column(name: 'change_date', type: Types::DATETIME_MUTABLE, nullable: true, options: ['default' => 'CURRENT_TIMESTAMP'])]
private ?DateTimeInterface $changeDate = null; private ?DateTimeInterface $changeDate = null;
#[ORM\Column(length: 255, nullable: true)]
private ?string $han = null;
#[ORM\Column(length: 255, nullable: true)]
private ?string $marke = null;
public function getId(): ?int public function getId(): ?int
{ {
return $this->id; return $this->id;
@ -100,28 +93,4 @@ class Order
return $this; return $this;
} }
public function getHan(): ?string
{
return $this->han;
}
public function setHan(?string $han): static
{
$this->han = $han;
return $this;
}
public function getMarke(): ?string
{
return $this->marke;
}
public function setMarke(?string $marke): static
{
$this->marke = $marke;
return $this;
}
} }

View File

@ -7,7 +7,9 @@ use App\Entity\Order;
use App\Repository\ProductRepository; use App\Repository\ProductRepository;
use App\Repository\StockRepository; use App\Repository\StockRepository;
use App\Repository\WarehouseRepository; use App\Repository\WarehouseRepository;
use Maknz\Slack\Client; use Maknz\Slack\Client;
use Psr\Log\LoggerInterface;
use Symfony\Component\EventDispatcher\EventSubscriberInterface; use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\Event\ViewEvent; use Symfony\Component\HttpKernel\Event\ViewEvent;
@ -24,12 +26,14 @@ class SlackNotifySubscriber implements EventSubscriberInterface
private $stockRepository; private $stockRepository;
private $warehouseRepository; private $warehouseRepository;
public function __construct(string $slackWebhookUrl, ProductRepository $productRepository, StockRepository $stockRepository, WarehouseRepository $warehouseRepository) public function __construct(string $slackWebhookUrl, ProductRepository $productRepository, StockRepository $stockRepository, WarehouseRepository $warehouseRepository)
{ {
$this->slackWebhookUrl = $slackWebhookUrl; $this->slackWebhookUrl = $slackWebhookUrl;
$this->productRepository = $productRepository; $this->productRepository = $productRepository;
$this->stockRepository = $stockRepository; $this->stockRepository = $stockRepository;
$this->warehouseRepository = $warehouseRepository; $this->warehouseRepository = $warehouseRepository;
} }
public static function getSubscribedEvents(): array public static function getSubscribedEvents(): array
@ -54,11 +58,18 @@ class SlackNotifySubscriber implements EventSubscriberInterface
if (!$order instanceof Order || Request::METHOD_POST !== $method) { if (!$order instanceof Order || Request::METHOD_POST !== $method) {
return; return;
} }
if ($order->getStatus() == 1) {
foreach ($order->getData()[0]['positions'] as $item) { foreach ($order->getData()[0]['positions'] as $item) {
if ($item['menge'] > 0) { if ($item['menge'] > 0) {
$warehouse = $this->getWarehouseByGtin($item['gtin']); $warehouses = $this->getWarehouseByGtin($item['gtin']);
if ($warehouses == false) {
continue;
}
foreach ($warehouses as $warehouse) {
$slack = new Client($this->slackWebhookUrl, [ $slack = new Client($this->slackWebhookUrl, [
'username' => 'CDS-Notify', 'username' => 'CDS-Notify',
@ -74,8 +85,10 @@ class SlackNotifySubscriber implements EventSubscriberInterface
$msg .= ' - ' . $item['han']; $msg .= ' - ' . $item['han'];
$msg .= ' * - ' . $item['menge'] . "* \n"; $msg .= ' * - ' . $item['menge'] . "* \n";
if ($order->getStatus() == 1) {
$slack->from('CDS-Notify')->send($msg); $slack->from('CDS-Notify')->send($msg);
}
} }
} }
} }
@ -83,26 +96,34 @@ class SlackNotifySubscriber implements EventSubscriberInterface
/** /**
* @param string $gtin * @param string $gtin
* @return string|null * @return array
*/ */
private function getWarehouseByGtin(string $gtin) private function getWarehouseByGtin(string $gtin)
{ {
if ($gtin == null) { if ($gtin == null) {
return false; return false;
} }
$warehouse = [];
$product = $this->productRepository->findOneBy(['gtin' => $gtin]); $product = $this->productRepository->findOneBy(['gtin' => $gtin]);
if ($product) { if ($product) {
$stock = $this->stockRepository->findOneBy(['product_id' => $product->getId()]); $stock = $this->stockRepository->findBy(['product_id' => $product->getId()]);
if ($stock) { if ($stock) {
$warehouse = $this->warehouseRepository->findOneBy(['id' => $stock->getWarehouse()->getId()]); $prio = 0;
return $warehouse->getName(); foreach ($stock as $item) {
$w = $this->warehouseRepository->findOneBy(['id' => $item->getWarehouse()->getId()]);
if ($w->getPrio() > $prio) {
$warehouse[] = $w->getName();
$prio = $w->getPrio();
}
}
} }
} }
return null; return $warehouse;
} }
} }

View File

@ -4,6 +4,7 @@ namespace App\Helper;
use App\Entity\Order; use App\Entity\Order;
use App\Repository\OrderRepository; use App\Repository\OrderRepository;
use Psr\Log\LoggerInterface;
use Symfony\Component\Filesystem\Exception\IOExceptionInterface; use Symfony\Component\Filesystem\Exception\IOExceptionInterface;
use Symfony\Component\Filesystem\Filesystem; use Symfony\Component\Filesystem\Filesystem;
use Symfony\Component\Finder\Finder; use Symfony\Component\Finder\Finder;
@ -21,7 +22,7 @@ class Hiltes
protected $hiltesApiUrl; protected $hiltesApiUrl;
public function __construct(private OrderRepository $orderRepository) public function __construct(private OrderRepository $orderRepository, private LoggerInterface $logger)
{ {
$this->fsObject = new Filesystem(); $this->fsObject = new Filesystem();
$this->current_dir_path = getcwd(); $this->current_dir_path = getcwd();
@ -31,19 +32,6 @@ class Hiltes
$this->hiltesPass = $_ENV['HILTES_API_PASS']; $this->hiltesPass = $_ENV['HILTES_API_PASS'];
} }
// public function import()
// {
//
// $finder = new Finder();
// $finder->files()->in($this->current_dir_path . "/hiltes/h2c/");
//
// foreach ($finder as $file) {
// $contents = $file->getContents();
//
// //var_dump($contents);
// }
//
// }
/** /**
* @param string $data * @param string $data
@ -100,7 +88,12 @@ class Hiltes
#dump($tA); #dump($tA);
#*** Umkonvertieren des Datumstings ***************** #*** Umkonvertieren des Datumstings *****************
$tA['orderdate'] = gmdate('Y-m-d\TH:i:s.v\Z', $tA['orderdate'] ? strtotime($tA['orderdate']) : time()); if (!empty($tA['salesdate'])) {
$tA['orderdate'] = gmdate('Y-m-d\TH:i:s.v\Z', $tA['salesdate'] ? strtotime($tA['salesdate']) : time());
} else {
$tA['orderdate'] = gmdate('Y-m-d\TH:i:s.v\Z', time());
}
#**** #****
$arr = array( $arr = array(
'SalesDate' => $tA['orderdate'], 'SalesDate' => $tA['orderdate'],
@ -112,9 +105,6 @@ class Hiltes
); );
#*** Items *************** #*** Items ***************
if (!empty($tA['positions']) && is_array($tA['positions'])) { if (!empty($tA['positions']) && is_array($tA['positions'])) {
# Noch nötig
# "CalculatedSellingPrice" => 0, #X Kalkulierter Verkaufspreis
# "AchievedSalesPrice" => 0, #X Erzielter Verkaufspreis
$tSalNr = array(); $tSalNr = array();
foreach ($tA['positions'] as $v) { foreach ($tA['positions'] as $v) {
if ($v['type'] == 'versandposition' || $v['sku'] == '') { if ($v['type'] == 'versandposition' || $v['sku'] == '') {
@ -163,7 +153,7 @@ class Hiltes
} }
} }
#*** Kundne ******************************* #*** Kunde *******************************
$arr['CustomerList'][] = array( $arr['CustomerList'][] = array(
"CustomerNumber" => $tA['kundenummer'], # Fake Daten "CustomerNumber" => $tA['kundenummer'], # Fake Daten
"Surname" => $tA['name'],#"string", "Surname" => $tA['name'],#"string",
@ -232,13 +222,19 @@ class Hiltes
); );
$r = $this->sendToHiltes($url, $param); $r = $this->sendToHiltes($url, $param);
dump($r);
if ($r === false) {
$this->logger->error('Login Error ' . $r . __LINE__);
return false;
}
$t = json_decode($r, true); $t = json_decode($r, true);
if ($t['Success']) { if ($t['Success']) {
$this->hiltesApiHash = $t['Data']; $this->hiltesApiHash = $t['Data'];
return true; return true;
} else { } else {
dump($r); $this->logger->error('Login Error ' . __LINE__);
dump('Login Error ' . __LINE__);
return false; return false;
} }
} }
@ -378,6 +374,13 @@ class Hiltes
//dump($param); //dump($param);
$r = $this->sendToHiltes($url, $param, true); $r = $this->sendToHiltes($url, $param, true);
dump($r);
if ($r === false) {
dump('Send Order Error ' . __LINE__);
return false;
}
$t = json_decode($r, true); $t = json_decode($r, true);
if ($t['Success']) { if ($t['Success']) {
return true; return true;

View File

@ -61,6 +61,18 @@
"config/packages/nelmio_cors.yaml" "config/packages/nelmio_cors.yaml"
] ]
}, },
"php-http/discovery": {
"version": "1.19",
"recipe": {
"repo": "github.com/symfony/recipes",
"branch": "main",
"version": "1.18",
"ref": "f45b5dd173a27873ab19f5e3180b2f661c21de02"
},
"files": [
"config/packages/http_discovery.yaml"
]
},
"phpunit/phpunit": { "phpunit/phpunit": {
"version": "9.6", "version": "9.6",
"recipe": { "recipe": {
@ -75,6 +87,18 @@
"tests/bootstrap.php" "tests/bootstrap.php"
] ]
}, },
"sentry/sentry-symfony": {
"version": "4.14",
"recipe": {
"repo": "github.com/symfony/recipes-contrib",
"branch": "main",
"version": "4.6",
"ref": "153de5f041f7e8a9c19f3674b800b76be0e6fd90"
},
"files": [
"config/packages/sentry.yaml"
]
},
"symfony/apache-pack": { "symfony/apache-pack": {
"version": "1.0", "version": "1.0",
"recipe": { "recipe": {