first commit
This commit is contained in:
@@ -0,0 +1,98 @@
|
||||
<?php
|
||||
|
||||
namespace KupShop\ProductGiftsBundle\Admin\Tabs;
|
||||
|
||||
use KupShop\AdminBundle\Admin\WindowTab;
|
||||
|
||||
class ProductGiftsTab extends WindowTab
|
||||
{
|
||||
protected $title = 'flapGifts';
|
||||
|
||||
protected $template = 'ProductGiftsTab.tpl';
|
||||
|
||||
public static function getTypes()
|
||||
{
|
||||
return [
|
||||
'products' => 1,
|
||||
];
|
||||
}
|
||||
|
||||
public function getLabel()
|
||||
{
|
||||
return 'Dárky';
|
||||
}
|
||||
|
||||
public function getVars($smarty_tpl_vars)
|
||||
{
|
||||
$product = $smarty_tpl_vars['body']->value['product'] ?? false;
|
||||
if ($product) {
|
||||
$product->fetchGifts(true);
|
||||
foreach ($product->gifts ?: [] as &$gift) {
|
||||
$gift->fetchImages('admin');
|
||||
$gift->fetchVariations();
|
||||
$variations = [];
|
||||
if (!empty($gift['variations']['variations'])) {
|
||||
foreach ($gift['variations']['variations'] as $variation) {
|
||||
$selected = false;
|
||||
if ($variation['id'] == $gift['selected_variation']) {
|
||||
$selected = true;
|
||||
}
|
||||
$variations[] = ['label' => $variation['title'], 'value' => $variation['id'], 'selected' => $selected];
|
||||
}
|
||||
}
|
||||
$gift['variations'] = $variations;
|
||||
}
|
||||
}
|
||||
|
||||
return $smarty_tpl_vars;
|
||||
}
|
||||
|
||||
public function handleUpdate()
|
||||
{
|
||||
parent::handleUpdate();
|
||||
|
||||
$data = $this->getData();
|
||||
$gifts = getVal('gifts', $data, []);
|
||||
|
||||
foreach ($gifts as $id => $gift) {
|
||||
$gift['id_product_gift'] = intval($gift['id_product_gift']);
|
||||
$gift['id_product'] = $this->getID();
|
||||
if (empty($gift['id_variation_gift'])) {
|
||||
$gift['id_variation_gift'] = null;
|
||||
}
|
||||
$this->prepareNull($gift['price']);
|
||||
|
||||
if (!ctype_digit($gift['pieces']) || $gift['pieces'] < 1) {
|
||||
$gift['pieces'] = 1;
|
||||
}
|
||||
|
||||
if ($this->isDuplicate() && $id > 0) {
|
||||
$id = -99;
|
||||
}
|
||||
|
||||
if (!empty($gift['delete']) || !$id || $gift['id_product_gift'] <= 0) {
|
||||
if ($id > 0) {
|
||||
$this->deleteSQL('products_gifts', $this->filterFields($gift, ['id_product', 'id_product_gift']));
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($id < 0) {
|
||||
try {
|
||||
$this->insertSQL('products_gifts', $gift);
|
||||
} catch (\Doctrine\DBAL\DBALException $e) {
|
||||
}
|
||||
} else {
|
||||
$this->updateSQL('products_gifts', $gift, $this->filterFields($gift, ['id_product', 'id_product_gift']));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function isVisible()
|
||||
{
|
||||
if ($this->getAction() != 'add') {
|
||||
return parent::isVisible(); // TODO: Change the autogenerated stub
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,98 @@
|
||||
<div id="flapGifts" class="tab-pane fade in boxFlex">
|
||||
<div id="gifts">
|
||||
<div class="row">
|
||||
<div class="form-group">
|
||||
<div class="col-md-2 control-label"><label>{'productGiftsSelectOption'|translate}</label></div>
|
||||
<div class="col-md-1">
|
||||
<input
|
||||
type="number"
|
||||
class="form-control input-sm autocomplete-control"
|
||||
name="data[data][gifts_settings][select_count]"
|
||||
placeholder="1"
|
||||
value="{$body.data.data.gifts_settings.select_count}">
|
||||
</div>
|
||||
<div class="col-md-1">
|
||||
{print_toggle name="data][gifts_settings][select_active]" value=$body.data.data.gifts_settings.select_active}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-11">
|
||||
<h1 class="h4 main-panel-title">{'productGifts'|translate:'products'}</h1>
|
||||
</div>
|
||||
<div class="col-md-1">
|
||||
<a href="javascript:help('gifts');"><i class="btn btn-info bi bi-question-circle"></i></a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row bottom-space">
|
||||
<div class="col-md-4">
|
||||
<input type="text" data-autocomplete-search="products_gifts" autocomplete="off" class="form-control input-sm autocomplete-control" name="addProduct"
|
||||
placeholder="{'addGiftsProduct'|translate}">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div data-autocomplete-items="products_gifts" class="panel-group panel-group-lists" id="gifts">
|
||||
|
||||
<script id="multiselectAutocomplete_gifts" type="text/x-dot-template">
|
||||
{literal}
|
||||
{{~it.items :item :index}}
|
||||
<div class="panel autocomplete-results" data-form-item="{{=item.id}}" style="display:none">
|
||||
<div class="panel-body">
|
||||
<input type="hidden" class="form-control input-sm" name="{/literal}{$tab.prefix}{literal}[gifts][{{? item.index }}-{{=item.index}}{{??}}{{=index + 1}}{{?}}][id_product_gift]"
|
||||
value="{{=item.id}}">
|
||||
{{? item.image}}
|
||||
<img src="{{=item.image.src}}" alt="{{=item.image.descr}}">
|
||||
{{?}}
|
||||
<p class="product-title">
|
||||
<a href="javascript:nw('product', '{{=item.id}}')">{{=item.title}}</a><br>
|
||||
<small>Kód: {{=item.code}} | Skladem: {{=item.inStore}} ks</small>
|
||||
</p>
|
||||
<p>
|
||||
{{? item.variations}}
|
||||
<select class="selecter" name="{/literal}{$tab.prefix}{literal}[gifts][{{? item.index }}-{{=item.index}}{{??}}{{=index + 1}}{{?}}][id_variation_gift]">
|
||||
<option value="">Neurčovat variantu</option>
|
||||
{{~item.variations :variation :indexVariation}}
|
||||
<option value="{{=variation.value}}" {{? variation.selected}}selected{{?}}>{{=variation.label}}</option>
|
||||
{{~}}
|
||||
</select>
|
||||
{{?}}
|
||||
</p>
|
||||
<p>
|
||||
<div class="input-group" style="width:150px">
|
||||
<input class="form-control input-sm" name="{/literal}{$tab.prefix}{literal}[gifts][{{? item.index }}-{{=item.index}}{{??}}{{=index + 1}}{{?}}][pieces]"
|
||||
value="{{? item.gift_pieces}}{{=item.gift_pieces}}{{??}}1{{?}}" type="text">
|
||||
<span class="input-group-addon">ks</span>
|
||||
</div>
|
||||
</p>
|
||||
<a class="btn-sm btn btn-danger" data-form-delete>
|
||||
<input class="hidden" type="checkbox" name="{/literal}{$tab.prefix}{literal}[gifts][{{? item.index }}-{{=item.index}}{{??}}{{=index + 1}}{{?}}][delete]"/>
|
||||
<span class="glyphicon glyphicon-remove"></span>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
{{~}}
|
||||
{/literal}
|
||||
</script>
|
||||
</div>
|
||||
</div>
|
||||
<script type="application/javascript">
|
||||
$('[data-autocomplete-search="products_gifts"]').multiSelectAutoComplete({
|
||||
formTemplate: '#multiselectAutocomplete_gifts',
|
||||
formWrapper: 'products_gifts',
|
||||
parameters: 'except_product={$body.data.id}',
|
||||
variations: {
|
||||
product_field: 'id_rel_product',
|
||||
},
|
||||
}).multiSelectAutoComplete('addItems', {$body.product.gifts|array_values|json_encode nofilter});
|
||||
|
||||
initForm({
|
||||
selector: '#gifts',
|
||||
beforeAdd: function(callback) {
|
||||
var $item = callback();
|
||||
return false;
|
||||
},
|
||||
});
|
||||
</script>
|
||||
</div>
|
||||
@@ -0,0 +1,116 @@
|
||||
<?php
|
||||
|
||||
namespace KupShop\ProductGiftsBundle\EventListener;
|
||||
|
||||
use KupShop\KupShopBundle\Context\CurrencyContext;
|
||||
use KupShop\OrderingBundle\Event\OrderItemEvent;
|
||||
use Query\Operator;
|
||||
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
|
||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||
|
||||
class OrderItemsListener implements EventSubscriberInterface
|
||||
{
|
||||
use \DatabaseCommunication;
|
||||
|
||||
private $currencyContext;
|
||||
/**
|
||||
* @var OrderItemsListener
|
||||
*/
|
||||
private $itemsListener;
|
||||
|
||||
private EventDispatcherInterface $eventDispatcher;
|
||||
|
||||
/**
|
||||
* @param OrderItemsListener $itemsListener
|
||||
*/
|
||||
public function __construct(CurrencyContext $currencyContext, \KupShop\OrderingBundle\EventListener\OrderItemListener $itemsListener, EventDispatcherInterface $eventDispatcher)
|
||||
{
|
||||
$this->currencyContext = $currencyContext;
|
||||
$this->itemsListener = $itemsListener;
|
||||
$this->eventDispatcher = $eventDispatcher;
|
||||
}
|
||||
|
||||
public static function getSubscribedEvents()
|
||||
{
|
||||
return [
|
||||
OrderItemEvent::ITEM_CREATED => [
|
||||
['splitGiftItem', 250],
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
public function splitGiftItem(OrderItemEvent $event)
|
||||
{
|
||||
if (!empty($event->getOrder()?->pos)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$product = $event->getProduct();
|
||||
$product->fetchGifts();
|
||||
|
||||
// Skip gift item creation, now it's part of createOrderFromPurchaseState
|
||||
if ($product->gifts && !findModule(\Modules::ORDERS, \Modules::SUB_CREATE_ORDER_FROM_PURCHASE_STATE)) {
|
||||
$data = $event->getData();
|
||||
$items_table = $data['items_table'];
|
||||
$row = $data['row'];
|
||||
$decimalPieces = toDecimal($row['pieces']);
|
||||
|
||||
$itemRow = sqlQueryBuilder()
|
||||
->select('*')
|
||||
->from($items_table)
|
||||
->where(Operator::equals(['id' => $row['id']]))
|
||||
->execute()
|
||||
->fetch();
|
||||
|
||||
$note = $product->parseNote($itemRow['note']);
|
||||
|
||||
$item_note = ['item_type' => 'gift'];
|
||||
|
||||
/** @var Product $gift_product */
|
||||
foreach ($product->gifts as $gift_product) {
|
||||
// skipneme darek, protoze uzivatel vybral, ze ho nechce
|
||||
if (($note['gifts'][$gift_product->id]['unwanted'] ?? 0) == 1) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!($variation = $this->itemsListener->checkSetVariations($gift_product, $note))) {
|
||||
continue;
|
||||
}
|
||||
$title = $this->setModifyTitle($gift_product->title, $variation['title']);
|
||||
$giftPieces = toDecimal($gift_product['gift_pieces'])->mul($decimalPieces);
|
||||
$gift_product->sell($variation['id'], $giftPieces->asFloat());
|
||||
$insert = [
|
||||
'id_order' => $itemRow['id_order'],
|
||||
'id_product' => $gift_product->id,
|
||||
'id_variation' => $variation['id'],
|
||||
'pieces' => $giftPieces,
|
||||
'pieces_reserved' => $giftPieces,
|
||||
'piece_price' => \DecimalConstants::zero(),
|
||||
'total_price' => \DecimalConstants::zero(),
|
||||
'descr' => $title,
|
||||
'tax' => $gift_product->vat,
|
||||
'note' => json_encode($item_note),
|
||||
'date' => new \DateTime(),
|
||||
];
|
||||
$this->insertSQL($items_table, $insert, [], ['date' => 'datetime']);
|
||||
$insert['id'] = sqlInsertId();
|
||||
|
||||
$this->eventDispatcher->dispatch(new OrderItemEvent(
|
||||
$gift_product,
|
||||
$variation['id'],
|
||||
\DecimalConstants::zero(),
|
||||
$giftPieces->asFloat(),
|
||||
['row' => $insert, 'items_table' => $items_table],
|
||||
$event->getOrder()),
|
||||
OrderItemEvent::ITEM_CREATED);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected function setModifyTitle($product, $variation)
|
||||
{
|
||||
$descr = translate_shop('gift', 'ordering', true);
|
||||
|
||||
return $descr.' - '.$product.' '.$variation;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
<?php
|
||||
|
||||
namespace KupShop\ProductGiftsBundle\EventListener;
|
||||
|
||||
use KupShop\KupShopBundle\Context\CurrencyContext;
|
||||
use KupShop\KupShopBundle\Util\Price\Price;
|
||||
use KupShop\OrderingBundle\Entity\Purchase\ProductPurchaseItem;
|
||||
use KupShop\OrderingBundle\Event\PurchaseStateCreatedEvent;
|
||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||
use Symfony\Contracts\Service\Attribute\Required;
|
||||
|
||||
class PurchaseStateListener implements EventSubscriberInterface
|
||||
{
|
||||
#[Required]
|
||||
public CurrencyContext $currencyContext;
|
||||
|
||||
public static function getSubscribedEvents()
|
||||
{
|
||||
return [
|
||||
PurchaseStateCreatedEvent::class => [
|
||||
['addProductGifts', 200],
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
public function addProductGifts(PurchaseStateCreatedEvent $event): void
|
||||
{
|
||||
$productCollection = $event->getPurchaseState()->createProductCollection();
|
||||
$productCollection->fetchGifts();
|
||||
|
||||
$purchaseGifts = [];
|
||||
foreach ($event->getPurchaseState()->getProducts() as $purchaseItem) {
|
||||
foreach ($purchaseItem->getProduct()->gifts ?? [] as $gift) {
|
||||
if (isset($purchaseItem->getNote()['gifts'][$gift['id']]) && !$purchaseItem->getNote()['gifts'][$gift['id']]) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$key = array_key_first($purchaseItem->getNote()['set_variation'] ?? []);
|
||||
if ($key == $gift->id) {
|
||||
$variation = \Variation::createProductOrVariation($gift->id, (int) $purchaseItem->getNote()['set_variation'][$key]);
|
||||
$variation->createFromDB();
|
||||
$variation->gift_pieces = $gift['gift_pieces'] ?? 1;
|
||||
$purchaseGifts[] = $variation;
|
||||
} else {
|
||||
$purchaseGifts[] = $gift;
|
||||
}
|
||||
}
|
||||
|
||||
$this->addProductGiftsToPurchaseItem($purchaseItem, $purchaseGifts);
|
||||
}
|
||||
}
|
||||
|
||||
private function addProductGiftsToPurchaseItem(ProductPurchaseItem $purchaseItem, array $gifts): void
|
||||
{
|
||||
foreach ($gifts as $gift) {
|
||||
$giftPurchaseItem = new ProductPurchaseItem(
|
||||
$gift->id,
|
||||
$gift->variationId ?? null,
|
||||
$gift['gift_pieces'] ?? 1,
|
||||
new Price(
|
||||
\DecimalConstants::zero(),
|
||||
$this->currencyContext->getActive(),
|
||||
$gift->vat
|
||||
),
|
||||
['item_type' => 'gift']
|
||||
);
|
||||
$giftPurchaseItem->setProduct($gift);
|
||||
|
||||
$purchaseItem->addAdditionalItem($giftPurchaseItem);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
<?php
|
||||
|
||||
namespace KupShop\ProductGiftsBundle;
|
||||
|
||||
use Symfony\Component\HttpKernel\Bundle\Bundle;
|
||||
|
||||
class ProductGiftsBundle extends Bundle
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
services:
|
||||
_defaults:
|
||||
autowire: true
|
||||
autoconfigure: true
|
||||
|
||||
KupShop\ProductGiftsBundle\:
|
||||
resource: ../../{Admin/Tabs,EventListener,Utils,Controller,Translations,AdminRegister}
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
<?php
|
||||
|
||||
namespace KupShop\ProductsGiftsBundle\Resources\upgrade;
|
||||
|
||||
class ProductsGiftsUpgrade extends \UpgradeNew
|
||||
{
|
||||
public function check_ProductsGifts()
|
||||
{
|
||||
return $this->checkTableExists('products_gifts');
|
||||
}
|
||||
|
||||
/** Create table products_gifts */
|
||||
public function upgrade_ProductsGifts()
|
||||
{
|
||||
sqlQuery(
|
||||
'
|
||||
create table products_gifts
|
||||
(
|
||||
id_product int not null,
|
||||
id_product_gift int not null,
|
||||
id_variation_gift int null,
|
||||
price double null,
|
||||
pieces int default 1 null,
|
||||
primary key (id_product, id_product_gift),
|
||||
constraint products_gifts_ibfk_1
|
||||
foreign key (id_product) references products (id)
|
||||
on update cascade on delete cascade,
|
||||
constraint products_gifts_ibfk_2
|
||||
foreign key (id_product_gift) references products (id)
|
||||
on update cascade on delete cascade,
|
||||
constraint products_gifts_ibfk_3
|
||||
foreign key (id_variation_gift) references products_variations (id)
|
||||
on update cascade on delete cascade
|
||||
)
|
||||
charset = utf8mb4 COLLATE utf8mb4_general_ci;
|
||||
|
||||
create index id_product_gift
|
||||
on products_gifts (id_product_gift);'
|
||||
);
|
||||
|
||||
if (!findModule(\Modules::PRODUCT_SETS) && findModule(\Modules::PRODUCT_GIFTS)) {
|
||||
sqlQuery(
|
||||
'INSERT INTO products_gifts (id_product,id_product_gift,price,id_variation_gift,pieces)
|
||||
SELECT id_product,id_product_set,price,id_variation,pieces FROM products_sets;'
|
||||
);
|
||||
|
||||
// zatim nemazat
|
||||
/*sqlQuery(
|
||||
'DELETE FROM products_sets;'
|
||||
);*/
|
||||
}
|
||||
$this->upgradeOK();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,522 @@
|
||||
{
|
||||
"set_categories": [
|
||||
{
|
||||
"id": 1,
|
||||
"name": "Vázání",
|
||||
"descr": "<p>adcasd cds</p>\r\n\r\n<p>asc</p>\r\n\r\n<p>d sa</p>\r\n\r\n<p>cds</p>\r\n\r\n<p>a</p>"
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"name": "Boty",
|
||||
"descr": "<p>adcasd cds</p>\r\n\r\n<p>asc</p>\r\n\r\n<p>d sa</p>\r\n\r\n<p>cds</p>\r\n\r\n<p>a</p>"
|
||||
}
|
||||
],
|
||||
"products": [
|
||||
{
|
||||
"id": 325,
|
||||
"title": "SET PRODUKTU",
|
||||
"code": "1cd23sc5465",
|
||||
"ean": null,
|
||||
"short_descr": "wpj",
|
||||
"long_descr": "<p class=\"last\">Mobilní telefon Apple A6 Dual-core 1.3GHz, dotykový 4\" Retina 1136x640, interní paměť 8GB, WiFi 802.11a/b/g/n, Bluetooth 4.0, 8 Mpx fotoaparát s LED bleskem, GPS, Gyroskop, Akcelerometr, Lightning rozhraní, iOS 8</p>",
|
||||
"parameters": "<p><strong>Barvy plné života</strong></p>\r\n\r\n<p>Každá funkce a vlastnost telefonu iPhone 5C vám vylepší všechny zážitky. Díky<br />\r\npestrým barevným povrchům si můžete vybrat barvu, která vám sedne nejvíce<br />\r\n- dokonce i domovská stránka a tapety jsou navrženy v barvě vašeho iPhonu.</p>\r\n\r\n<p><strong>Apple A6 - záruka neomezených možností</strong></p>\r\n\r\n<p>Spouštějte oblíbené aplikace. Procházejte si sociální sítě. Stahujte si a sledujte HD videa. Hrajte dechberoucí hry. Zkrátka všechno, co rádi na iPhonu děláte - navíc s rychlostí, kterou očekáváte.</p>\r\n\r\n<p><strong>Zbrusu nový iOS 8</strong></p>\r\n\r\n<p>Jasnější a jednodušší ikony. Prostředí, které působí živě a plynule. Nové funkce,<br />\r\nkteré naplno využívají potenciál skrytý uvnitř telefonu. Světově nejpokročilejší<br />\r\noperační systém iOS 8 je perfektním společníkem nového iPhonu 5C.</p>",
|
||||
"price": 4132.2314,
|
||||
"price_common": 0.0000,
|
||||
"vat": 1,
|
||||
"discount": 0,
|
||||
"producer": 17,
|
||||
"guarantee": 36,
|
||||
"in_store": 23,
|
||||
"pieces_sold": 10,
|
||||
"delivery_time": 0,
|
||||
"campaign": "PS",
|
||||
"updated": "2015-02-16 11:21:12",
|
||||
"date_added": "2015-02-13 13:56:00",
|
||||
"figure": "Y",
|
||||
"show_raw_price": "N",
|
||||
"position": null,
|
||||
"meta_title": null,
|
||||
"meta_description": null,
|
||||
"meta_keywords": null,
|
||||
"show_in_feed": "Y",
|
||||
"max_cpc": 0.0,
|
||||
"in_store_min": null,
|
||||
"weight": null,
|
||||
"price_buy": null
|
||||
},
|
||||
{
|
||||
"id": 1,
|
||||
"title": "NIKE Capri LACE Test Dlouheho Nazvu Produktu Test Dlouheho Produktu Tes",
|
||||
"code": "QO591",
|
||||
"ean": 1001,
|
||||
"short_descr": "Lorem ipsum dolor sit amet",
|
||||
"long_descr": "<p class=\"last\">Jenže kvůli všudy přítomné trávě jsou stíny balónků sotva vidět, natož aby šlo rozeznat, jakou barvu tyto stíny mají. Uvidět tak balónky náhodný kolemjdoucí, jistě by si pomyslel, že už tu takhle poletují snad tisíc let. Stále si víceméně drží výšku a ani do stran se příliš nepohybují. Proti slunci to vypadá, že se slunce pohybuje k západu rychleji než balónky, a možná to tak skutečně je. Nejeden filozof by mohl tvrdit, že balónky se sluncem závodí, ale fyzikové by to jistě vyvrátili. Z fyzikálního pohledu totiž balónky působí zcela nezajímavě.</p>",
|
||||
"parameters": "<ul style=\"line-height: 20.7999992370605px;\">\r\n\t<li><b>Složení</b>: WATERFEEL X-LIFE</li>\r\n\t<li><b>Boky</b>: 27</li>\r\n\t<li><b>Cílová skupina</b>: vhodné na trénink a pro aktivní plavání</li>\r\n\t<li><b>Pásek</b>: tkanička v pase pro snadné přizpůsobení velikosti</li>\r\n\t<li><b>Materiál</b>: pohodlný a měkký materiál s prodlouženou životností. Poskytuje neodolatelnou volnost pohybu a odolává chlorované vodě a slunečnímu záření</li>\r\n</ul>",
|
||||
"price": 4132.2314049587,
|
||||
"price_common": 1200.0000,
|
||||
"vat": 1,
|
||||
"discount": 0,
|
||||
"producer": 12,
|
||||
"guarantee": 24,
|
||||
"in_store": 0,
|
||||
"pieces_sold": 0,
|
||||
"delivery_time": 0,
|
||||
"campaign": "N,L",
|
||||
"updated": "2015-02-16 11:18:43",
|
||||
"date_added": "2015-02-16 09:41:00",
|
||||
"figure": "Y",
|
||||
"show_raw_price": "N",
|
||||
"position": null,
|
||||
"meta_title": null,
|
||||
"meta_description": null,
|
||||
"meta_keywords": null,
|
||||
"show_in_feed": "N",
|
||||
"max_cpc": 0.0,
|
||||
"in_store_min": null,
|
||||
"weight": null,
|
||||
"price_buy": null
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"title": "Adidas Mundial Goal Dalsi Test Velmi Dlouheho Produktoveho Nazvu",
|
||||
"code": "JQ671",
|
||||
"ean": 1002,
|
||||
"short_descr": "Lorem ipsum dolor sit amet",
|
||||
"long_descr": "<p class=\"last\">Jenže kvůli všudy přítomné trávě jsou stíny balónků sotva vidět, natož aby šlo rozeznat, jakou barvu tyto stíny mají. Uvidět tak balónky náhodný kolemjdoucí, jistě by si pomyslel, že už tu takhle poletují snad tisíc let. Stále si víceméně drží výšku a ani do stran se příliš nepohybují. Proti slunci to vypadá, že se slunce pohybuje k západu rychleji než balónky, a možná to tak skutečně je. Nejeden filozof by mohl tvrdit, že balónky se sluncem závodí, ale fyzikové by to jistě vyvrátili. Z fyzikálního pohledu totiž balónky působí zcela nezajímavě.</p>",
|
||||
"parameters": "<ul style=\"line-height: 20.7999992370605px;\">\r\n\t<li><b>Složení</b>: WATERFEEL X-LIFE</li>\r\n\t<li><b>Boky</b>: 27</li>\r\n\t<li><b>Cílová skupina</b>: vhodné na trénink a pro aktivní plavání</li>\r\n\t<li><b>Pásek</b>: tkanička v pase pro snadné přizpůsobení velikosti</li>\r\n\t<li><b>Materiál</b>: pohodlný a měkký materiál s prodlouženou životností. Poskytuje neodolatelnou volnost pohybu a odolává chlorované vodě a slunečnímu záření</li>\r\n</ul>",
|
||||
"price": 4132.2314049587,
|
||||
"price_common": 2800.0000,
|
||||
"vat": 1,
|
||||
"discount": 0,
|
||||
"producer": 10,
|
||||
"guarantee": 24,
|
||||
"in_store": 9,
|
||||
"pieces_sold": 0,
|
||||
"delivery_time": -1,
|
||||
"campaign": "D,L",
|
||||
"updated": "2015-02-16 11:18:47",
|
||||
"date_added": "2015-02-16 09:41:00",
|
||||
"figure": "Y",
|
||||
"show_raw_price": "N",
|
||||
"position": null,
|
||||
"meta_title": null,
|
||||
"meta_description": null,
|
||||
"meta_keywords": null,
|
||||
"show_in_feed": "N",
|
||||
"max_cpc": 0.0,
|
||||
"in_store_min": null,
|
||||
"weight": null,
|
||||
"price_buy": null
|
||||
},
|
||||
{
|
||||
"id": 3,
|
||||
"title": "Wilson pure battle crew",
|
||||
"code": "MV934",
|
||||
"ean": null,
|
||||
"short_descr": "Lorem ipsum dolor sit amet",
|
||||
"long_descr": "<p class=\"last\">Jenže kvůli všudy přítomné trávě jsou stíny balónků sotva vidět, natož aby šlo rozeznat, jakou barvu tyto stíny mají. Uvidět tak balónky náhodný kolemjdoucí, jistě by si pomyslel, že už tu takhle poletují snad tisíc let. Stále si víceméně drží výšku a ani do stran se příliš nepohybují. Proti slunci to vypadá, že se slunce pohybuje k západu rychleji než balónky, a možná to tak skutečně je. Nejeden filozof by mohl tvrdit, že balónky se sluncem závodí, ale fyzikové by to jistě vyvrátili. Z fyzikálního pohledu totiž balónky působí zcela nezajímavě.</p>",
|
||||
"parameters": "<ul style=\"line-height: 20.7999992370605px;\">\r\n\t<li><b>Složení</b>: WATERFEEL X-LIFE</li>\r\n\t<li><b>Boky</b>: 27</li>\r\n\t<li><b>Cílová skupina</b>: vhodné na trénink a pro aktivní plavání</li>\r\n\t<li><b>Pásek</b>: tkanička v pase pro snadné přizpůsobení velikosti</li>\r\n\t<li><b>Materiál</b>: pohodlný a měkký materiál s prodlouženou životností. Poskytuje neodolatelnou volnost pohybu a odolává chlorované vodě a slunečnímu záření</li>\r\n</ul>",
|
||||
"price": 661.1570,
|
||||
"price_common": 900.0000,
|
||||
"vat": 1,
|
||||
"discount": 0,
|
||||
"producer": null,
|
||||
"guarantee": 24,
|
||||
"in_store": -1,
|
||||
"pieces_sold": 1,
|
||||
"delivery_time": -1,
|
||||
"campaign": "S,L,A",
|
||||
"updated": "2015-02-16 11:21:49",
|
||||
"date_added": "2014-09-26 08:27:00",
|
||||
"figure": "Y",
|
||||
"show_raw_price": "N",
|
||||
"position": null,
|
||||
"meta_title": null,
|
||||
"meta_description": null,
|
||||
"meta_keywords": null,
|
||||
"show_in_feed": "N",
|
||||
"max_cpc": 0.0,
|
||||
"in_store_min": null,
|
||||
"weight": null,
|
||||
"price_buy": null
|
||||
},
|
||||
{
|
||||
"id": 4,
|
||||
"title": "Columbia Lay D Down",
|
||||
"code": "UQ372",
|
||||
"ean": null,
|
||||
"short_descr": "Lorem ipsum dolor sit amet",
|
||||
"long_descr": "<p class=\"last\">Jenže kvůli všudy přítomné trávě jsou stíny balónků sotva vidět, natož aby šlo rozeznat, jakou barvu tyto stíny mají. Uvidět tak balónky náhodný kolemjdoucí, jistě by si pomyslel, že už tu takhle poletují snad tisíc let. Stále si víceméně drží výšku a ani do stran se příliš nepohybují. Proti slunci to vypadá, že se slunce pohybuje k západu rychleji než balónky, a možná to tak skutečně je. Nejeden filozof by mohl tvrdit, že balónky se sluncem závodí, ale fyzikové by to jistě vyvrátili. Z fyzikálního pohledu totiž balónky působí zcela nezajímavě.</p>",
|
||||
"parameters": "<ul style=\"line-height: 20.7999992370605px;\">\r\n\t<li><b>Složení</b>: WATERFEEL X-LIFE</li>\r\n\t<li><b>Boky</b>: 27</li>\r\n\t<li><b>Cílová skupina</b>: vhodné na trénink a pro aktivní plavání</li>\r\n\t<li><b>Pásek</b>: tkanička v pase pro snadné přizpůsobení velikosti</li>\r\n\t<li><b>Materiál</b>: pohodlný a měkký materiál s prodlouženou životností. Poskytuje neodolatelnou volnost pohybu a odolává chlorované vodě a slunečnímu záření</li>\r\n</ul>",
|
||||
"price": 2066.1157024793,
|
||||
"price_common": 6000.0000,
|
||||
"vat": 1,
|
||||
"discount": 0,
|
||||
"producer": null,
|
||||
"guarantee": 24,
|
||||
"in_store": 1,
|
||||
"pieces_sold": 0,
|
||||
"delivery_time": -1,
|
||||
"campaign": "L",
|
||||
"updated": "2015-02-16 11:18:59",
|
||||
"date_added": "2014-09-26 08:27:00",
|
||||
"figure": "Y",
|
||||
"show_raw_price": "N",
|
||||
"position": null,
|
||||
"meta_title": null,
|
||||
"meta_description": null,
|
||||
"meta_keywords": null,
|
||||
"show_in_feed": "N",
|
||||
"max_cpc": 0.0,
|
||||
"in_store_min": null,
|
||||
"weight": null,
|
||||
"price_buy": null
|
||||
},
|
||||
{
|
||||
"id": 5,
|
||||
"title": "Columbia Lay D Down",
|
||||
"code": "UQ3726",
|
||||
"ean": null,
|
||||
"short_descr": "Lorem ipsum dolor sit amet",
|
||||
"long_descr": "<p class=\"last\">Jenže kvůli všudy přítomné trávě jsou stíny balónků sotva vidět, natož aby šlo rozeznat, jakou barvu tyto stíny mají. Uvidět tak balónky náhodný kolemjdoucí, jistě by si pomyslel, že už tu takhle poletují snad tisíc let. Stále si víceméně drží výšku a ani do stran se příliš nepohybují. Proti slunci to vypadá, že se slunce pohybuje k západu rychleji než balónky, a možná to tak skutečně je. Nejeden filozof by mohl tvrdit, že balónky se sluncem závodí, ale fyzikové by to jistě vyvrátili. Z fyzikálního pohledu totiž balónky působí zcela nezajímavě.</p>",
|
||||
"parameters": "<ul style=\"line-height: 20.7999992370605px;\">\r\n\t<li><b>Složení</b>: WATERFEEL X-LIFE</li>\r\n\t<li><b>Boky</b>: 27</li>\r\n\t<li><b>Cílová skupina</b>: vhodné na trénink a pro aktivní plavání</li>\r\n\t<li><b>Pásek</b>: tkanička v pase pro snadné přizpůsobení velikosti</li>\r\n\t<li><b>Materiál</b>: pohodlný a měkký materiál s prodlouženou životností. Poskytuje neodolatelnou volnost pohybu a odolává chlorované vodě a slunečnímu záření</li>\r\n</ul>",
|
||||
"price": 2066.1157024793,
|
||||
"price_common": 6000.0000,
|
||||
"vat": 1,
|
||||
"discount": 0,
|
||||
"producer": null,
|
||||
"guarantee": 24,
|
||||
"in_store": 5,
|
||||
"pieces_sold": 0,
|
||||
"delivery_time": -1,
|
||||
"campaign": "L",
|
||||
"updated": "2015-02-16 11:18:59",
|
||||
"date_added": "2014-09-26 08:27:00",
|
||||
"figure": "Y",
|
||||
"show_raw_price": "N",
|
||||
"position": null,
|
||||
"meta_title": null,
|
||||
"meta_description": null,
|
||||
"meta_keywords": null,
|
||||
"show_in_feed": "N",
|
||||
"max_cpc": 0.0,
|
||||
"in_store_min": null,
|
||||
"weight": null,
|
||||
"price_buy": null
|
||||
},
|
||||
{
|
||||
"id": 6,
|
||||
"title": "Dárek",
|
||||
"code": "UQ3721",
|
||||
"ean": null,
|
||||
"short_descr": "",
|
||||
"long_descr": "",
|
||||
"parameters": "",
|
||||
"price": 100,
|
||||
"price_common": 200,
|
||||
"vat": 1,
|
||||
"discount": 0,
|
||||
"producer": null,
|
||||
"guarantee": 24,
|
||||
"in_store": 5,
|
||||
"pieces_sold": 0,
|
||||
"delivery_time": -1,
|
||||
"campaign": "L",
|
||||
"updated": "2015-02-16 11:18:59",
|
||||
"date_added": "2014-09-26 08:27:00",
|
||||
"figure": "Y",
|
||||
"show_raw_price": "N",
|
||||
"position": null,
|
||||
"meta_title": null,
|
||||
"meta_description": null,
|
||||
"meta_keywords": null,
|
||||
"show_in_feed": "N",
|
||||
"max_cpc": 0.0,
|
||||
"in_store_min": null,
|
||||
"weight": null,
|
||||
"price_buy": null
|
||||
},
|
||||
{
|
||||
"id": 82,
|
||||
"id_block": 288,
|
||||
"title": "Kočárek Riko Basic Plus 2019 dvojkombinace Anthracite",
|
||||
"code": null,
|
||||
"ean": null,
|
||||
"short_descr": "<h3>vystaven na prodejně v barvě Anthracite</h3>\r\n\r\n<p>Trojkombinaci kočárku Riko Basic v antracitové barvě si oblíbíte pro jeho krásný vzhled a skvělé vychytávky.</p>\r\n\r\n<p>Máte zájem o kočárek i s autosedačkou? Podívejte se na <a href=\"https://www.imrnous.cz/kocarek-riko-basic-plus-2019-trojkombinace-s-autosedackou-anthracite_z548/\" target=\"_blank\">antracitový Riko Basic v trojkombinaci (3v1) s autosedačkou</a>.</p>",
|
||||
"long_descr": "<h3>Základní informace o kočárku</h3>\r\n\r\n<ul dir=\"ltr\">\r\n\t<li>model, který patří mezi oblíbené modely u všech maminek</li>\r\n\t<li>potah z nové luxusní látky v kombinaci s eko kůží</li>\r\n\t<li>foukaná kola</li>\r\n\t<li>výškově nastavitelná rukojeť - potažena eko kůží</li>\r\n\t<li>5-bodové bezpečnostní pásy s polstrováním</li>\r\n\t<li>velmi jednoduché upínání systémem Click-clack</li>\r\n\t<li>možnost upevnění ve směru i protisměru jízdy</li>\r\n</ul>",
|
||||
"parameters": "<p>Součásti balení</p>",
|
||||
"price": 5660.3306,
|
||||
"price_common": 0,
|
||||
"vat": 1,
|
||||
"discount": 0,
|
||||
"charge_id": null,
|
||||
"charge_included": "N",
|
||||
"producer": null,
|
||||
"guarantee": 24,
|
||||
"in_store": 6,
|
||||
"pieces_sold": 72,
|
||||
"delivery_time": 14,
|
||||
"campaign": "NP,PV",
|
||||
"updated": "2021-02-23 09:44:12",
|
||||
"date_added": "2020-02-19 11:15:00",
|
||||
"figure": "Y",
|
||||
"show_raw_price": "N",
|
||||
"position": null,
|
||||
"meta_title": null,
|
||||
"meta_description": "Kočárek Riko Basic Plus v krásné šedočerné variantě je neuvěřitelně prostorný a pohodlný. Do korbičky se jednoduše vleze miminko i v teplém fusaku.",
|
||||
"meta_keywords": null,
|
||||
"show_in_feed": "Y",
|
||||
"max_cpc": 0,
|
||||
"in_store_min": null,
|
||||
"note": null,
|
||||
"weight": null,
|
||||
"data": {
|
||||
"generate_coupon": "N"
|
||||
},
|
||||
"bonus_points": null,
|
||||
"date_stock_in": null,
|
||||
"show_in_search": "Y",
|
||||
"width": null,
|
||||
"height": null,
|
||||
"depth": null
|
||||
},
|
||||
{
|
||||
"id": 1060,
|
||||
"id_block": 3224,
|
||||
"title": "Autosedačka CYBEX Gold Aton 5 2021 River Blue",
|
||||
"code": 520000166,
|
||||
"ean": 4058511809779,
|
||||
"short_descr": "<p>Modrá autosedačka Cybex Aton 5 vašeho mrňouska spolehlivě ochrání a dopřeje mu pohodlí. Je vhodná pro miminka od narození. Vaši pozornost si získá bezpečnostním L.S.P systémem a širokými polstrovanými pásy.</p>",
|
||||
"long_descr": "<h3>Základní informace o autosedačce</h3>\r\n\r\n<ul>\r\n\t<li>oblíbený model, který si zamilujete již od prvního dne užívání</li>\r\n\t<li>L.S.P S systém - kvalitní lineární ochrana při nárazech</li>\r\n\t<li>extra široké Y-pásy s měkkým polstrováním</li>\r\n\t<li>cestovní systém CYBEX</li>\r\n</ul>\r\n\r\n<h3>Oblíbíte si...</h3>\r\n\r\n<ul>\r\n\t<li>jedinečné prvky pro bezpečí a pohodlí dítěte</li>\r\n\t<li>výškově nastavitelnou opěrku hlavy s integrovaným vedením pásů</li>\r\n\t<li>integrovanou sluneční stříšku XXL</li>\r\n\t<li>novorozeneckou vložku</li>\r\n</ul>",
|
||||
"parameters": "<p>Součásti balení</p>",
|
||||
"price": 3208.6957,
|
||||
"price_common": 0,
|
||||
"vat": 2,
|
||||
"discount": 0,
|
||||
"charge_id": null,
|
||||
"charge_included": "N",
|
||||
"producer": null,
|
||||
"guarantee": 24,
|
||||
"in_store": -3,
|
||||
"pieces_sold": 3,
|
||||
"delivery_time": 7,
|
||||
"campaign": "NP",
|
||||
"updated": "2021-02-23 09:44:12",
|
||||
"date_added": "2020-03-24 09:21:00",
|
||||
"figure": "Y",
|
||||
"show_raw_price": "N",
|
||||
"position": null,
|
||||
"meta_title": null,
|
||||
"meta_description": "Autosedačka Cybex ✅ bezpečná autosedačka ověřena maminkami ✅ Recenze ✅ Online poradna ✅ Autorizovaný servis ✅ Vzorková prodejna ✅",
|
||||
"meta_keywords": null,
|
||||
"show_in_feed": "Y",
|
||||
"max_cpc": 0,
|
||||
"in_store_min": null,
|
||||
"note": null,
|
||||
"weight": null,
|
||||
"data": {
|
||||
"generate_coupon": "N"
|
||||
},
|
||||
"bonus_points": null,
|
||||
"date_stock_in": null,
|
||||
"show_in_search": "Y",
|
||||
"width": null,
|
||||
"height": null,
|
||||
"depth": null
|
||||
},
|
||||
{
|
||||
"id": 1294,
|
||||
"id_block": 3955,
|
||||
"title": "Adaptér pro kočárky Riko Basic",
|
||||
"code": "VO819",
|
||||
"ean": null,
|
||||
"short_descr": "<p>Adaptéry ke kočárku Riko Basic se snadno instalují. Připojíte k nim více druhů autosedaček, a to například Maxi-Cosi, Cybex, Kiddy, Besafe, Joie a Nuna.</p>",
|
||||
"long_descr": "<h3>Základní informace o adaptérech</h3>\r\n\r\n<ul>\r\n\t<li>adaptéry pro připojení autosedaček Cybex, Maxi Cosi a dalších ke kočárkům Riko Basic</li>\r\n</ul>\r\n\r\n<h3>Oblíbíte si...</h3>\r\n\r\n<ul>\r\n\t<li>lehká instalace</li>\r\n\t<li>malé rozměry</li>\r\n\t<li>možnost nasazení na více druhů autosedaček</li>\r\n</ul>",
|
||||
"parameters": "<p>Součásti balení</p>",
|
||||
"price": 454.5455,
|
||||
"price_common": 0,
|
||||
"vat": 1,
|
||||
"discount": 0,
|
||||
"charge_id": null,
|
||||
"charge_included": "N",
|
||||
"producer": null,
|
||||
"guarantee": 24,
|
||||
"in_store": 12,
|
||||
"pieces_sold": 65,
|
||||
"delivery_time": 14,
|
||||
"campaign": "",
|
||||
"updated": "2021-02-23 09:44:12",
|
||||
"date_added": "2020-04-04 19:34:00",
|
||||
"figure": "Y",
|
||||
"show_raw_price": "N",
|
||||
"position": null,
|
||||
"meta_title": null,
|
||||
"meta_description": "K adaptérům pro kočárky Riko Basic jednoduše připnete autosedačky Maxi-Cosi, Cybex, Kiddy, Besafe, Joie a Nuna.",
|
||||
"meta_keywords": null,
|
||||
"show_in_feed": "Y",
|
||||
"max_cpc": 0,
|
||||
"in_store_min": null,
|
||||
"note": null,
|
||||
"weight": null,
|
||||
"data": {
|
||||
"generate_coupon": "N"
|
||||
},
|
||||
"bonus_points": null,
|
||||
"date_stock_in": null,
|
||||
"show_in_search": "Y",
|
||||
"width": null,
|
||||
"height": null,
|
||||
"depth": null
|
||||
},
|
||||
{
|
||||
"id": 3654,
|
||||
"id_block": 11344,
|
||||
"title": "Výhodný set Riko Basic Plus 2019 + autosedačka Cybex Aton 5",
|
||||
"code": "UF293",
|
||||
"ean": null,
|
||||
"short_descr": "<p>Výhodný set ke kočárku Riko Basic 2v1 vám nabízí výběr z pěti barev kočárků. K tomu je na vás, jakou barvu prémiové autosedačky Cybex Aton 5 zvolíte. Třetí položkou v setu jsou adaptéry, díky kterým snadno nasadíte autosedačku na rám kočárku.</p>",
|
||||
"long_descr": "<h3>Kočárek Riko Basic 2v1</h3>\r\n\r\n<ul dir=\"ltr\">\r\n\t<li>model, který patří mezi oblíbené modely u všech maminek</li>\r\n\t<li>potah z nové luxusní látky v kombinaci s eko kůží</li>\r\n\t<li>foukaná kola</li>\r\n\t<li>výškově nastavitelná rukojeť - potažena eko kůží</li>\r\n\t<li>5-bodové bezpečnostní pásy s polstrováním</li>\r\n\t<li>velmi jednoduché upínání systémem Click-clack</li>\r\n\t<li>možnost upevnění ve směru i protisměru jízdy</li>\r\n</ul>\r\n\r\n<h3>Autosedačka Cybex Aton 5</h3>\r\n\r\n<ul>\r\n\t<li>oblíbený model, který si zamilujete již od prvního dne užívání</li>\r\n\t<li>L.S.P S systém - kvalitní lineární ochrana při nárazech</li>\r\n\t<li>extra široké Y-pásy s měkkým polstrováním</li>\r\n\t<li>cestovní systém CYBEX</li>\r\n</ul>\r\n\r\n<h3>Adaptéry</h3>\r\n\r\n<ul>\r\n\t<li>lehká instalace</li>\r\n\t<li>malé rozměry</li>\r\n\t<li>možnost nasazení na více druhů autosedaček</li>\r\n</ul>",
|
||||
"parameters": "<p>Součásti balení</p>",
|
||||
"price": 8842.9752,
|
||||
"price_common": 0,
|
||||
"vat": 1,
|
||||
"discount": 0,
|
||||
"charge_id": null,
|
||||
"charge_included": "N",
|
||||
"producer": null,
|
||||
"guarantee": 24,
|
||||
"in_store": 7,
|
||||
"pieces_sold": 0,
|
||||
"delivery_time": 14,
|
||||
"campaign": "NP,PV,PS",
|
||||
"updated": "2021-02-23 09:44:12",
|
||||
"date_added": "2021-01-08 12:15:00",
|
||||
"figure": "Y",
|
||||
"show_raw_price": "N",
|
||||
"position": null,
|
||||
"meta_title": null,
|
||||
"meta_description": "Kočárek Riko Basic Plus v krásné šedočerné variantě je neuvěřitelně prostorný a pohodlný. Do korbičky se jednoduše vleze miminko i v teplém fusaku.",
|
||||
"meta_keywords": null,
|
||||
"show_in_feed": "Y",
|
||||
"max_cpc": 0,
|
||||
"in_store_min": null,
|
||||
"note": null,
|
||||
"weight": null,
|
||||
"data": {
|
||||
"generate_coupon": "N"
|
||||
},
|
||||
"bonus_points": null,
|
||||
"date_stock_in": null,
|
||||
"show_in_search": "Y",
|
||||
"width": null,
|
||||
"height": null,
|
||||
"depth": null
|
||||
}
|
||||
],
|
||||
"products_variations": [
|
||||
{
|
||||
"id": 10,
|
||||
"id_product": 2,
|
||||
"code": null,
|
||||
"ean": null,
|
||||
"title": "Velikost: 41",
|
||||
"in_store": 3,
|
||||
"delivery_time": -1,
|
||||
"price": null,
|
||||
"figure": "Y",
|
||||
"updated": null,
|
||||
"date_added": "",
|
||||
"weight": null,
|
||||
"price_buy": null
|
||||
},
|
||||
{
|
||||
"id": 11,
|
||||
"id_product": 2,
|
||||
"code": null,
|
||||
"ean": null,
|
||||
"title": "Velikost: 42",
|
||||
"in_store": 3,
|
||||
"delivery_time": -1,
|
||||
"price": null,
|
||||
"figure": "Y",
|
||||
"updated": null,
|
||||
"date_added": "",
|
||||
"weight": null,
|
||||
"price_buy": null
|
||||
}
|
||||
],
|
||||
"set_products": [
|
||||
{
|
||||
"id": 3,
|
||||
"id_product_master": 325,
|
||||
"id_product": 2,
|
||||
"category": 1
|
||||
},
|
||||
{
|
||||
"id": 4,
|
||||
"id_product_master": 325,
|
||||
"id_product": 1,
|
||||
"category": 1
|
||||
},
|
||||
{
|
||||
"id": 5,
|
||||
"id_product_master": 325,
|
||||
"id_product": 4,
|
||||
"category": 2
|
||||
},
|
||||
{
|
||||
"id": 6,
|
||||
"id_product_master": 325,
|
||||
"id_product": 3,
|
||||
"category": 2
|
||||
}
|
||||
],
|
||||
"products_gifts": [
|
||||
{
|
||||
"id_product": 5,
|
||||
"id_product_gift": 6,
|
||||
"price": null,
|
||||
"id_variation_gift": null,
|
||||
"pieces": 1
|
||||
},
|
||||
{
|
||||
"id_product": 3654,
|
||||
"id_product_gift": 2,
|
||||
"price": null,
|
||||
"id_variation_gift": 11,
|
||||
"pieces": 1
|
||||
}
|
||||
],
|
||||
"products_variations_choices_labels": [
|
||||
{
|
||||
"id": 1,
|
||||
"label": "Velikost"
|
||||
}
|
||||
],
|
||||
"products_variations_choices_values": [
|
||||
{
|
||||
"id": 1,
|
||||
"id_label" : 1,
|
||||
"value" : "42"
|
||||
}
|
||||
],
|
||||
"products_variations_choices_categorization": [
|
||||
{
|
||||
"id_product": 2,
|
||||
"id_label": 1,
|
||||
"list_order": 1
|
||||
}
|
||||
],
|
||||
"products_variations_combination": [
|
||||
{
|
||||
"id_variation": 10,
|
||||
"id_label": 1,
|
||||
"id_value": 1
|
||||
},
|
||||
{
|
||||
"id_variation": 11,
|
||||
"id_label": 1,
|
||||
"id_value": 1
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,97 @@
|
||||
<?php
|
||||
|
||||
namespace KupShop\ProductSetsBundle\Tests;
|
||||
|
||||
use KupShop\DevelopmentBundle\Util\Tests\CartTestTrait;
|
||||
|
||||
class OrderCreateGiftListenerTest extends \DatabaseTestCase
|
||||
{
|
||||
use CartTestTrait;
|
||||
|
||||
public function testGiftItem()
|
||||
{
|
||||
$item = [
|
||||
'id_product' => 5,
|
||||
'pieces' => 2,
|
||||
];
|
||||
|
||||
$user = \User::createFromId(1);
|
||||
$user->activateUser();
|
||||
|
||||
$this->createCart();
|
||||
$cart = $this->cart;
|
||||
$cart->createFromDB();
|
||||
|
||||
$cart->addItem($item);
|
||||
$cart->setDeliveryAndPayment(3, 3);
|
||||
|
||||
$cart->save();
|
||||
$cart->load();
|
||||
$order = $cart->submitOrder();
|
||||
|
||||
$orderObj = new \Order();
|
||||
$orderObj->createFromDB($order->id);
|
||||
|
||||
$items = $orderObj->fetchItems();
|
||||
|
||||
$item = array_shift($items);
|
||||
$this->assertEquals($item['id_product'], 5);
|
||||
$this->assertEquals($item['pieces'], 2);
|
||||
$this->assertEquals($item['id_variation'], null);
|
||||
|
||||
$item = array_shift($items);
|
||||
$this->assertEquals($item['id_product'], 6);
|
||||
$this->assertEquals($item['pieces'], 2);
|
||||
$this->assertEquals($item['id_variation'], null);
|
||||
$this->assertEquals(0, $item['piece_price']['value_with_vat']->asFloat());
|
||||
$this->assertEquals(0, $item['total_price']['value_with_vat']->asFloat());
|
||||
|
||||
$this->assertEquals(count($orderObj->items), 2);
|
||||
}
|
||||
|
||||
public function testGiftItemWithVariation()
|
||||
{
|
||||
$item = [
|
||||
'id_product' => 3654,
|
||||
'pieces' => 2,
|
||||
];
|
||||
|
||||
$user = \User::createFromId(1);
|
||||
$user->activateUser();
|
||||
|
||||
$this->createCart();
|
||||
$cart = $this->cart;
|
||||
$cart->createFromDB();
|
||||
|
||||
$cart->addItem($item);
|
||||
$cart->setDeliveryAndPayment(3, 3);
|
||||
|
||||
$cart->save();
|
||||
$cart->load();
|
||||
$order = $cart->submitOrder();
|
||||
|
||||
$orderObj = new \Order();
|
||||
$orderObj->createFromDB($order->id);
|
||||
|
||||
$items = $orderObj->fetchItems();
|
||||
|
||||
$item = array_shift($items);
|
||||
$this->assertEquals($item['id_product'], 3654);
|
||||
$this->assertEquals($item['pieces'], 2);
|
||||
$this->assertEquals($item['id_variation'], null);
|
||||
|
||||
$item = array_shift($items);
|
||||
$this->assertEquals($item['id_product'], 2);
|
||||
$this->assertEquals($item['pieces'], 2);
|
||||
$this->assertEquals($item['id_variation'], 11);
|
||||
$this->assertEquals(0, $item['piece_price']['value_with_vat']->asFloat());
|
||||
$this->assertEquals(0, $item['total_price']['value_with_vat']->asFloat());
|
||||
|
||||
$this->assertEquals(count($orderObj->items), 2);
|
||||
}
|
||||
|
||||
public function getDataSet()
|
||||
{
|
||||
return $this->getJsonDataSetFromFile();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
{
|
||||
"products_gifts": [
|
||||
{
|
||||
"id_product": 8,
|
||||
"id_product_gift": 9,
|
||||
"price": null,
|
||||
"id_variation_gift": null,
|
||||
"pieces": 1
|
||||
},
|
||||
{
|
||||
"id_product": 3,
|
||||
"id_product_gift": 9,
|
||||
"price": null,
|
||||
"id_variation_gift": null,
|
||||
"pieces": 1
|
||||
},
|
||||
{
|
||||
"id_product": 3,
|
||||
"id_product_gift": 11,
|
||||
"price": null,
|
||||
"id_variation_gift": null,
|
||||
"pieces": 2
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace KupShop\ProductGiftsBundle\Tests;
|
||||
|
||||
use KupShop\DevelopmentBundle\Util\Tests\CartTestTrait;
|
||||
use KupShop\OrderingBundle\Entity\Purchase\ProductPurchaseItem;
|
||||
|
||||
class ProductGiftsTest extends \DatabaseTestCase
|
||||
{
|
||||
use CartTestTrait;
|
||||
|
||||
/** @dataProvider data_testGiftsInPurchaseState */
|
||||
public function testGiftsInPurchaseState(int $productId, array $expectedGifts): void
|
||||
{
|
||||
$this->prepareCart();
|
||||
$this->insertProduct($productId);
|
||||
$this->recalculateCart();
|
||||
|
||||
$items = $this->cart->getPurchaseState()
|
||||
->getProducts();
|
||||
|
||||
// use first product in cart
|
||||
$item = reset($items);
|
||||
|
||||
/** @var ProductPurchaseItem[] $gifts */
|
||||
$gifts = array_filter($item->getAdditionalItems(), fn ($x) => $x instanceof ProductPurchaseItem);
|
||||
|
||||
$this->assertCount(count($expectedGifts), $gifts, 'Gifts count should be equal');
|
||||
|
||||
foreach ($gifts as $gift) {
|
||||
$this->assertNotEmpty($expectedGifts[$gift->getIdProduct()] ?? []);
|
||||
$this->assertEquals($expectedGifts[$gift->getIdProduct()]['pieces'], $gift->getPieces(), 'Pieces of gift should be equal');
|
||||
$this->assertEquals($expectedGifts[$gift->getIdProduct()]['price'], $gift->getPriceWithVat()->asFloat(), 'Price of gift should be equal');
|
||||
}
|
||||
}
|
||||
|
||||
private function data_testGiftsInPurchaseState(): iterable
|
||||
{
|
||||
yield 'Product without gift' => [9, []];
|
||||
yield 'Product with one gift' => [8, [9 => ['pieces' => 1, 'price' => 0]]];
|
||||
yield 'Product with two gift' => [3, [9 => ['pieces' => 1, 'price' => 0], 11 => ['pieces' => 2, 'price' => 0]]];
|
||||
}
|
||||
|
||||
protected function getDataSet()
|
||||
{
|
||||
return $this->getJsonDataSetFromFile();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user