Skip to content

Commit b967c62

Browse files
committed
Merge branch 'feature/custom-event-emails' of github.com:HiEventsDev/hi.events into feature/custom-event-emails
2 parents a4b56e6 + 1c38809 commit b967c62

File tree

36 files changed

+2436
-433
lines changed

36 files changed

+2436
-433
lines changed

backend/app/DomainObjects/Generated/EventDailyStatisticDomainObjectAbstract.php

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ abstract class EventDailyStatisticDomainObjectAbstract extends \HiEvents\DomainO
2626
final public const TOTAL_REFUNDED = 'total_refunded';
2727
final public const TOTAL_VIEWS = 'total_views';
2828
final public const ATTENDEES_REGISTERED = 'attendees_registered';
29+
final public const ORDERS_CANCELLED = 'orders_cancelled';
2930

3031
protected int $id;
3132
protected int $event_id;
@@ -43,6 +44,7 @@ abstract class EventDailyStatisticDomainObjectAbstract extends \HiEvents\DomainO
4344
protected float $total_refunded = 0.0;
4445
protected int $total_views = 0;
4546
protected int $attendees_registered = 0;
47+
protected int $orders_cancelled = 0;
4648

4749
public function toArray(): array
4850
{
@@ -63,6 +65,7 @@ public function toArray(): array
6365
'total_refunded' => $this->total_refunded ?? null,
6466
'total_views' => $this->total_views ?? null,
6567
'attendees_registered' => $this->attendees_registered ?? null,
68+
'orders_cancelled' => $this->orders_cancelled ?? null,
6669
];
6770
}
6871

@@ -241,4 +244,15 @@ public function getAttendeesRegistered(): int
241244
{
242245
return $this->attendees_registered;
243246
}
247+
248+
public function setOrdersCancelled(int $orders_cancelled): self
249+
{
250+
$this->orders_cancelled = $orders_cancelled;
251+
return $this;
252+
}
253+
254+
public function getOrdersCancelled(): int
255+
{
256+
return $this->orders_cancelled;
257+
}
244258
}

backend/app/DomainObjects/Generated/EventStatisticDomainObjectAbstract.php

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ abstract class EventStatisticDomainObjectAbstract extends \HiEvents\DomainObject
2626
final public const ORDERS_CREATED = 'orders_created';
2727
final public const TOTAL_REFUNDED = 'total_refunded';
2828
final public const ATTENDEES_REGISTERED = 'attendees_registered';
29+
final public const ORDERS_CANCELLED = 'orders_cancelled';
2930

3031
protected int $id;
3132
protected int $event_id;
@@ -43,6 +44,7 @@ abstract class EventStatisticDomainObjectAbstract extends \HiEvents\DomainObject
4344
protected int $orders_created = 0;
4445
protected float $total_refunded = 0.0;
4546
protected int $attendees_registered = 0;
47+
protected int $orders_cancelled = 0;
4648

4749
public function toArray(): array
4850
{
@@ -63,6 +65,7 @@ public function toArray(): array
6365
'orders_created' => $this->orders_created ?? null,
6466
'total_refunded' => $this->total_refunded ?? null,
6567
'attendees_registered' => $this->attendees_registered ?? null,
68+
'orders_cancelled' => $this->orders_cancelled ?? null,
6669
];
6770
}
6871

@@ -241,4 +244,15 @@ public function getAttendeesRegistered(): int
241244
{
242245
return $this->attendees_registered;
243246
}
247+
248+
public function setOrdersCancelled(int $orders_cancelled): self
249+
{
250+
$this->orders_cancelled = $orders_cancelled;
251+
return $this;
252+
}
253+
254+
public function getOrdersCancelled(): int
255+
{
256+
return $this->orders_cancelled;
257+
}
244258
}

