Files
kupshop/bundles/KupShop/ReclamationsBundle/Util/ReclamationsUtil.php
2025-08-02 16:30:27 +02:00

388 lines
14 KiB
PHP

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