Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ abstract class AccountDeletionRequestDomainObjectAbstract extends \HiEvents\Doma
final public const ID = 'id';
final public const ACCOUNT_ID = 'account_id';
final public const REQUESTED_BY_USER_ID = 'requested_by_user_id';
final public const CANCELLED_BY_USER_ID = 'cancelled_by_user_id';
final public const INITIATED_BY = 'initiated_by';
final public const REASON = 'reason';
final public const STATUS = 'status';
Expand All @@ -22,6 +21,7 @@ abstract class AccountDeletionRequestDomainObjectAbstract extends \HiEvents\Doma
final public const SCHEDULED_DELETION_AT = 'scheduled_deletion_at';
final public const REMINDER_SENT_AT = 'reminder_sent_at';
final public const CANCELLED_AT = 'cancelled_at';
final public const CANCELLED_BY_USER_ID = 'cancelled_by_user_id';
final public const COMPLETED_AT = 'completed_at';
final public const DELETION_MANIFEST = 'deletion_manifest';
final public const CREATED_AT = 'created_at';
Expand All @@ -30,7 +30,6 @@ abstract class AccountDeletionRequestDomainObjectAbstract extends \HiEvents\Doma
protected int $id;
protected int $account_id;
protected int $requested_by_user_id;
protected ?int $cancelled_by_user_id = null;
protected string $initiated_by;
protected ?string $reason = null;
protected string $status = 'REQUESTED';
Expand All @@ -39,6 +38,7 @@ abstract class AccountDeletionRequestDomainObjectAbstract extends \HiEvents\Doma
protected string $scheduled_deletion_at;
protected ?string $reminder_sent_at = null;
protected ?string $cancelled_at = null;
protected ?int $cancelled_by_user_id = null;
protected ?string $completed_at = null;
protected array|string|null $deletion_manifest = null;
protected ?string $created_at = null;
Expand All @@ -50,7 +50,6 @@ public function toArray(): array
'id' => $this->id ?? null,
'account_id' => $this->account_id ?? null,
'requested_by_user_id' => $this->requested_by_user_id ?? null,
'cancelled_by_user_id' => $this->cancelled_by_user_id ?? null,
'initiated_by' => $this->initiated_by ?? null,
'reason' => $this->reason ?? null,
'status' => $this->status ?? null,
Expand All @@ -59,6 +58,7 @@ public function toArray(): array
'scheduled_deletion_at' => $this->scheduled_deletion_at ?? null,
'reminder_sent_at' => $this->reminder_sent_at ?? null,
'cancelled_at' => $this->cancelled_at ?? null,
'cancelled_by_user_id' => $this->cancelled_by_user_id ?? null,
'completed_at' => $this->completed_at ?? null,
'deletion_manifest' => $this->deletion_manifest ?? null,
'created_at' => $this->created_at ?? null,
Expand Down Expand Up @@ -99,17 +99,6 @@ public function getRequestedByUserId(): int
return $this->requested_by_user_id;
}

public function setCancelledByUserId(?int $cancelled_by_user_id): self
{
$this->cancelled_by_user_id = $cancelled_by_user_id;
return $this;
}

public function getCancelledByUserId(): ?int
{
return $this->cancelled_by_user_id;
}

public function setInitiatedBy(string $initiated_by): self
{
$this->initiated_by = $initiated_by;
Expand Down Expand Up @@ -198,6 +187,17 @@ public function getCancelledAt(): ?string
return $this->cancelled_at;
}

public function setCancelledByUserId(?int $cancelled_by_user_id): self
{
$this->cancelled_by_user_id = $cancelled_by_user_id;
return $this;
}

public function getCancelledByUserId(): ?int
{
return $this->cancelled_by_user_id;
}

