Skip to content

Commit

Permalink
Merge branch 'main' of https://github.com/inikoo/aiku into main
Browse files Browse the repository at this point in the history
  • Loading branch information
KirinZero0 committed Feb 20, 2025
2 parents 3965cde + 3b287aa commit ae78f96
Show file tree
Hide file tree
Showing 49 changed files with 660 additions and 412 deletions.
2 changes: 1 addition & 1 deletion app/Actions/Analytics/GetSectionRoute.php
Original file line number Diff line number Diff line change
Expand Up @@ -212,7 +212,7 @@ public function parseGroupSections(string $route, $routeParameters): AikuScopedS
}

if ($routeParameters) {
return AikuScopedSection::where('code', $sectionCode)->where('model_slug', $routeParameters['group'])->first();
return AikuScopedSection::where('code', $sectionCode)->where('model_slug', group()->slug)->first();
} else {
return AikuScopedSection::where('code', $sectionCode)->first();
}
Expand Down
11 changes: 11 additions & 0 deletions app/Actions/Catalogue/Shop/Hydrators/ShopHydrateSales.php
Original file line number Diff line number Diff line change
Expand Up @@ -67,5 +67,16 @@ public function handle(Shop $shop, ?array $intervals = null, $doPreviousInterval
$shop->salesIntervals()->update($stats);
}

public string $commandSignature = 'test';

public function asCommand($command)
{
$f = Shop::all();
foreach ($f as $fulfilment) {
$this->handle($fulfilment);
}
}



}
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
<?php

/*
* Author: Artha <artha@aw-advantage.com>
* Created: Thu, 20 Feb 2025 13:37:24 Central Indonesia Time, Sanur, Bali, Indonesia
* Copyright (c) 2025, Raul A Perusquia Flores
*/

namespace App\Actions\Comms\DispatchedEmail\Hydrators;

use App\Actions\Traits\WithEnumStats;
use App\Enums\Comms\EmailTrackingEvent\EmailTrackingEventTypeEnum;
use App\Models\Comms\DispatchedEmail;
use Illuminate\Queue\Middleware\WithoutOverlapping;
use Lorisleiva\Actions\Concerns\AsAction;

