Скидка на количество для Розницы 2.2




Принцип обмена данными из 1С с сайтом (на MySQL) и выдачи (публикации) этих данных по запросу.
PHP-Скрипт автоматической загрузки данных из файла данных в формате CSV в базу данных сайта работающего на WordPress.

В продолжение моей темы: 1С:Альфа-Авто Автосалон Автосервис: обмен с сайтом.
С помощью данного скрипта можно загружать в автоматическом режиме, по расписанию, данные сервисных книжек (ремонтов авто) из 1С:Альфа-Авто Автосалон Автосервис.
Также можно загружать данные в ручном режиме: для этого делается скрытая страница, где размещается специальная кнопка.
Комментарии размещенные внутри скрипта разъяснят логику и порядок действия.
Комментарии с "/////    echo" использовались для отладки.
Дополнительно создана таблица для журналирования результатов загрузки данных.
Скрипт включает в себя защиту от SQL инъекций (думаю безопасность соблюдена в полной мере).
В кратце:
1. Пишется скрипт, который запускает этот.
2. Создается регламентное задание в WordPress, по которому запускается скрипт из п.1. 
3. Этот скрипт осуществляет проверку на существование файла обмена в папке.
4. Если данные не новые, загрузка не производится.
5. Если данные новые, очищается таблица сервисных книжек.
6. Загружаются новые данные.

Собственно сам скрипт:

<?php // Полная загрузка сервисных книжек, создан 2024-01-05 12:44:55

global $wpdb2;
global $failure;
global $file_hist;

/////  echo '<H2><b>Старт загрузки</b></H2><br>';

$failure=FALSE;
//подключаемся к базе
$wpdb2 = include_once 'connection.php'; ; // подключаемся к MySQL
// если не удалось подключиться, и нужно оборвать PHP с сообщением об этой ошибке
if (!empty($wpdb2->error))
{
/////   echo '<H2><b>Ошибка подключения к БД, завершение.</b></H2><br>';
$failure=TRUE;
wp_die( $wpdb2->error );
}

$m_size_file=0;
$m_mtime_file=0;
$m_comment='';
/////проверка существования файлов выгрузки из 1С
////файл выгрузки сервисных книжек
$file_hist = ABSPATH.'/_1c_alfa_exchange/AA_hist.csv';
if (!file_exists($file_hist))
{
/////   echo '<H2><b>Файл обмена с сервисными книжками не существует.</b></H2><br>';
$m_comment='Файл обмена с сервисными книжками не существует';
$failure=TRUE;
}

/////инициируем таблицу лога
/////если не существует файла то возврат и ничего не делаем
if ($failure){
///включает защиту от SQL инъекций и данные можно передавать как есть, например: $_GET['foo']
/////   echo '<H2><b>Попытка вставить запись в лог таблицу</b></H2><br>';
$insert_fail_zapros=$wpdb2->insert('vin_logs', array('time_stamp'=>time(),'last_mtime_upload'=>$m_mtime_file,'last_size_upload'=>$m_size_file,'comment'=>$m_comment));
wp_die();
/////    echo '<H2><b>Возврат в начало.</b></H2><br>';
return $failure;
}
/////проверка лога загрузки, что бы не загружать тоже самое
$masiv_data_file=stat($file_hist);   ////передаем в массив свойство файла
$m_size_file=$masiv_data_file[7];    ////получаем размер файла
$m_mtime_file=$masiv_data_file[9];   ////получаем дату модификации файла
////создаем запрос на получение последней удачной загрузки
////выбираем по штампу времени создания (редактирования) файла загрузки AA_hist.csv, $m_mtime_file

/////   echo '<H2><b>Размер файла: '.$m_size_file.'</b></H2><br>';
/////   echo '<H2><b>Штамп времени файла: '.$m_mtime_file.'</b></H2><br>';
/////   echo '<H2><b>Формирование запроса на выборку из лога</b></H2><br>';
////препарируем запрос
$text_zaprosa=$wpdb2->prepare("SELECT * FROM `vin_logs` WHERE `last_mtime_upload` = %s", $m_mtime_file);
$results=$wpdb2->get_results($text_zaprosa);

