Мой блог

Дублирование заказов в Simpla

К сожалению, данная CMS не имеет встроенной проверки на дублированние заказа. В одном большом интернет-магазине менеджеры часто жаловались на эту проблему.

Решения

JavaScript

Блокировать кнопку Submit формы, после первого клика.

*Результат:* дублей стало меньше, но не исчезли.

База данных

Создать метод, который будет проверять наличие заказа в БД по набору ФИО, email, адрес, телефон, время (с точностью до минуты).

Поправить файл /api/Orders.php, добавим метод:


private function check_unique_order($order)
{
    $where = $this->db->placehold('WHERE name = ?',                                        $order->name);
    $where .= $this->db->placehold('AND email = ?',                                        $order->email);
    $where .= $this->db->placehold('AND address = ?',                                    $order->address);
    $where .= $this->db->placehold('AND phone = ?',                                        $order->phone);
    $where .= $this->db->placehold('AND DATE_FORMAT(`date`, \'%Y-%m-%d %H:%i\') = ?',    date('Y-m-d H:i'));
    
    $query = $this->db->placehold("SELECT id FROM __orders  $where LIMIT 1");
    $this->db->query($query);
    
    return $this->db->result('id');
}

в этом же файле поправим метод:


public function add_order($order)
{
    $order = (object)$order;
    
    $id = $this->check_unique_order($order);
    
    if(!empty($id)) {
        return $id;
    }
...

Добавим строки в файле /view/CartView.php:


...
// Добавляем заказ в базу
$order_id = $this->orders->add_order($order);

// Побеждаем дубли
if(!empty($_SESSION['order_id']) && $_SESSION['order_id'] == $order_id) {
    header('Location: '.$this->config->root_url.'/order/');
}

$_SESSION['order_id'] = $order_id;
...

26 февраля   simpla

Задать скидку для нескольких товаров в Simpla

Интернет-магазинам требуется часто работать со скидками, делать распродажи на все товары или какой-то конкретный сегмент. В simpla можно работать с этим через csv файл, но это долго и неудобно.

Реализация скидки в админке.

В файле /simpla/ProductsAdmin.php добавим пару кейсов в switch($this->request->post(’action’)):


case 'add_discount':
{
    $discount = $this->request->post('discount', 'integer');
    
    if(!$discount) {
        break;
    }
    
    $discount = (100 - $discount) / 100;
    $query = $this->db->placehold("UPDATE __variants SET compare_price = price, price = (price * ?) WHERE product_id IN (?@) AND (compare_price IS NULL OR compare_price = 0)", $discount, $ids);
    $this->db->query($query);
    break;
}
case 'remove_discount':
{
    $query = $this->db->placehold("UPDATE __variants SET price = compare_price, compare_price = NULL WHERE product_id IN (?@) AND compare_price IS NOT NULL", $ids);
    $this->db->query($query);
    break;
}

В файле /simpla/design/html/products.tpl добавим:

<select name="action">
...
    <option value="add_discount">Задать скидку</option>
    <option value="remove_discount">Убрать скидку</option>
</select>

И поправим стили /simpla/design/css/style.css:


div#action span#move_to_page, div#action span#move_to_category, div#action span#move_to_brand, div#action span#add_discount{
    display:none;
}

2017   simpla   скидки

Тестирование дизайна в simpla

Задача

Требуется протестировать дизайн на рабочем сайте с Simpla CMS.

Решение

  • Создаете шаблон в папаке /design/
  • Добавляем в файл /api/Design.php код
// Берем тему из настроек
$theme = $this->settings->theme; // после строки добавляем

if(!empty($_GET['theme'])) {
    $theme = $_GET['theme'];
}
  • новый шаблон доступен по адресу http://{SERVER_NAME}/?theme={TEMPLATE_NAME}, где
    {SERVER_NAME} — имя домена;
    {TEMPLATE_NAME} — имя папки шаблона.
2017  

Раздел sale в simpla

Требуется создать категорию, куда будут попадать товары с скидкой.

  • создаем категорию с адресом страницы «sale»
  • в файле /view/ProductsView.php правим код:
// Выберем текущую категорию
if (!empty($category_url))
{
	$category = $this->categories->get_category((string)$category_url);
	if (empty($category) || (!$category->visible && empty($_SESSION['admin'])))
		return false;
	$this->design->assign('category', $category);
	
	if($category->url == 'sale') {
		$filter['discounted'] = 1;
	}
	else {
		$filter['category_id'] = $category->children;
	}
}
  • В файде /api/Products.php обновляем методы get_products и count_products:
