first commit
This commit is contained in:
@@ -0,0 +1,53 @@
|
||||
<?php
|
||||
|
||||
namespace KupShop\ReclamationsBundle\Admin\Actions;
|
||||
|
||||
use KupShop\AdminBundle\Admin\Actions\AbstractAction;
|
||||
use KupShop\AdminBundle\Admin\Actions\ActionResult;
|
||||
use KupShop\AdminBundle\Admin\Actions\IAction;
|
||||
|
||||
class ReclamationAction extends AbstractAction implements IAction
|
||||
{
|
||||
public function getTypes(): array
|
||||
{
|
||||
return ['orders'];
|
||||
}
|
||||
|
||||
public function getName(): string
|
||||
{
|
||||
return 'Vytvořit reklamaci';
|
||||
}
|
||||
|
||||
public function getHotKeys(): array
|
||||
{
|
||||
return [
|
||||
'key' => 'R',
|
||||
'modifier' => 'ALT+',
|
||||
];
|
||||
}
|
||||
|
||||
public function getPriority(): int
|
||||
{
|
||||
return -50;
|
||||
}
|
||||
|
||||
public function execute(&$data, array $config, string $type): ActionResult
|
||||
{
|
||||
return new ActionResult(true);
|
||||
}
|
||||
|
||||
public function hasDialog()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public function getLaunchHandler()
|
||||
{
|
||||
return "nw('Reclamations', '', 'id_order={$this->getId()}')";
|
||||
}
|
||||
|
||||
public function isEnabled()
|
||||
{
|
||||
return findModule(\Modules::RECLAMATIONS);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
<?php
|
||||
|
||||
namespace KupShop\ReclamationsBundle\Admin\Actions;
|
||||
|
||||
use KupShop\AdminBundle\Admin\Actions\AbstractAction;
|
||||
use KupShop\AdminBundle\Admin\Actions\ActionResult;
|
||||
use KupShop\AdminBundle\Admin\Actions\IAction;
|
||||
use KupShop\ReclamationsBundle\Util\ReclamationsUtil;
|
||||
|
||||
class ReclamationStornoAction extends AbstractAction implements IAction
|
||||
{
|
||||
public function getTypes(): array
|
||||
{
|
||||
return ['Reclamations'];
|
||||
}
|
||||
|
||||
public function getName(): string
|
||||
{
|
||||
return 'Stornovat reklamaci';
|
||||
}
|
||||
|
||||
public function execute(&$data, array $config, string $type): ActionResult
|
||||
{
|
||||
$reclamation = \KupShop\KupShopBundle\Util\Compat\ServiceContainer::getService(ReclamationsUtil::class);
|
||||
$reclamation->changeStatus($this->getID(), ReclamationsUtil::STATUS_HANDLED, 'Způsob vyřízení: Reklamace byla stornována', false);
|
||||
|
||||
return new ActionResult(true, 'Reklamace byla stornována');
|
||||
}
|
||||
|
||||
public function isEnabled()
|
||||
{
|
||||
return findModule(\Modules::RECLAMATIONS) && findRight('RECLAMATIONS');
|
||||
}
|
||||
|
||||
public function getColorText()
|
||||
{
|
||||
return self::COLOR_DANGER;
|
||||
}
|
||||
|
||||
/**
|
||||
* Pokud akci chcete v nějakých stavech dialogu třeba nezobrazit.
|
||||
*
|
||||
* @return false
|
||||
*/
|
||||
public function isVisible()
|
||||
{
|
||||
return empty($this->dialogData['status']);
|
||||
}
|
||||
}
|
||||
540
bundles/KupShop/ReclamationsBundle/Admin/Reclamations.php
Normal file
540
bundles/KupShop/ReclamationsBundle/Admin/Reclamations.php
Normal file
@@ -0,0 +1,540 @@
|
||||
<?php
|
||||
|
||||
namespace KupShop\ReclamationsBundle\Admin;
|
||||
|
||||
use KupShop\AdminBundle\Admin\UserMessagesAdminInterface;
|
||||
use KupShop\BalikonosBundle\Balikobot;
|
||||
use KupShop\BalikonosBundle\Exception\BalikonosException;
|
||||
use KupShop\KupShopBundle\Context\ContextManager;
|
||||
use KupShop\KupShopBundle\Email\UserMessagesInterface;
|
||||
use KupShop\KupShopBundle\Util\Compat\ServiceContainer;
|
||||
use KupShop\OrderingBundle\Util\Order\QRPayment;
|
||||
use KupShop\ReclamationsBundle\Attachment\ReclamationPDFAttachment;
|
||||
use KupShop\ReclamationsBundle\Email\ReclamationMessageEmail;
|
||||
use KupShop\ReclamationsBundle\Util\ReclamationsUtil;
|
||||
use KupShop\ReclamationsSuppliersBundle\Util\ReclamationsSuppliersUtil;
|
||||
use Query\Operator;
|
||||
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
||||
|
||||
class Reclamations extends \Window implements UserMessagesAdminInterface
|
||||
{
|
||||
protected $template = 'window/reclamations.tpl';
|
||||
|
||||
protected $nameField = 'code';
|
||||
protected $tableName = 'reclamations';
|
||||
|
||||
/** @var ReclamationsUtil */
|
||||
public $reclamations;
|
||||
|
||||
private $reclamation;
|
||||
public $contextManager;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->reclamations = ServiceContainer::getService(ReclamationsUtil::class);
|
||||
$this->contextManager = ServiceContainer::getService(ContextManager::class);
|
||||
}
|
||||
|
||||
public function createSQLFields($tablename)
|
||||
{
|
||||
parent::createSQLFields($tablename);
|
||||
|
||||
foreach ($this->fields as $key => $field) {
|
||||
if ($field == 'status') {
|
||||
unset($this->fields[$key]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function get_vars()
|
||||
{
|
||||
if (empty($this->getID())) {
|
||||
$this->action = 'add';
|
||||
}
|
||||
|
||||
$vars = parent::get_vars();
|
||||
|
||||
if ($this->getAction() == 'edit') {
|
||||
$order = $this->prepareOrder($vars['body']['data']['id_order']);
|
||||
|
||||
$diff = 0;
|
||||
if ($order->date_handle) {
|
||||
$diff = $order->date_handle->diff(new \DateTime());
|
||||
$diff = abs($diff->days);
|
||||
}
|
||||
|
||||
$vars['body']['order_date_diff'] = $diff;
|
||||
$vars['body']['order'] = $order;
|
||||
|
||||
$this->contextManager->activateOrder($order, function () use (&$vars) {
|
||||
$vars['body']['emails'] = $this->reclamations->getEmails($this->getReclamation());
|
||||
$vars['body']['emailsInStatuses'] = $this->reclamations->getEmailsInStatuses($this->getReclamation());
|
||||
});
|
||||
|
||||
$vars['body']['exchangeOrder'] = $this->getExchangeOrder();
|
||||
$vars['body']['returnPrice'] = toDecimal($this->getReclamation()->getItem()['total_price'])->addVat($this->getReclamation()->getItem()['tax']);
|
||||
$vars['body']['selected_delivery'] = $this->getDeliveryId();
|
||||
|
||||
$delivery = $this->getDelivery();
|
||||
if ($delivery && isset($vars['body']['data']['data']['delivery_data'])) {
|
||||
$delivery->loadDeliveryInfo($vars['body']['data']['data']['delivery_data']);
|
||||
}
|
||||
|
||||
$vars['body']['delivery'] = $delivery;
|
||||
|
||||
if (findModule(\Modules::RECLAMATIONS_SUPPLIERS)) {
|
||||
$vars['body']['supplierReclamation'] = sqlQueryBuilder()
|
||||
->select('rs.id, rs.code, rs.id_supplier, rs.status, rs.date_created, rs.date_accepted, rs.date_handle')
|
||||
->from('reclamations_suppliers_items', 'rsi')
|
||||
->where(Operator::equals([
|
||||
'id_reclamation' => $this->getID(),
|
||||
]))->join('rsi', 'reclamations_suppliers', 'rs', 'rs.id = rsi.id_reclamation_supplier')
|
||||
->execute()->fetchAssociative();
|
||||
|
||||
if (findModule(\Modules::PRODUCTS_SERIAL_NUMBERS)) {
|
||||
$vars['body']['serialNumberSuppliers'] = sqlQueryBuilder()->select('si.id_supplier')->from('products_serial_numbers',
|
||||
'psn')
|
||||
->innerJoin('psn', 'stock_in', 'si', 'psn.id_stock_in = si.id')
|
||||
->where(Operator::equals(['psn.id_order_item' => $vars['body']['data']['id_item']]))
|
||||
->execute()->fetchFirstColumn();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($this->getAction() == 'add') {
|
||||
$vars['body']['data']['id_order'] = getVal('id_order', null, '');
|
||||
}
|
||||
|
||||
$vars['body']['statuses'] = $this->reclamations->getStatuses();
|
||||
$vars['body']['handle_statuses'] = $this->reclamations->getHandleStatuses();
|
||||
$vars['body']['handle_types'] = $this->reclamations->getHandleTypes();
|
||||
$vars['body']['preferred_handle_types'] = $this->reclamations->getPrefHandleTypes();
|
||||
$vars['body']['address_fields'] = $this->reclamations->getAddressFields();
|
||||
|
||||
$vars['body']['deliveries'] = \Delivery::getAll();
|
||||
|
||||
$fakeOrder = new \Order();
|
||||
if (isset($vars['body']['data']['data']['delivery_data'])) {
|
||||
$fakeOrder->note_admin = json_encode(['delivery_data' => $vars['body']['data']['data']['delivery_data']]);
|
||||
}
|
||||
|
||||
$vars['body']['fakeOrder'] = $fakeOrder;
|
||||
|
||||
if (findModule(\Modules::PRODUCTS_SUPPLIERS) && $this->getAction() != 'add') {
|
||||
$item = $this->getReclamation()->getItem();
|
||||
$suppliersCodes = sqlQueryBuilder()->select('s.id, s.name, pos.code')
|
||||
->from('products_of_suppliers', 'pos')
|
||||
->leftJoin('pos', 'suppliers', 's', 's.id = pos.id_supplier')
|
||||
->where(\Query\Operator::equalsNullable(['id_product' => $item['id_product'], 'id_variation' => $item['id_variation']]))
|
||||
->execute()->fetchAll();
|
||||
|
||||
$vars['body']['suppliers_codes'] = $suppliersCodes;
|
||||
}
|
||||
|
||||
return $vars;
|
||||
}
|
||||
|
||||
public function getExchangeOrder()
|
||||
{
|
||||
$id = $this->getReclamation() === false
|
||||
? null
|
||||
: $this->getReclamation()->getData()['exchange_order'] ?? null;
|
||||
|
||||
if ($id) {
|
||||
$order = $this->prepareOrder($id);
|
||||
|
||||
return $order;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public function sendToBalikobot()
|
||||
{
|
||||
if (!findModule(\Modules::BALIKONOS)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$balikobot = ServiceContainer::getService(Balikobot::class);
|
||||
|
||||
if ($this->getReclamation()->getIdBalikonos()) {
|
||||
return;
|
||||
}
|
||||
|
||||
$address = $this->getReclamation()->getAddress();
|
||||
$deliveryId = $this->getDeliveryId();
|
||||
$deliveries = \Delivery::getAll();
|
||||
|
||||
$delivery = $deliveries[$deliveryId] ?? null;
|
||||
|
||||
// do not send to balikobot if in person
|
||||
if ($delivery && $delivery->isInPerson()) {
|
||||
return;
|
||||
}
|
||||
|
||||
$orderCls = new \Order();
|
||||
$orderCls->currency = $this->getReclamation()->getIdCurrency();
|
||||
$orderCls->note_admin = json_encode(['delivery_data' => $this->getReclamation()->getData()['delivery_data'] ?? []]);
|
||||
|
||||
$balikobot->setIDs([
|
||||
0 => [
|
||||
'type' => Balikobot::TYPE_RECLAMATION,
|
||||
'invoice_email' => $this->getReclamation()->getEmail(),
|
||||
'invoice_name' => $address['name'],
|
||||
'invoice_surname' => $address['surname'],
|
||||
'invoice_street' => $address['street'],
|
||||
'invoice_city' => $address['city'],
|
||||
'invoice_zip' => $address['zip'],
|
||||
'invoice_country' => !empty($address['country']) ? $address['country'] : 'CZ',
|
||||
'invoice_phone' => $address['phone'],
|
||||
'total_price' => $this->getReclamation()->getItem()['total_price'],
|
||||
'id_delivery' => $deliveryId,
|
||||
'cod_price' => 0,
|
||||
'order_id' => $this->getReclamation()->getCode(),
|
||||
'order' => $orderCls,
|
||||
'weight' => $this->getReclamation()->getItem()['weight'],
|
||||
],
|
||||
]);
|
||||
|
||||
$balikobot->sendDeliveries();
|
||||
|
||||
$result = $balikobot->getResult();
|
||||
$result = reset($result);
|
||||
|
||||
if (!empty($result['error_message']) && $result['error_message'] != 'OK') {
|
||||
$this->returnError('Chyba při odesílání do balíkobotu: '.$result['error_message']);
|
||||
}
|
||||
|
||||
$this->updateSQL('reclamations', ['package_id' => $result['package_id'] ?? null, 'id_balikonos' => $result['id_balikonos'] ?? null], ['id' => $this->getID()]);
|
||||
}
|
||||
|
||||
protected function getDeliveryId()
|
||||
{
|
||||
$dbcfg = \Settings::getDefault();
|
||||
|
||||
if ($this->getReclamation()) {
|
||||
$delivery = $this->reclamations->getData($this->getReclamation()->getId(), 'delivery');
|
||||
if (!empty($delivery)) {
|
||||
return $delivery;
|
||||
}
|
||||
|
||||
$order = $this->prepareOrder($this->getReclamation()->getIdOrder());
|
||||
if ($order->getDeliveryType() && $order->getDeliveryType()->id_delivery != null) {
|
||||
return $order->getDeliveryType()->id_delivery;
|
||||
}
|
||||
}
|
||||
|
||||
return $dbcfg->reclamations['delivery'] ?? null;
|
||||
}
|
||||
|
||||
private function deleteFromBalikobot($package_id)
|
||||
{
|
||||
if (!findModule(\Modules::BALIKONOS)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$balikobot = ServiceContainer::getService(Balikobot::class);
|
||||
try {
|
||||
$balikobot->deletePackage($package_id);
|
||||
} catch (BalikonosException $e) {
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public function getQRPayment()
|
||||
{
|
||||
$dbcfg = \Settings::getDefault();
|
||||
|
||||
$returnPrice = toDecimal($this->getReclamation()->getItem()['total_price'])->addVat($this->getReclamation()->getItem()['tax']);
|
||||
|
||||
$parameters = [
|
||||
'amount' => $returnPrice->asFloat(),
|
||||
'currency' => 'CZK',
|
||||
'vs' => $this->getReclamation()->getCode(),
|
||||
'message' => $dbcfg->shop_firm_name.' Reklamace '.$this->getReclamation()->getCode(),
|
||||
];
|
||||
|
||||
/** @var QRPayment $QRPayment */
|
||||
$QRPayment = ServiceContainer::getService(QRPayment::class);
|
||||
|
||||
$accountNumberParameters = $QRPayment->parseAccountNumber($this->getReclamation()->getBankAccount());
|
||||
|
||||
$parameters = array_merge($parameters, $accountNumberParameters);
|
||||
|
||||
return $QRPayment->getQRCodeImageUrl(
|
||||
$this->prepareOrder($this->getReclamation()->getIdOrder()), 200, $parameters
|
||||
);
|
||||
}
|
||||
|
||||
public function handlePrintLabel()
|
||||
{
|
||||
if (!findModule(\Modules::BALIKONOS)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$balikobot = ServiceContainer::getService(Balikobot::class);
|
||||
|
||||
if (empty($this->getReclamation()->getIdBalikonos())) {
|
||||
$this->returnError('Štítek nelze vytisknout, protože reklamace není v balíkobotu! Zkuste reklamaci odeslat do balíkobotu znovu tím, že na detailu reklamace kliknete na tlačítko "OK"');
|
||||
}
|
||||
|
||||
try {
|
||||
$balikobot->printTickets(null, 1, 'default', [], false, [$this->getReclamation()->getIdBalikonos()]);
|
||||
} catch (\KupShop\BalikonosBundle\Exception\BalikonosException $e) {
|
||||
$this->returnError($e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public function handlePrintReclamation()
|
||||
{
|
||||
/** @var ReclamationPDFAttachment $reclamationAttachment */
|
||||
$reclamationAttachment = ServiceContainer::getService(ReclamationPDFAttachment::class);
|
||||
$reclamationAttachment->setReclamation($this->getReclamation());
|
||||
$this->contextManager->activateContexts([\KupShop\KupShopBundle\Context\LanguageContext::class => $reclamationAttachment->getReclamation()['id_language']], function () use ($reclamationAttachment) {
|
||||
header('Content-type: application/pdf');
|
||||
header('Content-Disposition: inline; filename="'.$reclamationAttachment->getFilename().'"');
|
||||
|
||||
echo $reclamationAttachment->getContent();
|
||||
});
|
||||
}
|
||||
|
||||
public function handleSupplierReclamation()
|
||||
{
|
||||
/**
|
||||
* @var $reclamationsSuppliersUtil ReclamationsSuppliersUtil
|
||||
*/
|
||||
$reclamationsSuppliersUtil = ServiceContainer::getService(ReclamationsSuppliersUtil::class);
|
||||
|
||||
$supplierId = getVal('supplierId');
|
||||
$reclamation = $this->getReclamation();
|
||||
|
||||
$reclamationsSuppliersUtil->addItemFromReclamation($supplierId, $reclamation);
|
||||
|
||||
$this->returnOK('Produkt přidán do reklamace k dodavateli', false, ['supplierId' => null]);
|
||||
}
|
||||
|
||||
public function handleUpdate()
|
||||
{
|
||||
$data = $this->getData();
|
||||
|
||||
if ($this->getAction() == 'add') {
|
||||
$delivery = [];
|
||||
foreach ($this->reclamations->getAddressFields() as $field) {
|
||||
$delivery[$field] = getVal($field, $data);
|
||||
}
|
||||
|
||||
if (empty($data['id_item'])) {
|
||||
$this->returnError('Nevybrali jste položku!');
|
||||
}
|
||||
|
||||
// todo: set pieces in admin
|
||||
if (empty($data['pieces'])) {
|
||||
$data['pieces'] = 1;
|
||||
}
|
||||
|
||||
if ($id = $this->reclamations->createReclamation($data['id_item'], $data['pieces'], $delivery, $data['bank_account'], null, null, false)) {
|
||||
$this->setID($id);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
} elseif ($this->getAction() == 'edit') {
|
||||
if ($delivery = $this->getDelivery()) {
|
||||
$data['data']['delivery_data'] = $delivery->storeDeliveryInfo($data['delivery_data'] ?? []);
|
||||
|
||||
// Update address from delivery
|
||||
$delivery->applyToOrder($delivery_data, new \Order());
|
||||
if ($delivery_data) {
|
||||
foreach ($delivery_data as $field => $value) {
|
||||
$this->processedData[str_replace('delivery_', '', $field)] = $value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$return = parent::handleUpdate();
|
||||
|
||||
// save data before sendToBalikobot call
|
||||
if (!empty($data['data']) && is_array($data['data'])) {
|
||||
foreach ($data['data'] as $key => $value) {
|
||||
$this->reclamations->setData($this->getID(), $key, $value);
|
||||
}
|
||||
// Potřebuju dál pro balíkobota aktuální data, getReclamation vracelo zacachovanou verzi před updatem
|
||||
$this->reclamation = $this->reclamations->getReclamation($this->getID());
|
||||
}
|
||||
|
||||
$reclamation = $this->getReclamation();
|
||||
if (!is_null($data['handle_type']) && in_array($data['handle_type'], $this->getPrintLabelHandleTypes())) {
|
||||
$this->sendToBalikobot();
|
||||
} elseif (!empty($reclamation->getIdBalikonos()) && $reclamation['status'] != 2) {
|
||||
$this->deleteFromBalikobot($this->getReclamation()->getIdBalikonos());
|
||||
}
|
||||
|
||||
$userContent = ServiceContainer::getService(\KupShop\OrderingBundle\Util\UserContent\UserContent::class);
|
||||
if (($user_content = $userContent->getData('reclamation')) && $reclamation) {
|
||||
$this->reclamations->setData($this->getID(), 'userContent',
|
||||
array_merge($reclamation->getData()['userContent'] ?? [], $user_content)
|
||||
);
|
||||
$userContent->clearData('reclamation');
|
||||
}
|
||||
|
||||
$sendEmail = (!isset($data['doNotNotify'])) ? null : false;
|
||||
if (!empty($data['comment']) && !isset($data['doNotNotify'])) {
|
||||
$sendEmail = true;
|
||||
}
|
||||
|
||||
if ($data['handle_type'] != null) {
|
||||
$data['status'] = ReclamationsUtil::STATUS_HANDLED;
|
||||
}
|
||||
|
||||
if (isset($data['status'])) {
|
||||
$this->reclamations->changeStatus($this->getID(), $data['status'], $data['comment'], $sendEmail, $data['user_message']);
|
||||
}
|
||||
|
||||
if ($data['handle_type'] == '0' || $data['handle_type'] == '2' || $data['handle_type'] == '4') {
|
||||
$this->handleConvertToReturn($data['comment'], $data['handle_type'] != '4');
|
||||
}
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public function getPrintLabelHandleTypes()
|
||||
{
|
||||
return [1, 3];
|
||||
}
|
||||
|
||||
public function handleReopen()
|
||||
{
|
||||
$data = $this->getData();
|
||||
if (empty($data['comment'])) {
|
||||
$data['comment'] = null;
|
||||
}
|
||||
|
||||
$this->reclamations->changeStatus($this->getID(), 1, 'Reklamace byla znovu otevřena', false);
|
||||
$this->updateSQL('reclamations', [
|
||||
'handle_type' => null,
|
||||
'date_handle' => null,
|
||||
'package_id' => null,
|
||||
'id_balikonos' => null,
|
||||
], ['id' => $this->getID()]);
|
||||
|
||||
$this->returnOK('Reklamace byla znovu otevřena');
|
||||
}
|
||||
|
||||
public function handleConvertToReturn($comment, bool $isReclamation = true)
|
||||
{
|
||||
/** @var \KupShop\ReturnsBundle\Util\ReturnsUtil $returnsUtil */
|
||||
$returnsUtil = ServiceContainer::getService(\KupShop\ReturnsBundle\Util\ReturnsUtil::class);
|
||||
|
||||
$reasons = array_keys($returnsUtil->getReasons());
|
||||
$reasonId = end($reasons);
|
||||
$item = ['pieces' => $this->getReclamation()->getPieces(), 'return_reason' => $reasonId];
|
||||
|
||||
$returnId = $returnsUtil->createReturn(
|
||||
$this->getReclamation()->getBankAccount() ?: '',
|
||||
[$this->getReclamation()->getIdItem() => $item],
|
||||
[],
|
||||
null,
|
||||
false
|
||||
);
|
||||
|
||||
$return = $returnsUtil->getReturn($returnId);
|
||||
|
||||
$returnMessage = 'Vratka byla vytvořena pro vyřízení reklamace č.';
|
||||
if (!$isReclamation) {
|
||||
$returnMessage = 'Vratka vytvořena na základě reklamace č.';
|
||||
}
|
||||
$returnsUtil->logHistory($returnId, $returnMessage." <a href=\"javascript:nw('Reclamations', {$this->getReclamation()->getId()})\">{$this->getReclamation()->getCode()}");
|
||||
|
||||
$this->reclamations->setData($this->getReclamation()->getId(), 'return', $returnId);
|
||||
|
||||
$reclamationMessage = 'Pro vyřízení reklamace byla vytvořena vratka č.';
|
||||
if (!$isReclamation) {
|
||||
$reclamationMessage = 'Na základě reklamace byla vytvořená vratka č.';
|
||||
}
|
||||
$this->reclamations->logHistory($this->getReclamation()->getId(), $reclamationMessage.' <a href="javascript:nw(\'Returns\', '.$returnId.')">'.$return->getCode().'</a>', false, '2');
|
||||
|
||||
$orderMessage = 'Pro vyřízení reklamace č.';
|
||||
if (!$isReclamation) {
|
||||
$orderMessage = 'Na základě reklamace č.';
|
||||
}
|
||||
$order = new \Order($this->getReclamation()->getIdOrder());
|
||||
$order->createFromDB($this->getReclamation()->getIdOrder());
|
||||
$order->logHistory($orderMessage.' '.$this->getReclamation()->getId().' byla vytvořena vratka č. <a href="javascript:nw(\'Returns\', '.$returnId.')">'.$return->getCode().'</a>');
|
||||
|
||||
$params = [
|
||||
's' => 'Returns.php',
|
||||
'acn' => 'edit',
|
||||
'ID' => $returnId,
|
||||
];
|
||||
$this->redirect($params);
|
||||
}
|
||||
|
||||
public function prepareOrder($orderId)
|
||||
{
|
||||
$order = new \Order();
|
||||
$order->createFromDB($orderId);
|
||||
|
||||
return $order;
|
||||
}
|
||||
|
||||
public function getData()
|
||||
{
|
||||
$data = parent::getData();
|
||||
|
||||
if (getVal('Submit') && (!$this->getID() || !$this->getReclamation()->isClosed())) {
|
||||
if (empty($data['status'])) {
|
||||
$data['status'] = 0;
|
||||
}
|
||||
|
||||
$dates = ['date_created', 'date_accepted', 'date_handle'];
|
||||
foreach ($dates as $date) {
|
||||
if (!empty($data[$date])) {
|
||||
$data[$date] = $this->prepareDateTime($data[$date]);
|
||||
}
|
||||
}
|
||||
|
||||
if (($data['handle_type'] ?? -1) < 0) {
|
||||
$data['handle_type'] = null;
|
||||
}
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
protected function getReclamation()
|
||||
{
|
||||
if (!$this->reclamation) {
|
||||
$this->reclamation = $this->reclamations->getReclamation($this->getID());
|
||||
}
|
||||
|
||||
return $this->reclamation;
|
||||
}
|
||||
|
||||
protected function getObject()
|
||||
{
|
||||
$object = $this->getReclamation();
|
||||
if (!$object) {
|
||||
$errStr = sprintf(translate('errorNotFound', 'base'), $this->translateType(), $this->getID());
|
||||
throw new NotFoundHttpException($errStr);
|
||||
}
|
||||
|
||||
return $object;
|
||||
}
|
||||
|
||||
protected function getDelivery()
|
||||
{
|
||||
return \Delivery::getAll()[$this->getDeliveryId()] ?? null;
|
||||
}
|
||||
|
||||
public function getUserEmails(): UserMessagesInterface
|
||||
{
|
||||
return ServiceContainer::getService(ReclamationMessageEmail::class);
|
||||
}
|
||||
}
|
||||
|
||||
return Reclamations::class;
|
||||
@@ -0,0 +1,21 @@
|
||||
<?php
|
||||
|
||||
namespace KupShop\ReclamationsBundle\Admin\Tabs;
|
||||
|
||||
class ReclamationsLanguageSettingsWindowTab extends ReclamationsWindowTab
|
||||
{
|
||||
protected $title = 'flapReclamationsLanguageSettings';
|
||||
protected $template = 'window/languagesSettings.reclamations.tpl';
|
||||
|
||||
public static function getTypes()
|
||||
{
|
||||
return [
|
||||
'languagesSettings' => 1,
|
||||
];
|
||||
}
|
||||
|
||||
public function getLabel()
|
||||
{
|
||||
return translate('flapReclamationsSettings', 'reclamationsWindowTab');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,108 @@
|
||||
<?php
|
||||
|
||||
namespace KupShop\ReclamationsBundle\Admin\Tabs;
|
||||
|
||||
use KupShop\AdminBundle\Admin\WindowTab;
|
||||
use KupShop\KupShopBundle\Util\Compat\SymfonyBridge;
|
||||
use Symfony\Component\HttpFoundation\File\UploadedFile;
|
||||
|
||||
class ReclamationsWindowTab extends WindowTab
|
||||
{
|
||||
protected $title = 'flapReclamationsSettings';
|
||||
protected $template = 'window/settings.reclamations.tpl';
|
||||
|
||||
public static function getTypes()
|
||||
{
|
||||
return [
|
||||
'settings' => 1,
|
||||
];
|
||||
}
|
||||
|
||||
public function getVars($smarty_tpl_vars)
|
||||
{
|
||||
$vars = parent::getVars($smarty_tpl_vars);
|
||||
|
||||
$vars['tabView'] = $this;
|
||||
$vars['deliveries'] = \Delivery::getAll();
|
||||
|
||||
if (findModule(\Modules::RETURNS, \Modules::SUB_CP_AUTH_CODES)) {
|
||||
$vars['reclamations_auth_codes'] = sqlFetch($this->selectSQL('returns_auth_codes', [], ['COUNT(*) as total', 'SUM(used="Y") as used']));
|
||||
}
|
||||
|
||||
return $vars;
|
||||
}
|
||||
|
||||
public function handleImportAuthCodes()
|
||||
{
|
||||
if ($path = $this->getFile()) {
|
||||
try {
|
||||
$csv = new \SplFileObject($path);
|
||||
$csv->setFlags(\SplFileObject::READ_CSV);
|
||||
$csv->setCsvControl(';', "'");
|
||||
if ($csv->valid()) {
|
||||
$columns = ['ID', 'Note', 'Date', 'Date2', 'Date3', 'PackageID'];
|
||||
$codes = [];
|
||||
while ($csv->valid()) {
|
||||
$row_data = $csv->current();
|
||||
if (count($row_data) == count($columns)) {
|
||||
$row_data = array_combine($columns, $row_data);
|
||||
$code = trim($row_data['ID']);
|
||||
$date = trim($row_data['Date2']);
|
||||
$packageID = trim($row_data['PackageID'], '"');
|
||||
if (empty($packageID) && empty($date)) {
|
||||
$codes[] = ['code' => $code];
|
||||
sqlQuery("INSERT IGNORE INTO `returns_auth_codes` (`code`) VALUES ('{$code}')");
|
||||
}
|
||||
}
|
||||
$csv->next();
|
||||
}
|
||||
}
|
||||
} catch (Error $e) {
|
||||
$error = 'Chyba: '.$e->getMessage();
|
||||
|
||||
$this->window->returnError($error);
|
||||
}
|
||||
}
|
||||
|
||||
$this->window->returnOK();
|
||||
}
|
||||
|
||||
public function getPlaceholders()
|
||||
{
|
||||
$placeholders = [
|
||||
'KOD_REKLAMACE' => [
|
||||
'text' => 'Kód vytvořené reklamace',
|
||||
],
|
||||
'ODKAZ_PDF' => [
|
||||
'text' => 'Odkaz na reklamační protokol',
|
||||
],
|
||||
'ODKAZ_VRATKA' => [
|
||||
'text' => 'Odkaz na vratku',
|
||||
],
|
||||
'KOD_VRATKY' => [
|
||||
'text' => 'Kód vratky',
|
||||
],
|
||||
];
|
||||
|
||||
if (findModule(\Modules::RETURNS, \Modules::SUB_CP_AUTH_CODES)) {
|
||||
$placeholders['PACKAGE_LABEL'] = [
|
||||
'text' => 'Autorizační kód Odvozu zboží',
|
||||
];
|
||||
}
|
||||
|
||||
return $placeholders;
|
||||
}
|
||||
|
||||
public function getFile()
|
||||
{
|
||||
$request = SymfonyBridge::getCurrentRequest();
|
||||
|
||||
/** @var $file UploadedFile */
|
||||
$file = $request->files->get('file');
|
||||
if (!$file) {
|
||||
return '';
|
||||
}
|
||||
|
||||
return $file->getRealPath();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
<?php
|
||||
|
||||
$txt_str['Reclamations'] = [
|
||||
'navigation' => 'Reklamace',
|
||||
'toolbar_list' => 'Seznam reklamací',
|
||||
'toolbar_add' => 'Nová reklamace',
|
||||
'toolbar_massmodif' => 'Hromadné zpracování',
|
||||
'search' => 'Vyhledávání',
|
||||
'upcoming' => 'Blížící se termín',
|
||||
'searchCode' => 'Zadejte číslo / kód reklamace',
|
||||
'selectStatus' => 'Vyberte status',
|
||||
'delete' => 'Smazat',
|
||||
'searchBtn' => 'Hledat',
|
||||
|
||||
'titleEdit' => 'Úprava reklamace',
|
||||
'titleAdd' => 'Nová reklamace',
|
||||
|
||||
'reclamations' => 'Reklamace',
|
||||
'user' => 'Údaje zákazníka',
|
||||
|
||||
'filterTerm' => 'Podle termínu',
|
||||
'filterBasic' => 'Základní vyhledávání',
|
||||
'filterByProduct' => 'Podle produktu',
|
||||
|
||||
'selectOrder' => 'Vyberte objednávku',
|
||||
'selectItem' => 'Vyberte položku',
|
||||
'searchOrder' => 'Hledat objednávku...',
|
||||
'searchItem' => 'Hledat položku...',
|
||||
'handleType' => 'Vyberte způsob vyřízení',
|
||||
'order' => 'Objednávka',
|
||||
'product' => 'Produkt',
|
||||
'date_created' => 'Datum vytvoření',
|
||||
'date_accepted' => 'Datum přijetí',
|
||||
'date_handle' => 'Datum vyřízení',
|
||||
'date_handle_from' => 'Vyřízeno od',
|
||||
'date_handle_to' => 'Vyřízeno do',
|
||||
'address' => 'Adresa',
|
||||
'name' => 'Jméno',
|
||||
'surname' => 'Příjmení',
|
||||
'street' => 'Ulice',
|
||||
'city' => 'Město',
|
||||
'phone' => 'Telefon',
|
||||
'zip' => 'PSČ',
|
||||
'country' => 'Stát',
|
||||
'bank_account' => 'Číslo účtu',
|
||||
'handle_type' => 'Způsob vyřízení',
|
||||
'preferred_handle_type' => 'Požadovaný způsob vyřízení',
|
||||
'history' => 'Historie',
|
||||
'note' => 'Poznámka',
|
||||
'sent' => 'Odesláno',
|
||||
'comments' => 'Komentář',
|
||||
'descr' => 'Posudek',
|
||||
'user_note' => 'Důvod reklamace',
|
||||
'other' => 'Ostatní',
|
||||
|
||||
'delivery' => 'Doprava',
|
||||
|
||||
'code' => 'Kód',
|
||||
'created' => 'Vytvořeno',
|
||||
'accepted' => 'Přijato',
|
||||
'handle' => 'Vyřízeno',
|
||||
'status' => 'Stav',
|
||||
'customer' => 'Zákazník',
|
||||
'item' => 'Produkt',
|
||||
'id_order' => 'Číslo objednávky',
|
||||
|
||||
'suppliers_codes' => 'Kódy dodavatelů produktu',
|
||||
'supplier' => 'Dodavatel',
|
||||
'supplier_code' => 'Kód dodavatele',
|
||||
|
||||
'order_history' => 'Z této objednávky byla vytvořena reklamace č.:',
|
||||
|
||||
'nearDeadline' => 'Počet reklamací blížících se ke konci lhůty: %s. Např. reklamace s č. %s',
|
||||
|
||||
'deadline' => 'Termín',
|
||||
|
||||
'activityEdited' => 'Upravena reklamace: %s',
|
||||
'activityAdded' => 'Přidána reklamace: %s',
|
||||
'activityDeleted' => 'Smazána reklamace: %s',
|
||||
|
||||
'commentConfirm' => 'Opravdu chcete stornovat tuto reklamaci?<br>Tato akce již nepůjde vrátit.',
|
||||
|
||||
'handled' => 'Vyřízena',
|
||||
'new' => 'Nová',
|
||||
|
||||
'supplier_reclamation_action' => 'Reklamovat',
|
||||
'supplier_reclamation' => 'Reklamace u dodavatele',
|
||||
'serial_number_from_supplier' => 'Produkt má sériové číslo od tohoto dodavatele',
|
||||
|
||||
'activityLogTag' => 'Reklamace',
|
||||
];
|
||||
@@ -0,0 +1,5 @@
|
||||
<?php
|
||||
|
||||
$txt_str['ReclamationsMassModification'] = [
|
||||
'navigation' => 'Hromadné zpracování reklamací',
|
||||
];
|
||||
@@ -0,0 +1,13 @@
|
||||
<?php
|
||||
|
||||
$txt_str['reclamationsWindowTab'] = [
|
||||
'flapReclamationsSettings' => 'Reklamace',
|
||||
'flapReclamationsInstructions' => 'Instrukce reklamace zboží',
|
||||
'reclamation_days' => 'Počet dní přidaných k záruce',
|
||||
'reclamation_days_tooltip' => 'Počet dní přidaných k záruce, kdy je možné záruku uplatnit',
|
||||
'returnDescr' => 'Popis způsobu reklamace zboží',
|
||||
'delivery' => 'Doprava',
|
||||
'shopkeeperEmail' => 'Obchodníkův email',
|
||||
'shopkeeperEmailInfo' => 'Na tuto adresu budou chodit oznámení o přijetí nové reklamace. Je-li prázdné, oznámení se odešle na email ze základního nastavení emailů.',
|
||||
'reclamationsDelivery' => 'Výchozí nastavení, pokud není možné načíst dopravu z reklamace nebo z objednávky',
|
||||
];
|
||||
@@ -0,0 +1,80 @@
|
||||
<?php
|
||||
|
||||
$txt_str['Reclamations'] = [
|
||||
'navigation' => 'Reklamace',
|
||||
'toolbar_list' => 'Seznam reklamací',
|
||||
'toolbar_add' => 'Nová reklamace',
|
||||
'toolbar_massmodif' => 'Hromadné zpracování',
|
||||
'search' => 'Vyhledávání',
|
||||
'upcoming' => 'Blížící se termín',
|
||||
'searchCode' => 'Zadejte číslo / kód reklamace',
|
||||
'selectStatus' => 'Vyberte status',
|
||||
'delete' => 'Smazat',
|
||||
'searchBtn' => 'Hledat',
|
||||
|
||||
'titleEdit' => 'Úprava reklamace',
|
||||
'titleAdd' => 'Nová reklamace',
|
||||
|
||||
'reclamations' => 'Reklamace',
|
||||
'user' => 'Údaje zákazníka',
|
||||
|
||||
'filterTerm' => 'Podle termínu',
|
||||
'filterBasic' => 'Základní vyhledávání',
|
||||
'filterByProduct' => 'Podle produktu',
|
||||
|
||||
'selectOrder' => 'Vyberte objednávku',
|
||||
'selectItem' => 'Vyberte položku',
|
||||
'searchOrder' => 'Hledat objednávku...',
|
||||
'searchItem' => 'Hledat položku...',
|
||||
'handleType' => 'Vyberte způsob vyřízení',
|
||||
'preferred_handle_type' => 'The mode of handling the claim',
|
||||
'order' => 'Objednávka',
|
||||
'product' => 'Produkt',
|
||||
'date_created' => 'Datum vytvoření',
|
||||
'date_accepted' => 'Datum přijetí',
|
||||
'date_handle' => 'Datum vyřízení',
|
||||
'address' => 'Adresa',
|
||||
'name' => 'Jméno',
|
||||
'surname' => 'Příjmení',
|
||||
'street' => 'Ulice',
|
||||
'city' => 'Město',
|
||||
'phone' => 'Telefon',
|
||||
'zip' => 'PSČ',
|
||||
'country' => 'Stát',
|
||||
'bank_account' => 'Číslo účtu',
|
||||
'handle_type' => 'Způsob vyřízení',
|
||||
'history' => 'Historie',
|
||||
'note' => 'Poznámka',
|
||||
'sent' => 'Odesláno',
|
||||
'comments' => 'Komentář',
|
||||
'descr' => 'Posudek',
|
||||
'user_note' => 'Důvod reklamace',
|
||||
'other' => 'Ostatní',
|
||||
|
||||
'delivery' => 'Doprava',
|
||||
|
||||
'code' => 'Kód',
|
||||
'created' => 'Vytvořeno',
|
||||
'accepted' => 'Accepted',
|
||||
'handle' => 'Vyřízeno',
|
||||
'status' => 'Stav',
|
||||
'customer' => 'Zákazník',
|
||||
'item' => 'Produkt',
|
||||
'id_order' => 'Číslo objednávky',
|
||||
|
||||
'suppliers_codes' => 'Kódy dodavatelů produktu',
|
||||
'supplier' => 'Dodatavel',
|
||||
'supplier_code' => 'Kód dodavatele',
|
||||
|
||||
'order_history' => 'Z této objednávky byla vytvořena reklamace č.:',
|
||||
'deadline' => 'Deadline',
|
||||
|
||||
'handled' => 'Handled',
|
||||
'new' => 'New',
|
||||
|
||||
'supplier_reclamation_action' => 'Reklamovat',
|
||||
'supplier_reclamation' => 'Reklamace u dodavatele',
|
||||
'serial_number_from_supplier' => 'Produkt má sériové číslo od tohoto dodavatele',
|
||||
|
||||
'activityLogTag' => 'Reclamations',
|
||||
];
|
||||
@@ -0,0 +1,5 @@
|
||||
<?php
|
||||
|
||||
$txt_str['ReclamationsMassModification'] = [
|
||||
'navigation' => 'Hromadné zpracování reklamací',
|
||||
];
|
||||
@@ -0,0 +1,13 @@
|
||||
<?php
|
||||
|
||||
$txt_str['reclamationsWindowTab'] = [
|
||||
'flapReclamationsSettings' => 'Reklamace',
|
||||
'flapReclamationsInstructions' => 'Instrukce reklamace zboží',
|
||||
'reclamation_days' => 'Počet dní přidaných k záruce',
|
||||
'reclamation_days_tooltip' => 'Počet dní přidaných k záruce, kdy je možné záruku uplatnit',
|
||||
'returnDescr' => 'Popis způsobu reklamace zboží',
|
||||
'delivery' => 'Doprava',
|
||||
'shopkeeperEmail' => 'Obchodníkův email',
|
||||
'shopkeeperEmailInfo' => 'Na tuto adresu budou chodit oznámení o přijetí nové reklamace.',
|
||||
'reclamationsDelivery' => 'Výchozí nastavení, pokud není možné načíst dopravu z reklamace nebo z objednávky',
|
||||
];
|
||||
@@ -0,0 +1,248 @@
|
||||
<?php
|
||||
|
||||
namespace KupShop\ReclamationsBundle\Admin\lists;
|
||||
|
||||
use KupShop\AdminBundle\AdminList\BaseList;
|
||||
use KupShop\AdminBundle\AdminList\FiltersStorage;
|
||||
use KupShop\AdminBundle\Query\Invert;
|
||||
use KupShop\KupShopBundle\Util\Compat\ServiceContainer;
|
||||
use KupShop\KupShopBundle\Util\HtmlBuilder\HTML;
|
||||
use KupShop\ReclamationsBundle\Util\ReclamationsUtil;
|
||||
use Query\Operator;
|
||||
|
||||
class ReclamationsList extends BaseList
|
||||
{
|
||||
use FiltersStorage;
|
||||
|
||||
protected $showMassEdit = true;
|
||||
protected $tableName = 'reclamations';
|
||||
protected ?string $tableAlias = 'r';
|
||||
|
||||
protected $tableDef = [
|
||||
'id' => 'r.id',
|
||||
'fields' => [
|
||||
'code' => ['translate' => true, 'translation_section' => 'Reclamations', 'field' => 'r.id', 'render' => 'renderCode', 'size' => 0.25],
|
||||
'created' => ['translate' => true, 'translation_section' => 'Reclamations', 'field' => 'r.date_created', 'render' => 'renderDateTime'],
|
||||
'accepted' => ['translate' => true, 'translation_section' => 'Reclamations', 'field' => 'r.date_accepted', 'render' => 'renderDateTime'],
|
||||
'handle' => ['translate' => true, 'translation_section' => 'Reclamations', 'field' => 'r.date_handle', 'render' => 'renderDateTime'],
|
||||
'status' => ['translate' => true, 'translation_section' => 'Reclamations', 'field' => 'r.status', 'spec' => 'r.status', 'render' => 'renderStatus', 'size' => 0.5, 'fieldType' => ReclamationsList::TYPE_LIST],
|
||||
'customer' => ['translate' => true, 'translation_section' => 'Reclamations', 'field' => 'id_user', 'render' => 'renderCustomer', 'size' => 0.75],
|
||||
'item' => ['translate' => true, 'translation_section' => 'Reclamations', 'field' => 'id_product', 'render' => 'renderProduct'],
|
||||
'id_order' => ['translate' => true, 'translation_section' => 'Reclamations', 'field' => 'r.id', 'render' => 'renderOrderId'],
|
||||
'user_note' => ['translate' => true, 'translation_section' => 'Reclamations', 'field' => 'r.user_note', 'spec' => 'r.user_note', 'visible' => 'N', 'fieldType' => BaseList::TYPE_STRING],
|
||||
'descr' => ['translate' => true, 'translations_sections' => 'Reclamations', 'field' => 'r.descr', 'spec' => 'r.descr', 'visible' => 'N', 'fieldType' => BaseList::TYPE_STRING],
|
||||
'deadline' => ['translate' => true, 'translation_section' => 'Reclamations', 'render' => 'renderDeadline', 'size' => 0.5],
|
||||
],
|
||||
'class' => 'getRowClass',
|
||||
];
|
||||
|
||||
public function customizeTableDef($tableDef)
|
||||
{
|
||||
$tableDef = parent::customizeTableDef($tableDef);
|
||||
|
||||
$tableDef['fields']['status']['fieldOptions'] = [
|
||||
2 => translate('handled', 'Reclamations'),
|
||||
1 => translate('accepted', 'Reclamations'),
|
||||
0 => translate('new', 'Reclamations'),
|
||||
];
|
||||
|
||||
return $tableDef;
|
||||
}
|
||||
|
||||
protected $orderParam = [
|
||||
'sort' => 'code',
|
||||
'direction' => 'DESC',
|
||||
];
|
||||
|
||||
/** @var ReclamationsUtil */
|
||||
protected $reclamations;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->reclamations = ServiceContainer::getService(ReclamationsUtil::class);
|
||||
}
|
||||
|
||||
public function getRowClass($values)
|
||||
{
|
||||
$class = '';
|
||||
if (in_array($values['status'], $this->reclamations->getHandleStatuses())) {
|
||||
$class = ' row-green';
|
||||
}
|
||||
|
||||
// upcoming
|
||||
if (in_array($values['status'], $this->reclamations->getAcceptedStatuses())) {
|
||||
$dateAccepted = \DateTime::createFromFormat('Y-m-d H:i:s', $values['date_accepted']);
|
||||
if ($dateAccepted) {
|
||||
$diff = $dateAccepted->diff(new \DateTime());
|
||||
if (abs($diff->days) > 15) {
|
||||
$class = ' row-orange';
|
||||
}
|
||||
if (abs($diff->days) > 30) {
|
||||
$class = ' row-red';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $class;
|
||||
}
|
||||
|
||||
public function renderCode($values)
|
||||
{
|
||||
return $values['code'];
|
||||
}
|
||||
|
||||
public function renderDeadline($values)
|
||||
{
|
||||
if (in_array($values['status'], $this->reclamations->getAcceptedStatuses())) {
|
||||
$dateAccepted = \DateTime::createFromFormat('Y-m-d H:i:s', $values['date_accepted']);
|
||||
if ($dateAccepted) {
|
||||
$diff = $dateAccepted->diff(new \DateTime());
|
||||
$text = 'za '.(30 - $diff->days).' dnů';
|
||||
$class = '';
|
||||
|
||||
if (abs($diff->days) > 15) {
|
||||
$class = 'badge-warning';
|
||||
}
|
||||
|
||||
if (abs($diff->days) > 30) {
|
||||
$class = 'badge-danger';
|
||||
$text = '-'.($diff->days - 30).' dnů';
|
||||
}
|
||||
|
||||
if (abs($diff->days) === 30) {
|
||||
$text = 'dnes';
|
||||
}
|
||||
|
||||
return HTML::create('span')
|
||||
->attr('class', 'badge '.$class)
|
||||
->text($text);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function renderOrderId($values)
|
||||
{
|
||||
return HTML::create('a')
|
||||
->attr('href', 'javascript:nw(\'orders\', '.$values['id_order'].')')
|
||||
->text($values['order_no']);
|
||||
}
|
||||
|
||||
public function renderCustomer($values, $column)
|
||||
{
|
||||
$userID = $values['id_user'];
|
||||
if (!$userID) {
|
||||
return $values['name'].' '.$values['surname'];
|
||||
}
|
||||
|
||||
return HTML::create('a')
|
||||
->attr('href', 'javascript:nw(\'users\', \''.$values['id_user'].'\')')
|
||||
->text($values['name'].' '.$values['surname']);
|
||||
}
|
||||
|
||||
public function renderProduct($values, $column)
|
||||
{
|
||||
$product = new \Product();
|
||||
$product->createFromDB($values['id_product']);
|
||||
|
||||
return HTML::create('a')
|
||||
->attr('href', 'javascript:nw(\'products\', \''.$values['id_product'].'\')')
|
||||
->text($product->title);
|
||||
}
|
||||
|
||||
public function renderStatus($values, $column)
|
||||
{
|
||||
return $this->reclamations->getStatuses()[$values['status']];
|
||||
}
|
||||
|
||||
public function getQuery()
|
||||
{
|
||||
$qb = sqlQueryBuilder()->select('r.*, oi.id_product, o.id_user, o.id as id_order, o.order_no as order_no')
|
||||
->from('reclamations', 'r')
|
||||
->leftJoin('r', 'order_items', 'oi', 'oi.id = r.id_item')
|
||||
->leftJoin('oi', 'orders', 'o', 'o.id = oi.id_order')
|
||||
->groupBy('r.id');
|
||||
|
||||
if (getVal('upcoming')) {
|
||||
$qb->andWhere('DATEDIFF(NOW(), r.date_accepted) > 15')
|
||||
->andWhere(Operator::inIntArray($this->reclamations->getAcceptedStatuses(), 'r.status'));
|
||||
}
|
||||
|
||||
if ($status = getVal('status')) {
|
||||
$qb->andWhere(
|
||||
Invert::checkInvert(Operator::inIntArray($status, 'r.status'), getVal('status_invert'))
|
||||
);
|
||||
}
|
||||
|
||||
if ($code = getVal('code')) {
|
||||
$qb->andWhere(
|
||||
Invert::checkInvert(
|
||||
Operator::orX(
|
||||
[
|
||||
Operator::equals(['r.id' => $code]),
|
||||
Operator::equals(['r.code' => $code]),
|
||||
]
|
||||
), getVal('code_invert')
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
if ($productId = getVal('id_product')) {
|
||||
$qb->andWhere('oi.id_product = :id_product')
|
||||
->setParameter('id_product', $productId);
|
||||
|
||||
if ($variationId = getVal('id_variation')) {
|
||||
if (intval($variationId) > 0) {
|
||||
$qb->andWhere('oi.id_variation = :id_variation')
|
||||
->setParameter('id_variation', $variationId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($handleType = getVal('handle_type')) {
|
||||
$qb->andWhere(Operator::inIntArray($handleType, 'r.handle_type'));
|
||||
}
|
||||
|
||||
if ($name = getVal('surname')) {
|
||||
$qb->andWhere(Invert::checkInvert(Operator::like(['r.surname' => "%{$name}%", 'r.name' => "%{$name}%"], 'OR'), getVal('surname_invert')));
|
||||
}
|
||||
|
||||
if ($id_order = getVal('id_order')) {
|
||||
$qb->andWhere(Invert::checkInvert(Operator::like(['o.order_no' => "%{$id_order}%"]), getVal('id_order_invert')));
|
||||
}
|
||||
|
||||
$dateRange = getVal('date_range');
|
||||
|
||||
if ($from = $dateRange['from'] ?? null) {
|
||||
$from = \DateTime::createFromFormat(\Settings::getDateFormat(), $from)->format('Y-m-d 00:00:00');
|
||||
}
|
||||
if ($to = $dateRange['to'] ?? null) {
|
||||
$to = \DateTime::createFromFormat(\Settings::getDateFormat(), $to)->format('Y-m-d 23:59:59');
|
||||
}
|
||||
if ($from || $to) {
|
||||
$qb->andWhere(Operator::between('r.date_created', new \Range($from, $to)));
|
||||
}
|
||||
|
||||
if ($accepted_from = $dateRange['accepted_from'] ?? null) {
|
||||
$accepted_from = \DateTime::createFromFormat(\Settings::getDateFormat(), $accepted_from)->format('Y-m-d 00:00:00');
|
||||
}
|
||||
if ($accepted_to = $dateRange['accepted_to'] ?? null) {
|
||||
$accepted_to = \DateTime::createFromFormat(\Settings::getDateFormat(), $accepted_to)->format('Y-m-d 23:59:59');
|
||||
}
|
||||
if ($accepted_from || $accepted_to) {
|
||||
$qb->andWhere(Operator::between('r.date_accepted', new \Range($accepted_from, $accepted_to)));
|
||||
}
|
||||
if ($handle_from = $dateRange['handle_from'] ?? null) {
|
||||
$handle_from = \DateTime::createFromFormat(\Settings::getDateFormat(), $handle_from)->format('Y-m-d 00:00:00');
|
||||
}
|
||||
if ($handle_to = $dateRange['handle_to'] ?? null) {
|
||||
$handle_to = \DateTime::createFromFormat(\Settings::getDateFormat(), $handle_to)->format('Y-m-d 23:59:59');
|
||||
}
|
||||
if ($handle_from || $handle_to) {
|
||||
$qb->andWhere(Operator::between('r.date_handle', new \Range($handle_from, $handle_to)));
|
||||
}
|
||||
|
||||
return $qb;
|
||||
}
|
||||
}
|
||||
|
||||
return ReclamationsList::class;
|
||||
@@ -0,0 +1,90 @@
|
||||
<?php
|
||||
|
||||
namespace KupShop\ReclamationsBundle\Admin\lists;
|
||||
|
||||
use Query\Operator;
|
||||
|
||||
class ReclamationsMassModificationList extends ReclamationsList
|
||||
{
|
||||
protected $template = 'list/ReclamationsMassModificationList.tpl';
|
||||
|
||||
public function customizeTableDef($tableDef)
|
||||
{
|
||||
$tableDef = parent::customizeTableDef($tableDef);
|
||||
|
||||
$tableDef['id'] = '';
|
||||
|
||||
$field = [
|
||||
'Vybrat' => [
|
||||
'field' => 'r.code',
|
||||
'size' => '55px',
|
||||
'render' => 'renderCheckbox',
|
||||
'label' => 'check',
|
||||
'type' => '',
|
||||
'class' => 'hiddenTooltip overflow-visible hidden-label',
|
||||
],
|
||||
'Číslo' => [
|
||||
'field' => 'r.code',
|
||||
'type_id' => 'r.id',
|
||||
'type' => 'Reclamations',
|
||||
],
|
||||
];
|
||||
|
||||
$tableDef['fields'] = $field + $tableDef['fields'];
|
||||
|
||||
return $tableDef;
|
||||
}
|
||||
|
||||
public function renderCheckbox($values)
|
||||
{
|
||||
return $this->getCheckbox('reclamation_ids', $values['id']);
|
||||
}
|
||||
|
||||
public function handleBankCommand()
|
||||
{
|
||||
$dbcfg = \Settings::getDefault();
|
||||
$reclamationIds = getVal('reclamation_ids', getVal('data'), []);
|
||||
|
||||
$abo = new \snoblucha\Abo\Abo();
|
||||
$abo->setComittentNumer(0);
|
||||
$abo->setOrganization($dbcfg->shop_firm_name);
|
||||
$abo->setDate();
|
||||
|
||||
$account = $abo->addAccountFile(\snoblucha\Abo\Account\File::UHRADA);
|
||||
// $account->setBank('2010'); // banka prikazce
|
||||
$account->setBankDepartment(0);
|
||||
$group = $account->addGroup();
|
||||
|
||||
// $group->setAccount(2900217845); // cislo uctu prikazce
|
||||
$group->setDate();
|
||||
|
||||
foreach ($reclamationIds as $reclamationId) {
|
||||
$reclamation = $this->reclamations->getReclamation($reclamationId);
|
||||
|
||||
if ($orderId = $reclamation->getIdOrder()) {
|
||||
$orderObj = new \Order();
|
||||
$orderObj->createFromDB($orderId);
|
||||
|
||||
$price = toDecimal($reclamation->getItem()['total_price'])->addVat($reclamation->getItem()['tax']);
|
||||
$accountNo = $reclamation->getBankAccount();
|
||||
if (!empty($accountNo)) {
|
||||
$group->addItem($accountNo, $price->abs()->asFloat(), $orderObj->order_no);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
header('Content-type: application/txt');
|
||||
header('Content-Disposition: attachment; filename="ABO-'.date('Y-m-d_H-i').'_'.time().'.txt"');
|
||||
echo $abo->generate();
|
||||
exit;
|
||||
}
|
||||
|
||||
public function getQuery()
|
||||
{
|
||||
$qb = parent::getQuery();
|
||||
|
||||
$qb->andWhere(Operator::not(Operator::inIntArray($this->reclamations->getHandleStatuses(), 'r.status')));
|
||||
|
||||
return $qb;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
<?php
|
||||
|
||||
include_once __DIR__.'/ReclamationsMenu.php';
|
||||
|
||||
class ReclamationsMassModificationMenu extends \ReclamationsMenu
|
||||
{
|
||||
public function getTemplate()
|
||||
{
|
||||
return './menu/Reclamations.tpl';
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
<?php
|
||||
|
||||
use KupShop\KupShopBundle\Util\Compat\ServiceContainer;
|
||||
use KupShop\ReclamationsBundle\Util\ReclamationsUtil;
|
||||
|
||||
class ReclamationsMenu extends Menu
|
||||
{
|
||||
public function get_vars()
|
||||
{
|
||||
$vars = parent::get_vars();
|
||||
|
||||
/** @var ReclamationsUtil $reclamations */
|
||||
$reclamations = ServiceContainer::getService(ReclamationsUtil::class);
|
||||
|
||||
$vars['statuses'] = $reclamations->getStatuses();
|
||||
$vars['handle_types'] = $reclamations->getHandleTypes();
|
||||
|
||||
return $vars;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
<p class="text-center m-b-3"><strong>{'commentConfirm'|translate nofilter}</strong></p>
|
||||
@@ -0,0 +1,2 @@
|
||||
<p>{t}dnes k nám v pořádku dorazil balíček se zbožím k reklamaci. Vše prověříme, zjistíme, co stalo, a nejdéle do 30 dnů Vás budeme informovat o výsledku reklamace.{/t}</p>
|
||||
<p>{t}Děkujeme za Vaši trpělivost a pevně věříme, že vše vyřešíme k Vaší spokojenosti.{/t}</p>
|
||||
@@ -0,0 +1,6 @@
|
||||
<p>{t escape=false}právě jsme obdrželi Vaši žádost o reklamaci, které jsme přidělili číslo <strong>{KOD_REKLAMACE}</strong>. Zboží nám pošlete zdarma přes Zásilkovnu nebo na vlastní náklady jinou přepravní společností.{/t}</p>
|
||||
|
||||
<p>{ldelim}REKLAMACE_INSTRUKCE{rdelim}</p>
|
||||
|
||||
<p>{t escape=false}Stav reklamace můžete sledovat <a href="{ODKAZ_REKLAMACE}">zde</a>.{/t}</p>
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
<div>
|
||||
{ldelim}REKAPITULACE_OBCHODNIKOVI{rdelim}
|
||||
</div>
|
||||
@@ -0,0 +1,4 @@
|
||||
<p>{t escape=false}máme pro Vás špatnou zprávu. Reklamaci nemůžeme uznat, protože závada byla způsobena nevhodným užíváním. Zboží Vám v následujících dnech doveze kurýr na adresu uvedenou v reklamačním formuláři.{/t}</p>
|
||||
<p>{t}Číslo balíku: {BALIK_ID}{/t}</p>
|
||||
<p>{t}Posudek: {POSUDEK}{/t}</p>
|
||||
<p>{t}Děkujeme za Vaši přízeň a doufám, že u nás zase nakoupíte.{/t}</p>
|
||||
@@ -0,0 +1,2 @@
|
||||
<p>{t escape=false}vyhodnotili jsme, že se jedná o vrácení zboží, proto případ reklamace nyní uzavřeme a budeme ji dále vyřizovat jako vratku.{/t}</p>
|
||||
<p>{t}Děkujeme za Vaši přízeň a doufám, že u nás zase nakoupíte.{/t}</p>
|
||||
@@ -0,0 +1,2 @@
|
||||
<p>{t escape=false}Reklamace číslo <strong>{KOD_REKLAMACE}</strong> bude vyřízena vratkou č. <a href="{ODKAZ_VRATKA}">{KOD_VRATKY}</a>{/t}</p>
|
||||
<p>{t}Zboží bude vyměněno.{/t}</p>
|
||||
@@ -0,0 +1,4 @@
|
||||
<p>{t escape=false}reklamované zboží jsme opravili. V následujících dnech Vám opravené zboží doveze kurýr na adresu uvedenou v reklamačním formuláři.{/t}</p>
|
||||
<p>{t}Číslo balíku: {BALIK_ID}{/t}</p>
|
||||
<p>{t}Posudek: {POSUDEK}{/t}</p>
|
||||
<p>{t}Děkujeme za Vaši přízeň a doufám, že u nás zase nakoupíte.{/t}</p>
|
||||
@@ -0,0 +1,5 @@
|
||||
<p>{t escape=false}Vaši reklamaci jsme uznali jako oprávněnou. Peníze Vám vrátíme do 14 dnů na bankovní účet uvedený v reklamačním formuláři.{/t}</p>
|
||||
<p>{t}Číslo balíku: {BALIK_ID}{/t}</p>
|
||||
<p>{t}Posudek: {POSUDEK}{/t}</p>
|
||||
<p>{t}Vrácená částka: {CASTKA} Kč{/t}</p>
|
||||
<p>{t}Děkujeme za Vaši přízeň a těšíme se na Váš další nákup.{/t}</p>
|
||||
@@ -0,0 +1,105 @@
|
||||
<style type="text/css" media="all">
|
||||
{block "style"}
|
||||
hr {
|
||||
margin: 3px 0;
|
||||
border: 0;
|
||||
border-top: 1px solid #ccc;
|
||||
}
|
||||
|
||||
* {
|
||||
-webkit-box-sizing: border-box;
|
||||
-moz-box-sizing: border-box;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.print-footer {
|
||||
text-align: center;
|
||||
color: grey;
|
||||
margin: auto;
|
||||
padding-top: 5px;
|
||||
font-size: 11px;
|
||||
clear: both;
|
||||
}
|
||||
|
||||
.print {
|
||||
width: 675px;
|
||||
font-size: 12px;
|
||||
color: #000000;
|
||||
font-family: Arial, Helvetica, sans-serif;
|
||||
}
|
||||
|
||||
h1 {
|
||||
margin: 0 0 10px;
|
||||
font-size: 18px;
|
||||
font-weight: normal;
|
||||
padding: 3px 0;
|
||||
}
|
||||
|
||||
h2 {
|
||||
margin: 0;
|
||||
font-size: 13px;
|
||||
font-weight: bold;
|
||||
padding: 3px 0 0;
|
||||
clear: both;
|
||||
}
|
||||
|
||||
h3 {
|
||||
margin: 0;
|
||||
font-size: 12px;
|
||||
font-weight: bold;
|
||||
padding: 3px 3px 3px 0;
|
||||
clear: both;
|
||||
}
|
||||
|
||||
.print-main-content .print-main-content-center {
|
||||
width: 100%;
|
||||
float: left;
|
||||
}
|
||||
|
||||
.print-main-content-notes {
|
||||
width: 100%;
|
||||
clear: both;
|
||||
}
|
||||
|
||||
.print-main-content td {
|
||||
font-size: 12px;
|
||||
border-bottom: 1px solid #ccc;
|
||||
}
|
||||
|
||||
.print-main-content th {
|
||||
font-size: 12px;
|
||||
font-weight: bold;
|
||||
color: #000000;
|
||||
background-color: #CCCCCC;
|
||||
padding: 2px;
|
||||
border: 1px solid #999999;
|
||||
}
|
||||
|
||||
{/block}
|
||||
</style>
|
||||
|
||||
<div class="print">
|
||||
<h1>Byla přijata reklamace <a href="{path('kupshop_reclamations_reclamations_reclamation', ['id' => $reclamation.id])}">{$reclamation.code}</a></h1>
|
||||
|
||||
<div class="print-main-content">
|
||||
{block "reclamation-info"}
|
||||
<div class="print-main-content-center">
|
||||
<h2>Reklamace z objednávky:</h2>
|
||||
<hr/>
|
||||
<p><a href="{url s=orderView IDo=$order.id cf=$order->getSecurityCode()}">{$order.order_no}</a> ({$order.date_created|format_date})</p>
|
||||
<br/>
|
||||
</div>
|
||||
<div class="print-main-content-notes">
|
||||
<h2>Text reklamace:</h2>
|
||||
<hr/>
|
||||
<p>{$reclamation.user_note}</p>
|
||||
</div>
|
||||
{/block}
|
||||
</div>
|
||||
|
||||
<div class="print-footer">
|
||||
{block "footer"}
|
||||
<p>Váš wpjshop.cz</p>
|
||||
{/block}
|
||||
</div>
|
||||
</div>
|
||||
@@ -0,0 +1,20 @@
|
||||
{extends file="[shared]/list.tpl"}
|
||||
|
||||
{block content}
|
||||
<form method="post" id="reclamations-form">
|
||||
{$smarty.block.parent}
|
||||
</form>
|
||||
{/block}
|
||||
|
||||
{block buttons prepend}
|
||||
<script>
|
||||
var $form = $('#reclamations');
|
||||
</script>
|
||||
<button type="submit" class="btn btn-block" name="acn"
|
||||
value="bankCommand"
|
||||
onclick='$.redirectPost({ url:"launch.php?s=list.php&type=ReclamationsMassModification&acn=bankCommand", data:$form.serializeArray() })'>
|
||||
Příkaz bance
|
||||
</button>
|
||||
{/block}
|
||||
|
||||
{block "list-filter-mass-edit"}{/block}
|
||||
@@ -0,0 +1,163 @@
|
||||
{extends file="menu.tpl"}
|
||||
|
||||
{block name="menu-items"}
|
||||
<li class="nav-header"><i class="glyphicon glyphicon-tags"></i><span>{translate_type type=$type}</span></li>
|
||||
<li><a href="javascript:nf('launch.php?s=menu.php&type=Reclamations', 'launch.php?s=list.php&type=Reclamations');"><i class="glyphicon glyphicon-list"></i> <span>{'toolbar_list'|translate:'Reclamations'}</span></a></li>
|
||||
<!-- <li><a href="javascript:nf('launch.php?s=menu.php&type=ReclamationsMassModification', 'launch.php?s=list.php&type=ReclamationsMassModification');"><i class="glyphicon glyphicon-list"></i> <span>{'toolbar_massmodif'|translate:'Reclamations'}</span></a></li>-->
|
||||
<li><a href="javascript:nw('{$type}');"><i class="glyphicon glyphicon-plus"></i> <span>{'toolbar_add'|translate:'Reclamations'}</span></a></li>
|
||||
|
||||
<li class="nav-header smaller"><i class="glyphicon glyphicon-search"></i><span>{'search'|translate:'Reclamations'}</span></li>
|
||||
<li class="with_caret "><a href="#" class="opener"><span>{'filterTerm'|translate:'Reclamations'}</span></a></li>
|
||||
<li class="pill-content">
|
||||
<ul class="nav-sub nav-pills">
|
||||
<a href="launch.php?s=list.php&type={$type}&upcoming=1" target="mainFrame">{'upcoming'|translate:'Reclamations'}</a>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="with_caret "><a href="#" class="opener"><span>{'filterBasic'|translate:'Reclamations'}</span></a></li>
|
||||
<li class="pill-content">
|
||||
<ul class="nav-sub nav-pills">
|
||||
<form id='search' target="mainFrame" method="get" action="launch.php" class="form-inline">
|
||||
<input type="hidden" name="type" value="{$type}" /><input type="hidden" name="s" value="list.php">
|
||||
|
||||
<div class="form-group">
|
||||
<div class="input-group invert">
|
||||
<input type="text" name="code" class="form-control input-sm" placeholder="{'searchCode'|translate:'Reclamations'}">
|
||||
{inversion field="code"}
|
||||
</div
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<div class="input-group invert">
|
||||
<select name="status[]" multiple="multiple" class="selecter" data-placeholder="{'selectStatus'|translate:'Reclamations'}">
|
||||
{foreach $statuses as $key => $value}
|
||||
<option value="{$key}">{$value}</option>
|
||||
{/foreach}
|
||||
</select>
|
||||
{inversion field="status"}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<div class="input-group invert">
|
||||
<select name="handle_type[]" multiple="multiple" class="selecter" data-placeholder="{'handleType'|translate:'Reclamations'}">
|
||||
{foreach $handle_types as $key => $value}
|
||||
<option value="{$key}">{$value}</option>
|
||||
{/foreach}
|
||||
</select>
|
||||
{inversion field="handle_type"}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<div class="input-group invert">
|
||||
<input type="text" name="surname" class="form-control input-sm" placeholder="{'customer'|translate:'Reclamations'}">
|
||||
{inversion field="surname"}
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="input-group invert">
|
||||
<input type="text" name="id_order" class="form-control input-sm" placeholder="{'id_order'|translate:'Reclamations'}">
|
||||
{inversion field="id_order"}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<div class="input-group">
|
||||
<input id="createdFrom" data-filter-type="input" type="text" class="form-control"
|
||||
name="date_range[from]" value="{$filter.date_added_range.from}" placeholder="{'createdFrom'|translate:'Returns'}" autocomplete="off"/>
|
||||
{insert_calendar selector="#createdFrom" format='date'}
|
||||
<label for="createdFrom" class="input-group-addon">
|
||||
<span class="bi bi-calendar-week"></span>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="wpj-form-group">
|
||||
<div class="input-group">
|
||||
<input id="createdTo" data-filter-type="input" type="text" class="form-control"
|
||||
name="date_range[to]" value="{$filter.date_added_range.from}" placeholder="{'createdTo'|translate:'Returns'}" autocomplete="off"/>
|
||||
{insert_calendar selector="#createdTo" format='date'}
|
||||
<label for="createdTo" class="input-group-addon">
|
||||
<span class="bi bi-calendar-week"></span>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<div class="input-group">
|
||||
<input id="acceptedFrom" data-filter-type="input" type="text" class="form-control"
|
||||
name="date_range[accepted_from]" value="{$filter.date_added_range.accepted_from}" placeholder="{'acceptedFrom'|translate:'Returns'}" autocomplete="off"/>
|
||||
{insert_calendar selector="#acceptedFrom" format='date'}
|
||||
<label for="acceptedFrom" class="input-group-addon">
|
||||
<span class="bi bi-calendar-week"></span>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="wpj-form-group">
|
||||
<div class="input-group">
|
||||
<input id="acceptedTo" data-filter-type="input" type="text" class="form-control"
|
||||
name="date_range[accepted_to]" value="{$filter.date_added_range.accepted_from}" placeholder="{'acceptedTo'|translate:'Returns'}" autocomplete="off"/>
|
||||
{insert_calendar selector="#acceptedTo" format='date'}
|
||||
<label for="acceptedTo" class="input-group-addon">
|
||||
<span class="bi bi-calendar-week"></span>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="wpj-form-group">
|
||||
<div class="input-group">
|
||||
<input id="handleFrom" data-filter-type="input" type="text" class="form-control"
|
||||
name="date_range[handle_from]" value="{$filter.date_added_range.handle_from}" placeholder="{'date_handle_from'|translate:'Reclamations'}" autocomplete="off"/>
|
||||
{insert_calendar selector="#handleFrom" format='date'}
|
||||
<label for="handleFrom" class="input-group-addon">
|
||||
<span class="bi bi-calendar-week"></span>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="wpj-form-group">
|
||||
<div class="input-group">
|
||||
<input id="handleTo" data-filter-type="input" type="text" class="form-control"
|
||||
name="date_range[handle_to]" value="{$filter.date_added_range.handle_from}" placeholder="{'date_handle_to'|translate:'Reclamations'}" autocomplete="off"/>
|
||||
{insert_calendar selector="#handleTo" format='date'}
|
||||
<label for="handleTo" class="input-group-addon">
|
||||
<span class="bi bi-calendar-week"></span>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<input type="reset" id="resetBtn" value="{'delete'|translate:'Reclamations'}" class="btn btn-danger btn-sm"/>
|
||||
<input type="submit" value="{'searchBtn'|translate:'Reclamations'}" class="btn btn-primary btn-sm"/>
|
||||
</div>
|
||||
|
||||
</form>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="with_caret "><a href="#" class="opener"><span>{'filterByProduct'|translate:'Reclamations'}</span></a></li>
|
||||
<li class="pill-content">
|
||||
<ul class="nav-sub nav-pills">
|
||||
<form id='search' target="mainFrame" method="get" action="launch.php" class="form-inline">
|
||||
<input type="hidden" name="type" value="{$type}" /><input type="hidden" name="s" value="list.php">
|
||||
|
||||
<div class="form-group">
|
||||
<input type="text" class="form-control input-sm" name="id_product" maxlength="100" value="" onKeyPress="checkInputData('int')" placeholder="{'searchNameCode'|translate:'orders'}"/>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<select name="id_variation" class="input-sm form-control"></select>
|
||||
<script type="text/javascript">
|
||||
$(function(){
|
||||
initAutocompleteVariation('[name=id_product]', '[name=id_variation]');
|
||||
});
|
||||
</script>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<input type="reset" id="resetBtn" value="{'delete'|translate:'Reclamations'}" class="btn btn-danger btn-sm"/>
|
||||
<input type="submit" value="{'searchBtn'|translate:'Reclamations'}" class="btn btn-primary btn-sm"/>
|
||||
</div>
|
||||
|
||||
</form>
|
||||
</ul>
|
||||
</li>
|
||||
{/block}
|
||||
@@ -0,0 +1,156 @@
|
||||
<style type="text/css" media="all">
|
||||
@media print {
|
||||
@page {
|
||||
margin: 0 !important;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.stitek {
|
||||
float: none !important;
|
||||
border: none !important;
|
||||
}
|
||||
}
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
color: black;
|
||||
}
|
||||
|
||||
.stitek {
|
||||
width: 45mm;
|
||||
height: 45mm;
|
||||
box-sizing: border-box;
|
||||
page-break-after: always;
|
||||
border: dimgrey dashed 1px;
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
background-color: white;
|
||||
}
|
||||
|
||||
.title {
|
||||
padding: 2px 2px 2px 4px;
|
||||
font-weight: bold;
|
||||
}
|
||||
.variation_title {
|
||||
padding: 2px 2px 2px 4px;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.price {
|
||||
position: absolute;
|
||||
right: 2mm;
|
||||
bottom: 2mm;
|
||||
}
|
||||
.price td {
|
||||
padding: 0px 3px;
|
||||
vertical-align: baseline;
|
||||
}
|
||||
.price td:first-child {
|
||||
text-align: right;
|
||||
font-weight: bold;
|
||||
}
|
||||
.price td.price_sDPH {
|
||||
font-size: 24px;
|
||||
}
|
||||
.price td.price_bezDPH {
|
||||
font-size: 18px;
|
||||
}
|
||||
|
||||
.barcode {
|
||||
width: 100%;
|
||||
height: 17mm;
|
||||
overflow: hidden;
|
||||
font-size: 13px;
|
||||
line-height: 12px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.barcode > svg {
|
||||
max-width: 85%;
|
||||
}
|
||||
|
||||
.barcode-large {
|
||||
font-size: 140%;
|
||||
}
|
||||
|
||||
</style>
|
||||
|
||||
<div class="print-hidden" style="margin: 15px">
|
||||
<div class="row">
|
||||
<div class="col-md-3">
|
||||
<select data-supplier class="selecter">
|
||||
<option value="0">-- Vybrat konkrétního dodavatele --</option>
|
||||
{foreach $suppliers_codes as $id => $row}
|
||||
<option value="{$id}"
|
||||
{if ($smarty.get.id_supplier && $smarty.get.id_supplier == $id)} selected{/if}>{$row.name} - {$row.code}</option>
|
||||
{/foreach}
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-md-1">
|
||||
<button data-select class="btn btn-sm btn-primary">Vybrat</button>
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
function updateQueryStringParameter(uri, key, value) {
|
||||
var re = new RegExp("([?&])" + key + "=.*?(&|$)", "i");
|
||||
var separator = uri.indexOf('?') !== -1 ? "&" : "?";
|
||||
if (uri.match(re)) {
|
||||
return uri.replace(re, '$1' + key + "=" + value + '$2');
|
||||
}
|
||||
else {
|
||||
return uri + separator + key + "=" + value;
|
||||
}
|
||||
}
|
||||
|
||||
$('[data-select]').on('click', function () {
|
||||
var value =$('[data-supplier]').val();
|
||||
window.location.href = updateQueryStringParameter(window.location.href, 'id_supplier', value);
|
||||
});
|
||||
</script>
|
||||
</div>
|
||||
|
||||
<div class="stitek">
|
||||
<div class="title">
|
||||
{$reclamation.code} <small>(Objednávka: {$reclamation.id_order})</small>
|
||||
</div>
|
||||
<div class="variation_title">
|
||||
{$reclamation.address.name} {$reclamation.address.surname}
|
||||
</div>
|
||||
<div class="variation_title">
|
||||
{$reclamation.item.descr}
|
||||
</div>
|
||||
{if !empty($product_barcode_chars)}
|
||||
<div class="barcode">
|
||||
{insert_barcode type="EAN13" code=$product_barcode_chars height=45 width=2}
|
||||
<br>
|
||||
{$product_barcode_chars|substr:'0':'-3'}
|
||||
<span class="barcode-large">{$product_barcode_chars|substr:'-3'}</span>
|
||||
</div>
|
||||
{/if}
|
||||
{ifmodule PRODUCTS_SERIAL_NUMBERS}
|
||||
{if $serial_number}
|
||||
<div class="serial-number">
|
||||
{$serial_number}
|
||||
</div>
|
||||
{/if}
|
||||
{/ifmodule}
|
||||
<div class="variation_title">
|
||||
{$boughtDate|format_date:'j.n.Y'} / {$reclamation.date_accepted|format_date:'j.n.Y'}
|
||||
</div>
|
||||
<div class="price">
|
||||
{if !empty($suppliers_codes)}
|
||||
{foreach $suppliers_codes as $id => $row}
|
||||
{if ($smarty.get.id_supplier && $smarty.get.id_supplier == $id) || !$smarty.get.id_supplier}
|
||||
<div class="variation_title">
|
||||
{$row.name} - {$row.code}
|
||||
</div>
|
||||
{/if}
|
||||
{/foreach}
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
//window.print();
|
||||
</script>
|
||||
@@ -0,0 +1,85 @@
|
||||
<div id="flapReclamationsLanguageSettings" class="tab-pane boxStatic box">
|
||||
<div class="row bottom-space">
|
||||
<div class="col-md-12">
|
||||
<h1 class="h4 main-panel-title">{'flapReclamationsSettings'|translate:'reclamationsWindowTab'}</h1>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<div class="col-md-2 control-label">
|
||||
<label>
|
||||
{'reclamation_days'|translate:'reclamationsWindowTab'}
|
||||
<a class="help-tip" data-toggle="tooltip" title="" data-original-title="{'reclamation_days_tooltip'|translate:'reclamationsWindowTab'}"><i class="bi bi-question-circle"></i></a>
|
||||
</label>
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<input type="text" class="form-control input-sm" name="data[reclamations][days]" size="30" placeholder="{$dbcfg.reclamations.days}" value="{$body.data.reclamations.days}">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<div class="col-md-2 control-label">
|
||||
<label>
|
||||
{'delivery'|translate:'reclamationsWindowTab'}
|
||||
<a class="help-tip" data-toggle="tooltip" title="" data-original-title="{'reclamationsDelivery'|translate:'reclamationsWindowTab'}">
|
||||
<i class="bi bi-question-circle"></i>
|
||||
</a>
|
||||
</label>
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<select class="selecter" name="data[reclamations][delivery]">
|
||||
<option value="0">-- nevybráno --</option>
|
||||
{foreach $tab.data.deliveries as $delivery}
|
||||
<option value="{$delivery.id}" {if $body.data.reclamations.delivery == $delivery.id}selected{/if}>{$delivery.name_admin|default:$delivery.name}</option>
|
||||
{/foreach}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="row bottom-space">
|
||||
<div class="col-md-12">
|
||||
<h1 class="h4 main-panel-title">{'flapReclamationsInstructions'|translate:'reclamationsWindowTab'}</h1>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="panel panel-default" id="#reclamations_symbols">
|
||||
<div class="panel-heading" data-toggle="collapse" data-target="#reclamations-symbol-collapse">
|
||||
Zástupné symboly
|
||||
<i class="glyphicon glyphicon-minus-sign"></i>
|
||||
</div>
|
||||
|
||||
<div class="panel-collapse collapse symbol-collapse" id="reclamations-symbol-collapse">
|
||||
{$placeholders = $tab.data.tabView->getPlaceholders()}
|
||||
{$half = (($placeholders|count)/ 2)|round}
|
||||
{foreach $placeholders as $key => $placeholder}
|
||||
{if $placeholder@first}
|
||||
<div>
|
||||
<table class="table table-striped">
|
||||
{/if}
|
||||
{if $placeholder@index == $half}
|
||||
</table>
|
||||
</div>
|
||||
<div>
|
||||
<table class="table table-striped">
|
||||
{/if}
|
||||
<tr>
|
||||
<td><strong>{literal}{{/literal}{$key}{literal}}{/literal}</strong></td>
|
||||
<td>{$placeholder.text nofilter}</td>
|
||||
</tr>
|
||||
{if $placeholder@last}
|
||||
</table>
|
||||
</div>
|
||||
{/if}
|
||||
{/foreach}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<div class="col-md-3 control-label"><label>{'returnDescr'|translate:'reclamationsWindowTab'}</label></div>
|
||||
<div class="col-md-8">
|
||||
<textarea name="data[reclamations][descr]" rows="14" cols="30" placeholder="{$dbcfg.reclamations.descr}">{$body.data.reclamations.descr}</textarea>
|
||||
{insert_wysiwyg target="data[reclamations][descr]"}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -0,0 +1,798 @@
|
||||
{extends file="[shared]/window.tpl"}
|
||||
|
||||
{block size}
|
||||
width = 1220;
|
||||
height = 900;
|
||||
{/block}
|
||||
|
||||
{block tabs}
|
||||
{windowTab id='flapReclamation' label=translate('reclamations')|cat:' '|cat:$body.data.code}
|
||||
{windowTab id='flapUser' label=translate('user')}
|
||||
{/block}
|
||||
|
||||
{block tabsContent}
|
||||
<div id="flapReclamation" class="tab-pane fade active in boxStatic box">
|
||||
{if $body.acn == 'edit'}
|
||||
{if $body.data->isClosed()}
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<div class="alert alert-danger">
|
||||
Reklamace je uzavřena.
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
<div class="row bottom-space">
|
||||
<div class="col-md-6">
|
||||
<div class="form-group form-group-flex">
|
||||
<div class="col-md-4 control-label"><label>{'order'|translate}</label></div>
|
||||
<div class="col-md-8">
|
||||
<a href="javascript:nw('orders', {$body.order->id})">{$body.order->order_no}</a> <span class="copy-to-clipboard" data-copy-clipboard="{$body.order->order_no}" data-toggle="tooltip" title="{'clipboard-copy'|translate:'button'}"></span>
|
||||
<span style="margin-left: 5px">před {$body.order_date_diff} dny {$body.order->date_handle|format_date:'d.m.Y'}</span>
|
||||
<a href="{if $body.order->id}{path('kupshop_admin_emailattachment_adminattachment', ['id_order' => $body.order->id, 'type' => 'order_invoice'])}{/if}"
|
||||
target="printCenter">
|
||||
- Tisk faktury
|
||||
</a>
|
||||
<br>
|
||||
{get_order_source_info id=$body.order.id assign='sourceInfo'}
|
||||
<small>
|
||||
Zdroj: {$sourceInfo.source}
|
||||
{ifmodule DROPSHIP}
|
||||
{if $sourceInfo.dropshipment}
|
||||
-
|
||||
<a href="javascript:nw('Dropshipment', {$sourceInfo.dropshipment.dropshipment.id})">{$sourceInfo.dropshipment.dropshipment.name}</a>
|
||||
{/if}
|
||||
{/ifmodule}
|
||||
</small>
|
||||
</div>
|
||||
</div>
|
||||
{block products}
|
||||
<div class="form-group form-group-flex">
|
||||
<div class="col-md-4 control-label"><label>{'product'|translate}</label></div>
|
||||
<div class="col-md-8">
|
||||
<a href="javascript:nw('products', {$body.data.item.id_product})">
|
||||
{$body.data.item.descr}
|
||||
</a><br>
|
||||
<small>Kód: {$body.data.item.code}{if $body.data.item.ean}, EAN: {$body.data.item.ean}{/if}</small>
|
||||
</div>
|
||||
</div>
|
||||
{/block}
|
||||
{block pieces}
|
||||
{if $body.data.pieces > 1}
|
||||
<div class="form-group form-group-flex">
|
||||
<div class="col-md-4 control-label"><label>Kusů</label></div>
|
||||
<div class="col-md-8">
|
||||
{$body.data.pieces}
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
{/block}
|
||||
<div class="form-group form-group-flex">
|
||||
<div class="col-md-4 control-label"><label>{'status'|translate}</label></div>
|
||||
<div class="col-md-8">
|
||||
{$body.data.status_name}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-md-6">
|
||||
{if findModule('products_suppliers') && $body.acn == 'edit'}
|
||||
<div class="col-md-12">
|
||||
<div class="panel panel-default panel-sm">
|
||||
<div class="panel-heading">
|
||||
<h3 class="panel-title">
|
||||
{'suppliers_codes'|translate}
|
||||
<a href="javascript:nw('productStockIn', {$body.data.item.id_product}{if !empty($body.data.item.id_variation)}, {$body.data.item.id_variation}{/if})">
|
||||
<span class="badge badge-default pull-right" title="Naskladňující faktury produktu">
|
||||
<i class="glyphicon glyphicon-list-alt"></i>
|
||||
</span>
|
||||
</a>
|
||||
</h3>
|
||||
</div>
|
||||
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>{'supplier'|translate}</th>
|
||||
<th>{'supplier_code'|translate}</th>
|
||||
<th>{'supplier_reclamation'|translate}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{foreach $body.suppliers_codes as $key => $row}
|
||||
<tr style="border-bottom: thin; {if $row.notified == 3}background-color: #bfec55;{/if}">
|
||||
<td><a href="javascript:nw('suppliers', {$row.id})">{$row.name}</a></td>
|
||||
<td>{$row.code}</td>
|
||||
<td>
|
||||
{if $body.supplierReclamation and $body.supplierReclamation.id_supplier == $row.id }
|
||||
<a href="javascript:nw('ReclamationsSuppliers',{$body.supplierReclamation.id})">{$body.supplierReclamation.code}</a>
|
||||
{elseif !$body.supplierReclamation.id_supplier}
|
||||
{if in_array($row.id, $body.serialNumberSuppliers)}
|
||||
<i class="glyphicon glyphicon-arrow-right" style="color: #AAB2BD;"
|
||||
title="{'serial_number_from_supplier'|translate}"></i>
|
||||
{/if}
|
||||
<a href="launch.php?s=Reclamations.php&acn=supplierReclamation&supplierId={$row.id}&ID={$body.data.id}">{'supplier_reclamation_action'|translate}</a>
|
||||
{/if}
|
||||
</td>
|
||||
</tr>
|
||||
{/foreach}
|
||||
|
||||
</tbody>
|
||||
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
{else}
|
||||
<div class="form-group form-group-flex">
|
||||
<div class="col-md-4 control-label"><label>{'date_created'|translate}</label></div>
|
||||
<div class="col-md-8">
|
||||
<input id="date_created" class="form-control input-sm" type="text" name="data[date_created]" value="{$body.data.date_created|format_datetime}" autocomplete="off">
|
||||
{insert_calendar selector='#date_created' format='datetime'}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group form-group-flex">
|
||||
<div class="col-md-4 control-label"><label>{'date_accepted'|translate}</label></div>
|
||||
<div class="col-md-8">
|
||||
<input id="date_accepted" class="form-control input-sm" type="text" name="data[date_accepted]" value="{$body.data.date_accepted|format_datetime}" autocomplete="off">
|
||||
{insert_calendar selector='#date_accepted' format='datetime'}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group form-group-flex">
|
||||
<div class="col-md-4 control-label"><label>{'date_handle'|translate}</label></div>
|
||||
<div class="col-md-8">
|
||||
<input id="date_handle" class="form-control input-sm" type="text" name="data[date_handle]" value="{$body.data.date_handle|format_datetime}" autocomplete="off">
|
||||
{insert_calendar selector='#date_handle' format='datetime'}
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
{else}
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<div class="form-group form-group-flex">
|
||||
<div class="col-md-2 control-label"><label>{'selectOrder'|translate}</label></div>
|
||||
<div class="col-md-6">
|
||||
<input data-autocomplete-search="orders" class="form-control input-sm" type="text" name="order" value="{$body.data.id_order}" placeholder="{'searchOrder'|translate}" autocomplete="off">
|
||||
<input type="hidden" data-id-order name="id_order" value="{$body.data.id_order}">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row" id="item_selecter" style="display: none">
|
||||
<div class="col-md-12">
|
||||
<div class="form-group form-group-flex">
|
||||
<div class="col-md-2 control-label"><label>{'selectItem'|translate}</label></div>
|
||||
<div class="col-md-6">
|
||||
<input data-autocomplete-search="order_item" class="form-control input-sm" type="text" name="data[id_item]" value="" placeholder="{'searchItem'|translate}" autocomplete="off">
|
||||
<input type="hidden" data-id-item name="data[id_item]" value="{$body.data.id_item}">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
{if findModule('products_suppliers') && $body.acn == 'edit'}
|
||||
<div class="row">
|
||||
<div class="col-md-2 control-label">
|
||||
<label>{'date_created'|translate}</label>
|
||||
</div>
|
||||
<div class="col-md-2">
|
||||
<input id="date_created" class="form-control input-sm" type="text" name="data[date_created]" value="{$body.data.date_created|format_datetime}" autocomplete="off">
|
||||
{insert_calendar selector='#date_created' format='datetime'}
|
||||
</div>
|
||||
|
||||
<div class="col-md-2 control-label">
|
||||
<label>{'date_accepted'|translate}</label>
|
||||
</div>
|
||||
<div class="col-md-2">
|
||||
<input id="date_accepted" class="form-control input-sm" type="text" name="data[date_accepted]" value="{$body.data.date_accepted|format_datetime}" autocomplete="off">
|
||||
{insert_calendar selector='#date_accepted' format='datetime'}
|
||||
</div>
|
||||
|
||||
<div class="col-md-2 control-label">
|
||||
<label>{'date_handle'|translate}</label>
|
||||
</div>
|
||||
<div class="col-md-2">
|
||||
<input id="date_handle" class="form-control input-sm" type="text" name="data[date_handle]" value="{$body.data.date_handle|format_datetime}" autocomplete="off">
|
||||
{insert_calendar selector='#date_handle' format='datetime'}
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
{if $body.acn == 'edit'}
|
||||
{$custom_data = $body.data.data}
|
||||
<h1 class="h4 main-panel-title">{'delivery'|translate}</h1>
|
||||
{ifmodule RETURNS}
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<div class="form-group form-group-flex">
|
||||
<div class="col-md-2 control-label">
|
||||
<label for="return_delivery">Doprava zpět do e-shopu</label>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
{$new = ($body.data.status == Kupshop\ReclamationsBundle\Util\ReclamationsUtil::STATUS_NEW)}
|
||||
<select
|
||||
id="return_delivery"
|
||||
name="data[data][id_return_delivery]"
|
||||
class="form-control selecter"
|
||||
data-autocomplete="returns_deliveries"
|
||||
data-preload="returns_deliveries"
|
||||
{if !$new}disabled{/if}
|
||||
>
|
||||
<option value=""></option>
|
||||
{if $custom_data.id_return_delivery}
|
||||
<option value="{$custom_data.id_return_delivery}" selected></option>
|
||||
{/if}
|
||||
</select>
|
||||
</div>
|
||||
{if $custom_data.id_return_delivery}
|
||||
{$returnDeliveryLabel = $custom_data.returnDeliveryLabel|default:[]}
|
||||
{$returnDeliveryLabel = $returnDeliveryLabel[$custom_data.id_return_delivery]}
|
||||
{/if}
|
||||
{if $returnDeliveryLabel}
|
||||
<div class="col-md-1">
|
||||
{if $returnDeliveryLabel.label_url}
|
||||
<a href="{$returnDeliveryLabel.label_url}" title="Tisk štítku" target="_blank" class="btn-sm btn btn-default btn-xs">
|
||||
<span class="bi bi-image"></span>
|
||||
</a>
|
||||
{else}
|
||||
<span class="glyphicon glyphicon-warning-sign" style="color:#ffb700" title="Chybí odkaz na tisk štítku!"></span>
|
||||
{/if}
|
||||
</div>
|
||||
{if isSuperuser()}
|
||||
<div class="col-md-5">
|
||||
<span class="help-block">
|
||||
<i class="glyphicon glyphicon-flash" style="color:#AAB2BD;" title="Vidí pouze superadmin"></i>
|
||||
<abbr title="{$returnDeliveryLabel|json_encode}">{'returnLabelGenerateDescr'|translate:'Returns'}: response</abbr>
|
||||
</span>
|
||||
</div>
|
||||
{/if}
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{/ifmodule}
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<div class="form-group form-group-flex">
|
||||
<div class="col-md-2 control-label"><label>{'delivery'|translate}</label></div>
|
||||
<div class="col-md-4">
|
||||
<select class="selecter" name="data[data][delivery]">
|
||||
{foreach $body.deliveries as $delivery}
|
||||
<option value="{$delivery.id}" {if $body.selected_delivery == $delivery.id}selected{/if}>{$delivery.name_admin|default:$delivery.name}</option>
|
||||
{/foreach}
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-md-5">
|
||||
{if $body.delivery}
|
||||
<div>
|
||||
{$body.delivery->printDeliverySettings($body.fakeOrder) nofilter}
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h1 class="h4 main-panel-title">{'other'|translate}</h1>
|
||||
<div class="row">
|
||||
<div class="col-md-3"><label>{'preferred_handle_type'|translate}</label></div>
|
||||
<div class="col-md-3">
|
||||
<select class="selecter" name="data[preferred_handle_type]">
|
||||
<option value="">-- nevybráno --</option>
|
||||
{foreach $body.preferred_handle_types as $handleTypeId => $handleType}
|
||||
<option value="{$handleTypeId}" {if $handleTypeId == $body.data.preferred_handle_type}selected{/if}>{$handleType}</option>
|
||||
{/foreach}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<label>{'user_note'|translate}</label>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<label>{'descr'|translate}</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row bottom-space">
|
||||
<div class="col-md-6">
|
||||
<textarea class="form-control" name="data[user_note]">{$body.data.user_note}</textarea>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<textarea class="form-control" name="data[descr]">{$body.data.descr}</textarea>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="panel panel-default panel-sm">
|
||||
<div class="panel-heading"><h3 class="panel-title">{'history'|translate}</h3></div>
|
||||
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th width="13%">{'date'|translate:'base'}</th>
|
||||
<th width="15%">{'status'|translate}</th>
|
||||
<th width="55%">{'note'|translate}</th>
|
||||
<th width="10%">{'sent'|translate}</th>
|
||||
<th scope="col">admin</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{foreach $body.data.history as $key => $row}
|
||||
<tr style="border-bottom: thin; {if $row.notified == 3}background-color: #bfec55;{/if}">
|
||||
<td>{$row.date|format_datetime}</td>
|
||||
<td>{$row.status_name}</td>
|
||||
<td>{$row.comment nofilter}</td>
|
||||
<td>
|
||||
{if $row.notified == 1}
|
||||
Ano
|
||||
|
||||
{if !empty($row.custom_data.attachments)}
|
||||
{$attachments = []}
|
||||
{foreach $row.custom_data.attachments as $attachment}
|
||||
{$attachments[] = $body.attachmentTypes[$attachment]}
|
||||
{/foreach}
|
||||
|
||||
<span class="badge badge-default m-l-1" title="Přílohy: {join(', ', $attachments)}"><i class="glyphicon glyphicon-paperclip"></i></span>
|
||||
{/if}
|
||||
|
||||
{if !empty($row.custom_data['user-content'])}
|
||||
{$attachments = []}
|
||||
{foreach $row.custom_data['user-content'] as $attachment}
|
||||
{$attachments[] = $attachment.originalFilename}
|
||||
{/foreach}
|
||||
|
||||
<span class="badge badge-default m-l-1" title="Přílohy: {join(', ', $attachments)}"><i class="glyphicon glyphicon-paperclip"></i></span>
|
||||
{/if}
|
||||
{else}
|
||||
Ne
|
||||
{/if}
|
||||
</td>
|
||||
<td>{$row.admin_name}</td>
|
||||
</tr>
|
||||
{/foreach}
|
||||
|
||||
</tbody>
|
||||
|
||||
</table>
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
<div class="row">
|
||||
{if $body.acn == 'edit'}
|
||||
|
||||
{if $body.exchangeOrder}
|
||||
<div class="col-md-12">
|
||||
<div class="alert alert-info">
|
||||
Pro výměnu byla vytvořena objednávka <a href="javascript:nw('orders', {$body.exchangeOrder->id})"><strong>{$body.exchangeOrder->order_no}</strong></a>.
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
{if $body.data.handle_type == 2 && empty($body.data.bank_account)}
|
||||
<div class="col-md-12">
|
||||
<div class="alert alert-danger">
|
||||
Nepodařilo se vygenerovat údaje pro platbu, protože není vyplněné číslo účtu!
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
<input type="hidden" name="data[status]" value="{$body.data.status}" id="status_combo">
|
||||
<div class="col-md-6">
|
||||
{if $body.data->isClosed()}
|
||||
<div class="form-group form-group-flex">
|
||||
<div class="col-md-3 control-label"><label>{'handle_type'|translate}</label></div>
|
||||
<div class="col-md-9">
|
||||
{if isset($body.handle_types[$body.data.handle_type])}
|
||||
{$body.handle_types[$body.data.handle_type]}
|
||||
{else}
|
||||
Nevybráno
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="col-md-4">
|
||||
<button type="submit" class="btn btn-block btn-status"
|
||||
name="acn" value="reopen"
|
||||
style="background-color:#BBEECC;">
|
||||
Znovu otevřít
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
{else}
|
||||
<div class="form-group form-group-flex">
|
||||
<div class="col-md-3 control-label"><label>{'handle_type'|translate}</label></div>
|
||||
<div class="col-md-9">
|
||||
<input type="hidden" name="data[handle_type]" value="{if !$body.data.handle_type}-1{else}{$body.data.handle_type}{/if}" data-handle-type-input>
|
||||
<span>{if isset($body.handle_types[$body.data.handle_type])}
|
||||
{$body.handle_types[$body.data.handle_type]}
|
||||
{else}
|
||||
Nevybráno
|
||||
{/if}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group" id="statusButtons">
|
||||
{foreach $body.statuses as $key => $status}
|
||||
{if $key == 2}
|
||||
{continue}
|
||||
{/if}
|
||||
<div class="col-md-4">
|
||||
<button type="button" class="btn btn-block btn-status {if $body.data.status == $key}btn-active{/if}"
|
||||
style="background-color:#BBEECC;" data-status="{$key}" title="{$status}">
|
||||
{$status}
|
||||
</button>
|
||||
</div>
|
||||
{/foreach}
|
||||
|
||||
{* Zobazit button pro vybrani zpusobu doruceni *}
|
||||
{if $body.data.status >= 1}
|
||||
<div class="col-md-4">
|
||||
<div class="btn-group btn-block dropdown-toggle">
|
||||
<button data-handle-type-selecter type="button" class="btn btn-block btn-status" data-toggle="dropdown"
|
||||
style="background-color:#BBEECC;">
|
||||
{'handle_type'|translate} <span class="caret"></span>
|
||||
</button>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
{foreach $body.handle_types as $id => $status}
|
||||
<li><a data-handle-type="{$id}" data-status="2" >{$status}</a></li>
|
||||
{/foreach}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
{if $body.data.handle_type == 2 && !empty($body.data.bank_account)}
|
||||
<div class="row">
|
||||
<div class="col-md-7">
|
||||
<div class="col-md-12" style="padding-bottom: 15px">
|
||||
<strong style="text-decoration: underline">Údaje pro provedení platby</strong>
|
||||
</div>
|
||||
<div class="col-md-12">
|
||||
<div class="col-md-5">
|
||||
<strong>Číslo účtu</strong>
|
||||
</div>
|
||||
<div class="col-md-7">
|
||||
{$body.data.bank_account}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-md-12">
|
||||
<div class="col-md-5">
|
||||
<strong>Částka</strong>
|
||||
</div>
|
||||
<div class="col-md-7">
|
||||
{printPrice($body.returnPrice)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-md-12">
|
||||
<div class="col-md-5">
|
||||
<strong>VS</strong>
|
||||
</div>
|
||||
<div class="col-md-7">
|
||||
{$body.data.code}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-5">
|
||||
<div class="col-md-12" style="padding-bottom: 15px">
|
||||
<strong style="text-decoration: underline">QR platba</strong>
|
||||
</div>
|
||||
|
||||
<div class="col-md-12">
|
||||
<img width="175" src="{$view->getQRPayment()}">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{elseif $body.data.handle_type !== null && in_array($body.data.handle_type, $view->getPrintLabelHandleTypes())}
|
||||
<div class="row">
|
||||
<div class="col-md-4">
|
||||
<a href="launch.php?s=Reclamations.php&acn=printReclamation&ID={$body.data.id}" target="_blank" class="btn btn-block btn-primary">
|
||||
<span class="glyphicon glyphicon-print"></span>
|
||||
Tisk reklamace
|
||||
</a>
|
||||
</div>
|
||||
{ifmodule BALIKONOS}
|
||||
<div class="col-md-4">
|
||||
<a href="launch.php?s=Reclamations.php&acn=printLabel&ID={$body.data.id}" target="_blank" class="btn btn-block btn-primary">
|
||||
<span class="glyphicon glyphicon-print"></span>
|
||||
Tisk štítku
|
||||
</a>
|
||||
</div>
|
||||
{/ifmodule}
|
||||
<div class="col-md-4">
|
||||
<a href="launch.php?s=printCenter.php&type=order&set=Reclamations&ID={$body.data.id}{if $body.supplierReclamation.id_supplier}&id_supplier={$body.supplierReclamation.id_supplier}{/if}" target="_blank" class="btn btn-block btn-primary">
|
||||
<span class="glyphicon glyphicon-print"></span>
|
||||
Tisk polepky
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
{if !$body.data->isClosed()}
|
||||
{if !($body.data.handle_type !== null && in_array($body.data.handle_type, $view->getPrintLabelHandleTypes()))}
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<a href="launch.php?s=Reclamations.php&acn=printReclamation&ID={$body.data.id}" target="_blank" class="btn btn-block btn-primary">
|
||||
<span class="glyphicon glyphicon-print"></span>
|
||||
Tisk reklamace
|
||||
</a>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<a href="launch.php?s=printCenter.php&type=order&set=Reclamations&ID={$body.data.id}{if $body.supplierReclamation.id_supplier}&id_supplier={$body.supplierReclamation.id_supplier}{/if}" target="_blank" class="btn btn-block btn-primary">
|
||||
<span class="glyphicon glyphicon-print"></span>
|
||||
Tisk polepky
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
{/if}
|
||||
|
||||
</div>
|
||||
|
||||
{if !$body.data->isClosed()}
|
||||
<div class="col-md-6">
|
||||
<h1 class="h4 main-panel-title">{'comments'|translate} <span data-attachment="" class="badge badge-default pull-right"></span></h1>
|
||||
<textarea id="comments" name="data[comment]" wrap="soft"></textarea>
|
||||
{insert_wysiwyg target="comments" type="BasicTable"
|
||||
config="toolbarStartupExpanded : false,startupFocus : false,removePlugins : 'elementspath', height:'150px', resize_minHeight:'100px', resize_enabled:false, ignoreEmptyParagraph:true, startupOutlineBlocks:false"}
|
||||
<div class="checkbox">
|
||||
<input type="checkbox" class="check" value="1" name="data[doNotNotify]" id="donotnotify" {if $returnId}checked{/if}>
|
||||
<label for="donotnotify"><strong>{'negation'|translate:'orders'}</strong>{'sendEmail'|translate:'orders'}</label>
|
||||
</div>
|
||||
<div style="padding-top: 1em;">
|
||||
{* These status buttons works kinda differently, so we dont want to use user messages paired to statuses *}
|
||||
{* Only add buttons under message form *}
|
||||
<input type="hidden" name="data[user_message]" value="" id="status_comment">
|
||||
{include "block.UserMessages.tpl" skipBalikID=true}
|
||||
{renderMessageButtons}
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
<h4 class="main-panel-title">Přílohy</h4>
|
||||
<div class="row">
|
||||
<div class="col-xl-6 col-sm-6 col-xs-12">
|
||||
{$userContent = $custom_data['userContent']}
|
||||
<div class="panel panel-default panel-sm">
|
||||
<div class="panel-heading"></div>
|
||||
<table class="table">
|
||||
{foreach $userContent as $file}
|
||||
<tr>
|
||||
<td style="text-align: center;width: 100px;">
|
||||
{if $file.filename|strstr:".jpg" or $file.filename|strstr:".jpeg" or $file.filename|strstr:".png" or $file.filename|strstr:".gif"}
|
||||
<img src="{$file.src}" style="width: 70px;height: auto;">
|
||||
{/if}
|
||||
</td>
|
||||
<td style="vertical-align: middle;">
|
||||
{$file.originalFilename}
|
||||
</td>
|
||||
<td style="width: 120px; text-align: right; vertical-align: middle;">
|
||||
<a href="{$file.src}" target="_blank">Zobrazit <i class="glyphicon glyphicon-new-window"></i></a>
|
||||
</td>
|
||||
<td style="width: 120px; text-align: right; vertical-align: middle;">
|
||||
<a href="{$file.src}" download>Stáhnout <i class="glyphicon glyphicon-floppy-save"></i></a>
|
||||
</td>
|
||||
</tr>
|
||||
{foreachelse}
|
||||
<tr>
|
||||
<td>Žádné přílohy</td>
|
||||
</tr>
|
||||
{/foreach}
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-xl-6 col-sm-6 col-xs-12">
|
||||
{include "utils/fileUploader.tpl" pageType='reclamation'}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div id="flapUser" class="tab-pane fade active in boxStatic box">
|
||||
<h1 class="h4 main-panel-title">{'address'|translate}</h1>
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<div class="form-group form-group-flex">
|
||||
<div class="col-md-2 control-label"><label>{'name'|translate}</label></div>
|
||||
<div class="col-md-4">
|
||||
<input class="form-control input-sm" type="text" name="data[name]" value="{$body.data.address.name}">
|
||||
</div>
|
||||
|
||||
<div class="col-md-2 control-label"><label>{'surname'|translate}</label></div>
|
||||
<div class="col-md-4">
|
||||
<input class="form-control input-sm" type="text" name="data[surname]" value="{$body.data.address.surname}">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<div class="form-group form-group-flex">
|
||||
<div class="col-md-2 control-label"><label>{'street'|translate}</label></div>
|
||||
<div class="col-md-4">
|
||||
<input class="form-control input-sm" type="text" name="data[street]" value="{$body.data.address.street}">
|
||||
</div>
|
||||
|
||||
<div class="col-md-2 control-label"><label>{'city'|translate}</label></div>
|
||||
<div class="col-md-4">
|
||||
<input class="form-control input-sm" type="text" name="data[city]" value="{$body.data.address.city}">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<div class="form-group form-group-flex">
|
||||
<div class="col-md-2 control-label"><label>{'phone'|translate}</label></div>
|
||||
<div class="col-md-4">
|
||||
<input class="form-control input-sm" type="text" name="data[phone]" value="{$body.data.address.phone}">
|
||||
</div>
|
||||
|
||||
<div class="col-md-2 control-label"><label>{'zip'|translate}</label></div>
|
||||
<div class="col-md-4">
|
||||
<input class="form-control input-sm" type="text" name="data[zip]" value="{$body.data.address.zip}">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<div class="form-group form-group-flex">
|
||||
<div class="col-md-6"></div>
|
||||
<div class="col-md-2 control-label"><label>{'country'|translate}</label></div>
|
||||
<div class="col-md-4">
|
||||
{get_contexts country=1 assign="contexts"}
|
||||
<select class="selecter" name="data[country]">
|
||||
{foreach $contexts.country->getAll() as $country}
|
||||
<option value="{$country->getId()}"
|
||||
{if $body.data.address.country == $country->getId() || (empty($body.data.address.country) && $country->getId() == 'CZ')}selected{/if}>{$country->getName()}</option>
|
||||
{/foreach}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h1 class="h4 main-panel-title">{'bank_account'|translate}</h1>
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<div class="form-group form-group-flex">
|
||||
<div class="col-md-2 control-label"><label>{'bank_account'|translate}</label></div>
|
||||
<div class="col-md-4">
|
||||
<input class="form-control input-sm" type="text" name="data[bank_account]" id="bank_account" value="{$body.data.bank_account}" data-bv-bankaccount="true" >
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{/block}
|
||||
|
||||
{block js append}
|
||||
<script src="/admin/static/fineuploader/jquery.fine-uploader.min.js"></script>
|
||||
<script src="./static/js/EmailMessages.js"></script>
|
||||
<script src="/common/static/bootstrapvalidator/js/bootstrapValidator.min.js"></script>
|
||||
{if $cfg.Lang.language_admin != 'english'}
|
||||
<script src="/common/static/bootstrapvalidator/js/language/cs_CZ.js"></script>
|
||||
{/if}
|
||||
{/block}
|
||||
|
||||
<script>
|
||||
{block onready append}
|
||||
{if $body.acn == 'edit' && $body.data->isClosed()}
|
||||
$('#flapReclamation').find('input').each(function () {
|
||||
$(this).attr('disabled', 'disabled');
|
||||
});
|
||||
{/if}
|
||||
|
||||
$('[data-handle-type]').on('click', function () {
|
||||
var handleType = $(this).data('handle-type');
|
||||
|
||||
$('[data-handle-type-input]').val(handleType);
|
||||
var span = $('[data-handle-type-input]').closest('div').find('span');
|
||||
if (span) {
|
||||
span[0].innerText = this.innerText;
|
||||
}
|
||||
|
||||
$('input[name="Submit"]').click();
|
||||
});
|
||||
|
||||
var addressFields = {$body.address_fields|json_encode nofilter};
|
||||
|
||||
$('[data-autocomplete-search="orders"]').adminOrderAutoComplete({
|
||||
parameters: 'only_handled=1',
|
||||
select: function (e, data) {
|
||||
var item = data.data.items[data.item.data('autocomplete-item')];
|
||||
|
||||
$('[data-id-order]').val(item.id);
|
||||
$('[data-autocomplete-search="orders"]').val(item.order_no + ', ' + item.customer_name);
|
||||
$('[data-id-item]').val('');
|
||||
$('[data-autocomplete-search="order_item"]').val('');
|
||||
|
||||
// dynamicly change parameters option in order_item autocomplete
|
||||
$('[data-autocomplete-search="order_item"]').adminAutoComplete('option', 'parameters', 'orderIds=' + item.id);
|
||||
|
||||
// fill address
|
||||
autoFillAddress(item.id);
|
||||
|
||||
$('#item_selecter').show();
|
||||
|
||||
return false;
|
||||
},
|
||||
});
|
||||
|
||||
var autoFillAddress = function (id_order) {
|
||||
$.getJSON('launch.php?s=ajax.php&type=order&id_order=' + id_order, function (data) {
|
||||
// fill address inputs
|
||||
$.each(addressFields, function (index, value) {
|
||||
var prefix = 'delivery_';
|
||||
if (value == 'phone') {
|
||||
prefix = 'invoice_';
|
||||
}
|
||||
let el = $('[name="data[' + value + ']"]');
|
||||
|
||||
if(el.is('select')) {
|
||||
el.find('option[value="' + data[prefix + value] + '"]').attr('selected', 'selected');
|
||||
el.trigger("chosen:updated");
|
||||
} else {
|
||||
el.val(data[prefix + value]);
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
$('[data-autocomplete-search="order_item"]').adminAutoComplete({
|
||||
minLength: 0,
|
||||
type: 'ordersItems',
|
||||
parameters: 'orderIds=',
|
||||
{literal}
|
||||
subtemplates: {
|
||||
menuItem: '<div tabindex="-1" data-autocomplete-item="{{=index}}">' +
|
||||
'{{? item.image}}<img src="{{=item.image.src}}" alt="{{=item.image.descr}}">{{?}} ' +
|
||||
'<p>{{=item.descr}}<br><small>{{? item.code}}Kód: {{=item.code}} | {{?}}{{? item.ean}}EAN: {{=item.ean}} | {{?}}Skladem: {{=item.in_store}} ks{{? item.visible == "N"}} | Skrytý!{{?}}{{? item.visible == "O"}} | Prodej ukončen!{{?}}</small></p>' +
|
||||
'{{#def.buttons}}' +
|
||||
'</div>' +
|
||||
'{{#def.bottom}}',
|
||||
},
|
||||
{/literal}
|
||||
select: function (e, data) {
|
||||
var item = data.data.items[data.item.data('autocomplete-item')];
|
||||
|
||||
$('[data-id-item]').val(item.id);
|
||||
$('[data-autocomplete-search="order_item"]').val(item.descr);
|
||||
|
||||
return false;
|
||||
},
|
||||
});
|
||||
|
||||
$("#editform").bootstrapValidator();
|
||||
|
||||
$('#editform').on('submit', function () {
|
||||
if ($('[data-bac-has-error]').length) {
|
||||
alert('Zadané číslo účtu je chybné');
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
{if $body.acn == 'add' && $body.data.id_order}
|
||||
$('[data-autocomplete-search="orders"]').prop('disabled', true);
|
||||
|
||||
$('[data-autocomplete-search="order_item"]').adminAutoComplete('option', 'parameters', 'orderIds={$body.data.id_order}');
|
||||
|
||||
// fill address
|
||||
autoFillAddress('{$body.data.id_order}');
|
||||
|
||||
$('#item_selecter').show();
|
||||
{/if}
|
||||
{/block}
|
||||
</script>
|
||||
@@ -0,0 +1,111 @@
|
||||
<div id="flapReclamationsSettings" class="tab-pane boxStatic box">
|
||||
|
||||
<div class="row bottom-space">
|
||||
<div class="col-md-12">
|
||||
<h1 class="h4 main-panel-title">{'flapReclamationsSettings'|translate:'reclamationsWindowTab'}</h1>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<div class="col-md-3 control-label ">
|
||||
<a class="help-tip" data-toggle="tooltip" title="" data-original-title="{'adminOnlyToolTip'|translate:'Returns'}"><i class="bi bi-question-circle"></i></a>
|
||||
<label>{'adminOnly'|translate:'Returns'}</label></div>
|
||||
<div class="col-md-1">
|
||||
|
||||
{print_toggle name="reclamations][adminOnly" class='toggle-red' value=$dbcfg.reclamations.adminOnly|default:"N"}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<div class="col-md-2 control-label">
|
||||
<label>
|
||||
{'reclamation_days'|translate:'reclamationsWindowTab'}
|
||||
<a class="help-tip" data-toggle="tooltip" title="" data-original-title="{'reclamation_days_tooltip'|translate:'reclamationsWindowTab'}"><i class="bi bi-question-circle"></i></a>
|
||||
</label>
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<input type="text" class="form-control input-sm" name="data[reclamations][days]" size="30" value="{$dbcfg.reclamations.days}">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<div class="col-md-2 control-label">
|
||||
<label>
|
||||
{'shopkeeperEmail'|translate:'reclamationsWindowTab'}
|
||||
<a class="help-tip" data-toggle="tooltip" title="" data-original-title="{'shopkeeperEmailInfo'|translate:'reclamationsWindowTab'}">
|
||||
<i class="bi bi-question-circle"></i>
|
||||
</a>
|
||||
</label>
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<input type="text" class="form-control input-sm" name="data[reclamations][shopkeeper_email]" value="{$dbcfg.reclamations.shopkeeper_email}">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<div class="col-md-2 control-label">
|
||||
<label>
|
||||
{'delivery'|translate:'reclamationsWindowTab'}
|
||||
<a class="help-tip" data-toggle="tooltip" title="" data-original-title="{'reclamationsDelivery'|translate:'reclamationsWindowTab'}">
|
||||
<i class="bi bi-question-circle"></i>
|
||||
</a>
|
||||
</label>
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<select class="selecter" name="data[reclamations][delivery]">
|
||||
<option value="0">-- nevybráno --</option>
|
||||
{foreach $tab.data.deliveries as $delivery}
|
||||
<option value="{$delivery.id}" {if $dbcfg.reclamations.delivery == $delivery.id}selected{/if}>{$delivery.name_admin|default:$delivery.name}</option>
|
||||
{/foreach}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row bottom-space">
|
||||
<div class="col-md-12">
|
||||
<h1 class="h4 main-panel-title">{'flapReclamationsInstructions'|translate:'reclamationsWindowTab'}</h1>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="panel panel-default" id="#reclamations_symbols">
|
||||
<div class="panel-heading" data-toggle="collapse" data-target="#reclamations-symbol-collapse">
|
||||
Zástupné symboly
|
||||
<i class="glyphicon glyphicon-minus-sign"></i>
|
||||
</div>
|
||||
|
||||
<div class="panel-collapse collapse symbol-collapse" id="reclamations-symbol-collapse">
|
||||
{$placeholders = $tab.data.tabView->getPlaceholders()}
|
||||
{$half = (($placeholders|count)/ 2)|round}
|
||||
{foreach $placeholders as $key => $placeholder}
|
||||
{if $placeholder@first}
|
||||
<div>
|
||||
<table class="table table-striped">
|
||||
{/if}
|
||||
{if $placeholder@index == $half}
|
||||
</table>
|
||||
</div>
|
||||
<div>
|
||||
<table class="table table-striped">
|
||||
{/if}
|
||||
<tr>
|
||||
<td><strong>{literal}{{/literal}{$key}{literal}}{/literal}</strong></td>
|
||||
<td>{$placeholder.text nofilter}</td>
|
||||
</tr>
|
||||
{if $placeholder@last}
|
||||
</table>
|
||||
</div>
|
||||
{/if}
|
||||
{/foreach}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<div class="col-md-3 control-label"><label>{'returnDescr'|translate:'reclamationsWindowTab'}</label></div>
|
||||
<div class="col-md-8">
|
||||
<textarea name="data[reclamations][descr]" rows="14" cols="30">{$dbcfg.reclamations.descr}</textarea>
|
||||
{insert_wysiwyg target="data[reclamations][descr]"}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{block "reclamations-end"}{/block}
|
||||
</div>
|
||||
@@ -0,0 +1,37 @@
|
||||
<?php
|
||||
|
||||
namespace KupShop\ReclamationsBundle\AdminRegister;
|
||||
|
||||
use KupShop\AdminBundle\AdminRegister\AdminRegister;
|
||||
use KupShop\AdminBundle\AdminRegister\IAdminRegisterDynamic;
|
||||
use KupShop\AdminBundle\AdminRegister\IAdminRegisterStatic;
|
||||
use KupShop\ReclamationsBundle\ReclamationsBundle;
|
||||
|
||||
class ReclamationsAdminRegister extends AdminRegister implements IAdminRegisterDynamic, IAdminRegisterStatic
|
||||
{
|
||||
public function getDynamicMenu(): array
|
||||
{
|
||||
return [
|
||||
static::createMenuItem('ordersMenu', [
|
||||
'name' => 'Reclamations',
|
||||
'title' => translate('reclamations', 'Reclamations'),
|
||||
'left' => 's=menu.php&type=Reclamations',
|
||||
'right' => 's=list.php&type=Reclamations',
|
||||
]),
|
||||
];
|
||||
}
|
||||
|
||||
public static function getPermissions(): array
|
||||
{
|
||||
return [
|
||||
static::createPermissions('Reclamations', [\Modules::RECLAMATIONS], ['RECLAMATIONS']),
|
||||
];
|
||||
}
|
||||
|
||||
public function getActivityLogTags(): array
|
||||
{
|
||||
return [
|
||||
static::createActivityLogTag(ReclamationsBundle::LOG_TAG_RECLAMATIONS, translate('activityLogTag', 'Reclamations')),
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
<?php
|
||||
|
||||
namespace KupShop\ReclamationsBundle\Attachment;
|
||||
|
||||
use KupShop\KupShopBundle\Email\EmailGroupTypeEnum;
|
||||
use KupShop\KupShopBundle\Util\Pdf\HTMLToPDF;
|
||||
use KupShop\OrderingBundle\Attachment\BaseAttachment;
|
||||
use KupShop\OrderingBundle\Util\Invoice\PdfGenerator;
|
||||
use KupShop\ReclamationsBundle\Entity\ReclamationEntity;
|
||||
use KupShop\ReclamationsBundle\Util\ReclamationsUtil;
|
||||
|
||||
class ReclamationPDFAttachment extends BaseAttachment
|
||||
{
|
||||
protected static $name = 'Reklamace';
|
||||
protected static $type = 'reclamation';
|
||||
protected static $group = EmailGroupTypeEnum::RECLAMATION;
|
||||
|
||||
protected $filename = 'Reklamace_{KOD}.pdf';
|
||||
protected $template = 'reclamations/pdf/reclamationPDF.tpl';
|
||||
|
||||
/** @var ReclamationEntity */
|
||||
protected $reclamation;
|
||||
|
||||
private $pdfGenerator;
|
||||
private $reclamationsUtil;
|
||||
|
||||
public function __construct(PdfGenerator $pdfGenerator, ReclamationsUtil $reclamationsUtil)
|
||||
{
|
||||
$this->pdfGenerator = $pdfGenerator;
|
||||
$this->reclamationsUtil = $reclamationsUtil;
|
||||
}
|
||||
|
||||
public static function isAllowed()
|
||||
{
|
||||
// aby se nezobrazovala v prilohach k emailum
|
||||
return true;
|
||||
}
|
||||
|
||||
public function getFilename(): string
|
||||
{
|
||||
return $this->reclamationsUtil->replacePlaceholders(translate_shop('reclamation_filename', 'attachments'), ['KOD' => $this->reclamation->getCode()]);
|
||||
}
|
||||
|
||||
public function setReclamation(ReclamationEntity $reclamation)
|
||||
{
|
||||
$this->reclamation = $reclamation;
|
||||
}
|
||||
|
||||
public function getReclamation(): ReclamationEntity
|
||||
{
|
||||
return $this->reclamation;
|
||||
}
|
||||
|
||||
public function getContent()
|
||||
{
|
||||
$order = null;
|
||||
if ($this->reclamation->getIdOrder()) {
|
||||
$order = new \Order();
|
||||
$order->createFromDB($this->reclamation->getIdOrder());
|
||||
}
|
||||
|
||||
$smarty = createSmarty(false, true);
|
||||
$smarty->assign([
|
||||
'reclamation' => $this->reclamation,
|
||||
'order' => $order,
|
||||
]);
|
||||
|
||||
$content = $smarty->fetch($this->template);
|
||||
|
||||
$html2pdf = new HTMLToPDF();
|
||||
|
||||
return $html2pdf->generatePDF($content, null, true);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,156 @@
|
||||
<?php
|
||||
|
||||
namespace KupShop\ReclamationsBundle\Controller;
|
||||
|
||||
use KupShop\KupShopBundle\Exception\RedirectException;
|
||||
use KupShop\KupShopBundle\Routing\TranslatedRoute;
|
||||
use KupShop\KupShopBundle\Views\Traits\MessagesTrait;
|
||||
use KupShop\OrderingBundle\Util\Order\OrderActivationUtil;
|
||||
use KupShop\OrderingBundle\Util\UserContent\UserContent;
|
||||
use KupShop\ReclamationsBundle\Attachment\ReclamationPDFAttachment;
|
||||
use KupShop\ReclamationsBundle\Util\ReclamationsUtil;
|
||||
use KupShop\ReclamationsBundle\View\CreateReclamationView;
|
||||
use KupShop\ReclamationsBundle\View\ReclamationsView;
|
||||
use KupShop\ReclamationsBundle\View\ReclamationView;
|
||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||
use Symfony\Component\HttpFoundation\RedirectResponse;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
|
||||
class ReclamationsController extends AbstractController
|
||||
{
|
||||
use MessagesTrait;
|
||||
|
||||
/**
|
||||
* @TranslatedRoute("/#reclamations#/#reclamations-list#/")
|
||||
*/
|
||||
public function reclamationsAction(Request $request, ReclamationsView $view): Response
|
||||
{
|
||||
return $view->getResponse($request);
|
||||
}
|
||||
|
||||
/**
|
||||
* @TranslatedRoute("/#reclamations#/#create_reclamation#/")
|
||||
*/
|
||||
public function createReclamationAction(Request $request, CreateReclamationView $view, OrderActivationUtil $activationUtil): Response
|
||||
{
|
||||
$view->setStep('products');
|
||||
$filter = $request->get('filter', []);
|
||||
|
||||
if ($request->get('nextStep')) {
|
||||
if ($request->get('item_id') && $request->get('item_pieces')) {
|
||||
throw new RedirectException(path('kupshop_reclamations_reclamations_createreclamationsummary',
|
||||
['item_id' => $request->get('item_id'), 'pieces' => $request->get('item_pieces')]));
|
||||
} else {
|
||||
addUserMessage(translate('error_no_items', 'returns'), 'danger');
|
||||
}
|
||||
} elseif (($id_order = $request->get('id_order')) && ($cf = $request->get('cf'))) {
|
||||
if (!$activationUtil->activateOrderWithSecurityCode($id_order, $cf)) {
|
||||
$this->addErrorMessage(
|
||||
translate('error_order_not_found', 'returns')
|
||||
);
|
||||
|
||||
return new RedirectResponse(
|
||||
path('kupshop_returns_returns_createreturnslogin')
|
||||
);
|
||||
}
|
||||
|
||||
$filter['order'] = $id_order;
|
||||
}
|
||||
|
||||
$view->setFilter($filter);
|
||||
|
||||
return $view->getResponse($request);
|
||||
}
|
||||
|
||||
/**
|
||||
* @TranslatedRoute("/#reclamations#/#reclamation_summary#/")
|
||||
*/
|
||||
public function createReclamationSummaryAction(Request $request, CreateReclamationView $view, UserContent $userContent): Response
|
||||
{
|
||||
$view->setStep('summary')->setItemId($request->get('item_id'))->setItemPieces($request->get('pieces'));
|
||||
|
||||
if ($request->get('nextStep')) {
|
||||
$user_content = $userContent->getData('reclamation');
|
||||
$view->handleStep_reclamationSummary(
|
||||
$request->get('delivery'),
|
||||
$request->get('bank_account'),
|
||||
$request->get('preferred_handle_type'),
|
||||
$request->get('note'),
|
||||
$user_content
|
||||
);
|
||||
}
|
||||
|
||||
return $view->getResponse($request);
|
||||
}
|
||||
|
||||
/**
|
||||
* @TranslatedRoute("/#reclamations#/")
|
||||
*/
|
||||
public function createReclamationLoginAction(Request $request, CreateReclamationView $view, OrderActivationUtil $activationUtil): Response
|
||||
{
|
||||
$view->setStep('login');
|
||||
|
||||
// nacteni objednavky pro uzivatele bez registrace
|
||||
if ($request->isMethod('POST')) {
|
||||
if (!$activationUtil->activateFromRequest($request)) {
|
||||
$this->addErrorMessage(
|
||||
translate('error_order_not_found', 'returns')
|
||||
);
|
||||
|
||||
return new RedirectResponse(
|
||||
path('kupshop_reclamations_reclamations_createreclamationlogin')
|
||||
);
|
||||
}
|
||||
|
||||
return new RedirectResponse(
|
||||
path('kupshop_reclamations_reclamations_createreclamation')
|
||||
);
|
||||
}
|
||||
|
||||
return $view->getResponse($request);
|
||||
}
|
||||
|
||||
/**
|
||||
* @TranslatedRoute("/#reclamations#/{id}/", requirements={"id"="\d+"})
|
||||
*/
|
||||
public function reclamationAction(Request $request, ReclamationView $view, $id, UserContent $userContent): Response
|
||||
{
|
||||
if (getVal('success') == 1) {
|
||||
$userContent->setData('reclamation', null);
|
||||
}
|
||||
|
||||
$view->setReclamationId($id);
|
||||
|
||||
return $view->getResponse($request);
|
||||
}
|
||||
|
||||
/**
|
||||
* @TranslatedRoute("/#reclamations#/{id}/pdf/")
|
||||
*/
|
||||
public function reclamationAttachmentAction(ReclamationPDFAttachment $reclamationPDFAttachment, ReclamationsUtil $reclamationsUtil, $id, Request $request): Response
|
||||
{
|
||||
if (!($reclamation = $reclamationsUtil->getReclamation($id, $request->get('cf') != $reclamationsUtil->getSecurityCode($id)))) {
|
||||
throw new RedirectException(path('kupshop_reclamations_reclamations_createreclamationlogin'));
|
||||
}
|
||||
|
||||
$reclamationPDFAttachment->setReclamation($reclamation);
|
||||
|
||||
try {
|
||||
$response = new Response();
|
||||
$response->headers->set('Content-Type', $reclamationPDFAttachment->getMimeType());
|
||||
$response->headers->set('Content-Disposition', 'inline; filename="'.$reclamationPDFAttachment->getFilename().'"');
|
||||
$content = $reclamationPDFAttachment->getContent();
|
||||
if (!$content) {
|
||||
throw new \UnexpectedValueException('PDF error: server returned false');
|
||||
}
|
||||
$response->setContent($content);
|
||||
|
||||
return $response;
|
||||
} catch (\UnexpectedValueException $e) {
|
||||
getRaven()->captureException($e);
|
||||
|
||||
return new Response('Přílohu se nepodařilo vygenerovat, zkuste to znovu.');
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
<?php
|
||||
|
||||
namespace KupShop\ReclamationsBundle\Email;
|
||||
|
||||
class ReclamationAcceptEmail extends ReclamationEmail
|
||||
{
|
||||
protected static $name = 'Přijetí reklamace';
|
||||
protected static $type = 'RECLAMATION_ACCEPT_EMAIL';
|
||||
protected static $priority = -1;
|
||||
|
||||
protected $subject = 'Obdrželi jsme balíček s Vaší reklamací {KOD_REKLAMACE}';
|
||||
protected $template = 'email/email_reclamation_accept.tpl';
|
||||
|
||||
protected $defaultEnabled = 'N';
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
<?php
|
||||
|
||||
namespace KupShop\ReclamationsBundle\Email;
|
||||
|
||||
class ReclamationCreateAdminEmail extends ReclamationEmail
|
||||
{
|
||||
protected static $name = 'Obchodníkovi při vytvoření reklamace';
|
||||
protected static $type = 'RECLAMATION_CREATE_ADMIN';
|
||||
protected static $priority = -1;
|
||||
|
||||
protected $subject = 'Přijali jsme formulář s reklamací {KOD_REKLAMACE}';
|
||||
protected $template = 'email/email_reclamation_create_admin.tpl';
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
<?php
|
||||
|
||||
namespace KupShop\ReclamationsBundle\Email;
|
||||
|
||||
class ReclamationCreateEmail extends ReclamationEmail
|
||||
{
|
||||
protected static $name = 'Vytvoření reklamace';
|
||||
protected static $type = 'RECLAMATION_CREATE_EMAIL';
|
||||
protected static $priority = -1;
|
||||
|
||||
protected $subject = 'Přijali jsme formulář s reklamací {KOD_REKLAMACE}';
|
||||
protected $template = 'email/email_reclamation_create.tpl';
|
||||
}
|
||||
370
bundles/KupShop/ReclamationsBundle/Email/ReclamationEmail.php
Normal file
370
bundles/KupShop/ReclamationsBundle/Email/ReclamationEmail.php
Normal file
@@ -0,0 +1,370 @@
|
||||
<?php
|
||||
|
||||
namespace KupShop\ReclamationsBundle\Email;
|
||||
|
||||
use KupShop\KupShopBundle\Email\BaseEmail;
|
||||
use KupShop\KupShopBundle\Email\EmailGroupTypeEnum;
|
||||
use KupShop\KupShopBundle\Util\Compat\ServiceContainer;
|
||||
use KupShop\KupShopBundle\Util\HtmlBuilder\HTML;
|
||||
use KupShop\OrderingBundle\Util\Attachment\AttachmentLocator;
|
||||
use KupShop\ReclamationsBundle\Entity\ReclamationEntity;
|
||||
use KupShop\ReclamationsBundle\Util\ReclamationsUtil;
|
||||
use KupShop\ReturnsBundle\Util\ReturnsUtil;
|
||||
use Symfony\Component\Routing\Router;
|
||||
use Symfony\Component\Routing\RouterInterface;
|
||||
|
||||
class ReclamationEmail extends BaseEmail
|
||||
{
|
||||
protected static $priority = -2;
|
||||
protected static $type = 'RECLAMATION_EMAIL';
|
||||
protected static $group = EmailGroupTypeEnum::RECLAMATION;
|
||||
|
||||
/** @var ReclamationEntity */
|
||||
protected $reclamation;
|
||||
protected $comment;
|
||||
|
||||
/** @var ReclamationsUtil */
|
||||
private $reclamationsUtil;
|
||||
private $logHistory = false;
|
||||
|
||||
public static string $type_test_email = 'reclamations';
|
||||
|
||||
/** @var AttachmentLocator */
|
||||
private $attachmentLocator;
|
||||
|
||||
/**
|
||||
* @required
|
||||
*/
|
||||
public function setReclamationsUtil(ReclamationsUtil $reclamationsUtil)
|
||||
{
|
||||
$this->reclamationsUtil = $reclamationsUtil;
|
||||
}
|
||||
|
||||
/**
|
||||
* @required
|
||||
*/
|
||||
public function setAttachmentLocator(AttachmentLocator $attachmentLocator)
|
||||
{
|
||||
$this->attachmentLocator = $attachmentLocator;
|
||||
}
|
||||
|
||||
/** @var ReclamationsUtil */
|
||||
private $returnsUtil;
|
||||
|
||||
/**
|
||||
* @required
|
||||
*/
|
||||
public function setReturnsUtil(?ReturnsUtil $returnsUtil)
|
||||
{
|
||||
$this->returnsUtil = $returnsUtil;
|
||||
}
|
||||
|
||||
public function setComment($comment)
|
||||
{
|
||||
$this->comment = $comment;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function setLogHistory($logHistory)
|
||||
{
|
||||
$this->logHistory = $logHistory;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function setReclamation(ReclamationEntity $reclamation)
|
||||
{
|
||||
$this->reclamation = $reclamation;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function testEmail(): array
|
||||
{
|
||||
if (!isset($this->reclamation)) {
|
||||
$this->setTestEntity();
|
||||
}
|
||||
|
||||
return parent::testEmail();
|
||||
}
|
||||
|
||||
public function setTestEntity(?int $id = null): void
|
||||
{
|
||||
if (!$id) {
|
||||
$id = sqlQueryBuilder()->select('MAX(id)')->from('reclamations')->execute()->fetchOne();
|
||||
}
|
||||
|
||||
if ($id) {
|
||||
$this->reclamation = $this->reclamationsUtil->getReclamation($id);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$this->reclamation = new ReclamationEntity();
|
||||
$this->reclamation->setCode('R1234');
|
||||
$this->reclamation->setId(1234);
|
||||
$this->reclamation->setPackageId('TESTTEST');
|
||||
$this->reclamation->setBankAccount('TESTTESTTEST');
|
||||
$this->reclamation->setDescr('Some test description');
|
||||
$this->reclamation->setData([]);
|
||||
$this->reclamation->setOrderNumber('123456');
|
||||
$this->reclamation->setIdOrder('1');
|
||||
$this->reclamation->setDateCreated('2023-01-05 12:20:15');
|
||||
}
|
||||
|
||||
public function getEmail($replacements = []): array
|
||||
{
|
||||
$template = $this->getEmailTemplate();
|
||||
|
||||
$message = $this->renderEmail($template);
|
||||
$message['body'] = $this->reclamationsUtil->replacePlaceholders($message['body'], [], [$this, 'replacePlaceholdersItem']);
|
||||
$message['subject'] = $this->reclamationsUtil->replacePlaceholders($message['subject'], [], [$this, 'replacePlaceholdersItem']);
|
||||
|
||||
return $message;
|
||||
}
|
||||
|
||||
public function sendEmail($message)
|
||||
{
|
||||
if ($bcc = (\Settings::getDefault()->archive_email ?? null)) {
|
||||
$message['bcc'] = [$bcc];
|
||||
}
|
||||
|
||||
$sent = parent::sendEmail($message);
|
||||
|
||||
if ($sent && $this->logHistory && $this->reclamation) {
|
||||
if ($this->comment) {
|
||||
$template = $this->comment;
|
||||
} else {
|
||||
$template = $this->getEmailTemplate()['body'];
|
||||
}
|
||||
|
||||
$template = $this->reclamationsUtil->replacePlaceholders($template, [], [$this, 'replacePlaceholdersItem']);
|
||||
|
||||
$attachments = [];
|
||||
if (!empty($message['attachments'])) {
|
||||
foreach ($message['attachments'] as $attachment) {
|
||||
$attachments[] = $attachment['type'];
|
||||
}
|
||||
}
|
||||
|
||||
$this->reclamationsUtil->logHistory($this->reclamation->getId(), $template, true, $this->reclamation->getStatus(), ['attachments' => $attachments]);
|
||||
}
|
||||
|
||||
return $sent;
|
||||
}
|
||||
|
||||
public function renderEmail($template, $data = [], $base_template = 'other.tpl'): array
|
||||
{
|
||||
if ($this->comment) {
|
||||
$template['body'] = $this->comment;
|
||||
}
|
||||
|
||||
$message = parent::renderEmail($template, $data, $base_template);
|
||||
|
||||
if ($this->reclamation) {
|
||||
$message['to'] = $this->reclamation->getEmail();
|
||||
}
|
||||
$message['template'] = $template;
|
||||
|
||||
return $message;
|
||||
}
|
||||
|
||||
public static function getPlaceholders()
|
||||
{
|
||||
$placeholders = [
|
||||
'KOD_REKLAMACE' => [
|
||||
'text' => 'Kód reklamace',
|
||||
],
|
||||
'ODKAZ_REKLAMACE' => [
|
||||
'text' => 'Odkaz na reklamace',
|
||||
],
|
||||
'REKLAMACE_INSTRUKCE' => [
|
||||
'text' => 'Instrukce',
|
||||
],
|
||||
'KOD_OBJEDNAVKY' => [
|
||||
'text' => 'Kód objednávky vyřizující reklamaci výměnou',
|
||||
],
|
||||
'ODKAZ_OBJEDNAVKA' => [
|
||||
'text' => 'Odkaz na objednávku vyřizující reklamaci výměnou',
|
||||
],
|
||||
'KOD_PUVODNI_OBJEDNAVKY' => [
|
||||
'text' => 'Kód objednávky ze které byla vytvořena reklamace',
|
||||
],
|
||||
'ODKAZ_PUVODNI_OBJEDNAVKA' => [
|
||||
'text' => 'Odkaz na objednávku ze které byla vytvořena reklamace',
|
||||
],
|
||||
'ODKAZ_PDF' => [
|
||||
'text' => 'Odkaz na PDF',
|
||||
],
|
||||
'BALIK_ID' => [
|
||||
'text' => 'Číslo balíku',
|
||||
],
|
||||
'DATUM_VYTVORENI' => [
|
||||
'text' => 'Datum vytvoření reklamace',
|
||||
],
|
||||
'CISLO_UCTU' => [
|
||||
'text' => 'Číslo účtu',
|
||||
],
|
||||
'PACKAGE_LABEL' => [
|
||||
'text' => 'Autorizační kód Odvozu zboží',
|
||||
],
|
||||
'POSUDEK' => [
|
||||
'text' => 'Posudek',
|
||||
],
|
||||
'POZNAMKA_UZIVATELE' => [
|
||||
'text' => 'Poznámka uživatele',
|
||||
],
|
||||
'REKAPITULACE_OBCHODNIKOVI' => [
|
||||
'text' => 'Rekapitulace obchodníkovi',
|
||||
],
|
||||
'PRILOHY_NAHRANE_ZAKAZNIKEM' => [
|
||||
'text' => 'Vloží seznam příloh nahraných zákazníkem',
|
||||
],
|
||||
];
|
||||
|
||||
return [self::$type => $placeholders] + (parent::getPlaceholders() ?? []);
|
||||
}
|
||||
|
||||
public function replacePlaceholdersItem($placeholder)
|
||||
{
|
||||
$result = parent::replacePlaceholdersItem($placeholder);
|
||||
$dbcfg = \Settings::getDefault();
|
||||
|
||||
if (!$result) {
|
||||
switch ($placeholder) {
|
||||
case 'KOD_REKLAMACE':
|
||||
return $this->reclamation->getCode();
|
||||
case 'ODKAZ_REKLAMACE':
|
||||
return path('kupshop_reclamations_reclamations_reclamation', [
|
||||
'id' => $this->reclamation->getId(),
|
||||
'cf' => $this->reclamationsUtil->getSecurityCode($this->reclamation->getId()),
|
||||
]);
|
||||
case 'ODKAZ_VRATKA':
|
||||
$returnId = $this->reclamation->getData()['return'] ?? null;
|
||||
if ($returnId) {
|
||||
return path('kupshop_returns_returns_return', ['id' => $returnId, 'cf' => $this->returnsUtil->getSecurityCode($returnId)]);
|
||||
}
|
||||
// no break
|
||||
case 'KOD_VRATKY':
|
||||
return $this->returnsUtil->getCode($this->reclamation->getData()['return'] ?? null);
|
||||
case 'REKLAMACE_INSTRUKCE':
|
||||
return $dbcfg->reclamations['descr'] ?? '';
|
||||
case 'KOD_OBJEDNAVKY':
|
||||
$exchangeOrderID = $this->reclamation->getData()['exchange_order'] ?? null;
|
||||
if ($exchangeOrderID) {
|
||||
$order = new \Order();
|
||||
$order->createFromDB($exchangeOrderID);
|
||||
|
||||
return $order->order_no;
|
||||
}
|
||||
|
||||
return '';
|
||||
case 'ODKAZ_OBJEDNAVKA':
|
||||
$exchangeOrderID = $this->reclamation->getData()['exchange_order'] ?? null;
|
||||
if ($exchangeOrderID) {
|
||||
$order = new \Order();
|
||||
$order->createFromDB($exchangeOrderID);
|
||||
|
||||
return $order->getUrl();
|
||||
}
|
||||
|
||||
return '';
|
||||
case 'ODKAZ_PUVODNI_OBJEDNAVKA':
|
||||
$id_order = $this->reclamation->getIdOrder();
|
||||
|
||||
$order = new \Order();
|
||||
$order->createFromDB($id_order);
|
||||
|
||||
return $order->getUrl();
|
||||
case 'KOD_PUVODNI_OBJEDNAVKY':
|
||||
return $this->reclamation->getOrderNumber();
|
||||
case 'ODKAZ_PDF':
|
||||
return path('kupshop_reclamations_reclamations_reclamationattachment', [
|
||||
'id' => $this->reclamation->getId(),
|
||||
'cf' => $this->reclamationsUtil->getSecurityCode($this->reclamation->getId()),
|
||||
], Router::ABSOLUTE_URL);
|
||||
case 'BALIK_ID':
|
||||
return $this->reclamation->getPackageId();
|
||||
case 'CISLO_UCTU':
|
||||
return $this->reclamation->getBankAccount();
|
||||
case 'PACKAGE_LABEL':
|
||||
return $this->reclamationsUtil->getAuthCode($this->reclamation->getId());
|
||||
case 'POSUDEK':
|
||||
return $this->reclamation->getDescr();
|
||||
case 'DATUM_VYTVORENI':
|
||||
$date = $this->reclamation->getDateCreated();
|
||||
if (!$date) {
|
||||
return '';
|
||||
}
|
||||
|
||||
return \DateTime::createFromFormat('Y-m-d H:i:s', $date)->format(\Settings::getDateFormat());
|
||||
case 'POZNAMKA_UZIVATELE':
|
||||
return $this->reclamation->getUserNote();
|
||||
case 'REKAPITULACE_OBCHODNIKOVI':
|
||||
// Objednavka, z ktere byla reklamace vytvorena
|
||||
$order = new \Order();
|
||||
$order->createFromDB($this->reclamation->getIdOrder());
|
||||
|
||||
$smarty = createSmarty(true, true);
|
||||
$smarty->assign('reclamation', $this->reclamation);
|
||||
$smarty->assign('order', $order);
|
||||
|
||||
return $smarty->fetch('email/reclamationShopkeeper.tpl');
|
||||
case 'PRILOHY_NAHRANE_ZAKAZNIKEM':
|
||||
$returnCustomData = $this->reclamation->getData() ?? [];
|
||||
$element = HTML::create('div')
|
||||
->tag('h3')->text(translate_shop('attachments_uploaded_by_customer', 'email'))->end();
|
||||
$list = $element->tag('ul');
|
||||
foreach ($returnCustomData['userContent'] ?? [] as $fileInfo) {
|
||||
$src = ltrim($fileInfo['src'], '/');
|
||||
$list->tag('li')
|
||||
->tag('a')
|
||||
->attr('href', path('page', ['path' => $src], RouterInterface::ABSOLUTE_URL))
|
||||
->text($fileInfo['originalFilename'])->end()->end();
|
||||
}
|
||||
|
||||
return $element->end()->end();
|
||||
}
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
public function getAttachments($template): array
|
||||
{
|
||||
if (empty($template['attachments'])) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return $this->renderAttachments(function () use ($template): iterable {
|
||||
$order = new \Order();
|
||||
$order->createFromDB($this->reclamation->getIdOrder());
|
||||
|
||||
$types = json_decode($template['attachments'], true);
|
||||
foreach ($types as $type) {
|
||||
$attachment = $this->attachmentLocator->getServiceByType($type, $order);
|
||||
$attachment->setReclamation($this->reclamation);
|
||||
yield $attachment;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public function getTestType(): string
|
||||
{
|
||||
return self::$type_test_email;
|
||||
}
|
||||
|
||||
public function __wakeup()
|
||||
{
|
||||
parent::__wakeup();
|
||||
|
||||
$this->attachmentLocator = ServiceContainer::getService(AttachmentLocator::class);
|
||||
$this->reclamationsUtil = ServiceContainer::getService(ReclamationsUtil::class);
|
||||
}
|
||||
|
||||
public function __sleep()
|
||||
{
|
||||
return array_diff(parent::__sleep(), ['attachmentLocator', 'reclamationsUtil']);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
<?php
|
||||
|
||||
namespace KupShop\ReclamationsBundle\Email;
|
||||
|
||||
class ReclamationHandleCancelEmail extends ReclamationEmail
|
||||
{
|
||||
protected static $name = 'Vyřízení reklamace: zamítnuto';
|
||||
protected static $type = 'RECLAMATION_HANDLE_CANCEL_EMAIL';
|
||||
|
||||
protected $subject = 'Informace o výsledku reklamace {KOD_REKLAMACE}';
|
||||
protected $template = 'email/email_reclamation_handle_cancel.tpl';
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
<?php
|
||||
|
||||
namespace KupShop\ReclamationsBundle\Email;
|
||||
|
||||
class ReclamationHandleConvertToReturnlEmail extends ReclamationEmail
|
||||
{
|
||||
protected static $name = 'Vyřízení reklamace: reklamace zamítnuta, vytvořena vratka';
|
||||
protected static $type = 'RECLAMATION_HANDLE_CONVERT_TO_RETURN_EMAIL';
|
||||
|
||||
protected $subject = 'Informace o výsledku reklamace {KOD_REKLAMACE}';
|
||||
protected $template = 'email/email_reclamation_handle_convert_to_return.tpl';
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
<?php
|
||||
|
||||
namespace KupShop\ReclamationsBundle\Email;
|
||||
|
||||
class ReclamationHandleExchangeEmail extends ReclamationEmail
|
||||
{
|
||||
protected static $name = 'Vyřízení reklamace: výměna';
|
||||
protected static $type = 'RECLAMATION_HANDLE_EXCHANGE_EMAIL';
|
||||
|
||||
protected $subject = 'Informace o výsledku reklamace {KOD_REKLAMACE}';
|
||||
protected $template = 'email/email_reclamation_handle_exchange.tpl';
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
<?php
|
||||
|
||||
namespace KupShop\ReclamationsBundle\Email;
|
||||
|
||||
class ReclamationHandleFixEmail extends ReclamationEmail
|
||||
{
|
||||
protected static $name = 'Vyřízení reklamace: oprava';
|
||||
protected static $type = 'RECLAMATION_HANDLE_FIX_EMAIL';
|
||||
|
||||
protected $subject = 'Informace o výsledku reklamace {KOD_REKLAMACE}';
|
||||
protected $template = 'email/email_reclamation_handle_fix.tpl';
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
<?php
|
||||
|
||||
namespace KupShop\ReclamationsBundle\Email;
|
||||
|
||||
class ReclamationHandleReturnEmail extends ReclamationEmail
|
||||
{
|
||||
protected static $name = 'Vyřízení reklamace: vrácení peněz';
|
||||
protected static $type = 'RECLAMATION_HANDLE_RETURN_EMAIL';
|
||||
|
||||
protected $subject = 'Informace o výsledku reklamace {KOD_REKLAMACE}';
|
||||
protected $template = 'email/email_reclamation_handle_return.tpl';
|
||||
|
||||
protected $defaultEnabled = 'N';
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace KupShop\ReclamationsBundle\Email;
|
||||
|
||||
use KupShop\KupShopBundle\Email\UserMessagesInterface;
|
||||
use KupShop\KupShopBundle\Email\UserMessagesTrait;
|
||||
|
||||
class ReclamationMessageEmail extends ReclamationEmail implements UserMessagesInterface
|
||||
{
|
||||
use UserMessagesTrait;
|
||||
|
||||
protected static $name = 'Zprávy uživatelům';
|
||||
protected static $type = 'RECLAMATION_MESSAGE';
|
||||
protected static $priority = 1;
|
||||
|
||||
public function getMessages($languageID = null): array
|
||||
{
|
||||
if (!$languageID && $this->reclamation) {
|
||||
$languageID = $this->reclamation->getIdLanguage();
|
||||
}
|
||||
|
||||
return $this->fetchMessages($languageID);
|
||||
}
|
||||
|
||||
public function getMessagesByStatus($status, $languageID = null): array
|
||||
{
|
||||
return [];
|
||||
}
|
||||
|
||||
public function getObjectId(): ?int
|
||||
{
|
||||
return $this->reclamation->getId();
|
||||
}
|
||||
}
|
||||
384
bundles/KupShop/ReclamationsBundle/Entity/ReclamationEntity.php
Normal file
384
bundles/KupShop/ReclamationsBundle/Entity/ReclamationEntity.php
Normal file
@@ -0,0 +1,384 @@
|
||||
<?php
|
||||
|
||||
namespace KupShop\ReclamationsBundle\Entity;
|
||||
|
||||
use KupShop\KupShopBundle\Template\ArrayAccess;
|
||||
|
||||
class ReclamationEntity extends ArrayAccess
|
||||
{
|
||||
protected $id;
|
||||
protected $id_language;
|
||||
protected $id_currency;
|
||||
protected $code;
|
||||
protected $date_created;
|
||||
protected $date_accepted;
|
||||
protected $date_handle;
|
||||
protected $status;
|
||||
protected $status_name;
|
||||
protected $handle_type;
|
||||
protected $handle_type_name;
|
||||
protected $preferred_handle_type;
|
||||
protected $preferred_handle_type_name;
|
||||
protected $bank_account;
|
||||
protected $history;
|
||||
protected $package_id;
|
||||
protected $id_balikonos;
|
||||
|
||||
protected $email;
|
||||
protected $address = [];
|
||||
protected $descr;
|
||||
protected $user_note;
|
||||
|
||||
protected $id_order;
|
||||
protected $order_no;
|
||||
|
||||
protected $data;
|
||||
|
||||
protected $id_item;
|
||||
protected $item;
|
||||
|
||||
protected int $pieces;
|
||||
|
||||
public function getId()
|
||||
{
|
||||
return $this->id;
|
||||
}
|
||||
|
||||
public function setId($id)
|
||||
{
|
||||
$this->id = $id;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getIdLanguage()
|
||||
{
|
||||
return $this->id_language;
|
||||
}
|
||||
|
||||
public function setIdLanguage($id_language)
|
||||
{
|
||||
$this->id_language = $id_language;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getIdCurrency()
|
||||
{
|
||||
return $this->id_currency;
|
||||
}
|
||||
|
||||
public function setIdCurrency($id_currency)
|
||||
{
|
||||
$this->id_currency = $id_currency;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getCode()
|
||||
{
|
||||
return $this->code;
|
||||
}
|
||||
|
||||
public function setCode($code)
|
||||
{
|
||||
$this->code = $code;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getDateCreated()
|
||||
{
|
||||
return $this->date_created;
|
||||
}
|
||||
|
||||
public function setDateCreated($date_created)
|
||||
{
|
||||
$this->date_created = $date_created;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getDateAccepted()
|
||||
{
|
||||
return $this->date_accepted;
|
||||
}
|
||||
|
||||
public function setDateAccepted($date_accepted)
|
||||
{
|
||||
$this->date_accepted = $date_accepted;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getDateHandle()
|
||||
{
|
||||
return $this->date_handle;
|
||||
}
|
||||
|
||||
public function setDateHandle($date_handle)
|
||||
{
|
||||
$this->date_handle = $date_handle;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getStatus()
|
||||
{
|
||||
return $this->status;
|
||||
}
|
||||
|
||||
public function setStatus($status)
|
||||
{
|
||||
$this->status = $status;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getStatusName()
|
||||
{
|
||||
return $this->status_name;
|
||||
}
|
||||
|
||||
public function setStatusName($status_name)
|
||||
{
|
||||
$this->status_name = $status_name;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getHandleType()
|
||||
{
|
||||
return $this->handle_type;
|
||||
}
|
||||
|
||||
public function setHandleType($handle_type)
|
||||
{
|
||||
$this->handle_type = $handle_type;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getPrefHandleType()
|
||||
{
|
||||
return $this->preferred_handle_type;
|
||||
}
|
||||
|
||||
public function setPrefHandleType($preferred_handle_type)
|
||||
{
|
||||
$this->preferred_handle_type = $preferred_handle_type;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getHandleTypeName()
|
||||
{
|
||||
return $this->handle_type_name;
|
||||
}
|
||||
|
||||
public function setHandleTypeName($handle_type_name)
|
||||
{
|
||||
$this->handle_type_name = $handle_type_name;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getPrefHandleTypeName()
|
||||
{
|
||||
return $this->preferred_handle_type_name;
|
||||
}
|
||||
|
||||
public function setPrefHandleTypeName($preferred_handle_type_name)
|
||||
{
|
||||
$this->preferred_handle_type_name = $preferred_handle_type_name;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getBankAccount()
|
||||
{
|
||||
return $this->bank_account;
|
||||
}
|
||||
|
||||
public function setBankAccount($bank_account)
|
||||
{
|
||||
$this->bank_account = $bank_account;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getDescr()
|
||||
{
|
||||
return $this->descr;
|
||||
}
|
||||
|
||||
public function setDescr($descr)
|
||||
{
|
||||
$this->descr = $descr;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getUserNote()
|
||||
{
|
||||
return $this->user_note;
|
||||
}
|
||||
|
||||
public function setUserNote($user_note)
|
||||
{
|
||||
$this->user_note = $user_note;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getHistory()
|
||||
{
|
||||
return $this->history;
|
||||
}
|
||||
|
||||
public function setHistory($history)
|
||||
{
|
||||
$this->history = $history;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getEmail()
|
||||
{
|
||||
return $this->email;
|
||||
}
|
||||
|
||||
public function setEmail($email)
|
||||
{
|
||||
$this->email = $email;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getDelivery(): array
|
||||
{
|
||||
return $this->address;
|
||||
}
|
||||
|
||||
public function getAddress(): array
|
||||
{
|
||||
return $this->address;
|
||||
}
|
||||
|
||||
public function setAddress(array $address)
|
||||
{
|
||||
$this->address = $address;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getIdItem()
|
||||
{
|
||||
return $this->id_item;
|
||||
}
|
||||
|
||||
public function setIdItem($id_item)
|
||||
{
|
||||
$this->id_item = $id_item;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getItem()
|
||||
{
|
||||
return $this->item;
|
||||
}
|
||||
|
||||
public function setItem($item)
|
||||
{
|
||||
$this->item = $item;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getPieces(): int
|
||||
{
|
||||
return $this->pieces;
|
||||
}
|
||||
|
||||
public function setPieces($pieces)
|
||||
{
|
||||
$this->pieces = $pieces;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getIdOrder()
|
||||
{
|
||||
return $this->id_order;
|
||||
}
|
||||
|
||||
public function setIdOrder($id_order)
|
||||
{
|
||||
$this->id_order = $id_order;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getOrderNumber()
|
||||
{
|
||||
return $this->order_no;
|
||||
}
|
||||
|
||||
public function setOrderNumber($order_no)
|
||||
{
|
||||
$this->order_no = $order_no;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getPackageId()
|
||||
{
|
||||
return $this->package_id;
|
||||
}
|
||||
|
||||
public function setPackageId($package_id)
|
||||
{
|
||||
$this->package_id = $package_id;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getIdBalikonos()
|
||||
{
|
||||
return $this->id_balikonos;
|
||||
}
|
||||
|
||||
public function setIdBalikonos($id_balikonos)
|
||||
{
|
||||
$this->id_balikonos = $id_balikonos;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getData()
|
||||
{
|
||||
return $this->data;
|
||||
}
|
||||
|
||||
public function setData($data)
|
||||
{
|
||||
$this->data = $data;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function isClosed(): bool
|
||||
{
|
||||
return (bool) ($this->status > 1);
|
||||
}
|
||||
|
||||
public function getIdReturnDelivery(): ?int
|
||||
{
|
||||
if ($data = $this->getData()) {
|
||||
return empty($data['id_return_delivery']) ? null : $data['id_return_delivery'];
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
<?php
|
||||
|
||||
namespace KupShop\ReclamationsBundle\Event;
|
||||
|
||||
use KupShop\ReclamationsBundle\Entity\ReclamationEntity;
|
||||
use Symfony\Contracts\EventDispatcher\Event;
|
||||
|
||||
class ReclamationsEvent extends Event
|
||||
{
|
||||
public const RECLAMATION_CREATED = 'kupshop.reclamations.created';
|
||||
public const STATUS_CHANGED = 'kupshop.reclamations.status_changed';
|
||||
|
||||
private $entity;
|
||||
private $status;
|
||||
|
||||
public function __construct(ReclamationEntity $entity, $status)
|
||||
{
|
||||
$this->entity = $entity;
|
||||
$this->status = $status;
|
||||
}
|
||||
|
||||
public function getEntity()
|
||||
{
|
||||
return $this->entity;
|
||||
}
|
||||
|
||||
public function setEntity($entity): void
|
||||
{
|
||||
$this->entity = $entity;
|
||||
}
|
||||
|
||||
public function getStatus()
|
||||
{
|
||||
return $this->status;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
namespace KupShop\ReclamationsBundle\Inspections\User;
|
||||
|
||||
use KupShop\SystemInspectionBundle\Inspections\Inspection;
|
||||
use KupShop\SystemInspectionBundle\Inspections\User\UserInspectionInterface;
|
||||
use KupShop\SystemInspectionBundle\InspectionWriters\MessageTypes\InspectionMessage;
|
||||
use KupShop\SystemInspectionBundle\InspectionWriters\MessageTypes\StuckOrdersMessage;
|
||||
|
||||
class ReclamationsNearDeadline extends Inspection implements UserInspectionInterface
|
||||
{
|
||||
/**
|
||||
* @return InspectionMessage[]|null
|
||||
*/
|
||||
public function runInspection(): ?array
|
||||
{
|
||||
$errors = [];
|
||||
$qb = sqlQueryBuilder()->addCalcRows()->addselect('code')->from('reclamations')
|
||||
->where('date_accepted < NOW() - INTERVAL 27 DAY')
|
||||
->andWhere('status = 1')
|
||||
->setMaxResults(5);
|
||||
|
||||
$oldOrders = sqlFetchAll($qb, 'code');
|
||||
|
||||
if ($oldOrders) {
|
||||
$count = sqlQuery('SELECT FOUND_ROWS()')->fetchColumn();
|
||||
$errors[] = new StuckOrdersMessage(translate('nearDeadline', 'Reclamations', false, true), array_keys($oldOrders), $count);
|
||||
}
|
||||
|
||||
return $errors;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
<?php
|
||||
|
||||
namespace KupShop\ReclamationsBundle\Page;
|
||||
|
||||
use KupShop\ContentBundle\Page\BasePage;
|
||||
use KupShop\ReclamationsBundle\View\CreateReclamationView;
|
||||
|
||||
class ReclamationLoginPage extends BasePage
|
||||
{
|
||||
protected static $name = 'Reklamace - přihlášení';
|
||||
protected static $type = 'RECLAMATIONS_LOGIN';
|
||||
|
||||
/** @var CreateReclamationView */
|
||||
protected $view;
|
||||
|
||||
public function getUrl(): string
|
||||
{
|
||||
return path('kupshop_reclamations_reclamations_createreclamationlogin');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
<?php
|
||||
|
||||
namespace KupShop\ReclamationsBundle\Page;
|
||||
|
||||
use KupShop\ContentBundle\Page\BasePage;
|
||||
use KupShop\ReclamationsBundle\View\CreateReclamationView;
|
||||
|
||||
class ReclamationProductsPage extends BasePage
|
||||
{
|
||||
protected static $name = 'Reklamace - produkty';
|
||||
protected static $type = 'RECLAMATION_PRODUCTS';
|
||||
|
||||
/** @var CreateReclamationView */
|
||||
protected $view;
|
||||
|
||||
public function getUrl(): string
|
||||
{
|
||||
return path('kupshop_reclamations_reclamations_createreclamation');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
<?php
|
||||
|
||||
namespace KupShop\ReclamationsBundle\Page;
|
||||
|
||||
use KupShop\ContentBundle\Page\BasePage;
|
||||
use KupShop\ReclamationsBundle\View\CreateReclamationView;
|
||||
|
||||
class ReclamationSummaryPage extends BasePage
|
||||
{
|
||||
protected static $name = 'Reklamace - doprava a detaily';
|
||||
protected static $type = 'RECLAMATION_SUMMARY';
|
||||
|
||||
/** @var CreateReclamationView */
|
||||
protected $view;
|
||||
|
||||
public function getUrl(): string
|
||||
{
|
||||
return path('kupshop_reclamations_reclamations_createreclamationsummary');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
<?php
|
||||
|
||||
namespace KupShop\ReclamationsBundle\Page;
|
||||
|
||||
use KupShop\ContentBundle\Page\BasePage;
|
||||
use KupShop\ReclamationsBundle\View\ReclamationsView;
|
||||
|
||||
class ReclamationsListPage extends BasePage
|
||||
{
|
||||
protected static $name = 'Reklamace';
|
||||
protected static $type = 'RECLAMATIONS_LIST';
|
||||
|
||||
/** @var ReclamationsView */
|
||||
protected $view;
|
||||
|
||||
public function getUrl(): string
|
||||
{
|
||||
return path('kupshop_reclamations_reclamations_reclamations');
|
||||
}
|
||||
}
|
||||
37
bundles/KupShop/ReclamationsBundle/Query/Reclamations.php
Normal file
37
bundles/KupShop/ReclamationsBundle/Query/Reclamations.php
Normal file
@@ -0,0 +1,37 @@
|
||||
<?php
|
||||
|
||||
namespace KupShop\ReclamationsBundle\Query;
|
||||
|
||||
use KupShop\ReclamationsBundle\Util\ReclamationsUtil;
|
||||
use Query\QueryBuilder;
|
||||
|
||||
class Reclamations
|
||||
{
|
||||
public static function joinOrders()
|
||||
{
|
||||
return function (QueryBuilder $qb) {
|
||||
$qb->leftJoin('r', 'order_items', 'oi', 'oi.id = r.id_item')
|
||||
->leftJoin('oi', 'orders', 'o', 'o.id = oi.id_order');
|
||||
};
|
||||
}
|
||||
|
||||
public static function getReturnablePiecesSpec()
|
||||
{
|
||||
return function (QueryBuilder $qb) {
|
||||
// pocet kusu v objednavce - pocet kusu v nevyrizenych reklamacich - pocet kusu ve vratkach
|
||||
$returnable_pieces = sqlQueryBuilder()
|
||||
->from('reclamations', 'r')
|
||||
->andWhere('r.id_item = oi.id AND r.status != '.ReclamationsUtil::STATUS_HANDLED);
|
||||
|
||||
if (findModule(\Modules::RETURNS)) {
|
||||
$in_returns = sqlQueryBuilder()->select('COALESCE(SUM(ri.pieces), 0)')
|
||||
->from('return_items', 'ri')->andWhere('oi.id = ri.id_item');
|
||||
$returnable_pieces->addSubselect($in_returns, 'pieces', 'oi.pieces - COALESCE(SUM(r.pieces), 0) - {}');
|
||||
} else {
|
||||
$returnable_pieces->addSelect('oi.pieces - COALESCE(SUM(r.pieces), 0)');
|
||||
}
|
||||
|
||||
$qb->addSubselect($returnable_pieces, 'returnable_pieces');
|
||||
};
|
||||
}
|
||||
}
|
||||
10
bundles/KupShop/ReclamationsBundle/ReclamationsBundle.php
Normal file
10
bundles/KupShop/ReclamationsBundle/ReclamationsBundle.php
Normal file
@@ -0,0 +1,10 @@
|
||||
<?php
|
||||
|
||||
namespace KupShop\ReclamationsBundle;
|
||||
|
||||
use Symfony\Component\HttpKernel\Bundle\Bundle;
|
||||
|
||||
class ReclamationsBundle extends Bundle
|
||||
{
|
||||
public const LOG_TAG_RECLAMATIONS = 'Reclamations';
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
ReclamationsBundle:
|
||||
resource: "@ReclamationsBundle/Controller"
|
||||
type: annotation
|
||||
@@ -0,0 +1,10 @@
|
||||
services:
|
||||
_defaults:
|
||||
autowire: true
|
||||
autoconfigure: true
|
||||
public: false
|
||||
|
||||
KupShop\ReclamationsBundle\:
|
||||
resource: ../../{Admin/Tabs,AdminRegister,Attachment,EventListener,Email,View,Util,Controller,Page,Inspections,Admin/Actions}
|
||||
exclude: ../../Email/ReclamationEmail.php
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
<?php
|
||||
|
||||
$txt_str['email'] = [
|
||||
'attachments_uploaded_by_customer' => 'Anhänge, die vom Kunden hochgeladen wurden',
|
||||
];
|
||||
@@ -0,0 +1,5 @@
|
||||
<?php
|
||||
|
||||
$txt_str['email'] = [
|
||||
'attachments_uploaded_by_customer' => 'Anhänge, die vom Kunden hochgeladen wurden',
|
||||
];
|
||||
@@ -0,0 +1,5 @@
|
||||
<?php
|
||||
|
||||
$txt_str['email'] = [
|
||||
'attachments_uploaded_by_customer' => 'Anhänge, die vom Kunden hochgeladen wurden',
|
||||
];
|
||||
@@ -0,0 +1,5 @@
|
||||
<?php
|
||||
|
||||
$txt_str['email'] = [
|
||||
'attachments_uploaded_by_customer' => 'Přílohy nahrané zákazníkem',
|
||||
];
|
||||
@@ -0,0 +1,5 @@
|
||||
<?php
|
||||
|
||||
$txt_str['email'] = [
|
||||
'attachments_uploaded_by_customer' => 'Anhänge, die vom Kunden hochgeladen wurden',
|
||||
];
|
||||
@@ -0,0 +1,5 @@
|
||||
<?php
|
||||
|
||||
$txt_str['email'] = [
|
||||
'attachments_uploaded_by_customer' => 'Attachments uploaded by customer',
|
||||
];
|
||||
@@ -0,0 +1,5 @@
|
||||
<?php
|
||||
|
||||
$txt_str['email'] = [
|
||||
'attachments_uploaded_by_customer' => 'Pièces jointes téléchargées par le client',
|
||||
];
|
||||
@@ -0,0 +1,5 @@
|
||||
<?php
|
||||
|
||||
$txt_str['email'] = [
|
||||
'attachments_uploaded_by_customer' => 'Privici koje je učitao kupac',
|
||||
];
|
||||
@@ -0,0 +1,5 @@
|
||||
<?php
|
||||
|
||||
$txt_str['email'] = [
|
||||
'attachments_uploaded_by_customer' => 'A vásárló által feltöltött csatolmányok',
|
||||
];
|
||||
@@ -0,0 +1,5 @@
|
||||
<?php
|
||||
|
||||
$txt_str['email'] = [
|
||||
'attachments_uploaded_by_customer' => 'Allegati caricati dal cliente',
|
||||
];
|
||||
@@ -0,0 +1,5 @@
|
||||
<?php
|
||||
|
||||
$txt_str['email'] = [
|
||||
'attachments_uploaded_by_customer' => 'Bijlagen geüpload door klant',
|
||||
];
|
||||
@@ -0,0 +1,5 @@
|
||||
<?php
|
||||
|
||||
$txt_str['email'] = [
|
||||
'attachments_uploaded_by_customer' => 'Załączniki przesłane przez klienta',
|
||||
];
|
||||
@@ -0,0 +1,5 @@
|
||||
<?php
|
||||
|
||||
$txt_str['email'] = [
|
||||
'attachments_uploaded_by_customer' => 'Файлы, загруженные клиентом',
|
||||
];
|
||||
@@ -0,0 +1,5 @@
|
||||
<?php
|
||||
|
||||
$txt_str['email'] = [
|
||||
'attachments_uploaded_by_customer' => 'Prílohy nahrané zákazníkom',
|
||||
];
|
||||
@@ -0,0 +1,5 @@
|
||||
<?php
|
||||
|
||||
$txt_str['email'] = [
|
||||
'attachments_uploaded_by_customer' => 'Priloge naložene s strani kupca',
|
||||
];
|
||||
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"areas": [
|
||||
[
|
||||
{
|
||||
"type": "text",
|
||||
"settings": {
|
||||
"html": "<p><strong>{t}Vyberte produkt, který potřebujete reklamovat{/t}</strong></p><p>{t}V rámci jednoho formuláře je možné reklamovat pouze jeden produkt.{/t}</p>"
|
||||
}
|
||||
}
|
||||
]
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
[
|
||||
{
|
||||
"type" : "heading",
|
||||
"settings" : {
|
||||
"level" : "4",
|
||||
"align" : "center",
|
||||
"text" : "Jak nám zboží zašlete zpět?"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type" : "grid",
|
||||
"settings" : {
|
||||
"columns" : [
|
||||
6,
|
||||
6
|
||||
],
|
||||
"padding_right_0" : 5,
|
||||
"padding_left_0" : 5,
|
||||
"padding_left_1" : 5,
|
||||
"padding_right_1" : 5
|
||||
},
|
||||
"children" : [
|
||||
{
|
||||
"type" : "grid_item",
|
||||
"settings" : {
|
||||
"size" : 6
|
||||
},
|
||||
"children" : [
|
||||
{
|
||||
"type" : "text",
|
||||
"settings" : {
|
||||
"html" : "<h5>Zásilkovnou</h5><p>Dáme vám kód, nemusíte nic tisknout. Vrácení Zásilkovnou od nás máte zdarma.</p>"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type" : "grid_item",
|
||||
"settings" : {
|
||||
"size" : 6
|
||||
},
|
||||
"children" : [
|
||||
{
|
||||
"type" : "text",
|
||||
"settings" : {
|
||||
"html" : "<h5>Vlastními silami</h5><p>Balíček pošlete libovolnou službou nebo doručte na adresu e-shopu.</p>"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type" : "text",
|
||||
"settings" : {
|
||||
"html" : "<p style=\"text-align:center;\">Původní zboží k nám doručte co nejdříve, do 5 dnů.</p>"
|
||||
}
|
||||
}
|
||||
]
|
||||
@@ -0,0 +1,32 @@
|
||||
[
|
||||
{
|
||||
"type":"text",
|
||||
"id":"c87096a1-a528-449f-8058-fbb6aa32ef81",
|
||||
"settings":{
|
||||
"html":"<p>{t escape=false}Vypadá to, že zboží zakoupené u nás Vás zklamalo v záruční lhůtě. Nevěšte hlavu, určitě to napravíme. Vyberte si produkt, který chcete reklamovat. Vyplňte formulář a napište nám, co je špatně. Zabalené zboží pošlete zdarma přes Zásilkovnu nebo na vlastní náklady jinou přepravní společností. Jakmile zjistíme, co se stalo, ozveme se Vám. Nejpozději však do 30 dnů.{/t}</p>"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type":"button",
|
||||
"id":"23cae9bd-2e55-469e-888c-05e006342542",
|
||||
"settings":{
|
||||
"align":"left",
|
||||
"size":"2",
|
||||
"appearance":"1",
|
||||
"link":{
|
||||
"url":"{path('kupshop_reclamations_reclamations_createreclamation')}",
|
||||
"type":"internal",
|
||||
"value":"{path('kupshop_reclamations_reclamations_createreclamation')}",
|
||||
"blank":false
|
||||
},
|
||||
"text":"{t}Nová reklamace{/t}"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type":"hr",
|
||||
"id":"f29428f8-ff08-45e7-ab58-320280ee5aa1",
|
||||
"settings":{
|
||||
"padding":10
|
||||
}
|
||||
}
|
||||
]
|
||||
@@ -0,0 +1,44 @@
|
||||
{
|
||||
"areas": [
|
||||
[
|
||||
{
|
||||
"type": "heading",
|
||||
"settings": {
|
||||
"level": "3",
|
||||
"align": "left",
|
||||
"text": "Provedeme vás reklamací zboží ve čtyřech snadných krocích"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "text",
|
||||
"settings": {
|
||||
"html": "<ol><li>Přihlaste se do svého účtu. Nejste registrovaní? Nevadí, objednávku načtete pomocí jejího čísla.</li><li>Vyberte produkt, který potřebujete reklamovat.</li><li>Doplňte detaily o problému a zvolte způsob, jakým bychom reklamaci vyřešili k vaší co největší spokojenosti.</li><li>Odešlete nám balíček – můžete využít dopravu od nás nebo libovolnou jinou cestu.</li></ol>"
|
||||
}
|
||||
}
|
||||
],
|
||||
[
|
||||
{
|
||||
"type": "text",
|
||||
"settings": {
|
||||
"html": "<p style=\"text-align:center;\">Je nám líto, že jste se dostali do situace, kdy potřebujete řešit reklamaci produktu. Budeme se snažit vám proces reklamace co nejvíce zpříjemnit a průběžně vás informovat.</p>"
|
||||
}
|
||||
}
|
||||
],
|
||||
[
|
||||
{
|
||||
"type": "text",
|
||||
"settings": {
|
||||
"html": "<h3>Jak můžu zboží reklamovat?</h3><p>Pro jednoduchou a rychlou reklamaci prosím vyplňte <strong>online reklamační formulář</strong> výše. Pokud jste nakupovali jako přihlášený zákazník, ve formuláři uvidíte všechno zboží, které je stále v záruce. Po vyplnění formuláře se vám zobrazí všechny potřebné informace k reklamaci zboží a jeho zaslání zpět.</p>"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "text",
|
||||
"settings": {
|
||||
"html": "<h3>Jak mohu zjistit stav mojí reklamace?</h3><p>Jakmile k nám zboží dorazí, obdržíte od nás <strong>potvrzovací e-mail o přijetí</strong>. Máme <strong>30 dní</strong> na to, abychom vše vyřešili a informovali vás o výsledku reklamace. Vždy se však snažíme, aby to bylo co nejdříve.</p>"
|
||||
}
|
||||
}
|
||||
]
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,79 @@
|
||||
{foreach $body.itemsInOrder as $order}
|
||||
<div class="returns-box returns-box-returns" data-returns>
|
||||
<div class="title-default">
|
||||
{$first = $order|reset}
|
||||
{t order_no=$first.order_no date=$first.delivery_date|format_date_locale_pretty:'d. L. Y'}Objednávka č. {order_no} ze dne {date}{/t}
|
||||
</div>
|
||||
{foreach $order as $idItem => $item}
|
||||
{change_currency currency=$item.currency}
|
||||
{$img_size = "product_gallery"}
|
||||
{if isset($cfg.Photo.types["product_cart"])}{$img_size = "product_cart"}{/if}
|
||||
{$photo_dimensions = $cfg.Photo.types["product_cart"].size}
|
||||
<form name="items-form" method="post" data-reclamation-products>
|
||||
<div class="item">
|
||||
<input type="hidden" name="nextStep" value="1" />
|
||||
<div class="image">
|
||||
<a href="{url s=product IDproduct=$item.product.id TITLE=$item.product.title}"
|
||||
title="{t}Zobrazit produkt{/t}">
|
||||
{block 'image'}
|
||||
<img src="{get_photo photo=$item.product.image size=$img_size}" alt="{$item.product.title}"
|
||||
class="img-responsive" width="{$photo_dimensions[0]}" height="{$photo_dimensions[1]}">
|
||||
{/block}
|
||||
</a>
|
||||
</div>
|
||||
<div class="title-wrapper">
|
||||
<div class="title">
|
||||
<a href="{url s=product IDproduct=$item.product.id TITLE=$item.product.title}"
|
||||
title="{t}Zobrazit produkt{/t}">
|
||||
{$item.product.title}
|
||||
</a>
|
||||
{if $item.id_variation}
|
||||
<span class="variation-title">{$item.product.variationTitle}</span>
|
||||
{/if}
|
||||
</div>
|
||||
<div class="price">{$item.piece_price_with_vat|format_price}</div>
|
||||
</div>
|
||||
|
||||
{if $item.expired}
|
||||
<span>{t}Produkt již není v záruční době{/t}</span>
|
||||
{elseif $item.returnable_pieces <= 0}
|
||||
<span>{t}Produkt již nemůžete reklamovat{/t}</span>
|
||||
{else}
|
||||
<div class="pieces" data-buy_count="wrapper">
|
||||
{$step = $item.product.unit.step|default:1}
|
||||
{ifmodule PRODUCTS__STEP}
|
||||
{$data = $item.product->getData()}
|
||||
{$step = $data.step|default:$step}
|
||||
{/ifmodule}
|
||||
|
||||
<input type="number" name="item_pieces" value="{$step}" class="form-control" step="{$step}" min="{$step}"
|
||||
max="{$item.returnable_pieces}" data-buy_count="input"
|
||||
{if $module.PRODUCTS__UNITS_FLOAT}
|
||||
data-precision="{$item.product.unit.pieces_precision|default:0}"
|
||||
{/if}
|
||||
>
|
||||
<div class="buy_count">
|
||||
<button type="button" class="fc plus plus_unit" title="{t mnozstvi=$step}Přidat {mnozstvi} ks{/t}"
|
||||
{if $step >= $item.returnable_pieces}disabled{/if}></button>
|
||||
<button type="button" class="fc minus minus_unit" title="{t mnozstvi=$step}Odebrat {mnozstvi} ks{/t}"
|
||||
disabled></button>
|
||||
{if $module.PRODUCTS__UNITS_FLOAT}
|
||||
<p class="ordering-product-units">{$item.product.unit.short_name|lower}</p>
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
<button type="submit" name="item_id" value="{$item.id}" class="btn btn-primary btn-return">
|
||||
{t}Reklamovat{/t}
|
||||
</button>
|
||||
{/if}
|
||||
</div>
|
||||
</form>
|
||||
{/change_currency}
|
||||
{/foreach}
|
||||
</div>
|
||||
{/foreach}
|
||||
{if $body.pager.count > 1}
|
||||
<div {ifmodule COMPONENTS}class="c-pager"{/ifmodule}>
|
||||
{include "components/pager.tpl" pager=$body.pager}
|
||||
</div>
|
||||
{/if}
|
||||
@@ -0,0 +1,41 @@
|
||||
<div class="price-box">
|
||||
<p class="h2">{t}Shrnutí{/t}</p>
|
||||
{block "return-products"}
|
||||
<p class="subtitle">{t}Reklamujete{/t}</p>
|
||||
<div class="price-box-row price-box-product">
|
||||
<div class="image">
|
||||
{$img_size = "product_gallery"}
|
||||
{if isset($cfg.Photo.types["product_cart"])}{$img_size = "product_cart"}{/if}
|
||||
<a href="{url s=product IDproduct=$body.item.product.id TITLE=$body.item.product.title}" title="{t}Zobrazit produkt{/t}">
|
||||
<img src="{get_photo photo=$body.item.product.image size=$img_size}" alt="{$body.item.product.title}"
|
||||
class="img-responsive" width="{$photo_dimensions[0]}" height="{$photo_dimensions[1]}">
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="title">
|
||||
<a href="{url s=product IDproduct=$body.item.product.id TITLE=$body.item.product.title}" title="{t}Zobrazit produkt{/t}">
|
||||
{$body.item.product.title}
|
||||
</a>
|
||||
|
||||
{if $body.item.id_variation}
|
||||
<span class="variation-title">{$body.item.product.variationTitle}</span>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
<div class="price">
|
||||
{$body.item.pieces_to_return} {t}ks{/t}
|
||||
<strong>{$body.item.piece_price_with_vat|format_price}</strong>
|
||||
</div>
|
||||
</div>
|
||||
{/block}
|
||||
|
||||
<button type="submit" name="nextStep" value="1" class="btn btn-ctr btn-block">
|
||||
{t}Potvrdit a dokončit{/t}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<p class="text-center">
|
||||
<a href="{path('kupshop_reclamations_reclamations_createreclamation')}">
|
||||
{t}Zpět na výběr produktů{/t}
|
||||
</a>
|
||||
</p>
|
||||
@@ -0,0 +1,392 @@
|
||||
{extends '[common]pdf/invoicePDF.tpl'}
|
||||
|
||||
<style>
|
||||
{block "style-pdf"}
|
||||
|
||||
/* @formatter:off */
|
||||
{function page2}{
|
||||
size: A4 portrait;
|
||||
|
||||
@frame frame_header {
|
||||
-pdf-frame-content: header{$iteration};
|
||||
top: 5mm;
|
||||
left: 10mm;
|
||||
width: 190mm;
|
||||
height: 10mm;
|
||||
/*-pdf-frame-border: 1;*/
|
||||
}
|
||||
|
||||
@frame frame_left {
|
||||
-pdf-frame-content: left_column{$iteration};
|
||||
left: 10mm;
|
||||
top: 15mm;
|
||||
width: 90mm;
|
||||
height: 100mm;
|
||||
/*-pdf-frame-border: 1;*/
|
||||
}
|
||||
|
||||
@frame frame_right {
|
||||
-pdf-frame-content: right_column{$iteration};
|
||||
left: 110.22mm;
|
||||
top: 15mm;
|
||||
width: 90mm;
|
||||
height: 80mm;
|
||||
/*-pdf-frame-border: 1;*/
|
||||
}
|
||||
|
||||
@frame frame_down {
|
||||
left: 10mm;
|
||||
top: 110mm;
|
||||
width: 190mm;
|
||||
height: 190mm;
|
||||
}
|
||||
|
||||
@frame frame_footer {
|
||||
-pdf-frame-content: footer;
|
||||
top: 289mm;
|
||||
left: 10mm;
|
||||
width: 190mm;
|
||||
height: 8mm;
|
||||
}
|
||||
}
|
||||
{/function}
|
||||
|
||||
{if $iteration}
|
||||
@page first{$iteration} {page2 iteration=$iteration}
|
||||
{else}
|
||||
@page {page2 iteration=$iteration}
|
||||
{/if}
|
||||
|
||||
/* druhá a další stránka */
|
||||
@page regular_template {
|
||||
@frame frame_header {
|
||||
-pdf-frame-content: header;
|
||||
top: 5mm;
|
||||
left: 10mm;
|
||||
width: 190mm;
|
||||
height: 10mm;
|
||||
}
|
||||
|
||||
@frame frame_footer {
|
||||
-pdf-frame-content:footer;
|
||||
top: 289mm;
|
||||
left: 10mm;
|
||||
width: 190mm;
|
||||
height: 8mm;
|
||||
}
|
||||
|
||||
@frame frame_down {
|
||||
left: 10mm;
|
||||
top: 21mm;
|
||||
width: 190mm;
|
||||
height: 263mm;
|
||||
}
|
||||
}
|
||||
/* @formatter:on */
|
||||
{/block}
|
||||
|
||||
{block "style-css"}
|
||||
|
||||
@font-face {
|
||||
font-family: ArialFont;
|
||||
src: url(http://html2pdf.wpj.cz/fonts/arial.ttf);
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: ArialFont;
|
||||
src: url(http://html2pdf.wpj.cz/fonts/arialbd.ttf);
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
body {
|
||||
color: #000000;
|
||||
font-family: ArialFont, sans-serif;
|
||||
font-size: 8pt;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
/* cislo faktury - v ramecku */
|
||||
h1 {
|
||||
font-size: 13pt;
|
||||
font-weight: normal;
|
||||
padding: 3mm 2.5mm 1.8mm;
|
||||
margin: 0 0 5mm;
|
||||
border: 1pt solid #000000;
|
||||
border-top: 0;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
/* bank ucet, odberatel, dodaci udaje a zpusob odberu */
|
||||
h2 {
|
||||
border-bottom: 1pt solid #bbb;
|
||||
font-size: 8pt;
|
||||
font-weight: bold;
|
||||
margin: 0 0 2mm;
|
||||
padding: 2mm 0 1mm;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
/* jmeno a firma (dodaci i fakturacni) */
|
||||
h3 {
|
||||
font-weight: bold;
|
||||
font-size: 9pt;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
line-height: 1.2;
|
||||
}
|
||||
|
||||
p {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
/* hlavicka, adresa prodejce */
|
||||
.header {
|
||||
border-bottom: 0.7mm solid black;
|
||||
font-weight: bold;
|
||||
height: 10mm;
|
||||
}
|
||||
|
||||
.header td {
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
{* kdyz je sidlo firmy na 3 radky, zmensi se to *}
|
||||
.header div {
|
||||
-pdf-keep-in-frame-mode: shrink;
|
||||
}
|
||||
|
||||
/* obchod používá wpjshop */
|
||||
.print-footer {
|
||||
color: #999;
|
||||
}
|
||||
|
||||
/* bankovni udaje, data splatnosti */
|
||||
.bank {
|
||||
margin-bottom: 2mm;
|
||||
}
|
||||
|
||||
.bank td {
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
/* 2 tabulky odberatel a dodaci udaje */
|
||||
.address td {
|
||||
vertical-align: top;
|
||||
padding: 0.7mm 0;
|
||||
}
|
||||
|
||||
/* nesmi se oriznout! */
|
||||
.address {
|
||||
-pdf-keep-in-frame-mode: shrink;
|
||||
}
|
||||
|
||||
.product-list {
|
||||
margin-bottom: 10mm;
|
||||
}
|
||||
|
||||
.product-list td {
|
||||
font-size: 8pt;
|
||||
line-height: 1.3;
|
||||
padding: 1mm 0.5mm 0.2mm;
|
||||
}
|
||||
|
||||
.product-list th {
|
||||
border: 1pt solid #fff;
|
||||
background: #ddd;
|
||||
font-size: 7pt;
|
||||
font-weight: bold;
|
||||
line-height: 1;
|
||||
padding: 0.5mm 1mm;
|
||||
height: 5mm;
|
||||
}
|
||||
|
||||
/* posledni radek productlistu, doprava */
|
||||
.last td {
|
||||
border-top: 1pt solid #333;
|
||||
border-bottom: 1pt solid #999;
|
||||
}
|
||||
|
||||
/* boxík s cenou */
|
||||
.pricebox th {
|
||||
border: 1pt solid #fff;
|
||||
background: #ddd;
|
||||
font-size: 8pt;
|
||||
font-weight: bold;
|
||||
line-height: 1;
|
||||
padding: 0.5mm 1mm;
|
||||
height: 6mm;
|
||||
}
|
||||
|
||||
.pricebox td {
|
||||
font-size: 8pt;
|
||||
line-height: 1;
|
||||
padding: 0 0.5mm;
|
||||
height: 6mm;
|
||||
}
|
||||
|
||||
/* cena celkem */
|
||||
.pricebox-final td {
|
||||
border: 2pt solid #222;
|
||||
height: 8mm;
|
||||
font-weight: bold;
|
||||
font-size: 10pt;
|
||||
line-height: 1;
|
||||
padding: 0.2mm 0.6mm 0;
|
||||
}
|
||||
|
||||
.pricebox-final td:first-child {
|
||||
border-right: 0;
|
||||
}
|
||||
|
||||
.pricebox-final td:last-child {
|
||||
border-left: 0;
|
||||
}
|
||||
|
||||
.logo td {
|
||||
vertical-align: middle;
|
||||
padding: 2mm 1mm;
|
||||
}
|
||||
|
||||
.print:last-of-type {
|
||||
page-break-after: auto;
|
||||
}
|
||||
|
||||
.large {
|
||||
font-size: 10pt;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.storno {
|
||||
font-size: 50pt;
|
||||
color: red;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
{/block}
|
||||
</style>
|
||||
|
||||
{block "header-table"}
|
||||
<td align="right" valign="bottom" width="136"><pdf:barcode value="{$reclamation.code}" type="code128" humanreadable="0" barheight="27" barWidth="1" /></td>
|
||||
{/block}
|
||||
|
||||
{block "header-title"}
|
||||
{t}Reklamační protokol{/t}: {$reclamation.code}
|
||||
{/block}
|
||||
|
||||
{block "invoice-title"}
|
||||
<h1 class="bordered">{t}Reklamační protokol{/t} {$reclamation.code}</h1>
|
||||
{if $order}
|
||||
<p>{t}z objednávky č.{/t} {$order.order_no}</p><br>
|
||||
{/if}
|
||||
{/block}
|
||||
|
||||
{block "invoice-dates"}
|
||||
<table width="100%" class="dates">
|
||||
<tr>
|
||||
<td width="60%">
|
||||
{get_datetime assign="now"}
|
||||
<strong>{t}Přijetí{/t}:</strong>
|
||||
</td>
|
||||
<td align="right" width="40%" style="padding-right: 1mm;">{$reclamation.date_created|format_date:'d.m.Y'}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<strong>{t}Vyřízení{/t}:</strong>
|
||||
</td>
|
||||
{$date_handle = $reclamation.date_handle|default:$now}
|
||||
<td align="right" style="padding-right: 1mm;"> {$date_handle|format_date:'d.m.Y'}</td>
|
||||
</tr>
|
||||
</table>
|
||||
{/block}
|
||||
|
||||
{block "left-table"}
|
||||
<tr>
|
||||
<td colspan="2">
|
||||
<h2>{t}Dodavatel{/t}:</h2>
|
||||
{$dbcfg.shop_firm_name}<br>
|
||||
{$dbcfg.shop_address|nl2br nofilter}<br>
|
||||
{if $dbcfg.shop_ico}{t}IČO{/t}: {$dbcfg.shop_ico} {/if}<br>
|
||||
{if $dbcfg.shop_dic}{t}DIČ{/t}: {$dbcfg.shop_dic}{/if}
|
||||
</td>
|
||||
</tr>
|
||||
{/block}
|
||||
|
||||
{block "customer-address"}
|
||||
<table class="address">
|
||||
<tr>
|
||||
<td colspan="2">
|
||||
<h2>{t}Odběratel{/t}:</h2>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<h3>{$reclamation.address.name} {$reclamation.address.surname}</h3>
|
||||
</td>
|
||||
<td>
|
||||
{$reclamation.address.street} <br/>
|
||||
{$reclamation.address.zip} {$reclamation.address.city}
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<h3><strong>{t}Telefon{/t}:</strong> {$reclamation.address.phone}</h3>
|
||||
<p>
|
||||
<strong>{t}Email{/t}:</strong> {$reclamation.email}
|
||||
</p>
|
||||
</td>
|
||||
</tr>
|
||||
{block "delivery-address"}
|
||||
<tr>
|
||||
<td colspan="2">
|
||||
<h2>{t}Dodací údaje{/t}</h2>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<h3>{$reclamation.address.name} {$reclamation.address.surname}</h3>
|
||||
</td>
|
||||
<td>
|
||||
{$reclamation.address.street} <br/>
|
||||
{$reclamation.address.zip} {$reclamation.address.city}
|
||||
</td>
|
||||
</tr>
|
||||
{/block}
|
||||
</table>
|
||||
{/block}
|
||||
|
||||
{block "delivery"}{/block}
|
||||
|
||||
|
||||
{block "items"}
|
||||
<div class="product-list">
|
||||
<h2>{t}Informace o reklamaci{/t}</h2>
|
||||
<table>
|
||||
<tr>
|
||||
<td width="25%" style="vertical-align: top;"><strong>{t}Název zboží{/t}</strong></td>
|
||||
<td width="75%">{$reclamation.item.descr}<br>
|
||||
{t}Kód:{/t} {$reclamation.item.code}{if $reclamation.item.ean}, {t}EAN:{/t} {$reclamation.item.ean}{/if}
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="25%"><strong>{t}Důvod reklamace{/t}</strong></td>
|
||||
<td width="75%">{$reclamation.user_note}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="25%"><strong>{t}Požadovaný způsob vyřízení{/t}</strong></td>
|
||||
<td width="75%">{$reclamation.preferred_handle_type_name}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="25%"><strong>{t}Způsob vyřízení{/t}</strong></td>
|
||||
<td width="75%">{$reclamation.handle_type_name}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="25%"><strong>{t}Posudek{/t}</strong></td>
|
||||
<td width="75%">{$reclamation.descr}</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
{/block}
|
||||
|
||||
{block "invoice-bottom"}{/block}
|
||||
@@ -0,0 +1,91 @@
|
||||
{extends "index.tpl"}
|
||||
|
||||
{block content}
|
||||
<div class="page-returns page-reclamations page-reclamations-detail">
|
||||
{if $smarty.get.success}
|
||||
<h1>{t}Žádost o reklamaci jsme přijali{/t}</h1>
|
||||
<p>{t code=$body.reclamation.code}Vaší reklamaci jsme přidělili číslo {code}.{/t}</p>
|
||||
{$body.text nofilter}
|
||||
<a href="{path('kupshop_reclamations_reclamations_reclamation', ['id' => $body.reclamation.id])}"
|
||||
class="btn btn-primary">{t}Detail reklamace{/t}</a> <a target="_blank" href="{path('kupshop_reclamations_reclamations_reclamationattachment', ['id' => $body.reclamation.id])}" class="btn btn-primary">{t}Zobrazit v PDF{/t}</a>
|
||||
{else}
|
||||
<h1>{t}Reklamace{/t} {$body.reclamation.code}</h1>
|
||||
<p style="font-size: 1.2em;"><strong>{t}Datum vytvoření{/t}:</strong> {$body.reclamation.date_created|date_format:"%d.%m.%Y %H:%M"}
|
||||
<br>
|
||||
<strong>{t}Produkt{/t}:</strong>
|
||||
<a href="{path('kupshop_content_redirect_redirect', ['type' => 'product', 'id' => $body.reclamation.item.id_product])}">{$body.reclamation.item.descr}</a>
|
||||
{if $body.reclamation.pieces > 1}<br><strong>{t}Kusů{/t}:</strong> {$body.reclamation.pieces}{/if}
|
||||
<br>
|
||||
<strong>{t}Stav reklamace{/t}:</strong> {$body.reclamation.status_name}</p>
|
||||
<p style="font-size: 1.2em;">
|
||||
<a target="_blank" href="{path('kupshop_reclamations_reclamations_reclamationattachment', ['id' => $body.reclamation.id])}">{t}Zobrazit v PDF{/t}</a>
|
||||
</p>
|
||||
<hr>
|
||||
<h4>{t}Instrukce{/t}:</h4>
|
||||
<div class="instructions">
|
||||
{$body.text nofilter}
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-xs-12 col-lg-4">
|
||||
<h5>{t}Doručovací údaje{/t}</h5>
|
||||
<ul class="summary-list">
|
||||
<li><strong>{$body.reclamation.address.name} {$body.reclamation.address.surname}</strong></li>
|
||||
<li>{$body.reclamation.address.street} {$body.reclamation.address.number}</li>
|
||||
<li>{$body.reclamation.address.zip} {$body.reclamation.address.city}</li>
|
||||
<li>{$body.reclamation.address.phone}</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="col-xs-12 col-lg-3">
|
||||
<h5>{t}Číslo účtu pro vrácení peněz{/t}</h5>
|
||||
<ul class="summary-list">
|
||||
<li>{$body.reclamation.bank_account}</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<hr class="m-b-2">
|
||||
<h5>{t}Historie reklamace{/t}</h5>
|
||||
<table class="table table-cart">
|
||||
<tr>
|
||||
<th>{t}Datum{/t}</th>
|
||||
<th>{t}Stav{/t}</th>
|
||||
<th>{t}Poznámka{/t}</th>
|
||||
</tr>
|
||||
{foreach $body.reclamation.history as $history}
|
||||
{if !$history.notified}{continue}{/if}
|
||||
<tr>
|
||||
<td>{$history.date|date_format:"%d.%m.%Y %H:%M:%S"}</td>
|
||||
<td>{$history.status_name}</td>
|
||||
<td>{$history.comment nofilter}</td>
|
||||
</tr>
|
||||
{/foreach}
|
||||
</table>
|
||||
{$customData = $body.reclamation->getData()}
|
||||
{if !empty($customData['userContent'])}
|
||||
{$userContent = $customData['userContent']}
|
||||
<h4>{t}Přílohy{/t}</h4>
|
||||
<table class="table">
|
||||
{foreach $userContent as $file}
|
||||
<tr>
|
||||
<td style="text-align: center; width: 120px;">
|
||||
{if $file.filename|strstr:".jpg" or $file.filename|strstr:".jpeg" or $file.filename|strstr:".png" or $file.filename|strstr:".gif"}
|
||||
<img src="{$file.src}" class="img-responsive" alt="">
|
||||
{/if}
|
||||
</td>
|
||||
<td>
|
||||
<a href="{$file.src}" target="_blank">
|
||||
{$file.originalFilename}
|
||||
</a>
|
||||
</td>
|
||||
<td class="text-right">
|
||||
<a href="{$file.src}" download>{t}Stáhnout{/t}</a>
|
||||
</td>
|
||||
</tr>
|
||||
{/foreach}
|
||||
</table>
|
||||
{/if}
|
||||
|
||||
<a href="{path('kupshop_reclamations_reclamations_reclamations')}" class="btn btn-prevstep">{t}Všechny reklamace{/t}</a>
|
||||
{/if}
|
||||
</div>
|
||||
{/block}
|
||||
@@ -0,0 +1,52 @@
|
||||
{extends "reclamations/reclamations-new.tpl"}
|
||||
|
||||
{block "content"}
|
||||
{insert_page type="RECLAMATIONS_LOGIN" use_default=1 assign="page"}
|
||||
{if $page.blocks[1].content}
|
||||
{$page.blocks[1].content nofilter}
|
||||
{/if}
|
||||
<div class="returns-login-row row">
|
||||
<div class="col-xxs-12 col-xs-12 col-lg-7">
|
||||
<div class="bg-alt">
|
||||
{$page.blocks[0].content nofilter}
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-xxs-12 col-xs-12 col-lg-5 returns-login {if $ctrl.logged}logged-in{else}logged-out{/if}">
|
||||
{if $ctrl.logged}
|
||||
<span class="fc icons_user"></span>
|
||||
<p><strong>{t}Jste přihlášeni jako{/t}</strong>{$ctrl.user.name} {$ctrl.user.surname}</p>
|
||||
<a href="{path('kupshop_reclamations_reclamations_createreclamation')}"
|
||||
class="btn btn-primary">{t}Pokračovat na výběr produktů{/t}</a>
|
||||
{else}
|
||||
<span class="fc icons_user"></span>
|
||||
<p class="title-default">{t}Máte u nás účet? Přihlaste se.{/t}</p>
|
||||
<a href="{url s=login}" class="btn btn-primary cart-signin">{t}Přihlásit se{/t}</a>
|
||||
<div class="separator">
|
||||
<span>{t}nebo{/t}</span>
|
||||
</div>
|
||||
<p class="title-default">{t}Nakupovali jste bez registrace?{/t}</p>
|
||||
<form action="{path('kupshop_reclamations_reclamations_createreclamationlogin')}" method="post">
|
||||
<input type="email" name="email" class="form-control" placeholder="{t}E-mailová adresa{/t}">
|
||||
<input type="text" name="order_no" class="form-control" placeholder="{t}Číslo objednávky{/t}">
|
||||
<button type="submit" name="submit" value="1" class="btn btn-primary">{t}Načíst objednávku{/t}</button>
|
||||
</form>
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
<div class="reclamation-help">
|
||||
{* @formatter:off *}
|
||||
<p>{t escape=false email=$dbcfg.shop_email phone=$dbcfg.shop_phone}Pokud potřebujete s něčím pomoci, volejte
|
||||
<a href="tel:{phone}">{phone}</a> nebo nám napište e-mail na <a href="mailto:{email}">{email}</a>.{/t}</p>
|
||||
{* @formatter:on *}
|
||||
|
||||
<a href="{url s=index}" class="btn btn-secondary">{t}Zpět do e-shopu{/t}</a>
|
||||
</div>
|
||||
<div class="returns-faq">
|
||||
{if $page.blocks[2].content}
|
||||
{$page.blocks[2].content nofilter}
|
||||
{/if}
|
||||
</div>
|
||||
{/block}
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
{extends "reclamations/reclamations-new.tpl"}
|
||||
|
||||
{block content}
|
||||
<div class="bg-alt">
|
||||
{insert_page type="RECLAMATION_PRODUCTS" use_default=1}
|
||||
</div>
|
||||
|
||||
<div class="reclamation-filter">
|
||||
<form method="post">
|
||||
<div class="row">
|
||||
<div class="col-lg-6 col-xxs-12">
|
||||
<p class="title-default">{t}Vyhledat produkt{/t}</p>
|
||||
<div class="reclamation-filter-form-group">
|
||||
<span class="fc icons_search"></span>
|
||||
<input type="text" name="filter[product]" value="{$body.filter.product}" maxlength="150" class="form-control"
|
||||
placeholder="{t}Název produktu{/t}" autocomplete="off">
|
||||
<button type="submit" name="submit" value="1" class="btn btn-primary">{t}Vyhledat{/t}</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-lg-6 col-xxs-12">
|
||||
<p class="title-default">{t}Vyhledat objednávku{/t}</p>
|
||||
<div class="reclamation-filter-form-group">
|
||||
<span class="fc icons_search"></span>
|
||||
<input type="text" name="filter[order]" value="{$body.filter.order}" maxlength="50" class="form-control"
|
||||
placeholder="{t}Číslo objednávky{/t}" autocomplete="off">
|
||||
<button type="submit" name="submit" value="1" class="btn btn-primary">{t}Vyhledat{/t}</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
{if $body.items}
|
||||
<div class="reclamation-products">
|
||||
{include "reclamations/block.products.reclamations.tpl"}
|
||||
</div>
|
||||
{else}
|
||||
<div class="no-returns no-reclamations">
|
||||
{* @formatter:off *}
|
||||
<p>{t}Aktuálně nemáte zakoupený žádný produkt, který by bylo možné reklamovat.{/t}</p>
|
||||
<p>{t escape=false email=$dbcfg.shop_email}Pokud se domníváte, že se jedná o omyl, neváhejte nás kontaktovat
|
||||
na emailu <strong><a href="mailto:{email}">{email}</a></strong>.{/t}</p>
|
||||
{* @formatter:on *}
|
||||
</div>
|
||||
{/if}
|
||||
{/block}
|
||||
@@ -0,0 +1,145 @@
|
||||
{extends "reclamations/reclamations-new.tpl"}
|
||||
|
||||
{block content}
|
||||
<div class="descr">
|
||||
{insert_page type="RECLAMATION_SUMMARY" use_default=1}
|
||||
</div>
|
||||
<form name="summary-form" class="row flex-row" method="post" data-summary-form>
|
||||
{if $body.order}
|
||||
{$readonly = false}
|
||||
{$deliveryType = $body.order->getDeliveryType()}
|
||||
<div class="col-md-7 col-xxs-12">
|
||||
<fieldset>
|
||||
<div class="box-returns-summary">
|
||||
|
||||
<p class="title-default">{t}Pokud vám budeme něco posílat...{/t}</p>
|
||||
<p>{t escape=false}
|
||||
<strong>... máme uloženou tuto adresu.</strong>
|
||||
Případný balíček vám pošleme stejným způsobem
|
||||
jako původní objednávku. Potřebujete změnit způsob dopravy? Napište nám do poznámky.{/t}</p>
|
||||
<p><strong>{t}Doručovací adresa{/t}</strong></p>
|
||||
<div class="row">
|
||||
<div class="col-sm-6 col-xs-12">
|
||||
<div class="form-group required">
|
||||
<label for="name">{t}Jméno{/t}</label>
|
||||
<input type="text" name="delivery[name]" id="name" class="form-control" value="{$body.order.delivery_name}"
|
||||
data-bv-notempty="true" data-bv-stringlength="true" data-bv-stringlength-min="2">
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm-6 col-xs-12">
|
||||
<div class="form-group required">
|
||||
<label for="surname">{t}Příjmení{/t}</label>
|
||||
<input type="text" name="delivery[surname]" id="surname" class="form-control"
|
||||
value="{$body.order.delivery_surname}"
|
||||
data-bv-notempty="true" data-bv-stringlength="true" data-bv-stringlength-min="2">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-sm-6 col-xs-12">
|
||||
<div class="form-group required">
|
||||
<label for="street">{t}Ulice{/t}</label>
|
||||
<input type="text" name="delivery[street]" id="street" class="form-control" value="{$body.order.delivery_street}"
|
||||
data-bv-notempty="true" data-bv-regexp="true" {if !$readonly}pattern=".*\S+\s+[0-9]+.*"{/if}
|
||||
data-bv-regexp-message="{t}Doplňte prosím číslo popisné{/t}"
|
||||
{if $readonly}disabled{/if}
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm-6 col-xs-12">
|
||||
<div class="form-group required">
|
||||
<label for="city">{t}Město{/t}</label>
|
||||
<input type="text" name="delivery[city]" id="city" class="form-control" value="{$body.order.delivery_city}"
|
||||
data-bv-notempty="true" data-bv-stringlength="true" data-bv-stringlength-min="2"
|
||||
{if $readonly}disabled{/if}
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-sm-6 col-xs-12">
|
||||
<div class="form-group required">
|
||||
<label for="phone">{t}Telefon{/t}</label>
|
||||
<input type="text" name="delivery[phone]" id="phone" class="form-control" value="{$body.order.invoice_phone}"
|
||||
data-bv-notempty="true" data-bv-phone="true" data-bv-phone-country="delivery[country]">
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm-6 col-xs-12">
|
||||
<div class="form-group required">
|
||||
<label for="zip">{t}PSČ{/t}</label>
|
||||
<input type="text" name="delivery[zip]" id="zip" class="form-control" value="{$body.order.delivery_zip}"
|
||||
data-bv-notempty="true" data-bv-zipcode="true" data-bv-zipcode-country="delivery[country]"
|
||||
{if $readonly}disabled{/if}
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{block "delivery_country"}
|
||||
{get_contexts country=true assign='contexts'}
|
||||
<div class="row">
|
||||
<div class="col-sm-6 col-xs-12">
|
||||
<div class="form-group required">
|
||||
<label for="country">{t}Stát{/t}</label>
|
||||
<select class="form-control custom-select c-select" id="country" name="delivery[country]" {if $readonly}disabled{/if}>
|
||||
{$selected = $body.order.delivery_country|default:$active.id}
|
||||
{foreach $contexts.country->getAll() as $id => $country}
|
||||
<option value="{$id}" {if $selected == $id}selected{/if}>{$country->getName()}</option>
|
||||
{/foreach}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{/block}
|
||||
<br>
|
||||
<p><strong>{t}Způsob dopravy{/t}</strong></p>
|
||||
<p>{$deliveryType.delivery}</p>
|
||||
</div>
|
||||
</fieldset>
|
||||
{/if}
|
||||
<div class="box-returns-summary">
|
||||
<div class="form-group">
|
||||
<label for="preferred_handle_type" class="title-default">{t}Jaké řešení reklamace preferujete?{/t}</label>
|
||||
<select class="form-control custom-select c-select" id="preferred_handle_type" name="preferred_handle_type">
|
||||
{html_options options=$body.preferred_handle_types}
|
||||
</select>
|
||||
</div>
|
||||
<br>
|
||||
<div class="form-group">
|
||||
<label for="bank_account" class="title-default">{t}Na jaký účet Vám můžeme případně vrátit platbu?{/t}</label>
|
||||
<input type="text" name="bank_account" id="bank_account" class="form-control" data-bv-bankaccount="true"
|
||||
data-bv-notempty="false">
|
||||
<span data-bank-account="error" style="color: #ea0f33; display: none;">{t}Zadejte platné číslo bankovního účtu{/t}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="box-returns-summary">
|
||||
<div class="form-group required">
|
||||
<label for="note" class="title-default">{t}Důvod reklamace a poznámky{/t}</label>
|
||||
<p>{t}Popište, prosím, jaký se objevil problém. Pokud je lépe patrný na fotografiích,
|
||||
využijte možnosti nahrát obrázky níže. Klidně jej na fotkách označte.{/t}</p>
|
||||
<textarea required class="form-control" name="note" id="note" rows="5"
|
||||
data-bv-notempty="true"></textarea>
|
||||
</div>
|
||||
<br>
|
||||
<div class="form-group">
|
||||
<label for="note" class="title-default">{t}Přílohy k reklamaci{/t}</label>
|
||||
{include "block.fileUploader.tpl" pageType='reclamation'}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-md-5 col-xxs-12">
|
||||
<div class="sticky-wrapper">
|
||||
{include "reclamations/block.reclamations-pricebox.tpl"}
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
{/block}
|
||||
|
||||
{block "js-dynamic-load" append}
|
||||
<script src="/admin/static/fineuploader/jquery.fine-uploader.min.js"></script>
|
||||
{/block}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
{extends "index.tpl"}
|
||||
|
||||
{block "css-entry" append}
|
||||
{encore_entry_link_tags entry='returns'}
|
||||
{/block}
|
||||
|
||||
{block "main"}
|
||||
<main class="main container page-returns page-returns-new returns-step-{$body.stepName} page-reclamations">
|
||||
<div class="order-process">
|
||||
{$visited = true}
|
||||
{foreach $body.steps as $stepName => $step}
|
||||
{if $stepName == $body.stepName}{$visited = false}{/if}
|
||||
<div class="order-process-step {if $stepName == $body.stepName}active{/if}">
|
||||
{$step.title}
|
||||
</div>
|
||||
{/foreach}
|
||||
</div>
|
||||
|
||||
<h1>{$view->getTitle()}</h1>
|
||||
{include "block.messages.tpl"}
|
||||
|
||||
{block content}
|
||||
{/block}
|
||||
</main>
|
||||
{/block}
|
||||
|
||||
{block "js-entry" append}
|
||||
{encore_entry_script_tags entry='returns'}
|
||||
{/block}
|
||||
@@ -0,0 +1,55 @@
|
||||
{extends "index.tpl"}
|
||||
|
||||
{block content}
|
||||
<div class="page-returns page-reclamations">
|
||||
<div class="reclamations-header m-b-2">
|
||||
<h1>{t}Reklamace{/t}</h1>
|
||||
{include "block.messages.tpl"}
|
||||
{insert_page type="RECLAMATIONS_LIST" use_default=1}
|
||||
</div>
|
||||
|
||||
{if $body.reclamations|count}
|
||||
<h2 class="h5">{t}Moje reklamace{/t}</h2>
|
||||
<table class="table table-orders">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>{t}Číslo{/t}</th>
|
||||
<th>{t}Objednávka{/t}</th>
|
||||
<th>{t}Datum podání{/t}</th>
|
||||
<th>{t}Produkty{/t}</th>
|
||||
<th>{t}Stav{/t}</th>
|
||||
<th>{t}Detail{/t}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
|
||||
{foreach $body.reclamations as $reclamation}
|
||||
<tr>
|
||||
<td>{$reclamation.code}</td>
|
||||
<td>{t}č.{/t} {$reclamation.order_no}</td>
|
||||
<td>{$reclamation.date_created|format_date_locale_pretty:null:$ctrl.active_language}</td>
|
||||
<td>
|
||||
<a target="_blank"
|
||||
href="{path('kupshop_content_redirect_redirect', ['type' => 'product', 'id' => $reclamation.item.id_product])}">
|
||||
{$reclamation.item.descr}
|
||||
</a>
|
||||
</td>
|
||||
<td>
|
||||
<strong>{$reclamation.status_name}</strong>
|
||||
<small> {if $reclamation.status == 0}
|
||||
({$reclamation.date_created|format_date_locale_pretty:null:$ctrl.active_language})
|
||||
{elseif in_array($reclamation.status, $body.accepted_statuses)}
|
||||
({$reclamation.date_accepted|format_date_locale_pretty:null:$ctrl.active_language})
|
||||
{elseif in_array($reclamation.status, $body.handle_statuses)}
|
||||
({$reclamation.date_handle|format_date_locale_pretty:null:$ctrl.active_language})
|
||||
{/if}</small>
|
||||
</td>
|
||||
<td>
|
||||
<a href="{path('kupshop_reclamations_reclamations_reclamation', ['id' => $reclamation.id])}"
|
||||
class="btn btn-primary btn-sm">{t}Detail{/t}</a>
|
||||
</td>
|
||||
</tr>
|
||||
{/foreach}
|
||||
</table>
|
||||
{/if}
|
||||
</div>
|
||||
{/block}
|
||||
@@ -0,0 +1,157 @@
|
||||
<?php
|
||||
|
||||
namespace KupShop\ReclamationsBundle\Resources\upgrade;
|
||||
|
||||
class ReclamationsUpgrade extends \UpgradeNew
|
||||
{
|
||||
public function check_ReclamationsTable()
|
||||
{
|
||||
return $this->checkTableExists('reclamations');
|
||||
}
|
||||
|
||||
/** Create table 'reclamations' */
|
||||
public function upgrade_ReclamationsTable()
|
||||
{
|
||||
sqlQuery('CREATE TABLE IF NOT EXISTS reclamations (
|
||||
id INT(11) NOT NULL AUTO_INCREMENT PRIMARY KEY,
|
||||
code VARCHAR(20) DEFAULT NULL UNIQUE,
|
||||
date_created DATETIME NOT NULL,
|
||||
date_accepted DATETIME DEFAULT NULL,
|
||||
date_handle DATETIME DEFAULT NULL,
|
||||
status INT(11) NOT NULL,
|
||||
id_item INT(11) UNSIGNED DEFAULT NULL,
|
||||
name VARCHAR(50),
|
||||
surname VARCHAR(50),
|
||||
street VARCHAR(100),
|
||||
city VARCHAR(50),
|
||||
zip VARCHAR(50),
|
||||
phone VARCHAR(20),
|
||||
bank_account VARCHAR(100),
|
||||
history MEDIUMTEXT DEFAULT NULL,
|
||||
CONSTRAINT FK_id_item FOREIGN KEY (id_item) REFERENCES order_items (id) ON DELETE SET NULL
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;');
|
||||
|
||||
sqlQuery('ALTER TABLE reclamations AUTO_INCREMENT = 100');
|
||||
|
||||
$this->upgradeOK();
|
||||
}
|
||||
|
||||
public function check_HandleTypeColumn()
|
||||
{
|
||||
return $this->checkColumnExists('reclamations', 'handle_type');
|
||||
}
|
||||
|
||||
/** Add column handle_type into reclamations */
|
||||
public function upgrade_HandleTypeColumn()
|
||||
{
|
||||
sqlQuery('ALTER TABLE reclamations ADD COLUMN handle_type INT(11) DEFAULT NULL');
|
||||
|
||||
$this->upgradeOK();
|
||||
}
|
||||
|
||||
public function check_dataColumn()
|
||||
{
|
||||
return $this->checkColumnExists('reclamations', 'data');
|
||||
}
|
||||
|
||||
/** Add column data into reclamations */
|
||||
public function upgrade_dataColumn()
|
||||
{
|
||||
sqlQuery('ALTER TABLE reclamations ADD COLUMN data MEDIUMTEXT DEFAULT NULL');
|
||||
|
||||
$this->upgradeOK();
|
||||
}
|
||||
|
||||
public function check_AddPackageIDColumn()
|
||||
{
|
||||
return $this->checkColumnExists('reclamations', 'package_id');
|
||||
}
|
||||
|
||||
/** Add package_id column into reclamations */
|
||||
public function upgrade_AddPackageIDColumn()
|
||||
{
|
||||
sqlQuery('ALTER TABLE reclamations ADD COLUMN package_id VARCHAR(100) DEFAULT NULL');
|
||||
|
||||
$this->upgradeOK();
|
||||
}
|
||||
|
||||
public function check_ReclamationDescrColumn()
|
||||
{
|
||||
return $this->checkColumnExists('reclamations', 'descr');
|
||||
}
|
||||
|
||||
/** Add descr column into reclamations */
|
||||
public function upgrade_ReclamationDescrColumn()
|
||||
{
|
||||
sqlQuery('ALTER TABLE reclamations ADD COLUMN descr MEDIUMTEXT AFTER bank_account');
|
||||
|
||||
$this->upgradeOK();
|
||||
}
|
||||
|
||||
public function check_BalikonosIdColumn()
|
||||
{
|
||||
return $this->checkColumnExists('reclamations', 'id_balikonos') && (findModule(\Modules::BALIKONOS, 'provider') == 'balikobot');
|
||||
}
|
||||
|
||||
/** Add column id_balikonos into reclamations */
|
||||
public function upgrade_BalikonosIdColumn()
|
||||
{
|
||||
sqlQuery('ALTER TABLE reclamations ADD COLUMN id_balikonos INT(11) DEFAULT NULL;');
|
||||
sqlQuery('ALTER TABLE reclamations ADD CONSTRAINT fk_reclamations_balikonos FOREIGN KEY (id_balikonos)
|
||||
REFERENCES balikonos (id) ON DELETE SET NULL;');
|
||||
|
||||
$this->upgradeOK();
|
||||
}
|
||||
|
||||
public function check_NoteColumn()
|
||||
{
|
||||
return $this->checkColumnExists('reclamations', 'user_note');
|
||||
}
|
||||
|
||||
/** Add column user_note into reclamations */
|
||||
public function upgrade_NoteColumn()
|
||||
{
|
||||
sqlQuery('ALTER TABLE reclamations ADD COLUMN user_note MEDIUMTEXT DEFAULT NULL AFTER descr');
|
||||
|
||||
$this->upgradeOK();
|
||||
}
|
||||
|
||||
public function check_CountryColumn()
|
||||
{
|
||||
return $this->checkColumnExists('reclamations', 'country');
|
||||
}
|
||||
|
||||
/** Add country column into 'reclamations' */
|
||||
public function upgrade_CountryColumn()
|
||||
{
|
||||
sqlQuery('ALTER TABLE reclamations ADD COLUMN country VARCHAR(50) DEFAULT NULL AFTER zip');
|
||||
|
||||
$this->upgradeOK();
|
||||
}
|
||||
|
||||
public function check_HandlingColumn()
|
||||
{
|
||||
return $this->checkColumnExists('reclamations', 'preferred_handle_type');
|
||||
}
|
||||
|
||||
/** Add preferred handle type column into 'reclamations' - The mode of handling the claim */
|
||||
public function upgrade_HandlingColumn()
|
||||
{
|
||||
sqlQuery('ALTER TABLE reclamations ADD COLUMN preferred_handle_type INT DEFAULT NULL AFTER history');
|
||||
|
||||
$this->upgradeOK();
|
||||
}
|
||||
|
||||
public function check_PiecesColumn()
|
||||
{
|
||||
return $this->checkColumnExists('reclamations', 'pieces');
|
||||
}
|
||||
|
||||
/** Add pieces column into 'reclamations' */
|
||||
public function upgrade_PiecesColumn()
|
||||
{
|
||||
sqlQuery('ALTER TABLE reclamations ADD COLUMN pieces INT DEFAULT 1 AFTER id_item');
|
||||
|
||||
$this->upgradeOK();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
{
|
||||
"reclamations": [
|
||||
{
|
||||
"id": 100,
|
||||
"code": "R100",
|
||||
"date_created": "2019-04-11 08:12:08",
|
||||
"date_accepted": null,
|
||||
"date_handle": null,
|
||||
"status": 0,
|
||||
"id_item": 34,
|
||||
"name": "Ondřej",
|
||||
"surname": "Beneš",
|
||||
"street": "Úpická 337",
|
||||
"city": "Malé Svatoňovice",
|
||||
"zip": "54234",
|
||||
"phone": "+420702089098",
|
||||
"bank_account": "123-000055515231/0800",
|
||||
"history": "[{\"comment\":\"Nefouka to\",\"status\":0,\"date\":\"2019-04-11 08:12:08\",\"notified\":0,\"custom_data\":[],\"admin\":null}]"
|
||||
}
|
||||
]
|
||||
}
|
||||
102
bundles/KupShop/ReclamationsBundle/Tests/ReclamationsTest.php
Normal file
102
bundles/KupShop/ReclamationsBundle/Tests/ReclamationsTest.php
Normal file
@@ -0,0 +1,102 @@
|
||||
<?php
|
||||
|
||||
namespace KupShop\ReclamationsBundle\Tests;
|
||||
|
||||
use KupShop\DevelopmentBundle\MailArchive;
|
||||
use KupShop\ReclamationsBundle\Util\ReclamationsUtil;
|
||||
|
||||
class ReclamationsTest extends \DatabaseTestCase
|
||||
{
|
||||
/** @var ReclamationsUtil */
|
||||
private $reclamations;
|
||||
/** @var MailArchive */
|
||||
private $mailArchive;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
$this->reclamations = $this->get(ReclamationsUtil::class);
|
||||
$this->mailArchive = $this->get(MailArchive::class);
|
||||
}
|
||||
|
||||
public function testCreateAndGetReclamation()
|
||||
{
|
||||
$reclamationId = $this->reclamations->createReclamation(34, 1, [], '123-4561315454/0800', null, 'User note');
|
||||
$reclamation = $this->reclamations->getReclamation($reclamationId);
|
||||
|
||||
$this->assertRegExp('/R\d{3}/', $reclamation->getCode());
|
||||
|
||||
$history = $reclamation->getHistory();
|
||||
$history = reset($history);
|
||||
|
||||
$this->assertEquals('User note', $history['comment']);
|
||||
}
|
||||
|
||||
public function testEmailSentOnReturnCreated()
|
||||
{
|
||||
$dbcfg = \Settings::getDefault();
|
||||
$dbcfg->reclamations['descr'] = '{KOD_REKLAMACE}';
|
||||
|
||||
$this->reclamations->createReclamation(34, 1, [], '123-4561315454/0800', 'User note');
|
||||
|
||||
$email = $this->mailArchive->getLast();
|
||||
|
||||
$this->assertNotEmpty($email);
|
||||
$this->assertRegExp('/Přijali jsme formulář s reklamací R\d{3}/', $email['subject']);
|
||||
}
|
||||
|
||||
public function testGetEmails()
|
||||
{
|
||||
$contents = $this->reclamations->getEmails();
|
||||
|
||||
$this->assertNotEmpty($contents);
|
||||
}
|
||||
|
||||
public function testLogAndGetHistory()
|
||||
{
|
||||
$this->reclamations->logHistory(100, 'Log history test');
|
||||
|
||||
$history = $this->reclamations->getHistory(100);
|
||||
$last = end($history);
|
||||
unset($last['date']);
|
||||
|
||||
$this->assertEquals($last, [
|
||||
'comment' => 'Log history test',
|
||||
'status' => 0,
|
||||
'notified' => 0,
|
||||
'custom_data' => [],
|
||||
'admin' => null,
|
||||
'status_name' => 'Nová',
|
||||
'admin_name' => null,
|
||||
]);
|
||||
}
|
||||
|
||||
public function testChangeStatus()
|
||||
{
|
||||
$reclamation = $this->reclamations->getReclamation(100);
|
||||
$this->assertEquals(0, $reclamation->getStatus());
|
||||
$this->assertEmpty($reclamation->getDateAccepted());
|
||||
$this->assertEmpty($reclamation->getDateHandle());
|
||||
|
||||
$this->reclamations->changeStatus(100, 1);
|
||||
|
||||
$reclamation = $this->reclamations->getReclamation(100);
|
||||
$this->assertEquals(1, $reclamation->getStatus());
|
||||
$this->assertNotEmpty($reclamation->getDateAccepted());
|
||||
$this->assertEmpty($reclamation->getDateHandle());
|
||||
|
||||
$this->reclamations->changeStatus(100, 2);
|
||||
|
||||
$reclamation = $this->reclamations->getReclamation(100);
|
||||
$this->assertEquals(2, $reclamation->getStatus());
|
||||
$this->assertNotEmpty($reclamation->getDateAccepted());
|
||||
$this->assertNotEmpty($reclamation->getDateHandle());
|
||||
$this->assertTrue($reclamation->isClosed());
|
||||
}
|
||||
|
||||
protected function getDataSet()
|
||||
{
|
||||
return $this->getJsonDataSetFromFile();
|
||||
}
|
||||
}
|
||||
387
bundles/KupShop/ReclamationsBundle/Util/ReclamationsUtil.php
Normal file
387
bundles/KupShop/ReclamationsBundle/Util/ReclamationsUtil.php
Normal file
@@ -0,0 +1,387 @@
|
||||
<?php
|
||||
|
||||
namespace KupShop\ReclamationsBundle\Util;
|
||||
|
||||
use KupShop\KupShopBundle\Context\CurrencyContext;
|
||||
use KupShop\KupShopBundle\Context\LanguageContext;
|
||||
use KupShop\ReclamationsBundle\Email\ReclamationCreateAdminEmail;
|
||||
use KupShop\ReclamationsBundle\Entity\ReclamationEntity;
|
||||
use KupShop\ReclamationsBundle\Event\ReclamationsEvent;
|
||||
use KupShop\ReturnsBundle\Util\ReturnsReclamations;
|
||||
use Query\Operator;
|
||||
use Query\QueryBuilder;
|
||||
|
||||
class ReclamationsUtil extends ReturnsReclamations
|
||||
{
|
||||
public const DEFAULT_GUARANTEE = 24;
|
||||
public const STATUS_NEW = 0;
|
||||
public const STATUS_ACCEPTED = 1;
|
||||
public const STATUS_HANDLED = 2;
|
||||
|
||||
protected static $tableName = 'reclamations';
|
||||
|
||||
private $languageContext;
|
||||
|
||||
public function __construct(LanguageContext $languageContext)
|
||||
{
|
||||
$this->languageContext = $languageContext;
|
||||
}
|
||||
|
||||
public function createReclamation(int $itemId, int $itemPieces, array $delivery, $bankAccount, $preferred_handle_type, $userNote = null, $sendMail = true, ?array $user_content = null)
|
||||
{
|
||||
$entity = sqlGetConnection()->transactional(function () use ($itemId, $itemPieces, $delivery, $bankAccount, $preferred_handle_type, $userNote, $sendMail, $user_content) {
|
||||
$order_id = sqlQueryBuilder()
|
||||
->select('oi.id_order')
|
||||
->from('order_items', 'oi')
|
||||
->where(Operator::equals(['oi.id' => $itemId]))
|
||||
->execute()->fetchColumn();
|
||||
|
||||
$order = new \Order($order_id);
|
||||
$order->createFromDB($order_id);
|
||||
|
||||
$insert = [
|
||||
'date_created' => new \DateTime(),
|
||||
'status' => 0,
|
||||
'id_item' => $itemId,
|
||||
'pieces' => $itemPieces,
|
||||
'bank_account' => $bankAccount,
|
||||
'preferred_handle_type' => $preferred_handle_type,
|
||||
'user_note' => $userNote,
|
||||
] + $delivery;
|
||||
|
||||
$data = json_decode($insert['data'] ?? '', true) ?? [];
|
||||
|
||||
if (!empty($user_content)) {
|
||||
$data['userContent'] = $user_content;
|
||||
}
|
||||
|
||||
$deliveryData = $order->getDeliveryType()->getDelivery()->data;
|
||||
if (!empty($deliveryData)) {
|
||||
$data['delivery_data'] = $deliveryData;
|
||||
}
|
||||
|
||||
if (!empty($data)) {
|
||||
$insert['data'] = json_encode($data);
|
||||
}
|
||||
|
||||
sqlQueryBuilder()->insert('reclamations')
|
||||
->directValues($insert, ['date_created' => 'datetime'])
|
||||
->execute();
|
||||
|
||||
$reclamationId = sqlInsertId();
|
||||
|
||||
$code = $this->getCode($reclamationId);
|
||||
|
||||
sqlQueryBuilder()->update('reclamations')
|
||||
->directValues(['code' => $code])
|
||||
->where(Operator::equals(['id' => $reclamationId]))
|
||||
->execute();
|
||||
|
||||
$this->logHistory($reclamationId, empty($userNote) ? '' : $userNote, $sendMail);
|
||||
|
||||
$entity = $this->getReclamation($reclamationId);
|
||||
|
||||
$order->logHistory(translate('order_history', 'Reclamations', false, true)." <a href=\"javascript:nw('Reclamations', {$reclamationId})\">{$code}</a>");
|
||||
|
||||
$entity->setOrderNumber($order->order_no);
|
||||
$event = new ReclamationsEvent($entity, self::STATUS_NEW);
|
||||
$this->dispatcher->dispatch($event, ReclamationsEvent::RECLAMATION_CREATED);
|
||||
|
||||
return $entity;
|
||||
});
|
||||
|
||||
if ($sendMail) {
|
||||
$this->contextManager->activateContexts([
|
||||
LanguageContext::class => $entity->getIdLanguage(),
|
||||
CurrencyContext::class => $entity->getIdCurrency(),
|
||||
],
|
||||
function () use ($entity) {
|
||||
$this->sendEmail($entity, $this->getEmailsInStatuses()[self::STATUS_NEW]);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
$dbcfg = \Settings::getDefault();
|
||||
// Shopkeeper notification
|
||||
$shopkeeperEmail = !empty($dbcfg->reclamations['shopkeeper_email']) ? $dbcfg->reclamations['shopkeeper_email'] : $dbcfg->order_shopkeeper_mail;
|
||||
if (!empty($shopkeeperEmail)) {
|
||||
$this->sendNotificationToOwner(
|
||||
$entity,
|
||||
$shopkeeperEmail
|
||||
);
|
||||
}
|
||||
|
||||
return $entity->getId();
|
||||
}
|
||||
|
||||
public function getCode($reclamationId)
|
||||
{
|
||||
return 'R'.sprintf('%03d', $reclamationId);
|
||||
}
|
||||
|
||||
public function setData(int $reclamationId, $key, $value)
|
||||
{
|
||||
$data = $this->getData($reclamationId);
|
||||
|
||||
$data[$key] = $value;
|
||||
|
||||
sqlQueryBuilder()->update('reclamations')
|
||||
->directValues(['data' => json_encode($data)])
|
||||
->where(Operator::equals(['id' => $reclamationId]))
|
||||
->execute();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public function getData(int $reclamationId, $key = null)
|
||||
{
|
||||
$data = sqlQueryBuilder()
|
||||
->select('data')
|
||||
->from('reclamations')
|
||||
->where(Operator::equals(['id' => $reclamationId]))
|
||||
->execute()->fetchColumn();
|
||||
|
||||
$data = json_decode($data ?? '', true) ?? [];
|
||||
|
||||
if ($key) {
|
||||
return $data[$key] ?? null;
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
public function getReclamation(int $reclamationId, bool $ordersSpecs = false)
|
||||
{
|
||||
$reclamation_qb = sqlQueryBuilder()->select('r.*, o.id as id_order, o.order_no, o.invoice_email as email')
|
||||
->from('reclamations', 'r')
|
||||
->leftJoin('r', 'order_items', 'oi', 'oi.id = r.id_item')
|
||||
->leftJoin('oi', 'orders', 'o', 'o.id = oi.id_order')
|
||||
->where(Operator::equals(['r.id' => $reclamationId]));
|
||||
|
||||
if ($ordersSpecs && !getAdminUser()) {
|
||||
$reclamation_qb->andWhere($this->getOrdersSpec());
|
||||
}
|
||||
|
||||
if ($reclamation = $reclamation_qb->execute()->fetch()) {
|
||||
$reclamationEntity = new ReclamationEntity();
|
||||
|
||||
$delivery = [];
|
||||
foreach ($reclamation as $key => $value) {
|
||||
if (in_array($key, $this->getAddressFields())) {
|
||||
$delivery[$key] = $value;
|
||||
}
|
||||
}
|
||||
|
||||
$order = new \Order();
|
||||
$order->createFromDB($reclamation['id_order']);
|
||||
|
||||
$reclamationEntity->setId($reclamationId)
|
||||
->setIdLanguage($order->getLanguage())
|
||||
->setIdCurrency($order->getCurrency())
|
||||
->setCode($reclamation['code'])
|
||||
->setDateCreated($reclamation['date_created'])
|
||||
->setDateAccepted($reclamation['date_accepted'])
|
||||
->setDateHandle($reclamation['date_handle'])
|
||||
->setStatus($reclamation['status'])
|
||||
->setStatusName(
|
||||
$this->getStatuses()[$reclamation['status']] ?? ''
|
||||
)
|
||||
->setHandleType($reclamation['handle_type'])
|
||||
->setHandleTypeName(
|
||||
$this->getHandleTypes()[$reclamation['handle_type']] ?? ''
|
||||
)
|
||||
->setPrefHandleType($reclamation['preferred_handle_type'])
|
||||
->setPrefHandleTypeName(
|
||||
$this->getPrefHandleTypes()[$reclamation['preferred_handle_type']] ?? ''
|
||||
)
|
||||
->setBankAccount($reclamation['bank_account'])
|
||||
->setDescr($reclamation['descr'])
|
||||
->setUserNote($reclamation['user_note'])
|
||||
->setHistory(
|
||||
$this->getHistory($reclamationId)
|
||||
)
|
||||
->setEmail($reclamation['email'])
|
||||
->setAddress($delivery)
|
||||
->setIdItem($reclamation['id_item'])
|
||||
->setItem(
|
||||
$this->getReclamationItem($reclamationId)
|
||||
)
|
||||
->setPieces($reclamation['pieces'])
|
||||
->setIdOrder($reclamation['id_order'])
|
||||
->setOrderNumber($reclamation['order_no'])
|
||||
->setPackageId($reclamation['package_id'])
|
||||
->setIdBalikonos($reclamation['id_balikonos'] ?? null)
|
||||
->setData(
|
||||
$this->getData($reclamationId)
|
||||
);
|
||||
|
||||
return $reclamationEntity;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public function getAddressFields(bool $requiresDeliveryAddress = true)
|
||||
{
|
||||
return array_merge(['name', 'surname', 'phone'],
|
||||
$requiresDeliveryAddress
|
||||
? ['street', 'city', 'zip', 'country']
|
||||
: []
|
||||
);
|
||||
}
|
||||
|
||||
public function getReclamationItem(int $reclamationId)
|
||||
{
|
||||
$qb = sqlQueryBuilder()->select('oi.*, p.code, COALESCE(pv.ean, p.ean) AS ean, r.pieces, oi.piece_price*r.pieces as total_price')
|
||||
->from('order_items', 'oi')
|
||||
->leftJoin('oi', 'reclamations', 'r', 'r.id_item = oi.id')
|
||||
->leftJoin('oi', 'products', 'p', 'p.id = oi.id_product')
|
||||
->joinVariationsOnProducts()
|
||||
->andWhere(Operator::equals(['r.id' => $reclamationId]))
|
||||
->andWhere(Operator::equalsToOrNullable('oi.id_variation', 'pv.id'));
|
||||
if (findModule('products_variations', 'variationCode')) {
|
||||
$qb->addSelect('COALESCE(pv.code, p.code) AS `code`');
|
||||
}
|
||||
|
||||
if (findModule(\Modules::PRODUCTS, \Modules::SUB_WEIGHT) && findModule(\Modules::PRODUCTS_VARIATIONS)) {
|
||||
$qb->addSelect('COALESCE(pv.weight, p.weight) as weight');
|
||||
} elseif (findModule(\Modules::PRODUCTS, \Modules::SUB_WEIGHT) && !findModule(\Modules::PRODUCTS_VARIATIONS)) {
|
||||
$qb->addSelect('p.weight as weight');
|
||||
}
|
||||
|
||||
$item = $qb->execute()->fetch();
|
||||
|
||||
return $item;
|
||||
}
|
||||
|
||||
public function getStatuses(): array
|
||||
{
|
||||
return [
|
||||
0 => translate_shop('status_0', 'reclamations'),
|
||||
1 => translate_shop('status_1', 'reclamations'),
|
||||
2 => translate_shop('status_2', 'reclamations'),
|
||||
];
|
||||
}
|
||||
|
||||
public function getHandleTypes(): array
|
||||
{
|
||||
return [
|
||||
1 => translate_shop('handle_type_1', 'reclamations'),
|
||||
0 => translate_shop('handle_type_0', 'reclamations'),
|
||||
2 => translate_shop('handle_type_2', 'reclamations'),
|
||||
3 => translate_shop('handle_type_3', 'reclamations'),
|
||||
4 => translate_shop('handle_type_4', 'reclamations'),
|
||||
];
|
||||
}
|
||||
|
||||
public function getPrefHandleTypes(): array
|
||||
{
|
||||
return [
|
||||
1 => translate_shop('handle_1', 'reclamations'),
|
||||
2 => translate_shop('handle_2', 'reclamations'),
|
||||
3 => translate_shop('handle_3', 'reclamations'),
|
||||
4 => translate_shop('handle_4', 'reclamations'),
|
||||
];
|
||||
}
|
||||
|
||||
public function getEmailsInStatuses($entity = null): array
|
||||
{
|
||||
$handleEmail = 'RECLAMATION_HANDLE_EXCHANGE_EMAIL';
|
||||
/** @var ReclamationEntity $entity */
|
||||
if ($entity) {
|
||||
switch ($entity->getHandleType()) {
|
||||
case 0:
|
||||
$handleEmail = 'RECLAMATION_HANDLE_EXCHANGE_EMAIL';
|
||||
break;
|
||||
case 1:
|
||||
$handleEmail = 'RECLAMATION_HANDLE_FIX_EMAIL';
|
||||
break;
|
||||
case 2:
|
||||
$handleEmail = 'RECLAMATION_HANDLE_RETURN_EMAIL';
|
||||
break;
|
||||
case 3:
|
||||
$handleEmail = 'RECLAMATION_HANDLE_CANCEL_EMAIL';
|
||||
break;
|
||||
case 4:
|
||||
$handleEmail = 'RECLAMATION_HANDLE_CONVERT_TO_RETURN_EMAIL';
|
||||
break;
|
||||
default:
|
||||
throw new \RuntimeException('Invalid handle_type');
|
||||
}
|
||||
}
|
||||
|
||||
return [
|
||||
self::STATUS_NEW => 'RECLAMATION_CREATE_EMAIL',
|
||||
self::STATUS_ACCEPTED => 'RECLAMATION_ACCEPT_EMAIL',
|
||||
self::STATUS_HANDLED => $handleEmail,
|
||||
self::STATUS_HANDLED.'-0' => 'RECLAMATION_HANDLE_EXCHANGE_EMAIL',
|
||||
self::STATUS_HANDLED.'-1' => 'RECLAMATION_HANDLE_FIX_EMAIL',
|
||||
self::STATUS_HANDLED.'-2' => 'RECLAMATION_HANDLE_RETURN_EMAIL',
|
||||
self::STATUS_HANDLED.'-3' => 'RECLAMATION_HANDLE_CANCEL_EMAIL',
|
||||
self::STATUS_HANDLED.'-4' => 'RECLAMATION_HANDLE_CONVERT_TO_RETURN_EMAIL',
|
||||
];
|
||||
}
|
||||
|
||||
public function sendNotificationToOwner(ReclamationEntity $reclamation, string $email): void
|
||||
{
|
||||
$reclamationEmail = $reclamation->getEmail();
|
||||
// Override reclamation email that is used as "to"
|
||||
$reclamation->setEmail($email);
|
||||
// Send email
|
||||
$this->sendEmail($reclamation, ReclamationCreateAdminEmail::getType());
|
||||
// Set original email back
|
||||
$reclamation->setEmail($reclamationEmail);
|
||||
}
|
||||
|
||||
public function getAcceptedStatuses(): array
|
||||
{
|
||||
return [self::STATUS_ACCEPTED];
|
||||
}
|
||||
|
||||
public function getHandleStatuses(): array
|
||||
{
|
||||
return [self::STATUS_HANDLED];
|
||||
}
|
||||
|
||||
public function getAuthCode(int $reclamationId)
|
||||
{
|
||||
if (!findModule(\Modules::RETURNS, \Modules::SUB_CP_AUTH_CODES)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$auth_code = $this->getData($reclamationId, 'auth_code');
|
||||
|
||||
if ($auth_code) {
|
||||
return $auth_code;
|
||||
}
|
||||
|
||||
if ($auth_code = $this->getNextAuthCode()) {
|
||||
$this->setData($reclamationId, 'auth_code', $auth_code);
|
||||
}
|
||||
|
||||
return $auth_code;
|
||||
}
|
||||
|
||||
public function getSecurityCode(int $reclamationId)
|
||||
{
|
||||
$reclamationArr = sqlFetchAssoc(sqlQuery('SELECT
|
||||
id, code, date_created
|
||||
FROM '.getTableName('reclamations')."
|
||||
WHERE id='{$reclamationId}'
|
||||
LIMIT 1"));
|
||||
|
||||
$code = $reclamationArr['id'].'*'.$reclamationArr['code'].'*'.$reclamationArr['date_created'];
|
||||
|
||||
return md5($code);
|
||||
}
|
||||
|
||||
public function getExpiredItemsSpec()
|
||||
{
|
||||
return function (QueryBuilder $qb) {
|
||||
$dbcfg = \Settings::getDefault();
|
||||
$qb->addSelect('COALESCE(o.date_delivered, o.date_handle, o.date_created) + INTERVAL COALESCE(NULLIF(p.guarantee, 0), :defaultGuarantee) MONTH + INTERVAL :dayGuarantee DAY < NOW() as expired')
|
||||
->setParameter('dayGuarantee', $dbcfg->reclamations['days'] == '' ? 0 : $dbcfg->reclamations['days'])
|
||||
->setParameter('defaultGuarantee', self::DEFAULT_GUARANTEE);
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,332 @@
|
||||
<?php
|
||||
|
||||
namespace KupShop\ReclamationsBundle\View;
|
||||
|
||||
use KupShop\KupShopBundle\Exception\RedirectException;
|
||||
use KupShop\KupShopBundle\Query\JsonOperator;
|
||||
use KupShop\KupShopBundle\Util\Database\QueryHint;
|
||||
use KupShop\KupShopBundle\Views\View;
|
||||
use KupShop\ReclamationsBundle\Query\Reclamations;
|
||||
use KupShop\ReclamationsBundle\Util\ReclamationsUtil;
|
||||
use Query\Filter;
|
||||
use Query\Operator;
|
||||
use Query\Product;
|
||||
|
||||
class CreateReclamationView extends View
|
||||
{
|
||||
protected static $type = 'reclamations';
|
||||
|
||||
protected $template = 'reclamations/reclamations-new.products.tpl';
|
||||
protected string $smartyFallback = 'account';
|
||||
protected string $entrypoint = 'account';
|
||||
|
||||
private string $step = 'login';
|
||||
|
||||
protected array $steps;
|
||||
|
||||
private $itemId;
|
||||
private $itemPieces;
|
||||
|
||||
protected $reclamationsUtil;
|
||||
|
||||
private \Pager $pager;
|
||||
private array $filter;
|
||||
|
||||
public function __construct(ReclamationsUtil $reclamationsUtil)
|
||||
{
|
||||
$this->reclamationsUtil = $reclamationsUtil;
|
||||
|
||||
$this->steps = $this->getSteps();
|
||||
$this->setPager(new \Pager());
|
||||
}
|
||||
|
||||
public function getBodyVariables()
|
||||
{
|
||||
$vars = parent::getBodyVariables();
|
||||
|
||||
$vars['steps'] = $this->steps;
|
||||
$vars['stepName'] = $this->getStep();
|
||||
$page = getVal('page', null, 1);
|
||||
$noOnPage = 50;
|
||||
$pager = $this->getPager();
|
||||
$pager->setOnPage($noOnPage);
|
||||
$pager->setPageNumber($page);
|
||||
|
||||
$items = $this->getBoughtItems();
|
||||
$vars['filter'] = $this->filter ?? [];
|
||||
|
||||
if ($this->getStep() == 'products') {
|
||||
$productList = new \ProductList();
|
||||
$productList->setVariationsAsResult(true);
|
||||
|
||||
$products = [];
|
||||
|
||||
$vars['items'] = $items;
|
||||
|
||||
foreach ($vars['items'] as $item) {
|
||||
$products[$item['id_product']] = $products[$item['id_product']] ?? null;
|
||||
|
||||
if ($item['id_variation']) {
|
||||
$products[$item['id_product']][] = $item['id_variation'];
|
||||
}
|
||||
}
|
||||
|
||||
$productList->andSpec(Product::productsAndVariationsIds($products));
|
||||
$productList->fetchImages('product_gallery', null, true);
|
||||
|
||||
$products = $productList->getProducts();
|
||||
|
||||
$vars['itemsInOrder'] = [];
|
||||
|
||||
foreach ($vars['items'] as &$item) {
|
||||
$key = $item['id_product'];
|
||||
|
||||
if ($item['id_variation']) {
|
||||
$key .= '/'.$item['id_variation'];
|
||||
}
|
||||
|
||||
$item['product'] = $products[$key];
|
||||
|
||||
if (empty($vars['itemsInOrder'][$item['id_order']][$item['id']])) {
|
||||
$vars['itemsInOrder'][$item['id_order']][$item['id']] = $item;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($this->step == 'summary' && $this->itemId) {
|
||||
$itemExists = false;
|
||||
foreach ($items as $item) {
|
||||
if ($item['id'] == $this->itemId && !$item['expired']) {
|
||||
$itemExists = true;
|
||||
$selected = $item;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!$itemExists) {
|
||||
$this->addErrorMessage(translate('error_item', 'reclamations'));
|
||||
throw new RedirectException(path('kupshop_reclamations_reclamations_createreclamation'));
|
||||
}
|
||||
|
||||
if (!empty($selected['id_variation'])) {
|
||||
$product = new \Variation($selected['id_product'], $selected['id_variation']);
|
||||
} else {
|
||||
$product = new \Product($selected['id_product']);
|
||||
}
|
||||
|
||||
$product->createFromDB();
|
||||
$product->fetchImages('product_gallery');
|
||||
|
||||
$vars['item'] = $selected;
|
||||
$vars['item']['product'] = $product;
|
||||
$vars['item']['pieces_to_return'] = $this->itemPieces;
|
||||
|
||||
if ($order = $this->getOrder()) {
|
||||
$vars['order'] = $order;
|
||||
}
|
||||
}
|
||||
|
||||
$vars['preferred_handle_types'] = $this->reclamationsUtil->getPrefHandleTypes();
|
||||
$vars['pager'] = $pager;
|
||||
|
||||
return $vars;
|
||||
}
|
||||
|
||||
public function getOrder(): ?\Order
|
||||
{
|
||||
$orderId = sqlQueryBuilder()
|
||||
->select('id_order')
|
||||
->from('order_items')
|
||||
->where(Operator::equals(['id' => $this->itemId]))
|
||||
->execute()->fetchColumn();
|
||||
|
||||
if ($orderId) {
|
||||
$order = new \Order();
|
||||
$order->createFromDB($orderId);
|
||||
|
||||
return $order;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public function handleStep_reclamationSummary($delivery, $bankAccount, $preferred_handle_type, $note, $user_content)
|
||||
{
|
||||
$order = $this->getOrder();
|
||||
// validate required address fields
|
||||
foreach ($this->reclamationsUtil->getAddressFields($order->getDeliveryType()->requiresDeliveryAddress()) as $field) {
|
||||
if (empty($delivery[$field])) {
|
||||
addUserMessage(translate('error_delivery_fields', 'reclamations'), 'danger');
|
||||
throw new RedirectException(path('kupshop_reclamations_reclamations_createreclamationsummary',
|
||||
['id_item' => $this->itemId]));
|
||||
}
|
||||
}
|
||||
|
||||
if (empty($note)) {
|
||||
addUserMessage(translate('error_note', 'reclamations'), 'danger');
|
||||
throw new RedirectException(path('kupshop_reclamations_reclamations_createreclamationsummary', ['id_item' => $this->itemId]));
|
||||
}
|
||||
|
||||
if ($id = QueryHint::withRouteToMaster(function () use ($delivery, $bankAccount, $preferred_handle_type, $note, $user_content) {
|
||||
return $this->reclamationsUtil->createReclamation($this->itemId, $this->itemPieces, $delivery, $bankAccount, $preferred_handle_type, $note, true, $user_content);
|
||||
})) {
|
||||
throw new RedirectException(path('kupshop_reclamations_reclamations_reclamation', ['id' => $id, 'success' => 1]));
|
||||
}
|
||||
}
|
||||
|
||||
protected function getBoughtItems()
|
||||
{
|
||||
$products = sqlQueryBuilder()
|
||||
->select('oi.*, COALESCE(o.date_delivered, o.date_handle, o.date_created) as delivery_date, p.guarantee, o.order_no')
|
||||
->from('order_items', 'oi')
|
||||
->leftJoin('oi', 'orders', 'o', 'o.id = oi.id_order')
|
||||
->leftJoin('oi', 'products', 'p', 'p.id = oi.id_product')
|
||||
->addSelect(Reclamations::getReturnablePiecesSpec())
|
||||
->andWhere('oi.id_product IS NOT NULL')
|
||||
->andWhere('oi.pieces > 0')
|
||||
->andWhere(Operator::inIntArray(getStatuses('handled'), 'o.status'))
|
||||
->andWhere(
|
||||
Operator::orX(
|
||||
Operator::not(JsonOperator::contains('oi.note', 'item_type', 'gift')),
|
||||
Operator::equalsNullable(['JSON_CONTAINS(oi.note,\'"gift"\',\'$.item_type\')' => null])
|
||||
)
|
||||
)
|
||||
->andWhere('o.status_storno != 1')
|
||||
->andWhere($this->reclamationsUtil->getOrdersSpec())
|
||||
->orderBy('delivery_date', 'DESC')
|
||||
->groupBy('oi.id');
|
||||
|
||||
if (findModule(\Modules::CURRENCIES)) {
|
||||
$products->addSelect('o.currency');
|
||||
}
|
||||
|
||||
$products
|
||||
->addSelect($this->reclamationsUtil->getExpiredItemsSpec())
|
||||
->addCalcRows();
|
||||
|
||||
if ($this->getStep() == 'products') {
|
||||
$products->andWhere($this->getPager()->getSpec());
|
||||
}
|
||||
|
||||
// Filter:
|
||||
// Vyhledat produkt
|
||||
if (!empty($this->filter['product'])) {
|
||||
$products->andWhere(Filter::search($this->filter['product']));
|
||||
}
|
||||
// Vyhledat objednávku
|
||||
if (!empty($this->filter['order'])) {
|
||||
$order = sqlQueryBuilder()->select('id, order_no')->from('orders')
|
||||
->andWhere(Operator::equals(['id' => $this->filter['order'], 'order_no' => $this->filter['order']], 'OR'))
|
||||
->execute()->fetchAssociative();
|
||||
if ($order) {
|
||||
$products->andWhere(Operator::equals(['o.id' => $order['id']]));
|
||||
}
|
||||
$this->filter['order'] = ($order ? $order['order_no'] : null);
|
||||
}
|
||||
|
||||
$return = [];
|
||||
$productsList = $products->execute();
|
||||
$this->getPager()->setTotal(returnSQLResult('SELECT FOUND_ROWS()'));
|
||||
foreach ($productsList as $item) {
|
||||
$piecePrice = toDecimal($item['piece_price']);
|
||||
$piecePrice = $piecePrice->addVat($item['tax']);
|
||||
|
||||
$item['piece_price_with_vat'] = $piecePrice;
|
||||
|
||||
$return[] = $item;
|
||||
}
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
||||
public function getBreadcrumbs()
|
||||
{
|
||||
return getReturnNavigation(-1, 'RECLAMATION', [$this->getTitle()]);
|
||||
}
|
||||
|
||||
public function getTitle()
|
||||
{
|
||||
return $this->getActiveStep()['descr'];
|
||||
}
|
||||
|
||||
public function setItemId($itemId)
|
||||
{
|
||||
$this->itemId = $itemId;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function setItemPieces($itemPieces)
|
||||
{
|
||||
$this->itemPieces = $itemPieces;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function setStep($step)
|
||||
{
|
||||
$this->step = $step;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getTemplate(): string
|
||||
{
|
||||
switch ($this->step) {
|
||||
case 'login':
|
||||
return 'reclamations/reclamations-new.login.tpl';
|
||||
case 'products':
|
||||
return 'reclamations/reclamations-new.products.tpl';
|
||||
case 'summary':
|
||||
return 'reclamations/reclamations-new.summary.tpl';
|
||||
}
|
||||
|
||||
return parent::getTemplate();
|
||||
}
|
||||
|
||||
private function getSteps(): array
|
||||
{
|
||||
return [
|
||||
'login' => [
|
||||
'title' => translate('step_login', 'reclamations'),
|
||||
'descr' => translate('step_login_descr', 'reclamations'),
|
||||
],
|
||||
'products' => [
|
||||
'title' => translate('step_products', 'reclamations'),
|
||||
'descr' => translate('step_products_descr', 'reclamations'),
|
||||
],
|
||||
'summary' => [
|
||||
'title' => translate('step_summary', 'reclamations'),
|
||||
'descr' => translate('step_summary_descr', 'reclamations'),
|
||||
],
|
||||
'success' => [
|
||||
'title' => translate('step_success', 'reclamations'),
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
public function getStep(): string
|
||||
{
|
||||
return $this->step;
|
||||
}
|
||||
|
||||
private function getActiveStep(): array
|
||||
{
|
||||
return $this->steps[$this->getStep()];
|
||||
}
|
||||
|
||||
private function getPager(): \Pager
|
||||
{
|
||||
return $this->pager;
|
||||
}
|
||||
|
||||
private function setPager(\Pager $pager): void
|
||||
{
|
||||
$this->pager = $pager;
|
||||
}
|
||||
|
||||
public function setFilter(array $filter): void
|
||||
{
|
||||
$this->filter = $filter;
|
||||
}
|
||||
}
|
||||
89
bundles/KupShop/ReclamationsBundle/View/ReclamationView.php
Normal file
89
bundles/KupShop/ReclamationsBundle/View/ReclamationView.php
Normal file
@@ -0,0 +1,89 @@
|
||||
<?php
|
||||
|
||||
namespace KupShop\ReclamationsBundle\View;
|
||||
|
||||
use KupShop\ReclamationsBundle\Util\ReclamationsUtil;
|
||||
use KupShop\ReturnsBundle\View\ReturnsReclamationsView;
|
||||
use Symfony\Component\HttpFoundation\RequestStack;
|
||||
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
||||
|
||||
class ReclamationView extends ReturnsReclamationsView
|
||||
{
|
||||
protected static $type = 'reclamations';
|
||||
|
||||
protected $template = 'reclamations/reclamation.tpl';
|
||||
protected string $smartyFallback = 'account';
|
||||
protected string $entrypoint = 'account';
|
||||
|
||||
private $reclamationId;
|
||||
private $reclamations;
|
||||
|
||||
private $reclamation;
|
||||
private $requestStack;
|
||||
|
||||
public function __construct(ReclamationsUtil $reclamationsUtil, RequestStack $requestStack)
|
||||
{
|
||||
$this->reclamations = $reclamationsUtil;
|
||||
$this->requestStack = $requestStack;
|
||||
}
|
||||
|
||||
public function getBodyVariables()
|
||||
{
|
||||
$vars = parent::getBodyVariables();
|
||||
|
||||
$dbcfg = \Settings::getDefault();
|
||||
|
||||
$reclamation = $this->getReclamation();
|
||||
if (!$reclamation) {
|
||||
throw new NotFoundHttpException('Reclamation not found');
|
||||
}
|
||||
|
||||
$vars['reclamation'] = $reclamation;
|
||||
$vars['text'] = !empty($dbcfg->reclamations['descr']) ? replacePlaceholders($dbcfg->reclamations['descr'], [
|
||||
'KOD_REKLAMACE' => $vars['reclamation']['code'],
|
||||
'ODKAZ_PDF' => path('kupshop_reclamations_reclamations_reclamationattachment', ['id' => $reclamation->getId()]),
|
||||
'PACKAGE_LABEL' => $this->reclamations->getAuthCode($reclamation->getId()),
|
||||
]) : '';
|
||||
|
||||
return $vars;
|
||||
}
|
||||
|
||||
public function getReclamation()
|
||||
{
|
||||
if (!$this->reclamation) {
|
||||
$cf = $this->requestStack->getMainRequest()->get('cf');
|
||||
if (!($this->reclamation = $this->reclamations->getReclamation($this->reclamationId, $cf != $this->reclamations->getSecurityCode($this->reclamationId)))) {
|
||||
throw new NotFoundHttpException('Reclamation not found');
|
||||
}
|
||||
}
|
||||
|
||||
return $this->reclamation;
|
||||
}
|
||||
|
||||
public function setReclamationId(int $reclamationId)
|
||||
{
|
||||
$this->reclamationId = $reclamationId;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getBreadcrumbs()
|
||||
{
|
||||
return getReturnNavigation(-1, 'RECLAMATION', [$this->getTitle()]);
|
||||
}
|
||||
|
||||
public function getTitle()
|
||||
{
|
||||
return translate('reclamation_title', 'reclamations').': '.$this->getReclamation()->getCode();
|
||||
}
|
||||
|
||||
public function getWpjToolbar()
|
||||
{
|
||||
$arr = [
|
||||
'url' => getAdminUrl('Reclamations', ['ID' => $this->reclamationId]),
|
||||
'title' => 'Upravit',
|
||||
];
|
||||
|
||||
return array_merge(parent::getWpjToolbar(), $arr);
|
||||
}
|
||||
}
|
||||
77
bundles/KupShop/ReclamationsBundle/View/ReclamationsView.php
Normal file
77
bundles/KupShop/ReclamationsBundle/View/ReclamationsView.php
Normal file
@@ -0,0 +1,77 @@
|
||||
<?php
|
||||
|
||||
namespace KupShop\ReclamationsBundle\View;
|
||||
|
||||
use KupShop\KupShopBundle\Exception\RedirectException;
|
||||
use KupShop\ReclamationsBundle\Query\Reclamations;
|
||||
use KupShop\ReclamationsBundle\Util\ReclamationsUtil;
|
||||
use KupShop\ReturnsBundle\View\ReturnsReclamationsView;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
|
||||
class ReclamationsView extends ReturnsReclamationsView
|
||||
{
|
||||
protected static $type = 'reclamations';
|
||||
|
||||
protected $template = 'reclamations/reclamations.tpl';
|
||||
|
||||
protected string $smartyFallback = 'account';
|
||||
protected string $entrypoint = 'account';
|
||||
|
||||
private $reclamations;
|
||||
|
||||
public function __construct(ReclamationsUtil $reclamationsUtil)
|
||||
{
|
||||
$this->reclamations = $reclamationsUtil;
|
||||
}
|
||||
|
||||
public function getResponse(?Request $request = null)
|
||||
{
|
||||
if (!$this->userContext->getActive() && !$this->session->get('active_order')) {
|
||||
throw new RedirectException(path('kupshop_reclamations_reclamations_createreclamationlogin'));
|
||||
}
|
||||
|
||||
return parent::getResponse($request);
|
||||
}
|
||||
|
||||
public function getBodyVariables()
|
||||
{
|
||||
$vars = parent::getBodyVariables();
|
||||
|
||||
$vars['reclamations'] = $this->getReclamations();
|
||||
$vars['accepted_statuses'] = $this->reclamations->getAcceptedStatuses();
|
||||
$vars['handle_statuses'] = $this->reclamations->getHandleStatuses();
|
||||
|
||||
return $vars;
|
||||
}
|
||||
|
||||
private function getReclamations()
|
||||
{
|
||||
$reclamations = sqlQueryBuilder()->select('r.*, o.order_no')
|
||||
->from('reclamations', 'r')
|
||||
->andWhere(Reclamations::joinOrders())
|
||||
->andWhere($this->reclamations->getOrdersSpec())
|
||||
->orderBy('r.id', 'DESC')
|
||||
->groupBy('r.id');
|
||||
|
||||
$statuses = $this->reclamations->getStatuses();
|
||||
|
||||
$result = [];
|
||||
foreach ($reclamations->execute() as $reclamation) {
|
||||
$reclamation['status_name'] = $statuses[$reclamation['status']];
|
||||
$reclamation['item'] = $this->reclamations->getReclamationItem($reclamation['id']);
|
||||
$result[] = $reclamation;
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
public function getBreadcrumbs()
|
||||
{
|
||||
return getReturnNavigation(-1, 'RECLAMATION');
|
||||
}
|
||||
|
||||
public function getTitle()
|
||||
{
|
||||
return translate('reclamations', 'reclamations');
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user