Сертификация Marketplace-приложения

Легкий

Сертификация Marketplace-приложений — программа, в рамках которой вендор платформы Creatio сертифицирует опубликованные Marketplace-приложения. Сертификация гарантирует, что Marketplace-приложение рекомендовано к использованию, соответствует высоким стандартам качества и получает достаточный уровень удовлетворенности пользователей. Условия и процесс сертификации Marketplace-приложений описаны в регламенте процесса сертификации решений.

Характеристики сертифицированных Marketplace-приложений представлены в таблице ниже.

Характеристики сертифицированных Marketplace-приложений
Характеристика
Описание
Бейдж сертифицированного Marketplace-приложения Для Marketplace-приложений, которые прошли сертификацию, на Creatio Marketplace отображается бейдж Certified ("Application is certified by Creatio experts").
Активные экспертные продажи сертифицированного Marketplace-приложения Информация о сертифицированных Marketplace-приложениях включается в стандартные коммерческие материалы экспертов нашей компании в партнерской сети. Возможности сертифицированных приложений включаются в программу экзамена для менеджеров по продажам. Сертифицированные Marketplace-приложения рекомендуются к активной продаже, т. е. активно предлагаются клиентам.
Обзор качества сертифицированного Marketplace-приложения Все сертифицированные Marketplace-приложения проходят обзор экспертами нашей компании и получают рекомендации по исправлению ошибок и улучшению приложений.
Инструменты для поддержки сертифицированного Marketplace-приложения Для помощи партнеру в поддержке сертифицированного Marketplace-приложения наша компания предоставляет возможность регистрации обращений через партнерский портал, а также схему эскалации обращений с участием службы поддержки компании.

Этапы сертификации Marketplace-приложений 

Этапы сертификации Marketplace-приложений представлены в таблице ниже.

Этапы сертификации Marketplace-приложений
Этап
Ответственный
Описание
1. Отправка заявки на сертификацию Marketplace-приложения
Разработчик Marketplace-приложения
Выполняется после публикации Marketplace-приложения в личном кабинете разработчика. Подробнее читайте в статье Публикация Marketplace-приложения.
2. Утверждение заявки на сертификацию Marketplace-приложения
Служба поддержки Marketplace
Анализ приоритета заявки на сертификацию Marketplace-приложения.
3. Сертификация качества Marketplace-приложения
Разработчик Marketplace-приложения
Предоставление материалов для сертификации Marketplace-приложения.
Служба поддержки Marketplace
Проверка Definition of Done (DoD) Marketplace-приложения.
4. Сертификация поддержки Marketplace-приложения
Служба поддержки Marketplace
Перевод поддержки Marketplace-приложения на портал Creatio.
Отправка уведомления о внедрении стандартов поддержки Marketplace-приложения.
Аудит поддержки Marketplace-приложения.
5. Регулярный аудит Marketplace-приложения
Служба поддержки Marketplace
Оценка удовлетворенности Marketplace-приложений (NPS).
Оценка удовлетворенности решением обращений.
Анализ эскалаций по обращениям.
Аудит поддержки Marketplace-приложения.

Этапы сертификации Marketplace-приложений описаны в регламенте процесса сертификации решений.

При публикации обновления ранее сертифицированного Marketplace-приложения выполняется ресертификация. Этапы ресертификации соответствуют этапам сертификации.

Критерии обзора кода Marketplace-приложения 

Критерии обзора кода Marketplace-приложения представлены в таблице ниже.