class DispatchedEmailHydrateEmailTracking
{
use AsAction;
use WithEnumStats;

private DispatchedEmail $dispatchedEmail;

public function __construct(DispatchedEmail $dispatchedEmail)
{
$this->dispatchedEmail = $dispatchedEmail;
}

public function getJobMiddleware(): array
{
return [(new WithoutOverlapping($this->dispatchedEmail->id))->dontRelease()];
}


public function handle(DispatchedEmail $dispatchedEmail): void
{
$stats = [
'number_clicks' => $dispatchedEmail
->emailTrackingEvents()
->where('type', EmailTrackingEventTypeEnum::CLICKED)
->count(),
'number_reads' => $dispatchedEmail
->emailTrackingEvents()
->where('type', EmailTrackingEventTypeEnum::OPENED)
->count()
];

$dispatchedEmail->update($stats);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ public function authorize(ActionRequest $request): bool
public function rules(): array
{
$rules = [
'ses_id' => ['sometimes', 'required', 'string'],
'provider_dispatch_id' => ['sometimes', 'required', 'string'],
'state' => ['sometimes', 'required', Rule::enum(DispatchedEmailStateEnum::class)]
];
if (!$this->strict) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

namespace App\Actions\Comms\EmailTrackingEvent;

use App\Actions\Comms\DispatchedEmail\Hydrators\DispatchedEmailHydrateEmailTracking;
use App\Actions\OrgAction;
use App\Actions\Traits\Rules\WithNoStrictRules;
use App\Enums\Comms\EmailTrackingEvent\EmailTrackingEventTypeEnum;
Expand All @@ -27,6 +28,8 @@ public function handle(DispatchedEmail $dispatchedEmail, array $modelData): Emai
/** @var EmailTrackingEvent $emailTrackingEvent */
$emailTrackingEvent = $dispatchedEmail->emailTrackingEvents()->create($modelData);

DispatchedEmailHydrateEmailTracking::dispatch($dispatchedEmail);

return $emailTrackingEvent;
}

Expand Down
3 changes: 1 addition & 2 deletions app/Actions/Comms/Notifications/GetSnsNotification.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ public function asController(ServerRequestInterface $request): string
{
$message = Message::fromPsrRequest($request);
$validator = new MessageValidator();

if ($validator->isValid($message)) {
if ($message['Type'] == 'SubscriptionConfirmation') {
file_get_contents($message['SubscribeURL']);
Expand All @@ -45,7 +44,7 @@ public function asController(ServerRequestInterface $request): string
]
);

// ProcessSesNotification::dispatch($sesNotification);
ProcessSesNotification::run($sesNotification);

}
}
Expand Down
187 changes: 57 additions & 130 deletions app/Actions/Comms/SesNotification/ProcessSesNotification.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,210 +8,137 @@

namespace App\Actions\Comms\SesNotification;

use App\Actions\Comms\DispatchedEmail\UpdateDispatchedEmail;
use App\Actions\Comms\EmailTrackingEvent\StoreEmailTrackingEvent;
use App\Actions\CRM\Prospect\UpdateProspectEmailClicked;
use App\Actions\CRM\Prospect\UpdateProspectEmailHardBounced;
use App\Actions\CRM\Prospect\UpdateProspectEmailOpened;
use App\Actions\CRM\Prospect\UpdateProspectEmailSoftBounced;
use App\Actions\CRM\Prospect\UpdateProspectEmailUnsubscribed;
use App\Actions\Traits\WithActionUpdate;
use App\Actions\Utils\IsGoogleIp;
use App\Enums\Comms\DispatchedEmail\DispatchedEmailStateEnum;
use App\Enums\Comms\DispatchedEmailEvent\DispatchedEmailEventTypeEnum;
use App\Enums\Comms\EmailTrackingEvent\EmailTrackingEventTypeEnum;
use App\Models\Comms\DispatchedEmail;
use App\Models\Comms\SesNotification;
use Exception;
use Illuminate\Console\Command;
use Illuminate\Support\Arr;
use Illuminate\Support\Carbon;
use Lorisleiva\Actions\Concerns\AsAction;

class ProcessSesNotification
{
use AsAction;
use WithActionUpdate;

public function handle(SesNotification $sesNotification): ?array
{
$dispatchedEmail = DispatchedEmail::where('provider_message_id', $sesNotification->message_id)->first();
$dispatchedEmail = DispatchedEmail::where('provider_dispatch_id', $sesNotification->message_id)->first();

if (!$dispatchedEmail) {
$sesNotification->delete();

return [];
}

$additionalData = [];

switch (Arr::get($sesNotification->data, 'eventType')) {
case 'Bounce':
$type = DispatchedEmailEventTypeEnum::BOUNCE;
$date = Arr::get($sesNotification->data, 'bounce.timestamp');
$data = Arr::only($sesNotification->data['bounce'], ['bounceType', 'bounceSubType', 'reportingMTA']);

$isHardBounce = Arr::get($sesNotification->data, 'bounce.bounceType') == 'Permanent';

if ($dispatchedEmail->recipient_type == 'Prospect') {
if ($isHardBounce) {
UpdateProspectEmailHardBounced::run(
$dispatchedEmail->recipient,
new Carbon($date)
);
} else {
UpdateProspectEmailSoftBounced::run(
$dispatchedEmail->recipient,
new Carbon($date)
);
}
}

$type = EmailTrackingEventTypeEnum::SOFT_BOUNCE;
$dispatchedEmailState = DispatchedEmailStateEnum::SOFT_BOUNCE;

if ($isHardBounce) {
$dispatchedEmail->email()->update(
[
'is_hard_bounced' => true,
'hard_bounce_type' => Arr::get($sesNotification->data, 'bounce.bounceSubType')
]
);
$type = EmailTrackingEventTypeEnum::HARD_BOUNCE;
$dispatchedEmailState = DispatchedEmailStateEnum::HARD_BOUNCE;
}

UpdateDispatchedEmail::run(
$dispatchedEmail,
[
'state' => $isHardBounce ? DispatchedEmailStateEnum::HARD_BOUNCE : DispatchedEmailStateEnum::SOFT_BOUNCE,
'date' => $date,
'is_hard_bounced' => $isHardBounce,
'is_soft_bounced' => !$isHardBounce

]
);

break;
case 'Complaint':
$type = DispatchedEmailEventTypeEnum::COMPLAIN;
$date = Arr::get($sesNotification->data, 'complaint.timestamp');
$type = EmailTrackingEventTypeEnum::MARKED_AS_SPAM;
$dispatchedEmailState = DispatchedEmailStateEnum::SPAM;
$data = Arr::only($sesNotification->data['complaint'], ['userAgent', 'complaintSubType', 'complaintFeedbackType']);

if ($dispatchedEmail->recipient_type == 'Prospect') {
UpdateProspectEmailUnsubscribed::run($dispatchedEmail->recipient, new Carbon($date));
}
$additionalData = [
'mask_as_spam' => true
];

UpdateDispatchedEmail::run(
$dispatchedEmail,
[
'state' => DispatchedEmailStateEnum::SPAM,
'is_spam' => true,
'date' => $date,
]
);
break;
case 'Delivery':
$type = DispatchedEmailEventTypeEnum::DELIVERY;
$date = Arr::get($sesNotification->data, 'delivery.timestamp');
$type = EmailTrackingEventTypeEnum::DELIVERED;
$dispatchedEmailState = DispatchedEmailStateEnum::DELIVERED;
$data = Arr::only($sesNotification->data['delivery'], ['remoteMtaIp', 'smtpResponse']);

UpdateDispatchedEmail::run(
$dispatchedEmail,
[
'state' => DispatchedEmailStateEnum::DELIVERED,
'date' => $date,
'delivered_at' => $date,
'is_delivered' => true
]
);
break;
case 'Reject':
$type = EmailTrackingEventTypeEnum::DECLINED_BY_PROVIDER;
$dispatchedEmailState = DispatchedEmailStateEnum::REJECTED_BY_PROVIDER;
$data = Arr::only($sesNotification->data['reject'], ['ipAddress', 'userAgent']);

if ($dispatchedEmail->state == DispatchedEmailStateEnum::READY) {
UpdateDispatchedEmail::run(
$dispatchedEmail,
[
'state' => DispatchedEmailStateEnum::REJECTED,
'is_rejected' => true,
]
);
}
$sesNotification->delete();

return null;

break;

case 'Open':
$type = DispatchedEmailEventTypeEnum::OPEN;
$date = Arr::get($sesNotification->data, 'open.timestamp');
$type = EmailTrackingEventTypeEnum::OPENED;
$dispatchedEmailState = DispatchedEmailStateEnum::OPENED;
$data = Arr::only($sesNotification->data['open'], ['ipAddress', 'userAgent']);



if (Arr::get($data, 'userAgent') == "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.135 Safari/537.36 Edge/12.246 Mozilla/5.0"
and IsGoogleIp::run(Arr::get($data, 'ipAddress'))
) {
$sesNotification->delete();
return null;
}

$additionalData = [
'last_read_at' => now()
];

if ($dispatchedEmail->recipient_type == 'Prospect') {
UpdateProspectEmailOpened::run($dispatchedEmail->recipient, new Carbon($date));
if (!$dispatchedEmail->first_read_at) {
$additionalData = [
'first_read_at' => now(),
'last_read_at' => now()
];
}

UpdateDispatchedEmail::run(
$dispatchedEmail,
[
'state' => DispatchedEmailStateEnum::OPENED,
'date' => $date,
'is_opened' => true
]
);

break;
case 'Click':
StoreEmailTrackingEvent::make()->action($dispatchedEmail, [
'provider_reference' => $sesNotification->message_id
]);
/* $type = DispatchedEmailEventTypeEnum::CLICK;
$date = Arr::get($sesNotification->data, 'click.timestamp');
$data = Arr::only($sesNotification->data['click'], ['ipAddress', 'userAgent', 'link', 'linkTags']);
if ($dispatchedEmail->recipient_type == 'Prospect') {
UpdateProspectEmailClicked::run($dispatchedEmail->recipient, new Carbon($date));
}*/

// Create storetracking event and call hydrators

/* UpdateDispatchedEmail::run(
$dispatchedEmail,
[
'state' => DispatchedEmailStateEnum::CLICKED,
'date' => $date,
'is_clicked' => true
]
);*/
$type = EmailTrackingEventTypeEnum::CLICKED;
$dispatchedEmailState = DispatchedEmailStateEnum::CLICKED;
$data = Arr::only($sesNotification->data['click'], ['ipAddress', 'userAgent']);

$additionalData = [
'last_clicked_at' => now()
];

if (!$dispatchedEmail->first_read_at) {
$additionalData = [
'first_clicked_at' => now(),
'last_clicked_at' => now()
];
}

break;

case 'DeliveryDelay':
$type = DispatchedEmailEventTypeEnum::DELIVERY_DELAY;
$date = Arr::get($sesNotification->data, 'deliveryDelay.timestamp');
$data = Arr::only(
$sesNotification->data['deliveryDelay'],
['delayType', 'expirationTime', 'reportingMTA']
);
$type = EmailTrackingEventTypeEnum::DECLINED_BY_PROVIDER;
$dispatchedEmailState = DispatchedEmailStateEnum::DELAY;
$data = Arr::only($sesNotification->data['deliveryDelay'], ['ipAddress', 'userAgent']);

break;

default:
return $sesNotification->data;
}

$sesNotification->delete();


$eventData = [
StoreEmailTrackingEvent::make()->action($dispatchedEmail, [
'provider_reference' => $sesNotification->message_id,
'type' => $type,
'date' => $date,
'data' => $data
];
]);

$this->update($dispatchedEmail, [
'state' => $dispatchedEmailState,
...$additionalData
]);

$dispatchedEmail->events()->create($eventData);

$sesNotification->delete();

return null;
}
Expand Down
Loading

0 comments on commit ae78f96

Please sign in to comment.