Skip to content

Commit

Permalink
Fixing the stocks number of bundled products after successful order i…
Browse files Browse the repository at this point in the history
…n the shop.

remp/crm#622
  • Loading branch information
lubos-michalik committed Mar 31, 2020
1 parent bbab446 commit ec440fc
Show file tree
Hide file tree
Showing 5 changed files with 164 additions and 22 deletions.
2 changes: 2 additions & 0 deletions src/config/config.neon
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ services:
- Crm\ProductsModule\Distribution\ProductShopCountsDistribution
- Crm\ProductsModule\Distribution\ProductDaysFromLastOrderDistribution

productManager: Crm\ProductsModule\Manager\ProductManager

ebookProvider:
class: Crm\ProductsModule\Ebook\EbookProvider

Expand Down
34 changes: 13 additions & 21 deletions src/events/PaymentStatusChangeHandler.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,10 @@
use Crm\PaymentsModule\DataProvider\PaymentInvoiceProviderManager;
use Crm\PaymentsModule\Events\PaymentChangeStatusEvent;
use Crm\PaymentsModule\Repository\PaymentsRepository;
use Crm\ProductsModule\Manager\ProductManager;
use Crm\ProductsModule\PaymentItem\PaymentItemHelper;
use Crm\ProductsModule\PaymentItem\ProductPaymentItem;
use Crm\ProductsModule\Repository\OrdersRepository;
use Crm\ProductsModule\Repository\ProductPropertiesRepository;
use Crm\ProductsModule\Repository\ProductsRepository;
use Crm\UsersModule\Events\NotificationEvent;
use League\Event\AbstractListener;
use League\Event\Emitter;
Expand All @@ -23,38 +22,35 @@ class PaymentStatusChangeHandler extends AbstractListener
{
private $ordersRepository;

private $paymentsRepository;

private $paymentInvoiceProviderManager;

private $productPropertiesRepository;

private $productsRepository;

private $paymentItemHelper;

private $emitter;

private $applicationConfig;

private $productManager;

public function __construct(
OrdersRepository $ordersRepository,
PaymentsRepository $paymentsRepository,
PaymentInvoiceProviderManager $paymentInvoiceProviderManager,
ProductPropertiesRepository $productPropertiesRepository,
ProductsRepository $productsRepository,
PaymentItemHelper $paymentItemHelper,
Emitter $emitter,
ApplicationConfig $applicationConfig
ApplicationConfig $applicationConfig,
ProductManager $productManager
) {
$this->ordersRepository = $ordersRepository;
$this->paymentsRepository = $paymentsRepository;

$this->paymentInvoiceProviderManager = $paymentInvoiceProviderManager;
$this->productPropertiesRepository = $productPropertiesRepository;
$this->productsRepository = $productsRepository;
$this->paymentItemHelper = $paymentItemHelper;
$this->emitter = $emitter;
$this->applicationConfig = $applicationConfig;
$this->productManager = $productManager;
}

public function handle(EventInterface $event)
Expand Down Expand Up @@ -83,7 +79,9 @@ public function handle(EventInterface $event)
switch ($payment->status) {
case PaymentsRepository::STATUS_PAID:
$this->ordersRepository->update($order, ['status' => OrdersRepository::STATUS_PAID]);
$this->decreaseStock($payment);
$this->paymentItemHelper->unBundleProducts($payment, function ($product, $itemCount) {
$this->productManager->decreaseStock($product, $itemCount);
});

if ($order->billing_address_id !== null) {
$invoices = $this->paymentInvoiceProviderManager->getAttachments($payment);
Expand Down Expand Up @@ -112,7 +110,9 @@ public function handle(EventInterface $event)
case PaymentsRepository::STATUS_PREPAID:
if ($order->status === OrdersRepository::STATUS_NEW) {
$this->ordersRepository->update($order, ['status' => OrdersRepository::STATUS_PAID]);
$this->decreaseStock($payment);
$this->paymentItemHelper->unBundleProducts($payment, function ($product, $itemCount) {
$this->productManager->decreaseStock($product, $itemCount);
});
}

$this->attachAttachments($payment, $order, $templateCode, $sendHelpdeskEmail, $attachments);
Expand Down Expand Up @@ -188,12 +188,4 @@ private function sendMails(ActiveRow $payment, string $templateCode, array $para
));
}
}

private function decreaseStock(ActiveRow $payment)
{
foreach ($payment->related('payment_items')->where('type = ?', ProductPaymentItem::TYPE) as $paymentItem) {
$product = $paymentItem->product;
$this->productsRepository->decreaseStock($product, $paymentItem->count);
}
}
}
28 changes: 28 additions & 0 deletions src/models/Manager/ProductManager.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<?php

namespace Crm\ProductsModule\Manager;

use Nette\Database\Table\ActiveRow;
use Crm\ProductsModule\Repository\ProductsRepository;