Критерии обзора кода Marketplace-приложения
Критерий
Реализация
Бесшовное обновление
При разработке Marketplace-приложения расширяйте, а не замещайте базовую функциональность приложения. В схемах замещающих конфигурационных элементов при переопределении (override) неабстрактных классов вызывайте базовые методы. Подробнее читайте в статье Замещение конфигурационных элементов.
Взаимодействие с данными реализуйте через ORM-модель и прямой доступ к данным, а не через схемы конфигурационных элементов типа SQL сценарий (SQL script).
Производительность
Учитывайте, что количество объектов в оперативной памяти и количество потоков ограничено и не зависит от количества пользователей или объема СУБД (постраничность и буферизация).
Если для продолжения работы нет необходимости получить результат выполнения операций обработки, то реализуйте их выполнение в фоновом режиме. Подробнее читайте в статье Фоновое выполнение операций.
Интеграции
Организуйте систему защиты Marketplace-приложения от массовых входящих запросов внешних систем. Для этого используйте легковесные шлюзы или очереди.
Если недоступен внешний сервис, то реализуйте блокировку процесса интеграции. Работа пользователя блокироваться не должна.
Если недоступен сервис Creatio, то реализуйте варианты работы логики интеграции.
Объемы данных
Реализуйте архивацию данных, которые создаются в автоматическом режиме (логирование, журналирование и т. д.).
Реализуйте ограничения пользователя при выполнении произвольных операций с большими объемами данных в таблицах базы данных. Реализуйте возможность работы с оптимизированной структурой данных, используя индексы и денормализацию.

Требования к инструкциям Marketplace-приложения 

Под инструкциями необходимо понимать инструкцию по установке и настройке Marketplace-приложения и инструкцию пользователя Marketplace-приложения.

Инструкция по установке и настройке Marketplace-приложения добавляется на вкладке Installation and setup (блок Guide поле Load guide) в личном кабинете разработчика на этапе публикации.

Информация, которую необходимо описать в инструкции по установке и настройке Marketplace-приложения:

  • Вступление — назначение Marketplace-приложения.
  • Технические требования к Marketplace-приложению.
  • Особенности установки Marketplace-приложения (перечень настроек, которые необходимо выполнить в дополнение к стандартному процессу установки).
  • Шаги настройки Marketplace-приложения для начала работы.
  • Шаги настройки по работе в Marketplace-приложении (например, настройка дополнительных возможностей, описание процессов и процедур, которые без участия пользователей выполняют обработку данных, и т. д.).

На заметку. Шаблон инструкции по установке и настройке Marketplace-приложения можно скачать по ссылке.

Информация, которую необходимо описать в инструкции пользователя Marketplace-приложения:

  • Вступление — назначение Marketplace-приложения и особенности его использования.
  • Работа пользователя (все реализованные функциональные возможности).
  • Примеры пользовательских бизнес-задач.
  • Примечания и ограничения.

Виды требований к инструкциям Marketplace-приложения:

  • Общие требования.
  • Требования к стилистике.
  • Требования к оформлению.
  • Требования к рисункам.

Общие требования к инструкциям 

Общие требования к инструкциям Marketplace-приложения:

  • Формат инструкции: *.pdf.
  • Структура файла: титульная страница, содержание и основной материал.
  • Титульная страница содержит название Marketplace-приложения и название (или логотип) компании.
  • Содержание файла сформировано с использованием стандартных средств MS Word с возможностью автоматического обновления.
  • Шаблон названия файла: "Инструкция по установке и настройке приложения %Название приложения%" и "Инструкция пользователя %Название приложения%".

Требования к стилистике инструкций 

  • Текст инструкции логично структурирован, используются заголовки, подзаголовки, маркированные и нумерованные списки, выделение полужирным (bold).
  • При описании последовательности действий используются глаголы в повелительном наклонении (например, "open", "go", "set" и т. д.).
  • Полнота описания инструкции достаточна для самостоятельного выполнения бизнес-задачи пользователем. Отсутствуют пропущенные шаги. Функциональность описана с использованием актуальных названий объектов, элементов пользовательского интерфейса и компонентов программного обеспечения.
  • Для элементов интерфейса используется терминология, которая принята в документации Creatio. Для одного и того же понятия во всей инструкции используется один и тот же термин. Используйте терминологию, которая описана в глоссарии.
  • В тексте используется длинное тире (комбинация клавиш Alt+0151). Между цифрами используется короткое соединительное тире без пробелов (комбинация клавиш Alt+0150).
  • В сокращении "etc." не используется пробел.
  • Для названий клавиш клавиатуры (например, стрелок, функциональных клавиш, клавиш смены регистра) используются заглавные буквы. Например: "Press ALT+F3". Исключениями являются описательные названия клавиш (например, "Windows").
  • Для названий элементов интерфейса используются квадратные скобки. Например: "Click [Add]", "Fill the [Name] field".
  • Используется одинаковый тип кавычек: "".

