update
This commit is contained in:
@@ -10,14 +10,17 @@ use App\Core\Security\Csrf;
|
||||
use App\Core\Support\Flash;
|
||||
use App\Core\View\Template;
|
||||
use App\Modules\Auth\AuthService;
|
||||
use App\Modules\Settings\ReceiptConfigRepository;
|
||||
use Throwable;
|
||||
|
||||
final class AutomationController
|
||||
{
|
||||
private const ALLOWED_EVENTS = ['receipt.created', 'shipment.status_changed'];
|
||||
private const ALLOWED_CONDITION_TYPES = ['integration', 'shipment_status'];
|
||||
private const ALLOWED_ACTION_TYPES = ['send_email'];
|
||||
private const ALLOWED_ACTION_TYPES = ['send_email', 'issue_receipt'];
|
||||
private const ALLOWED_RECIPIENTS = ['client', 'client_and_company', 'company'];
|
||||
private const ALLOWED_RECEIPT_ISSUE_DATE_MODES = ['today', 'order_date', 'payment_date'];
|
||||
private const ALLOWED_RECEIPT_DUPLICATE_POLICIES = ['skip_if_exists', 'allow_duplicates'];
|
||||
private const SHIPMENT_STATUS_OPTIONS = [
|
||||
'registered' => ['label' => 'Przesylka zarejestrowana', 'statuses' => ['created', 'confirmed']],
|
||||
'ready_for_pickup' => ['label' => 'Przesylka do odbioru', 'statuses' => ['ready_for_pickup']],
|
||||
@@ -32,7 +35,8 @@ final class AutomationController
|
||||
private readonly Template $template,
|
||||
private readonly Translator $translator,
|
||||
private readonly AuthService $auth,
|
||||
private readonly AutomationRepository $repository
|
||||
private readonly AutomationRepository $repository,
|
||||
private readonly ReceiptConfigRepository $receiptConfigs
|
||||
) {
|
||||
}
|
||||
|
||||
@@ -194,6 +198,9 @@ final class AutomationController
|
||||
'conditionTypes' => self::ALLOWED_CONDITION_TYPES,
|
||||
'actionTypes' => self::ALLOWED_ACTION_TYPES,
|
||||
'recipientOptions' => self::ALLOWED_RECIPIENTS,
|
||||
'receiptConfigs' => $this->listActiveReceiptConfigs(),
|
||||
'receiptIssueDateModes' => self::ALLOWED_RECEIPT_ISSUE_DATE_MODES,
|
||||
'receiptDuplicatePolicies' => self::ALLOWED_RECEIPT_DUPLICATE_POLICIES,
|
||||
'shipmentStatusOptions' => self::SHIPMENT_STATUS_OPTIONS,
|
||||
'errorMessage' => Flash::get('settings.automation.error', ''),
|
||||
], 'layouts/app');
|
||||
@@ -366,6 +373,51 @@ final class AutomationController
|
||||
return ['template_id' => $templateId, 'recipient' => $recipient];
|
||||
}
|
||||
|
||||
if ($type === 'issue_receipt') {
|
||||
$configId = (int) ($action['receipt_config_id'] ?? 0);
|
||||
$issueDateMode = (string) ($action['issue_date_mode'] ?? '');
|
||||
$duplicatePolicy = (string) ($action['duplicate_policy'] ?? '');
|
||||
|
||||
if (
|
||||
$configId <= 0
|
||||
|| !in_array($issueDateMode, self::ALLOWED_RECEIPT_ISSUE_DATE_MODES, true)
|
||||
|| !in_array($duplicatePolicy, self::ALLOWED_RECEIPT_DUPLICATE_POLICIES, true)
|
||||
) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return [
|
||||
'receipt_config_id' => $configId,
|
||||
'issue_date_mode' => $issueDateMode,
|
||||
'duplicate_policy' => $duplicatePolicy,
|
||||
];
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return list<array{id:int,name:string,number_format:string}>
|
||||
*/
|
||||
private function listActiveReceiptConfigs(): array
|
||||
{
|
||||
$all = $this->receiptConfigs->listAll();
|
||||
$result = [];
|
||||
foreach ($all as $config) {
|
||||
if ((int) ($config['is_active'] ?? 0) !== 1) {
|
||||
continue;
|
||||
}
|
||||
$configId = (int) ($config['id'] ?? 0);
|
||||
if ($configId <= 0) {
|
||||
continue;
|
||||
}
|
||||
$result[] = [
|
||||
'id' => $configId,
|
||||
'name' => (string) ($config['name'] ?? ''),
|
||||
'number_format' => (string) ($config['number_format'] ?? ''),
|
||||
];
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,13 +3,19 @@ declare(strict_types=1);
|
||||
|
||||
namespace App\Modules\Automation;
|
||||
|
||||
use App\Modules\Accounting\ReceiptRepository;
|
||||
use App\Modules\Email\EmailSendingService;
|
||||
use App\Modules\Orders\OrdersRepository;
|
||||
use App\Modules\Settings\CompanySettingsRepository;
|
||||
use App\Modules\Settings\ReceiptConfigRepository;
|
||||
use Throwable;
|
||||
|
||||
final class AutomationService
|
||||
{
|
||||
private const CHAIN_STATE_KEY = '__automation_chain';
|
||||
private const MAX_CHAIN_DEPTH = 8;
|
||||
private const MAX_CHAIN_EXECUTIONS = 200;
|
||||
|
||||
private const SHIPMENT_STATUS_OPTION_MAP = [
|
||||
'registered' => ['created', 'confirmed'],
|
||||
'ready_for_pickup' => ['ready_for_pickup'],
|
||||
@@ -24,7 +30,9 @@ final class AutomationService
|
||||
private readonly AutomationRepository $repository,
|
||||
private readonly EmailSendingService $emailService,
|
||||
private readonly OrdersRepository $orders,
|
||||
private readonly CompanySettingsRepository $companySettings
|
||||
private readonly CompanySettingsRepository $companySettings,
|
||||
private readonly ReceiptRepository $receipts,
|
||||
private readonly ReceiptConfigRepository $receiptConfigs
|
||||
) {
|
||||
}
|
||||
|
||||
@@ -33,6 +41,12 @@ final class AutomationService
|
||||
*/
|
||||
public function trigger(string $eventType, int $orderId, array $context = []): void
|
||||
{
|
||||
$chainState = $this->getChainState($context);
|
||||
if ($chainState['depth'] > self::MAX_CHAIN_DEPTH) {
|
||||
return;
|
||||
}
|
||||
$context = $this->withChainState($context, $chainState);
|
||||
|
||||
$rules = $this->repository->findActiveByEvent($eventType);
|
||||
if ($rules === []) {
|
||||
return;
|
||||
@@ -47,12 +61,19 @@ final class AutomationService
|
||||
|
||||
foreach ($rules as $rule) {
|
||||
try {
|
||||
$ruleId = (int) ($rule['id'] ?? 0);
|
||||
$executionKey = $this->buildExecutionKey($eventType, $ruleId);
|
||||
if ($this->isExecutionAlreadyProcessed($chainState, $executionKey)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$conditions = is_array($rule['conditions'] ?? null) ? $rule['conditions'] : [];
|
||||
$actions = is_array($rule['actions'] ?? null) ? $rule['actions'] : [];
|
||||
$ruleName = (string) ($rule['name'] ?? '');
|
||||
$ruleContext = $this->withExecution($context, $executionKey);
|
||||
|
||||
if ($this->evaluateConditions($conditions, $order, $context)) {
|
||||
$this->executeActions($actions, $orderId, $ruleName);
|
||||
if ($this->evaluateConditions($conditions, $order, $ruleContext)) {
|
||||
$this->executeActions($actions, $orderId, $ruleName, $ruleContext);
|
||||
}
|
||||
} catch (Throwable) {
|
||||
// Blad jednej reguly nie blokuje kolejnych
|
||||
@@ -151,8 +172,9 @@ final class AutomationService
|
||||
|
||||
/**
|
||||
* @param list<array<string, mixed>> $actions
|
||||
* @param array<string, mixed> $context
|
||||
*/
|
||||
private function executeActions(array $actions, int $orderId, string $ruleName): void
|
||||
private function executeActions(array $actions, int $orderId, string $ruleName, array $context): void
|
||||
{
|
||||
foreach ($actions as $action) {
|
||||
$type = (string) ($action['action_type'] ?? '');
|
||||
@@ -160,6 +182,11 @@ final class AutomationService
|
||||
|
||||
if ($type === 'send_email') {
|
||||
$this->handleSendEmail($config, $orderId, $ruleName);
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($type === 'issue_receipt') {
|
||||
$this->handleIssueReceipt($config, $orderId, $ruleName, $context);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -214,4 +241,396 @@ final class AutomationService
|
||||
$companyName
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<string, mixed> $config
|
||||
* @param array<string, mixed> $context
|
||||
*/
|
||||
private function handleIssueReceipt(array $config, int $orderId, string $ruleName, array $context): void
|
||||
{
|
||||
$actorName = 'Automatyzacja: ' . $ruleName;
|
||||
|
||||
$configId = (int) ($config['receipt_config_id'] ?? 0);
|
||||
if ($configId <= 0) {
|
||||
return;
|
||||
}
|
||||
$issueDateMode = (string) ($config['issue_date_mode'] ?? 'today');
|
||||
$duplicatePolicy = (string) ($config['duplicate_policy'] ?? 'skip_if_exists');
|
||||
|
||||
$receiptConfig = $this->receiptConfigs->findById($configId);
|
||||
if ($receiptConfig === null || (int) ($receiptConfig['is_active'] ?? 0) !== 1) {
|
||||
$this->orders->recordActivity(
|
||||
$orderId,
|
||||
'automation_receipt_failed',
|
||||
$actorName . ' - nieprawidlowa lub nieaktywna konfiguracja paragonu',
|
||||
['receipt_config_id' => $configId],
|
||||
'system',
|
||||
$actorName
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
$existingReceipts = $this->receipts->findByOrderId($orderId);
|
||||
if ($duplicatePolicy === 'skip_if_exists' && $existingReceipts !== []) {
|
||||
$this->orders->recordActivity(
|
||||
$orderId,
|
||||
'automation_receipt_skipped',
|
||||
$actorName . ' - pomieto, paragon juz istnieje dla zamowienia',
|
||||
['duplicate_policy' => $duplicatePolicy, 'existing_count' => count($existingReceipts)],
|
||||
'system',
|
||||
$actorName
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
$details = $this->orders->findDetails($orderId);
|
||||
if ($details === null) {
|
||||
return;
|
||||
}
|
||||
$order = is_array($details['order'] ?? null) ? $details['order'] : [];
|
||||
$items = is_array($details['items'] ?? null) ? $details['items'] : [];
|
||||
$addresses = is_array($details['addresses'] ?? null) ? $details['addresses'] : [];
|
||||
$payments = is_array($details['payments'] ?? null) ? $details['payments'] : [];
|
||||
|
||||
$issueDate = $this->resolveIssueDate($issueDateMode, $order, $payments);
|
||||
$saleDate = $this->resolveSaleDate($receiptConfig, $order, $payments, $issueDate);
|
||||
$orderReference = $this->resolveOrderReference($receiptConfig, $order);
|
||||
$sellerSnapshot = $this->buildSellerSnapshot();
|
||||
$buyerSnapshot = $this->buildBuyerSnapshot($addresses);
|
||||
['items' => $itemsSnapshot, 'total_gross' => $totalGross] = $this->buildItemsSnapshot($items);
|
||||
|
||||
try {
|
||||
$receiptNumber = $this->receipts->getNextNumber(
|
||||
$configId,
|
||||
(string) ($receiptConfig['number_format'] ?? 'PAR/%N/%M/%Y'),
|
||||
(string) ($receiptConfig['numbering_type'] ?? 'monthly')
|
||||
);
|
||||
$this->receipts->create([
|
||||
'order_id' => $orderId,
|
||||
'config_id' => $configId,
|
||||
'receipt_number' => $receiptNumber,
|
||||
'issue_date' => $issueDate,
|
||||
'sale_date' => $saleDate,
|
||||
'seller_data_json' => json_encode($sellerSnapshot, JSON_UNESCAPED_UNICODE),
|
||||
'buyer_data_json' => $buyerSnapshot !== null ? json_encode($buyerSnapshot, JSON_UNESCAPED_UNICODE) : null,
|
||||
'items_json' => json_encode($itemsSnapshot, JSON_UNESCAPED_UNICODE),
|
||||
'total_net' => number_format($totalGross, 2, '.', ''),
|
||||
'total_gross' => number_format($totalGross, 2, '.', ''),
|
||||
'order_reference_value' => $orderReference,
|
||||
'created_by' => null,
|
||||
]);
|
||||
|
||||
$this->orders->recordActivity(
|
||||
$orderId,
|
||||
'receipt_issued',
|
||||
'Wystawiono paragon: ' . $receiptNumber,
|
||||
['receipt_number' => $receiptNumber, 'config_id' => $configId, 'total_gross' => number_format($totalGross, 2, '.', '')],
|
||||
'system',
|
||||
$actorName
|
||||
);
|
||||
|
||||
// Chain automation: issuing receipt from one rule should trigger
|
||||
// rules listening on receipt.created. Uses generic chain context
|
||||
// with depth + rule deduplication to prevent loops.
|
||||
$this->emitEvent(
|
||||
'receipt.created',
|
||||
$orderId,
|
||||
$context,
|
||||
[
|
||||
'automation_source' => 'issue_receipt',
|
||||
'automation_rule' => $ruleName,
|
||||
'receipt_number' => $receiptNumber,
|
||||
'receipt_config_id' => $configId,
|
||||
]
|
||||
);
|
||||
} catch (Throwable $exception) {
|
||||
$this->orders->recordActivity(
|
||||
$orderId,
|
||||
'automation_receipt_failed',
|
||||
$actorName . ' - blad wystawiania paragonu',
|
||||
['error' => $exception->getMessage(), 'receipt_config_id' => $configId],
|
||||
'system',
|
||||
$actorName
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<string, mixed> $order
|
||||
* @param list<array<string, mixed>> $payments
|
||||
*/
|
||||
private function resolveIssueDate(string $mode, array $order, array $payments): string
|
||||
{
|
||||
if ($mode === 'order_date') {
|
||||
$orderedAt = trim((string) ($order['ordered_at'] ?? ''));
|
||||
if ($orderedAt !== '') {
|
||||
$timestamp = strtotime($orderedAt);
|
||||
if ($timestamp !== false) {
|
||||
return date('Y-m-d', $timestamp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($mode === 'payment_date') {
|
||||
$firstPayment = $payments[0] ?? [];
|
||||
$paymentDate = trim((string) ($firstPayment['payment_date'] ?? ''));
|
||||
if ($paymentDate !== '') {
|
||||
$timestamp = strtotime($paymentDate);
|
||||
if ($timestamp !== false) {
|
||||
return date('Y-m-d', $timestamp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return date('Y-m-d');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<string, mixed> $receiptConfig
|
||||
* @param array<string, mixed> $order
|
||||
* @param list<array<string, mixed>> $payments
|
||||
*/
|
||||
private function resolveSaleDate(array $receiptConfig, array $order, array $payments, string $issueDate): string
|
||||
{
|
||||
$source = (string) ($receiptConfig['sale_date_source'] ?? 'issue_date');
|
||||
|
||||
if ($source === 'order_date') {
|
||||
$ordered = (string) ($order['ordered_at'] ?? '');
|
||||
if ($ordered !== '') {
|
||||
$ts = strtotime($ordered);
|
||||
return $ts !== false ? date('Y-m-d', $ts) : $issueDate;
|
||||
}
|
||||
}
|
||||
|
||||
if ($source === 'payment_date' && $payments !== []) {
|
||||
$lastPayment = $payments[0] ?? [];
|
||||
$payDate = (string) ($lastPayment['payment_date'] ?? '');
|
||||
if ($payDate !== '') {
|
||||
$ts = strtotime($payDate);
|
||||
return $ts !== false ? date('Y-m-d', $ts) : $issueDate;
|
||||
}
|
||||
}
|
||||
|
||||
return $issueDate;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<string, mixed> $receiptConfig
|
||||
* @param array<string, mixed> $order
|
||||
*/
|
||||
private function resolveOrderReference(array $receiptConfig, array $order): ?string
|
||||
{
|
||||
$ref = (string) ($receiptConfig['order_reference'] ?? 'none');
|
||||
|
||||
if ($ref === 'orderpro') {
|
||||
return (string) ($order['internal_order_number'] ?? '');
|
||||
}
|
||||
|
||||
if ($ref === 'integration') {
|
||||
return (string) ($order['external_order_id'] ?? '');
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
private function buildSellerSnapshot(): array
|
||||
{
|
||||
$seller = $this->companySettings->getSettings();
|
||||
|
||||
return [
|
||||
'company_name' => $seller['company_name'] ?? '',
|
||||
'tax_number' => $seller['tax_number'] ?? '',
|
||||
'street' => $seller['street'] ?? '',
|
||||
'city' => $seller['city'] ?? '',
|
||||
'postal_code' => $seller['postal_code'] ?? '',
|
||||
'phone' => $seller['phone'] ?? '',
|
||||
'email' => $seller['email'] ?? '',
|
||||
'bank_account' => $seller['bank_account'] ?? '',
|
||||
'bdo_number' => $seller['bdo_number'] ?? '',
|
||||
'regon' => $seller['regon'] ?? '',
|
||||
'court_register' => $seller['court_register'] ?? '',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param list<array<string, mixed>> $addresses
|
||||
* @return array<string, mixed>|null
|
||||
*/
|
||||
private function buildBuyerSnapshot(array $addresses): ?array
|
||||
{
|
||||
$buyerAddress = $this->resolveBuyerAddress($addresses);
|
||||
if ($buyerAddress === null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return [
|
||||
'name' => $buyerAddress['name'] ?? '',
|
||||
'company_name' => $buyerAddress['company_name'] ?? '',
|
||||
'tax_number' => $buyerAddress['company_tax_number'] ?? '',
|
||||
'street' => trim((string) (($buyerAddress['street_name'] ?? '') . ' ' . ($buyerAddress['street_number'] ?? ''))),
|
||||
'city' => $buyerAddress['city'] ?? '',
|
||||
'postal_code' => $buyerAddress['zip_code'] ?? '',
|
||||
'phone' => $buyerAddress['phone'] ?? '',
|
||||
'email' => $buyerAddress['email'] ?? '',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param list<array<string, mixed>> $addresses
|
||||
* @return array<string, mixed>|null
|
||||
*/
|
||||
private function resolveBuyerAddress(array $addresses): ?array
|
||||
{
|
||||
$byType = [];
|
||||
foreach ($addresses as $address) {
|
||||
$type = (string) ($address['address_type'] ?? '');
|
||||
if ($type !== '' && !isset($byType[$type])) {
|
||||
$byType[$type] = $address;
|
||||
}
|
||||
}
|
||||
|
||||
return $byType['invoice'] ?? $byType['customer'] ?? null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param list<array<string, mixed>> $items
|
||||
* @return array{items:list<array<string,mixed>>,total_gross:float}
|
||||
*/
|
||||
private function buildItemsSnapshot(array $items): array
|
||||
{
|
||||
$itemsSnapshot = [];
|
||||
$totalGross = 0.0;
|
||||
foreach ($items as $item) {
|
||||
$qty = (float) ($item['quantity'] ?? 0);
|
||||
$price = $item['original_price_with_tax'] !== null ? (float) $item['original_price_with_tax'] : 0.0;
|
||||
$lineTotal = $qty * $price;
|
||||
$totalGross += $lineTotal;
|
||||
$itemsSnapshot[] = [
|
||||
'name' => $item['original_name'] ?? '',
|
||||
'quantity' => $qty,
|
||||
'price' => $price,
|
||||
'total' => $lineTotal,
|
||||
'sku' => $item['sku'] ?? '',
|
||||
'ean' => $item['ean'] ?? '',
|
||||
];
|
||||
}
|
||||
|
||||
return [
|
||||
'items' => $itemsSnapshot,
|
||||
'total_gross' => $totalGross,
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<string, mixed> $context
|
||||
* @return array{chain_id:string,depth:int,executions:list<string>}
|
||||
*/
|
||||
private function getChainState(array $context): array
|
||||
{
|
||||
$raw = $context[self::CHAIN_STATE_KEY] ?? null;
|
||||
$rawState = is_array($raw) ? $raw : [];
|
||||
|
||||
$chainId = trim((string) ($rawState['chain_id'] ?? ''));
|
||||
if ($chainId === '') {
|
||||
$chainId = $this->generateChainId();
|
||||
}
|
||||
|
||||
$depth = max(0, (int) ($rawState['depth'] ?? 0));
|
||||
|
||||
$executionsRaw = $rawState['executions'] ?? [];
|
||||
$executions = [];
|
||||
if (is_array($executionsRaw)) {
|
||||
foreach ($executionsRaw as $executionRaw) {
|
||||
$execution = trim((string) $executionRaw);
|
||||
if ($execution === '') {
|
||||
continue;
|
||||
}
|
||||
$executions[] = $execution;
|
||||
}
|
||||
}
|
||||
|
||||
return [
|
||||
'chain_id' => $chainId,
|
||||
'depth' => $depth,
|
||||
'executions' => array_values(array_unique($executions)),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<string, mixed> $context
|
||||
* @param array{chain_id:string,depth:int,executions:list<string>} $state
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
private function withChainState(array $context, array $state): array
|
||||
{
|
||||
$context[self::CHAIN_STATE_KEY] = [
|
||||
'chain_id' => $state['chain_id'],
|
||||
'depth' => $state['depth'],
|
||||
'executions' => $state['executions'],
|
||||
];
|
||||
|
||||
return $context;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<string, mixed> $context
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
private function withExecution(array $context, string $executionKey): array
|
||||
{
|
||||
$state = $this->getChainState($context);
|
||||
$state['executions'][] = $executionKey;
|
||||
if (count($state['executions']) > self::MAX_CHAIN_EXECUTIONS) {
|
||||
$state['executions'] = array_slice($state['executions'], -self::MAX_CHAIN_EXECUTIONS);
|
||||
}
|
||||
|
||||
return $this->withChainState($context, $state);
|
||||
}
|
||||
|
||||
private function buildExecutionKey(string $eventType, int $ruleId): string
|
||||
{
|
||||
if ($ruleId <= 0) {
|
||||
return $eventType . '#unknown';
|
||||
}
|
||||
|
||||
return $eventType . '#' . $ruleId;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array{chain_id:string,depth:int,executions:list<string>} $state
|
||||
*/
|
||||
private function isExecutionAlreadyProcessed(array $state, string $executionKey): bool
|
||||
{
|
||||
return in_array($executionKey, $state['executions'], true);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<string, mixed> $parentContext
|
||||
* @param array<string, mixed> $eventContext
|
||||
*/
|
||||
private function emitEvent(string $eventType, int $orderId, array $parentContext, array $eventContext): void
|
||||
{
|
||||
$parentState = $this->getChainState($parentContext);
|
||||
if ($parentState['depth'] >= self::MAX_CHAIN_DEPTH) {
|
||||
return;
|
||||
}
|
||||
|
||||
$childState = $parentState;
|
||||
$childState['depth'] = $parentState['depth'] + 1;
|
||||
|
||||
$childContext = $this->withChainState($eventContext, $childState);
|
||||
$this->trigger($eventType, $orderId, $childContext);
|
||||
}
|
||||
|
||||
private function generateChainId(): string
|
||||
{
|
||||
try {
|
||||
return bin2hex(random_bytes(8));
|
||||
} catch (Throwable) {
|
||||
return uniqid('chain_', true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -184,7 +184,9 @@ final class CronHandlerFactory
|
||||
$automationRepository,
|
||||
$emailService,
|
||||
$ordersRepository,
|
||||
$companySettingsRepository
|
||||
$companySettingsRepository,
|
||||
new ReceiptRepository($this->db),
|
||||
new ReceiptConfigRepository($this->db)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user