Skip to content

Commit

Permalink
OXDEV-5103 Low stock article message
Browse files Browse the repository at this point in the history
  • Loading branch information
AshrafOxid committed Apr 8, 2024
1 parent 0b4454b commit 842b523
Show file tree
Hide file tree
Showing 11 changed files with 395 additions and 77 deletions.
2 changes: 1 addition & 1 deletion CHANGELOG-7.2.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
## v7.2.0 - unreleased

### Added
-
- Set custom product low stock label [#0004401](https://bugs.oxid-esales.com/view.php?id=4401)

### Deprecated
-
Expand Down
67 changes: 47 additions & 20 deletions source/Application/Model/Article.php
Original file line number Diff line number Diff line change
Expand Up @@ -164,9 +164,11 @@ class Article extends \OxidEsales\Eshop\Core\Model\MultiLanguageModel implements

/**
* $_fPricePerUnit holds price per unit value in active shop currency.
* $_fPricePerUnit is calculated from \OxidEsales\Eshop\Application\Model\Article::oxarticles__oxunitquantity->value
* and from \OxidEsales\Eshop\Application\Model\Article::oxarticles__oxuniname->value. If either one of these values is empty then $_fPricePerUnit is not calculated.
* Example: In case when product price is 10 EUR and product quantity is 0.5 (liters) then $_fPricePerUnit would be 20,00
* $_fPricePerUnit is calculated from
* \OxidEsales\Eshop\Application\Model\Article::oxarticles__oxunitquantity->value
* and from \OxidEsales\Eshop\Application\Model\Article::oxarticles__oxuniname->value. If either one of these
* values is empty then $_fPricePerUnit is not calculated. Example: In case when product price is 10 EUR and
* product quantity is 0.5 (liters) then $_fPricePerUnit would be 20,00
*/
protected $_fPricePerUnit = null;

Expand Down Expand Up @@ -469,7 +471,8 @@ class Article extends \OxidEsales\Eshop\Core\Model\MultiLanguageModel implements
* Constructor, sets shop ID for article (\OxidEsales\Eshop\Core\Config::getShopId()),
* initiates parent constructor (parent::oxI18n()).
*
* @param array $aParams The array of names and values of oxArticle instance properties to be set on object instantiation
* @param array $aParams The array of names and values of oxArticle instance properties to be set on object
* instantiation
*/
public function __construct($aParams = null)
{
Expand Down Expand Up @@ -709,7 +712,8 @@ protected function createSqlActiveSnippet($forceCoreTable)
}

/**
* Assign condition setter. In case article assignment is skipped ($_blSkipAssign = true), it does not perform additional
* Assign condition setter. In case article assignment is skipped ($_blSkipAssign = true), it does not perform
* additional
*
* @param bool $blSkipAssign Whether to skip assign process for the article
*/
Expand Down Expand Up @@ -1522,7 +1526,8 @@ public function hasDownloadableAgreement()
*
* @param array $aFilterIds ids of active selections [optional]
* @param string $sActVariantId active variant id [optional]
* @param int $iLimit limit variant lists count (if non zero, return limited number of multidimensional variant selections)
* @param int $iLimit limit variant lists count (if non zero, return limited number of multidimensional
* variant selections)
*
* @return array
*/
Expand Down Expand Up @@ -1613,7 +1618,8 @@ public function getSelections($iLimit = null, $aFilter = null)
/**
* Returns variant list (list contains oxArticle objects)
*
* @param bool $blRemoveNotOrderables if true, removes from list not orderable articles, which are out of stock [optional]
* @param bool $blRemoveNotOrderables if true, removes from list not orderable articles, which are out of stock
* [optional]
* @param bool $blForceCoreTable if true forces core table use, default is false [optional]
*
* @return \OxidEsales\Eshop\Application\Model\ArticleList
Expand All @@ -1625,7 +1631,8 @@ public function getFullVariants($blRemoveNotOrderables = true, $blForceCoreTable

/**
* Collects and returns article variants.
* Note: Only active variants are returned by this method. If you need full variant list use \OxidEsales\Eshop\Application\Model\Article::getAdminVariants()
* Note: Only active variants are returned by this method. If you need full variant list use
* \OxidEsales\Eshop\Application\Model\Article::getAdminVariants()
*
* @param bool $blRemoveNotOrderables if true, removes from list not orderable articles, which are out of stock
* @param bool $blForceCoreTable if true forces core table use, default is false [optional]
Expand Down Expand Up @@ -2406,7 +2413,8 @@ public function getPictureGallery()
* This function is triggered whenever article is saved or deleted or after the stock is changed.
* Originally we need to update the oxstock for possible article parent in case parent is not buyable
* Plus you may want to extend this function to update some extended information.
* Call \OxidEsales\Eshop\Application\Model\Article::onChange($sAction, $sOXID) with ID parameter when changes are executed over SQL.
* Call \OxidEsales\Eshop\Application\Model\Article::onChange($sAction, $sOXID) with ID parameter when changes are
* executed over SQL.
* (or use module class instead of oxArticle if such exists)
*
* @param string $action Action constant
Expand Down Expand Up @@ -3549,8 +3557,10 @@ public function hasAmountPrice()
/**
* Loads and returns variants list.
*
* @param bool $loadSimpleVariants if parameter $blSimple - list will be filled with oxSimpleVariant objects, else - oxArticle
* @param bool $blRemoveNotOrderables if true, removes from list not orderable articles, which are out of stock [optional]
* @param bool $loadSimpleVariants if parameter $blSimple - list will be filled with oxSimpleVariant
* objects, else - oxArticle
* @param bool $blRemoveNotOrderables if true, removes from list not orderable articles, which are out of
* stock [optional]
* @param bool|null $forceCoreTableUsage if true forces core table use, default is false [optional]
*
* @return array|\OxidEsales\Eshop\Application\Model\SimpleVariantList|\OxidEsales\Eshop\Application\Model\ArticleList
Expand Down Expand Up @@ -3697,7 +3707,8 @@ protected function getActiveCategorySelectSnippet()
* Calculates price of article (adds taxes, currency and discounts).
*
* @param \OxidEsales\Eshop\Core\Price $oPrice price object
* @param double $dVat vat value, optional, if passed, bypasses "bl_perfCalcVatOnlyForBasketOrder" config value
* @param double $dVat vat value, optional, if passed, bypasses
* "bl_perfCalcVatOnlyForBasketOrder" config value
*
* @return \OxidEsales\Eshop\Core\Price
*/
Expand Down Expand Up @@ -4482,18 +4493,14 @@ protected function assignStock()
$this->oxarticles__oxstockflag->value != 4
) {
//ORANGE light
$iStock = $this->oxarticles__oxstock->value;

if ($this->_blNotBuyableParent) {
$iStock = $this->oxarticles__oxvarstock->value;
}
$stock = $this->getAvailableStock();

if ($iStock <= $myConfig->getConfigParam('sStockWarningLimit') && $iStock > 0) {
if ($stock > 0 && $this->isLowStock()) {
$this->_iStockStatus = 1;
}

//RED light
if ($iStock <= 0) {
if ($stock <= 0) {
$this->_iStockStatus = -1;
}
}
Expand Down Expand Up @@ -5255,7 +5262,8 @@ protected function getLoadVariantsQuery($blRemoveNotOrderables, $forceCoreTableU
* Set needed parameters to article list object like language.
*
* @param \OxidEsales\Eshop\Core\Model\BaseModel $baseObject article list template object.
* @param bool|null $forceCoreTableUsage if true forces core table use, default is false [optional]
* @param bool|null $forceCoreTableUsage if true forces core table use, default is
* false [optional]
*/
protected function updateVariantsBaseObject($baseObject, $forceCoreTableUsage = null)
{
Expand All @@ -5269,4 +5277,23 @@ protected function updateManufacturerBeforeLoading($oManufacturer)
{
$oManufacturer->setReadOnly(true);
}

private function getAvailableStock(): int
{
return (int) ($this->_blNotBuyableParent
? $this->oxarticles__oxvarstock->value
: $this->oxarticles__oxstock->value);
}

private function isLowStock(): bool
{
return $this->getAvailableStock() <= $this->getLowStockThreshold();
}

private function getLowStockThreshold(): int
{
return (int) ($this->oxarticles__oxlowstockactive->value ?
$this->oxarticles__oxremindamount->value :
Registry::getConfig()->getConfigParam('sStockWarningLimit'));
}
}
16 changes: 6 additions & 10 deletions source/Core/ViewConfig.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
use OxidEsales\Eshop\Core\Exception\FileException;
use OxidEsales\Eshop\Core\Registry;
use OxidEsales\Eshop\Core\Str;
use OxidEsales\EshopCommunity\Core\Exception\ShopException;
use OxidEsales\EshopCommunity\Internal\Framework\Module\Path\ModuleAssetsPathResolverBridgeInterface;
use OxidEsales\EshopCommunity\Internal\Framework\Module\Setup\Bridge\ModuleActivationBridgeInterface;
use OxidEsales\Facts\Facts;
Expand Down Expand Up @@ -984,26 +985,21 @@ public function getNavFormParams()
return $sParams;
}

/**
* Returns config param "blStockOnDefaultMessage" value
*
* @return string
*/
public function getStockOnDefaultMessage()
{
return Registry::getConfig()->getConfigParam('blStockOnDefaultMessage');
}

/**
* Returns config param "blStockOnDefaultMessage" value
*
* @return string
*/
public function getStockOffDefaultMessage()
{
return Registry::getConfig()->getConfigParam('blStockOffDefaultMessage');
}

public function getStockLowDefaultMessage(): bool
{
return (bool) Registry::getConfig()->getConfigParam('blStockLowDefaultMessage');
}

/**
* Returns shop version defined in view
*
Expand Down
1 change: 1 addition & 0 deletions source/Internal/Setup/Database/Sql/initial_data.sql
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ INSERT INTO `oxconfig` (`OXID`, `OXSHOPID`, `OXMODULE`, `OXVARNAME`, `OXVARTYPE`
('2a944b2cc31311e8957700163e4021bf', 1, '', 'includeProductReviewLinksInEmail', 'bool', ''),
('2ca4277aa49a5bd27.44511187', 1, '', 'blStockOnDefaultMessage', 'bool', '1'),
('2ca4277aa49a634f8.76432326', 1, '', 'blStockOffDefaultMessage', 'bool', '1'),
('0282a93ba014458d7a9249e5aef1a8eb', 1, '', 'blStockLowDefaultMessage', 'bool', '1'),
('2e4452b5763e03c74.88240349', 1, '', 'blDisableDublArtOnCopy', 'bool', '1'),
('32ddeaf2694e06b47b6ff74eafc69b65', 1, '', 'sParcelService', 'str', 'http://www.dpd.de/cgi-bin/delistrack?typ=1&amp;lang=de&amp;pknr=##ID##'),
('33341949f476b65e8.17282442', 1, '', 'iAttributesPercent', 'str', '70'),
Expand Down
1 change: 1 addition & 0 deletions source/Setup/Sql/initial_data.sql
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ INSERT INTO `oxconfig` (`OXID`, `OXSHOPID`, `OXMODULE`, `OXVARNAME`, `OXVARTYPE`
('2a944b2cc31311e8957700163e4021bf', 1, '', 'includeProductReviewLinksInEmail', 'bool', ''),
('2ca4277aa49a5bd27.44511187', 1, '', 'blStockOnDefaultMessage', 'bool', '1'),
('2ca4277aa49a634f8.76432326', 1, '', 'blStockOffDefaultMessage', 'bool', '1'),
('0282a93ba014458d7a9249e5aef1a8eb', 1, '', 'blStockLowDefaultMessage', 'bool', '1'),
('2e4452b5763e03c74.88240349', 1, '', 'blDisableDublArtOnCopy', 'bool', '1'),
('32ddeaf2694e06b47b6ff74eafc69b65', 1, '', 'sParcelService', 'str', 'http://www.dpd.de/cgi-bin/delistrack?typ=1&amp;lang=de&amp;pknr=##ID##'),
('33341949f476b65e8.17282442', 1, '', 'iAttributesPercent', 'str', '70'),
Expand Down
49 changes: 49 additions & 0 deletions source/migration/data/Version20231128113123.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
<?php

/**
* Copyright © OXID eSales AG. All rights reserved.
* See LICENSE file for license details.
*/

declare(strict_types=1);

namespace OxidEsales\EshopCommunity\Migrations;

use Doctrine\DBAL\Schema\Schema;
use Doctrine\Migrations\AbstractMigration;

final class Version20231128113123 extends AbstractMigration
{
public function getDescription(): string
{
return 'Add Low Stock Message';
}

public function up(Schema $schema): void
{
$this->addSql(
'ALTER TABLE `oxarticles` ADD column `OXLOWSTOCKTEXT` VARCHAR(255) NOT NULL default "" COMMENT '
. '"Message, which is shown if the article is in low stock (multilanguage)" AFTER `OXSTOCKTEXT`'
);
$this->addSql(
'ALTER TABLE `oxarticles` ADD column `OXLOWSTOCKTEXT_1` VARCHAR(255) NOT NULL default "" AFTER '
. '`OXSTOCKTEXT_3`'
);
$this->addSql(
'ALTER TABLE `oxarticles` ADD column `OXLOWSTOCKTEXT_2` VARCHAR(255) NOT NULL default "" AFTER '
. '`OXLOWSTOCKTEXT_1`'
);
$this->addSql(
'ALTER TABLE `oxarticles` ADD column `OXLOWSTOCKTEXT_3` VARCHAR(255) NOT NULL default "" AFTER '
. '`OXLOWSTOCKTEXT_2`'
);
$this->addSql(
'ALTER TABLE `oxarticles` ADD column `OXLOWSTOCKACTIVE` TINYINT(1) AFTER '
. '`OXLOWSTOCKTEXT`'
);
}

public function down(Schema $schema): void
{
}
}
40 changes: 40 additions & 0 deletions tests/Codeception/Acceptance/Admin/MasterCoreStockSettingsCest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
<?php

/**
* Copyright © OXID eSales AG. All rights reserved.
* See LICENSE file for license details.
*/

declare(strict_types=1);

namespace Acceptance\Admin;

use Codeception\Attribute\Group;
use OxidEsales\EshopCommunity\Tests\Codeception\Support\AcceptanceTester;

#[Group('admin', 'core', 'stock')]
final class MasterCoreStockSettingsCest
{
public function setActiveCategoryAtStart(AcceptanceTester $I): void
{
$I->wantToTest('Activate and deactivate default stock message');

$adminPanel = $I->loginAdmin();
$coreSettings = $adminPanel->openCoreSettings();
$settingsTab = $coreSettings->openSettingsTab();

$I->amGoingTo('Check Low stock default message option');
$stockDropdown = $settingsTab->openStockSettings();
$stockDropdown->checkLowStockMessageOption();
$settingsTab->save();

$stockDropdown->seeLowStockMessageSelected();

$I->amGoingTo('Uncheck Low stock default message option');
$stockDropdown = $settingsTab->openStockSettings();
$stockDropdown->uncheckLowStockMessageOption();
$settingsTab->save();

$stockDropdown->dontSeeLowStockMessageSelected();
}
}
48 changes: 48 additions & 0 deletions tests/Codeception/Acceptance/Admin/ProductStockTestCest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
<?php

/**
* Copyright © OXID eSales AG. All rights reserved.
* See LICENSE file for license details.
*/

declare(strict_types=1);

namespace Acceptance\Admin;

use Codeception\Attribute\Group;
use OxidEsales\EshopCommunity\Tests\Codeception\Support\AcceptanceTester;

#[Group('admin', 'product', 'stock')]
final class ProductStockTestCest
{
private string $productID = '1000';

public function setLowStockMessage(AcceptanceTester $I): void
{
$I->wantToTest('Set low stock message for product');

$productsMainPage = $I->loginAdmin()->openProducts();
$productMainTab = $productsMainPage->find($productsMainPage->searchNumberInput, $this->productID);
$stockTab = $productMainTab->openStockTab();
$lowStockMessage = 'This product is in low stock' . $this->productID;
$remindAmount = 20.5;

$I->amGoingTo('Set and activate low stock message');

$stockTab->checkLowStockMessageOption()
->setRemindAmountValue($remindAmount)
->setLowStockMessageValue($lowStockMessage)
->save();

$stockTab->seeRemindAmountValue($remindAmount);
$stockTab->seeLowStockMessageSelected();
$stockTab->seeLowStockMessageValue($lowStockMessage);

$I->amGoingTo('Disable low stock message');

$stockTab->uncheckLowStockMessageOption()
->save();

$stockTab->dontSeeLowStockMessageSelected();
}
}
Loading

0 comments on commit 842b523

Please sign in to comment.