Требования к оформлению инструкций 

  • Шрифт основного текста: Verdana серого цвета (RGB 89, 89, 89).
  • Кегль основного текста (включая списки и таблицы): 10px.
  • Кегль подзаголовков: 14px.
  • Кегль заголовков: 16px.
  • Межстрочный интервал основного текста: 1.15.
  • Межстрочный интервал заголовков (в том числе заголовков таблиц): 1.5.
  • Поля страницы: 2.5 сантиметра.
  • В тексте не используются принудительные переносы.
  • Абзацы обычного текста без отступа.
  • Отступ списков первого уровня: 0.63. Отступ списков второго уровня: 1.9.
  • Текст не содержит пустых строк.
  • Рисунки и таблицы имеют сквозную нумерацию.
  • Выравнивание основного текста: по ширине.
  • Выравнивание заголовков и подзаголовков: по левому краю.
  • Для маркеров маркированных и нумерованных списков первого уровня используется голубой цвет (RGB 100, 184, 223).

Требования к рисункам инструкций 

  • Все рисунки подписаны и пронумерованы.
  • Заголовок и номер рисунка размещаются непосредственно перед рисунком.
  • Шрифт заголовка рисунка: Verdana светло-серого цвета (RGB 150, 150, 150).
  • Кегль заголовка рисунка: 8px.
  • Выравнивание заголовка рисунка: по левому краю.
  • Выравнивание рисунка: по центру.
  • Положение рисунка: в тексте.
  • Межстрочный интервал заголовка рисунка: 1.5.
  • Скриншоты сняты программой для съемки экрана (например, Snagit, Monosnap, ScreenSh3ooter и т. д.).
  • Формат рисунков: *.png или *.jpeg.
  • Допускается выделение ключевых элементов интерфейса (поля, детали, области). Для выделения используется прямоугольная рамка красного цвета толщиной 2px. Максимальное количество рамок на одном рисунке: 2. Другие способы выделения (стрелки, текст и т. д.) не используются.
  • Все рисунки упоминаются в тексте.

Требования к обучающим материалам  

Обучающие материалы по сертифицированным Marketplace-приложениям доступны в онлайн-курсе Приложения Маркетплейс на Академии.

Информация, которую необходимо предоставить партнеру для публикации на Академии обучающего модуля по Marketplace-приложению:

  • Обучающее видео.
  • Скрипт озвучки обучающего видео.
  • Обучающая статья (опционально).
  • Тестовые вопросы.
  • Практическое задание (опционально).

Пример модуля с демонстрацией работы Marketplace-приложения "Numerator for Creatio" содержится по ссылке.

Требования к обучающему видео 

Назначение обучающего видео — обучить сотрудников компании и пользователей работе с Marketplace-приложением.

Информация, которую необходимо отобразить в обучающем видео к Marketplace-приложению:

  • Назначение Marketplace-приложения.
  • Бизнес-кейсы использования Marketplace-приложению.
  • Примеры задач, которые решает Marketplace-приложение.
  • Описание работы функциональности Marketplace-приложения.

