$payload */ public static function isShippedEvent(array $payload): bool { return strtoupper(trim((string) ($payload['event_type'] ?? ''))) === 'ORDER_SHIPPED' || strtoupper(trim((string) ($payload['status'] ?? ''))) === 'SHIPPED'; } /** @param array $payload */ public static function isWorkflowStepEvent(array $payload): bool { return strtoupper(trim((string) ($payload['event_type'] ?? ''))) === 'WORKFLOW_STEP_COMPLETED'; } /** @param array $payload */ public static function isCompletedEvent(array $payload): bool { // A workflow node (including the final “ship” node) is only a // pharmacy-process update. It must not close the ZYT business order. return !self::isWorkflowStepEvent($payload) && strtoupper(trim((string) ($payload['status'] ?? ''))) === 'COMPLETED'; } /** @param array $payload */ public static function isRejectedEvent(array $payload): bool { return in_array(strtoupper(trim((string) ($payload['event_type'] ?? ''))), [ 'REVIEW_REJECTED', 'INVENTORY_SHORTAGE', ], true) || strtoupper(trim((string) ($payload['status'] ?? ''))) === 'REJECTED' || strtoupper(trim((string) ($payload['review_status'] ?? ''))) === 'REJECTED'; } /** @param array $payload */ public static function nextFulfillmentStatus( int $currentStatus, array $payload, ?int $rollbackStatus = null ): int { if (self::isRejectedEvent($payload)) { // EJ rejection means the pharmacy did not accept the submission; // it must not turn the ZYT business order into a customer refusal. // Restore the status captured immediately before the submission. return $rollbackStatus !== null && $rollbackStatus > 0 ? $rollbackStatus : ($currentStatus === 9 ? 2 : $currentStatus); } if (self::isWorkflowStepEvent($payload)) { // EJ workflow callbacks are informational nodes. Keep the ZYT // fulfillment status unchanged; only explicit shipment/completion // events may advance it. return $currentStatus; } if (self::isShippedEvent($payload) && in_array($currentStatus, [1, 2], true)) { return 5; } if (self::isCompletedEvent($payload) && in_array($currentStatus, [1, 2, 5], true)) { return 3; } return $currentStatus; } }