public function get_products($filter = array())
{
...
$is_featured_filter = '';
$discounted_filter = '';
$in_stock_filter = '';
...
if(isset($filter['discounted']))
	$discounted_filter = $this->db->placehold('AND (SELECT 1 FROM __variants pv WHERE pv.product_id=p.id AND pv.compare_price>0 LIMIT 1) = ?', intval($filter['discounted']));
...
$query = "SELECT 
...
WHERE
...
$discounted_filter
...
";
...
}
public function count_products($filter = array())
{
...
$is_featured_filter = '';
$discounted_filter = '';
$in_stock_filter = '';
...
if(isset($filter['discounted']))
	$discounted_filter = $this->db->placehold('AND (SELECT 1 FROM __variants pv WHERE pv.product_id=p.id AND pv.compare_price>0 LIMIT 1) = ?', intval($filter['discounted']));
...
$query = "SELECT 
...
WHERE
...
$discounted_filter
...
";
...
}
2016  

Перевод письма в html

Требуется получить корректный html письма для внедрения его на сайте.

  • создал письмо с помощью конструктора писем, на сервисе email-рассылок;
  • отправил тестовое письмо на свой почтовый ящик @gmail.com;
  • скопировал исходный код письма из gmail;
  • убрал «=» из кода в Sublime (заменил символ (\=$\s) на пустоту);
  • декодировал Quoted-printable с помощью сервиса.
2016  

Хочу html страницы из sketch

Решил провести тест сервисов/студий, которые переводят sketch файлы в html.

В моём случае, это 3 страницы: главная, результат поиска+форма поиска, карточка детально.

Макеты есть под следующие разрешения: 1280, 1024, 768, 320 пикселей.

Победитель назначил цену = X. Срок реализации 10 рыбочих дней.

Список участников:

  1. http://topfloat.ru
  2. http://csssr.ru
  3. http://coderiver.com.ua
  4. https://www.psd2html.com
  5. https://thesiteslinger.com
  6. https://www.xfive.co
  7. http://www.htmlpanda.com

Отклик на заявку

http://topfloat.ru

Время: без оценки. С ребятами мы уже делали проект, потому отклик на заявку был моментальным.
Вопросы по заявке: данная компания умеет декомпозировать задачи любых объемов и вникать в суть проекта, поэтому задачи выполняются в срок

http://csssr.ru

Время: 30 минут.
Вопросы по заявке: вопросы по делу.

http://coderiver.com.ua

Время: 4 часа 30 минут.
Вопросы по заявке: без уточнений, выдали сразу расчет.

https://thesiteslinger.com

Время: 1 часа 20 минут. На сайте интересно построено взаимодействие, для заказчика заводится профиль и ведется общение через внутреннюю переписку.
Вопросы по заявке: сначала общается менеджер по заявке, после идет уточнение у разработчиков.

https://www.xfive.co

Время: 12 часов.
Вопросы по заявке: вопросы были направлены на проект, ожидаемый результат, технические решения, предложения по дополнительным работам.

https://www.psd2html.com

Время: сошли с дистанции

http://www.htmlpanda.com

Время: сошли с дистанции

Цена, сроки

https://www.xfive.co

Спустя 4 часа, с момента последнего письма, получит расчет. В расчете описан рабочий процесс от общения с менеджером до реализации макетов. Отдельно описаны доп работы по проекту, сроки, когда команда может приступить к реализации, срок действия гарантии.
Цена: X
Время: 38 hours

http://topfloat.ru

Через 2 дня я получил декомпозированный проект, с минимальным шагом в 1 час работ.
Цена: 1.28 * X
Время: 114 часов

http://coderiver.com.ua

Цена: 0.25 * X
Время: 40 часов

http://csssr.ru

Итоговое письмо содержало странные фразы «Комфортный для нас срок...», «стоимость будет варьироваться в пределе...».
В вопросе технологий предлагаю выступить по классике и без необходимости не прибегать к использованию фреймворков.
Цена: 3.8 * X
Время: 15 дней

https://thesiteslinger.com

Через день я получил стоимость верстки каждого экрана.
Цена: 1.50 * X
Время: 10 рабочих дней

2016  

sitemap для Эгеи

Решил ковырнуть движок, написать компактно и вот что у меня получилось:

<?
require 'system/core.php';

$domain = d83c8('e2m_frontpage'); // в функции есть строка if (@$_config['preferred_domain_name'] and $_SERVER['HTTP_HOST'] != $_config['preferred_domain_name']) {
$dir = 'blog'; // Если блог находится в папке