Требования к обучающему видео к Marketplace-приложению:

  • Длительность: 3–10 минут. Если длительность превышает 10 минут, то разделите видео на два отдельных видеоролика.
  • Контент: запись экрана с демонстрацией настройки и использования Marketplace-приложения для решения бизнес-задач, закадровая озвучка. Допускается использование презентационных слайдов для иллюстрации концептуальной части.

    Шаблоны слайдов можно скачать по ссылке.

  • Формат видео: *.mp4.
  • Разрешение видео: 1920x1080.
  • Текст, который появляется в кадре, отображен на языке ролика. В ролике на английском языке запрещается использовать русский текст, в том числе, в заголовках браузера или всплывающих уведомлениях.
  • Для съемки используется браузер Google Chrome со стандартной темой.
  • В кадре отсутствуют личные данные пользователя (например, сохраненные вкладки браузера, сообщения мессенджеров и т. д.). Допускается ФИО и фото автора, название компании.
  • Допускается использование подсветки кликов серым цветом.
  • Для работы с файловым менеджером используется только стандартный проводник Windows.
  • При работе с файловым менеджером в папках отсутствует содержимое, которое не относится к отображаемому кейсу.
  • Вырезаны все технологические моменты (например, переключение между окнами приложений, ошибки при вводе текста, ожидание открытия страниц, длительные страницы загрузки приложения и т. д.).
  • Для выделения ключевых элементов интерфейса (поля, детали, области) используется прямоугольная рамка красного цвета толщиной 5px или эффект затемнения остальной области.
  • Логические блоки в видео разделены заголовочными слайдами.

Требования к обучающей статье 

Назначение обучающей статьи — предоставить дополнительные материалы для изучения работы Marketplace-приложения, которые есть в свободном доступе.

В обучающей статье к Marketplace-приложению приведите вспомогательные ссылки, которые позволяют погрузиться в функциональность Marketplace-приложения.

Требования к обучающей статье к Marketplace-приложению:

  • Длительность прочтения: 1–3 минуты.
  • Формат: *.docx.
  • Объем: не более 1 страницы А4 при наборе шрифтом 14 кегля.

Требования к тестовым вопросам 

Назначение тестовых вопросов — самопроверка и закрепление знаний по пройденному материалу.

Требования к тестовым вопросам по обучающим материалам Marketplace-приложения:

  • Если модуль содержит несколько обучающих видео, то сформирован общий перечень вопросов по Marketplace-приложению.
  • Формат: *.docx. Отправляется в одном файле с практическим заданием.
  • Объем: 3–5 вопросов.
  • Длительность проходжения: 1–10 минут.
  • Все вопросы содержат варианты ответов.
  • Допускается как одиночный, так и множественный выбор.
  • Для вопросов с множественным выбором к тексту вопроса добавляется предложение "Выберите все правильные ответы".
  • Суть вопроса была раскрыта в обучающем видео. Не допускаются вопросы, суть которых не раскрыта в видео, сложные вопросы или вопросы "с подвохом".
  • Вопросы лаконичны и понятны, без двусмысленности.

Требования к практическому заданию 

Назначение практического задания — финальный самоконтроль пользователя, получение практических навыков работы с Marketplace-приложением.

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

Требования к практическому заданию к Marketplace-приложения:

  • Используется уникальный бизнес-кейс, но логика задания практически копирует материал, который рассмотрен в обучающем видео.
  • Формат: *.docx. Отправляется в одном файле с тестовыми вопросами.
  • Длительность выполнения: 15–20 минут.

Требования к демоверсии 

Softkey-данные — примеры заполнения объектов системы, которые добавляются в пакет с функциональностью Marketplace-приложения. Такие данные создаются на английском языке с добавлением суффикса (sample) в названиях записей.

Демоданные (демонстрационные записи) — примеры заполнения объектов системы, которые создаются в отдельном пакете. Этот пакет зависит от пакета с функциональностью Marketplace-приложения.

Эталонные записи — записи раздела, которые максимально заполнены демоданными. Эталонными считаются первые три записи в каждом разделе.

Назначение демоверсии — предоставить пользователям возможность увидеть результат работы Marketplace-приложения в системе.

Демоверсия Marketplace-приложения представляет собой набор демоданных. Для каждой локализации создайте отдельный пакет с демоданными.