if ($results)
{   foreach ( $results as $r)
{
////если штамп времени и размер файла совпадают, возврат
if (($r->last_mtime_upload==$m_mtime_file) && ($r->last_size_upload==$m_size_file))
{////echo '<H2><b>Возврат в начало, т.к. найдена запись в логе.</b></H2><br>';
$insert_fail_zapros=$wpdb2->insert('vin_logs', array('time_stamp'=>time(),'last_mtime_upload'=>$m_mtime_file,'last_size_upload'=>$m_size_file,'comment'=>'Загрузка отменена, новых данных нет, т.к. найдена запись в логе.'));
wp_die();
return $failure;
}
}
}
////если данные новые, пишем в лог запись о начале загрузки
/////echo '<H2><b>Попытка вставить запись о начале загрузки в лог таблицу</b></H2><br>';
$insert_fail_zapros=$wpdb2->insert('vin_logs', array('time_stamp'=>time(),'last_mtime_upload'=>0, 'last_size_upload'=>$m_size_file, 'comment'=>'Начало загрузки'));

////очищаем таблицу
$clear_tbl_zap=$wpdb2->prepare("TRUNCATE TABLE %s", 'vin_history');
$clear_tbl_zap_repl=str_replace("'","`",$clear_tbl_zap);
$results=$wpdb2->query($clear_tbl_zap_repl);
/////   echo '<H2><b>Очистка таблицы сервисных книжек</b></H2><br>';
if (empty($results))
{
/////   echo '<H2><b>Ошибка очистки таблицы книжек, завершение.</b></H2><br>';
//// если очистка не удалась, возврат
$failure=TRUE;
wp_die();
return $failure;
}

////загружаем данные
$table='vin_history';         // Имя таблицы для импорта
//$file_hist Имя CSV файла, откуда берется информация     // (путь от корня web-сервера)
$delim=';';          // Разделитель полей в CSV файле
$enclosed='"';      // Кавычки для содержимого полей
$escaped='\

