update
This commit is contained in:
102
cron.php
102
cron.php
@@ -1,5 +1,5 @@
|
||||
<?php
|
||||
error_reporting( E_ALL ^ E_NOTICE ^ E_STRICT ^ E_WARNING ^ E_DEPRECATED );
|
||||
error_reporting( E_ALL ^ E_NOTICE ^ E_STRICT );
|
||||
|
||||
function __autoload_my_classes( $classname )
|
||||
{
|
||||
@@ -131,6 +131,7 @@ function getImageUrlById($id) {
|
||||
|
||||
$settings = ( new \Domain\Settings\SettingsRepository( $mdb ) )->allSettings();
|
||||
$integrationsRepository = new \Domain\Integrations\IntegrationsRepository( $mdb );
|
||||
$apiloRepository = new \Domain\Integrations\ApiloRepository( $mdb );
|
||||
$orderRepo = new \Domain\Order\OrderRepository( $mdb );
|
||||
$cronRepo = new \Domain\CronJob\CronJobRepository( $mdb );
|
||||
$orderAdminService = new \Domain\Order\OrderAdminService( $orderRepo, null, null, null, $cronRepo );
|
||||
@@ -184,21 +185,28 @@ if ( file_exists( $json_queue_path ) )
|
||||
// =========================================================================
|
||||
|
||||
// 1. Apilo token keepalive (priorytet: krytyczny)
|
||||
$processor->registerHandler( \Domain\CronJob\CronJobType::APILO_TOKEN_KEEPALIVE, function($payload) use ($integrationsRepository) {
|
||||
$processor->registerHandler( \Domain\CronJob\CronJobType::APILO_TOKEN_KEEPALIVE, function($payload) use ($integrationsRepository, $apiloRepository) {
|
||||
$apilo_settings = $integrationsRepository->getSettings('apilo');
|
||||
if ( !(int)($apilo_settings['enabled'] ?? 0) ) return true; // skip if disabled
|
||||
|
||||
$integrationsRepository->apiloKeepalive( 300 );
|
||||
$apiloRepository->apiloKeepalive( 300 );
|
||||
echo '<p>Apilo token keepalive</p>';
|
||||
return true;
|
||||
});
|
||||
|
||||
// 2. Apilo send order (priorytet: wysoki)
|
||||
$processor->registerHandler( \Domain\CronJob\CronJobType::APILO_SEND_ORDER, function($payload) use ($mdb, $integrationsRepository, $orderAdminService, $config) {
|
||||
$processor->registerHandler( \Domain\CronJob\CronJobType::APILO_SEND_ORDER, function($payload) use ($mdb, $integrationsRepository, $apiloRepository, $orderAdminService, $config) {
|
||||
$apilo_settings = $integrationsRepository->getSettings('apilo');
|
||||
if ( !$apilo_settings['enabled'] || !$apilo_settings['sync_orders'] || !$apilo_settings['access-token'] || $apilo_settings['sync_orders_date_start'] > date('Y-m-d H:i:s') ) return true;
|
||||
|
||||
$orders = $mdb->select( 'pp_shop_orders', '*', [ 'AND' => [ 'apilo_order_id' => null, 'date_order[>=]' => $apilo_settings['sync_orders_date_start'] ], 'ORDER' => [ 'date_order' => 'ASC' ], 'LIMIT' => 1 ] );
|
||||
|
||||
// Jeśli brak nowych, ponów failed (-1) z interwałem 1h
|
||||
if ( empty($orders) ) {
|
||||
$retryAfter = date( 'Y-m-d H:i:s', strtotime( '-1 hour' ) );
|
||||
$orders = $mdb->select( 'pp_shop_orders', '*', [ 'AND' => [ 'apilo_order_id' => -1, 'apilo_order_status_date[<=]' => $retryAfter, 'date_order[>=]' => $apilo_settings['sync_orders_date_start'] ], 'ORDER' => [ 'date_order' => 'ASC' ], 'LIMIT' => 1 ] );
|
||||
}
|
||||
|
||||
if ( empty($orders) ) return true;
|
||||
|
||||
foreach ( $orders as $order )
|
||||
@@ -276,7 +284,7 @@ $processor->registerHandler( \Domain\CronJob\CronJobType::APILO_SEND_ORDER, func
|
||||
continue;
|
||||
}
|
||||
|
||||
$access_token = $integrationsRepository->apiloGetAccessToken();
|
||||
$access_token = $apiloRepository->apiloGetAccessToken();
|
||||
$order_date = new DateTime( $order['date_order'] );
|
||||
$paczkomatData = parsePaczkomatAddress( $order['inpost_paczkomat'] );
|
||||
$orlenPointData = parseOrlenAddress( $order['orlen_point'] );
|
||||
@@ -423,6 +431,7 @@ $processor->registerHandler( \Domain\CronJob\CronJobType::APILO_SEND_ORDER, func
|
||||
if (curl_errno( $ch ) ) {
|
||||
$curl_error_send = curl_error( $ch );
|
||||
\Domain\Integrations\ApiloLogger::log( $mdb, 'send_order', (int)$order['id'], 'Błąd cURL przy wysyłaniu zamówienia: ' . $curl_error_send, [ 'curl_error' => $curl_error_send ] );
|
||||
\Shared\Helpers\Helpers::send_email( 'biuro@project-pro.pl', 'Błąd cURL wysyłania zamówienia #' . $order['id'] . ' do apilo.com', 'Zamówienie #' . $order['id'] . ' nie zostało wysłane do Apilo z powodu błędu połączenia (cURL).' . "\n\n" . 'Błąd: ' . $curl_error_send );
|
||||
echo 'Błąd cURL: ' . $curl_error_send;
|
||||
}
|
||||
$http_code_send = (int)curl_getinfo( $ch, CURLINFO_HTTP_CODE );
|
||||
@@ -500,8 +509,8 @@ $processor->registerHandler( \Domain\CronJob\CronJobType::APILO_SEND_ORDER, func
|
||||
}
|
||||
elseif ( $http_code_send >= 400 || !isset( $response['id'] ) )
|
||||
{
|
||||
$mdb->update( 'pp_shop_orders', [ 'apilo_order_id' => -1 ], [ 'id' => $order['id'] ] );
|
||||
\Domain\Integrations\ApiloLogger::log( $mdb, 'send_order', (int)$order['id'], 'Błąd wysyłania zamówienia do Apilo (HTTP ' . $http_code_send . ')', [ 'http_code' => $http_code_send, 'response' => $response ] );
|
||||
$mdb->update( 'pp_shop_orders', [ 'apilo_order_id' => -1, 'apilo_order_status_date' => date('Y-m-d H:i:s') ], [ 'id' => $order['id'] ] );
|
||||
\Domain\Integrations\ApiloLogger::log( $mdb, 'send_order', (int)$order['id'], 'Błąd wysyłania zamówienia do Apilo (HTTP ' . $http_code_send . ') — ponowna próba za 1h', [ 'http_code' => $http_code_send, 'response' => $response ] );
|
||||
$email_data = 'HTTP Code: ' . $http_code_send . "\n\n";
|
||||
$email_data .= print_r( $response, true );
|
||||
$email_data .= print_r( $postData, true );
|
||||
@@ -512,6 +521,17 @@ $processor->registerHandler( \Domain\CronJob\CronJobType::APILO_SEND_ORDER, func
|
||||
{
|
||||
$mdb->update( 'pp_shop_orders', [ 'apilo_order_id' => $response['id'] ], [ 'id' => $order['id'] ] );
|
||||
\Domain\Integrations\ApiloLogger::log( $mdb, 'send_order', (int)$order['id'], 'Zamówienie wysłane do Apilo (apilo_order_id: ' . $response['id'] . ')', [ 'http_code' => $http_code_send, 'response' => $response ] );
|
||||
|
||||
// Wyczyść stare stuck joby sync_payment/sync_status dla tego zamówienia
|
||||
$orderPayloadJson = json_encode(['order_id' => (int)$order['id']]);
|
||||
$mdb->delete('pp_cron_jobs', [
|
||||
'AND' => [
|
||||
'job_type' => [\Domain\CronJob\CronJobType::APILO_SYNC_PAYMENT, \Domain\CronJob\CronJobType::APILO_SYNC_STATUS],
|
||||
'payload' => $orderPayloadJson,
|
||||
'status' => [\Domain\CronJob\CronJobType::STATUS_PENDING, \Domain\CronJob\CronJobType::STATUS_FAILED],
|
||||
]
|
||||
]);
|
||||
|
||||
echo '<p>Wysłałem zamówienie do apilo.com: ID: ' . $order['id'] . ' - ' . $response['id'] . '</p>';
|
||||
}
|
||||
}
|
||||
@@ -549,7 +569,7 @@ $processor->registerHandler( \Domain\CronJob\CronJobType::APILO_SYNC_STATUS, fun
|
||||
});
|
||||
|
||||
// 5. Apilo product sync
|
||||
$processor->registerHandler( \Domain\CronJob\CronJobType::APILO_PRODUCT_SYNC, function($payload) use ($mdb, $integrationsRepository) {
|
||||
$processor->registerHandler( \Domain\CronJob\CronJobType::APILO_PRODUCT_SYNC, function($payload) use ($mdb, $integrationsRepository, $apiloRepository) {
|
||||
$apilo_settings = $integrationsRepository->getSettings('apilo');
|
||||
if ( !$apilo_settings['enabled'] || !$apilo_settings['sync_products'] || !$apilo_settings['access-token'] ) return true;
|
||||
|
||||
@@ -557,7 +577,7 @@ $processor->registerHandler( \Domain\CronJob\CronJobType::APILO_PRODUCT_SYNC, fu
|
||||
$result = $stmt ? $stmt->fetch( \PDO::FETCH_ASSOC ) : null;
|
||||
if ( !$result ) return true;
|
||||
|
||||
$access_token = $integrationsRepository->apiloGetAccessToken();
|
||||
$access_token = $apiloRepository->apiloGetAccessToken();
|
||||
$url = 'https://projectpro.apilo.com/rest/api/warehouse/product/' . $result['apilo_product_id'] . '/';
|
||||
$curl = curl_init( $url );
|
||||
curl_setopt( $curl, CURLOPT_RETURNTRANSFER, true );
|
||||
@@ -582,11 +602,11 @@ $processor->registerHandler( \Domain\CronJob\CronJobType::APILO_PRODUCT_SYNC, fu
|
||||
});
|
||||
|
||||
// 6. Apilo pricelist sync
|
||||
$processor->registerHandler( \Domain\CronJob\CronJobType::APILO_PRICELIST_SYNC, function($payload) use ($mdb, $integrationsRepository) {
|
||||
$processor->registerHandler( \Domain\CronJob\CronJobType::APILO_PRICELIST_SYNC, function($payload) use ($mdb, $integrationsRepository, $apiloRepository) {
|
||||
$apilo_settings = $integrationsRepository->getSettings('apilo');
|
||||
if ( !$apilo_settings['enabled'] || !$apilo_settings['access-token'] ) return true;
|
||||
|
||||
$access_token = $integrationsRepository->apiloGetAccessToken();
|
||||
$access_token = $apiloRepository->apiloGetAccessToken();
|
||||
$url = 'https://projectpro.apilo.com/rest/api/warehouse/price-calculated/?price=' . $apilo_settings['pricelist_id'];
|
||||
|
||||
$curl = curl_init( $url );
|
||||
@@ -628,7 +648,7 @@ $processor->registerHandler( \Domain\CronJob\CronJobType::APILO_PRICELIST_SYNC,
|
||||
});
|
||||
|
||||
// 7. Apilo status poll
|
||||
$processor->registerHandler( \Domain\CronJob\CronJobType::APILO_STATUS_POLL, function($payload) use ($mdb, $integrationsRepository, $orderRepo, $orderAdminService) {
|
||||
$processor->registerHandler( \Domain\CronJob\CronJobType::APILO_STATUS_POLL, function($payload) use ($mdb, $integrationsRepository, $apiloRepository, $orderRepo, $orderAdminService) {
|
||||
$apilo_settings = $integrationsRepository->getSettings('apilo');
|
||||
if ( !$apilo_settings['enabled'] || !$apilo_settings['sync_orders'] || !$apilo_settings['access-token'] ) return true;
|
||||
|
||||
@@ -639,7 +659,7 @@ $processor->registerHandler( \Domain\CronJob\CronJobType::APILO_STATUS_POLL, fun
|
||||
{
|
||||
if ( $order['apilo_order_id'] )
|
||||
{
|
||||
$access_token = $integrationsRepository->apiloGetAccessToken();
|
||||
$access_token = $apiloRepository->apiloGetAccessToken();
|
||||
$url = 'https://projectpro.apilo.com/rest/api/orders/' . $order['apilo_order_id'] . '/';
|
||||
|
||||
$ch = curl_init( $url );
|
||||
@@ -751,5 +771,61 @@ $processor->registerHandler( \Domain\CronJob\CronJobType::TRUSTMATE_INVITATION,
|
||||
|
||||
$result = $processor->run( 20 );
|
||||
|
||||
// Powiadomienie mailowe o problemach Apilo
|
||||
// 1. Trwale failed joby (nie-order: token, product sync itp.)
|
||||
$failedApiloJobs = $mdb->select('pp_cron_jobs', ['id', 'job_type', 'last_error', 'payload', 'attempts', 'completed_at'], [
|
||||
'AND' => [
|
||||
'status' => 'failed',
|
||||
'job_type[~]' => 'apilo_%',
|
||||
'completed_at[>=]' => date('Y-m-d H:i:s', time() - 120),
|
||||
]
|
||||
]);
|
||||
// 2. Order joby z wieloma próbami (infinite retry, ale wymagają uwagi)
|
||||
$stuckOrderJobs = $mdb->select('pp_cron_jobs', ['id', 'job_type', 'last_error', 'payload', 'attempts', 'scheduled_at'], [
|
||||
'AND' => [
|
||||
'status' => 'pending',
|
||||
'job_type' => [\Domain\CronJob\CronJobType::APILO_SEND_ORDER, \Domain\CronJob\CronJobType::APILO_SYNC_PAYMENT, \Domain\CronJob\CronJobType::APILO_SYNC_STATUS],
|
||||
'attempts[>=]' => 10,
|
||||
]
|
||||
]);
|
||||
|
||||
$allProblems = array_merge($failedApiloJobs, $stuckOrderJobs);
|
||||
if (!empty($allProblems)) {
|
||||
$emailBody = "";
|
||||
$orderNumbers = [];
|
||||
|
||||
foreach ($allProblems as $fj) {
|
||||
$payloadData = is_string($fj['payload']) ? json_decode($fj['payload'], true) : $fj['payload'];
|
||||
$orderId = isset($payloadData['order_id']) ? (int)$payloadData['order_id'] : 0;
|
||||
$isOrderJob = \Domain\CronJob\CronJobType::isOrderRelatedApiloJob($fj['job_type']);
|
||||
$statusLabel = $isOrderJob ? 'PONAWIANY CO 30 MIN' : 'TRWAŁY BŁĄD';
|
||||
|
||||
$emailBody .= "Job #" . $fj['id'] . " (" . $fj['job_type'] . ") — " . $statusLabel . "\n";
|
||||
|
||||
if ($orderId > 0) {
|
||||
$order = $mdb->get('pp_shop_orders', ['id', 'client_name', 'client_surname', 'date_order', 'summary'], ['id' => $orderId]);
|
||||
if ($order) {
|
||||
$emailBody .= " Zamówienie: #" . $order['id'] . "\n";
|
||||
$emailBody .= " Klient: " . trim($order['client_name'] . ' ' . $order['client_surname']) . "\n";
|
||||
$emailBody .= " Data zamówienia: " . $order['date_order'] . "\n";
|
||||
$emailBody .= " Kwota: " . $order['summary'] . " PLN\n";
|
||||
$orderNumbers[] = '#' . $order['id'];
|
||||
}
|
||||
}
|
||||
|
||||
$emailBody .= " Próby: " . $fj['attempts'] . "\n";
|
||||
$emailBody .= " Błąd: " . $fj['last_error'] . "\n";
|
||||
$emailBody .= " Data: " . ($fj['completed_at'] ? $fj['completed_at'] : $fj['scheduled_at']) . "\n\n";
|
||||
}
|
||||
|
||||
$subject = 'shopPRO: Problemy synchronizacji Apilo';
|
||||
if (!empty($orderNumbers)) {
|
||||
$subject .= ' — zamówienia ' . implode(', ', array_unique($orderNumbers));
|
||||
}
|
||||
$subject .= ' (' . count($allProblems) . ' zadań)';
|
||||
|
||||
\Shared\Helpers\Helpers::send_email('biuro@project-pro.pl', $subject, $emailBody);
|
||||
}
|
||||
|
||||
echo '<hr>';
|
||||
echo '<p><small>CronJob stats: scheduled=' . $result['scheduled'] . ', processed=' . $result['processed'] . ', succeeded=' . $result['succeeded'] . ', failed=' . $result['failed'] . ', skipped=' . $result['skipped'] . '</small></p>';
|
||||
|
||||
Reference in New Issue
Block a user