Чтобы создать демоверсию:

  1. Разверните минимально совместимую сборку Creatio без демоданных (например, с установленным русским языком).
  2. Установите пакет с функциональностью Marketplace-приложения (например, LabReports). Для этого воспользуйтесь инструкцией, которая приведена в статье Установить приложение Marketplace.
  3. Создайте пакет с демоданными. Для этого воспользуйтесь инструкцией, которая приведена в статье Создать пользовательский пакет. Шаблон названия пакета: НазваниеПакета_Demo (например, LabReports_Demo).
  4. В зависимости пакета добавьте пакет с функциональностью Marketplace-приложения.
  5. Добавьте демоданные в разделы и справочники. Все демоданные создавайте от имени пользователя John Best (идентификатор 76929f8c-7e15-4c64-bdb0-adc62d383727). При добавлении демоданных соблюдайте требования.
  6. Настройте сортировку демонстрационных записей. Настройте сортировку таким образом, чтобы вверху реестра раздела отображались эталонные записи. Если эталонные записи не выбраны или не заполнены, то сначала выберите сортировку, а затем заполните эталонные записи. После выбора необходимой сортировки сохраните ее настройки для всех пользователей.

    1. На панели инструментов реестра раздела нажмите Вид —> Настроить колонки (View —> Select fields to display).
    2. В выпадающем меню кнопки Сохранить (Save) выберите пункт Сохранить для всех пользователей (Save for all users).

    Необходимую запись можно отыскать по значению поля Key, которое соответствует схеме с установленной сортировкой. Значение можно посмотреть в URL. Например, для раздела Договоры (Contracts) сортировка сохраняется в записи с Key=ContractSectionV2GridSettingsGridDataView. После сохранения настроек сортировки для всех пользователей значение изменяется на ContactId=NULL.

    Сортировка демоданных отменяет сортировку softkey-данных в схемах.

  7. Привяжите демоданные к пакету. Для этого воспользуйтесь инструкцией, которая приведена в статье Общие принципы работы с пакетами.
  8. Выгрузите пакет из приложения. Для этого воспользуйтесь инструкцией, которая приведена в статье Перенести пакеты.
  9. Протестируйте полноту и корректность привязанных данных.

    1. Разверните минимально совместимую сборку Creatio без демоданных.
    2. Установите пакеты с функциональностью Marketplace-приложения и с демоданными. Для этого воспользуйтесь инструкцией, которая приведена в статье Перенести пакеты.
  10. При необходимости, повторите шаги 1-9 на сборке с другой локализацией.
  11. Отправьте пакеты с демоданными службе поддержки Marketplace.

Требования к демонстрационным записям разделов:

  • Перед добавлением демонстрационных записей разделов проверьте и обновите наполнение справочников.
  • Количество записей в разделах достаточное для отображения на экране и красивой аналитики (в среднем, 20).
  • Количество записей в соответствующей таблице базы данных не превышает 1000.
  • Первые три записи в разделе — эталонные.
  • Записи содержат последовательную и непротиворечивую информацию.
  • Записи разделов не являются однотипными. Разнообразие записей отображается в группах и в аналитике.
  • Записи логически связаны с другими записями (рекомендуется наполнять «цепочками», а не по разделам).
  • Добавляются не только демонстрационные записи в разделах, но и записи в ленте, напоминания, уведомления, email-сообщения, комментарии, лайки и т. д.
  • Демоданные имеют позитивный посыл.
  • Наполнение справочников может быть softkey-данными и демоданными.
  • В справочниках запрещается дублирование записей.
  • Если в процессе добавления данных создаются активности, то проверяйте наличие записей в расписании активностей.
  • Если при наполнении демоданных необходимо отобразить аналитику в итогах, то проверяйте построение графиков в каждом разделе с учетом даты актуализации.
  • В некоторых разделах есть предустановленные фильтры по ответственному и периоду (например, Активности (Activities), Счета (Invoices)). При наполнении проверяйте, что в реестре раздела присутствуют записи, которые соответствуют условиям фильтра.
  • Чтобы информация не устаревала, в записях используется SQL-скрипт актуализации дат, который отталкивается от даты актуализации демоданных.
  • При создании демозаписей изменяйте данные. Например, если дата актуализации 11.01.2022, то при актуализации скрипт перезаписывает дату 11.01.2022 в демоданных текущей датой выполнения скрипта, дату 10.01.2022 – вчерашним днем и т. д. Запись, у которой в демоданных указана дата 11.05.2022, после сдвига дат окажется в будущем, на 4 месяца позже текущей даты выполнения SQL-скрипта.
  • Даты могут автоматически добавляться при сохранении записи. В приложении отсутствуют даты, которые противоречат логике.
