first commit
This commit is contained in:
92
bundles/KupShop/MarginsBundle/Admin/margins.php
Normal file
92
bundles/KupShop/MarginsBundle/Admin/margins.php
Normal file
@@ -0,0 +1,92 @@
|
||||
<?php
|
||||
|
||||
use KupShop\KupShopBundle\Util\Compat\ServiceContainer;
|
||||
|
||||
$main_class = 'Margins';
|
||||
|
||||
class Margins extends Window
|
||||
{
|
||||
public function get_vars()
|
||||
{
|
||||
$vars = parent::get_vars();
|
||||
|
||||
$margins = sqlQueryBuilder()
|
||||
->select('*')
|
||||
->from('margins')
|
||||
->orderBy('range_from')
|
||||
->execute()
|
||||
->fetchAll();
|
||||
|
||||
$last = 0;
|
||||
|
||||
foreach ($margins as &$margin) {
|
||||
if ($margin['range_from'] < $last) {
|
||||
$margin['bad_down_range'] = true;
|
||||
}
|
||||
|
||||
$margin['pl_range_from'] = $margin['range_from'] * (100 + $margin['margin']) / 100;
|
||||
$margin['pl_range_to'] = $margin['range_to'] * (100 + $margin['margin']) / 100;
|
||||
|
||||
$last = $margin['range_to'];
|
||||
}
|
||||
|
||||
$vars['body']['data']['margins'] = $margins;
|
||||
|
||||
return $vars;
|
||||
}
|
||||
|
||||
public function handle()
|
||||
{
|
||||
$acn = getVal('acn');
|
||||
if ($acn) {
|
||||
$action = 'handle'.ucfirst($acn);
|
||||
if (method_exists($this, $action)) {
|
||||
call_user_func([$this, $action]);
|
||||
}
|
||||
}
|
||||
|
||||
$data = getVal('data');
|
||||
$submit = getVal('Submit');
|
||||
|
||||
if ($submit) {
|
||||
foreach ($data as $id => $margin) {
|
||||
if (!empty($margin['delete']) || empty($margin['range_to'])) {
|
||||
if ($id > 0) {
|
||||
$this->deleteSQL('margins', ['id' => $margin['id']]);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
$margin['margin'] = floatval(str_replace([',', ' '], ['.', ''], $margin['margin']));
|
||||
|
||||
if ($id < 0) {
|
||||
$this->insertSQL('margins', $margin, ['id', 'delete']);
|
||||
} else {
|
||||
$this->updateSQL('margins', $margin, ['id' => $margin['id']], ['id', 'delete']);
|
||||
}
|
||||
}
|
||||
|
||||
$this->returnOK('Uloženo');
|
||||
}
|
||||
}
|
||||
|
||||
public function handleRecalculateProducts()
|
||||
{
|
||||
$compute = ServiceContainer::getService('kupshop.margins.compute.compute');
|
||||
|
||||
$compute->computeAll();
|
||||
|
||||
$this->returnOK('Přepočítáno.');
|
||||
}
|
||||
|
||||
public function hasRights($name = null)
|
||||
{
|
||||
switch ($name) {
|
||||
case Window::RIGHT_DUPLICATE:
|
||||
case Window::RIGHT_DELETE:
|
||||
return false;
|
||||
default:
|
||||
return parent::hasRights($name);
|
||||
}
|
||||
}
|
||||
}
|
||||
110
bundles/KupShop/MarginsBundle/Admin/templates/window/margins.tpl
Normal file
110
bundles/KupShop/MarginsBundle/Admin/templates/window/margins.tpl
Normal file
@@ -0,0 +1,110 @@
|
||||
{extends "[shared]window.tpl"}
|
||||
|
||||
{block tabs}
|
||||
{windowTab id='flapMargins'}
|
||||
{/block}
|
||||
|
||||
{block size}
|
||||
width = 1220;
|
||||
height = 900;
|
||||
{/block}
|
||||
|
||||
{block tabsContent}
|
||||
<div id="flapMargins" class="tab-pane fade in boxFlex">
|
||||
<div class="panel-group panel-group-lists" data-values="margins">
|
||||
<div class="row bottom-space">
|
||||
<div class="col-md-3">
|
||||
<a href="#" data-form-add class="btn btn-success btn-block"><span class="glyphicon glyphicon-plus"></span> {'buttonAdd'|translate}</a>
|
||||
</div>
|
||||
<div class="col-md-8">
|
||||
<p>Při úpravě dbejte na správnou návaznost hranic OD-DO, přičemž DO a následné OD použijte stejnou hodnotu.
|
||||
Například při použití hladin od 10 Kč do 50 Kč a následně od 50 Kč do 100 Kč, bude při ceně produktu 50 Kč použita první, tedy nižší hladina.</p>
|
||||
</div>
|
||||
|
||||
<div class="col-md-1">
|
||||
<a href="javascript:help('margins');"><i class="btn btn-info bi bi-question-circle"></i></a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="panel">
|
||||
<div class="panel-heading">
|
||||
<div class="row">
|
||||
<div class="col-md-2 col-md-offset-1" style="padding-left: 0;">
|
||||
<small><strong>{'range_from'|translate}</strong></small>
|
||||
</div>
|
||||
<div class="col-md-2 text-center">
|
||||
<small><strong>{'range_to'|translate}</strong></small>
|
||||
</div>
|
||||
<div class="col-md-2 col-md-offset-1 text-center">
|
||||
<small><strong>{'margin'|translate}</strong></small>
|
||||
</div>
|
||||
<div class="col-md-2 text-center">
|
||||
<small><strong>{'title'|translate}</strong></small>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{foreach array_merge([[]], $body.data.margins) as $key => $row}
|
||||
<div class="panel
|
||||
{if $row.bad_down_range}row-red{else}row-green{/if}
|
||||
|
||||
" {if $key == 0}data-form-new style="display:none"{else}data-form-item{/if}>
|
||||
<div class="row bottom-space">
|
||||
{*<div class="col-md-1">*}
|
||||
{*<span class="drag-drop-mover pull-right">*}
|
||||
{*<i class="bi bi-arrows-move handle"></i>*}
|
||||
{*</span>*}
|
||||
{*</div>*}
|
||||
<div class="col-md-2 col-md-offset-1" style="padding-left: 0;">
|
||||
{if $row.bad_down_range}
|
||||
<a class="help-tip" data-toggle="tooltip"title="!! Zadaný rozsah koliduje s jiným !!"><i class="glyphicon glyphicon-warning-sign"></i></a>
|
||||
{/if}
|
||||
<input type="text" class="form-control input-sm" name="data[{$key}][range_from]" maxlength="10" value="{$row.range_from}" />
|
||||
</div>
|
||||
<div class="col-md-2">
|
||||
<input type="text" class="form-control input-sm" name="data[{$key}][range_to]" maxlength="10" value="{$row.range_to}" />
|
||||
{if $row.pl_range_to}
|
||||
<a class="help-tip" data-toggle="tooltip" title="Rozsah pro cenové hladiny: OD:{$row.pl_range_from} DO:{$row.pl_range_to} "><i class="glyphicon glyphicon-signal"></i></a>
|
||||
{/if}
|
||||
</div>
|
||||
<div class="col-md-2 col-md-offset-1">
|
||||
<div class="input-group">
|
||||
<input type="text" class="form-control input-sm" name="data[{$key}][margin]" maxlength="10" value="{$row.margin}" />
|
||||
<span class="input-group-addon">%</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<input type="text" class="form-control input-sm" name="data[{$key}][title]" maxlength="100" value="{$row.title}" />
|
||||
</div>
|
||||
<div class="col-md-1">
|
||||
<div class="btn-group">
|
||||
<a class="btn-sm btn btn-danger" title="{'buttonDeleteValue'|translate}" data-form-delete>
|
||||
<input class="hidden" type="checkbox" name="data[{$key}][delete]" />
|
||||
<input type="hidden" name="data[{$key}][id]" value="{$row.id}" />
|
||||
<span class="glyphicon glyphicon-remove"></span>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{/foreach}
|
||||
</div>
|
||||
</div>
|
||||
{/block}
|
||||
|
||||
<script type="application/javascript">
|
||||
{block onready append}
|
||||
initForm({
|
||||
selector:'[data-values=margins]'
|
||||
});
|
||||
{/block}
|
||||
</script>
|
||||
|
||||
|
||||
{block buttonsLeft}
|
||||
<div class="col-md-3">
|
||||
<a href="launch.php?s={$type}.php&acn=recalculateProducts" class="btn btn-block btn-warning confirm"
|
||||
title="{'recalculateProductsButtonConfirm'|translate}">{'recalculateProductsButton'|translate}</a>
|
||||
</div>
|
||||
{/block}
|
||||
83
bundles/KupShop/MarginsBundle/Compute/Compute.php
Normal file
83
bundles/KupShop/MarginsBundle/Compute/Compute.php
Normal file
@@ -0,0 +1,83 @@
|
||||
<?php
|
||||
|
||||
namespace KupShop\MarginsBundle\Compute;
|
||||
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
|
||||
class Compute
|
||||
{
|
||||
/**
|
||||
* @var EntityManagerInterface
|
||||
*/
|
||||
private $entityManager;
|
||||
|
||||
/**
|
||||
* Compute constructor.
|
||||
*/
|
||||
public function __construct(EntityManagerInterface $entityManager)
|
||||
{
|
||||
$this->entityManager = $entityManager;
|
||||
}
|
||||
|
||||
public function computeAll()
|
||||
{
|
||||
$this->computeProducts();
|
||||
$this->computeVariations();
|
||||
}
|
||||
|
||||
protected function computeProducts()
|
||||
{
|
||||
sqlQueryBuilder()
|
||||
->update('products', 'p')
|
||||
->set('p.price', $this->getMarginPattern('p'))
|
||||
->where('p.price_buy IS NOT NULL AND !FIND_IN_SET(\'MM\', p.campaign)')
|
||||
->execute();
|
||||
}
|
||||
|
||||
protected function computeVariations()
|
||||
{
|
||||
sqlQuery("
|
||||
UPDATE products_variations pv
|
||||
JOIN margins m ON m.range_from < pv.price_buy AND m.range_to >= pv.price_buy
|
||||
JOIN products p ON p.id = pv.id_product
|
||||
SET pv.price = pv.price_buy * (100 + m.margin) / 100
|
||||
WHERE pv.price_buy IS NOT NULL AND !FIND_IN_SET('MM', p.campaign)
|
||||
");
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $id_product int id of product
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function computeProductPrice($id_product)
|
||||
{
|
||||
return sqlQueryBuilder()
|
||||
->update('products', 'p')
|
||||
->set('p.price', $this->getMarginPattern('p'))
|
||||
->where('p.price_buy IS NOT NULL AND p.id = :id AND !FIND_IN_SET(\'MM\', p.campaign)')
|
||||
->setParameter('id', $id_product)
|
||||
->execute();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $id_variation int id of variation
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function computeVariationPrice($id_variation = null)
|
||||
{
|
||||
return sqlQuery("
|
||||
UPDATE products_variations pv
|
||||
JOIN margins m ON m.range_from < pv.price_buy AND m.range_to >= pv.price_buy
|
||||
JOIN products p ON p.id = pv.id_product
|
||||
SET pv.price = pv.price_buy * (100 + m.margin) / 100
|
||||
WHERE pv.price_buy IS NOT NULL AND pv.id = :id AND !FIND_IN_SET('MM', p.campaign)
|
||||
", ['id' => $id_variation]);
|
||||
}
|
||||
|
||||
private function getMarginPattern($alias)
|
||||
{
|
||||
return "{$alias}.price_buy * (100 + COALESCE((SELECT margin FROM margins m WHERE m.range_from < {$alias}.price_buy AND m.range_to >= {$alias}.price_buy), 0)) / 100";
|
||||
}
|
||||
}
|
||||
94
bundles/KupShop/MarginsBundle/Entity/Margin.php
Normal file
94
bundles/KupShop/MarginsBundle/Entity/Margin.php
Normal file
@@ -0,0 +1,94 @@
|
||||
<?php
|
||||
|
||||
namespace KupShop\MarginsBundle\Entity;
|
||||
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
|
||||
/**
|
||||
* Margins.
|
||||
*
|
||||
* @ORM\Table(name="margins")})
|
||||
*
|
||||
* @ORM\Entity
|
||||
*/
|
||||
class Margin
|
||||
{
|
||||
/**
|
||||
* @var int
|
||||
*
|
||||
* @ORM\Column(name="id", type="integer")
|
||||
*
|
||||
* @ORM\Id
|
||||
*
|
||||
* @ORM\GeneratedValue(strategy="IDENTITY")
|
||||
*/
|
||||
private $id;
|
||||
|
||||
/**
|
||||
* @var int
|
||||
*
|
||||
* @ORM\Column(name="range_from", type="integer", nullable=true)
|
||||
*/
|
||||
private $range_from;
|
||||
|
||||
public function getRangeFrom(): int
|
||||
{
|
||||
return $this->range_from;
|
||||
}
|
||||
|
||||
public function setRangeFrom(int $range_from)
|
||||
{
|
||||
$this->range_from = $range_from;
|
||||
}
|
||||
|
||||
public function getRangeTo(): int
|
||||
{
|
||||
return $this->range_to;
|
||||
}
|
||||
|
||||
public function setRangeTo(int $range_to)
|
||||
{
|
||||
$this->range_to = $range_to;
|
||||
}
|
||||
|
||||
public function getMargin(): int
|
||||
{
|
||||
return $this->margin;
|
||||
}
|
||||
|
||||
public function setMargin(int $margin)
|
||||
{
|
||||
$this->margin = $margin;
|
||||
}
|
||||
|
||||
public function getTitle(): string
|
||||
{
|
||||
return $this->title;
|
||||
}
|
||||
|
||||
public function setTitle(string $title)
|
||||
{
|
||||
$this->title = $title;
|
||||
}
|
||||
|
||||
/**
|
||||
* @var int
|
||||
*
|
||||
* @ORM\Column(name="range_to", type="integer", nullable=true)
|
||||
*/
|
||||
private $range_to;
|
||||
|
||||
/**
|
||||
* @var int
|
||||
*
|
||||
* @ORM\Column(name="margin", type="integer", nullable=true)
|
||||
*/
|
||||
private $margin;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*
|
||||
* @ORM\Column(name="title", type="string", length=250, nullable=true)
|
||||
*/
|
||||
private $title;
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
<?php
|
||||
|
||||
namespace KupShop\MarginsBundle\EventListener;
|
||||
|
||||
use KupShop\KupShopBundle\Event\CreateMenuEvent;
|
||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||
|
||||
class MarginMenuListener implements EventSubscriberInterface
|
||||
{
|
||||
public static function getSubscribedEvents()
|
||||
{
|
||||
return [
|
||||
CreateMenuEvent::COMPLETING_TREE => [
|
||||
['addItem', 200],
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @var CreateMenuEvent
|
||||
*/
|
||||
public function addItem(CreateMenuEvent $event)
|
||||
{
|
||||
$event->addItem('productsMenu',
|
||||
[
|
||||
'name' => 'margins',
|
||||
'script' => "nw('margins')",
|
||||
]
|
||||
);
|
||||
}
|
||||
}
|
||||
9
bundles/KupShop/MarginsBundle/MarginsBundle.php
Normal file
9
bundles/KupShop/MarginsBundle/MarginsBundle.php
Normal file
@@ -0,0 +1,9 @@
|
||||
<?php
|
||||
|
||||
namespace KupShop\MarginsBundle;
|
||||
|
||||
use Symfony\Component\HttpKernel\Bundle\Bundle;
|
||||
|
||||
class MarginsBundle extends Bundle
|
||||
{
|
||||
}
|
||||
10
bundles/KupShop/MarginsBundle/Resources/config/services.yml
Normal file
10
bundles/KupShop/MarginsBundle/Resources/config/services.yml
Normal file
@@ -0,0 +1,10 @@
|
||||
services:
|
||||
kupshop.margins.compute.compute:
|
||||
class: KupShop\MarginsBundle\Compute\Compute
|
||||
autowire: true
|
||||
|
||||
KupShop\MarginsBundle\EventListener\MarginMenuListener:
|
||||
class: KupShop\MarginsBundle\EventListener\MarginMenuListener
|
||||
autowire: true
|
||||
tags:
|
||||
- { name: kernel.event_subscriber }
|
||||
@@ -0,0 +1,35 @@
|
||||
<?php
|
||||
|
||||
class UpgradeMargins extends UpgradeNew
|
||||
{
|
||||
public function check_MarginsModule()
|
||||
{
|
||||
return findModule(\Modules::MARGINS) && $this->checkTableExists('margins');
|
||||
}
|
||||
|
||||
/** Create table for margins module*/
|
||||
public function upgrade_MarginsModule()
|
||||
{
|
||||
sqlQuery(' CREATE TABLE IF NOT EXISTS margins (
|
||||
`id` INT(11) NOT NULL AUTO_INCREMENT PRIMARY KEY,
|
||||
`range_from` INT(11) NOT NULL DEFAULT 0,
|
||||
`range_to` INT(11) NOT NULL DEFAULT 0,
|
||||
`margin` FLOAT NOT NULL DEFAULT 0,
|
||||
`title` VARCHAR(250) NOT NULL DEFAULT ""
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||||
');
|
||||
|
||||
$this->upgradeOK();
|
||||
}
|
||||
|
||||
public function check_InnoDBMargins()
|
||||
{
|
||||
return findModule(\Modules::MARGINS) && $this->checkIsInnoDB('margins');
|
||||
}
|
||||
|
||||
/** Fix innodb instead myisam*/
|
||||
public function upgrade_InnoDBMargins()
|
||||
{
|
||||
sqlQuery('ALTER TABLE margins ENGINE = InnoDB;');
|
||||
}
|
||||
}
|
||||
43
bundles/KupShop/MarginsBundle/Tests/MarginsTest.json
Normal file
43
bundles/KupShop/MarginsBundle/Tests/MarginsTest.json
Normal file
@@ -0,0 +1,43 @@
|
||||
{
|
||||
"products" : [
|
||||
{
|
||||
"id": 123,
|
||||
"title": "Test",
|
||||
"code": "QO591",
|
||||
"ean": 321564,
|
||||
"short_descr": "Lorem ipsum dolor sit amet",
|
||||
"long_descr": "",
|
||||
"parameters": "",
|
||||
"price": 1000,
|
||||
"price_buy": 1000,
|
||||
"vat": 1,
|
||||
"discount": 0,
|
||||
"producer": 15,
|
||||
"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,
|
||||
"in_store_min": null
|
||||
}
|
||||
],
|
||||
"margins":[
|
||||
{
|
||||
"id": 4,
|
||||
"range_from": 500,
|
||||
"range_to": 1500,
|
||||
"margin": 20,
|
||||
"title": ""
|
||||
}
|
||||
]
|
||||
}
|
||||
26
bundles/KupShop/MarginsBundle/Tests/MarginsTest.php
Normal file
26
bundles/KupShop/MarginsBundle/Tests/MarginsTest.php
Normal file
@@ -0,0 +1,26 @@
|
||||
<?php
|
||||
|
||||
namespace KupShop\CatalogBundle\Tests;
|
||||
|
||||
use KupShop\KupShopBundle\Util\Compat\ServiceContainer;
|
||||
use KupShop\MarginsBundle\Compute;
|
||||
|
||||
class MarginsTest extends \DatabaseTestCase
|
||||
{
|
||||
public function testMarginsCompute()
|
||||
{
|
||||
/** @var Compute\Compute $service */
|
||||
$service = ServiceContainer::getService('kupshop.margins.compute.compute');
|
||||
$service->computeAll();
|
||||
|
||||
$product = new \Product();
|
||||
$product->createFromDB(123);
|
||||
|
||||
$this->assertEquals('1200', $product->price_array['value_without_vat']->asFloat());
|
||||
}
|
||||
|
||||
public function getDataSet()
|
||||
{
|
||||
return $this->getJsonDataSetFromFile();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user