public function setCompletedAt(?string $completed_at): self
{
$this->completed_at = $completed_at;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
<?php

namespace HiEvents\DomainObjects\Generated;

/**
* THIS FILE IS AUTOGENERATED - DO NOT EDIT IT DIRECTLY.
* @package HiEvents\DomainObjects\Generated
*/
abstract class ProductAddonDomainObjectAbstract extends \HiEvents\DomainObjects\AbstractDomainObject
{
final public const SINGULAR_NAME = 'product_addon';
final public const PLURAL_NAME = 'product_addons';
final public const ID = 'id';
final public const PRODUCT_ID = 'product_id';
final public const ADDON_PRODUCT_ID = 'addon_product_id';
final public const ORDER = 'order';
final public const CREATED_AT = 'created_at';
final public const UPDATED_AT = 'updated_at';

protected int $id;
protected int $product_id;
protected int $addon_product_id;
protected int $order = 0;
protected ?string $created_at = null;
protected ?string $updated_at = null;

public function toArray(): array
{
return [
'id' => $this->id ?? null,
'product_id' => $this->product_id ?? null,
'addon_product_id' => $this->addon_product_id ?? null,
'order' => $this->order ?? null,
'created_at' => $this->created_at ?? null,
'updated_at' => $this->updated_at ?? null,
];
}

public function setId(int $id): self
{
$this->id = $id;
return $this;
}

public function getId(): int
{
return $this->id;
}

public function setProductId(int $product_id): self
{
$this->product_id = $product_id;
return $this;
}

public function getProductId(): int
{
return $this->product_id;
}

public function setAddonProductId(int $addon_product_id): self
{
$this->addon_product_id = $addon_product_id;
return $this;
}

public function getAddonProductId(): int
{
return $this->addon_product_id;
}

public function setOrder(int $order): self
{
$this->order = $order;
return $this;
}

public function getOrder(): int
{
return $this->order;
}

public function setCreatedAt(?string $created_at): self
{
$this->created_at = $created_at;
return $this;
}

public function getCreatedAt(): ?string
{
return $this->created_at;
}

public function setUpdatedAt(?string $updated_at): self
{
$this->updated_at = $updated_at;
return $this;
}

public function getUpdatedAt(): ?string
{
return $this->updated_at;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ abstract class ProductDomainObjectAbstract extends \HiEvents\DomainObjects\Abstr
final public const IS_HIGHLIGHTED = 'is_highlighted';
final public const HIGHLIGHT_MESSAGE = 'highlight_message';
final public const WAITLIST_ENABLED = 'waitlist_enabled';
final public const IS_ADDON_ONLY = 'is_addon_only';

protected int $id;
protected int $event_id;
Expand Down Expand Up @@ -65,6 +66,7 @@ abstract class ProductDomainObjectAbstract extends \HiEvents\DomainObjects\Abstr
protected bool $is_highlighted = false;
protected ?string $highlight_message = null;
protected ?bool $waitlist_enabled = null;
protected bool $is_addon_only = false;

public function toArray(): array
{
Expand Down Expand Up @@ -96,6 +98,7 @@ public function toArray(): array
'is_highlighted' => $this->is_highlighted ?? null,
'highlight_message' => $this->highlight_message ?? null,
'waitlist_enabled' => $this->waitlist_enabled ?? null,
'is_addon_only' => $this->is_addon_only ?? null,
];
}

Expand Down Expand Up @@ -395,4 +398,15 @@ public function getWaitlistEnabled(): ?bool
{
return $this->waitlist_enabled;
}

public function setIsAddonOnly(bool $is_addon_only): self
{
$this->is_addon_only = $is_addon_only;
return $this;
}

public function getIsAddonOnly(): bool
{
return $this->is_addon_only;
}
}
7 changes: 7 additions & 0 deletions backend/app/DomainObjects/ProductAddonDomainObject.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<?php

namespace HiEvents\DomainObjects;

class ProductAddonDomainObject extends Generated\ProductAddonDomainObjectAbstract
{
}
19 changes: 19 additions & 0 deletions backend/app/DomainObjects/ProductDomainObject.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ class ProductDomainObject extends Generated\ProductDomainObjectAbstract implemen

private ?Collection $prices = null;

private ?Collection $addons = null;

private ?string $offSaleReason = null;

private ?int $quantityAvailable = null;
Expand Down Expand Up @@ -79,6 +81,23 @@ public function getFees(): ?Collection
return $this->getTaxAndFees()?->filter(fn (TaxAndFeesDomainObject $taxAndFee) => $taxAndFee->isFee());
}

public function setAddons(Collection $addons): ProductDomainObject
{
$this->addons = $addons;

return $this;
}

public function getAddons(): ?Collection
{
return $this->addons;
}

public function getAddonProductIds(): ?array
{
return $this->addons?->map(fn (ProductDomainObject $addon) => $addon->getId())->all();
}

