Skip to content

Commit 604312f

Browse files
authored
allow restricting products to personal pickup only (#4671)
2 parents edc4844 + 9a57c42 commit 604312f

19 files changed

Lines changed: 222 additions & 23 deletions

src/Form/Admin/Product/ProductFormType.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -284,6 +284,11 @@ private function createBasicInformationGroup(
284284
'multiple' => true,
285285
'expanded' => false,
286286
'label' => 'Excluded transports',
287+
])
288+
->add('personalPickupOnly', YesNoType::class, [
289+
'required' => false,
290+
'label' => 'Personal pickup only',
291+
'help' => t('If enabled, a cart containing this product can only use personal pickup at store transports.'),
287292
]);
288293

289294
return $builderBasicInformationGroup;
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Shopsys\FrameworkBundle\Migrations;
6+
7+
use Doctrine\DBAL\Schema\Schema;
8+
use Override;
9+
use Shopsys\MigrationBundle\Component\Doctrine\Migrations\AbstractMigration;
10+
11+
final class Version20260618191555 extends AbstractMigration
12+
{
13+
#[Override]
14+
public function up(Schema $schema): void
15+
{
16+
$this->sql('ALTER TABLE products ADD personal_pickup_only BOOLEAN NOT NULL DEFAULT FALSE');
17+
$this->sql('ALTER TABLE products ALTER personal_pickup_only DROP DEFAULT');
18+
}
19+
}

src/Model/Cart/Cart.php

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
use Shopsys\FrameworkBundle\Model\Order\PromoCode\PromoCode;
1616
use Shopsys\FrameworkBundle\Model\Payment\Payment;
1717
use Shopsys\FrameworkBundle\Model\Product\Exception\ProductNotFoundException;
18+
use Shopsys\FrameworkBundle\Model\Product\Product;
1819
use Shopsys\FrameworkBundle\Model\Transport\Transport;
1920
use Shopsys\McpAttributes\Attribute\AsMcpColumn;
2021
use Shopsys\McpAttributes\Attribute\AsMcpTable;
@@ -243,6 +244,22 @@ public function getProducts(): array
243244
);
244245
}
245246