40 Comments

  1. psviridov

    Прошу прощения, а это точно востребованная скидка? Ни разу не видел и не реализовывал, хотя и проработал в торговле больше 10 лет. И даже не могу ее себе представить-я как покупатель выложил товары на ленту, а что потом? Говорю кассиру-вот это пусть будет первой/последней позицией в чеке (она-же берет сперва что поближе, но товар лежит некой компактной кучкой, а не строгой вереницей)? Учитывает-ли ваша обработка то, что n-ной позицией в чеке, на которую надо предоставить скидку может являться товар с фиксированной ценой или товар, на которую скидка не распространяется (акционный, например)?

    Reply
  2. fixin

    (1) показываю на пальцах.

    Допустим, покупают:

    Туфли 1000 рублей

    Ботинки 2000 рублей.

    Акция — скидка 10% на второй товар в чеке по цене.

    Соответственно скидка будет даваться на туфли, как более дешевый товар.

    Т.е. будет 100 рублей.

    все алгоритмически прозрачно и таких акций пруд пруди, обычно на обувь и вещи.

    Скидка дается на товары из сегмента, а не на все товары в чеке.

    Акционный не учитывает, это вам надо дописать, или создать сегмент без акционных товаров, если хотите. Но и так востребована.

    Reply
  3. user635667

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

    Reply
  4. fixin

    (3) я сперва тоже пробовал через типовые мудреные акции, но потом плюнул, и написал код.

    В реальном магазине (обувном) работает, так шта…

    Reply
  5. psviridov

    (2) Т.е. скидка дается не на позицию, которая стоит на n- строке по порядку, а в смысле если в чеке n-позиций, то дается на самое дешевое (т.е. скидка на длину чека)?

    Reply
  6. fixin

    (5) ну не знаю что вы подразумеваете под длиной чека. По-моему в примере все ясно написано.

    Часто такая скидка дается в обувных и одежных — скидка на вторую, третью и далее пару. Причем первой считается самая дорогая.

    Reply
  7. Davlad_A

    Сережа, можно подробнее:

    -поле «Количество товаров 2» используется альтернативно с «Количество товаров 1» или одновременно (если 2-е, при какой прикладной логике);

    -опция «Точное количество» за что отвечает?

    — последняя опция «При наличии товара из сегмента в чеке» — содержит скидку, кот. надо предварительно создать в справочнике? А значение скидки тогда берется из этого элемента или из «Процент скидки», не совсем ясно.

    Спасибо.

    Reply
  8. fixin

    (7) Количество 1 и Количество 2 — это пороги.

    Можно указать количество 1 = 1, количество 2 = 3, тогда за 1 и 2-ю пару будет процент 1, а за 3ю, 4ю и т.д — процент 2. Если не указывать количество 2 (ноль), то только первый порог используется.

    Точное количество — обозначает, что не количество1 (количество2) и выше, а именно на такое количество. Т.е. в прошлом примере действует на 1-ю пару и третью. На вторую скидки нет.

    Последняя опция обозначает наличие определенного товара-маркера в чеке, который будет активизировать скидку. Например, скидка дается только при наличии в чеке купона (у нас была такая услуга за 1 копейку)…

    Эти купоны добавлялись в сегмент «Купоны».

    Всё из практики.

    Reply
  9. Davlad_A

    Отлично, теперь все понятно.

    Спасибо, хорошая вещь!

    Reply
  10. fixin

    (9) да, эта разработка закрывает определенное белое пятно. Ведь такие акции не редкость, а инструмента для их проведения в 1с не было.

    Я закрыл этот пробел, буду рад, если кому пригодится.

    Reply
  11. annach-83@mail.ru

    Добры день. Подскажите, пжл, а как сделать скидку на третий товар? Например: на 1-й — 20%, на второй — 30%, на третий — 40%

    Reply
  12. fixin

    (11) тут только два порога.

    Могу доработать третий за 1000, предоплата. Или сами допишите по аналогии

    Reply
  13. qsanatoly

    Сергей, скажите, а действует ли данная обработка, если в чеке 4 товара и на 2 из них (самых дешевых) необходима скидка. Не пойму как настроить в этом случае: если в чеке больше двух товаров, а скидку необходимо на каждый второй более дешевый?

    Reply
  14. fixin

    (13) поставьте первый порог на количество = 1 и второй порог на количество = 2. Т.е. ставьте галочку «Точное количество». Тогда на 3-й и 4-й товар и т.п. скидки не будет. Процент скидки соответственно ставьте одинаковым.

    Reply
  15. d.tohmahov

    Именно то что я и искал, подскажите, работает из РМК ?

    Reply
  16. fixin

    (15) да, все такие внешние обработки работают из рмк

    Reply
  17. Dilovar9

    Нашел ошибку. Если кол. товара в строке больше чем 1, то тогда считается неверно. Исправить можно так.

    СуммаСкидки = Окр(КоличествоСкидки * ТоварСегмента.Цена * ПроцентСкидки / 100, ОкруглятьСуммуДо);
    
    Reply
  18. user834076

    Сергей, добрый день! А можно настроить скидку на каждый 3-ий товар независимо от количества товаров в чеке? Если да, то можете помочь ее настроить в базе за доп плату!

    Reply
  19. user896337

    Сергей, добрый день! Не корректно работает обработка.

    Мои настройки:

    — Сегмент номенклатуры выбран

    — Количество товаров1: 2

    — Процент скидки: 10

    — Количество товаров2: 0

    — Точное количество: Да

    — Сортировать вперед дешевые: Да

    — При наличии товара из сегмента в чеке Не выбран

    — Округлять сумму до: 0

    Документ чек

    1) Товар 1. Количество 1. цена 230

    2) Товар 2. Количество 1. Цена 650

    3) Товар 3. Количество 1. Цена 450. % авт 10. Сумма авт. 45

    Не работает сортировка и не работает порог.

    Для примера еще один документ чек. В этот же чек добавил еще одну позицию.

    1) Товар 1. Количество 1. цена 230. % авт 10. Сумма авт. 23

    2) Товар 2. Количество 1. Цена 650

    3) Товар 3. Количество 1. Цена 450

    4) Товар 4. Количество 1. Цена 150

    Так же не работает сортировка и не работает порог. Исправьте пожалуйста обработку

    Reply
  20. fixin

    (18) напишите мне на fixin@mail.ru я скину более актуальную версию, там 3 скидки, если вы ставите порог3 = 0, то скидка будет всегда (вроде). Но если что, смогу и допилить за символическую плату, если так не сработает.

    Reply
  21. fixin

    (19) напишите в fixin@mail.ru , пришлю последнюю версию, протестируете.

    Reply
  22. user896337

    (21) Написал

    Reply
  23. fixin

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

    все возможности апробированы на клиентах.

    Reply
  24. fixin

    выложил новую версию. читайте UPD к статье (внизу)

    Reply
  25. STnmsk

    Добрый день!

    При вот таких настройках https://yadi.sk/i/8rv7kiIvuadx4w скидка на третий товар считается 50%, а на второй не считается совсем.

    В сегменте всего один товар.

    https://yadi.sk/i/mugQln7O4OWedw

    Reply
  26. fixin

    (25) в протоколе все правильно, похоже, что 105 и 175 не суммируются, т.к. в одной строке сразу 3 штуки товара. Видимо, ошибка, что не суммируются скидки в одну строку. Проверю, поправлю. Напишите мне на fixin@mail.ru, вышли исправление.

    И не обязательно заполнять поле «давать скидку при наличии товара в чеке». Он же у вас и так есть.

    Reply
  27. fixin

    (25) Какую версию используете?

    По скриншоту видно, что на закладке (скидки) всего одна строка, а должно быть две.

    Я воспроизвел ситуацию, в последней версии обработки все работает. Пишите в личку, вышлю версию (которая здесь последняя).

    Reply
  28. pererva98

    Добрый вечер! Не работает обработка. Пишет недействительный адрес или не найден родительский сеанс задания

    Reply
  29. fixin

    (28) нажимаете вверху справка — о программе — там «Информация для технической поддержки» и копируете оттуда.

    или пришлите мне запрос на fixin@mail.ru вышлю последнюю версию, может там это уже починено.

    Reply
  30. pererva98

    Перевыбрали заново из файла — ошибка ушла. Вроде работает. Спасибо

    Reply
  31. pererva98

    Подскажите пожалуйста, как можно сделать? Условия такие: При покупке трех товаров из сегмента, на третий по наименьшей стоимости дается скидка 50%. Это настроить получилось. Но еще должна применяться ДК, с которой скидка не должна даваться, только накопления падают с покупки этих товаров. Так вот это не получается сделать. Скидка по ДК на дешевый товар не дается, а на остальных два дается. Как ее можно убрать?

    Reply
  32. fixin

    (31) копать в группы совместного применения, хотя думаю, что в таком случае на первые два товара тоже должна начисляться скидка одна копейка, как вариант.

    Reply
  33. eugene1C

    (32) вы правы, создание корневой группы скидок с вытеснением, помещение новой скидки первой в группе с вытеснением, работает.

    Reply
  34. eugene1C

    (32) При применении в обработке надо добавлять «нулевые» записи сумм скидок даже для тех строк, для которых скидка не работает, чтобы вытеснение срабатывало.

    Reply
  35. eugene1C

    (32) Если заранее непонятно, должна ли хоть в какой то строке сработать новая скидка, то чтобы «нулевые» записи не вытеснили ошибочно остальные скидки, придется делать первый дублирующий прогон с установкой флага необходимости применить новую скидку, и запись «нулевых» записей производить по этому флагу.

    Reply
  36. pererva98

    Подскажите пожалуйста такую ситуацию как правильно настроить? При покупке 3-х вещей из сегмента, на самую дешевую 50%. При этом если в чек подбирается 4-е вещи или 5 вещей, то все равно должна даваться скидка 50% только на одну самую дешевую. А скидка перепрыгивает не на самую дешевую вещь. Как это настроить?

    Reply
  37. fixin

    (36) напишите мне Fixin@mail.ru, вышлю самую последнюю версию, там это можно настроить

    Хотя даже в таком варианте скидка должна даваться на самую маленкькую, ведь сортировка по цене идет.

    Reply
  38. LifeRock

    обработка умеет делать скидку на каждую вторую штуку по строке?

    Reply
  39. LifeRock

    точнее не так. а может ли считать только по строке а не по документу?

    Reply
  40. fixin

    (39) обратитесь ко мне за последней версией в лычку, вышлю, она умеет намного больше.

    Reply

Leave a Comment

Ваш адрес email не будет опубликован. Обязательные поля помечены *