SQL-cкрипт для выполнения актуализации дат
/*
    ** Project: Creatio
    ** DBMS   : MSSQL 2008
    ** Type   : Script
    ** Name   : Actualize Date For Demo
*/
IF EXISTS (
    SELECT NULL
    FROM sys.objects
    WHERE [type] = 'TR' AND [name] = 'TR_BulkEmail_ProcessStatisticAfterUpdate'
)
DISABLE TRIGGER [dbo].[TR_BulkEmail_ProcessStatisticAfterUpdate] ON [dbo].[BulkEmail]
GO
IF EXISTS (
    SELECT NULL
    FROM sys.objects
    WHERE [type] = 'TR' AND [name] = 'TRCallAI'
)
DISABLE TRIGGER [dbo].[TRCallAI] ON [dbo].[Call]
GO


set nocount on
declare @NL char(1)
set @NL = char(13)

declare @ActualizedDemoDate datetime2
set @ActualizedDemoDate = (
    select top 1 sv.DateTimeValue 
    from SysSettings ss, SysSettingsValue sv
    where ss.Id = sv.SysSettingsId 
    and ss.Code like 'ActualizedDemoDate%'
    order by sv.ModifiedOn desc
)

if (@ActualizedDemoDate is null) 
begin
    print 'DemoDate is null.'
    return
end

print 'DemoDate is ' + cast(@ActualizedDemoDate as varchar)
declare @DaysDiff int
set @DaysDiff = datediff(DAY, @ActualizedDemoDate, getdate())
declare @DaysDiffStr varchar(6)
set @DaysDiffStr = cast(@DaysDiff as varchar(6))

declare @Table sysname
declare @Column sysname    

declare [c] cursor for
select table_name, column_name
from INFORMATION_SCHEMA.COLUMNS
where 
    (upper(data_type) = 'DATETIME' or upper(data_type) = 'DATETIME2' or upper(data_type) = 'DATE')
    and (column_name not in ('ModifiedOn') or 
            table_name in ('Opportunity', 'OpportunityInStage', 'SocialMessage', 'Lead', 'Contact', 'Account', 'KnowledgeBase', 'Product',
            'ApplicationApproval', 'Campaign', 'BulkEmail', 'CaseMessageHistory', 'Case', 'Activity', 'Invoice'))
    and (column_name not in ('CreatedOn') or 
            table_name in ('Opportunity', 'OpportunityInStage', 'SocialMessage', 'Lead', 'Contact', 'Account', 'KnowledgeBase', 'Product',
            'ApplicationApproval', 'Campaign', 'BulkEmail', 'CaseMessageHistory', 'Case', 'Activity', 'Invoice'))
    and not table_name in ('SysLic', 'RemindInterval', 'SysRecentEntity', 'PlanYear', 'PlanMonth', 'PlanQuarter', 'Period', 'FinIndicator', 'CampaignPlanner', 'MktgActivity', 'CurrencyRate')
    and not (table_name in ('ContactAnniversary', 'AccountAnniversary') and column_name = 'Date')
    and not (table_name in ('Contact') and column_name = 'BirthDate')
    and not (table_name in ('SysAdminUnit') and column_name = 'PasswordExpireDate')
    and not (table_name in ('SysImage') and column_name = 'UploadedOn')
    and objectproperty(object_id(table_name), 'IsTable') = 1
    order by table_name, column_name

open [c]