247+
/**
248+
* @return \Shopsys\FrameworkBundle\Model\Product\Product[]
249+
*/
250+
public function getPersonalPickupOnlyProducts(): array
251+
{
252+
return array_filter(
253+
$this->getProducts(),
254+
static fn (Product $product) => $product->isPersonalPickupOnly(),
255+
);
256+
}
257+
258+
public function isPersonalPickupRequired(): bool
259+
{
260+
return $this->getPersonalPickupOnlyProducts() !== [];
261+
}
262+
246263
public function findSimilarItemByItem(CartItem $item): ?CartItem
247264
{
248265
foreach ($this->items as $similarItem) {

src/Model/Product/Elasticsearch/ProductExportRepository.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,7 @@ protected function getExportedFieldValue(int $domainId, Product $product, string
153153
ProductExportFieldProvider::PARAMETERS => $this->extractParametersIncludedVariants($product, $locale, $domainId),
154154
ProductExportFieldProvider::ORDERING_PRIORITY => $product->getOrderingPriority($domainId),
155155
ProductExportFieldProvider::SELLING_DENIED => $product->isCalculatedSellingDenied($domainId),
156+
ProductExportFieldProvider::PERSONAL_PICKUP_ONLY => $product->isPersonalPickupOnly(),
156157
ProductExportFieldProvider::AVAILABILITY => $this->productAvailabilityFacade->getProductAvailabilityInformationByDomainId($product, $domainId),
157158
ProductExportFieldProvider::IS_MAIN_VARIANT => $product->isMainVariant(),
158159
ProductExportFieldProvider::IS_VARIANT => $product->isVariant(),

src/Model/Product/Elasticsearch/Scope/ProductExportFieldProvider.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ class ProductExportFieldProvider
2828
public const string PARAMETERS = 'parameters';
2929
public const string ORDERING_PRIORITY = 'ordering_priority';
3030
public const string SELLING_DENIED = 'selling_denied';
31+
public const string PERSONAL_PICKUP_ONLY = 'personal_pickup_only';
3132
public const string AVAILABILITY = 'availability';
3233
public const string IS_MAIN_VARIANT = 'is_main_variant';
3334
public const string IS_VARIANT = 'is_variant';

src/Model/Product/Product.php

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,13 @@ class Product extends AbstractTranslatableEntity
110110
#[ORM\Column(type: 'boolean')]
111111
protected $hidden;
112112

113+
/**
114+
* @var bool
115+
*/
116+
#[AsMcpColumn]
117+
#[ORM\Column(type: 'boolean')]
118+
protected $personalPickupOnly;
119+
113120
/**
114121
* @var \Shopsys\FrameworkBundle\Model\Product\Unit\Unit
115122
*/
@@ -271,6 +278,7 @@ protected function setData(ProductData $productData): void
271278
$this->weight = $productData->weight;
272279
$this->productType = $productData->productType;
273280
$this->isAllowedNegativeStock = $productData->isAllowedNegativeStock;
281+
$this->personalPickupOnly = $productData->personalPickupOnly;
274282
$this->setTranslations($productData);
275283
$this->setExcludedTransports($productData->excludedTransports);
276284
$this->editRelatedProducts($productData->relatedProducts);
@@ -450,6 +458,14 @@ public function isSellingDenied()
450458
return $this->sellingDenied;
451459
}
452460

461+
/**
462+
* @return bool
463+
*/
464+
public function isPersonalPickupOnly()
465+
{
466+
return $this->personalPickupOnly;
467+
}
468+
453469
/**
454470
* @param mixed|null $domainId
455471
* @return bool

src/Model/Product/ProductData.php

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,11 @@ class ProductData
5858
*/
5959
public $hidden;
6060

61+
/**
62+
* @var bool
63+
*/
64+
public $personalPickupOnly;
65+
6166
/**
6267
* @var \Shopsys\FrameworkBundle\Model\Product\Unit\Unit|null
6368
*/
@@ -240,6 +245,7 @@ public function __construct()
240245
$this->nameSuffix = [];
241246
$this->sellingDenied = false;
242247
$this->hidden = false;
248+
$this->personalPickupOnly = false;
243249
$this->flagsByDomainId = [];
244250
$this->isAllowedNegativeStock = true;
245251
$this->productStockData = [];

src/Model/Product/ProductDataFactory.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,7 @@ protected function fillFromProduct(ProductData $productData, Product $product):
167167
$productData->productType = $product->getProductType();
168168

169169
$productData->isAllowedNegativeStock = $product->isAllowedNegativeStock();
170+
$productData->personalPickupOnly = $product->isPersonalPickupOnly();
170171
$this->fillProductStockByProduct($productData, $product);
171172
}
172173

src/Model/Product/Search/ProductElasticsearchConverter.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ public function fillEmptyFields(array $product): array
5151
$result[ProductExportFieldProvider::VARIANTS] = $product[ProductExportFieldProvider::VARIANTS] ?? [];
5252

5353
$result[ProductExportFieldProvider::SELLING_DENIED] = $product[ProductExportFieldProvider::SELLING_DENIED] ?? true;
54+
$result[ProductExportFieldProvider::PERSONAL_PICKUP_ONLY] = $product[ProductExportFieldProvider::PERSONAL_PICKUP_ONLY] ?? false;
5455

5556
// unknown default value, used for filtering only
5657
$result[ProductExportFieldProvider::BRAND] = $product[ProductExportFieldProvider::BRAND] ?? null;

src/Model/Transport/TransportFacade.php

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -231,10 +231,6 @@ public function getVisibleOnCurrentDomainWithEagerLoadedDomainsAndTranslations(?
231231
$domainId = $this->domain->getId();
232232
$transports = $this->transportRepository->getAllWithEagerLoadedDomainsAndTranslations($this->domain->getCurrentDomainConfig(), $cart?->getTotalWeight());
233233

234-
if ($cart !== null) {
235-
$transports = $this->transportVisibilityCalculation->filterTransportsByProductsInCart($transports, $cart);
236-
}
237-
238234
$visiblePayments = $this->paymentFacade->getVisibleOnCurrentDomain();
239235

240236
return $this->transportVisibilityCalculation->filterVisible($transports, $visiblePayments, $domainId);

0 commit comments

Comments
 (0)