public function isSoldOut(): bool
{
if (! $this->getProductPrices() || $this->getProductPrices()->isEmpty()) {
Expand Down
6 changes: 6 additions & 0 deletions backend/app/Http/Actions/Products/CreateProductAction.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
use HiEvents\Resources\Product\ProductResource;
use HiEvents\Services\Application\Handlers\Product\CreateProductHandler;
use HiEvents\Services\Application\Handlers\Product\DTO\UpsertProductDTO;
use HiEvents\Services\Domain\Product\Exception\InvalidAddonProductException;
use HiEvents\Services\Domain\Product\Exception\UnrecognizedProductIdException;
use Illuminate\Http\JsonResponse;
use Illuminate\Validation\ValidationException;
use Throwable;
Expand Down Expand Up @@ -43,6 +45,10 @@ public function __invoke(int $eventId, UpsertProductRequest $request): JsonRespo
throw ValidationException::withMessages([
'tax_and_fee_ids' => $e->getMessage(),
]);
} catch (InvalidAddonProductException|UnrecognizedProductIdException $e) {
throw ValidationException::withMessages([
'addon_product_ids' => $e->getMessage(),
]);
}

return $this->resourceResponse(
Expand Down
6 changes: 6 additions & 0 deletions backend/app/Http/Actions/Products/EditProductAction.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
use HiEvents\Resources\Product\ProductResource;
use HiEvents\Services\Application\Handlers\Product\DTO\UpsertProductDTO;
use HiEvents\Services\Application\Handlers\Product\EditProductHandler;
use HiEvents\Services\Domain\Product\Exception\InvalidAddonProductException;
use HiEvents\Services\Domain\Product\Exception\UnrecognizedProductIdException;
use Illuminate\Http\JsonResponse;
use Illuminate\Validation\ValidationException;
use Throwable;
Expand Down Expand Up @@ -46,6 +48,10 @@ public function __invoke(UpsertProductRequest $request, int $eventId, int $produ
throw ValidationException::withMessages([
'type' => $e->getMessage(),
]);
} catch (InvalidAddonProductException|UnrecognizedProductIdException $e) {
throw ValidationException::withMessages([
'addon_product_ids' => $e->getMessage(),
]);
}

return $this->resourceResponse(ProductResource::class, $product);
Expand Down
3 changes: 3 additions & 0 deletions backend/app/Http/Actions/Products/GetProductAction.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,10 @@

use HiEvents\DomainObjects\EventDomainObject;
use HiEvents\DomainObjects\Generated\ProductDomainObjectAbstract;
use HiEvents\DomainObjects\ProductDomainObject;
use HiEvents\DomainObjects\ProductPriceDomainObject;
use HiEvents\DomainObjects\TaxAndFeesDomainObject;
use HiEvents\Repository\Eloquent\Value\Relationship;
use HiEvents\Http\Actions\BaseAction;
use HiEvents\Repository\Interfaces\ProductRepositoryInterface;
use HiEvents\Resources\Product\ProductResource;
Expand All @@ -30,6 +32,7 @@ public function __invoke(int $eventId, int $productId): JsonResponse|Response
$product = $this->productRepository
->loadRelation(TaxAndFeesDomainObject::class)
->loadRelation(ProductPriceDomainObject::class)
->loadRelation(new Relationship(domainObject: ProductDomainObject::class, name: 'addons'))
->findFirstWhere([
ProductDomainObjectAbstract::EVENT_ID => $eventId,
ProductDomainObjectAbstract::ID => $productId,
Expand Down
3 changes: 3 additions & 0 deletions backend/app/Http/Request/Product/UpsertProductRequest.php
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,9 @@ public function rules(): array
'type' => ['required', Rule::in(ProductPriceType::valuesArray())],
'product_type' => ['required', Rule::in(ProductType::valuesArray())],
'tax_and_fee_ids' => 'array',
'addon_product_ids' => 'array',
'addon_product_ids.*' => 'integer',
'is_addon_only' => 'boolean',
'product_category_id' => ['required', 'integer'],
'is_highlighted' => 'boolean',
'highlight_message' => 'string|nullable|max:255',
Expand Down
7 changes: 7 additions & 0 deletions backend/app/Models/Product.php
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,13 @@ public function tax_and_fees(): BelongsToMany
return $this->belongsToMany(TaxAndFee::class, 'product_taxes_and_fees');
}

public function addons(): BelongsToMany
{
return $this->belongsToMany(self::class, 'product_addons', 'product_id', 'addon_product_id')
->withPivot('order')
->orderByPivot('order');
}

public function capacity_assignments(): BelongsToMany
{
return $this->belongsToMany(CapacityAssignment::class, 'product_capacity_assignments');
Expand Down
32 changes: 32 additions & 0 deletions backend/app/Repository/Eloquent/ProductRepository.php
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,38 @@ public function addTaxesAndFeesToProduct(int $productId, array $taxIds): void
Product::findOrFail($productId)?->tax_and_fees()->sync($taxIds);
}

public function syncAddons(int $productId, array $addonProductIds): void
{
$syncData = [];
foreach (array_values($addonProductIds) as $position => $addonProductId) {
$syncData[$addonProductId] = ['order' => $position];
}

Product::findOrFail($productId)->addons()->sync($syncData);
}

public function detachAddonAssociations(int $productId): void
{
$this->runQuery(
fn () => $this->db->table('product_addons')
->where('product_id', $productId)
->orWhere('addon_product_id', $productId)
->delete()
);
}

public function findParentProductIds(array $addonProductIds): Collection
{
return $this->runQuery(
fn () => collect(
$this->db->table('product_addons')
->whereIn('addon_product_id', $addonProductIds)
->get(['product_id', 'addon_product_id'])
)->groupBy('addon_product_id')
->map(fn ($rows) => $rows->pluck('product_id')->all())
);
}

public function addCapacityAssignmentToProducts(int $capacityAssignmentId, array $productIds): void
{
$productIds = array_unique($productIds);
Expand Down
Loading
Loading