Skip to content
This repository has been archived by the owner on Nov 13, 2021. It is now read-only.

Commit

Permalink
Merge branch '3.12.x' of https://github.com/treolabs/treopim into 3.12.x
Browse files Browse the repository at this point in the history
  • Loading branch information
rratsun committed Mar 15, 2020
2 parents 233dc94 + 09bf50d commit eff616a
Show file tree
Hide file tree
Showing 7 changed files with 115 additions and 106 deletions.
43 changes: 4 additions & 39 deletions app/Listeners/ProductAttributeValueEntity.php
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ public function beforeSave(Event $event)
throw new BadRequest($this->exception('Product and Attribute cannot be empty'));
}

if (!$entity->isNew() && !empty($entity->get('productFamilyAttribute'))) {
if (!$entity->isNew() && !empty($entity->get('productFamilyAttribute')) && empty($entity->skipPfValidation)) {
if ($entity->isAttributeChanged('scope')
|| $entity->isAttributeChanged('isRequired')
|| $entity->isAttributeChanged('channelsIds')
Expand All @@ -74,7 +74,7 @@ public function beforeSave(Event $event)
if (!$this->isUnique($entity)) {
throw new BadRequest(
sprintf(
$this->exception('Such product attribute \'%s\' already exists'),
'Such product attribute \'%s\' already exists',
$entity->get('attribute')->get('name')
)
);
Expand Down Expand Up @@ -147,43 +147,7 @@ public function beforeRemove(Event $event)
*/
protected function isUnique(Entity $entity): bool
{
// prepare count
$count = 0;

if ($entity->get('scope') == 'Global') {
$count = $this
->getEntityManager()
->getRepository('ProductAttributeValue')
->where(
[
'id!=' => $entity->get('id'),
'productId' => $entity->get('productId'),
'attributeId' => $entity->get('attributeId'),
'scope' => 'Global',
]
)
->count();
}

if ($entity->get('scope') == 'Channel') {
$count = $this
->getEntityManager()
->getRepository('ProductAttributeValue')
->distinct()
->join('channels')
->where(
[
'id!=' => $entity->get('id'),
'productId' => $entity->get('productId'),
'attributeId' => $entity->get('attributeId'),
'scope' => 'Channel',
'channels.id' => $entity->get('channelsIds'),
]
)
->count();
}

return empty($count);
return empty($this->getEntityManager()->getRepository('ProductAttributeValue')->findCopy($entity));
}

/**
Expand Down Expand Up @@ -262,6 +226,7 @@ protected function exception(string $key): string

/**
* @param ProductAttributeValue $attributeValue
*
* @return void
* @throws Error
*/
Expand Down
102 changes: 62 additions & 40 deletions app/Listeners/ProductEntity.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
namespace Pim\Listeners;

use Espo\Core\Exceptions\BadRequest;
use Espo\Core\Utils\Util;
use Espo\ORM\Entity;
use Treo\Core\EventManager\Event;
use Pim\Entities\Channel;
Expand Down Expand Up @@ -58,9 +59,6 @@ public function beforeSave(Event $event)
if (!$entity->isNew() && $entity->isAttributeChanged('type')) {
throw new BadRequest($this->exception('You can\'t change field of Type'));
}
if ($entity->isAttributeChanged('productFamilyId') && !$entity->isNew()) {
throw new BadRequest($this->exception('You can\'t change Product Family in Product'));
}
}

/**
Expand All @@ -74,10 +72,9 @@ public function afterSave(Event $event)
// get options
$options = $event->getArgument('options');

$skipUpdate = empty($entity->skipUpdateProductAttributesByProductFamily)
&& empty($options['skipProductFamilyHook']);
$skipUpdate = empty($entity->skipUpdateProductAttributesByProductFamily) && empty($options['skipProductFamilyHook']);

if ($skipUpdate && !empty($entity->get('productFamily')) && empty($entity->isDuplicate)) {
if ($skipUpdate && empty($entity->isDuplicate)) {
$this->updateProductAttributesByProductFamily($entity, $options);
}
}
Expand All @@ -88,13 +85,15 @@ public function afterSave(Event $event)
public function afterUnrelate(Event $event)
{
//set default value in isActive for channel after deleted link
if($event->getArgument('relationName') == 'channels' && $event->getArgument('foreign') instanceof Channel) {
if ($event->getArgument('relationName') == 'channels' && $event->getArgument('foreign') instanceof Channel) {
$dataEntity = new \StdClass();
$dataEntity->entityName = 'Product';
$dataEntity->entityId = $event->getArgument('entity')->get('id');
$dataEntity->value = (int)!empty($event
$dataEntity->value = (int)!empty(
$event
->getArgument('entity')
->getRelations()['channels']['additionalColumns']['isActive']['default']);
->getRelations()['channels']['additionalColumns']['isActive']['default']
);

$this
->getService('Channel')
Expand Down Expand Up @@ -198,56 +197,79 @@ protected function isProductCategoriesInSelectedCatalog(Entity $entity): bool

/**
* @param Entity $entity
* @param array $options
* @param array $options
*
* @return bool
*
* @throws \Espo\Core\Exceptions\Error
*/
protected function updateProductAttributesByProductFamily(Entity $entity, array $options): bool
{
// get product family
$productFamily = $entity->get('productFamily');
if (!$entity->isNew() && $entity->isAttributeChanged('productFamilyId')) {
// unlink attributes from old product family
$this
->getEntityManager()
->nativeQuery(
"UPDATE product_attribute_value SET product_family_attribute_id=NULL WHERE product_id=:productId AND product_family_attribute_id IS NOT NULL AND deleted=0",
['productId' => $entity->get('id')]
);
}

if (empty($productFamily = $entity->get('productFamily'))) {
return true;
}

// get product family attributes
$productFamilyAttributes = $productFamily->get('productFamilyAttributes');

if ($entity->isNew()) {
if (count($productFamilyAttributes) > 0) {
foreach ($productFamilyAttributes as $productFamilyAttribute) {
// create
$productAttributeValue = $this->getEntityManager()->getEntity('ProductAttributeValue');
$productAttributeValue->set(
[
'productId' => $entity->get('id'),
'attributeId' => $productFamilyAttribute->get('attributeId'),
'productFamilyAttributeId' => $productFamilyAttribute->get('id'),
'isRequired' => $productFamilyAttribute->get('isRequired'),
'scope' => $productFamilyAttribute->get('scope')
]
);
// save
if (count($productFamilyAttributes) > 0) {
/** @var \Pim\Repositories\ProductAttributeValue $repository */
$repository = $this->getEntityManager()->getRepository('ProductAttributeValue');

foreach ($productFamilyAttributes as $productFamilyAttribute) {
// create
$productAttributeValue = $repository->get();
$productAttributeValue->set(
[
'productId' => $entity->get('id'),
'attributeId' => $productFamilyAttribute->get('attributeId'),
'productFamilyAttributeId' => $productFamilyAttribute->get('id'),
'isRequired' => $productFamilyAttribute->get('isRequired'),
'scope' => $productFamilyAttribute->get('scope')
]
);

// relate channels if it needs
if ($productFamilyAttribute->get('scope') == 'Channel') {
$channels = $productFamilyAttribute->get('channels');
if (count($channels) > 0) {
$productAttributeValue->set('channelsIds', array_column($channels->toArray(), 'id'));
}
}

// save
try {
$this->getEntityManager()->saveEntity($productAttributeValue);
} catch (BadRequest $e) {
$message = sprintf('Such product attribute \'%s\' already exists', $productFamilyAttribute->get('attribute')->get('name'));
if ($message == $e->getMessage()) {
$copy = $repository->findCopy($productAttributeValue);
$copy->set('productFamilyAttributeId', $productFamilyAttribute->get('id'));
$copy->set('isRequired', $productAttributeValue->get('isRequired'));

// relate channels if it needs
if ($productFamilyAttribute->get('scope') == 'Channel') {
$channels = $productFamilyAttribute->get('channels');
if (count($channels) > 0) {
foreach ($channels as $channel) {
$this
->getEntityManager()
->getRepository('ProductAttributeValue')
->relate($productAttributeValue, 'channels', $channel);
}
if ($productFamilyAttribute->get('scope') == 'Channel') {
$copy->set('channelsIds', $productAttributeValue->get('channelsIds'));
}

$copy->skipPfValidation = true;

$this->getEntityManager()->saveEntity($copy);
}
}
}

return true;
}

return false;
return true;
}

/**
Expand Down
42 changes: 42 additions & 0 deletions app/Repositories/ProductAttributeValue.php
Original file line number Diff line number Diff line change
Expand Up @@ -92,4 +92,46 @@ public function beforeSave(Entity $entity, array $options = [])
}
}
}

/**
* @param Entity $entity
*
* @return Entity|null
*/
public function findCopy(Entity $entity): ?Entity
{
// prepare copy
$copy = null;

if ($entity->get('scope') == 'Global') {
$copy = $this
->where(
[
'id!=' => $entity->get('id'),
'productId' => $entity->get('productId'),
'attributeId' => $entity->get('attributeId'),
'scope' => 'Global',
]
)
->findOne();
}

if ($entity->get('scope') == 'Channel') {
$copy = $this
->distinct()
->join('channels')
->where(
[
'id!=' => $entity->get('id'),
'productId' => $entity->get('productId'),
'attributeId' => $entity->get('attributeId'),
'scope' => 'Channel',
'channels.id' => $entity->get('channelsIds'),
]
)
->findOne();
}

return $copy;
}
}
3 changes: 1 addition & 2 deletions app/Resources/i18n/de_DE/ProductAttributeValue.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@
},
"exceptions": {
"You have no ACL rights to read attribute values": "Sie haben keine ACL-Rechte zum Lesen von Attributwerten",
"You can't change product in attribute from Product Family": "Sie können das Produkt im Attribut der Produktfamilie nicht ändern",
"Such product attribute '%s' already exists": "Ein solches Produktattribut '%s' ist bereits vorhanden"
"You can't change product in attribute from Product Family": "Sie können das Produkt im Attribut der Produktfamilie nicht ändern"
}
}
3 changes: 1 addition & 2 deletions app/Resources/i18n/en_US/ProductAttributeValue.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@
},
"exceptions": {
"You have no ACL rights to read attribute values": "You have no ACL rights to read attribute values",
"You can't change product in attribute from Product Family": "You can't change product in attribute from ProductFamily",
"Such product attribute '%s' already exists": "Such product attribute '%s' already exists"
"You can't change product in attribute from Product Family": "You can't change product in attribute from ProductFamily"
}
}
23 changes: 0 additions & 23 deletions app/Resources/metadata/clientDefs/Product.json
Original file line number Diff line number Diff line change
Expand Up @@ -131,29 +131,6 @@
}
]
}
},
"productFamily": {
"readOnly": {
"conditionGroup": [
{
"type": "isNotEmpty",
"attribute": "id"
}
]
},
"required": {
"conditionGroup": [
{
"type": "notEquals",
"attribute": "type",
"value": "productVariant"
},
{
"type": "isEmpty",
"attribute": "id"
}
]
}
}
}
}
Expand Down
5 changes: 5 additions & 0 deletions client/modules/pim/src/views/product/record/detail.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,11 @@ Espo.define('pim:views/product/record/detail', 'pim:views/record/detail',
this.isCatalogTreePanel = true;
this.setupCatalogTreePanel();
}

// refresh attributes panel after any saving
this.listenTo(this.model, 'after:save', () => {
$(".panel-productAttributeValues button[data-action='refresh']").click();
});
},

setupCatalogTreePanel() {
Expand Down

0 comments on commit eff616a

Please sign in to comment.