Files
2025-08-02 16:30:27 +02:00

541 lines
20 KiB
PHP

<?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;