<?php
namespace JanusHercules\DatawarehouseIntegration\Domain\Entity;
use App\Entity\ExternalPartner\ExternalPartner;
use App\Entity\PlatformSite;
use App\Service\ConversionEventService;
use App\Utility\DatabaseIdGenerator;
use App\Utility\DateTimeUtility;
use App\Utility\GuidUtility;
use App\Utility\ReflectionHelper;
use DateTime;
use Doctrine\DBAL\Types\Types;
use Doctrine\ORM\Mapping as ORM;
use Exception;
use InvalidArgumentException;
use ReflectionClass;
use ValueError;
#[ORM\Entity]
#[ORM\Table(name: 'external_partner_events')]
class ExternalPartnerEvent
{
public const EVENT_TYPE_USER_CREATED = 0;
public const EVENT_TYPE_RECURRENT_JOB_CREATED = 1;
public const EVENT_TYPE_USER_HAS_BEEN_FORWARDED_TO_EXTERNAL_JOB_POST_THAT_IS_RECURRENT_JOB = 2;
public const EVENT_TYPE_RECURRENT_JOB_SHARE_PAGE_REQUESTED = 3;
public const EVENT_TYPE_JOBRADAR_CREATED = 4;
public const EVENT_TYPE_PREMIUM_JOBRADAR_CREATED = 5;
public const EVENT_TYPE_TANKUNDRAST_RADAR_CREATED = 6;
public const EVENT_TYPE_WISAG_RADAR_CREATED = 7;
public const EVENT_TYPE_WISAG_PREMIUM_RADAR_CREATED = 8;
public const EVENT_TYPE_RECURRENT_JOB_HAS_BEEN_PROLONGED = 9;
public const EVENT_TYPE_RECURRENT_JOB_HAS_BEEN_REACTIVATED_BECAUSE_QUOTA_BECAME_AVAILABLE_AGAIN = 10;
public const EVENT_TYPE_RECURRENT_JOB_REMOVED = 11;
public const EVENT_TYPE_GOOGLE_INDEXING_WAS_REQUESTED_FOR_RECURRENT_JOB = 12;
public const EVENT_TYPE_RECURRENT_JOB_DEACTIVATED = 13;
public const EVENT_TYPE_RECURRENT_JOB_PUBLISHED = 14;
public const EVENT_TYPE_EXTERNAL_JOB_AVAILABILITY_CHECK_WAS_POSITIVE = 15;
public const EVENT_TYPE_EXTERNAL_JOB_AVAILABILITY_CHECK_WAS_NEGATIVE = 16;
public const EVENT_TYPE_EXTERNAL_JOB_AVAILABILITY_CHECK_WAS_CONNECTION_PROBLEM = 17;
public const EVENT_TYPE_EXTERNAL_JOB_AVAILABILITY_CHECK_WAS_SERVER_ERROR = 18;
// See https://trello.com/c/9gH3Hdjn/2088-verl%C3%A4ngerungs-command-hat-die-falschen-jobs-deaktiviert-oder-verl%C3%A4ngert
public const EVENT_TYPE_RECURRENT_JOB_REACTIVATED_DUE_TO_BUGFIX_2088 = 19;
public const EVENT_TYPE_USAGE_EVENT_REMOVED_DUE_TO_BUGFIX_2088 = 20;
public const EVENT_TYPE_QUOTA_WAS_DECREMENTED_DUE_TO_BUGFIX_2088 = 21;
public const EVENT_TYPE_RECURRENT_JOB_HAS_NOT_BEEN_PROLONGED_BECAUSE_MAX_AGE_REACHED = 22;
public const EVENT_TYPE_RECURRENT_JOB_HAS_NOT_BEEN_PROLONGED_BECAUSE_NO_QUOTA_AVAILABLE = 23;
public const EVENT_TYPE_EXTENDED_APPLICATION_HAS_BEEN_CREATED = 24;
public const EVENT_TYPE_RECURRENT_JOB_HAS_NOT_BEEN_PROLONGED_BECAUSE_MAX_NUMBER_OF_PROLONGATIONS_REACHED = 25;
public const EVENT_TYPE_AVAILABILITY_OF_RECURRENT_JOB_COULD_NOT_BE_CHECKED_BECAUSE_OF_MISSING_EXTERNAL_JOB_POSTING_URL = 26;
public const EVENT_TYPE_EXTERNAL_JOB_AVAILABILITY_CHECK_WAS_ERROR = 27;
public const EVENT_TYPE_USER_HAS_BEEN_FORWARDED_TO_EXTERNAL_JOB_POST_THAT_IS_RECURRENT_JOB_VIA_CONTENT_DISTRIBUTION_PARTNER = 28;
public const EVENT_TYPE_USER_HAS_BEEN_FORWARDED_TO_EXTERNAL_JOB_POST_THAT_IS_RECURRENT_JOB_VIA_JOBLIFT = 29;
public const EVENT_TYPE_USER_HAS_BEEN_FORWARDED_TO_EXTERNAL_JOB_POST_THAT_IS_RECURRENT_JOB_VIA_TALENTCOM = 30;
public const EVENT_TYPE_USER_HAS_BEEN_FORWARDED_TO_EXTERNAL_JOB_POST_THAT_IS_RECURRENT_JOB_VIA_JOBRAPIDO = 31;
public const EVENT_TYPE_USER_HAS_BEEN_FORWARDED_TO_EXTERNAL_JOB_POST_THAT_IS_RECURRENT_JOB_VIA_INDEED = 32;
public const EVENT_TYPE_USER_HAS_BEEN_FORWARDED_TO_EXTERNAL_JOB_POST_THAT_IS_RECURRENT_JOB_VIA_EBAY = 33;
public const EVENT_TYPE_USER_HAS_BEEN_FORWARDED_TO_EXTERNAL_JOB_POST_THAT_IS_RECURRENT_JOB_VIA_KIMETA = 34;
public const EVENT_TYPE_USER_HAS_BEEN_FORWARDED_TO_EXTERNAL_JOB_POST_THAT_IS_RECURRENT_JOB_VIA_STELLENONLINE = 35;
public const EVENT_TYPE_USER_HAS_BEEN_FORWARDED_TO_EXTERNAL_JOB_POST_THAT_IS_RECURRENT_JOB_VIA_GOOGLE_FOR_JOBS = 36;
public const EVENT_TYPE_USER_HAS_BEEN_FORWARDED_TO_EXTERNAL_JOB_POST_THAT_IS_RECURRENT_JOB_VIA_AGENTUR_FUER_ARBEIT = 37;
public const EVENT_TYPE_RECURRENT_JOB_HAS_BEEN_REACTIVATED_BECAUSE_RECURRENT_JOBS_LIMIT_HAS_CAPACITY_AGAIN = 38;
public const EVENT_TYPE_EXTERNAL_JOBPOSTING_IMPORT_FAILED_DUE_TO_INSUFFICIENT_UNUSED_QUOTA = 39;
public const EVENT_TYPE_EXTERNAL_JOBOFFER_CREATED = 40;
public const EVENT_TYPE_EXTERNAL_JOBOFFER_UPDATED = 41;
public const EVENT_TYPE_EXTERNAL_JOBOFFER_REMOVED = 42;
public const EVENT_TYPE_SENT_EXTERNAL_APPLICATION = 43;
public const EVENT_TYPE_RECURRENT_JOB_UPDATED = 44;
public const EVENT_TYPE_USER_REMOVED = 45;
public const EVENT_TYPE_USER_HAS_BEEN_FORWARDED_TO_EXTERNAL_JOB_POST_THAT_IS_RECURRENT_JOB_VIA_JOBIJOBA = 46;
public const EVENT_TYPE_USER_HAS_BEEN_FORWARDED_TO_EXTERNAL_JOB_POST_THAT_IS_RECURRENT_JOB_VIA_WHATJOBS = 47;
public const EVENT_TYPE_USER_HAS_BEEN_FORWARDED_TO_EXTERNAL_JOB_POST_THAT_IS_RECURRENT_JOB_VIA_JOOBLE = 48;
public const EVENT_TYPE_UPDATE_CHECK_FOR_RECURRENT_JOB_COULD_NOT_BE_EXECUTED_BECAUSE_OF_MISSING_EXTERNAL_JOB_POSTING_URL = 49;
public const EVENT_TYPE_USED_QUOTA_INCREMENTED_DUE_TO_CHANGED_ZIPCODE = 50;
public const EVENT_TYPE_IMPORTED_EXTERNAL_APPLICATION_QUESTIONS = 51;
public const EVENT_TYPE_RECURRENT_JOB_UPDATE_DENIED_BECAUSE_ZIPCODE_CHANGE_NOT_POSSIBLE = 52;
public const EVENT_TYPE_SKIPPED_USED_QUOTA_INCREASE_DUE_TO_RECURRENT_JOB_SPECIFIC_RULES = 53;
public const EVENT_TYPE_RECURRENT_JOB_CONTACT_INFO_DISPLAYED = 54;
public const EVENT_TYPE_USER_HAS_CLICKED_RECURRENT_JOB_WEBSITE = 55;
public const EVENT_TYPE_RECURRENT_JOB_DUPLICATED = 56;
public const EVENT_TYPE_EXTERNAL_JOBPOSTING_IMPORT_FAILED_DUE_TO_LIMIT_EXHAUSTED = 57;
public const EVENT_TYPE_RECURRENT_JOB_FRESHNESS_DATE_UPDATE = 58;
public const EVENT_TYPE_USER_HAS_BEEN_FORWARDED_TO_CUSTOMER_SPECIFIC_SEARCH_RESULTS_PAGE_VIA_PERSOMATCH_GOOGLE = 59;
/**
* @throws InvalidArgumentException|Exception
*/
public function __construct(
string $id,
int $eventType,
int $externalPartnerId
) {
GuidUtility::validOrThrow($id);
$this->id = $id;
if (!ReflectionHelper::hasConstWithValue(self::class, 'EVENT_TYPE_', $eventType)) {
throw new InvalidArgumentException('Value ' . $eventType . ' not allowed for eventType.');
}
$this->eventType = $eventType;
if (!ReflectionHelper::hasConstWithValue(ExternalPartner::class, 'ID_', $externalPartnerId)) {
throw new InvalidArgumentException('Value ' . $externalPartnerId . ' not allowed for externalPartnerId.');
}
$this->externalPartnerId = $externalPartnerId;
$this->occuredAt = DateTimeUtility::createDateTimeUtc();
$this->affectedUserId = null;
$this->adminUserId = null;
$this->affectedUserRegisteredAt = null;
$this->affectedUserIsJobofferer = false;
$this->affectedUserIsJobseeker = false;
$this->requestId = null;
$this->sessionId = null;
$this->clientId = null;
$this->isMeerbuschOfficeRequest = false;
$this->additionalData = null;
$this->platformSiteId = PlatformSite::PLATFORM_SITE_ID_JOBOO;
$this->conversionCampaignId = null;
$this->businessName = null;
$this->integratedExternalPartnerCustomerId = null;
$this->integratedExternalPartnerCustomerInternalId = null;
$this->recurrentJobId = null;
$this->recurrentJobCreatedAt = null;
$this->recurrentJobExternalId = null;
$this->recurrentJobOccupationalFieldSearchterm = null;
$this->recurrentJobZipcode = null;
$this->recurrentJobExternalUrl = null;
$this->isProbablyBotRequest = null;
}
/**
* @throws Exception
*/
public function getEventTypeTitle(): string
{
return self::getEventTypeTitleByEventType($this->getEventType());
}
/**
* @throws Exception
*/
public static function getEventTypeTitleByEventType(int $eventType): string
{
$refl = new ReflectionClass(self::class);
$constants = $refl->getConstants();
foreach ($constants as $constantName => $constantValue) {
if (substr($constantName, 0, 11) === 'EVENT_TYPE_' && $constantValue === $eventType) {
return strtolower(str_replace('_', '-', substr($constantName, 11)));
}
}
throw new Exception('Cannot resolve title for event type ' . $eventType);
}
#[ORM\Id]
#[ORM\GeneratedValue(strategy: 'CUSTOM')]
#[ORM\CustomIdGenerator(class: DatabaseIdGenerator::class)]
#[ORM\Column(
name : 'id',
type : Types::GUID,
unique: true
)]
private string $id;
public function getId(): string
{
return $this->id;
}
#[ORM\Column(
name : 'event_type',
type : Types::SMALLINT,
nullable: false
)]
private int $eventType;
public function getEventType(): int
{
return $this->eventType;
}
#[ORM\Column(
name : 'occured_at',
type : Types::DATETIME_MUTABLE,
nullable: false
)]
protected DateTime $occuredAt;
public function getOccuredAt(): DateTime
{
return $this->occuredAt;
}
#[ORM\Column(
name : 'external_partner_id',
type : Types::SMALLINT,
nullable: false
)]
protected int $externalPartnerId;
public function getExternalPartnerId(): ?int
{
return $this->externalPartnerId;
}
#[ORM\Column(
name : 'integrated_external_partner_customer_id',
type : Types::GUID,
nullable: true
)]
protected ?string $integratedExternalPartnerCustomerId;
public function setIntegratedExternalPartnerCustomerId(
?string $integratedExternalPartnerCustomerId
): void {
GuidUtility::validOrThrow($integratedExternalPartnerCustomerId, true);
$this->integratedExternalPartnerCustomerId = $integratedExternalPartnerCustomerId;
}
public function getIntegratedExternalPartnerCustomerId(): ?string
{
return $this->integratedExternalPartnerCustomerId;
}
#[ORM\Column(
name : 'integrated_external_partner_customer_internal_id',
type : Types::STRING,
length : 255,
nullable: true
)]
protected ?string $integratedExternalPartnerCustomerInternalId;
public function setIntegratedExternalPartnerCustomerInternalId(
?string $integratedExternalPartnerCustomerInternalId
): void {
$this->integratedExternalPartnerCustomerInternalId = $integratedExternalPartnerCustomerInternalId;
}
public function getIntegratedExternalPartnerCustomerInternalId(): ?string
{
return $this->integratedExternalPartnerCustomerInternalId;
}
#[ORM\Column(
name : 'recurrent_job_id',
type : Types::GUID,
nullable: true
)]
protected ?string $recurrentJobId;
public function setRecurrentJobId(
?string $recurrentJobId
): void {
GuidUtility::validOrThrow($recurrentJobId, true);
$this->recurrentJobId = $recurrentJobId;
}
public function getRecurrentJobId(): ?string
{
return $this->recurrentJobId;
}
#[ORM\Column(
name : 'recurrent_job_created_at',
type : Types::DATETIME_MUTABLE,
nullable: true
)]
protected ?DateTime $recurrentJobCreatedAt;
public function getRecurrentJobCreatedAt(): ?DateTime
{
return $this->recurrentJobCreatedAt;
}
public function setRecurrentJobCreatedAt(?DateTime $recurrentJobCreatedAt): void
{
$this->recurrentJobCreatedAt = $recurrentJobCreatedAt;
}
#[ORM\Column(
name : 'recurrent_job_zipcode',
type : Types::STRING,
length : 5,
nullable: true
)]
protected ?string $recurrentJobZipcode;
public function setRecurrentJobZipcode(
?string $recurrentJobZipcode
): void {
$this->recurrentJobZipcode = $recurrentJobZipcode;
}
public function getRecurrentJobZipcode(): ?string
{
return $this->recurrentJobZipcode;
}
#[ORM\Column(
name : 'recurrent_job_occupational_field_searchterm',
type : Types::STRING,
length : 1024,
nullable: true
)]
protected ?string $recurrentJobOccupationalFieldSearchterm;
public function setRecurrentJobOccupationalFieldSearchterm(
?string $recurrentJobOccupationalFieldSearchterm
): void {
$this->recurrentJobOccupationalFieldSearchterm = $recurrentJobOccupationalFieldSearchterm;
}
public function getRecurrentJobOccupationalFieldSearchterm(): ?string
{
return $this->recurrentJobOccupationalFieldSearchterm;
}
#[ORM\Column(
name : 'recurrent_job_external_id',
type : Types::STRING,
length : 1024,
nullable: true
)]
protected ?string $recurrentJobExternalId;
public function setRecurrentJobExternalId(
?string $recurrentJobExternalId
): void {
$this->recurrentJobExternalId = $recurrentJobExternalId;
}
public function getRecurrentJobExternalId(): ?string
{
return $this->recurrentJobExternalId;
}
#[ORM\Column(
name : 'recurrent_job_external_url',
type : Types::STRING,
length : 4096,
nullable: true
)]
protected ?string $recurrentJobExternalUrl;
public function setRecurrentJobExternalUrl(
?string $recurrentJobExternalUrl
): void {
$this->recurrentJobExternalUrl = $recurrentJobExternalUrl;
}
public function getRecurrentJobExternalUrl(): ?string
{
return $this->recurrentJobExternalUrl;
}
#[ORM\Column(
name : 'affected_user_id',
type : Types::GUID,
nullable: true
)]
protected ?string $affectedUserId;
public function setAffectedUserId(
?string $userId
): void {
GuidUtility::validOrThrow($userId, true);
$this->affectedUserId = $userId;
}
public function getAffectedUserId(): ?string
{
return $this->affectedUserId;
}
/**
* We don't make this a foreign key on purpose, we don't need the integrity and don't want to delete event data
* if a user is deleted.
*/
#[ORM\Column(
name : 'admin_user_id',
type : Types::GUID,
nullable: true
)]
protected ?string $adminUserId;
public function setAdminUserId(?string $adminUserId = null): void
{
GuidUtility::validOrThrow($adminUserId, true);
$this->adminUserId = $adminUserId;
}
public function getAdminUserId(): ?string
{
return $this->adminUserId;
}
#[ORM\Column(
name : 'affected_user_is_jobofferer',
type : Types::BOOLEAN,
nullable: false
)]
protected bool $affectedUserIsJobofferer;
public function setAffectedUserIsJobofferer(
bool $affectedUserIsJobofferer
): void {
$this->affectedUserIsJobofferer = $affectedUserIsJobofferer;
}
public function getAffectedUserIsJobofferer(): bool
{
return $this->affectedUserIsJobofferer;
}
#[ORM\Column(
name : 'affected_user_is_jobseeker',
type : Types::BOOLEAN,
nullable: false
)]
protected bool $affectedUserIsJobseeker;
public function setAffectedUserIsJobseeker(
bool $affectedUserIsJobseeker
): void {
$this->affectedUserIsJobseeker = $affectedUserIsJobseeker;
}
public function getAffectedUserIsJobseeker(): bool
{
return $this->affectedUserIsJobseeker;
}
#[ORM\Column(
name : 'affected_user_registered_at',
type : Types::DATETIME_MUTABLE,
nullable: true
)]
protected ?DateTime $affectedUserRegisteredAt;
public function setAffectedUserRegisteredAt(?DateTime $affectedUserRegisteredAt): void
{
$this->affectedUserRegisteredAt = $affectedUserRegisteredAt;
}
public function getAffectedUserRegisteredAt(): ?DateTime
{
return $this->affectedUserRegisteredAt;
}
#[ORM\Column(
name : 'additional_data',
type : Types::TEXT,
length : 8192,
nullable: true
)]
protected ?string $additionalData;
/**
* @throws Exception
*/
public function setAdditionalData(?string $additionalData = null): void
{
if (!is_null($additionalData)) {
if (is_null(json_decode($additionalData))) {
throw new Exception('additionalData must be valid JSON');
}
}
$this->additionalData = $additionalData;
}
public function getAdditionalData(): ?string
{
return $this->additionalData;
}
#[ORM\Column(
name : 'request_id',
type : Types::TEXT,
length : 256,
nullable: true
)]
protected ?string $requestId;
public function setRequestId(?string $requestId = null): void
{
$this->requestId = $requestId;
}
public function getRequestId(): ?string
{
return $this->requestId;
}
#[ORM\Column(
name : 'session_id',
type : Types::TEXT,
length : 256,
nullable: true
)]
protected ?string $sessionId;
public function setSessionId(?string $sessionId = null): void
{
$this->sessionId = $sessionId;
}
public function getSessionId(): ?string
{
return $this->sessionId;
}
#[ORM\Column(
name : 'client_id',
type : Types::TEXT,
length : 64,
nullable: true
)]
protected ?string $clientId;
public function setClientId(?string $clientId = null): void
{
$this->clientId = $clientId;
}
public function getClientId(): ?string
{
return $this->clientId;
}
#[ORM\Column(
name : 'is_meerbusch_office_request',
type : Types::BOOLEAN,
nullable: false
)]
protected bool $isMeerbuschOfficeRequest;
public function getIsMeerbuschOfficeRequest(): bool
{
return $this->isMeerbuschOfficeRequest;
}
public function setIsMeerbuschOfficeRequest(bool $isMeerbuschOfficeRequest): void
{
$this->isMeerbuschOfficeRequest = $isMeerbuschOfficeRequest;
}
#[ORM\Column(
name : 'platform_site_id',
type : Types::INTEGER,
nullable: true
)]
private ?int $platformSiteId;
public function getPlatformSiteId(): ?int
{
return $this->platformSiteId;
}
/**
* @throws Exception
*/
public function setPlatformSiteId(?int $platformSiteId): void
{
if (!is_null($platformSiteId) && !ReflectionHelper::hasConstWithValue(PlatformSite::class, 'PLATFORM_SITE_ID_', $platformSiteId)) {
throw new Exception("Not a valid value for : '$platformSiteId'.");
}
$this->platformSiteId = $platformSiteId;
}
#[ORM\Column(
name : 'conversion_campaign_id',
type : Types::INTEGER,
nullable: true
)]
private ?int $conversionCampaignId;
public function getConversionCampaignId(): ?int
{
return $this->conversionCampaignId;
}
/**
* @throws Exception
*/
public function setConversionCampaignId(?int $conversionCampaignId): void
{
if (!is_null($conversionCampaignId)
&& !ReflectionHelper::hasConstWithValue(
ConversionEventService::class,
'CAMPAIGN_ID_',
$conversionCampaignId
)
) {
throw new ValueError("Invalid campaign id '$conversionCampaignId'.");
}
$this->conversionCampaignId = $conversionCampaignId;
}
#[ORM\Column(
name : 'business_name',
type : Types::TEXT,
length : 255,
nullable: true
)]
protected ?string $businessName;
public function getBusinessName(): ?string
{
return $this->businessName;
}
public function setBusinessName(?string $businessName): void
{
$this->businessName = $businessName;
}
#[ORM\Column(
name : 'is_probably_bot_request',
type : Types::BOOLEAN,
nullable: true
)]
private ?bool $isProbablyBotRequest = null;
public function getIsProbablyBotRequest(): ?bool
{
return $this->isProbablyBotRequest;
}
public function setIsProbablyBotRequest(?bool $isProbablyBotRequest): void
{
$this->isProbablyBotRequest = $isProbablyBotRequest;
}
}