![Корзина покупателя GAS](https://habrastorage.org/files/be5/0fc/2b8/be50fc2b89204158ac1b28eb57c64fb1.png)
Началось все с того, что цена импортируемых товаров в России неуклонно росла вверх. Работая IT-специалистом в крупной ритейл-сети, у меня возникла идея о том, как можно воспользоваться преимуществом наличия доступа к товарной базе, не нарушая установленных правил компании и тем более закона. Наибольший интерес с точки зрения экономии личных денежных средств представляют так называемые «промоакции» (тарифы со скидкой). Необходимо было организовать ежедневную выгрузку «промоакций» на интересующие товары и реализовать возможность своевременного получения уведомлений о наличии скидок на Android-смартфон.
Очевидно, что существует множество вариантов реализации необходимого функционала. Рассматривались варианты создания консольного приложения на любом языке (например Java), выполняющего подключение к базе данных и дальнейшую отправку SMS через HTTP API любого из существующих бесплатных сервисов рассылки. Однако, мне хотелось по максимуму использовать уже имеющиеся инструменты, в том числе корпоративный сервис от Google (Почта, Диск, Календарь и т.д.).
Для достижения желаемого результата необходимо было решить следующие задачи:
- Выгрузить данные о промоакциях в файл;
- Обработать файл, добавить событие в Google Календарь и настроить SMS-оповещение;
- Запланировать выполнение задач на ежедневное автоматическое выполнение.
Chapter 1. SQLless
Есть цель, есть дистанция. Остальное — детали.
Первый пункт сводится к написанию не сложного SQL-запроса, который выгружает актуальные на день промоакции для обозначенного в запросе списка товаров. Чтобы максимально упростить данный этап и не писать ни строчки кода, было решено использовать «родные» утилиты для работы с БД от производителя.Поддержка выгрузки в CSV присутствует «из коробки», что полностью отвечает требованиям к поставленной задаче. Достаточно было составить корректный SQL-запрос и создать на его основе конфигурационный файл для утилиты выгрузки из базы данных. В результате мы имеем конфигурационный файл, при запуске которого получаем на выходе готовый CSV-файл с актуальными на день промоакциями.
Chapter 2. Fifty shades of GAS
Основной задачей на этом этапе являлось добавление информацию из CSV-файла в Google Календарь. Google Apps Script (GAS) предоставляет доступ к API множества сервисов Google (Диск, Почта, Календарь, Документы и др.) с помощью языка, базирующегося на JavaScript. Таким образом, вы можете например автоматизировать ежедневную отправку каких-либо логов или других файлов с вашего Google Диск на Google Почта. Это всего лишь один из множества возможных примеров использования.
Я не люблю искать сложных путей, поэтому CSV-файл при выгрузке мы будем сохранять прямо в синхронизированной на компьютере папке Google Drive. Благодаря этому изящному решению, файл практически сразу после сохранения доступен нам из GAS. Остается прочитать файл, добавить событие в Google Календарь и включить для него SMS-уведомление.
Я напишу ровно 30 строк кода. Считайте вслух...
function addTarifsFromCSVtoCalendar() {
var csvFiles = DriveApp.getFilesByName("TarifNotifier.csv");
if(csvFiles.hasNext()) {
var csvFile = csvFiles.next();
var lastModDate = csvFile.getLastUpdated();
var currentDate = new Date();
lastModDate.setHours(0,0,0,0);
currentDate.setHours(0,0,0,0);
if (lastModDate.getTime() == currentDate.getTime()) {
var csvData = csvFile.getBlob().getDataAsString("windows-1251");
var csv2DArray = Utilities.parseCsv(csvData, ',');
var calendars = CalendarApp.getCalendarsByName("Скидки");
if(calendars.length == 0) {
var calendar = CalendarApp.createCalendar("Скидки");
} else
var calendar = calendars[0];
var events = calendar.getEventsForDay(currentDate);
for (var i=0; i<events.length; i++) events[i].deleteEvent();
startTime = new Date();
endTime = new Date();
startTime.setHours(09,30,0,0);
endTime.setHours(22,0,0,0);
for (var i=0; i<csv2DArray.length; i++) {
var event = calendar.createEvent(csv2DArray[i][0] + ' - ' + csv2DArray[i][1], startTime, endTime);
event.setDescription(csv2DArray[i]);
event.addSmsReminder(30);
}
} else Logger.log("No updated data!");
}
}
Итак, разберем, что же это за код и как он работает:
var csvFiles = DriveApp.getFilesByName("TarifNotifier.csv");
if(csvFiles.hasNext()) {
var csvFile = csvFiles.next();
...
}
Обращаемся через API Google Drive к файлу с именем TarifNotifier.csv. Поскольку в различных директориях могут храниться файлы с одинаковым именем, переменной csvFiles будет передана ссылка на массив всех файлов с именем TarifNotifier.csv. Но мы-то знаем, что у нас только один файл с таким именем, поэтому просто обращаемся к самому первому элементу из массива при его наличии.
var lastModDate = csvFile.getLastUpdated();
var currentDate = new Date();
lastModDate.setHours(0,0,0,0);
currentDate.setHours(0,0,0,0);
if (lastModDate.getTime() == currentDate.getTime()) {
...
}
Проверяем дату последнего обновления CSV-файл и сверяем ее с текущей датой. Метод setHours(0,0,0,0) используется для обнуления времени в переменных, что позволит нам учитывать при сравнении только дату. Промоакции изменяются только 1 раз в день, поэтому если CSV-файл не был обновлен «сегодня», то это означает что новых интересующих нас промоакций в магазине не появилось.
var csvData = csvFile.getBlob().getDataAsString("windows-1251");
var csv2DArray = Utilities.parseCsv(csvData, ',');
Считываем данные из CSV-файла и разбираем их в двумерный массив. Это нам понадобится для того, чтобы выводить каждый товар отдельным событием в календаре.
var calendars = CalendarApp.getCalendarsByName("Скидки");
if(calendars.length == 0) {
var calendar = CalendarApp.createCalendar("Скидки");
} else
var calendar = calendars[0];
var events = calendar.getEventsForDay(currentDate);
for (var i=0; i<events.length; i++) events[i].deleteEvent();
Проверяем наличие календаря с именем «Скидки» и если он не существует, то создаем новый. Опять же, поскольку календарей с одинаковым именем может быть несколько, то в переменную calendars будет передана ссылка на массив. Мы же уже обусловливались, что календарь с именем «Скидки» у нас один? Так вот, он один. На случай если скрипт уже был запущен ранее в этот день, очищаем календарь от всех событий за текущий день, чтобы избежать дублирования.
startTime = new Date();
startTime.setHours(09,30,0,0);
endTime = new Date();
endTime.setHours(22,0,0,0);
for (var i=0; i<csv2DArray.length; i++) {
var event = calendar.createEvent(csv2DArray[i][0] + ' - ' + csv2DArray[i][1], startTime, endTime);
event.setDescription(csv2DArray[i]);
event.addSmsReminder(30);
}
Собственно то, ради чего все и начиналось. Для каждой строки CSV-файла (для каждого товара) создаем новое событие в календаре с 09:30 до 22:00 (время работы магазина) и устанавливаем для него SMS-уведомление, которое должно срабатывать ровно за 30 минут до начала события.
Chapter 3. Schedueler's list
Этот список — само добро. Этот список — сама жизнь. А по краям его — сплошная пропасть.
Для получения желаемого результата, осталась самая малость — запланировать задачи на ежедневное выполнение:
- Планируем ежедневный запуск выгрузки CSV-файла на Google Диск в 07:30 через Windows Task Scheduler;
- Воспользуемся встроенным в Google Apps Script планировщиком «Триггеры проекта», чтобы настроить ежедневный запуск нашей функции addTarifsFromCSVtoCalendar() с 08:00 до 09:00 (Google не позволяет указать точное время запуска).
В результате информация о свежих промо-тарифах ежедневно обновляется в календаре Android-телефона к 9 утра. В это же время на телефон, привязанный к учетной записи Google, приходит SMS-уведомление.
Кризис и санкции теперь не так страшны!
При наличии вашего интереса к данной теме, в следующих статьях могу поделиться другими примерами использования Google Apps Script:
- Как работать с Google Почта при помощи GAS?
- Перенос графика работы сотрудников из Excel в Google Календарь.
Ссылки
- Документация по API Google Calendar: developers.google.com/apps-script/reference/calendar
- Документация по API Google Drive: developers.google.com/apps-script/reference/drive