backend/app/DomainObjects/Generated/OrderDomainObjectAbstract.php

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ abstract class OrderDomainObjectAbstract extends \HiEvents\DomainObjects\Abstrac
4242
final public const LOCALE = 'locale';
4343
final public const PAYMENT_PROVIDER = 'payment_provider';
4444
final public const NOTES = 'notes';
45+
final public const STATISTICS_DECREMENTED_AT = 'statistics_decremented_at';
4546

4647
protected int $id;
4748
protected int $event_id;
@@ -75,6 +76,7 @@ abstract class OrderDomainObjectAbstract extends \HiEvents\DomainObjects\Abstrac
7576
protected string $locale = 'en';
7677
protected ?string $payment_provider = null;
7778
protected ?string $notes = null;
79+
protected ?string $statistics_decremented_at = null;
7880

7981
public function toArray(): array
8082
{
@@ -111,6 +113,7 @@ public function toArray(): array
111113
'locale' => $this->locale ?? null,
112114
'payment_provider' => $this->payment_provider ?? null,
113115
'notes' => $this->notes ?? null,
116+
'statistics_decremented_at' => $this->statistics_decremented_at ?? null,
114117
];
115118
}
116119

@@ -465,4 +468,15 @@ public function getNotes(): ?string
465468
{
466469
return $this->notes;
467470
}
471+
472+
public function setStatisticsDecrementedAt(?string $statistics_decremented_at): self
473+
{
474+
$this->statistics_decremented_at = $statistics_decremented_at;
475+
return $this;
476+
}
477+
478+
public function getStatisticsDecrementedAt(): ?string
479+
{
480+
return $this->statistics_decremented_at;
481+
}
468482
}

backend/app/DomainObjects/OrderDomainObject.php

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,13 @@
22

33
namespace HiEvents\DomainObjects;
44

5+
use HiEvents\DomainObjects\Enums\PaymentProviders;
56
use HiEvents\DomainObjects\Enums\ProductType;
67
use HiEvents\DomainObjects\Interfaces\IsFilterable;
78
use HiEvents\DomainObjects\Interfaces\IsSortable;
89
use HiEvents\DomainObjects\SortingAndFiltering\AllowedSorts;
910
use HiEvents\DomainObjects\Status\OrderPaymentStatus;
11+
use HiEvents\DomainObjects\Status\OrderRefundStatus;
1012
use HiEvents\DomainObjects\Status\OrderStatus;
1113
use HiEvents\Helper\AddressHelper;
1214
use Illuminate\Support\Carbon;
@@ -276,4 +278,12 @@ public function getSessionIdentifier(): ?string
276278
{
277279
return $this->sessionIdentifier;
278280
}
281+
282+
public function isRefundable(): bool
283+
{
284+
return !$this->isFreeOrder()
285+
&& $this->getStatus() !== OrderPaymentStatus::AWAITING_OFFLINE_PAYMENT->name
286+
&& $this->getPaymentProvider() === PaymentProviders::STRIPE->name
287+
&& $this->getRefundStatus() !== OrderRefundStatus::REFUNDED->name;
288+
}
279289
}

backend/app/Http/Actions/Orders/CancelOrderAction.php

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,19 @@
44

55
use HiEvents\DomainObjects\EventDomainObject;
66
use HiEvents\DomainObjects\Status\OrderStatus;
7+
use HiEvents\Exceptions\RefundNotPossibleException;
78
use HiEvents\Exceptions\ResourceConflictException;
89
use HiEvents\Http\Actions\BaseAction;
910
use HiEvents\Resources\Order\OrderResource;
1011
use HiEvents\Services\Application\Handlers\Order\CancelOrderHandler;
1112
use HiEvents\Services\Application\Handlers\Order\DTO\CancelOrderDTO;
1213
use Illuminate\Http\JsonResponse;
14+
use Illuminate\Http\Request;
1315
use Illuminate\Http\Response;
16+
use Illuminate\Validation\ValidationException;
17+
use Stripe\Exception\ApiErrorException;
1418
use Symfony\Component\HttpFoundation\Response as HttpResponse;
19+
use Throwable;
1520