if (r0f7c()) { // в функции есть строка global $settings, $_db, $_db_error;
	$xml = '<?xml version="1.0" encoding="UTF-8"?>';
	$xml .= '<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">';

	$xml .= "
	<url>
	        <loc>$domain</loc>
	        <priority>1.0</priority>
	</url>\n";

	$result = mysql_query("SELECT OriginalAlias, LastModified FROM `e2_Notes` WHERE
								IsPublished = 1
								AND IsIssue = 0
								AND isvisible = 1");
	while ($data = mysql_fetch_array($result)) {
		$page = d83c8('e2m_note', array('alias' => $data['OriginalAlias']));
		$xml .= "
	<url>
	        <loc>".str_replace('?go=', $dir.'/', $page)."</loc>
	        <priority>0.5</priority>
	        <lastmod>".date('Y-m-d', $data['LastModified'])."</lastmod>
	</url>\n";
	}
	$xml .= "
	</urlset>";
	$fp = fopen(ROOT_FOLDER.'sitemap.xml', 'w'); // здесь укажите свой путь к файлу sitemap.xml
	fwrite($fp, $xml);
	fclose($fp);
}

добавить задание cron.

2016  

Simpla vs. WebAsyst

Очень долго у Simpla CMS не было равных по юзабилити, простоте интеграции и бизнес-процессу выстроенному в бэкофисе.

Недавно услышал про WebAsyst и их модуле интернет-магазина. Демо режим данной CMS мне понравился, ребята проделали большой объем работ и им удалось не только повторить функционал Simpla, но и сделать несколько хороших доработок.

Появился клиент с которым захотел попробовать WebAsyst. Последовательность стандартная:

  1. определяем функционал
  2. выбираем шаблон
  3. интегрируем

Послевкусие

  • Наличие у WebAsyst готовых решений, сильно упрощает задачу по доработке нового функционала, часто он уже есть и стоит вменяемых денег.
  • Если вы приобретаете шаблон не у WebAsyst, вас жду сюрпризы. Дело в том, что не все элементы страницы имеют tpl файлы. Например, страница оформление заказа спрятана очень глубоко и править ей придется дописывая CSS классы под уже имеющуюся форму.
  • Если попытаешься засучить рукава и «быстро поправить», знай, все будет очень не просто, придется долго читать мануалы и копаться в структуре, чтобы добраться до нужного куска кода.
  • Ответы в комьюнити часто упираются в то, что так делать нельзя. Просто потому что реализация глубоко закопана и это не предусмотрели для модификации. С одной стороны это защищает код от кривых рук, с другой стороны нельзя немного допилить систему под свои задачи.
  • Наличие документации упрощает время погружения в систему.
2016  

Доработка раздела пользователей в Simpla

Когда постоянных покупателей становится много, появляется задача по их сегментации.

В моём случае потребовалось:

  • отобразить сумму покупок
  • реализовать сортировку по сумме покупок

/api/Users.php

switch ($filter['sort'])
{
    ...
    case 'top_price':
        $order = 'o.total_price DESC';
        break;
}
...
$query = $this->db->placehold("SELECT
    u.id, u.email, u.name, u.password, u.address, u.phone, u.group_id, u.enabled, u.last_ip, u.created, g.discount, g.name as group_name, o.total_price FROM __users u
    LEFT JOIN __groups g ON u.group_id=g.id 
    LEFT JOIN (SELECT
                SUM(total_price) total_price, user_id FROM __orders
                WHERE paid = 1 AND closed = 1 AND user_id <> 0 group by user_id) o
    ON o.user_id = u.id
    WHERE 1 $group_id_filter $keyword_filter $name_empty_filter ORDER BY $order $sql_limit");

/simpla/design/html/users.tpl

{if $sort!='name'}<a href="{url sort=name}">имени</a>{else}имени{/if} или
{if $sort!='top_price'}<a href="{url sort=top_price}">сумме покупок</a>{else}сумме покупок{/if} или
...
<div class="price cell">
    {if $user->total_price}{$user->total_price} {$currency->sign}{/if}
</div>
<div class="user_group cell">
    {$groups[$user->group_id]->name}
</div>

/simpla/design/css/style.css

#list .user_group {
    width:150px;
    text-align: right;
    color: #707070;
}
#list .price {
    width:65px;
    text-align: left;
    color: #707070;
}
2016  

Импорт товаров в Simpla, загрузка фото по url

Потребовалось реализовать загрузку фото товаров, если указана прямая ссылка на источник.

Как мы знаем, при импорте можно указать фото товара через запятую в поле images или изображения.

Добавим метод в /api/Image.php

public function download_image_from_site($url, $type = 'copy') {
    if(strpos($url, 'http://') === false)
        return false;
    
    if($type == 'copy') {
        $name = $this->correct_filename(pathinfo($url, PATHINFO_BASENAME));
        $base = pathinfo($url, PATHINFO_FILENAME);
        $ext = pathinfo($url, PATHINFO_EXTENSION);
        
        if(in_array(strtolower($ext), $this->allowed_extentions))
        {
            while(file_exists($this->config->root_dir.$this->config->original_images_dir.$name))
            {    
                $name = pathinfo($name, PATHINFO_FILENAME);
                if(preg_match('/_([0-9]+)$/', $name, $parts))
                    $name = $base.'_'.($parts[1]+1).'.'.$ext;
                else
                    $name = $base.'_1.'.$ext;
            }
            if(copy($url, $this->config->root_dir.$this->config->original_images_dir.$name))
                return $name;
        }
        return false;
    }

    return false;
}

Добавим данный метод в /simpla/ajax/import.php. Добавим код

if(strpos($image, 'http://') !== false) {
    $image = $this->image->download_image_from_site($image);
}

// Имя файла
$image_filename = pathinfo($image, PATHINFO_BASENAME);
2016  
Ctrl + ↓ Ранее