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)." {$code}"); $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); }; } }