1621
class CancelOrderAction extends BaseAction
1722
{
@@ -21,14 +26,28 @@ public function __construct(
2126
{
2227
}
2328

24-
public function __invoke(int $eventId, int $orderId): JsonResponse|Response
29+
/**
30+
* @throws Throwable
31+
* @throws ValidationException
32+
*/
33+
public function __invoke(int $eventId, int $orderId, Request $request): JsonResponse|Response
2534
{
2635
$this->isActionAuthorized($eventId, EventDomainObject::class);
2736

2837
try {
29-
$order = $this->cancelOrderHandler->handle(new CancelOrderDTO($eventId, $orderId));
38+
$order = $this->cancelOrderHandler->handle(new CancelOrderDTO(
39+
eventId: $eventId,
40+
orderId: $orderId,
41+
refund: $request->boolean('refund')
42+
));
3043
} catch (ResourceConflictException $e) {
3144
return $this->errorResponse($e->getMessage(), HttpResponse::HTTP_CONFLICT);
45+
} catch (ApiErrorException|RefundNotPossibleException $exception) {
46+
throw ValidationException::withMessages([
47+
'refund' => $exception instanceof ApiErrorException
48+
? 'Stripe error: ' . $exception->getMessage()
49+
: $exception->getMessage(),
50+
]);
3251
}
3352

3453
return $this->resourceResponse(OrderResource::class, $order->setStatus(OrderStatus::CANCELLED->name));

backend/app/Jobs/Event/UpdateEventStatisticsJob.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
use HiEvents\DomainObjects\OrderDomainObject;
66
use HiEvents\Exceptions\EventStatisticsVersionMismatchException;
7-
use HiEvents\Services\Domain\EventStatistics\EventStatisticsUpdateService;
7+
use HiEvents\Services\Domain\EventStatistics\EventStatisticsIncrementService;
88
use Illuminate\Bus\Queueable;
99
use Illuminate\Contracts\Queue\ShouldQueue;
1010
use Illuminate\Foundation\Bus\Dispatchable;
@@ -30,9 +30,9 @@ public function __construct(OrderDomainObject $order)
3030
/**
3131
* @throws EventStatisticsVersionMismatchException|Throwable
3232
*/
33-
public function handle(EventStatisticsUpdateService $service): void
33+
public function handle(EventStatisticsIncrementService $service): void
3434
{
35-
$service->updateStatistics($this->order);
35+
$service->incrementForOrder($this->order);
3636
}
3737

3838
public function failed(Throwable $exception): void

backend/app/Models/Order.php

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -63,11 +63,7 @@ protected function getCastMap(): array
6363
'point_in_time_data' => 'array',
6464
'address' => 'array',
6565
'taxes_and_fees_rollup' => 'array',
66+
'statistics_decremented_at' => 'datetime'
6667
];
6768
}
68-
69-
protected function getFillableFields(): array
70-
{
71-
return [];
72-
}
7369
}

backend/app/Repository/Eloquent/BaseRepository.php

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -308,6 +308,15 @@ public function deleteWhere(array $conditions): int
308308
return $deleted;
309309
}
310310