while (1 = 1)
begin
    fetch next from [c] into @Table, @Column

    if @@fetch_status = -1 break
    if @@fetch_status = -2 continue

    declare @tempExecStr nvarchar(max)
    set @tempExecStr = (
        ' update [' + @Table + '] ' + @NL +
        ' set [' + @Column + '] = dateadd(DAY, ' + @DaysDiffStr + ', [' + @Column + '])' + @NL + 
        ' where not [' + @Column + '] is null ' + @NL + 
        ' and datediff(DAY, [' + @Column + '], ''99991231'') > ' + @DaysDiffStr)
        
    exec (@tempExecStr)
    
    set @tempExecStr = (
    'DECLARE @currentDate DATETIME2 = getutcdate();' +
    ' update [' + @Table + '] ' + @NL +
    ' set [' + @Column + '] = @currentDate' + @NL + 
    ' where [' + @Column + '] > @currentDate' + @NL +
    ' and ''' + @Column + ''' in (''CreatedOn'', ''ModifiedOn'')')

    exec (@tempExecStr)
    
    print @Table + ' Column ->' +@Column + ' Diff->' + @DaysDiffStr + '(days) is updated.'
end
close [c]
deallocate [c]
GO
/* Actualize Date For Demo Forecasts */

IF (OBJECT_ID(N'ForecastSheet') IS NOT NULL)
BEGIN
    /*Actualize opportunity DueDate for demo Forecast*/
    --DECLARE @minOpportunityDueDate DATETIME2 = (SELECT MIN(o.DueDate) FROM Opportunity o);
    --DECLARE @newMinOpportunityDueDate DATETIME2 = DATEADD(MONTH, ((DATEPART(YEAR, GETUTCDATE()) - 2000) * 12) + DATEPART(MONTH, GETUTCDATE()) - 2, CONVERT(DATETIME, '2000.01.13', 102));
    --DECLARE @opportunityDueDateDiff INT = DATEDIFF(DAY,@minOpportunityDueDate, @newMinOpportunityDueDate);
    --IF @opportunityDueDateDiff > 0 BEGIN
    -- PRINT 'Will add ' + CAST(@opportunityDueDateDiff AS VARCHAR(10)) + ' days to Opportunity DueDate';
    -- UPDATE Opportunity
    -- SET DueDate = DATEADD(DAY, @opportunityDueDateDiff, DueDate)                                    
    --END
    

    DECLARE @entityForecastMap TABLE(
        ForecastEntityName NVARCHAR(50)
    );  

    INSERT INTO @entityForecastMap 
    VALUES 
        ('AccountForecast'),
        ('ContactForecast'),
        ('LeadTypeForecast'),
        ('OppDepartmentForecast')

    DECLARE @sql NVARCHAR(max);
    DECLARE @tableName NVARCHAR(100);

    DECLARE c CURSOR FOR
        SELECT ForecastEntityName FROM @entityForecastMap
    OPEN c

    WHILE 1 = 1
    BEGIN
        FETCH NEXT FROM c INTO @tableName
        IF @@FETCH_STATUS = -1 BREAK
        IF @@FETCH_STATUS = -2 CONTINUE

        IF (OBJECT_ID(@tableName) IS NOT NULL)
        BEGIN
            SET @sql = '
                UPDATE f
                SET PeriodId = (
                    SELECT 
                        inp.Id 
                    FROM Period inp
                    WHERE inp.PeriodTypeId = p.PeriodTypeId
                    AND inp.StartDate = DATEADD(year, DATEDIFF(year, p.StartDate, GETDATE()), p.StartDate)
                    AND inp.DueDate = DATEADD(year, DATEDIFF(year, p.DueDate, GETDATE()), p.DueDate)
                    )
                FROM '+ @tableName +' f
                JOIN Period p ON p.Id = f.PeriodId
            ';
            EXEC sp_executesql @sql;
        END;
    END;
    CLOSE c
    DEALLOCATE c
END;

GO

IF EXISTS (
    SELECT NULL
    FROM sys.objects
    WHERE [type] = 'TR' AND [name] = 'TR_BulkEmail_ProcessStatisticAfterUpdate'
)
ENABLE TRIGGER [dbo].[TR_BulkEmail_ProcessStatisticAfterUpdate] ON [dbo].[BulkEmail]
GO
IF EXISTS (
    SELECT NULL
    FROM sys.objects
    WHERE [type] = 'TR' AND [name] = 'TRCallAI'
)
ENABLE TRIGGER [dbo].[TRCallAI] ON [dbo].[Call]
GO