class ProductManager
{
private $productsRepository;

public function __construct(ProductsRepository $productsRepository)
{
$this->productsRepository = $productsRepository;
}

public function decreaseStock(ActiveRow $product, int $itemCount): void
{
$this->productsRepository->decreaseStock($product, $itemCount);

foreach ($product->related('product_bundles', 'item_id') as $item) {
$mainProduct = $item->bundle;
if ($mainProduct->stock > $product->stock) {
$this->productsRepository->update($mainProduct, ['stock' => $product->stock]);
}
}
}
}
2 changes: 1 addition & 1 deletion src/models/Repository/ProductsRepository.php
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,7 @@ final public function productShopCountsDistributionList($fromlevel, $toLevel, $p
return $this->productShopCountsDistribution->distributionList($productId, $fromlevel, $toLevel);
}

final public function decreaseStock(IRow $product, $count = 1)
final public function decreaseStock(IRow &$product, $count = 1)
{
$this->update($product, ['stock-=' => $count]);
}
Expand Down
120 changes: 120 additions & 0 deletions src/tests/ProductManagerTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
<?php

namespace Crm\ProductsModule\Tests;

use Crm\ApplicationModule\ActiveRow;
use Crm\ApplicationModule\Tests\DatabaseTestCase;
use Crm\ProductsModule\Manager\ProductManager;
use Crm\ProductsModule\Repository\ProductBundlesRepository;
use Crm\ProductsModule\Repository\ProductsRepository;

class ProductManagerTest extends DatabaseTestCase
{
/** @var ProductsRepository */
private $productsRepository;

/** @var ProductBundlesRepository */
private $productBundlesRepository;

public function setUp(): void
{
parent::setUp();

$this->productsRepository = $this->getRepository(ProductsRepository::class);
$this->productBundlesRepository = $this->getRepository(ProductBundlesRepository::class);
}

protected function requiredRepositories(): array
{
return [
ProductsRepository::class,
ProductBundlesRepository::class
];
}

protected function requiredSeeders(): array
{
return [
];
}

public function testDecreaseStockSimpleProduct(): void
{
/** @var ActiveRow $product */
$product = $this->insertProduct();

$productManager = new ProductManager($this->productsRepository);

$productManager->decreaseStock($product, 1);
$product = $this->productsRepository->find($product->id);
$this->assertEquals(9, $product->stock);

$productManager->decreaseStock($product, 3);
$product = $this->productsRepository->find($product->id);
$this->assertEquals(6, $product->stock);
}

public function testDecreaseStockBundleProducts(): void
{
$productManager = new ProductManager($this->productsRepository);

/** @var ActiveRow $mainProduct */
$mainProduct = $this->insertProduct(10);
/** @var ActiveRow $bundleProduct */
$bundleProduct = $this->insertProduct(7);

$this->productBundlesRepository->add($mainProduct->id, $bundleProduct->id);

$productManager->decreaseStock($bundleProduct, 3);

$this->assertEquals(4, $this->productsRepository->find($mainProduct->id)->stock);
$this->assertEquals(4, $this->productsRepository->find($bundleProduct->id)->stock);

/** @var ActiveRow $mainProduct */
$mainProduct = $this->insertProduct(4);
/** @var ActiveRow $bundleProduct1 */
$bundleProduct = $this->insertProduct(10);

$this->productBundlesRepository->add($mainProduct->id, $bundleProduct->id);

$productManager->decreaseStock($bundleProduct, 3);

$this->assertEquals(4, $this->productsRepository->find($mainProduct->id)->stock);
$this->assertEquals(7, $this->productsRepository->find($bundleProduct->id)->stock);

/** @var ActiveRow $mainProduct */
$mainProduct = $this->insertProduct(10);
/** @var ActiveRow $bundleProduct1 */
$bundleProduct1 = $this->insertProduct(10);
/** @var ActiveRow $bundleProduct2 */
$bundleProduct2 = $this->insertProduct(14);

$this->productBundlesRepository->add($mainProduct->id, $bundleProduct1->id);
$this->productBundlesRepository->add($mainProduct->id, $bundleProduct2->id);

$productManager->decreaseStock($bundleProduct1, 2);
$productManager->decreaseStock($bundleProduct2, 2);

$this->assertEquals(8, $this->productsRepository->find($mainProduct->id)->stock);
$this->assertEquals(8, $this->productsRepository->find($bundleProduct1->id)->stock);
$this->assertEquals(12, $this->productsRepository->find($bundleProduct2->id)->stock);
}

private function insertProduct(int $stock = 10)
{
return $this->productsRepository->insert([
'name' => 'test1',
'code' => 'test1_code',
'price' => 10.0,
'vat' => 19,
'user_label' => 'user_label',
'bundle' => 0,
'shop' => 1,
'visible' => 1,
'stored' => 1,
'stock' => $stock,
'created_at' => new \DateTime(),
'modified_at' => new \DateTime()
]);
}
}

0 comments on commit ec440fc

Please sign in to comment.