311+
public function countWhere(array $conditions): int
312+
{
313+
$this->applyConditions($conditions);
314+
$count = $this->model->count();
315+
$this->resetModel();
316+
317+
return $count;
318+
}
319+
311320
public function loadRelation(string|Relationship $relationship): static
312321
{
313322
if (is_string($relationship)) {

backend/app/Repository/Interfaces/RepositoryInterface.php

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ public function paginateWhere(
7171
*/
7272
public function simplePaginateWhere(
7373
array $where,
74-
?int $limit = null,
74+
?int $limit = null,
7575
array $columns = self::DEFAULT_COLUMNS,
7676
): Paginator;
7777

@@ -128,9 +128,9 @@ public function findFirstWhere(array $where, array $columns = self::DEFAULT_COLU
128128
* @return T|null
129129
*/
130130
public function findFirstByField(
131-
string $field,
131+
string $field,
132132
?string $value = null,
133-
array $columns = ['*']
133+
array $columns = ['*']
134134
): ?DomainObjectInterface;
135135

136136
/**
@@ -198,6 +198,8 @@ public function decrementEach(array $where, array $columns, array $extra = []):
198198

199199
public function incrementEach(array $columns, array $additionalUpdates = [], ?array $where = null);
200200

201+
public function countWhere(array $conditions): int;
202+
201203
public function includeDeleted(): static;
202204

203205
public function loadRelation(string|Relationship $relationship): static;

backend/app/Services/Application/Handlers/Attendee/PartialEditAttendeeHandler.php

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,9 @@
55
use HiEvents\DomainObjects\AttendeeDomainObject;
66
use HiEvents\DomainObjects\Status\AttendeeStatus;
77
use HiEvents\Repository\Interfaces\AttendeeRepositoryInterface;
8+
use HiEvents\Repository\Interfaces\OrderRepositoryInterface;
89
use HiEvents\Services\Application\Handlers\Attendee\DTO\PartialEditAttendeeDTO;
10+
use HiEvents\Services\Domain\EventStatistics\EventStatisticsCancellationService;
911
use HiEvents\Services\Domain\Product\ProductQuantityUpdateService;
1012
use HiEvents\Services\Infrastructure\DomainEvents\DomainEventDispatcherService;
1113
use HiEvents\Services\Infrastructure\DomainEvents\Enums\DomainEventType;
@@ -17,10 +19,12 @@
1719
class PartialEditAttendeeHandler
1820
{
1921
public function __construct(
20-
private readonly AttendeeRepositoryInterface $attendeeRepository,
21-
private readonly ProductQuantityUpdateService $productQuantityService,
22-
private readonly DatabaseManager $databaseManager,
23-
private readonly DomainEventDispatcherService $domainEventDispatcherService,
22+
private readonly AttendeeRepositoryInterface $attendeeRepository,
23+
private readonly OrderRepositoryInterface $orderRepository,
24+
private readonly ProductQuantityUpdateService $productQuantityService,
25+
private readonly DatabaseManager $databaseManager,
26+
private readonly DomainEventDispatcherService $domainEventDispatcherService,
27+
private readonly EventStatisticsCancellationService $eventStatisticsCancellationService,
2428
)
2529
{
2630
}
@@ -50,6 +54,7 @@ private function updateAttendee(PartialEditAttendeeDTO $data): AttendeeDomainObj
5054

5155
if ($statusIsUpdated) {
5256
$this->adjustProductQuantity($data, $attendee);
57+
$this->adjustEventStatistics($data, $attendee);
5358
}
5459

5560
if ($statusIsUpdated && $data->status === AttendeeStatus::CANCELLED->name) {
@@ -87,4 +92,22 @@ private function adjustProductQuantity(PartialEditAttendeeDTO $data, AttendeeDom
8792
$this->productQuantityService->decreaseQuantitySold($attendee->getProductPriceId());
8893
}
8994
}
95+
96+
/**
97+
* Adjust event statistics when attendee status changes
98+
*
99+
* @throws Throwable
100+
*/
101+
private function adjustEventStatistics(PartialEditAttendeeDTO $data, AttendeeDomainObject $attendee): void
102+
{
103+
if ($data->status === AttendeeStatus::CANCELLED->name) {
104+
// Get the order to access the creation date for daily statistics
105+
$order = $this->orderRepository->findById($attendee->getOrderId());
106+
107+
$this->eventStatisticsCancellationService->decrementForCancelledAttendee(
108+
eventId: $attendee->getEventId(),
109+
orderDate: $order->getCreatedAt()
110+
);
111+
}
112+
}
90113
}

0 commit comments

Comments
 (0)